Problem
apps/web/src/services/interceptor/DirectModeInterceptor.ts is ~3,658 lines in a single file. It is the native/Capacitor runtime's reimplementation of the entire server API (profiles, shots, analysis, recommendations, machine I/O) and is the #1 maintenance and dual-runtime parity risk in the codebase: nearly every feature change has to touch it, diffs are hard to review, and it repeatedly churns thousands of lines when helpers move around (e.g. the recent computeRichLocalAnalysis extraction).
Goal
Break DirectModeInterceptor into focused, independently testable modules without changing behavior, so future feature work and parity mirroring become surgical.
Proposed decomposition (by route family)
interceptor/routes/profiles.ts — profile CRUD, import/export, catalogue cache
interceptor/routes/shots.ts — shot listing/data/annotation
interceptor/routes/analysis.ts — local analysis, ShotFacts, analyze-llm, recommendations
interceptor/routes/machine.ts — machine status, run-shot, live
interceptor/lib/ — already-extracted pure helpers (analyzeLlmPrompt, shotFacts, compassRules, dynamics resolvers, meanDynamicsTarget, formatters)
- A thin
DirectModeInterceptor.ts that only wires the router/dispatch table to the handlers.
Constraints
- Pure refactor — no functional change; each step should be a byte-for-byte behavior move verifiable by the existing
*.direct.test.tsx suites.
- Preserve dual-runtime parity with the Python server (
apps/server/); keep the module boundaries roughly aligned with the server's route/service split.
- Land incrementally (one route family per PR) to keep diffs reviewable.
- No change to the insecure-context / crypto guards or Capacitor thenable-proxy handling already in place.
Definition of done
- No single interceptor file > ~800 lines.
- All existing native direct-mode tests +
tsc/eslint green.
- A short module map documented in
apps/web/src/services/interceptor/README.md.
Problem
apps/web/src/services/interceptor/DirectModeInterceptor.tsis ~3,658 lines in a single file. It is the native/Capacitor runtime's reimplementation of the entire server API (profiles, shots, analysis, recommendations, machine I/O) and is the #1 maintenance and dual-runtime parity risk in the codebase: nearly every feature change has to touch it, diffs are hard to review, and it repeatedly churns thousands of lines when helpers move around (e.g. the recentcomputeRichLocalAnalysisextraction).Goal
Break
DirectModeInterceptorinto focused, independently testable modules without changing behavior, so future feature work and parity mirroring become surgical.Proposed decomposition (by route family)
interceptor/routes/profiles.ts— profile CRUD, import/export, catalogue cacheinterceptor/routes/shots.ts— shot listing/data/annotationinterceptor/routes/analysis.ts— local analysis, ShotFacts, analyze-llm, recommendationsinterceptor/routes/machine.ts— machine status, run-shot, liveinterceptor/lib/— already-extracted pure helpers (analyzeLlmPrompt,shotFacts,compassRules, dynamics resolvers,meanDynamicsTarget, formatters)DirectModeInterceptor.tsthat only wires the router/dispatch table to the handlers.Constraints
*.direct.test.tsxsuites.apps/server/); keep the module boundaries roughly aligned with the server's route/service split.Definition of done
tsc/eslint green.apps/web/src/services/interceptor/README.md.