Findings
Confirmed dead code by area
apps/server (245k LOC)
| Item | LOC | Evidence |
|---|---|---|
src/service-launcher.ts (shim) | 1 | Only content is import "./serviceLauncher.ts"; referenced solely by the build:bundle script. Repoint script, delete file. |
scripts/cursor-acp-model-mismatch-probe.ts | 442 | Zero references anywhere — no package.json script, no import, no docs. Unwired ACP probe. |
src/provider/testFixtures/codexCollabMockPeer.mjs | 243 | Integration test uses the .sh variant; the .mjs fork is orphaned. |
| 23 dead exports (errors, helpers) | ~120 | e.g. toOrchestrationCommandDecodeError, mergeProviderSnapshots, selectProvidersByKind, PreviewToolkitHandlersLive, 3× format*JsonDecodeError — zero internal or external callers. |
| 6 dead types | ~30 | OrchestrationEngineError, ProviderSessionRepositoryError, TextGenerationProvider/Service, WorkspaceSearchIndexError, XAiAskUserQuestionResponse, CountingWsRpcClient. |
| ~189 over-exported internals | 0 runtime | Used 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)
| Item | LOC | Evidence |
|---|---|---|
src/historyBootstrap.ts | 139 | buildBootstrapInput has zero references repo-wide. Pre-orchestration leftover. |
src/orchestrationEventEffects.ts | 94 | Zero imports; superseded by state/orchestration.ts. |
src/orchestrationRecovery.ts | 211 | Full snapshot/replay FSM never wired to anything. |
src/components/SplashScreen.tsx | 14 | No import in main/router/AppRoot; boot screen is inline in index.html. |
src/lib/terminalUiStateCleanup.ts | 33 | collectActiveTerminalUiThreadKeys — definition only. |
components/ui/{card,fieldset,form}.tsx | 239 | shadcn scaffolds with import count 0 across all of apps/web/src. |
public/mockServiceWorker.js + devDep msw | 349 | No setupWorker/setupServer anywhere; msw installed but never initialized. |
56 dead exports + ~11 dead selectors in state/entities.ts | ~400 | e.g. formatProviderDisplayName, remoteHttpRuntime, useBranches, primaryServerStateAtom, 5 dead theme labels, dead preview-toggle shortcuts. |
| ~205 over-exported internals | 0 runtime | Local-only constants/hooks exported unnecessarily. |
apps/desktop (56k LOC) + apps/companion (9.5k LOC)
| Item | LOC | Evidence |
|---|---|---|
src/preview/PickLabelPosition.ts | 46 | Zero 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 files | 0 | False positives — vite pack entries and string-path build inputs. Kept. |
| Companion app (whole) | 9,494 | Not 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)
| Item | LOC | Evidence |
|---|---|---|
src/components/GlassSafeAreaView.tsx | 52 | Zero imports; superseded by GlassSurface. |
src/state/auth.ts + src/state/git.ts | 10 | Dead forks of web state; mobile uses state/session.ts + state/vcs.ts. |
src/features/review/diffParser.ts | 158 | parseUnifiedDiff — zero callers; review uses reviewModel.ts. |
src/features/terminal/ThreadTerminalPanel.tsx + model | 281 | Overlay panel never routed; superseded by ThreadTerminalRouteScreen. |
Deps: @noble/hashes, punycode | — | Zero imports; leftovers from web/relay porting. |
| 29 of 35 knip-flagged files | 0 | False 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)
| Item | LOC | Evidence |
|---|---|---|
packages/jarvis-native-microphone/ | 0 | Empty 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.ts | 81 | Manual demo spawning a real cursor-agent binary; never run, never imported. |
effect-codex-app-server/src/_generated/meta.gen.ts + effect-acp twin | 825 | Generated metadata consumed only by the generator script itself. |
6 dead make/layer exports in client-runtime | ~6 | Internal 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) | 0 | False positive — optionalDependencies loaded by native binding per platform. Keep. |
Overengineering
Abstractions earning their keep vs. not
| Subsystem | Why it's overbuilt | Simpler shape | Est. 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 ×3 | shikiReviewHighlighter.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 ×8 | Eight 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 harness | 890 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 entrypoints | 16 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 ConnectionResolver | 4 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 ×2 | orchestration.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 ×14 | 14 one-liner files (export const foo = createFooAtoms(connectionAtomRuntime)), including 2 dead. | One runtimeEnvironments.ts. | ~100 |
Tests
Test suite health (~1,003 test files)
| Finding | Detail | Action |
|---|---|---|
apps/server/src/server.test.ts — 9,755 LOC | Single 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 LOC | 8 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 app | Many 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 ×4 | Test fixtures that only run under EXPO_PUBLIC_SHOWCASE=1. | Delete with the harness (~260 LOC). |
| Possible uncollected test | apps/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 tests | effect-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
| Tier | Effort | Action | Impact |
|---|---|---|---|
| Tier 0 | ~1 hour | Pure 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 day | Dead 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 2 | 1–2 days | Test 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 3 | 2–4 days | Structural 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 4 | decision | Product 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.