codev doctor: detect protocol-file drift — local copies shadowing newer skeleton files, and stale installed skeletons
The failure class
The four-tier resolver (.codev/ → codev/ → cache → installed skeleton) is working as designed when a project-local file shadows the skeleton — that's the customization mechanism. But it fails silently when the local copy is not a customization, just a stale snapshot of an old upstream default. The project then runs old framework behavior indefinitely, with no signal, even as the installed package ships fixes.
Nothing today distinguishes "deliberately customized" from "rotted copy of an old default." Both look identical to the resolver.
Field evidence (adopting workspace, details scrubbed)
- A consult-noise bug ("bugfix-protocol PRs reviewed against SPIR conventions — spec/plan artifacts demanded that the protocol deliberately doesn't produce") hit 3× in one CI-cleanup sweep. Root cause: two project-local
codev/protocols/bugfix/consult-types/*.md files, checked in Feb/May from old upstream defaults, shadowing the installed skeleton's fixed templates (which carry an explicit "BUGFIX is not SPIR" guard). Upgrading the package changed nothing — tier precedence kept loading the stale local copies.
- A follow-up sweep of that repo found 15 more differing local protocol files (air/maintain/bugfix families, same vintage) each needing customization-vs-rot adjudication.
- The same incident also surfaced the sibling failure mode: before the upgrade, the installed skeleton itself was a version behind, so even non-shadowed resolution served pre-fix templates. Equally silent.
- Meta-note: the first diagnosis attempt of this very bug was itself derailed by a silently-vacuous check (relative paths run from the wrong cwd) — this failure class compounds because every layer of it is quiet.
Proposal
codev doctor (and optionally codev update) gains a drift report:
- Shadow drift: for every file under
codev/protocols/** (and codev/consult-types/**, roles, prompts) that also exists in the installed skeleton, diff them. Byte-identical → fine (redundant copy; suggest removal). Differs → list it with the skeleton version's mtime/package-version, flagged "customized or stale? adjudicate."
- Known-default detection (stretch): ship hashes of historical skeleton versions of each file; a local copy matching an old default hash is provably rot, not customization → safe-to-delete recommendation.
- Skeleton staleness:
codev doctor compares the installed package version against the npm latest (best-effort, offline-tolerant) and reports how far behind the resolved framework files are.
- No auto-delete. Report only; adjudication stays human (local copies may be deliberate).
Why doctor
This is exactly doctor's contract — diagnose silent misconfiguration. The failure class is invisible in normal operation, cheap to detect mechanically, and now has 17 confirmed field instances in one adopting repo.
Areas: area/scaffold (resolver/doctor).
codev doctor: detect protocol-file drift — local copies shadowing newer skeleton files, and stale installed skeletons
The failure class
The four-tier resolver (
.codev/→codev/→ cache → installed skeleton) is working as designed when a project-local file shadows the skeleton — that's the customization mechanism. But it fails silently when the local copy is not a customization, just a stale snapshot of an old upstream default. The project then runs old framework behavior indefinitely, with no signal, even as the installed package ships fixes.Nothing today distinguishes "deliberately customized" from "rotted copy of an old default." Both look identical to the resolver.
Field evidence (adopting workspace, details scrubbed)
codev/protocols/bugfix/consult-types/*.mdfiles, checked in Feb/May from old upstream defaults, shadowing the installed skeleton's fixed templates (which carry an explicit "BUGFIX is not SPIR" guard). Upgrading the package changed nothing — tier precedence kept loading the stale local copies.Proposal
codev doctor(and optionallycodev update) gains a drift report:codev/protocols/**(andcodev/consult-types/**, roles, prompts) that also exists in the installed skeleton, diff them. Byte-identical → fine (redundant copy; suggest removal). Differs → list it with the skeleton version's mtime/package-version, flagged "customized or stale? adjudicate."codev doctorcompares the installed package version against the npm latest (best-effort, offline-tolerant) and reports how far behind the resolved framework files are.Why doctor
This is exactly doctor's contract — diagnose silent misconfiguration. The failure class is invisible in normal operation, cheap to detect mechanically, and now has 17 confirmed field instances in one adopting repo.
Areas:
area/scaffold(resolver/doctor).