The guide learns the thread it was silent on, and grows a vendor-neutral twin
CLAUDE.md bumps to v14: a new Comments section teaches the comments/ mechanics (chronology-as-ordering, author vs modified-by, .draft/.trash as the app's, retract-by-follow-up), and a new "Use the thread: journal your work" section teaches conduct the guide never had — body is the spec, thread is the journal, post a plan cold-reader-ready on start, decisions as they're made, questions as comments, re-read before resuming, close with verification. comments/ leaves the reserved-tracker-keys list; the Layout diagram gains comments/ and AGENTS.md. The app now writes a byte-identical twin at AGENTS.md, the vendor-neutral name most non-Claude tools read — same lifecycle as CLAUDE.md, decided and healed independently per claimed name, both funneling a markerless foreign file to the single shared CLAUDE.user.md rescue. AgentGuide.install now returns [Displacement]; IntegrityRules.claimedRootNames and BoardStore.refreshAgentGuide cover both names; ChangeNarrator's guide-commit path check widens to both. DESIGN/08-agent-integration.md amends: the agent-guide section gains the Comments and Use-the-thread bullets and an AGENTS.md twin paragraph. Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
@@ -215,9 +215,15 @@ public enum IntegrityRules: Sendable {
|
||||
/// `CLAUDE.md`'s squatter is displaced by the **agent guide's** own heal, which already owns
|
||||
/// that file's whole decision (`AgentGuide.Decision.displaceSquatterThenWrite`); `.trash`'s is
|
||||
/// its own scheduled heal, because nothing else ever writes that name.
|
||||
///
|
||||
/// **`AGENTS.md` joined 2026-08-09** (card dc1314bb, 08-agent-integration.md ▸ The agent guide):
|
||||
/// the byte-identical twin of `CLAUDE.md`, claimed and displaced on exactly the same terms — its
|
||||
/// squatter is the agent guide's own heal too (`AgentGuide.install` runs the same decision against
|
||||
/// both names), so it is not answered by `squattedClaimedName(atBoardRoot:)` below either.
|
||||
public static let claimedRootNames: [ClaimedName] = [
|
||||
ClaimedName(name: trashFolderName, expected: .directory, displacesSquatters: true),
|
||||
ClaimedName(name: "CLAUDE.md", expected: .file, displacesSquatters: true),
|
||||
ClaimedName(name: "AGENTS.md", expected: .file, displacesSquatters: true),
|
||||
ClaimedName(name: "CLAUDE.user.md", expected: .file, displacesSquatters: false),
|
||||
ClaimedName(name: gitignoreFileName, expected: .file, displacesSquatters: false),
|
||||
]
|
||||
@@ -291,9 +297,9 @@ public enum IntegrityRules: Sendable {
|
||||
/// (01-storage-format.md § Fractal layout ▸ Rules, ruled 2026-07-29).
|
||||
///
|
||||
/// Only names whose `displacesSquatters` is `true` can produce one, and only `.trash` is
|
||||
/// answered here: `CLAUDE.md`'s squatter is the agent guide's, detected by `AgentGuide.inspect`
|
||||
/// in the same read that decides everything else about that file, so answering it twice would be
|
||||
/// two mechanisms racing to displace one node.
|
||||
/// answered here: `CLAUDE.md` and its `AGENTS.md` twin's squatters are the agent guide's,
|
||||
/// detected by `AgentGuide.inspect` in the same read that decides everything else about each
|
||||
/// file, so answering either here too would be two mechanisms racing to displace one node.
|
||||
public static func squattedClaimedName(atBoardRoot root: URL) -> ClaimedNameSquatter? {
|
||||
guard let claimed = claimedRootNames.first(where: { $0.name == trashFolderName }),
|
||||
let found = node(at: root.appendingPathComponent(claimed.name)),
|
||||
|
||||
Reference in New Issue
Block a user