You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
src/commands/doctor.ts is one file carrying the model, the registry, the runner, thirteen checks and the renderer — 1,159 lines with the in-flight #458 check. Adding a check means editing the file every other check lives in, and nothing but convention stops one check from reaching into another. ADR-0032's context section names this file size as part of what forced the ADR.
Why this exists
PRD §9.4 fixes the layout, and the ADR's consequences section states the outcome: "src/commands/doctor.ts splits into a registry, a runner, per-check modules, and a renderer; the PRD fixes the layout. The command's observable text output for existing checks does not change."
The contributor story depends on it: one registry entry plus one test against an injected context, in a file of its own.
Scope
Move-only. No logic change, no behaviour change.
Create src/commands/doctor/ with registry.ts, runner.ts, report.ts, render.ts, and checks/<category>-<id>.ts (PRD §9.4), one file per check: checks/runtime-cli-runtime.ts, checks/runtime-git-trailers.ts, checks/transport-notes-refspec.ts, checks/transport-notes-push.ts, checks/capture-commit-msg-hook.ts, checks/capture-hook-runtime.ts, checks/capture-pending-backlog.ts, checks/delivery-inject-runtime.ts, checks/delivery-inject-version.ts, checks/delivery-mcp-lifecycle.ts, checks/history-history-depth.ts, checks/history-squash-conservation.ts, checks/index-index-health.ts.
src/commands/doctor.ts becomes a re-export shim so every existing import path keeps working (PRD §9.4: "The public import surface (runDoctor, formatReport, register) is re-exported so callers (init, tests) do not change"). The full surface in use today: runDoctor, formatReport, register, evaluateInjectRun, and the types CheckStatus, DoctorCheck, DoctorReport, DoctorOptions — src/commands/init.ts and test/doctor.test.ts / test/doctor-inject-version.test.ts import through ./doctor.js and must not change.
Layout exactly as PRD §9.4 plus the shim; src/commands/init.ts untouched; every existing test passes unedited.
Text output and --json byte-identical (the pinned snapshots stay green with zero updates).
No file under checks/ imports another file under checks/ — the seam is real: a check depends on the model and src/core/, never on a sibling. Enforced by a test that walks the import graph, not by review.
npm run build still produces dist/commitlore.mjs, and the CI fresh-clone step ("A fresh clone runs, and the plugin entry points resolve", .github/workflows/ci.yml) passes.
git log --follow/rename detection recognises the moves (move-only diffs, reviewable as such).
Tests that must exist
case
what it catches
no check module imports a sibling check module (import-graph walk over src/commands/doctor/checks/)
dependency-by-import creeping back — the coupling the registry's declared edges exist to replace. This is the fails-if-wrong case: the split that leaves checks entangled has not produced the seam PRD §9.4 is for
text and JSON snapshots unchanged
any behaviour smuggled into the move
the existing full suite, unedited
a broken re-export — init and the doctor tests are the consumers PRD §9.4 promises stability to
Open question — flagged, not decided here
PRD §9.4 names four module files plus checks/, but does not name a home for the model and factory (DoctorCheck, check(...), the unions). A model.ts beside them is the obvious reading; report.ts is arguable. Implementer's choice, stated in the PR, not silently mixed into runner.ts.
src/commands/doctor.tsis one file carrying the model, the registry, the runner, thirteen checks and the renderer — 1,159 lines with the in-flight #458 check. Adding a check means editing the file every other check lives in, and nothing but convention stops one check from reaching into another. ADR-0032's context section names this file size as part of what forced the ADR.Why this exists
src/commands/doctor.tssplits into a registry, a runner, per-check modules, and a renderer; the PRD fixes the layout. The command's observable text output for existing checks does not change."Scope
Move-only. No logic change, no behaviour change.
src/commands/doctor/withregistry.ts,runner.ts,report.ts,render.ts, andchecks/<category>-<id>.ts(PRD §9.4), one file per check:checks/runtime-cli-runtime.ts,checks/runtime-git-trailers.ts,checks/transport-notes-refspec.ts,checks/transport-notes-push.ts,checks/capture-commit-msg-hook.ts,checks/capture-hook-runtime.ts,checks/capture-pending-backlog.ts,checks/delivery-inject-runtime.ts,checks/delivery-inject-version.ts,checks/delivery-mcp-lifecycle.ts,checks/history-history-depth.ts,checks/history-squash-conservation.ts,checks/index-index-health.ts.src/commands/doctor.tsbecomes a re-export shim so every existing import path keeps working (PRD §9.4: "The public import surface (runDoctor,formatReport,register) is re-exported so callers (init, tests) do not change"). The full surface in use today:runDoctor,formatReport,register,evaluateInjectRun, and the typesCheckStatus,DoctorCheck,DoctorReport,DoctorOptions—src/commands/init.tsandtest/doctor.test.ts/test/doctor-inject-version.test.tsimport through./doctor.jsand must not change.dist/cli.jswhile distribution shipsdist/commitlore.mjs; CI red #40, the hook could be redirected to any executable and doctor still said ok #49, doctor: PreToolUse hook runtime reports exit 127 for a working hook on a binary-only install (checks a synthesised path, not the recorded command) #128, doctor prescribes 'commitlore hooks install' for a stale commitlore.bin, but that command cannot repair it #296, doctor reports a healthy install on a repository where every capture has been silently dropped for 8 days #458) and are part of what is being preserved.Acceptance criteria
src/commands/init.tsuntouched; every existing test passes unedited.--jsonbyte-identical (the pinned snapshots stay green with zero updates).checks/imports another file underchecks/— the seam is real: a check depends on the model andsrc/core/, never on a sibling. Enforced by a test that walks the import graph, not by review.npm run buildstill producesdist/commitlore.mjs, and the CI fresh-clone step ("A fresh clone runs, and the plugin entry points resolve",.github/workflows/ci.yml) passes.git log --follow/rename detection recognises the moves (move-only diffs, reviewable as such).Tests that must exist
no check module imports a sibling check module(import-graph walk oversrc/commands/doctor/checks/)text and JSON snapshots unchangedinitand the doctor tests are the consumers PRD §9.4 promises stability toOpen question — flagged, not decided here
PRD §9.4 names four module files plus
checks/, but does not name a home for the model and factory (DoctorCheck,check(...), the unions). Amodel.tsbeside them is the obvious reading;report.tsis arguable. Implementer's choice, stated in the PR, not silently mixed intorunner.ts.Depends on
Out of scope
Traceability: PRD §9.4; ADR-0032 consequences.