cleargate 0.1.0-alpha.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +41 -2
  2. package/dist/MANIFEST.json +160 -0
  3. package/dist/cli.cjs +4396 -16
  4. package/dist/cli.cjs.map +1 -1
  5. package/dist/cli.js +4380 -4
  6. package/dist/cli.js.map +1 -1
  7. package/dist/templates/cleargate-planning/.claude/agents/architect.md +57 -0
  8. package/dist/templates/cleargate-planning/.claude/agents/cleargate-wiki-ingest.md +145 -0
  9. package/dist/templates/cleargate-planning/.claude/agents/cleargate-wiki-lint.md +256 -0
  10. package/dist/templates/cleargate-planning/.claude/agents/cleargate-wiki-query.md +143 -0
  11. package/dist/templates/cleargate-planning/.claude/agents/developer.md +58 -0
  12. package/dist/templates/cleargate-planning/.claude/agents/qa.md +57 -0
  13. package/dist/templates/cleargate-planning/.claude/agents/reporter.md +114 -0
  14. package/dist/templates/cleargate-planning/.claude/hooks/session-start.sh +4 -0
  15. package/dist/templates/cleargate-planning/.claude/hooks/stamp-and-gate.sh +18 -0
  16. package/dist/templates/cleargate-planning/.claude/hooks/token-ledger.sh +174 -0
  17. package/dist/templates/cleargate-planning/.claude/settings.json +35 -0
  18. package/dist/templates/cleargate-planning/.claude/skills/flashcard/SKILL.md +73 -0
  19. package/dist/templates/cleargate-planning/.cleargate/FLASHCARD.md +6 -0
  20. package/dist/templates/cleargate-planning/.cleargate/delivery/archive/.gitkeep +0 -0
  21. package/dist/templates/cleargate-planning/.cleargate/delivery/pending-sync/.gitkeep +0 -0
  22. package/dist/templates/cleargate-planning/.cleargate/knowledge/cleargate-protocol.md +508 -0
  23. package/dist/templates/cleargate-planning/.cleargate/knowledge/readiness-gates.md +133 -0
  24. package/dist/templates/cleargate-planning/.cleargate/templates/Bug.md +82 -0
  25. package/dist/templates/cleargate-planning/.cleargate/templates/CR.md +77 -0
  26. package/dist/templates/cleargate-planning/.cleargate/templates/Sprint Plan Template.md +63 -0
  27. package/dist/templates/cleargate-planning/.cleargate/templates/epic.md +120 -0
  28. package/dist/templates/cleargate-planning/.cleargate/templates/initiative.md +53 -0
  29. package/dist/templates/cleargate-planning/.cleargate/templates/proposal.md +52 -0
  30. package/dist/templates/cleargate-planning/.cleargate/templates/story.md +125 -0
  31. package/dist/templates/cleargate-planning/CLAUDE.md +41 -0
  32. package/dist/templates/cleargate-planning/MANIFEST.json +160 -0
  33. package/dist/templates/synthesis/active-sprint.md +30 -0
  34. package/dist/templates/synthesis/open-gates.md +38 -0
  35. package/dist/templates/synthesis/product-state.md +32 -0
  36. package/dist/templates/synthesis/roadmap.md +63 -0
  37. package/package.json +9 -2
  38. package/templates/cleargate-planning/.claude/agents/architect.md +57 -0
  39. package/templates/cleargate-planning/.claude/agents/cleargate-wiki-ingest.md +145 -0
  40. package/templates/cleargate-planning/.claude/agents/cleargate-wiki-lint.md +256 -0
  41. package/templates/cleargate-planning/.claude/agents/cleargate-wiki-query.md +143 -0
  42. package/templates/cleargate-planning/.claude/agents/developer.md +58 -0
  43. package/templates/cleargate-planning/.claude/agents/qa.md +57 -0
  44. package/templates/cleargate-planning/.claude/agents/reporter.md +114 -0
  45. package/templates/cleargate-planning/.claude/hooks/session-start.sh +4 -0
  46. package/templates/cleargate-planning/.claude/hooks/stamp-and-gate.sh +18 -0
  47. package/templates/cleargate-planning/.claude/hooks/token-ledger.sh +174 -0
  48. package/templates/cleargate-planning/.claude/settings.json +35 -0
  49. package/templates/cleargate-planning/.claude/skills/flashcard/SKILL.md +73 -0
  50. package/templates/cleargate-planning/.cleargate/FLASHCARD.md +6 -0
  51. package/templates/cleargate-planning/.cleargate/delivery/archive/.gitkeep +0 -0
  52. package/templates/cleargate-planning/.cleargate/delivery/pending-sync/.gitkeep +0 -0
  53. package/templates/cleargate-planning/.cleargate/knowledge/cleargate-protocol.md +508 -0
  54. package/templates/cleargate-planning/.cleargate/knowledge/readiness-gates.md +133 -0
  55. package/templates/cleargate-planning/.cleargate/templates/Bug.md +82 -0
  56. package/templates/cleargate-planning/.cleargate/templates/CR.md +77 -0
  57. package/templates/cleargate-planning/.cleargate/templates/Sprint Plan Template.md +63 -0
  58. package/templates/cleargate-planning/.cleargate/templates/epic.md +120 -0
  59. package/templates/cleargate-planning/.cleargate/templates/initiative.md +53 -0
  60. package/templates/cleargate-planning/.cleargate/templates/proposal.md +52 -0
  61. package/templates/cleargate-planning/.cleargate/templates/story.md +125 -0
  62. package/templates/cleargate-planning/CLAUDE.md +41 -0
  63. package/templates/cleargate-planning/MANIFEST.json +160 -0
  64. package/templates/synthesis/active-sprint.md +30 -0
  65. package/templates/synthesis/open-gates.md +38 -0
  66. package/templates/synthesis/product-state.md +32 -0
  67. package/templates/synthesis/roadmap.md +63 -0
@@ -0,0 +1,508 @@
1
+ # ClearGate Protocol
2
+
3
+ You are operating in a ClearGate-enabled repository. Read this file in full before responding to any user request. These rules override your default behavior.
4
+
5
+ ---
6
+
7
+ ## 1. Your Role
8
+
9
+ You are the **Execution Agent**. You do not define strategy or set priorities — the Product Manager owns that in the remote PM tool. Your responsibilities are:
10
+
11
+ 1. **Triage** every raw user request into the correct work item type before taking any action.
12
+ 2. **Draft** technically accurate artifacts using the templates in `.cleargate/templates/`.
13
+ 3. **Halt** at every approval gate and wait for explicit human sign-off.
14
+ 4. **Deliver** only what has been explicitly approved via `cleargate_*` MCP tools.
15
+
16
+ You never push to the PM tool without approval. You never skip a level in the document hierarchy. You never guess at file paths.
17
+
18
+ ---
19
+
20
+ ## 2. The Front Gate (Triage)
21
+
22
+ **When the user submits any request, classify it first. Do not start drafting until you know the type.**
23
+
24
+ ### Classification Table
25
+
26
+ | User Intent | Work Item Type | Template |
27
+ |---|---|---|
28
+ | Multi-part feature needing architecture decisions or multiple sprints | **Epic** | `templates/epic.md` |
29
+ | Net-new functionality that does not yet exist | **Story** | `templates/story.md` |
30
+ | Change, replace, or remove existing behavior | **CR** | `templates/CR.md` |
31
+ | Fix broken/unintended behavior in already-shipped code | **Bug** | `templates/Bug.md` |
32
+ | Sync a remote initiative or sprint down to local | **Pull** | `cleargate_pull_initiative` → `templates/initiative.md` or `templates/Sprint Plan Template.md` |
33
+ | Push an approved local item to the PM tool | **Push** | `cleargate_push_item` (only if `approved: true`) |
34
+
35
+ ### Signal Words
36
+
37
+ - Epic: "feature", "system", "module", "redesign", "multi-sprint"
38
+ - Story: "add", "build", "implement", "new", "create"
39
+ - CR: "change", "replace", "update how X works", "remove", "refactor" (existing behavior)
40
+ - Bug: "broken", "error", "crash", "not working", "wrong output", "fix"
41
+ - Pull: "pull", "sync", "what's in Linear/Jira", "show me the sprint"
42
+ - Push: "push to Linear", "create in Jira", "sync this item"
43
+
44
+ ### Ambiguous Requests
45
+
46
+ If the type is not clear, ask **one targeted question** before proceeding. Do not guess.
47
+
48
+ Example: *"Is this adding functionality that doesn't exist yet (Story) or changing how an existing feature works (CR)?"*
49
+
50
+ ### Always Start with a Proposal
51
+
52
+ For Epic, Story, and CR types — before drafting the work item itself, you **must** first draft a Proposal using `templates/proposal.md`. The Proposal is Gate 1 (see §4). You may not skip it.
53
+
54
+ Exception: if an `approved: true` proposal already exists for this work, reference it directly and proceed to the work item.
55
+
56
+ ---
57
+
58
+ ## 3. Document Hierarchy
59
+
60
+ All work follows a strict four-level hierarchy. You cannot skip levels or create orphaned documents.
61
+
62
+ ```
63
+ LEVEL 0 — PROPOSAL
64
+ (approved: false → human sets approved: true)
65
+
66
+ LEVEL 1 — EPIC
67
+ (🔴 High Ambiguity → human answers §6 → 🟢 Low Ambiguity)
68
+
69
+ LEVEL 2 — STORY
70
+ (🔴 High Ambiguity → human answers §6 → 🟢 Low Ambiguity)
71
+
72
+ LEVEL 3 — DELIVERY
73
+ (cleargate_push_item → remote ID injected → moved to archive/)
74
+ ```
75
+
76
+ ### Hierarchy Rules
77
+
78
+ - **Proposal before everything.** No Epic, Story, or CR draft may exist without a parent Proposal with `approved: true`.
79
+ - **Epic before Story.** Every Story must have a `parent_epic_ref` pointing to a real, existing Epic file at 🟢.
80
+ - **No orphans.** A Story with no parent Epic is invalid. A Bug or CR must reference the affected Epic or Story.
81
+ - **Cascade ambiguity.** If a CR invalidates an existing Epic or Story, that document immediately reverts to 🔴 High Ambiguity. Do not proceed with execution on reverted items.
82
+
83
+ ---
84
+
85
+ ## 4. Phase Gates
86
+
87
+ There are three hard stops. You halt at each one and do not proceed until the human acts.
88
+
89
+ ### Gate 1 — Proposal Approval
90
+
91
+ 1. Draft the Proposal using `templates/proposal.md`.
92
+ 2. Save to `.cleargate/delivery/pending-sync/PROPOSAL-{Name}.md` with `approved: false`.
93
+ 3. Present the document to the user.
94
+ 4. **STOP. Do not draft Epics or Stories. Do not call any MCP tool. Wait.**
95
+ 5. Proceed only after the human has set `approved: true` in the frontmatter.
96
+
97
+ ### Gate 2 — Ambiguity Gate (per Epic and Story)
98
+
99
+ 1. Every drafted Epic or Story starts at 🔴 High Ambiguity.
100
+ 2. Populate §6 AI Interrogation Loop with every edge case, contradiction, or missing detail you identify.
101
+ 3. **STOP. Present the document. Wait for the human to answer every question in §6.**
102
+ 4. Once §6 is empty and zero "TBDs" remain in the document, move the status to 🟢.
103
+ 5. Only documents at 🟢 may proceed to the Delivery phase.
104
+
105
+ ### Gate 3 — Push Gate
106
+
107
+ - **Never call `cleargate_push_item` on a file where `approved: false`.**
108
+ - Never push a document that is 🔴 or 🟡.
109
+ - Only push when: the document is 🟢 AND the human has explicitly confirmed the push.
110
+
111
+ > Gate 2 (Ambiguity) is machine-checked via `cleargate gate check`; see §12.
112
+ > (See §13 for scaffold lifecycle commands)
113
+
114
+ ---
115
+
116
+ ## 5. Delivery Workflow ("Local First, Sync, Update")
117
+
118
+ Follow these steps in exact order:
119
+
120
+ ```
121
+ 1. DRAFT — Fill the appropriate template.
122
+ Save to: .cleargate/delivery/pending-sync/{TYPE}-{ID}-{Name}.md
123
+
124
+ 2. HALT — Present the draft to the human. Wait for approval (Gate 1 or Gate 2).
125
+
126
+ 3. SYNC — Human approves. Call cleargate_push_item with the exact file path.
127
+
128
+ 4. COMMIT — Inject the returned remote ID into the file's YAML frontmatter.
129
+ Example: remote_id: "LIN-102"
130
+
131
+ 5. ARCHIVE — Move the file to: .cleargate/delivery/archive/{ID}-{Name}.md
132
+ ```
133
+
134
+ **On MCP failure:** Leave the file in `pending-sync/`. Report the exact error to the human. Do not retry in a loop. Do not attempt a workaround.
135
+
136
+ **On PM tool unreachable:** Same as above. Local state is the source of truth. Never mutate local files to reflect a push that did not succeed.
137
+
138
+ ---
139
+
140
+ ## 6. MCP Tools Reference
141
+
142
+ Only use the `cleargate_*` MCP tools to communicate with PM tools. Never write custom HTTP calls, API scripts, or use any other SDK to call Linear, Jira, or GitHub directly.
143
+
144
+ | Tool | When to Call |
145
+ |---|---|
146
+ | `cleargate_pull_initiative` | User wants to pull a remote initiative or sprint into local context. Pass `remote_id`. Writes to `.cleargate/plans/`. |
147
+ | `cleargate_push_item` | An approved local file needs to be pushed. Pass `file_path`, `item_type`, and `parent_id` if it is a Story. Requires `approved: true`. |
148
+ | `cleargate_sync_status` | A work item changes state (e.g., moved to Done). Pass `remote_id` and `new_status`. |
149
+
150
+ ---
151
+
152
+ ## 7. Scope Discipline
153
+
154
+ These rules prevent hallucinated or out-of-scope changes.
155
+
156
+ - **Only modify files explicitly listed** in the "Technical Grounding > Affected Files" section (Epic/Story) or "Execution Sandbox" section (Bug/CR).
157
+ - **Do not refactor, optimize, or clean up** code that is not in scope. If you notice an issue outside scope, note it and ask the human whether to create a separate Story or CR.
158
+ - **Do not create new files** unless they appear under "New Files Needed" in the Implementation Guide.
159
+ - **Do not assume file paths.** All affected file paths must originate from an approved Proposal. If a path is missing or unverified, add it to §6 AI Interrogation Loop — do not guess.
160
+
161
+ ---
162
+
163
+ ## 8. Planning Phase (Pull Workflow)
164
+
165
+ When the user wants to ingest context from the PM tool before any execution:
166
+
167
+ 1. Call `cleargate_pull_initiative` with the remote ID provided by the user.
168
+ 2. The tool writes the result to `.cleargate/plans/` using the appropriate local format.
169
+ 3. Read the pulled file to understand scope, constraints, and sprint context.
170
+ 4. Use this as the input context when beginning a Proposal draft.
171
+
172
+ You do not push during the Planning Phase. Planning Phase ends when the user confirms they want to begin drafting a Proposal.
173
+
174
+ ---
175
+
176
+ ## 9. Quick Decision Reference
177
+
178
+ ```
179
+ User prompt received
180
+
181
+ Is this a PULL request? ──YES──→ cleargate_pull_initiative → read result → done
182
+ │ NO
183
+
184
+ Is this a PUSH request? ──YES──→ check approved: true → cleargate_push_item → archive
185
+ │ NO
186
+
187
+ Classify: Epic / Story / CR / Bug
188
+
189
+ Does an approved: true Proposal exist for this work?
190
+ ├── NO → Draft Proposal → HALT at Gate 1
191
+ └── YES → Draft work item (Epic/Story/CR/Bug) → HALT at Gate 2
192
+
193
+ Human resolves §6 + sets 🟢
194
+
195
+ Human confirms push → cleargate_push_item → archive
196
+ ```
197
+
198
+ ---
199
+
200
+ ## 10. Knowledge Wiki Protocol
201
+
202
+ The Knowledge Wiki is the compiled awareness layer at `.cleargate/wiki/`. Read it before reading raw delivery files — it surfaces relationships and status that individual raw files do not expose. The wiki is always derived: when a raw file under `.cleargate/delivery/**` contradicts a wiki page, the raw file wins.
203
+
204
+ ---
205
+
206
+ ### §10.1 Directory Layout
207
+
208
+ ```
209
+ .cleargate/wiki/
210
+ index.md ← master page registry (one row per page)
211
+ log.md ← append-only audit log of all ingest events
212
+ product-state.md ← synthesised product health snapshot
213
+ roadmap.md ← synthesised roadmap view
214
+ active-sprint.md ← synthesised current-sprint progress
215
+ open-gates.md ← synthesised blocked-item registry
216
+ epics/ ← one page per Epic (EPIC-NNN.md)
217
+ stories/ ← one page per Story (STORY-NNN-NN.md)
218
+ bugs/ ← one page per Bug
219
+ proposals/ ← one page per Proposal
220
+ crs/ ← one page per CR
221
+ sprints/ ← one page per Sprint
222
+ topics/ ← cross-cutting topic pages (written by query --persist only)
223
+ ```
224
+
225
+ ---
226
+
227
+ ### §10.2 Three Operations
228
+
229
+ **ingest**
230
+
231
+ Triggered automatically by a PostToolUse hook on Write or Edit operations under `.cleargate/delivery/**`. When the hook is unavailable, every agent that writes a raw delivery file must invoke the `cleargate-wiki-ingest` subagent directly (protocol-rule fallback — see §10.9). On each ingest: one per-item wiki page is created or updated, one YAML event is appended to `log.md`, and every synthesis page affected by the item is recompiled (`product-state.md`, `roadmap.md`, `active-sprint.md`, `open-gates.md`). Ingest is always safe to re-run.
232
+
233
+ **query**
234
+
235
+ Invoked automatically at triage (read-only). Searches the wiki index and existing pages to surface related work items before any new draft begins. Explicit queries use `cleargate wiki query <terms>`. Append `--persist` to write the result as a topic page at `wiki/topics/<slug>.md`. Topic pages are never written by ingest — only by `query --persist`.
236
+
237
+ **lint**
238
+
239
+ Enforcement run. Checks for drift between wiki pages and their raw source files. Exits non-zero on any violation; a non-zero exit halts Gate 1 (Proposal approval) and Gate 3 (Push). Run with `--suggest` to receive candidate cross-ref patches without blocking (exits 0).
240
+
241
+ ---
242
+
243
+ ### §10.3 Exclusions
244
+
245
+ Ingest skips the following directories — they are static configuration or orchestration-only and must not generate wiki pages:
246
+
247
+ - `.cleargate/knowledge/`
248
+ - `.cleargate/templates/`
249
+ - `.cleargate/sprint-runs/`
250
+ - `.cleargate/hook-log/`
251
+
252
+ ---
253
+
254
+ ### §10.4 Page Schema
255
+
256
+ Every wiki page has a YAML frontmatter block followed by a short prose body.
257
+
258
+ ```markdown
259
+ ---
260
+ type: story
261
+ id: "STORY-042-01"
262
+ parent: "[[EPIC-042]]"
263
+ children: []
264
+ status: "🟢"
265
+ remote_id: "LIN-1042"
266
+ raw_path: ".cleargate/delivery/archive/STORY-042-01_name.md"
267
+ last_ingest: "2026-04-19T10:00:00Z"
268
+ last_ingest_commit: "a1b2c3d4e5f6..."
269
+ repo: "planning"
270
+ ---
271
+
272
+ # STORY-042-01: Short title
273
+
274
+ Summary in one or two sentences.
275
+
276
+ ## Blast radius
277
+ Affects: [[EPIC-042]], [[service-auth]]
278
+
279
+ ## Open questions
280
+ None.
281
+ ```
282
+
283
+ Field notes:
284
+
285
+ - `last_ingest_commit` — the SHA returned by `git log -1 --format=%H -- <raw_path>` at ingest time. Used for idempotency (see §10.7).
286
+ - `repo` — derived from `raw_path` prefix: `cleargate-cli/` → `cli`; `mcp/` → `mcp`; `.cleargate/` or `cleargate-planning/` → `planning`. Never manually set.
287
+
288
+ ---
289
+
290
+ ### §10.5 Backlink Syntax
291
+
292
+ Use `[[WORK-ITEM-ID]]` (Obsidian-style double-bracket links) to express relationships between pages. Every parent/child pair declared in frontmatter must have a corresponding backlink in the body of each page. `cleargate wiki lint` verifies bidirectionality: a `parent:` entry without a matching `[[parent-id]]` reference in the parent's `children:` list is a lint violation.
293
+
294
+ ---
295
+
296
+ ### §10.6 `log.md` Event Shape
297
+
298
+ One YAML list entry is appended to `wiki/log.md` on every ingest. Fields:
299
+
300
+ ```yaml
301
+ - timestamp: "2026-04-19T10:00:00Z"
302
+ actor: "cleargate-draft-proposal"
303
+ action: "create"
304
+ target: "PROPOSAL-stripe-webhooks"
305
+ path: ".cleargate/delivery/pending-sync/PROPOSAL-stripe-webhooks.md"
306
+ ```
307
+
308
+ - `timestamp` — ISO 8601 UTC.
309
+ - `actor` — subagent name (e.g. `cleargate-wiki-ingest`) or `vibe-coder` for manual writes.
310
+ - `action` — one of `create`, `update`, `delete`, `approve`.
311
+ - `target` — work-item ID (e.g. `STORY-042-01`).
312
+ - `path` — absolute path to the raw source file.
313
+
314
+ ---
315
+
316
+ ### §10.7 Idempotency Rule
317
+
318
+ Re-ingesting a file is a no-op when **both** of the following are true:
319
+
320
+ (a) The file content is byte-identical to the content at last ingest.
321
+ (b) `git log -1 --format=%H -- <raw_path>` matches the `last_ingest_commit` stored in the page frontmatter.
322
+
323
+ Drift detection is commit-SHA comparison — not content hashing — eliminating any dependency on external hash storage or EPIC-001 infrastructure. If either condition is false, ingest proceeds and the page is overwritten.
324
+
325
+ ---
326
+
327
+ ### §10.8 Gate Enforcement
328
+
329
+ `cleargate wiki lint` exits non-zero and blocks execution at:
330
+
331
+ - **Gate 1 (Proposal approval):** lint must pass before the agent may proceed past the Proposal halt.
332
+ - **Gate 3 (Push):** lint must pass before `cleargate_push_item` is called.
333
+
334
+ Lint checks performed:
335
+
336
+ - Orphan pages — wiki pages whose `raw_path` no longer exists.
337
+ - Missing backlinks — parent/child pairs without bidirectional `[[ID]]` references.
338
+ - `raw_path` ↔ `repo` tag mismatch — `repo` field does not match the prefix of `raw_path`.
339
+ - Stale `last_ingest_commit` — stored SHA differs from current `git log -1` for the raw file.
340
+ - Invalidated topic citations — a `wiki/topics/*.md` page cites an item that has been archived or status-set to cancelled.
341
+
342
+ The gate-check hook (§12.5) runs before ingest; staleness (§12.4) is a lint error.
343
+
344
+ ---
345
+
346
+ ### §10.9 Fallback Chain
347
+
348
+ Ingest reliability follows a three-level fallback:
349
+
350
+ 1. **PostToolUse hook (primary)** — fires automatically on every Write or Edit under `.cleargate/delivery/**`. No agent action required.
351
+ 2. **Protocol rule (secondary)** — when the hook is unavailable (e.g. non-Claude-Code environment), every agent that writes a raw delivery file must explicitly invoke the `cleargate-wiki-ingest` subagent before returning.
352
+ 3. **Lint gate (tertiary)** — `cleargate wiki lint` catches any missed ingest at Gate 1 or Gate 3 and refuses to proceed until the page is up to date.
353
+
354
+ ---
355
+
356
+ ## 11. Document Metadata Lifecycle
357
+
358
+ Every work item file managed by ClearGate carries timestamp and version fields that track when it was created, last modified, and last pushed to the remote PM tool. This section defines those fields, how they are populated, and when they are frozen.
359
+
360
+ ---
361
+
362
+ ### §11.1 Field Semantics
363
+
364
+ | Field | Type | Description |
365
+ |---|---|---|
366
+ | `created_at` | ISO 8601 UTC string | Timestamp set once on first `cleargate stamp` invocation. Never updated after creation. |
367
+ | `updated_at` | ISO 8601 UTC string | Timestamp updated on every `cleargate stamp` invocation that changes the file. Equal to `created_at` at creation time. |
368
+ | `created_at_version` | string | Codebase version string at time of first stamp. See §11.3 for format. Never updated after creation. |
369
+ | `updated_at_version` | string | Codebase version string at time of most recent stamp. Equal to `created_at_version` at creation time. |
370
+ | `server_pushed_at_version` | string \| null | Codebase version string at the time this file was last successfully pushed via `cleargate_push_item`. `null` until the first push succeeds. Present on write-template files (epic/story/bug/CR/proposal) only. |
371
+
372
+ ---
373
+
374
+ ### §11.2 Stamp Invocation Rule
375
+
376
+ After any Write or Edit operation on a file under `.cleargate/delivery/`, the author must invoke:
377
+
378
+ ```
379
+ cleargate stamp <path>
380
+ ```
381
+
382
+ This updates `updated_at` and `updated_at_version` in place. The `created_at` and `created_at_version` fields are set on the first invocation and are never overwritten thereafter.
383
+
384
+ In Claude Code environments, a PostToolUse hook fires automatically on Write/Edit under `.cleargate/delivery/**` and calls `cleargate stamp` without any agent action (hook wiring is STORY-008-06 scope, M3). Until that hook is active, every agent that writes a delivery file must call `cleargate stamp` explicitly before returning.
385
+
386
+ ---
387
+
388
+ ### §11.3 Dirty-SHA Convention
389
+
390
+ The version string embedded in `created_at_version` and `updated_at_version` is produced by `getCodebaseVersion()` (STORY-001-03). Its format follows this precedence:
391
+
392
+ 1. If inside a git repo and `git status --porcelain` is non-empty (uncommitted changes present): `<short-sha>-dirty` (e.g. `a3f2e91-dirty`).
393
+ 2. If inside a git repo and the working tree is clean: `<short-sha>` (e.g. `a3f2e91`), where `<short-sha>` is the 7-character output of `git rev-parse --short HEAD`.
394
+ 3. If no git repo is present but a `package.json` is found in an ancestor directory: the `version` field value from that file (e.g. `1.4.2`).
395
+ 4. If neither is available: the literal string `"unknown"`, and a warning is emitted to stderr.
396
+
397
+ The `-dirty` suffix signals that the version string was captured from a working tree with uncommitted changes. Consumers comparing version strings must treat `a3f2e91-dirty` and `a3f2e91` as belonging to the same base commit but different workspace states.
398
+
399
+ ---
400
+
401
+ ### §11.4 Archive Immutability
402
+
403
+ Files that have been moved to `.cleargate/delivery/archive/` are frozen. `cleargate stamp` is a no-op on any path matching `.cleargate/delivery/archive/`. No fields are written, no file bytes change.
404
+
405
+ Rationale: archived files represent the accepted state at push time. Retroactively updating their timestamps would break the audit trail used by the wiki lint stale-detection check (§11.6).
406
+
407
+ ---
408
+
409
+ ### §11.5 Git-Absent Fallback
410
+
411
+ When `cleargate stamp` runs outside a git repository (e.g. a freshly unzipped scaffold before `git init`), the version resolution falls back in order:
412
+
413
+ 1. Walk up from the current working directory looking for a `package.json`. If found, use its `version` field as the version string.
414
+ 2. If no `package.json` ancestor exists, use the literal string `"unknown"` and emit a warning to stderr: `"cleargate stamp: cannot determine codebase version — no git repo or package.json found"`.
415
+
416
+ The `"unknown"` value is valid frontmatter; downstream consumers (stamp, lint, wiki-ingest) must accept it without error.
417
+
418
+ ---
419
+
420
+ ### §11.6 Stale Detection Threshold
421
+
422
+ A wiki page for a work item is considered **stale** when the following condition holds:
423
+
424
+ > The number of merge commits in `git log --merges <updated_at_version>..HEAD -- <raw_path>` is ≥ 1.
425
+
426
+ That is: if at least one merge commit has landed on the default branch since the file was last stamped, the wiki page is out of date and `cleargate wiki lint` reports a stale-detection violation.
427
+
428
+ Implementation notes:
429
+ - `updated_at_version` must be a resolvable git ref (short SHA or tag). If the value is `"unknown"` or `"strategy-phase-pre-init"`, lint skips the stale check for that file and emits a warning rather than an error.
430
+ - The `-dirty` suffix is stripped before resolving the ref: `a3f2e91-dirty` → `a3f2e91`.
431
+ - This check is consumed by `cleargate wiki lint` (STORY-008-07) and the wiki-ingest subagent's idempotency evaluation (§10.7).
432
+
433
+ ---
434
+
435
+ ## 12. Token Cost Stamping & Readiness Gates
436
+
437
+ ### §12.1 Overview
438
+ Two-capability bundle: (1) `draft_tokens` frontmatter stamp populated by a PostToolUse hook from the sprint token ledger; (2) closed-set predicate engine + `cleargate gate check` CLI writing `cached_gate_result` into frontmatter, blocking wiki-lint on enforcing types (Epic/Story/CR/Bug), advising on Proposals.
439
+
440
+ ### §12.2 Token stamp semantics
441
+ - Idempotent within a session (re-stamp = no-op when last_stamp + totals unchanged).
442
+ - Accumulative across sessions: `sessions[]` gains one entry per session; top-level totals are sums; `model` is comma-joined across distinct values.
443
+ - Missing ledger row → `draft_tokens:{…null…, stamp_error:"<reason>"}` — never fabricate.
444
+ - Archive-path stamping is a no-op (freeze-on-archive).
445
+ - Sprint files record only planning-phase tokens; story tokens attribute to their own files (no double-count).
446
+
447
+ ### §12.3 Readiness gates
448
+ - Central definitions: `.cleargate/knowledge/readiness-gates.md` keyed by `{work_item_type, transition}`.
449
+ - Predicates are a CLOSED set (6 shapes): `frontmatter(...)`, `body contains`, `section(N) has count`, `file-exists`, `link-target-exists`, `status-of`. No shell-out, no network.
450
+ - Severity: Proposal = advisory (exit 0, records `pass:false` without blocking). Epic/Story/CR/Bug = enforcing (exit non-zero at CLI; wiki lint refuses).
451
+
452
+ ### §12.4 Enforcement points
453
+ - v1: `wiki lint` only. MCP-side `push_item` enforcement is deferred post-PROP-007.
454
+ - Staleness: `cached_gate_result.last_gate_check < updated_at` → lint error for ALL types (catches silent hook failures).
455
+
456
+ ### §12.5 Hook lifecycle
457
+ - PostToolUse `stamp-and-gate.sh` chains `stamp-tokens → gate check → wiki ingest` on every Write/Edit under `.cleargate/delivery/**`. Exit always 0.
458
+ - SessionStart `session-start.sh` pipes `cleargate doctor --session-start` (≤100 LLM-tokens, ≤10 items + overflow pointer) into context.
459
+ - Every invocation logs to `.cleargate/hook-log/gate-check.log`; `cleargate doctor` surfaces last-24h failures.
460
+
461
+ ### §12.6 Cross-references
462
+ - §4 Phase Gates: "Gate 2 (Ambiguity) is machine-checked via `cleargate gate check`; see §12."
463
+ - §10.8 Wiki-lint enforcement: extended by the gate-check hook; staleness check added per §12.4.
464
+
465
+ ---
466
+
467
+ ## 13. Scaffold Manifest & Uninstall
468
+
469
+ ### §13.1 Overview
470
+ Three-surface model: package manifest (shipped in `@cleargate/cli`), install snapshot (`.cleargate/.install-manifest.json` written at init), current state (live FS). Drift is classified pairwise into 4 states (clean / user-modified / upstream-changed / both-changed) + `untracked` for user-artifact tier. SHA256 over normalized content (LF / UTF-8 no-BOM / trailing-newline) is the file identifier.
471
+
472
+ ### §13.2 Install
473
+ `cleargate init` copies the bundled payload, then writes `.cleargate/.install-manifest.json`:
474
+
475
+ ```json
476
+ {
477
+ "cleargate_version": "0.2.0",
478
+ "installed_at": "2026-04-19T10:00:00Z",
479
+ "files": [
480
+ {"path": ".cleargate/knowledge/cleargate-protocol.md", "sha256": "…", "tier": "protocol", "overwrite_policy": "merge-3way", "preserve_on_uninstall": "default-remove"}
481
+ ]
482
+ }
483
+ ```
484
+
485
+ If a `.cleargate/.uninstalled` marker exists at init time, init prompts "Detected previous ClearGate install … Restore preserved items? [Y/n]". Y = blind-copy preserved paths back into the new install (v1); mismatches log a warning and do not fail.
486
+
487
+ ### §13.3 Drift detection
488
+ `cleargate doctor --check-scaffold` compares the three surfaces and writes `.cleargate/.drift-state.json` (daily-throttled refresh). SessionStart-triggered refresh runs at most once per day. Agent never auto-overwrites on upstream-changed drift — it emits a one-line advisory at triage; `cleargate upgrade` is always human-initiated. `user-artifact` tier (sha256: null) is silently skipped in drift output; surfaces only in uninstall preview.
489
+
490
+ ### §13.4 Upgrade
491
+ `cleargate upgrade [--dry-run] [--yes] [--only <tier>]` drives a three-way merge for `merge-3way` policy files. Per-file prompt: `[k]eep mine / [t]ake theirs / [e]dit in $EDITOR`. Execution is incremental: successes are committed to disk + `.install-manifest.json` updated before the next file is processed; a mid-run error leaves earlier successes intact.
492
+
493
+ ### §13.5 Uninstall
494
+ `cleargate uninstall [--dry-run] [--preserve …] [--remove …] [--yes] [--path <dir>] [--force]` is preservation-first. Defaults: `.cleargate/delivery/archive/**`, `FLASHCARD.md`, `sprint-runs/*/REPORT.md`, `pending-sync/**` → keep. `.cleargate/knowledge/`, `.cleargate/templates/`, `.cleargate/wiki/`, `.cleargate/hook-log/` → remove. Safety rails: typed confirmation (project name), single-target (no recursion into nested `.cleargate/`), refuse on uncommitted manifest-tracked changes without `--force`, CLAUDE.md marker-presence check. Always-removed (no prompt): `.claude/agents/*.md`, ClearGate hooks, `flashcard/` skill, CLAUDE.md CLEARGATE block, `@cleargate/cli` in `package.json`, `.install-manifest.json`, `.drift-state.json`. Writes `.cleargate/.uninstalled` marker:
495
+
496
+ ```json
497
+ {
498
+ "uninstalled_at": "2026-04-19T11:00:00Z",
499
+ "prior_version": "0.2.0",
500
+ "preserved": [".cleargate/FLASHCARD.md", ".cleargate/delivery/archive/**"],
501
+ "removed": [".cleargate/knowledge/cleargate-protocol.md"]
502
+ }
503
+ ```
504
+
505
+ Future `cleargate init` in the same dir detects this marker and offers restore.
506
+
507
+ ### §13.6 Publishing notes
508
+ `MANIFEST.json` is built at `npm run build` (prebuild step in `cleargate-cli/package.json`) and shipped in the npm tarball (`files[]`). Never computed at install time. `generate-changelog-diff.ts` diffs `MANIFEST.json` between the previous published version and the current one at release time; CHANGELOG.md auto-opens with a "Scaffold files changed" block per release. Content-identical entries (path-moved-only, metadata-changed-only) are collapsed to avoid noise.
@@ -0,0 +1,133 @@
1
+ # Readiness Gates
2
+
3
+ This file is the single source of truth for ClearGate's machine-checkable readiness gates. Each gate entry declares the `{work_item_type, transition}` pair it governs, along with a list of criteria expressed in the closed-set predicate vocabulary defined below. The predicate evaluator in `cleargate-cli/src/lib/readiness-predicates.ts` (STORY-008-02) reads these YAML blocks and evaluates them against a target document's frontmatter and body. Gate check results are cached in the document's own frontmatter under `cached_gate_result:` by `cleargate gate check <file>`.
4
+
5
+ ---
6
+
7
+ ## Predicate Vocabulary
8
+
9
+ There are exactly **6 predicate shapes**. No other shapes are recognized; a check string that does not match one of these forms throws a parse error at evaluation time.
10
+
11
+ **1. `frontmatter(<ref>).<field> <op> <value>`**
12
+ Reads a frontmatter field from a document. `<ref>` is either `.` (the document being evaluated) or a frontmatter key whose value is a relative path to another document (e.g. `context_source`). `<op>` is one of `==`, `!=`, `>=`, `<=`. `<value>` is a literal string, number, or boolean. Example: `frontmatter(context_source).approved == true` reads the file named by the evaluated document's `context_source` key and asserts its `approved` field equals `true`.
13
+
14
+ **2. `body contains "<string>"` / `body does not contain "<string>"`**
15
+ Performs a case-sensitive substring search on the document body (everything after the frontmatter block). The negated form `body does not contain` passes when the string is absent. Example: `body does not contain 'TBD'` fails if the literal string `TBD` appears anywhere in the body.
16
+
17
+ **3. `section(<N>) has <count> <item-type>`**
18
+ Splits the document body on `## ` heading boundaries (1-indexed) and counts items of a given type within section N. `<count>` is an expression like `≥1`, `≥3`, or `0` (exact zero). `<item-type>` is one of `checked-checkbox` (lines matching `- [x]`), `unchecked-checkbox` (lines matching `- [ ]`), or `listed-item` (lines matching `- ` regardless of checkbox state). Example: `section(2) has ≥1 checked-checkbox` asserts that the second `##` section contains at least one checked markdown checkbox.
19
+
20
+ **4. `file-exists(<path>)`**
21
+ Asserts that a file exists on disk at the given path, resolved relative to the project root. Example: `file-exists(.cleargate/knowledge/cleargate-protocol.md)` passes when that file is present in the working tree.
22
+
23
+ **5. `link-target-exists(<[[WORK-ITEM-ID]]>)`**
24
+ Reads `.cleargate/wiki/index.md` and asserts that the wiki index contains a reference to the given ID. Passes when the wiki has an entry for the linked item, meaning it has been ingested at least once. Example: `link-target-exists([[EPIC-008]])` passes when EPIC-008 appears in the compiled wiki index.
25
+
26
+ **6. `status-of(<[[ID]]>) == <value>`**
27
+ Resolves the given ID via the wiki index, reads that page's compiled frontmatter `status:` field, and compares it to `<value>`. Status values in the live corpus are textual strings (`Draft`, `Ready`, `Active`, `Done`) — not emoji. Example: `status-of([[EPIC-008]]) == Active` passes when EPIC-008's wiki page has `status: Active`. Note: this predicate returns `unknown` (evaluates to fail) when the wiki index is stale and the item is not yet compiled. Run `cleargate wiki build` before relying on `status-of` predicates.
28
+
29
+ ---
30
+
31
+ ## Severity Model
32
+
33
+ Gates are classified as either **advisory** or **enforcing**.
34
+
35
+ **Advisory** gates (Proposal only) emit warnings and exit 0 regardless of pass/fail. They are informational checkpoints — they record `cached_gate_result.pass: false` in the document's frontmatter so an agent can read the state, but they never block a downstream action. Crucially, a Proposal's `approved: true` field is a pure human judgment: a Vibe Coder manually sets it after reviewing the document. The gate cannot and must not intercept that. Failing an advisory gate means "the document could be stronger" — it does not mean "the human may not approve."
36
+
37
+ **Enforcing** gates (Epic, Story, CR, Bug) exit non-zero on any failing criterion. `cleargate wiki lint` refuses to mark an Epic/Story/CR/Bug as 🟢-candidate when `cached_gate_result.pass == false` or when `last_gate_check < updated_at` (stale result). This ensures every enforcing gate check is fresh at the time of promotion.
38
+
39
+ The asymmetry exists because Proposal documents are human-authored strategy artifacts where partial drafts are normal and iterative. Epics, Stories, CRs, and Bugs represent engineering commitments where incomplete specification directly causes execution failures.
40
+
41
+ ---
42
+
43
+ ## Gate Definitions
44
+
45
+ ```yaml
46
+ - work_item_type: proposal
47
+ transition: ready-for-decomposition
48
+ severity: advisory
49
+ criteria:
50
+ - id: architecture-populated
51
+ check: "section(2) has ≥1 listed-item"
52
+ - id: touched-files-populated
53
+ check: "section(3) has ≥1 listed-item"
54
+ - id: no-tbds
55
+ check: "body does not contain 'TBD'"
56
+ ```
57
+
58
+ ```yaml
59
+ - work_item_type: epic
60
+ transition: ready-for-decomposition
61
+ severity: enforcing
62
+ criteria:
63
+ - id: proposal-approved
64
+ check: "frontmatter(context_source).approved == true"
65
+ - id: no-tbds
66
+ check: "body does not contain 'TBD'"
67
+ - id: scope-in-populated
68
+ check: "section(2) has ≥1 listed-item"
69
+ - id: affected-files-declared
70
+ check: "section(4) has ≥1 listed-item"
71
+ - id: interrogation-resolved
72
+ check: "body does not contain 'Unresolved'"
73
+ ```
74
+
75
+ ```yaml
76
+ - work_item_type: epic
77
+ transition: ready-for-coding
78
+ severity: enforcing
79
+ criteria:
80
+ - id: stories-referenced
81
+ check: "body contains 'STORY-'"
82
+ - id: gherkin-happy-path
83
+ check: "body contains 'Scenario:'"
84
+ - id: gherkin-error-path
85
+ check: "body contains 'Error'"
86
+ - id: no-tbds
87
+ check: "body does not contain 'TBD'"
88
+ - id: interrogation-resolved
89
+ check: "body does not contain 'Unresolved'"
90
+ ```
91
+
92
+ ```yaml
93
+ - work_item_type: story
94
+ transition: ready-for-execution
95
+ severity: enforcing
96
+ criteria:
97
+ - id: parent-epic-ref-set
98
+ check: "frontmatter(.).parent_epic_ref != null"
99
+ - id: no-tbds
100
+ check: "body does not contain 'TBD'"
101
+ - id: implementation-files-declared
102
+ check: "section(3) has ≥1 listed-item"
103
+ - id: dod-declared
104
+ check: "section(4) has ≥1 listed-item"
105
+ - id: gherkin-present
106
+ check: "body contains 'Scenario:'"
107
+ ```
108
+
109
+ ```yaml
110
+ - work_item_type: cr
111
+ transition: ready-to-apply
112
+ severity: enforcing
113
+ criteria:
114
+ - id: blast-radius-populated
115
+ check: "section(1) has ≥1 listed-item"
116
+ - id: no-tbds
117
+ check: "body does not contain 'TBD'"
118
+ - id: sandbox-paths-declared
119
+ check: "section(2) has ≥1 listed-item"
120
+ ```
121
+
122
+ ```yaml
123
+ - work_item_type: bug
124
+ transition: ready-for-fix
125
+ severity: enforcing
126
+ criteria:
127
+ - id: repro-steps-deterministic
128
+ check: "section(2) has ≥3 listed-item"
129
+ - id: severity-set
130
+ check: "frontmatter(.).severity != null"
131
+ - id: no-tbds
132
+ check: "body does not contain 'TBD'"
133
+ ```