diff --git a/Kanban/Storage/AgentGuide.swift b/Kanban/Storage/AgentGuide.swift index 31352e5..e0e2206 100644 --- a/Kanban/Storage/AgentGuide.swift +++ b/Kanban/Storage/AgentGuide.swift @@ -335,9 +335,9 @@ enum AgentGuide { keys you don't recognize and don't reformat content you didn't change. - **Delete a card = move it into `/.trash/`**: `mv / /.trash/` (create `.trash/` if missing). Arrivals go on top: set - the card's `order` below the smallest `order` already in `.trash/` (empty - trash: any number), and update `modified`. Restore is the same move in - reverse — into a lane, with a fresh `order`. + the card's `order` to the smallest `order` already in `.trash/` minus + 1024 (empty trash: any number), and update `modified`. Restore is the + same move in reverse — into a lane, with a fresh `order`. - Never write a `deleted:` key — that convention is retired; the app migrates any it finds. - Remove a folder outright (`rm -r`) only when you mean permanent, diff --git a/KanbanTests/AgentGuideTests.swift b/KanbanTests/AgentGuideTests.swift index 7890cea..00901de 100644 --- a/KanbanTests/AgentGuideTests.swift +++ b/KanbanTests/AgentGuideTests.swift @@ -568,3 +568,48 @@ struct AgentGuideRegistryTests { #expect(store.reloadFailure == nil) } } + +// MARK: - 5. The content + +/// What the guide *says*, pinned where saying it wrong would mislead every agent that reads it — +/// the authoring card's contract (08-agent-integration.md ▸ The agent guide's list): the schema it +/// condenses is 01-storage-format.md's, post-pivot, and the vocabulary it teaches must be the +/// app's own. +@Suite("Agent guide ▸ the content") +struct AgentGuideContentTests { + + /// The palette tables are transcribed prose, and transcriptions drift. Tying every name to + /// `Palette`'s own tables makes a palette rename a failing guide test rather than a silently + /// wrong document teaching agents colors the app no longer resolves. + @Test("Every palette name the app resolves appears in the guide") + func paletteNamesMatchTheSource() { + for color in Palette.foregrounds + Palette.backgrounds { + #expect(AgentGuide.content.contains("`\(color.name)`"), "missing palette name: \(color.name)") + } + } + + @Test("The guide teaches the current conventions by name") + func currentVocabularyIsPresent() { + let content = AgentGuide.content + // The rewrite's list, 08 ▸ The agent guide: attachments, the trash, self-stamping, the + // user extension point, staging etiquette — each findable by the string an agent would + // grep for. + #expect(content.contains(".trash/")) + #expect(content.contains("attachments/")) + #expect(content.contains("modified-by")) + #expect(content.contains("CLAUDE.user.md")) + #expect(content.contains("git add -A")) + #expect(content.contains("schema: 1")) + } + + /// The pathfinder's guide taught `media/` and tombstone deletes; both are retired + /// (01-storage-format.md ▸ Changes from the pathfinder schema; ▸ Deletion). The one legitimate + /// mention of `deleted:` is the warning never to write it. + @Test("Retired vocabulary does not resurface") + func retiredVocabularyIsAbsent() { + let content = AgentGuide.content + #expect(!content.contains("media/")) + #expect(!content.contains("tombstone")) + #expect(content.contains("Never write a `deleted:` key")) + } +}