|
| 1 | +# Refactoring Plan |
| 2 | + |
| 3 | +Findings from the May 2026 architecture review. Work on these one at a time. Mark items as **Done** when complete. |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +## 1. Unify target mappings — LOW effort / HIGH value |
| 8 | + |
| 9 | +**Problem:** Two parallel, unconnected mapping structures had to be kept in sync manually. |
| 10 | + |
| 11 | +- `src/adapters/model_mappings.js` — `targetId → profile → model` (used by SDK adapters) |
| 12 | +- `src/adapters/model_mappings.js` — `TARGET_TO_CLAUDE_CLI` (`targetId → { model, effort }`) (used by CLI path) |
| 13 | + |
| 14 | +Adding or renaming a target required updates in both places with no guardrail. |
| 15 | + |
| 16 | +**Status:** Done |
| 17 | + |
| 18 | +--- |
| 19 | + |
| 20 | +## 2. Extract shared fs-utils — LOW effort |
| 21 | + |
| 22 | +**Problem:** `session_store.js` and `route_context.js` each define nearly identical private helpers: |
| 23 | + |
| 24 | +```js |
| 25 | +function ensureFile(storePath) { ... } |
| 26 | +function readStore(storePath) { ... } |
| 27 | +function writeStore(storePath, data) { ... } |
| 28 | +``` |
| 29 | + |
| 30 | +Divergence risk: if one is fixed, the other silently stays broken. |
| 31 | + |
| 32 | +**Status:** Done |
| 33 | + |
| 34 | +--- |
| 35 | + |
| 36 | +## 3. Hard-code `ANTHROPIC_TARGETS_PATH` in one place — LOW effort |
| 37 | + |
| 38 | +**Problem:** The same path was independently resolved in two files: |
| 39 | + |
| 40 | +```js |
| 41 | +// now centralized in src/switchboard/paths.js |
| 42 | +export const ANTHROPIC_TARGETS_PATH = path.join(__dirname, "..", "router", "data", "targets.anthropic.json"); |
| 43 | +``` |
| 44 | + |
| 45 | +**Status:** Done |
| 46 | + |
| 47 | +--- |
| 48 | + |
| 49 | +## 4. Extract `explain` command from `workflow.js` — MEDIUM effort |
| 50 | + |
| 51 | +**Problem:** `workflow.js` handles session loading, routing coordination, log writing, context-package building, attribution construction, serialization helpers, the `explain` command, and continuity probes. It is both orchestrator and utility module. |
| 52 | + |
| 53 | +The `explain` command is conceptually separate — it reads past logs rather than driving a new turn — so it's the most obvious thing to split out. |
| 54 | + |
| 55 | +**Fix:** Create `src/switchboard/explain.js` that owns `explainLatestSwitchboardTurn`, `reconstructReasoning`, and related read-only log helpers. Import from `workflow.js` if needed, then remove the implementation there. |
| 56 | + |
| 57 | +**Status:** Not started |
| 58 | + |
| 59 | +--- |
| 60 | + |
| 61 | +## 5. Separate prompt classifier from router — MEDIUM effort |
| 62 | + |
| 63 | +**Problem:** `router.js` mixes two distinct concerns: |
| 64 | + |
| 65 | +- `classifyPrompt` — keyword-matching heuristics that produce `taskType` / `proposedMode` signals |
| 66 | +- `routePrompt` — policy evaluation, hard/soft constraints, continuity cost, target selection |
| 67 | + |
| 68 | +The classifier produces signals; the router consumes them. They have different change rates and different test surfaces. |
| 69 | + |
| 70 | +**Fix:** Extract `classifyPrompt` (and its supporting constants like `TASK_TYPE_TO_ADDITIONAL_REQUIREMENTS`) into `src/router/classifier.js`. Keep `router.js` as the policy engine that imports from the classifier. |
| 71 | + |
| 72 | +**Status:** Not started |
| 73 | + |
| 74 | +--- |
| 75 | + |
| 76 | +## 6. Remove or promote `extractTurnFields` — LOW effort |
| 77 | + |
| 78 | +**Problem:** `route_context.js` had a function named `deriveLegacyTurnFields`. The "legacy" label signaled it had been kept alive longer than intended and imposed a cognitive tax on every reader. |
| 79 | + |
| 80 | +**Status:** Done |
| 81 | + |
| 82 | +--- |
| 83 | + |
| 84 | +## 7. Align file naming convention — LOW effort |
| 85 | + |
| 86 | +**Problem:** Source files use `snake_case` (`anthropic_claude_adapter.js`, `session_store.js`); test files use `kebab-case` (`claude-cli-launcher.test.js`, `thread-session-store.test.js`). Pairing a source file with its test requires a mental translation step. |
| 87 | + |
| 88 | +**Fix:** Decide on one convention (kebab-case is more common in the JS ecosystem) and rename files accordingly. Update all imports. |
| 89 | + |
| 90 | +**Status:** Not started |
| 91 | + |
| 92 | +--- |
| 93 | + |
| 94 | +## Order of execution |
| 95 | + |
| 96 | +| # | Item | Effort | Notes | |
| 97 | +|---|------|--------|-------| |
| 98 | +| 1 | Unify target mappings | Low | Do first — prevents divergence bugs | |
| 99 | +| 2 | Shared fs-utils | Low | Quick win, reduces duplication | |
| 100 | +| 3 | Paths constant | Low | Quick win, no logic changes | |
| 101 | +| 6 | Legacy field | Low | Audit first to confirm safe to delete | |
| 102 | +| 4 | Extract explain | Medium | Biggest readability gain in workflow.js | |
| 103 | +| 5 | Separate classifier | Medium | Makes router independently testable | |
| 104 | +| 7 | File naming | Low | Do last — touches many files at once | |
0 commit comments