[#179] Dead code, duplicated constants & lying names sweep#190
Conversation
Grep-verified zero callers across the app, tests, and the example: - CaptionPipeline::start_capture (session.rs rolls its own start_captures; the example calls start_mic/start_system directly) - ContinuousVadProcessor::processed_ms - MicCapture::device()/sample_rate() (and the now-dead fields backing them) - SystemAudioCapture::sample_rate() (and MacSystemAudioCapture's getter/field) The mic/system capture handles kept a native-rate field solely to serve the dead getters; each channel's ready-signal now carries unit — the pipeline resamples every AudioChunk by its own reported rate, so the initial rate was never consumed. Pure deletion, no behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Grep-verified zero consumers anywhere (the app never imports them; the engine's own tests import from ./src/* directly, not the barrel): - @livecap/engine barrel: drop 20 symbols with no barrel importers (StreamJsonParser, buildClaudeArgs/ISOLATION_ARGS/DEFAULT_MODEL, sanitizeChildEnv, the buildSystemPrompt/…/formatUserMessageLine prompt builders, parseSummaryBoard/parseAnalyzeRespond/parseCoachResult/ buildCoachPrompt, periodKeyFor, EngineTurnError/EngineTimeoutError, ModelChecksumError/ModelDownloadStallError). Each stays package-private; only the barrel re-export line changes. This also stops re-exporting the content-bearing StreamJsonParser its own doc flags as the #23 foot-gun. - FeedState.recentSources: dead export; reply-chip context is built host-side from transcriptLines.slice(-10) in session.ts. - ReviewSurface.registerCoachingCard: no external caller (only runCoaching registers, internally) — removed from the interface and returned object, kept as a private function. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- epoch_ms: session.rs::now_epoch_ms and ui_state.rs::now_ms were line-for-line identical; extract one pub(crate) util::epoch_ms() used by both so the caption and UI-heartbeat timestamps (compared during verification) can't drift. - vad.rs: the scattered 0.8 / 0.9 confidence literals become named constants FORCED_SEGMENT_CONFIDENCE (force-cut + flush) and VAD_SEGMENT_CONFIDENCE (natural SpeechEnd) so the two forced sites stay in lockstep if retuned. - settings.rs: default_stt_model() now derives from livecap_core::model::DEFAULT_MODEL (the same value session.rs uses for the download-failure fallback) instead of a hardcoded "small", with a test that DEFAULT_MODEL stays inside the curated STT_MODELS list. - lib.rs/tray.rs: the "Alt+Space" / "Alt+Shift+Space" hint strings become TOGGLE_LABEL / CYCLE_LABEL constants referenced by both the tray accelerator hint and the registration error log, so they can't drift from each other. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- DEFAULT_CLI_NAMES: default to ["claude"] only (was ["claude","codex"]).
probeCapabilities/buildClaudeArgs emit Claude-CLI-specific argv, so the codex
fallback could only misbehave; the ordering test now passes names explicitly.
- DEFAULT_CONTEXT_CAPTIONS: export it from extras-prompts and consume it in
extras-pipeline (config.contextCaptions ?? DEFAULT_CONTEXT_CAPTIONS) instead of
a second hardcoded 10, so the reply/analyze context window has one source.
- POOL_PRESETS/PlanId: the engine's {pro,max5x,max20x} const (and the PlanId
derived from it) were consumed by nothing — the app uses the labeled
POOL_PRESETS in app-settings.ts. Drop the dead engine export/type so the plan
dollar amounts live once, in app-settings.ts.
- parseBrief: logic-identical in both adapters (l vs line) — extract one
internal/brief.ts and import it from both (summarize() is live, so it is
unified, not deleted).
- MAX_STDERR_TAIL: one shared constant beside stderrDigest in internal/redact.ts.
- dropUndefinedEnv: the shared drop-undefined loop moves to env.ts; sanitizeChildEnv
builds on it and the local engine uses it directly (the local sanitize() was
NOT sanitizeChildEnv — that adds Claude-only env munging — so only the loop is
shared, no behavior change).
The two deeper duplications in the finding (the stderr-drain wiring and the
spawn-await onSpawn/onError promise blocks) are left in place: extracting them
means refactoring live child-process spawn/IO paths, beyond this cleanup's
constant/helper unification and no-behavior-change scope — noted in the PR.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- clockLabel: identical HH:MM formatter in main.ts and host/session.ts → one dependency-free src/clock.ts imported by both, so the live-feed and archive/ coaching timestamps (which the amend keys depend on) can't drift. - CLOSE_ICON: the same ✕ SVG lived in main.ts (ICONS.close), review.ts, and dashboard.ts → one src/icons.ts imported by all three. - renderBoard: the review surface and the dashboard built the board DOM identically (labels/rows/empty-state) but with different signatures/returns → a shared renderBoardInto(target, board) exported from review.ts (beside renderBetter); each caller keeps its own container. (The metric tile is left as-is: review builds it as a static HTML template with ids it updates by reference, the dashboard as a value-passed DOM builder — sharing one builder would mean refactoring review's update model, out of scope here. Noted in PR.) - EnginePref: defined twice (protocol.ts + app-settings.ts) → app-settings.ts imports/re-exports the protocol.ts definition. - WORKING_TITLE: parse.ts mirrored the literal → import it from ./sanitize (its post-#178 definition site, pure — keeps parse.ts free of the fs writer the dashboard deliberately avoids bundling). - DEFAULT_POOL_USD / DEFAULT_RESET_DAY: the pool ($20) and reset-day (1) defaults were hardcoded in both main.ts DEFAULT_SETTINGS and host/start-config.ts's fallback/clamp → one dependency-free src/defaults.ts imported by both. - EXTRAS_CONTEXT_LINES: onReply used a magic 10 while onAnalyze used the named constant → one shared EXTRAS_CONTEXT_LINES for both extras. - MEETING_VOICE_LANG vs AUTO_MEETING_LANGUAGE: per the Batch-36 amendment this is conceptual coupling, not a literal duplicate — documented as an explicit bidirectional cross-reference rather than forced into a shared constant. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- session.rs: rename HOST_EXIT_TIMEOUT → HOST_STOPPED_EVENT_TIMEOUT. Since #82 the host deliberately no longer exits on stop; stop() uses this to bound the wait for the host's `stopped` JSONL event (archive finalized), not a process exit. The name now matches, and its new doc + SHUTDOWN_HOST_TIMEOUT's cross-reference describe the stopped-event wait. (Per the Batch-36 amendment, only this constant is renamed — SHUTDOWN_HOST_TIMEOUT is correctly named and untouched.) - main.ts: the onboarding comment claimed "three onboarding cards, then straight into a session" — onboarding renders TWO cards and #1 removed auto-start (the onDone handler lands on the idle Start screen). Comment corrected to match. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- styles.css: delete the orphaned .ob-select rule — no TS renders an .ob-select element since the onboarding language pick moved to the Start screen (#2); the live equivalents are .sp-lang / .sh-select. - index.html: the boot-error inline style hardcoded #e8b84b, the exact value of the existing --accent-live token; use var(--accent-live) so a future retune of the token follows here too (styles.css is linked in <head> before this inline script paints, so the variable resolves). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The no-stub-gate bans the marker word "placeholder"; the new FORCED/VAD segment
confidence doc comments and the shared renderBoardInto doc used it in ordinary
prose. Reworded ("estimated" / "dash") — no code change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: REQUEST CHANGES
Epic Alignment: PASS
The cleanup follows #179’s amended boundaries: it preserves #178, keeps behavior-decision items documented, and does not start the deferred packaging/process-path refactors.
Checked (evidence)
- Structural gate: live PR body includes filled EPIC Alignment, Self-Verification, Design Fidelity, and Deviations sections.
- Amendment checks: session.rs renames HOST_EXIT_TIMEOUT only; renderBoard is deliberately shared while the metric tile is deferred; clockLabel/parseBrief are logic-unified; the en-US/English coupling is documented rather than falsely merged.
- Design fidelity: spot-checked Board DOM, close SVG, boot-error token, dead .ob-select removal, and onboarding comment against the cited live files.
- Riskiest part: 34-file cross-config cleanup; shared utilities remain dependency-free and the skipped behavior/packaging work is explicitly out of scope.
- Kill-list: scanned full diff — clean.
- CI: gh pr checks 190 → color-guard, no-stub-gate, packages-linux pass; app-macos FAIL; release-invariants pending.
Findings
- [blocking] Resolve the failing macOS CI job.
- Evidence: gh pr checks 190 → app-macos FAIL (53s).
- Why it fails: #179 requires all gates green; the macOS job is the authoritative build/test coverage for the src-tauri cleanup.
- Do instead: identify and fix the app-macos failure, push the correction, then request a delta re-review after all checks are green.
Decision
The reviewed cleanup is aligned with #179, but the failing required macOS check blocks approval.
Removing SystemAudioCapture::sample_rate() left the macOS `inner` field held only as an RAII guard (its Drop stops the tap thread) with no direct read, which trips clippy's dead_code under -D warnings in the app-macos job. Annotate the field #[allow(dead_code)] with a comment (this path isn't compiled on Linux, so it only surfaced in CI). MicCapture is unaffected — its explicit Drop reads its fields. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
RE2 — APPROVE at PR #190 head (cleanup sweep; all 5 CI green, behavior-preserving verified)Reviewed all 8 commits + ran the full gate suite on Linux + adversarially verified every dead-code removal and every constant/helper unification (the two failure modes for a cleanup: a "dead" symbol with a live caller, or a "dedup" that silently changed a value). None found. Checked (evidence)
RE2 APPROVE — unconditional (all 5 CI green). (Verified in part via two parallel adversarial sweeps over the dead-code and dedup commits; conclusions independently spot-checked. Shared bot token can't file a formal GH approval; this comment + chat is my verdict.) |
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: APPROVE
Epic Alignment: PASS
The #179 cleanup remains within the amended behavior boundaries; the delta only documents the macOS RAII guard that preserves capture shutdown behavior.
Checked (evidence)
- Re-review range: 2e0c2a1..edfe2ce
- Prior CI blocker resolved: crates/livecap-core/src/audio/system.rs:29 preserves the macOS capture field as a documented Drop-driven RAII guard.
- Riskiest part of this diff: the field is intentionally unread, but its lifetime triggers capture cleanup on Drop; the field-scoped allow documents and preserves that invariant.
- Kill-list: scanned all new-range items — clean.
- CI: gh pr checks 190 → app-macos, color-guard, no-stub-gate, packages-linux, and release-invariants all pass.
Findings
None.
Decision
The sole follow-up change fixes the macOS warning without changing runtime behavior. The live CI suite is green and the re-review delta is aligned with #179.
Closes #179
Design-lens cleanup sweep: dead code, duplicated constants, and comments/names that lie. Pure deletion / constant-unification / comment fixes — no behavior changes, no new dependencies. Eight commits grouped by kind (dead code → duplicated constants → names → CSS), each grep-verified. Net −40 lines across 34 files.
EPIC Alignment
Part of EPIC #134 (v1.3 audit follow-up), Batch 47 — the final ticket in the standing-order sequence. Rebased on current
main(includes #178, which touchedresample.rs/render.ts/parse.ts/pipeline.rs); all #178 changes are preserved and its regressions still green (archive 98,source_language_preserves_auto_translate, etc.). Batch-36 amendments honored (see below). No overlap conflicts — the shared files are edited in non-conflicting regions.Self-Verification — per finding (fixed / skipped-with-reason)
Dead code (2 commits)
vad.rsresample_to_16kContinuousVadProcessor::new(input_sample_rate, …)contract (non-16 kHz input currently resamples; deletion would require callers to pre-resample and silently misbehave otherwise); the alternative — a non-16 kHz test — keeps the code. Both are design decisions beyond "pure deletion, no behavior change" (the ticket's own scope rule).pipeline.rsstart_capture,vad.rsprocessed_ms,MicCapture::device/sample_rate,SystemAudioCapture::sample_rate(+ the rate plumbing that only fed the getters)AudioChunkcarries its own rate).feed-state.tsrecentSourcesreview.tsregisterCoachingCardReviewSurfaceinterface + returned object, kept a private function.engine/index.tsbarrel (20 symbols)./src/*directly). Dropped; each stays package-private. Also stops re-exporting the content-bearingStreamJsonParserits own doc flags as the #23 foot-gun.extras-pipeline.tsper-item usage-attribution machinerydivideUsage/addUsage/cumulative splitting changes whatcoachBatchrecords to the budget and the per-item return shape (tests assert onusage); the fix direction itself says "if per-item attribution is planned, keep… behind a ticket." Out of a no-behavior-change cleanup's scope.Duplicated constants (3 commits: Rust / engine / webview)
now_ms/now_epoch_msutil::epoch_ms()(newsrc-tauri/src/util.rs).vad.rs0.8/0.9confidence literalsFORCED_SEGMENT_CONFIDENCE/VAD_SEGMENT_CONFIDENCE.settings.rsdefault STT modellivecap_core::model::DEFAULT_MODEL; added a test that it stays insideSTT_MODELS.lib.rs/tray.rsshortcut labelsTOGGLE_LABEL/CYCLE_LABELreferenced by both.DEFAULT_CLI_NAMES(["claude","codex"])["claude"]only (the engine can only drive the Claude CLI); ordering test passesnamesexplicitly.DEFAULT_CONTEXT_CAPTIONSextras-prompts, consumed inextras-pipeline.POOL_PRESETS/PlanIdapp-settings.tsis the single source of the plan dollar amounts.parseBrief(both adapters)internal/brief.ts(summarize() is live, so unified not deleted).MAX_STDERR_TAIL(both adapters)internal/redact.ts.sanitize()vssanitizeChildEnvdrop-undefined loopdropUndefinedEnvinenv.ts. The two functions are NOT equivalent (sanitizeChildEnvadds Claude-onlyMAX_THINKING_TOKENS/credential stripping), so only the shared loop is extracted — no behavior change.clockLabel(main.ts + session.ts)src/clock.ts.src/icons.tsCLOSE_ICON.renderBoard(review.ts + dashboard.ts)renderBoardInto(target, board)(each caller keeps its container). The metric tile is not unified: review builds it as a static HTML template with ids it updates by reference, the dashboard as a value-passed DOM builder — sharing one builder means refactoring review's update model, beyond this cleanup.EnginePref(protocol.ts + app-settings.ts)app-settings.tsimports/re-exports the protocol definition.WORKING_TITLEmirror inparse.ts./sanitize(its post-#178 definition site, pure — keepsparse.tsfree of the fs writer the dashboard avoids bundling; slight deviation from the finding's./writer, justified).DEFAULT_POOL_USD/DEFAULT_RESET_DAYin dep-freesrc/defaults.ts.onReplymagic10vsANALYZE_CONTEXT_LINESEXTRAS_CONTEXT_LINES.MEETING_VOICE_LANGvsAUTO_MEETING_LANGUAGENames / comments (1 commit)
session.rsHOST_EXIT_TIMEOUTHOST_STOPPED_EVENT_TIMEOUT+ doc describing the stopped-event wait. Per amendment,SHUTDOWN_HOST_TIMEOUT(correctly named) is left alone.main.ts:1219lying commentCSS / HTML (1 commit)
styles.cssdead.ob-selectindex.htmlraw#e8b84bvar(--accent-live)(same value; styles.css is linked before the boot-error script).Also partially deferred: the two deeper
#11duplications (the stderr-drain wiring + the spawn-awaitonSpawn/onErrorpromise blocks) are left in place — extracting them means refactoring live child-process spawn/IO paths, beyond a constant/helper unification.Also skipped:
archive/package.jsonsubpath-exportsmap — adding an exports map and rewiringdashboard.ts's deep imports is a packaging/module-resolution change (build behavior), not a pure cleanup; belongs in a dedicated ticket.Design Fidelity
Every UI-touching change is DOM/pixel-identical — this is a refactor of how markup is produced, not what it produces.
renderBoard→ sharedrenderBoardIntoboard-row/board-head/<ul>/<li>, same"—"empty state; review keeps its board node, dashboard keeps.dash-board.CLOSE_ICON#e8b84b→var(--accent-live)#e8b84b)..ob-selectdeletedDeviations
WORKING_TITLEimported from./sanitize(its actual post-[audit][bug] Small-correctness polish: resampler drops buffered audio on rate change; overlay transition flag races; archive board-separator and '(?)' round-trip ambiguities; device-name casing; fallback stop() state #178 home, pure) rather than the finding's literal./writer— keepsparse.tsoff the fs writer that the dashboard deliberately never bundles.resample_to_16kand the extras usage-attribution machinery (behavior decisions) and thearchive/package.jsonexports map (packaging change); partially deferred the metric-tile share and the two deeper#11process-spawn extractions. All noted above with reasons.Tests / evidence
Local, all green:
livecap-core62 + clippy-D warnings;pnpm typecheck(webview and host configs);pnpm lint; app 162,@livecap/archive98,@livecap/engine270;no-stub-gate+color-guardpass.src-tauri(session/util/settings/lib/tray/system macOS module) can't build on Linux — its build +cargo test --workspacerun in theapp-macosCI job on this PR; watch it green.🤖 Generated with Claude Code