Generated: 2026-06-13
Metrics refreshed: 2026-08-12 via node scripts/report-code-health.mjs.
Previous: Round 8 (28 commits) — barrel-to-subpath migration. tsc/test/build all green.
Round 9 progress: merged to main; see "Round 9 Status" below.
Round 10: docs/CODEBASE_AUDIT_2026-08-12.md + docs/IMPROVEMENT_PLAN_2026-08-12.md
(defect repair and control tightening — metrics endpoint, test flake, coverage gate,
UI page tests, Windows CI). Round 10 did not touch file decomposition.
Goal: This document is the canonical roadmap for the next round of structural improvement.
Refreshed 2026-08-12.
| Package | Prod LOC | Prod files | Test files | Largest production file | Files > 1000 LOC |
|---|---|---|---|---|---|
@ownpilot/core |
80,522 | 272 | 157 | 1118 (agent/tools/expense-tracker.ts) |
4 |
@ownpilot/gateway |
173,318 | 588 | 472 | 1473 (channels/plugins/whatsapp/…-api.ts) |
14 |
@ownpilot/cli |
5,078 | 19 | 14 | 511 (commands/agentic.ts) |
0 |
@ownpilot/ui |
146,801 | 482 | 99 | 1286 (pages/CodingAgentsPage.tsx) |
15 |
| Total | 405,719 | 1,361 | 742 | — | 33 |
Production files over thresholds: > 500 LOC: 256 · > 800 LOC: 89 · > 1000 LOC: 33.
Two things changed since the 06-22 snapshot that alter the plan below:
- Phase 1 is complete and overachieved. Every correctness/type-safety target was
met — production
as unknown asis 7 (target was ≤ 40),as any0,Math.random()0,eslint-disable2,@ts-expect-error0. §1.10 and §1.14 are closed; do not spend more effort there. - The UI is now the largest decomposition target, not the gateway. UI has 15 files over 1000 LOC against gateway's 14, yet Phase 2A below lists six gateway targets and zero UI ones. That aim is stale — see the revised 2A ordering.
File-size totals have barely moved (249 → 256 over 500 LOC), because no round since has attempted decomposition. That is the honest status: Phase 2 has not started.
Bugs fixed (14 of 15 from §1):
| Bug | Title | Commit | Files |
|---|---|---|---|
| §1.1 | scheduler unhandled rejection on Promise.race loser | 16fff5ab |
scheduler/index.ts |
| §1.2 | email-tools SMTP/IMAP lie (6 executors) | f31ec481, e7b194cc |
email-tools.ts + test |
| §1.3 | personalStoreCache unbounded growth | 86d290e0 |
memory/personal.ts |
| §1.4 | anthropic thinking-block crash | 5a6be29d |
anthropic-provider.ts |
| §1.5 | credentials decrypt throws out of get/getById | 315570ac |
credentials/index.ts + test |
| §1.6 | data-gateway 'calendar' typo for tasks |
30c6b0a8, 9c4e2c70 |
data-gateway/index.ts + test |
| §1.7 | utility-data stack overflow on min/max/flatten | 1156f5a0 |
utility-data-tools.ts |
| §1.8 | email-tools attachment path-traversal | f31ec481 |
email-tools.ts + test |
| §1.9 | web-fetch timer leak (3 sites) | f8b72ca5 |
web-fetch.ts |
| §1.11 | biased Math.random shuffle |
1156f5a0 |
utility-data-tools.ts |
| §1.12 | corrupt-JSON silent data loss (4 files) | 9d92cdd8, 8f25039f, 35327314, 93cad327 |
memory/*.ts + scheduler/index.ts |
| §1.13 | sandbox env prefix gaps | 36722914 |
sandbox/local-executor.ts |
| §1.14 | security-sensitive Math.random (5 sites) |
1f22eb0b, e528227c |
generator-tools.ts, claw, telegram, audio, service-impl |
| §1.15 | agent cancel aborts in-flight tool calls (plumbing) | 413f3763 |
agent.ts, tools.ts |
Refactors (§1.10 — historical manual count as unknown as 162 → 142; current script count: 150 production / 265 test; 67 casts documented):
| Commit | Title | Reduction |
|---|---|---|
fa0563f8 |
document as unknown as casts in provider factory | -2 (count) |
94c635b7 |
document as unknown as casts in tool-validation | -3 (count) |
1ee78f1e |
localise 18 as unknown as casts in workflow-service to two helpers (nodeDataField, nodeDataRecord) |
-16 (count) |
799d2d0e |
localise 5 as unknown as casts in acp-event-mapper to a helper (toMappedEvent) |
-4 (count) |
52d4b4ca |
add trust-boundary header to 10 UI workflow config files | docs |
f4fb662f |
add trust-boundary notes to 13 gateway route/service files | docs |
dbb1a408 |
add trust-boundary note to useLayoutConfig | docs |
Documentation pattern: For the remaining typed-boundary casts (current script count: 150 production), the pattern is now: one Trust boundary: line in the file's JSDoc header explaining the source of untyped data (DB row, HTTP body, npm registry, worker IPC). The cast sites themselves are unchanged — they are real bridges between generic payloads and typed consumers. Further reduction to ≤40 requires architectural changes (typed DB rows, post-validation typed handler args).
Test status: core 9441/9441 ✅, gateway 17297/17297 ✅, ui 414/414 ✅, pnpm -r typecheck clean (caught and fixed two tsc regressions — DataStoreType: 'tasks' missing and error/reason fields on ToolExecutionResult). Zero regressions across all 25 commits. Note: gateway has a pre-existing flaky test in src/tools/skill/tools.test.ts (~1/3 runs fail on different test cases). It is not caused by round-9 changes — running the same suite 3 times in a row gives varying pass/fail counts.
Remaining from §1 (updated 2026-08-12): §1.10 is CLOSED — production
as unknown as is now 7, well past the ≤40 target, and as any is 0. No further
work needed there; treat the numbers in the table below as achieved, not aspirational.
§1.15 plumbing is done; the only genuine follow-up is per-tool adoption (each
long-running tool executor checking ctx.signal and forwarding to its own async APIs).
Risk signal counts from node scripts/report-code-health.mjs (production/test separated; excludes dist, coverage, node_modules):
| Pattern | Production | Tests | Interpretation |
| ----------------------------------- | ---------: | ----: | --------------------------------------------------------------------------------- | --- | --- | ----------------------------------------------------------------- |
| as any | 5 | 494 | Production remains low; tests intentionally use mock casts. |
| as unknown as | 150 | 265 | Still the main typed-boundary debt; reduce via validators/typed DB rows. |
| TODO | FIXME | HACK | XXX | 5 | 8 | Low; visible production hits include generated/default task text. |
| dangerouslySetInnerHTML/innerHTML | 1 | 2 | Production hit is HtmlWidget and is sanitized; keep allowlisted. |
| eval/new Function | 8 | 49 | Mostly validators/comments/Puppeteer $eval; audit before changing. |
| child_process/spawn/exec | 110 | 354 | Centralize or document through permission gates and sandbox boundaries. |
| Math.random() | 22 | 9 | Mostly jitter/sampling; replace ID/shuffle uses first. |
| eslint-disable | 40 | 0 | Audit line-level exceptions. |
| @ts-expect-error | 1 | 5 | Good production count; keep under 5. |
| console.* | 554 | 71 | CLI/test noise expected, but gateway/core runtime should move to structured logs. |
| JSON.parse() | 213 | 260 | Ensure untrusted parse sites use safe parse/validation. |
Test coverage gap: 41 source files in packages/gateway/src/services/ have no direct colocated test by the health script heuristic (see Appendix A).
These came from the bug-hunter audit. Each is a real, reproducible bug — fix before refactor so the refactor doesn't have to track behavior changes.
packages/core/src/scheduler/index.ts:728-738 — Promise.race for task timeout has no catch on the loser. If the timeout fires first, the still-in-flight executionPromise rejection becomes unhandledRejection.
Fix: add executionPromise.catch(() => {}); before Promise.race() (the pattern already exists in heartbeat-runner.ts:494).
packages/core/src/agent/tools/email-tools.ts:263-305, 359, 444, 502, 562, 627 — all email executors return isError: false with status: 'prepared' but the email is never sent (no SMTP wiring). The agent loop treats these as successes.
Fix: until SMTP is wired, return isError: true with requiresSMTPConfig: true. Don't tell the user the email was sent.
packages/core/src/memory/personal.ts:848 — personalStoreCache is a module-level Map<userId, PersonalMemoryStore> that is never cleared. Long-running gateways leak one full per-user in-memory dataset per unique userId seen.
Fix: add LRU cap (e.g. 1000 entries) and a clear(userId) method, called from the assistant shutdown path.
packages/core/src/agent/providers/anthropic-provider.ts:582-617 — when msg.content is a string and the message is assistant-role with thinking blocks, line 617 calls contentParts.unshift(...thinkingParts) but contentParts is the string itself, so it throws "is not a function".
Fix: initialize contentParts: unknown[] = [], push the text part explicitly.
packages/core/src/credentials/index.ts:377-382 — decryptValue(...) is not wrapped in try/catch. A wrong encryption key throws synchronously out of get()/getById(), taking down the request handler.
Fix: try/catch, return null and auditLog('decrypt_failed', ...).
packages/core/src/data-gateway/index.ts:490, 507, 519, 535, 541 — createTask/completeTask/listTasks/searchTasks/deleteTask call this.access(agentId, 'calendar', ...) while operating on this.tasks. Means: a user with tasks permission can't use tasks; a user with calendar permission can.
Fix: change first arg to 'tasks'.
packages/core/src/agent/tools/utility-data-tools.ts:721, 726 — Math.min(...numsMin) / Math.max(...numsMax) spreads the full array onto the call stack. Throws RangeError on 10k+ numeric inputs (within applyToolLimits).
Fix: replace with manual for loop. Also cap flat(Infinity) (line 691) at e.g. flat(100).
packages/core/src/agent/tools/email-tools.ts:264-274 — attachments are read directly from LLM-controlled args, no isPathAllowedAsync call. When SMTP is wired, an LLM could exfiltrate /etc/passwd. The error path also leaks the requested path.
Fix: run attachments through isPathAllowedAsync(filePath, context.workspaceDir) (mirror file-system.ts:266-279).
packages/core/src/agent/tools/file-system.ts:606-632 (downloadFile) and web-fetch.ts:355-365, 493-502, 752-761 — on network error, the setTimeout is only cleared on the success path; an AbortError in the catch block leaves the timer firing.
Fix: move clearTimeout(timeoutId) into finally.
162 occurrences. Goal: cut to <40 by adding proper type guards. Focus areas:
core/agent/providers/*(anthropic, google, openai-compatible)core/memory/*(personal, secure-store)gateway/services/agent/*
Approach: add as Type only at trust boundaries (HTTP/DB/JSON.parse) with a // trust boundary: comment. Use zod .parse() for all route bodies (gateway uses zod already).
packages/core/src/agent/tools/utility-data-tools.ts:695 — sort(() => Math.random() - 0.5) is mathematically biased.
Fix: Fisher–Yates (the pattern is already used at line 673, copy it).
personal.ts:819, secure-store.ts:725, conversation-store.ts:737, scheduler/index.ts:823 — all wrap JSON.parse in try{} catch{} that silently resets the in-memory map to empty on corruption. A disk error loses ALL user data with only a debug log.
Fix: at minimum log.error not log.debug, and back up the corrupt file as *.corrupt-${ts} before resetting.
packages/core/src/sandbox/local-executor.ts:46-62 — SENSITIVE_ENV_PREFIXES list omits AUTH, JWT, OAUTH. A MYAUTH_TOKEN env var would slip through.
Fix: add 'AUTH', 'JWT', 'OAUTH', 'CUSTOMER', 'SESSION'.
22 hits — review each. Replace with crypto.randomInt / crypto.randomUUID for:
- IDs / tokens / nonces
- CAPTCHA / rate-limit salt
- Anything used in a security context
Acceptable for: sampling, jitter, UI effects.
packages/core/src/agent/agent.ts:763-768 — cancel() only flips isProcessing: false. The provider's fetch is aborted, but executeToolCall keeps running local code or DB queries.
Fix: pass the AbortController through ToolContext, check signal.aborted before/during tool execution.
Each phase is independent, gated by tsc + pnpm -r test. Use the git-flow skill: one concern per commit, branch from main.
No behavior change, tests already pass, quick wins.
| # | Task | Files | Effort | Risk | Why |
|---|---|---|---|---|---|
| 1.1 | Fix all 15 critical/high bugs from §1 | (listed above) | M | low | Correctness first — refactor on a known-good base |
| 1.2 | Add proper type guards — cut production as unknown as from 150 → ≤80 |
core/agent/providers/*, core/memory/*, gateway/services/agent/* |
L | low | Big leverage: enforces strict + noUncheckedIndexedAccess discipline |
| 1.3 | Add/verify clear() + LRU to module-level Map caches (personalStoreCache, secure-store, conversation-store) |
core/memory/*.ts |
S | low | Prevents production memory leak |
| 1.4 | Replace Math.random in security/ID/shuffle paths with crypto.randomInt/randomUUID or Fisher-Yates |
grep-driven, 22 production hits | S | low | Security and correctness hygiene |
| 1.5 | Centralize/document child_process/spawn/exec through permission gates and sandbox boundaries |
core/sandbox/*, gateway/services/permission/*, tool executors |
M | low | One audit point for shell-execution risk |
| 1.6 | Add missing tests for the 41 gateway services without direct colocated tests — start with manager lifecycle helpers, workflow dispatch, metric pulse, and orphan reconciliation | packages/gateway/src/services/**/*.test.ts |
M | low | Phase-1 baseline coverage |
Phase 1 exit criteria:
- All 15 bugs in §1 fixed
- Production
as unknown ascount ≤ 80 vianode scripts/report-code-health.mjs -
pnpm -r teststill green -
pnpm -r typecheckstill green - No new
Math.randomin security paths
Significant test coverage needed. May need rollback plan. Run collab_debug on each file split.
Retargeted 2026-08-12. This section previously listed six gateway files and no UI ones, on 06-22 metrics. The UI now has more >1000 LOC files than the gateway (15 vs 14) and is where user-visible regressions land, so UI pages are first-class targets.
Sequencing note: the five largest UI pages gained smoke tests in Round 10 (
ChatPage,ClawsPage,AnalyticsPage,CodingAgentsPage,LogsPage). Split those first — they are the only large files with a regression net under them. Any other page should get its smoke test before being split, not after.
UI targets (all pages; each splits into a container + components/ + a hook holding
the data logic, mirroring the existing pages/claws/ and pages/workflows/ layout):
Status 2026-08-12: 2.1a-d and 2.1f-h are DONE. Seven of the eight targets split; every one kept its smoke test green across the move.
| # | Source | LOC | Status |
|---|---|---|---|
| 2.1a | pages/CodingAgentsPage.tsx |
1285→536 | DONE — pages/coding-agents/{NewSessionModal,cards,helpers} |
| 2.1b | pages/ClawsPage.tsx |
1203→791 | DONE — pages/claws/{useClawActions,derive,BulkActionsBar,AttentionBanners} (+15 tests) |
| 2.1c | pages/LogsPage.tsx |
1172→702 | DONE — pages/logs/{formatters,DebugLogsTab} |
| 2.1d | pages/AnalyticsPage.tsx |
1058→763 | DONE — pages/analytics/{format,chart-primitives,derive} (+20 tests) |
| 2.1e | pages/ChatPage.tsx |
1050 | NOT STARTED — highest traffic, split last and most carefully |
| 2.1f | components/workflows/…templates.ts |
1268→52 | DONE — templates/{scheduling,automation,ai,integration,data} |
| 2.1g | components/ToolPicker.tsx |
1247→788 | DONE — tool-picker/{types,tabs,builtin-data,instructions,icons,filter} (+27 tests) |
| 2.1h | pages/MissionControlPage.tsx |
1109→536 | DONE — smoke test written first; mission-control/{derive,ClawMissionCard,panels} (+21 tests) |
The splits were not purely mechanical: extracting the pure logic made it testable for
the first time, and 83 new unit tests came out of four of them. Two encode decisions
that had never been pinned — ToolPicker's instruction builders (their output is injected
verbatim into the prompt and is the only thing telling the agent which tool to call) and
Mission Control's attentionScore (a claw stalled mid-task still reports running, so
cyclesInProgress is the only signal anything is wrong).
Gateway targets (unchanged from the original plan; still valid):
Each split should leave the public barrel re-export everything so call sites don't change. Test files for the new modules come first (TDD).
| # | Source | LOC | Target structure | Why |
|---|---|---|---|---|
| 2.1 | services/claw/manager/manager.ts |
1314 | services/claw/manager/{index,lifecycle,tasks,escalation,inbox,persistence,scheduler-sync}.ts |
Manager mixes lifecycle, task state, escalation, persistence, and scheduling. |
| 2.2 | services/workflow/workflow-service.ts |
1068 | services/workflow/{service,runtime,resume-runtime,error-handling,persistence,dispatch}.ts |
Workflow service mixes runtime, resume, persistence, and DAG execution. |
| 2.3 | channels/service-impl.ts |
1553 | channels/{service,plugin-registry,outbound,inbound,pairing,ownership,session-bridge}.ts |
Channel service mixes plugin, send, receive, pairing, ownership, persistence. |
| 2.4 | ws/server.ts |
1189 | ws/{server,auth,subscriptions,event-bridge,session}.ts |
WebSocket server mixes auth, event routing, sessions, and transport. |
| 2.5 | routes/claws.ts |
1305 | routes/claws.ts + services/claw/{health,recommendations,serialization}.ts |
Route contains domain scoring/recommendation logic. |
| 2.6 | services/tool/templates.ts |
853 | services/tool/templates/{registry,builtin,user,render}.ts |
Template engine has multiple phases mixed together. |
Phase 2A exit criteria:
- No file > 800 LOC in
gateway/src/services/andgateway/src/db/repositories/ - No file > 800 LOC in
ui/src/pages/— 8 pages remain, all 1041-1103 LOC (ProfilePage,ChatHistoryPage,McpServersPage,TriggersPage,AgenticPage,ChatPage,PlansPage,coding-agent-settings-tabs). None has a smoke test yet; each needs one before it is split. - Repo-wide
> 1000 LOCcount down from 33 → 25 (2026-08-12);> 500 LOCstill to re-measure (verify withnode scripts/report-code-health.mjs) - Every page split has a colocated smoke test that passed before the split
- Existing
*.test.tsfiles for the source still pass (re-import from new location) -
pnpm -r testgreen,pnpm -r typecheckgreen
| # | Barrel | Exports | Suggested split |
|---|---|---|---|
| 2.7 | core/services/index.ts |
73 | Split into ./services/registry, ./services/builtins/weather, ./services/builtins/finance, etc. Keep a thin barrel re-exporting all. |
| 2.8 | core/agent/index.ts |
39 | Split into ./agent/agent, ./agent/providers, ./agent/tools, ./agent/soul. |
| 2.9 | core/agent/tools/index.ts |
34 | Already has sub-folders — split into ./agent/tools/file-system, ./agent/tools/web, ./agent/tools/email, ./agent/tools/personal-data, ./agent/tools/code, ./agent/tools/index (barrel). |
| 2.10 | core/agent/soul/index.ts |
21 | Split into ./agent/soul/{heartbeat,identity,profile} if not already |
Phase 2B exit criteria:
- No sub-path barrel > 35 exports
- No new sub-path barrel changes the public API (all re-exports present)
-
pnpm -r typecheckgreen -
pnpm -r testgreen
Priority order (highest blast-radius first):
services/claw/manager/**/*.ts— supports the ClawManager split and lifecycle behaviorservices/workflow/executors/*.ts— node executors run user-controlled workflow dataservices/workflow/{workflow-dispatch,workflow-node-job-handler}.ts— dispatch and job handling are high blast-radiusservices/metric/pulse.ts— observability/runtime signal pathservices/orphan-reconciliation.tsandservices/log.ts— startup/shutdown operational safety
Phase 2C exit criteria:
- At least 20 of the 41 listed services have direct colocated tests, prioritizing high blast-radius files
-
pnpm --filter @ownpilot/gateway testgreen
Behavior changes expected. Integration tests required.
Each of telegram, discord, slack, whatsapp, matrix, email, sms, webchat plugins has near-identical:
- plugin lifecycle (init/start/stop)
- message normalization
- webhook signature verification
- outbound message queue
- rate-limit handling
Plan:
- Extract a
plugins/channel-base.tswith the lifecycle, verification, and queue - Each plugin becomes a thin subclass with
verifyWebhook(),normalizeIncoming(),sendOutbound() - Add
plugins/__tests__/channel-base.test.tswith shared conformance tests - Migrate all 8 plugins, one PR per plugin
- Remove duplicated verification logic (current bug: 1
dangerouslySetInnerHTMLlives in webchat — verify it gets killed by the new sanitization layer)
Risk: high — these are integration points. Each PR should include a manual test plan.
The current core/services/index.ts mixes 73 exports. The cleanest model is a ServiceRegistry (already exists per memory) — make it the pattern across all services. Benefit:
- Lazy init (no eager construction)
- Test isolation (clear/reset per test)
- Single audit point for service lifecycle
This pairs with Phase 2.7 (split the barrel).
Suspected cycle (verify with madge or graph analysis):
core/agent/agent.ts→core/memory/*(for context injection)core/memory/personal.ts→core/agent/*(for tool invocation in memory ops?)core/scheduler/index.ts→core/agent/*(for running scheduled prompts)
Plan: introduce a core/contracts/ package (or use the existing core/types/) with plain interface types. Both sides depend on contracts, not each other. Use dependency injection to wire the implementation.
Risk: medium-high — touches the most-imported modules in the codebase.
The observability skill recommends JSON-to-stdout with traceId, event, duration_ms, outcome. Current state: pino is a dependency, but use is inconsistent. Add a small wrapper:
core/observability/log.ts—log.info({traceId, event, ...}, msg)core/observability/trace.ts—withTrace(traceId, fn)helper
Then a single PR per package switches call sites.
Risk: low-medium (it's an additive change), but very large surface (hundreds of console.log calls).
The audit-log skill notes: "WrongStack writes session JSONL to sessionRoot." The services/agent/service.ts and services/llm/router.ts are the integration points. Add a packages/gateway/tests/integration/ suite that:
- Mocks provider responses
- Walks through agent → tool → LLM → response
- Asserts JSONL log structure
Risk: low (test-only), but high value for confidence before 1.0.
gateway/src/services/claw/manager.ts (1572)
├── claw/manager/index.ts (re-export)
├── claw/manager/registry.ts (claw CRUD: ~400 LOC)
├── claw/manager/lifecycle.ts (start/stop/health: ~300 LOC)
├── claw/manager/permissions.ts (gate checks: ~250 LOC)
└── claw/manager/scheduler-sync.ts (claw↔scheduler: ~400 LOC)
gateway/src/services/workflow/workflow-service.ts (1531)
├── workflow/service.ts (public API, ~250 LOC)
├── workflow/runtime.ts (execution loop: ~500 LOC)
├── workflow/job-dispatch.ts (queue + retry: ~350 LOC)
├── workflow/persistence.ts (DB I/O: ~300 LOC)
└── workflow/index.ts (re-export)
gateway/src/services/agent/service.ts (1054)
├── agent/service.ts (public API, ~200 LOC)
├── agent/runs.ts (run state machine: ~300 LOC)
├── agent/prompts.ts (template rendering: ~250 LOC)
├── agent/tools-bridge.ts (tool invocation: ~250 LOC)
└── agent/index.ts (re-export)
gateway/src/services/tool/templates.ts (853)
├── tool/templates/registry.ts (template CRUD: ~200 LOC)
├── tool/templates/builtin.ts (bundled templates: ~300 LOC)
├── tool/templates/user.ts (user-saved: ~150 LOC)
├── tool/templates/render.ts (template engine: ~200 LOC)
└── tool/templates/index.ts (re-export)
Each split leaves a thin index.ts re-export so all existing call sites work unchanged.
| Module | LOC | Cyclomatic | Test % (est.) | Public API | Phase |
|---|---|---|---|---|---|
services/claw/manager.ts |
1572 | ~35 | ~50% | yes | 2A |
services/workflow/workflow-service.ts |
1531 | ~30 | ~55% | yes | 2A |
services/agent/service.ts |
1054 | ~25 | ~60% | yes | 2A |
services/tool/templates.ts |
853 | ~20 | ~40% | yes | 2A |
core/agent/tools/file-system.ts |
1114 | ~25 | ~70% | yes (tool) | 3.6 |
core/agent/orchestrator.ts |
829 | ~30 | ~75% | yes (agent) | 3.6 |
ui/components/workflows/workflow-templates.ts |
1266 | low (UI) | ~30% | yes (page) | 3.7 |
file-system.ts and orchestrator.ts are the most-leverage targets in core but already well-tested. Phase 3.6 is "extract the workspace-isolation helpers" — a small surgical cut.
| Phase | Strategy |
|---|---|
| 1 | Single PR per bug fix — git revert per commit |
| 2A | Feature flag GATEWAY_CLAW_SPLIT=0 keeps the old manager.ts re-export path |
| 2B | Sub-path barrels are additive; old barrel still works (this is what round 8 did) |
| 2C | Test-only — revert is the PR |
| 3.1 | One plugin per PR; old plugin stays until the new one ships |
| 3.2 | Two-week overlap with old registry (env var picks) |
| 3.3 | git revert per affected file; tsc gates the merge |
- All Phase 1 bugs fixed and merged
- All Phase 2A files split, all tests green, no file > 800 LOC in
services/anddb/repositories/ - All Phase 2B barrels < 35 exports
- 30+ of the 46 untested gateway services have tests
- All 8 channel plugins migrated to the shared base class
- Cyclic deps between
core/agent,core/memory,core/schedulerbroken (usemadgeto verify) -
pnpm -r typecheckgreen -
pnpm -r testgreen (core 9440, gateway 17297, ui 414 baseline; CLI 190 ECONNREFUSED expected) -
pnpm -r buildgreen -
pnpm audit --prod --audit-level highclean -
as unknown ascount ≤ 40 - Zero
as anyin production code
- Don't over-phase: if a task is < 1h, merge it with a related task.
- Don't plan without analyzing: this plan is built on actual line counts, grep counts, and a bug-hunter run. Always re-verify before acting.
- Don't skip the dependency graph: when splitting a file, draw the import map first.
- Don't break the public API: keep the old entry point as a re-export for at least one release.
- Don't touch tests and logic in the same commit: the round 8 subagent architecture proved this — separate commits.
- Don't merge a refactor with a bug fix: each commit does one thing, so
git bisectworks. - Don't trust the LLM's stale training data: package versions, deprecations, API surfaces — always check the registry (use the
tech-stackskill).
For Phase 1 (bug fixes), spawn 3 parallel subagents with role debugger, scoped to:
core-bugs— bugs #1.1, #1.3, #1.4, #1.5, #1.6, #1.7, #1.8, #1.11, #1.12, #1.13, #1.15core-tool-bugs— bugs #1.2, #1.8 (email-tools), #1.9, #1.14type-cleanup— bug #1.10 (as unknown asaudit) + #1.14 (Math.randomaudit)
For Phase 2A (file splits), one subagent per file — 6 sequential commits, each with its own tests.
For Phase 3.1 (channel plugins), one subagent per plugin — 8 sequential PRs.
Mail protocol: subagents should mail_send results to the main agent. Main agent aggregates via roll_up.
Generated by node scripts/report-code-health.mjs. This is a heuristic: shared integration tests may still cover some files.
services/agent/agent-context.ts
services/agent/session-info.ts
services/claw/manager-cycle-ops.ts
services/claw/manager-scheduling.ts
services/claw/manager-stop-conditions.ts
services/claw/manager/constants.ts
services/claw/manager/events.ts
services/claw/manager/manager.ts
services/claw/manager/singleton.ts
services/config/entry-validation.ts
services/log.ts
services/metric/pulse.ts
services/orphan-reconciliation.ts
services/page-prompts/agent-copilot-prompt.ts
services/page-prompts/autonomous-copilot-prompt.ts
services/page-prompts/claw-copilot-prompt.ts
services/page-prompts/cli-tools-copilot-prompt.ts
services/page-prompts/coding-agent-copilot-prompt.ts
services/page-prompts/mcp-copilot-prompt.ts
services/page-prompts/skill-copilot-prompt.ts
services/page-prompts/tool-copilot-prompt.ts
services/page-prompts/tool-groups-copilot-prompt.ts
services/page-prompts/workflow-tools-copilot-prompt.ts
services/page-prompts/workspace-copilot-prompt.ts
services/workflow/executors/claw.ts
services/workflow/executors/control-flow.ts
services/workflow/executors/data.ts
services/workflow/executors/io.ts
services/workflow/executors/tool-llm-code.ts
services/workflow/template-ideas.ts
services/workflow/templates/api.ts
services/workflow/templates/business.ts
services/workflow/templates/content.ts
services/workflow/templates/data.ts
services/workflow/templates/devops.ts
services/workflow/templates/monitoring.ts
services/workflow/templates/personal.ts
services/workflow/templates/research.ts
services/workflow/templates/security.ts
services/workflow/workflow-dispatch.ts
services/workflow/workflow-node-job-handler.ts
| Barrel | Exports |
|---|---|
core/services/index.ts |
73 |
core/agent/index.ts |
39 |
core/agent/tools/index.ts |
34 |
core/agent/soul/index.ts |
21 |
core/scheduler/index.ts |
21 |
core/events/index.ts |
17 |
core/data-gateway/index.ts |
15 |
core/credentials/index.ts |
13 |
core/costs/index.ts |
12 |
core/security/index.ts |
12 |
core/sandbox/index.ts |
11 |
core/agent/providers/configs/index.ts |
19 |
Generated by node scripts/report-code-health.mjs.
| LOC | File |
|---|---|
| 1701 | ui/src/pages/ChatPage.tsx |
| 1553 | gateway/src/channels/service-impl.ts |
| 1502 | gateway/src/channels/plugins/whatsapp/whatsapp-api.ts |
| 1388 | ui/src/components/MarkdownContent.tsx |
| 1380 | ui/src/pages/ProfilePage.tsx |
| 1379 | ui/src/pages/SystemPage.tsx |
| 1314 | gateway/src/services/claw/manager/manager.ts |
| 1305 | gateway/src/routes/claws.ts |
| 1286 | ui/src/pages/CodingAgentsPage.tsx |
| 1277 | core/src/agent/tools/file-system.ts |
| 1269 | ui/src/components/workflows/workflow-templates.ts |
| 1248 | ui/src/components/ToolPicker.tsx |
| 1227 | gateway/src/utils/chat-widgets.ts |
| 1204 | ui/src/pages/ClawsPage.tsx |
| 1189 | gateway/src/ws/server.ts |
| 1172 | ui/src/pages/LogsPage.tsx |
| 1118 | core/src/agent/tools/expense-tracker.ts |
| 1112 | gateway/src/routes/workflow/index.ts |
| 1109 | ui/src/pages/MissionControlPage.tsx |
| 1104 | ui/src/pages/coding-agent-settings-tabs.tsx |
| 1095 | gateway/src/channels/plugins/telegram/telegram-api.ts |
| 1084 | ui/src/pages/McpServersPage.tsx |
| 1078 | gateway/src/routes/chat/index.ts |
| 1077 | ui/src/pages/TriggersPage.tsx |
| 1072 | gateway/src/plans/executor.ts |