feat: scaffold DCP config in replicator init and add doctor check - #79
Conversation
- Add ScaffoldDCP() to agentkit: creates .opencode/dcp.jsonc with protectTags enabled, making <protect> tags in slash commands functional - Integrate ScaffoldDCP() into replicator init with idempotent behavior (creates, skips if configured, updates if missing protectTags) - Add checkDCPConfig() doctor check: warns when protect-tagged commands exist but DCP config is missing or misconfigured - Support .dcp.json alias with .jsonc preference when both exist - Fix pre-existing unchecked errors in init_test.go setup code - Add OpenSpec artifacts and Dewey learnings Closes: unbound-force/unbound-force#502 Assisted-by: claude-opus Generated with AI assistance (claude-opus)
yvonnedevlinrh
left a comment
There was a problem hiding this comment.
Review: PR #79 — feat: scaffold DCP config in replicator init and add doctor check
Summary
This PR correctly fixes a real gap: <protect> tags in scaffolded slash commands were silently inert without .opencode/dcp.jsonc. The implementation is clean, idempotent, and well-tested across the full scenario matrix (12 new tests). Spec artifacts are complete and committed. CI passes.
One consolidated HIGH finding around a name-implementation contract mismatch on ScaffoldResult.Action, one MEDIUM spec-gap finding, and two LOW observability/doc findings.
Verdict: APPROVE (with non-blocking findings)
Nothing here blocks merge. The HIGH is a doc/naming inconsistency, not a runtime bug — the caller handles all values correctly today.
Findings
| # | Severity | Category | Summary | Location |
|---|---|---|---|---|
| 1 | HIGH | Contract | ScaffoldResult.Action doc claims 3 values; ScaffoldDCP returns a 4th undocumented value "updated" |
agentkit.go:23, agentkit.go:75 |
| 2 | MEDIUM | Alignment | Issue #502 suggests DryRun support; not captured in spec or implemented | spec gap |
| 3 | MEDIUM | Contract | runInit doc comment omits DCP scaffolding step and "updated" action |
init.go:36-38 |
| 4 | LOW | Security | Silent continue on unreadable files in doctor <protect> scan loop |
checks.go:162-163 |
See inline comments for details on findings 1, 3, and 4.
This review was generated by /uf.review-pr (AI-assisted).
…tten" The Action field documented "created", "skipped", "overwritten" but ScaffoldDCP returned "updated" and its doc comment used "replaced". Align all three to use "overwritten" consistently. Also update runInit doc comment to mention DCP scaffolding. Addresses PR unbound-force#79 review feedback from @yvonnedevlinrh. Signed-off-by: Joel Hooks <joelhooks@gmail.com> Assisted-by: claude-opus-4-6
Previously, unreadable .md files were silently skipped during the protectTags scan. Return a warn-level CheckResult so permission issues are visible to the user. Addresses PR unbound-force#79 review feedback from @yvonnedevlinrh. Signed-off-by: Joel Hooks <joelhooks@gmail.com> Assisted-by: claude-opus-4-6
Ensures checkDCPConfig returns a warn-level result with the file name when a command .md file cannot be read, rather than silently skipping. Signed-off-by: Joel Hooks <joelhooks@gmail.com> Assisted-by: claude-opus-4-6
yvonnedevlinrh
left a comment
There was a problem hiding this comment.
No blocking issues found
…tten" The Action field documented "created", "skipped", "overwritten" but ScaffoldDCP returned "updated" and its doc comment used "replaced". Align all three to use "overwritten" consistently. Also update runInit doc comment to mention DCP scaffolding. Addresses PR #79 review feedback from @yvonnedevlinrh. Signed-off-by: Joel Hooks <joelhooks@gmail.com> Assisted-by: claude-opus-4-6
Previously, unreadable .md files were silently skipped during the protectTags scan. Return a warn-level CheckResult so permission issues are visible to the user. Addresses PR #79 review feedback from @yvonnedevlinrh. Signed-off-by: Joel Hooks <joelhooks@gmail.com> Assisted-by: claude-opus-4-6
ScaffoldDCP() returns "overwritten" (consistent with Scaffold()), but three spec documents still referenced "updated". Align scaffold-dcp.md, design.md, and proposal.md to match the implementation. Identified during review of PR #79. Assisted-by: claude-opus-4-6 Signed-off-by: Yvonne Devlin <ydevlin@redhat.com>
Summary
replicator initscaffolds five slash-command files with<protect>tags, but did not create the.opencode/dcp.jsoncconfiguration that tells DCP to honor those tags. Without this file, the<protect>tags were inert — DCP had no configuration telling it to preserve protected sections during context pruning.This change fixes the gap by:
ScaffoldDCP()to create.opencode/dcp.jsoncwithprotectTags: trueduringreplicator initcheckDCPConfig()doctor health check that warns when protect-tagged commands exist but DCP config is missing or misconfigured.dcp.jsonas an alias with.jsoncpreference when both existCloses: unbound-force/unbound-force#502
How to Test
How to Demo
replicator initin a fresh directory — observedcp.jsoncin the output.opencode/dcp.jsonc— contains$schemaandprotectTags: truereplicator doctor— the 5th check (dcp_config) shows pass.opencode/dcp.jsoncand re-runreplicator doctor— shows warning with "run replicator init"Key Files Changed
cmd/replicator/
doctor.go— passesos.Getwd()toRun()for per-project DCP checkinit.go— callsScaffoldDCP()afterScaffold(), renders styled outputinit_test.go— DCP assertions + fixed pre-existing unchecked errors in test setupinternal/agentkit/
agentkit.go—ScaffoldDCP()function anddcpConfigContentconstantagentkit_test.go— 6 tests: fresh dir, skip, update, .json alias, both files, dir creationinternal/doctor/
checks.go—checkDCPConfig(projectDir)check,Run()signature acceptsprojectDirchecks_test.go— 6 tests covering pass/warn scenarios + .json aliasopenspec/changes/add-dcp-config/
This PR was generated by /uf.finale (AI-assisted).