Build AgentGuide — versioned CLAUDE.md maintenance

The app-owned agent guide at every board root (DESIGN/08 ▸ The agent
guide): version-gated by a first-line marker (v5, superseding the
pathfinder's v4 guides on real boards), rewritten when missing or older,
byte-for-byte untouched when current or newer. A markerless CLAUDE.md is
displaced to CLAUDE.user.md when that name is free — never clobbered —
and the guide write is skipped with a log when it isn't. Symlinks,
folders, and read-only volumes are skipped in silence; the write rides
performWrite's bracket as an app-mediated Writer operation (new
WriteOperation.agentGuide), so the echo lands appMediated and the
Pro-era committer can attribute it honestly later.

Hooked at store acquire (beside the loose-file relocation, after the
watcher exists) and on every successful reload — the guide self-heals
from foreign deletion or rollback, pre-wiring 06's acknowledged undo
bounce. The refresh memo arms before each attempt and clears on a
successful write, so a failing write can't hot-loop and a foreign
deletion stays healable. First-line-only marker parsing (no Regex);
guide content is one swappable literal, finalized under the next card.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-07-28 21:56:10 -04:00
parent 3aa80db2a4
commit b3812ed928
8 changed files with 1119 additions and 2 deletions
@@ -23,9 +23,16 @@ import Testing
// MARK: - Shared fixtures
/// A one-lane, one-card board, ready for whatever the test wants to leave beside `index.md`.
///
/// It carries a **current agent guide**, which is what any board the app has opened once looks like
/// (08-agent-integration.md The agent guide). Without it the store's own guide refresh which
/// runs on every successful reload, beside this file's relocation would write a `CLAUDE.md` on
/// the first reload and open a bracket of its own, and the bracket counts below would stop being
/// claims about the relocation.
private func makeCardBoard() throws -> WriterFixture {
let fixture = try WriterFixture()
try fixture.item("", Item.board)
try fixture.file(AgentGuide.filename, Data(AgentGuide.content.utf8))
try fixture.item(Ident.lane1, Item.rich(order: "1024", title: "Todo"))
try fixture.item("\(Ident.lane1)/\(Ident.card1)", Item.rich(order: "1024", title: "Fix login"))
return fixture