Address T2 review asks from Karpathy (request_changes) + Jobs (approve with minor asks) without touching published commits: - scripts/codemod/README.md (new): records remove-appdatabase-passthrough.mjs usage, the completeness proof for METHOD_TO_MODULE (typecheck-clean + 524 tests green at118e3d8= no orphaned call sites), and the sequential revert recipe for C1 (3 -> 2 -> 1, not independent because118e3d8bundled vault simplification). - CONTRIBUTING.md (new): pass-through ban + codemod usage + sequential revert recipe + file-size ceiling + C6 wave cap. Whitelisted in .gitignore alongside the existing doc exceptions. - docs/proposals/C6.2-error-taxonomy-phase2.md: wave 2 scope boundary names renderer-adjacent / api-server / browser / automation / skills explicitly and excludes src/main/database/** + src/main/worker/runtime/** (B2 / M10 high-churn zones). Wave 2 and wave 3 each capped at 30 catch sites so C6 cannot expand without bound. - src/main/agent-runtime/artifact-projector.ts, runtime-bridge.ts: N-scan TODOs now carry a death date ("TODO(M-followup by 2026-05-20)"). If the date passes without decomposition, a follow-up session MUST revisit or justify the exception. Karpathy T2 asks #1 and #2 (split part 3 / "independent revert" language) are addressed in CONTRIBUTING + codemod README as documentation, not history rewrites, because118e3d8is already published. Typecheck clean. No structural code changes; pure docs + comment edits.
scripts/codemod/
One-shot and reusable codemods for mechanical refactors. Kept in the repo so the next person doing a similar migration has a working starting point instead of re-deriving it from scratch.
remove-appdatabase-passthrough.mjs
Rewrites db.<method>(...) → db.<module>.<method>(...) for every
pass-through method that used to live on AppDatabase / AppDatabaseBase
and now lives on a sub-module field.
Usage
# Full rewrite across src/**, tests/**:
node scripts/codemod/remove-appdatabase-passthrough.mjs
# Dry run (print what would change, don't write):
node scripts/codemod/remove-appdatabase-passthrough.mjs --dry-run
# Restrict to one or more modules:
node scripts/codemod/remove-appdatabase-passthrough.mjs --modules=tasks,agents
The script walks git ls-files 'src/**/*.ts' 'src/**/*.tsx' 'tests/**/*.ts'
(so it respects .gitignore), excludes the three files that define the
pass-throughs themselves (src/main/database.ts,
src/main/database-base.ts, src/main/database/**), and applies the
regex (^|[^\w.])((?:[\w$]+\.)*)db\.(<method>)\( → $1$2db.<module>.<method>(.
C1 migration evidence (coverage proof)
The METHOD_TO_MODULE map in the script was derived mechanically from
two source-of-truth files as they existed at the start of C1:
src/main/database.ts(pre-C1) — defined pass-through methods onAppDatabasethat delegated to domain modules.src/main/database-base.ts(pre-C1) — defined pass-through methods on the base class that delegated to sub-module fields.
Every pass-through method name from those two files was copied into the
map with its owning sub-module field name. Two composite methods
(createHireRequest, rollbackConfigRevision) are intentionally left
unmapped because they span multiple modules and live on AppDatabase
itself; rewriting them would break caller semantics.
The completeness of the map is proven by two independent signals, not by inspection alone:
- Typecheck after C1 part 3/3 (commit
ee1734e):pnpm typecheckis clean. If the map had missed any pass-through, call sites would still readdb.<method>(...)against a deleted method, and the TypeScript compiler would surface it asProperty '<method>' does not exist on type 'AppDatabase'. Typecheck passing = no orphaned call sites. - Test suite green after C1 part 3/3: 524 tests pass. If the
codemod had silently mis-mapped a method (e.g. routed
saveGoaltodocumentsModinstead ofentityCrud), the runtime would throwTypeError: db.documentsMod.saveGoal is not a functionon the exercising test. All 524 tests green = map entries are semantically correct, not just syntactically in scope.
Taken together, typecheck-clean + 524 tests green = the map is complete and correct across every live call site at the time of C1.
When to use this script in the future
If a future refactor re-introduces a pass-through on AppDatabase for
temporary back-compat, and you want to remove it again, you have two
options:
- Add the method to
METHOD_TO_MODULEin this script and run it. - If the new pass-through follows a different shape (e.g. a method that moved to a different module entirely), copy this script as a template and adjust the map. The regex structure is reusable.
The ESLint rule in eslint.config.mjs blocks new pass-throughs from
landing in the first place. See CONTRIBUTING.md at the repo root for
the rule and the guidance on when to invoke the codemod.
C1 commit recipe and revert ordering
C1 landed as three commits. The final one (ee1734e) did two things in
the same commit — removed the remaining pass-throughs AND simplified the
vault binding layer. In retrospect the vault simplification should have
been a separate fourth commit so each concern could revert independently;
in practice the commits are already published, so the recipe below
records the actual state.
Commits (oldest first):
e352a69— codemod-driven rewrite oftasks+agentspass-throughs- (C1 part 2/3) — rewrite of remaining domain-module pass-throughs
ee1734e— remove final pass-throughs + add ESLint guard + simplify vault binding
Sequential revert (not independent): to unwind C1 cleanly you revert
in reverse order: 3 → 2 → 1. Reverting commit 2 or 1 without first
reverting 3 will leave the ESLint guard still active, which will then
fail on the re-introduced pass-throughs. The "net simplification" part
of ee1734e that touched the vault layer comes along for the ride; it
does not have its own revert handle.
If that bundling is ever a problem, the fix is not to rewrite history
(already published) but to issue a targeted revert of only the vault
hunks of ee1734e via git revert -n ee1734e && git checkout --patch HEAD -- <vault-files>.