Class fix for the fresh-install bug discussed in #738. Spec 618 correctly moved framework files into the package skeleton (resolver tier 4). The resolver works. The bug is consumer-side: prompts, role docs, and protocol docs reference framework files (protocol.md, templates, workflow-reference) by literal path, which bypasses the resolver and fails when the file lives only in the embedded skeleton. This issue covers the whole class of framework-file references reachable from builder-side consumers; the project-bootstrap gap (codev/resources/ not created on init) is tracked separately as #1012. The strategic question in #738 (whether to restore framework file copying broadly) stays separate.
Bug class
In fresh post-Spec-618 installs, any framework-provided file referenced by literal path from a builder-side consumer fails. Three sub-instances observed in current main:
A.1 — Protocol meta-doc references (9 builder-prompts + 1 role file). Every protocol's builder-prompt.md instructs the builder to read codev/protocols/<name>/protocol.md:
codev-skeleton/protocols/air/builder-prompt.md:27
codev-skeleton/protocols/aspir/builder-prompt.md:30
codev-skeleton/protocols/bugfix/builder-prompt.md:28
codev-skeleton/protocols/experiment/builder-prompt.md:27
codev-skeleton/protocols/maintain/builder-prompt.md:26
codev-skeleton/protocols/pir/builder-prompt.md:30, :90
codev-skeleton/protocols/research/builder-prompt.md:27
codev-skeleton/protocols/spike/builder-prompt.md:14
codev-skeleton/protocols/spir/builder-prompt.md:30
codev-skeleton/roles/builder.md:83 (literal `cat codev/protocols/spir/protocol.md`)
A.2 — Template file references in phase prompts and protocol docs. Templates live in <skeleton>/protocols/<name>/templates/*.md and are referenced during phase work:
codev-skeleton/protocols/spir/prompts/plan.md:79
Use the plan template from `codev/protocols/spir/templates/plan.md` if available.
codev-skeleton/protocols/aspir/prompts/plan.md:79
Use the plan template from `codev/protocols/spir/templates/plan.md` if available.
codev-skeleton/protocols/experiment/protocol.md:40
cp codev/protocols/experiment/templates/notes.md notes.md
codev-skeleton/protocols/spike/protocol.md:55
Use the template: `codev/protocols/spike/templates/findings.md`
A.3 — Workflow-reference doc, referenced from inside protocol.md. When protocol.md is delivered to the builder (after A.1 is fixed), it carries a "See workflow-reference.md for stage diagrams" pointer that itself bypasses the resolver:
codev-skeleton/protocols/spir/protocol.md:7
> **Quick Reference**: See `codev/resources/workflow-reference.md` for stage diagrams and common commands.
The roles/architect.md:5 reference to the same file is the architect-side consumer (a different surface from this issue's builder scope) and stays out of scope here.
Verified in current main:
packages/codev/src/lib/skeleton.ts:63 (resolveCodevFile) reaches the embedded skeleton correctly. The bug is purely on the consumer side, not in the resolver itself.
packages/codev/src/agent-farm/commands/spawn-roles.ts:99-108 (loadBuilderPromptTemplate) loads builder-prompt.md via the resolver but does not include framework-file content in the returned template.
packages/codev/src/commands/porch/prompts.ts:77-82 (loadPromptFile) loads per-phase prompts via the resolver and returns them to the builder via porch next JSON. Phase prompts work; the framework-file references inside those phase prompts don't.
Sample
Fix
Three components organized in layers. Together they eliminate the bug class entirely under the no-copy constraint.
Layer 1 — Delivery: inline framework content into AI channels
The builder is the only concrete consumer with high-frequency framework-file needs. Make sure it receives content via the channels that already work (spawn-time prompt, porch JSON), never via literal-path shell reads.
Patch 1 — Spawn-time inline (covers A.1). Extend loadBuilderPromptTemplate() in packages/codev/src/agent-farm/commands/spawn-roles.ts:
function loadBuilderPromptTemplate(config, protocolName) {
const templatePath = resolveCodevFile(
`protocols/${protocolName}/builder-prompt.md`,
config.workspaceRoot,
);
if (!templatePath) return null;
let template = readFileSync(templatePath, 'utf-8');
// Inline protocol.md so the builder doesn't have to fetch it.
const protocolDocPath = resolveCodevFile(
`protocols/${protocolName}/protocol.md`,
config.workspaceRoot,
);
if (protocolDocPath) {
template += `\n\n---\n\n## Protocol Reference (full text)\n\n` +
readFileSync(protocolDocPath, 'utf-8');
}
return template;
}
~15 LOC. The builder receives protocol.md once in its initial prompt — never re-shipped, no shell command. Covers all 9 builder-prompts and the roles/builder.md:83 cat reference (the builder has the content when it would have tried to cat).
Patch 2 — Per-phase template inline (covers A.2). Two options, plan-gate decides:
- A — Extend
loadPromptFile() in packages/codev/src/commands/porch/prompts.ts to scan loaded prompt content for codev/protocols/<name>/templates/<file> references, resolve each, and inline under a ## Template heading. ~25 LOC code.
- B — Edit the four affected prompts to embed template content directly. ~40-100 LOC markdown, 0 LOC code.
Either way the builder receives the template content via porch's existing per-phase JSON — no resolver bypass.
Layer 2 — Cleanup: sweep redundant literal-path references from the skeleton
With Layer 1 delivering content, the literal-path instructions in the skeleton are redundant (and a regression risk — the builder might still try them). Remove or rewrite them:
- Builder-prompts: drop the
Follow the <X> protocol: \codev/protocols//protocol.md`` line in all 9 files. The protocol meta-doc is already in the builder's context via Patch 1.
roles/builder.md: replace the cat codev/protocols/spir/protocol.md example with reference to the inlined content (or remove the example entirely).
- Phase prompts referencing templates (if Patch 2 = Option A): rewrite to drop the literal-path reference since auto-detection handles it. If Patch 2 = Option B: literal paths are gone from these prompts by construction.
- A.3 (
workflow-reference.md inside spir/protocol.md:7): plan-gate decides:
- 1 Recursively inline workflow-reference.md alongside protocol.md (small extension of Patch 1).
- 2 Strip the "See workflow-reference.md" pointer (informational chrome, not load-bearing).
- 3 Accept graceful degradation (low impact, but leaves a known fail-source).
Layer 3 — Enforcement: convention docs + doctor audit
The fix only stays fixed if future contributors don't reintroduce literal-path references. Two enforcement steps:
- AGENTS.md / CLAUDE.md addition: a short section in the contributor guidance: "Framework files (protocols, roles, resources) live in the package skeleton, not in user projects. Never reference them by literal
codev/... path in any prompt, doc, or instruction. Content is delivered to builders via the spawn prompt (for protocol.md) and porch JSON (for per-phase prompts and templates)."
codev doctor audit check: grep the skeleton (and any local codev/protocols/, codev/roles/, codev/resources/ directories) for cat codev/(protocols|roles|resources)/ and backtick-wrapped literal paths to framework files. Warn on hits with a pointer to the convention doc. ~30 LOC, same pattern as existing doctor checks.
Why these patches, not the rejected alternatives
| Alternative |
Rejected because |
| Restore framework file copying on init/update |
Reverses Spec 618; "single source of truth, straightforward updates" is the load-bearing reason to maintain the no-copy model; humans-need-files-locally rationale is mostly speculative |
Add codev read <path> CLI for shell consumers |
Speculative infrastructure. Every concrete consumer is either served by inlining (builders / AI agents) or not actually helped by a CLI (IDE search, @-mention in chat tools, both bypass shell entirely). No named real consumer that the CLI uniquely serves. Add only if a real shell consumer surfaces. |
Inject framework files on every porch next response |
Wasteful — meta-doc and templates don't change phase-to-phase; redundant re-delivery wastes context budget |
| Drop literal-path instructions WITHOUT inlining |
Per-protocol audit cost; per-phase prompts vary in self-containment (PIR may be fine without protocol.md, SPIR likely isn't). Combined WITH inlining (this proposal's Layer 1) it's safe; alone it's not. |
Acceptance criteria
Out of scope
Suggested protocol
PIR. The fix is mechanically small (Layer 1 ~30 LOC code, Layer 2 ~50-100 LOC skeleton edits, Layer 3 ~50 LOC code + docs), but applies to every builder spawn and every per-phase prompt across every protocol, and the plan-gate has real decisions to lock before code:
- Heading / delimiter format for inlined sections (
## Protocol Reference, ## Template) so per-phase prompts and inlined content don't blur in the builder's context.
- Patch 2 mechanism: auto-detect template references and inline at load time (Option A), or explicit-embed at edit time (Option B).
- A.3 disposition: recursive inline / strip the reference / accept graceful degradation.
- Behavior when a framework file does not resolve (warn vs silently skip; current default is silently skip; worth a conscious decision).
- Doctor check semantics: warn vs error on literal-path findings; whether to also check user-customized
codev/ directories or skeleton only.
The dev-approval gate is load-bearing. The change has to be tested in a running builder in a fresh codev init test project to confirm:
- The inlined content actually stops the file-hunting behavior.
- It doesn't introduce new confusion (the builder ignoring per-phase prompts because the inlined material is louder in its context).
- Per-phase templates land correctly in the right phase prompts.
- The doctor audit catches a deliberately-introduced literal-path reference (negative test).
PR-diff review alone won't catch these.
Related
Bug class
In fresh post-Spec-618 installs, any framework-provided file referenced by literal path from a builder-side consumer fails. Three sub-instances observed in current
main:A.1 — Protocol meta-doc references (9 builder-prompts + 1 role file). Every protocol's
builder-prompt.mdinstructs the builder to readcodev/protocols/<name>/protocol.md:A.2 — Template file references in phase prompts and protocol docs. Templates live in
<skeleton>/protocols/<name>/templates/*.mdand are referenced during phase work:A.3 — Workflow-reference doc, referenced from inside protocol.md. When
protocol.mdis delivered to the builder (after A.1 is fixed), it carries a "See workflow-reference.md for stage diagrams" pointer that itself bypasses the resolver:The
roles/architect.md:5reference to the same file is the architect-side consumer (a different surface from this issue's builder scope) and stays out of scope here.Verified in current
main:packages/codev/src/lib/skeleton.ts:63(resolveCodevFile) reaches the embedded skeleton correctly. The bug is purely on the consumer side, not in the resolver itself.packages/codev/src/agent-farm/commands/spawn-roles.ts:99-108(loadBuilderPromptTemplate) loadsbuilder-prompt.mdvia the resolver but does not include framework-file content in the returned template.packages/codev/src/commands/porch/prompts.ts:77-82(loadPromptFile) loads per-phase prompts via the resolver and returns them to the builder viaporch nextJSON. Phase prompts work; the framework-file references inside those phase prompts don't.Sample
Fix
Three components organized in layers. Together they eliminate the bug class entirely under the no-copy constraint.
Layer 1 — Delivery: inline framework content into AI channels
The builder is the only concrete consumer with high-frequency framework-file needs. Make sure it receives content via the channels that already work (spawn-time prompt, porch JSON), never via literal-path shell reads.
Patch 1 — Spawn-time inline (covers A.1). Extend
loadBuilderPromptTemplate()inpackages/codev/src/agent-farm/commands/spawn-roles.ts:~15 LOC. The builder receives
protocol.mdonce in its initial prompt — never re-shipped, no shell command. Covers all 9 builder-prompts and theroles/builder.md:83cat reference (the builder has the content when it would have tried to cat).Patch 2 — Per-phase template inline (covers A.2). Two options, plan-gate decides:
loadPromptFile()inpackages/codev/src/commands/porch/prompts.tsto scan loaded prompt content forcodev/protocols/<name>/templates/<file>references, resolve each, and inline under a## Templateheading. ~25 LOC code.Either way the builder receives the template content via porch's existing per-phase JSON — no resolver bypass.
Layer 2 — Cleanup: sweep redundant literal-path references from the skeleton
With Layer 1 delivering content, the literal-path instructions in the skeleton are redundant (and a regression risk — the builder might still try them). Remove or rewrite them:
Follow the <X> protocol: \codev/protocols//protocol.md`` line in all 9 files. The protocol meta-doc is already in the builder's context via Patch 1.roles/builder.md: replace thecat codev/protocols/spir/protocol.mdexample with reference to the inlined content (or remove the example entirely).workflow-reference.mdinsidespir/protocol.md:7): plan-gate decides:Layer 3 — Enforcement: convention docs + doctor audit
The fix only stays fixed if future contributors don't reintroduce literal-path references. Two enforcement steps:
codev/...path in any prompt, doc, or instruction. Content is delivered to builders via the spawn prompt (forprotocol.md) and porch JSON (for per-phase prompts and templates)."codev doctoraudit check: grep the skeleton (and any localcodev/protocols/,codev/roles/,codev/resources/directories) forcat codev/(protocols|roles|resources)/and backtick-wrapped literal paths to framework files. Warn on hits with a pointer to the convention doc. ~30 LOC, same pattern as existing doctor checks.Why these patches, not the rejected alternatives
codev read <path>CLI for shell consumers@-mention in chat tools, both bypass shell entirely). No named real consumer that the CLI uniquely serves. Add only if a real shell consumer surfaces.porch nextresponseprotocol.md, SPIR likely isn't). Combined WITH inlining (this proposal's Layer 1) it's safe; alone it's not.Acceptance criteria
loadBuilderPromptTemplate()inlinesprotocol.mdcontent into the returned spawn template when present, under a clear delimiter heading. Covers all 9 protocols uniformly.roles/builder.md, phase prompts that reference templates (per Patch 2 choice), and A.3 reference (per chosen disposition).codev doctoraudit check added; greps for literal-path framework references and warns with a pointer to the convention.codev inittest project: the builder's initial prompt contains the protocol meta-doc; per-phase prompts contain referenced templates; no file-hunting visible across the full plan + implement + review cycle.Out of scope
codev/resources/arch.md,codev/resources/lessons-learned.md). These are user-evolved files, not framework files. Tracked as scaffold:codev initbootstraps emptycodev/resources/with arch.md + lessons-learned.md starters #1012.workflow-reference.mdreference inroles/architect.md:5. Different consumer surface; file separately if it becomes a real architect-side problem.codev init/codev update— Spec 618 left builders without local protocol files in fresh installs #738). The single-source-of-truth model is the architectural premise this fix preserves.@-mention resolution for framework files. Unavoidable consequence of the no-copy model; no patch within the constraint helps. Workaround: contributors addnode_modules/@cluesmith/codev/skeleton/to their IDE search scope.Suggested protocol
PIR. The fix is mechanically small (Layer 1 ~30 LOC code, Layer 2 ~50-100 LOC skeleton edits, Layer 3 ~50 LOC code + docs), but applies to every builder spawn and every per-phase prompt across every protocol, and the plan-gate has real decisions to lock before code:
## Protocol Reference,## Template) so per-phase prompts and inlined content don't blur in the builder's context.codev/directories or skeleton only.The dev-approval gate is load-bearing. The change has to be tested in a running builder in a fresh
codev inittest project to confirm:PR-diff review alone won't catch these.
Related
codev init/codev update— Spec 618 left builders without local protocol files in fresh installs #738 — original issue. This closes its tactical layer broadly. The strategic question (restore framework file copying) stays in Restore framework file copying oncodev init/codev update— Spec 618 left builders without local protocol files in fresh installs #738 for separate discussion.codev initbootstraps emptycodev/resources/with arch.md + lessons-learned.md starters #1012 — project-specific bootstrap (codev/resources/) on init. Companion fix from the same audit.