Internal briefing · codebase audit

Jarvis dead-code & overengineering audit

Full-repo scan (knip 6.33) plus six parallel manual verification passes found ~1,800 LOC of confirmed-dead files, ~2,400 LOC of confirmed-dead exports and fixtures, 9 unused dependencies, and roughly ~20k LOC of simplifiable code across over-engineered subsystems and weak tests. Every finding below was verified by grep against the whole monorepo — knip false positives (Effect layers, Expo plugins, native modules) were discarded.

Findings

Confirmed dead code by area

~1,800 LOC dead files ~2,400 LOC dead exports/fixtures 9 unused deps 0 false positives shipped

apps/server (245k LOC)

ItemLOCEvidence
src/service-launcher.ts (shim)1Only content is import "./serviceLauncher.ts"; referenced solely by the build:bundle script. Repoint script, delete file.
scripts/cursor-acp-model-mismatch-probe.ts442Zero references anywhere — no package.json script, no import, no docs. Unwired ACP probe.
src/provider/testFixtures/codexCollabMockPeer.mjs243Integration test uses the .sh variant; the .mjs fork is orphaned.
23 dead exports (errors, helpers)~120e.g. toOrchestrationCommandDecodeError, mergeProviderSnapshots, selectProvidersByKind, PreviewToolkitHandlersLive, 3× format*JsonDecodeError — zero internal or external callers.
6 dead types~30OrchestrationEngineError, ProviderSessionRepositoryError, TextGenerationProvider/Service, WorkspaceSearchIndexError, XAiAskUserQuestionResponse, CountingWsRpcClient.
~189 over-exported internals0 runtimeUsed only inside their own file (CLI flags, migration helpers, auth error classes). Demote export → const; halves the public API surface.
Dep: @effect/platform-node-shared—Never imported; pulled transitively by @effect/platform-node. Remove from package.json + catalog.

apps/web (222k LOC)

ItemLOCEvidence
src/historyBootstrap.ts139buildBootstrapInput has zero references repo-wide. Pre-orchestration leftover.
src/orchestrationEventEffects.ts94Zero imports; superseded by state/orchestration.ts.
src/orchestrationRecovery.ts211Full snapshot/replay FSM never wired to anything.
src/components/SplashScreen.tsx14No import in main/router/AppRoot; boot screen is inline in index.html.
src/lib/terminalUiStateCleanup.ts33collectActiveTerminalUiThreadKeys — definition only.
components/ui/{card,fieldset,form}.tsx239shadcn scaffolds with import count 0 across all of apps/web/src.
public/mockServiceWorker.js + devDep msw349No setupWorker/setupServer anywhere; msw installed but never initialized.
56 dead exports + ~11 dead selectors in state/entities.ts~400e.g. formatProviderDisplayName, remoteHttpRuntime, useBranches, primaryServerStateAtom, 5 dead theme labels, dead preview-toggle shortcuts.
~205 over-exported internals0 runtimeLocal-only constants/hooks exported unnecessarily.

apps/desktop (56k LOC) + apps/companion (9.5k LOC)

ItemLOCEvidence
src/preview/PickLabelPosition.ts46Zero importers; header claims it's for unit testing but no test exists and PickPreload.ts uses inline geometry instead.
Deps: @t3tools/jarvis-client-runtime, node-cpal, electron-builder (desktop)—Zero imports in desktop src. Desktop mic is Pipecat sidecar now; desktop builds via vp pack, not electron-builder.
5 of 6 knip-flagged preview files0False positives — vite pack entries and string-path build inputs. Kept.
Companion app (whole)9,494Not dead — still gates every stable release via jarvis-release.yml and its own 355-line CI workflow. But it's a frozen legacy app with 29 test files and a voice stack fully duplicated by desktop's Pipecat path. This is a product decision, not a deletion candidate (see Plan).

apps/mobile (81k LOC)

ItemLOCEvidence
src/components/GlassSafeAreaView.tsx52Zero imports; superseded by GlassSurface.
src/state/auth.ts + src/state/git.ts10Dead forks of web state; mobile uses state/session.ts + state/vcs.ts.
src/features/review/diffParser.ts158parseUnifiedDiff — zero callers; review uses reviewModel.ts.
src/features/terminal/ThreadTerminalPanel.tsx + model281Overlay panel never routed; superseded by ThreadTerminalRouteScreen.
Deps: @noble/hashes, punycode—Zero imports; leftovers from web/relay porting.
29 of 35 knip-flagged files0False positives — Expo config plugins referenced by string in app.config.ts, and the whole t3-markdown-text native module (Metro platform resolution).

packages/* (~112k LOC)

ItemLOCEvidence
packages/jarvis-native-microphone/0Empty shell — only a node_modules dir, no package.json, no source. 14 repo references are all guards asserting its absence. Delete the directory.
effect-acp/test/examples/cursor-acp-client.example.ts81Manual demo spawning a real cursor-agent binary; never run, never imported.
effect-codex-app-server/src/_generated/meta.gen.ts + effect-acp twin825Generated metadata consumed only by the generator script itself.
6 dead make/layer exports in client-runtime~6Internal factories exported but only the wrapping layer/service is consumed.
Dep: @effect/platform-node in tailscale (→ devDep), yaml in scripts—tailscale src never imports it (tests do); scripts gets yaml transitively via shared.
sherpa-onnx platform packages (jarvis-native-voice)0False positive — optionalDependencies loaded by native binding per platform. Keep.

Overengineering

Abstractions earning their keep vs. not

SubsystemWhy it's overbuiltSimpler shapeEst. LOC
Pull-request providers ×4 (server: GitHub/GitLab/Bitbucket/AzureDevOps, ~8k LOC)Four parallel *Cli/*Provider/*Json triples; ~70% identical arg-parsing logic. Three format*JsonDecodeError helpers already dead.One SourceControlCli with {bin, listArgs, viewArgs, parse}; keep GitHub primary, flag-gate the rest.~2,000
Companion voice stack (9.5k LOC)Complete parallel STT/TTS/mic/hotkey pipeline duplicated against desktop's Pipecat sidecar. Frozen legacy product still shipped per release.Product decision: deprecate-and-freeze (recommended), archive, or dedupe onto jarvis-native-voice. Not a silent deletion.up to 9,500
Mobile review highlighting ×3shikiReviewHighlighter.ts (1,085 LOC) + nativeReviewDiffHighlighter.ts (530) + atom wrapper (179) — two engines, two LRU caches, one job.Keep the native engine with JS fallback; port markdown code highlighting onto it; delete the shiki path.~1,100
Desktop Electron facet layers ×8Eight Effect Layers each wrapping one Electron module 1:1 (ElectronApp, ElectronMenu, …) with matching mock test files.One DesktopElectron facade layer, or direct imports + vi.mock("electron").~1,500
Mobile showcase harness890 LOC of in-app screenshot/showcase code gated by EXPO_PUBLIC_SHOWCASE, shipped in the production bundle.Move to build-time injection in scripts/mobile-showcase/.~890
VcsDriver registry + contract harness (server)Registry + fixture harness anticipating multiple VCS backends; only Git exists (3,330-line driver).Use GitVcsDriver directly; reintroduce the registry when a second VCS lands.~400
ProviderDriver generic + 5 drivers (server)Generic ProviderDriver<Config,R> with 3 unused helper types; 5 hardcoded implementations, never extended.Record<ProviderDriverKind, DriverSpec> + one makeDriver(kind).~150
jarvis-core 16 entrypoints16 package exports for 3 internal call sites in apps/server; tiny mappers each with their own test file.Collapse to 3 exports (voice, desk, planning) or one index.~150
client-runtime ConnectionResolver4 broker factories with identical shape differing in 5 lines of credential lookup, behind a service + layer for one call site.Inline prepare as a pure function in driver.ts.~200
contracts event vocabularies ×2orchestration.ts and providerRuntime.ts define overlapping event unions (turn.started etc. in both, different payload shapes); server re-decodes between them.Single RuntimeEvent source, derive the orchestration view. Needs explicit sign-off per the Jarvis/T3 boundary doc.~600
kokoro lifecycle ×3 layers (jarvis-native-voice)Lifecycle scheduler + worker client + worker for one Worker used by one caller.Inline eviction in native-speech.ts; delete the client adapter.~300
Mobile state barrels ×1414 one-liner files (export const foo = createFooAtoms(connectionAtomRuntime)), including 2 dead.One runtimeEnvironments.ts.~100

Tests

Test suite health (~1,003 test files)

0 orphaned snapshots 0 orphan scripts ~800 LOC duplicated shared/web tests 2 monster files to split
FindingDetailAction
apps/server/src/server.test.ts — 9,755 LOCSingle file covering HTTP, auth, pairing, WS sync, transfer budget. Shard bottleneck.Split into http/auth/ws suites (~3k each).
apps/web/src/session-logic.test.ts — 2,320 LOC8 pure derive functions in one file.Split per function.
Duplicate shared/web coverage~12 modules extracted to packages/shared still tested in both places (dpop, git, model, preview, filePreview…).Keep canonical tests in shared; web keeps integration smoke only. ~800 LOC.
Obsolete migration tests (server)Migrations 016/019/024/025/026 test historical schemas no new DB will have (~700 LOC).Delete after their irreversibility window; keep latest-migration snapshot.
Weak _tag-string assertion pattern (server)Auth/pull-request/terminal tests assert error._tag === "..." for error classes never thrown on that path in production — they keep dead classes alive and give false confidence.Replace with behavior assertions (HTTP 401/403 mapping etc.).
Duplicated PR-provider coverage (server)PullRequestService.test.ts (3,424 LOC) duplicates per-provider CLI tests (GitHub 2,606 / GitLab 1,405 / Bitbucket 988).Keep CLI-level tests; merge or delete service-level duplicates.
Companion: 29 test files for a frozen legacy appMany are packaging-invariant guards (asserting package.json strings) or trivial presentation tests.Keep smoke + packaging guards; archive ~15 granular UI tests (~1,200 LOC).
Mobile showcase tests ×4Test fixtures that only run under EXPO_PUBLIC_SHOWCASE=1.Delete with the harness (~260 LOC).
Possible uncollected testapps/server/test/ActivityPayloadProjection.test.ts lives outside src/; may not be picked up by the runner.Verify collection; move under src/ if orphaned.
Vendored-package schema smoke testseffect-acp / effect-codex-app-server: thin tests asserting generated-code decode, duplicated per package (~900 LOC).Keep one protocol integration test per package.

CI and config are clean: no orphan scripts, no stale workflow paths, no dead patches (15/15 applied), all 5 oxlint rules enabled, all 11 .env.example vars referenced. One housekeeping item: experiments/messages-glass-lab (~300 LOC of SwiftUI spike) is unreferenced committed scratch — move to docs/spikes/ or delete.

Plan

Suggested execution order

TierEffortActionImpact
Tier 0~1 hourPure deletions, zero risk. 18 dead files (~1,800 LOC): server shim + probe + mock peer; web bootstrap/recovery/splash/cleanup + 3 shadcn files + MSW worker; mobile 6 files; desktop PickLabelPosition; acp example; jarvis-native-microphone shell. Remove 9 unused deps (@effect/platform-node-shared, msw, @noble/hashes, punycode, jarvis-client-runtime + node-cpal + electron-builder from desktop, yaml from scripts, tailscale platform-node → devDep).~1,800 LOC + 9 deps
Tier 1~half dayDead exports + knip hygiene. Delete ~85 confirmed-dead exports/types across server (23) and web (56+). Demote ~400 over-exported internals to non-export. Add knip.json ignores for Expo plugins, generated files, native-module string loads so future scans are signal, not noise (35 → ~6 mobile findings).~2,400 LOC, API surface −50%
Tier 21–2 daysTest cleanup. Split server.test.ts and session-logic.test.ts; delete obsolete migration tests, showcase tests, duplicated shared/web tests, companion granular UI tests, weak vendored schema tests.~3,500 LOC test
Tier 32–4 daysStructural simplification. Collapse desktop Electron layers ×8→1, mobile highlighters ×3→1, mobile state barrels, client-runtime resolver, jarvis-core entrypoints, kokoro layers, VcsDriver registry, ProviderDriver generic.~4,500 LOC
Tier 4decisionProduct calls, not code calls. (a) Companion: deprecate-and-freeze (recommended) vs archive (~11–13k LOC incl. CI) vs invest-and-dedupe. (b) PR providers: consolidate 4→1+flags (~2,000 LOC). (c) contracts event-vocabulary unification (~600 LOC, touches the Jarvis/T3 boundary — read docs/internals/jarvis-t3-boundary.md first).up to ~14,000 LOC

Total addressable: ~7,700 LOC safely deletable in Tiers 0–2 with no behavior change; ~20k+ LOC if the Tier 3/4 structural work and product decisions land. Against ~700k LOC of TypeScript that's a 1–3% reduction — but the bigger win is signal: knip goes from 11k raw issues to near-zero, the public API surface halves, and the next audit takes minutes instead of a day.

Takeaway

Takeaway

The repo is healthier than the raw scan suggested — two-thirds of knip's findings were false positives from Effect layers, Expo conventions, and native modules. The real debt concentrates in three places: (1) a layer of genuinely dead files and exports from past cycles, cheap to delete; (2) parallel subsystems built for futures that didn't arrive (4 PR providers, 3 mobile highlighters, 8 Electron facades, 2 voice stacks); (3) test bulk that mocks rather than verifies. Tiers 0–1 are an afternoon of work with zero behavioral risk and should land first; the companion question is the single largest item and deserves an explicit product decision.