Skip to content

fix(init): preserve manual content in AGENTS.md / CLAUDE.md via managed-section markers#167

Merged
avrabe merged 3 commits intomainfrom
fix/init-agents-preserve-manual-sections
Apr 21, 2026
Merged

fix(init): preserve manual content in AGENTS.md / CLAUDE.md via managed-section markers#167
avrabe merged 3 commits intomainfrom
fix/init-agents-preserve-manual-sections

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented Apr 21, 2026

Summary

rivet init --agents previously regenerated AGENTS.md (and the newer CLAUDE.md shim) from scratch on every run, obliterating any manual content users had added. Downstream projects like sigil ship a load-bearing top-of-file warning comment saying "don't run rivet init --agents or you'll lose the manual audit section" — that comment being load-bearing is itself a bug. This PR fixes the root cause.

Root cause

cmd_init_agents called std::fs::write on the file path unconditionally. Any hand-written content outside the auto-generated prose was discarded. There was no way to opt out short of committing a workaround comment.

Marker scheme design

Only content between HTML-comment markers is regenerated; everything outside is preserved verbatim:

<!-- BEGIN rivet-managed: auto-generated section. ... -->
... generated content ...
<!-- END rivet-managed -->

HTML comments are valid Markdown and invisible in rendered output. The splice logic (new rivet_core::managed_section module) matches BEGIN/END by prefix so the explanatory text in the opening comment can be updated over time without breaking detection of already-markered files. Error cases are exhaustively modelled:

Existing file state Behaviour
Does not exist Write preamble + fresh BEGIN/END block.
Exactly one BEGIN/END Splice — replace only the managed region.
No markers, no flag Refuse with exit 1, file untouched byte-for-byte, stderr suggests --migrate or --force-regen.
No markers, --migrate Wrap existing content: managed section on top, prior content preserved verbatim below.
No markers, --force-regen Overwrite with freshly markered content; loud stderr warning.
Multiple BEGIN/END pairs Refuse with exit 1 (ambiguous); file untouched; error lists the offending line numbers.
Unclosed BEGIN / orphan END Refuse with exit 1 and a pointer to the specific line.

Migration path for existing projects

Projects that already have an AGENTS.md or CLAUDE.md without markers will hit the new refusal on first run after upgrading. Two ways forward:

  1. rivet init --agents --migrate — safe, non-destructive; wraps existing content. Recommended.
  2. Manually add <!-- BEGIN rivet-managed --> / <!-- END rivet-managed --> around the portion that should regenerate, then re-run rivet init --agents.
  3. rivet init --agents --force-regen — destructive; only for the case where you truly want to throw away everything.

rivet's own AGENTS.md and CLAUDE.md are migrated as part of this PR (commit 3) so the repo is self-consistent after merge.

CLAUDE.md scope

CLAUDE.md is written by the same cmd_init_agents code path as AGENTS.md (grep rivet-cli/src for CLAUDE\.md — only cmd_init_agents writes it). Both files use the same write_managed_file helper and therefore inherit the marker semantics automatically. No additional code path needed CLAUDE.md support.

Can sigil remove its warning comment now?

Yes. Once sigil updates to a rivet that contains this PR, it can drop the "don't regenerate" header comment and either migrate its AGENTS.md via rivet init --agents --migrate or hand-add markers around the auto-generated portion. Manual audit sections placed outside the markers will survive every subsequent rivet init --agents call.

Commits

  1. d66dee2 — wip scaffolding: managed_section.rs + --migrate / --force-regen flag wiring (from previous agent).
  2. fc3e576 — integration tests covering all six required scenarios + CLAUDE.md splice.
  3. 3a1fbf2 — migrate rivet's own AGENTS.md and CLAUDE.md to use markers.

Test plan

  • cargo check --all-targets clean
  • cargo build -p rivet-cli clean
  • cargo clippy --all-targets -- -D warnings clean (only pre-existing MSRV warning)
  • cargo test -p rivet-core --lib managed_section — 11/11 unit tests pass (splice, wrap_fresh, migrate_wrap, has_markers, and all error variants)
  • cargo test -p rivet-cli --test init_integration — 7/7 end-to-end tests pass:
    • agents_md_fresh_file_has_markers
    • agents_md_preserves_manual_section_outside_markers
    • agents_md_refuses_no_markers_default
    • agents_md_force_regen_overwrites_no_markers
    • agents_md_migrate_wraps_existing_content
    • agents_md_multiple_markers_rejected
    • claude_md_preserves_manual_section_outside_markers
  • CI pipeline on the PR
  • Manual smoke: rivet init --agents on a fresh project, verify markers; re-run with manual edits above/below markers, verify they survive

🤖 Generated with Claude Code

avrabe and others added 2 commits April 21, 2026 20:00
The stalled Mythos agent got about 60% through this task before
hitting a 600s watchdog timeout. Saving the WIP so it isn't lost:

- New rivet-core/src/managed_section.rs: splice_managed_section() with
  the BEGIN rivet-managed / END rivet-managed HTML-comment scheme, plus
  error types for NoMarkers and MultipleMarkers.
- rivet-cli/src/main.rs: --migrate and --force-regen flags wired into
  cmd_init_agents (partial).

**Not yet done** (pickup list for whoever takes this over):
- Integration tests in rivet-cli/tests/init_integration.rs
- CLAUDE.md regen path (confirm whether init --agents touches it)
- Migrate rivet's own AGENTS.md to use markers
- Confirm cargo build + cargo test pass

**Why it matters**: without this, `rivet init --agents` silently
overwrites downstream consumers' manual AGENTS.md content. Sigil
ships a "don't regenerate" warning comment as a workaround.

Do not merge this commit; pick up where it left off or restart
with a tighter agent scope.

Trace: skip
Seven end-to-end tests that exercise `rivet init --agents` against the
full CLI binary, covering every branch of the write_managed_file state
machine:

- agents_md_fresh_file_has_markers — non-existent file gets exactly one
  BEGIN/END rivet-managed pair on first write.
- agents_md_preserves_manual_section_outside_markers — prose above and
  below the markers survives regeneration; only the managed region is
  replaced.
- agents_md_refuses_no_markers_default — pre-existing file with no
  markers and no flag -> exit 1, file untouched byte-for-byte.
- agents_md_force_regen_overwrites_no_markers — --force-regen discards
  prior content, emits a stderr warning.
- agents_md_migrate_wraps_existing_content — --migrate puts the managed
  section on top, preserves prior content below, and a subsequent plain
  regen splices cleanly.
- agents_md_multiple_markers_rejected — two BEGIN/END pairs -> exit 1,
  file untouched.
- claude_md_preserves_manual_section_outside_markers — the same splice
  semantics apply to CLAUDE.md.

The existing 11 unit tests in rivet-core/src/managed_section.rs already
cover the pure-function surface (splice, wrap_fresh, migrate_wrap,
has_markers, and the error cases NoMarkers, MultipleBeginMarkers,
UnclosedMarker, OrphanEndMarker), so these integration tests focus on
the CLI wiring and filesystem side-effects rather than duplicating
the unit coverage.

Fixes: REQ-007
Verifies: REQ-007
Refs: FEAT-026

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'Rivet Criterion Benchmarks'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.20.

Benchmark suite Current: 4e3b1df Previous: 60d728a Ratio
store_lookup/100 2251 ns/iter (± 5) 1681 ns/iter (± 4) 1.34
store_lookup/1000 25616 ns/iter (± 71) 19280 ns/iter (± 48) 1.33
traceability_matrix/1000 61043 ns/iter (± 179) 41331 ns/iter (± 88) 1.48
query/100 795 ns/iter (± 6) 619 ns/iter (± 1) 1.28
query/1000 7284 ns/iter (± 15) 5174 ns/iter (± 14) 1.41

This comment was automatically generated by workflow using github-action-benchmark.

Self-host the managed-section scheme so a future `rivet init --agents`
run on the rivet repo itself splices the auto-generated region cleanly
instead of tripping the new no-marker refusal path.

AGENTS.md:
- Project overview, artifact-type table, link-type table, and the
  Conventions block (all currently regenerated by `cmd_init_agents`)
  are wrapped inside a single BEGIN/END rivet-managed pair.
- The hand-expanded Commit Traceability reference (trailer table,
  choosing-the-right-artifacts guide, and the retroactive traceability
  map) is moved below the END marker so it survives regeneration. The
  generator emits a much shorter commits section; keeping the rich
  reference outside the markers lets us expand it without fighting the
  regenerator.

CLAUDE.md:
- The entire hand-authored content (validation/queries, commit
  traceability quick reference, hook security model, AI provenance)
  now lives above the markers and will be preserved verbatim.
- The managed region is committed as an empty stub with an explanatory
  comment; the next `rivet init --agents` will populate it with the
  generated CLAUDE.md shim.

CLAUDE.md scope check: `rivet init --agents` is the only code path in
rivet-cli that writes CLAUDE.md (grep for `CLAUDE\.md` in
rivet-cli/src confirms no other write site), and it already uses the
same `write_managed_file` helper as AGENTS.md via d66dee2. No
additional code change is needed for CLAUDE.md support.

Fixes: REQ-007
Refs: FEAT-026

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@avrabe avrabe force-pushed the fix/init-agents-preserve-manual-sections branch from 3a1fbf2 to 4e3b1df Compare April 21, 2026 19:41
@avrabe avrabe merged commit a7dcc30 into main Apr 21, 2026
13 checks passed
@avrabe avrabe deleted the fix/init-agents-preserve-manual-sections branch April 21, 2026 19:44
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 21, 2026

Codecov Report

❌ Patch coverage is 98.26590% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
rivet-core/src/managed_section.rs 98.26% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant