Skip to content

feat: scaffold DCP config in replicator init and add doctor check - #79

Merged
jflowers merged 4 commits into
unbound-force:mainfrom
jflowers:opsx/add-dcp-config
Aug 17, 2026
Merged

feat: scaffold DCP config in replicator init and add doctor check#79
jflowers merged 4 commits into
unbound-force:mainfrom
jflowers:opsx/add-dcp-config

Conversation

@jflowers

Copy link
Copy Markdown
Contributor

Summary

replicator init scaffolds five slash-command files with <protect> tags, but did not create the .opencode/dcp.jsonc configuration 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:

  • Adding ScaffoldDCP() to create .opencode/dcp.jsonc with protectTags: true during replicator init
  • Adding a checkDCPConfig() doctor health check that warns when protect-tagged commands exist but DCP config is missing or misconfigured
  • Supporting .dcp.json as an alias with .jsonc preference when both exist

Closes: unbound-force/unbound-force#502

How to Test

# Run the full test suite
make check

# Verify in a fresh directory
mkdir /tmp/test-dcp && cd /tmp/test-dcp
replicator init
# Should show: "created .opencode/dcp.jsonc"
cat .opencode/dcp.jsonc
# Should contain protectTags: true

# Re-run (idempotent)
replicator init
# Should show: "skipped .opencode/dcp.jsonc (exists)"

# Doctor check
replicator doctor
# Should show: dcp_config [pass] "protectTags enabled in DCP config"

How to Demo

  1. Run replicator init in a fresh directory — observe dcp.jsonc in the output
  2. Inspect .opencode/dcp.jsonc — contains $schema and protectTags: true
  3. Run replicator doctor — the 5th check (dcp_config) shows pass
  4. Delete .opencode/dcp.jsonc and re-run replicator doctor — shows warning with "run replicator init"

Key Files Changed

cmd/replicator/

  • doctor.go — passes os.Getwd() to Run() for per-project DCP check
  • init.go — calls ScaffoldDCP() after Scaffold(), renders styled output
  • init_test.go — DCP assertions + fixed pre-existing unchecked errors in test setup

internal/agentkit/

  • agentkit.goScaffoldDCP() function and dcpConfigContent constant
  • agentkit_test.go — 6 tests: fresh dir, skip, update, .json alias, both files, dir creation

internal/doctor/

  • checks.gocheckDCPConfig(projectDir) check, Run() signature accepts projectDir
  • checks_test.go — 6 tests covering pass/warn scenarios + .json alias

openspec/changes/add-dcp-config/

  • Full spec artifacts: proposal, design (11 decisions), specs, tasks

This PR was generated by /uf.finale (AI-assisted).

- 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)
@jflowers
jflowers requested a review from a team as a code owner August 16, 2026 18:44
@jflowers jflowers self-assigned this Aug 16, 2026
@jflowers jflowers moved this to Ready for Review 👀 in Unbound Force Planning Aug 16, 2026

@yvonnedevlinrh yvonnedevlinrh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Comment thread internal/agentkit/agentkit.go
Comment thread internal/agentkit/agentkit.go Outdated
Comment thread cmd/replicator/init.go Outdated
Comment thread internal/doctor/checks.go Outdated
…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 yvonnedevlinrh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found

@jflowers
jflowers merged commit 307f86e into unbound-force:main Aug 17, 2026
1 check passed
jflowers added a commit that referenced this pull request Aug 17, 2026
…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
jflowers added a commit that referenced this pull request Aug 17, 2026
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
yvonnedevlinrh added a commit that referenced this pull request Aug 18, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Ready for Review 👀

Development

Successfully merging this pull request may close these issues.

chore: uf init should scaffold .opencode/dcp.jsonc with compress.protectTags

3 participants