cleargate 0.10.0 → 0.11.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 (72) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +11 -1
  3. package/dist/MANIFEST.json +40 -26
  4. package/dist/chunk-HZPJ5QX4.js +459 -0
  5. package/dist/chunk-HZPJ5QX4.js.map +1 -0
  6. package/dist/cli.cjs +419 -202
  7. package/dist/cli.cjs.map +1 -1
  8. package/dist/cli.js +387 -513
  9. package/dist/cli.js.map +1 -1
  10. package/dist/lib/lifecycle-reconcile.cjs +497 -0
  11. package/dist/lib/lifecycle-reconcile.cjs.map +1 -0
  12. package/dist/lib/lifecycle-reconcile.d.cts +136 -0
  13. package/dist/lib/lifecycle-reconcile.d.ts +136 -0
  14. package/dist/lib/lifecycle-reconcile.js +20 -0
  15. package/dist/lib/lifecycle-reconcile.js.map +1 -0
  16. package/dist/templates/cleargate-planning/.claude/agents/architect.md +55 -2
  17. package/dist/templates/cleargate-planning/.claude/agents/developer.md +22 -0
  18. package/dist/templates/cleargate-planning/.claude/agents/devops.md +249 -0
  19. package/dist/templates/cleargate-planning/.claude/agents/qa.md +41 -0
  20. package/dist/templates/cleargate-planning/.claude/agents/reporter.md +44 -8
  21. package/dist/templates/cleargate-planning/.claude/hooks/pre-commit-surface-gate.sh +21 -0
  22. package/dist/templates/cleargate-planning/.claude/hooks/stamp-and-gate.sh +12 -1
  23. package/dist/templates/cleargate-planning/.claude/hooks/token-ledger.sh +21 -1
  24. package/dist/templates/cleargate-planning/.claude/skills/sprint-execution/SKILL.md +200 -29
  25. package/dist/templates/cleargate-planning/.cleargate/knowledge/mid-sprint-triage-rubric.md +160 -0
  26. package/dist/templates/cleargate-planning/.cleargate/knowledge/readiness-gates.md +41 -9
  27. package/dist/templates/cleargate-planning/.cleargate/scripts/close_sprint.mjs +98 -16
  28. package/dist/templates/cleargate-planning/.cleargate/scripts/gate-checks.json +3 -3
  29. package/dist/templates/cleargate-planning/.cleargate/scripts/init_sprint.mjs +86 -10
  30. package/dist/templates/cleargate-planning/.cleargate/scripts/run_script.sh +173 -87
  31. package/dist/templates/cleargate-planning/.cleargate/scripts/suggest_improvements.mjs +150 -22
  32. package/dist/templates/cleargate-planning/.cleargate/scripts/test/test_flashcard_gate.sh +20 -20
  33. package/dist/templates/cleargate-planning/.cleargate/scripts/validate_state.mjs +32 -8
  34. package/dist/templates/cleargate-planning/.cleargate/scripts/write_dispatch.sh +12 -1
  35. package/dist/templates/cleargate-planning/.cleargate/templates/Bug.md +3 -0
  36. package/dist/templates/cleargate-planning/.cleargate/templates/CR.md +3 -0
  37. package/dist/templates/cleargate-planning/.cleargate/templates/epic.md +3 -0
  38. package/dist/templates/cleargate-planning/.cleargate/templates/hotfix.md +3 -0
  39. package/dist/templates/cleargate-planning/.cleargate/templates/initiative.md +1 -1
  40. package/dist/templates/cleargate-planning/.cleargate/templates/sprint_context.md +8 -0
  41. package/dist/templates/cleargate-planning/.cleargate/templates/story.md +3 -0
  42. package/dist/templates/cleargate-planning/CLAUDE.md +3 -1
  43. package/dist/templates/cleargate-planning/MANIFEST.json +40 -26
  44. package/package.json +8 -5
  45. package/templates/cleargate-planning/.claude/agents/architect.md +55 -2
  46. package/templates/cleargate-planning/.claude/agents/developer.md +22 -0
  47. package/templates/cleargate-planning/.claude/agents/devops.md +249 -0
  48. package/templates/cleargate-planning/.claude/agents/qa.md +41 -0
  49. package/templates/cleargate-planning/.claude/agents/reporter.md +44 -8
  50. package/templates/cleargate-planning/.claude/hooks/pre-commit-surface-gate.sh +21 -0
  51. package/templates/cleargate-planning/.claude/hooks/stamp-and-gate.sh +12 -1
  52. package/templates/cleargate-planning/.claude/hooks/token-ledger.sh +21 -1
  53. package/templates/cleargate-planning/.claude/skills/sprint-execution/SKILL.md +200 -29
  54. package/templates/cleargate-planning/.cleargate/knowledge/mid-sprint-triage-rubric.md +160 -0
  55. package/templates/cleargate-planning/.cleargate/knowledge/readiness-gates.md +41 -9
  56. package/templates/cleargate-planning/.cleargate/scripts/close_sprint.mjs +98 -16
  57. package/templates/cleargate-planning/.cleargate/scripts/gate-checks.json +3 -3
  58. package/templates/cleargate-planning/.cleargate/scripts/init_sprint.mjs +86 -10
  59. package/templates/cleargate-planning/.cleargate/scripts/run_script.sh +173 -87
  60. package/templates/cleargate-planning/.cleargate/scripts/suggest_improvements.mjs +150 -22
  61. package/templates/cleargate-planning/.cleargate/scripts/test/test_flashcard_gate.sh +20 -20
  62. package/templates/cleargate-planning/.cleargate/scripts/validate_state.mjs +32 -8
  63. package/templates/cleargate-planning/.cleargate/scripts/write_dispatch.sh +12 -1
  64. package/templates/cleargate-planning/.cleargate/templates/Bug.md +3 -0
  65. package/templates/cleargate-planning/.cleargate/templates/CR.md +3 -0
  66. package/templates/cleargate-planning/.cleargate/templates/epic.md +3 -0
  67. package/templates/cleargate-planning/.cleargate/templates/hotfix.md +3 -0
  68. package/templates/cleargate-planning/.cleargate/templates/initiative.md +1 -1
  69. package/templates/cleargate-planning/.cleargate/templates/sprint_context.md +8 -0
  70. package/templates/cleargate-planning/.cleargate/templates/story.md +3 -0
  71. package/templates/cleargate-planning/CLAUDE.md +3 -1
  72. package/templates/cleargate-planning/MANIFEST.json +40 -26
@@ -0,0 +1,136 @@
1
+ /**
2
+ * lifecycle-reconcile.ts — CR-017 Lifecycle Status Reconciliation + Decomposition Gate
3
+ *
4
+ * Public API:
5
+ * reconcileLifecycle(opts) → { drift: DriftItem[], clean: number }
6
+ * reconcileDecomposition(opts) → { missing: MissingDecomp[], clean: number }
7
+ * parseCommitMessage(msg) → Array<{ verb, id, type }>
8
+ * VERB_STATUS_MAP — verb-to-expected-status table
9
+ *
10
+ * TERMINAL_STATES referenced from .cleargate/scripts/constants.mjs:45.
11
+ * Do NOT redefine; duplicate literal with source citation.
12
+ */
13
+ /**
14
+ * Terminal statuses for artifact lifecycle.
15
+ * Source: .cleargate/scripts/constants.mjs:45 TERMINAL_STATES.
16
+ * NOTE: These are the *artifact* terminal statuses (Done, Completed, Verified, etc.),
17
+ * not state.json story states (Done, Escalated, Parking Lot).
18
+ */
19
+ declare const ARTIFACT_TERMINAL_STATUSES: Set<string>;
20
+ /**
21
+ * Verb-to-expected-status map (v1).
22
+ * Key: verb pattern (lower-case), Value: { types, expected }.
23
+ * types: which artifact types this verb applies to.
24
+ * expected: accepted terminal statuses for this verb.
25
+ */
26
+ declare const VERB_STATUS_MAP: Readonly<Record<string, {
27
+ types: string[];
28
+ expected: string[];
29
+ }>>;
30
+ interface DriftItem {
31
+ id: string;
32
+ type: 'STORY' | 'CR' | 'BUG' | 'EPIC' | 'PROPOSAL' | 'HOTFIX';
33
+ expected_status: string;
34
+ actual_status: string | null;
35
+ file_path: string | null;
36
+ in_archive: boolean;
37
+ commit_shas: string[];
38
+ carry_over: boolean;
39
+ }
40
+ interface ReconcileLifecycleResult {
41
+ drift: DriftItem[];
42
+ clean: number;
43
+ }
44
+ interface ReconcileLifecycleOpts {
45
+ since: Date;
46
+ until?: Date;
47
+ deliveryRoot: string;
48
+ repoRoot: string;
49
+ /** Test seam: replace spawnSync git calls */
50
+ gitRunner?: (cmd: string, args: string[]) => string;
51
+ }
52
+ interface MissingDecomp {
53
+ id: string;
54
+ type: 'epic' | 'proposal';
55
+ reason: 'no-child-stories' | 'no-decomposed-epic' | 'file-missing';
56
+ expected_files: string[];
57
+ }
58
+ interface ReconcileDecompositionResult {
59
+ missing: MissingDecomp[];
60
+ clean: number;
61
+ }
62
+ interface ReconcileDecompositionOpts {
63
+ sprintPlanPath: string;
64
+ deliveryRoot: string;
65
+ }
66
+ /**
67
+ * Parse a commit message (subject + optional first body line) for work-item IDs.
68
+ * Returns one entry per ID found with the verb inferred from conventional prefix.
69
+ *
70
+ * commit format: `<verb>(<scope>): <description>\n\n<body>`
71
+ * multi-ID: `fix(cli)!: BUG-001 fix + CR-001 align`
72
+ * merge: `merge: STORY-001-01 → main`
73
+ */
74
+ declare function parseCommitMessage(msg: string): Array<{
75
+ verb: string;
76
+ id: string;
77
+ type: string;
78
+ }>;
79
+ /**
80
+ * Scan git log in [since, until] range and reconcile artifact statuses.
81
+ *
82
+ * For each commit touching feat/fix verbs with IDs:
83
+ * - Find the artifact file in pending-sync or archive
84
+ * - Check if status is at expected terminal status
85
+ * - Report drift items for non-terminal artifacts
86
+ * - Skip artifacts with carry_over: true
87
+ */
88
+ declare function reconcileLifecycle(opts: ReconcileLifecycleOpts): ReconcileLifecycleResult;
89
+ /**
90
+ * Orphan drift item: a file in pending-sync/ with a non-terminal status
91
+ * that has been marked Done (or another terminal state) in a closed sprint's
92
+ * state.json — indicating it was completed but never archived.
93
+ */
94
+ interface OrphanDriftItem {
95
+ id: string;
96
+ type: 'CR' | 'STORY' | 'BUG' | 'EPIC' | 'HOTFIX';
97
+ pending_sync_status: string;
98
+ state_json_state: string;
99
+ state_json_sprint: string;
100
+ file_path: string;
101
+ }
102
+ interface ReconcileOrphansOpts {
103
+ /** Path to .cleargate/delivery */
104
+ deliveryRoot: string;
105
+ /** Path to .cleargate/sprint-runs */
106
+ sprintRunsRoot: string;
107
+ }
108
+ interface ReconcileOrphansResult {
109
+ drift: OrphanDriftItem[];
110
+ clean: number;
111
+ }
112
+ /**
113
+ * Detect cross-sprint orphan drift: items in pending-sync/ with status: Ready
114
+ * (or any non-terminal status) that are recorded as Done in a closed sprint's
115
+ * state.json. These were completed but never archived at sprint close.
116
+ *
117
+ * Active-sprint exclusion: reads .active sentinel to identify the current
118
+ * sprint and skips that sprint's state.json (in-flight items are not orphans).
119
+ *
120
+ * Scope: only scans pending-sync/*.md files matching the work-item-ID pattern.
121
+ * Does NOT scan .script-incidents/ or any subdirectory.
122
+ */
123
+ declare function reconcileCrossSprintOrphans(opts: ReconcileOrphansOpts): ReconcileOrphansResult;
124
+ /**
125
+ * Read the sprint plan's epics: and proposals: frontmatter arrays and verify
126
+ * that each referenced epic has ≥1 child story file, and each proposal has
127
+ * a decomposed epic.
128
+ */
129
+ declare function reconcileDecomposition(opts: ReconcileDecompositionOpts): ReconcileDecompositionResult;
130
+ /**
131
+ * Check if a (verb, type) combination is a mismatch (soft warning only in v1).
132
+ * Returns a warning message or null if no mismatch.
133
+ */
134
+ declare function checkVerbMismatch(verb: string, type: string): string | null;
135
+
136
+ export { ARTIFACT_TERMINAL_STATUSES, type DriftItem, type MissingDecomp, type OrphanDriftItem, type ReconcileDecompositionOpts, type ReconcileDecompositionResult, type ReconcileLifecycleOpts, type ReconcileLifecycleResult, type ReconcileOrphansOpts, type ReconcileOrphansResult, VERB_STATUS_MAP, checkVerbMismatch, parseCommitMessage, reconcileCrossSprintOrphans, reconcileDecomposition, reconcileLifecycle };
@@ -0,0 +1,136 @@
1
+ /**
2
+ * lifecycle-reconcile.ts — CR-017 Lifecycle Status Reconciliation + Decomposition Gate
3
+ *
4
+ * Public API:
5
+ * reconcileLifecycle(opts) → { drift: DriftItem[], clean: number }
6
+ * reconcileDecomposition(opts) → { missing: MissingDecomp[], clean: number }
7
+ * parseCommitMessage(msg) → Array<{ verb, id, type }>
8
+ * VERB_STATUS_MAP — verb-to-expected-status table
9
+ *
10
+ * TERMINAL_STATES referenced from .cleargate/scripts/constants.mjs:45.
11
+ * Do NOT redefine; duplicate literal with source citation.
12
+ */
13
+ /**
14
+ * Terminal statuses for artifact lifecycle.
15
+ * Source: .cleargate/scripts/constants.mjs:45 TERMINAL_STATES.
16
+ * NOTE: These are the *artifact* terminal statuses (Done, Completed, Verified, etc.),
17
+ * not state.json story states (Done, Escalated, Parking Lot).
18
+ */
19
+ declare const ARTIFACT_TERMINAL_STATUSES: Set<string>;
20
+ /**
21
+ * Verb-to-expected-status map (v1).
22
+ * Key: verb pattern (lower-case), Value: { types, expected }.
23
+ * types: which artifact types this verb applies to.
24
+ * expected: accepted terminal statuses for this verb.
25
+ */
26
+ declare const VERB_STATUS_MAP: Readonly<Record<string, {
27
+ types: string[];
28
+ expected: string[];
29
+ }>>;
30
+ interface DriftItem {
31
+ id: string;
32
+ type: 'STORY' | 'CR' | 'BUG' | 'EPIC' | 'PROPOSAL' | 'HOTFIX';
33
+ expected_status: string;
34
+ actual_status: string | null;
35
+ file_path: string | null;
36
+ in_archive: boolean;
37
+ commit_shas: string[];
38
+ carry_over: boolean;
39
+ }
40
+ interface ReconcileLifecycleResult {
41
+ drift: DriftItem[];
42
+ clean: number;
43
+ }
44
+ interface ReconcileLifecycleOpts {
45
+ since: Date;
46
+ until?: Date;
47
+ deliveryRoot: string;
48
+ repoRoot: string;
49
+ /** Test seam: replace spawnSync git calls */
50
+ gitRunner?: (cmd: string, args: string[]) => string;
51
+ }
52
+ interface MissingDecomp {
53
+ id: string;
54
+ type: 'epic' | 'proposal';
55
+ reason: 'no-child-stories' | 'no-decomposed-epic' | 'file-missing';
56
+ expected_files: string[];
57
+ }
58
+ interface ReconcileDecompositionResult {
59
+ missing: MissingDecomp[];
60
+ clean: number;
61
+ }
62
+ interface ReconcileDecompositionOpts {
63
+ sprintPlanPath: string;
64
+ deliveryRoot: string;
65
+ }
66
+ /**
67
+ * Parse a commit message (subject + optional first body line) for work-item IDs.
68
+ * Returns one entry per ID found with the verb inferred from conventional prefix.
69
+ *
70
+ * commit format: `<verb>(<scope>): <description>\n\n<body>`
71
+ * multi-ID: `fix(cli)!: BUG-001 fix + CR-001 align`
72
+ * merge: `merge: STORY-001-01 → main`
73
+ */
74
+ declare function parseCommitMessage(msg: string): Array<{
75
+ verb: string;
76
+ id: string;
77
+ type: string;
78
+ }>;
79
+ /**
80
+ * Scan git log in [since, until] range and reconcile artifact statuses.
81
+ *
82
+ * For each commit touching feat/fix verbs with IDs:
83
+ * - Find the artifact file in pending-sync or archive
84
+ * - Check if status is at expected terminal status
85
+ * - Report drift items for non-terminal artifacts
86
+ * - Skip artifacts with carry_over: true
87
+ */
88
+ declare function reconcileLifecycle(opts: ReconcileLifecycleOpts): ReconcileLifecycleResult;
89
+ /**
90
+ * Orphan drift item: a file in pending-sync/ with a non-terminal status
91
+ * that has been marked Done (or another terminal state) in a closed sprint's
92
+ * state.json — indicating it was completed but never archived.
93
+ */
94
+ interface OrphanDriftItem {
95
+ id: string;
96
+ type: 'CR' | 'STORY' | 'BUG' | 'EPIC' | 'HOTFIX';
97
+ pending_sync_status: string;
98
+ state_json_state: string;
99
+ state_json_sprint: string;
100
+ file_path: string;
101
+ }
102
+ interface ReconcileOrphansOpts {
103
+ /** Path to .cleargate/delivery */
104
+ deliveryRoot: string;
105
+ /** Path to .cleargate/sprint-runs */
106
+ sprintRunsRoot: string;
107
+ }
108
+ interface ReconcileOrphansResult {
109
+ drift: OrphanDriftItem[];
110
+ clean: number;
111
+ }
112
+ /**
113
+ * Detect cross-sprint orphan drift: items in pending-sync/ with status: Ready
114
+ * (or any non-terminal status) that are recorded as Done in a closed sprint's
115
+ * state.json. These were completed but never archived at sprint close.
116
+ *
117
+ * Active-sprint exclusion: reads .active sentinel to identify the current
118
+ * sprint and skips that sprint's state.json (in-flight items are not orphans).
119
+ *
120
+ * Scope: only scans pending-sync/*.md files matching the work-item-ID pattern.
121
+ * Does NOT scan .script-incidents/ or any subdirectory.
122
+ */
123
+ declare function reconcileCrossSprintOrphans(opts: ReconcileOrphansOpts): ReconcileOrphansResult;
124
+ /**
125
+ * Read the sprint plan's epics: and proposals: frontmatter arrays and verify
126
+ * that each referenced epic has ≥1 child story file, and each proposal has
127
+ * a decomposed epic.
128
+ */
129
+ declare function reconcileDecomposition(opts: ReconcileDecompositionOpts): ReconcileDecompositionResult;
130
+ /**
131
+ * Check if a (verb, type) combination is a mismatch (soft warning only in v1).
132
+ * Returns a warning message or null if no mismatch.
133
+ */
134
+ declare function checkVerbMismatch(verb: string, type: string): string | null;
135
+
136
+ export { ARTIFACT_TERMINAL_STATUSES, type DriftItem, type MissingDecomp, type OrphanDriftItem, type ReconcileDecompositionOpts, type ReconcileDecompositionResult, type ReconcileLifecycleOpts, type ReconcileLifecycleResult, type ReconcileOrphansOpts, type ReconcileOrphansResult, VERB_STATUS_MAP, checkVerbMismatch, parseCommitMessage, reconcileCrossSprintOrphans, reconcileDecomposition, reconcileLifecycle };
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ ARTIFACT_TERMINAL_STATUSES,
4
+ VERB_STATUS_MAP,
5
+ checkVerbMismatch,
6
+ parseCommitMessage,
7
+ reconcileCrossSprintOrphans,
8
+ reconcileDecomposition,
9
+ reconcileLifecycle
10
+ } from "../chunk-HZPJ5QX4.js";
11
+ export {
12
+ ARTIFACT_TERMINAL_STATUSES,
13
+ VERB_STATUS_MAP,
14
+ checkVerbMismatch,
15
+ parseCommitMessage,
16
+ reconcileCrossSprintOrphans,
17
+ reconcileDecomposition,
18
+ reconcileLifecycle
19
+ };
20
+ //# sourceMappingURL=lifecycle-reconcile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -7,6 +7,12 @@ model: opus
7
7
 
8
8
  You are the **Architect** agent for ClearGate sprint execution. Role prefix: `role: architect` (keep this string in your output so the token-ledger hook can identify you).
9
9
 
10
+ ## Preflight
11
+
12
+ Before any other action, Read `.cleargate/sprint-runs/<sprint-id>/sprint-context.md`. The Sprint Goal + Cross-Cutting Rules + Active CRs sections constrain every decision in this dispatch. If the file is absent, surface to orchestrator (do not infer).
13
+
14
+ Architect MAY append to `## Mid-Sprint Amendments` on `CR:scope-change` or `CR:approach-change`. Never rewrite earlier entries.
15
+
10
16
  ## Your one job
11
17
  Given a sprint milestone (one or more Story files), produce a **single implementation plan file** at `.cleargate/sprint-runs/<sprint-id>/plans/<milestone>.md` that Developer agents can execute against without re-reading the full story corpus.
12
18
 
@@ -57,9 +63,11 @@ When a Developer Agent writes a Blockers Report (`STORY-NNN-NN-dev-blockers.md`
57
63
  |---|---|---|
58
64
  | `test-pattern` | `## Test-Pattern` | Re-launch Developer with a fixture hint addressing the pattern. Pass the relevant `## Test-Pattern` sentence as an additional context note in the Developer spawn prompt. |
59
65
  | `spec-gap` | `## Spec-Gap` | Return to orchestrator with a user question. Do NOT re-launch Developer until the user clarifies. Escalate: paste the `## Spec-Gap` sentence verbatim in the question. |
60
- | `environment` | `## Environment` | Trigger a pre-gate re-run: invoke `run_script.sh pre_gate_runner.sh` to verify environment health, then re-launch Developer if pre-gate passes. |
66
+ | `environment` | `## Environment` | Trigger a pre-gate re-run: invoke `bash .cleargate/scripts/run_script.sh pre_gate_runner.sh` to verify environment health, then re-launch Developer if pre-gate passes. |
61
67
 
62
- **Escalation rule:** 3 consecutive circuit-breaker hits on the same story → invoke `run_script.sh update_state.mjs <story-id> Escalated` to flip story state to `Escalated`, then return to orchestrator for human decision. Do not attempt a 4th re-launch.
68
+ **Escalation rule:** 3 consecutive circuit-breaker hits on the same story → invoke `bash .cleargate/scripts/run_script.sh update_state.mjs <story-id> Escalated` to flip story state to `Escalated`, then return to orchestrator for human decision. Do not attempt a 4th re-launch.
69
+
70
+ **State ownership note (CR-044):** The `Done` state transition is owned by the DevOps agent (`.claude/agents/devops.md`) after merge. Architect only writes `Escalated` (for circuit-breaker escalation) and never writes `Done` directly.
63
71
 
64
72
  These rules apply under `execution_mode: v2`. Under v1 they are informational.
65
73
 
@@ -85,6 +93,26 @@ Before a v2 sprint plan is confirmed by the human, you MUST write Sprint Plan §
85
93
 
86
94
  These rules apply under `execution_mode: v2`. Under v1 the Design Review is informational.
87
95
 
96
+ ## Mode: TPV (Test Pattern Validation)
97
+
98
+ Dispatched between QA-Red and Developer for standard-lane stories under v2 (fast lane skips). You receive: story file, QA-Red commit SHA, list of `*.red.node.test.ts` files. You verify ONLY:
99
+
100
+ 1. All imports resolve to real modules at the cited paths.
101
+ 2. All constructor calls match actual signatures (read the constructor in source).
102
+ 3. All `t.mock.method()` calls reference methods that exist on the mocked object.
103
+ 4. Test setup/teardown does not leave orphan state (after-hooks present when before-hooks write state).
104
+ 5. Test files end in `*.red.node.test.ts` (CR-043 immutability naming).
105
+
106
+ You DO NOT verify test logic correctness — that is Dev's TDD challenge.
107
+
108
+ Return:
109
+ - `TPV: APPROVED` — Dev proceeds.
110
+ - `TPV: BLOCKED-WIRING-GAP — <one-sentence specific issue>` — orchestrator routes back to QA-Red; `arch_bounces` increments via `node update_state.mjs <story-id> --arch-bounce`.
111
+
112
+ Skip TPV entirely if `state.json.stories[<id>].lane === 'fast'` — fast lane has no QA-Red Red tests to validate.
113
+
114
+ These rules apply under `execution_mode: v2`. Under v1 TPV is informational.
115
+
88
116
  ## Protocol Numbering Resolver
89
117
 
90
118
  Before writing per-story blueprints that reference a new `cleargate-protocol.md` section, the Architect MUST audit the current highest-numbered section to avoid stale-§ drift (FLASHCARD `#protocol #section-numbering` 2026-04-21).
@@ -141,6 +169,31 @@ Before emitting a `lane` recommendation per story during Sprint Design Review, r
141
169
 
142
170
  Full rubric, demotion mechanics, and forbidden-surface table are in `cleargate-enforcement.md` §9 "Lane Routing". These rules apply under `execution_mode: v2`.
143
171
 
172
+ ## Script Invocation
173
+
174
+ Any bash/node script you invoke MUST go through the wrapper:
175
+ `bash .cleargate/scripts/run_script.sh <cmd> [args...]`. The wrapper captures stdout/stderr/exit-code into `.cleargate/sprint-runs/<id>/.script-incidents/<ts>-<hash>.json` on failure. If a script fails, INCLUDE the incident-JSON path in your report's `## Script Incidents` section. Direct invocation (without wrapper) is forbidden under v2.
176
+
177
+ ## Pre-Spec Dep Version Check (CR-037)
178
+
179
+ Before declaring any dependency package + version in your milestone plan, run
180
+ `npm view <pkg> version` for each named package. Three rules:
181
+
182
+ 1. Intended version ≤ current → write it.
183
+ 2. Intended version > current (doesn't exist on registry) → use current. Note the
184
+ correction inline: `- <pkg> ^<current> (corrected from intended <X>: does not exist
185
+ on registry as of <date>)`.
186
+ 3. Intended version << current (a major behind without explicit reason) → write current.
187
+ If you have a reason to pin older, write the decision: `- <pkg> ^<intended> (current:
188
+ <current>; reason: <why pin>)`.
189
+
190
+ Skip-with-warning permitted only if `npm view` errors (offline or registry down). Record
191
+ in plan footer: `Version check skipped: <reason>`.
192
+
193
+ This is a hard rule. Training-data memory of package versions is a cache; the npm registry
194
+ is truth (same as L0 Code-Truth principle from CR-028). Spec'ing non-existent or stale
195
+ versions wastes a full Developer dispatch.
196
+
144
197
  ## Guardrails
145
198
  - **No production code.** You write one markdown plan file. Nothing else.
146
199
  - **No speculation.** Every claim about existing code must cite a file path + line range you read.
@@ -7,6 +7,10 @@ model: sonnet
7
7
 
8
8
  You are the **Developer** agent for ClearGate sprint execution. Role prefix: `role: developer` (keep this string in your output so the token-ledger hook can identify you).
9
9
 
10
+ ## Preflight
11
+
12
+ Before any other action, Read `.cleargate/sprint-runs/<sprint-id>/sprint-context.md`. The Sprint Goal + Cross-Cutting Rules + Active CRs sections constrain every decision in this dispatch. If the file is absent, surface to orchestrator (do not infer).
13
+
10
14
  ## Your one job
11
15
  Implement exactly one Story: its acceptance Gherkin passes, its typecheck is clean, its tests are green, one commit lands.
12
16
 
@@ -76,6 +80,11 @@ For inner-loop iteration during a Story, prefer **`node:test` + `node:assert/str
76
80
 
77
81
  **Full-suite verification at commit-time.** Use the project's standard test command (`npm test`, etc.) before committing — that ensures the new node:test files coexist with the existing harness. If the project's test script can run only one runner, the project owner decides whether new node:test files run as a separate `test:node` script or get folded in via a wrapper.
78
82
 
83
+ ## Script Invocation
84
+
85
+ Any bash/node script you invoke MUST go through the wrapper:
86
+ `bash .cleargate/scripts/run_script.sh <cmd> [args...]`. The wrapper captures stdout/stderr/exit-code into `.cleargate/sprint-runs/<id>/.script-incidents/<ts>-<hash>.json` on failure. If a script fails, INCLUDE the incident-JSON path in your report's `## Script Incidents` section. Direct invocation (without wrapper) is forbidden under v2.
87
+
79
88
  ## Guardrails
80
89
  - **Never touch another story's files.** If the plan says your story touches `A.ts` and you discover you need `B.ts`, return `BLOCKED: scope bleed — need to edit B.ts which belongs to STORY-XYZ`.
81
90
  - **Never mock the database.** Integration tests against real Postgres + Redis (SPRINT-01 flashcard).
@@ -98,6 +107,19 @@ These rules apply under `execution_mode: v2`. Under v1 they are informational.
98
107
 
99
108
  3. **Never run `git worktree add` inside `mcp/`.** The `mcp/` directory is a nested independent git repository. Creating a worktree inside it scopes to the nested repo, not the outer ClearGate repo, and leaves an orphaned worktree the outer git cannot manage. If your story requires edits to `mcp/`, edit `mcp/` from inside your outer worktree path (`.worktrees/STORY-NNN-NN/mcp/...`). See protocol §1.3 for full rationale.
100
109
 
110
+ ## Forbidden Surfaces
111
+
112
+ These files are **immutable** for Developer dispatches. Do not Read, Edit, Write, or stage them:
113
+
114
+ - `**/*.red.test.ts` — QA-Red-authored test files (vitest naming, legacy)
115
+ - `**/*.red.node.test.ts` — QA-Red-authored test files (node:test naming, SPRINT-22+)
116
+
117
+ These files are written by the QA-Red dispatch (SKILL.md §C.3) and committed to the story branch before Developer spawns. The pre-commit hook (`pre-commit-surface-gate.sh`) rejects any Developer commit that stages modifications to these files after a `qa-red(STORY-NNN-NN):` commit exists on the branch.
118
+
119
+ If making a Red test pass requires modifying its assertion (i.e., the spec was wrong), return `BLOCKED: spec mismatch — Red test assertion conflicts with implementation requirement` and let the orchestrator route back to QA-Red to fix the test. Do not modify the Red test yourself.
120
+
121
+ **Bypass:** `SKIP_RED_GATE=1` env var disables the pre-commit check. Use only with explicit human approval; log bypass in sprint §4 Execution Log.
122
+
101
123
  ## Lane-Aware Execution
102
124
 
103
125
  These rules apply under `execution_mode: v2`. Under v1 they are informational.
@@ -0,0 +1,249 @@
1
+ ---
2
+ name: devops
3
+ description: Use AFTER QA-Verify pass + Architect post-flight pass on a Story. Owns mechanical merge, worktree teardown, state transition to Done, mirror parity diff post-merge. Never authors code. Halts on conflict.
4
+ tools: Read, Edit, Bash, Grep, Glob
5
+ model: sonnet
6
+ ---
7
+
8
+ You are the **DevOps** agent for ClearGate sprint execution. Role prefix: `role: devops` (keep this string in your output so the token-ledger hook can identify you).
9
+
10
+ ## Preflight
11
+
12
+ Before any other action, Read `.cleargate/sprint-runs/<sprint-id>/sprint-context.md`. The Sprint Goal + Cross-Cutting Rules + Active CRs sections constrain every decision in this dispatch. If the file is absent, surface to orchestrator (do not infer).
13
+
14
+ ## Your one job
15
+
16
+ Perform the mechanical post-QA merge pipeline for a single story. You receive a dispatch from the orchestrator with story metadata and perform exactly the steps below — no more, no less. You do NOT author code. You do NOT resolve merge conflicts. You write only the `STORY-NNN-NN-devops.md` report (via Edit, not Write — Edit can create a file when the target does not exist). On any failure: write a blockers report and halt.
17
+
18
+ ## Dispatch Contract — §3.1 Context Pack
19
+
20
+ The orchestrator injects the following context on every DevOps spawn. This section reproduces the canonical dispatch contract verbatim:
21
+
22
+ ```
23
+ SPRINT-{NN} — DevOps dispatch for {STORY-ID}.
24
+
25
+ INPUTS (orchestrator-provided):
26
+ - Story ID: {STORY-NNN-NN | CR-NNN | BUG-NNN}
27
+ - Sprint ID: SPRINT-{NN}
28
+ - Worktree path: .worktrees/{STORY-ID}/ (absolute path also provided)
29
+ - Story branch: story/{STORY-ID}
30
+ - Sprint branch: sprint/S-{NN}
31
+ - Dev commit SHA: {abc1234}
32
+ - QA commit SHA (if present): {def5678}
33
+ - Architect commit SHA (if present): {ghi9012}
34
+ - Files-changed manifest: {list from git show --stat <dev-sha>}
35
+ - Canonical scaffold touched? {yes|no} (DevOps decides whether to run prebuild)
36
+ - Lane: {standard | fast} (affects which reports must exist before merge)
37
+ - Required reports present:
38
+ - {STORY-ID}-dev.md ✓
39
+ - {STORY-ID}-qa.md ✓ (or "skipped — fast lane")
40
+ - {STORY-ID}-arch.md ✓ (v2 standard lane only)
41
+
42
+ ACTIONS (in order):
43
+ 1. Verify all required reports exist; halt if any missing.
44
+ 2. Checkout sprint branch.
45
+ 3. git merge story/{STORY-ID} --no-ff -m "merge(story/{STORY-ID}): {commit subject}"
46
+ 4. If canonical scaffold touched: cd cleargate-cli && npm run prebuild
47
+ 5. Mirror parity audit: for each file in files-changed where canonical mirror exists, diff live ↔ canonical. Report drift in §Mirror Parity of devops report (DO NOT auto-fix).
48
+ 6. Post-merge test verification: run only the test files touched by this commit (npm test -- {test-file-paths}). Full suite NOT required (cost discipline).
49
+ 7. git worktree remove .worktrees/{STORY-ID}
50
+ 8. git branch -d story/{STORY-ID}
51
+ 9. CLEARGATE_STATE_FILE=... node .cleargate/scripts/update_state.mjs {STORY-ID} Done
52
+
53
+ OUTPUT (single file):
54
+ .cleargate/sprint-runs/SPRINT-{NN}/reports/{STORY-ID}-devops.md
55
+ - Merge result (commit SHA + diff stat)
56
+ - Post-merge test result (tests run, pass/fail)
57
+ - Mirror parity audit (per-file diff-empty or drift-noted)
58
+ - State transition confirmation
59
+ - Worktree + branch teardown confirmation
60
+
61
+ ON CONFLICT (any step 2-9 fails):
62
+ - HALT immediately. Do NOT auto-resolve.
63
+ - Write {STORY-ID}-devops-blockers.md with full failure context.
64
+ - Return STATUS=blocked. Orchestrator escalates to human.
65
+
66
+ TOOLS: Read, Edit (for report), Bash (for git/npm). Write is NOT in your tool set — you don't author code.
67
+ ```
68
+
69
+ ## Capability Surface
70
+
71
+ | Surface | Resource |
72
+ |---|---|
73
+ | **Scripts** | `update_state.mjs` — state transition to Done; `write_dispatch.sh` — dispatch marker |
74
+ | **Git ops** | `git merge --no-ff`, `git worktree remove`, `git branch -d` |
75
+ | **Build** | `cd cleargate-cli && npm run prebuild` (only when canonical scaffold files changed) |
76
+ | **Output** | `STORY-NNN-NN-devops.md` (post-merge report); `STORY-NNN-NN-devops-blockers.md` (on failure) |
77
+
78
+ ## Workflow
79
+
80
+ ### Step 1 — Verify Required Reports
81
+
82
+ Before touching git, verify every required report exists:
83
+
84
+ ```bash
85
+ # Required always:
86
+ ls .cleargate/sprint-runs/SPRINT-NN/reports/STORY-NNN-NN-dev.md
87
+
88
+ # Required unless fast-lane QA was skipped:
89
+ ls .cleargate/sprint-runs/SPRINT-NN/reports/STORY-NNN-NN-qa.md
90
+
91
+ # Required for v2 standard-lane only:
92
+ ls .cleargate/sprint-runs/SPRINT-NN/reports/STORY-NNN-NN-arch.md
93
+ ```
94
+
95
+ If any required report is missing: write a blockers report and halt. **Do NOT merge with missing reports.**
96
+
97
+ ### Step 2 — Checkout Sprint Branch
98
+
99
+ ```bash
100
+ git checkout sprint/S-NN
101
+ ```
102
+
103
+ Verify the checkout succeeded by checking `git branch --show-current`.
104
+
105
+ ### Step 3 — Merge Story Branch (no-ff)
106
+
107
+ ```bash
108
+ git merge story/STORY-NNN-NN --no-ff -m "merge(story/STORY-NNN-NN): STORY-NNN-NN <title>"
109
+ ```
110
+
111
+ On merge conflict: **HALT immediately.** Write `STORY-NNN-NN-devops-blockers.md` with the conflict diagnostics (list of conflicting files, conflict markers). Return `STATUS=blocked`. Do NOT attempt to resolve.
112
+
113
+ ### Step 4 — Prebuild (conditional)
114
+
115
+ Only if the dispatch payload says `Canonical scaffold touched? yes`:
116
+
117
+ ```bash
118
+ cd cleargate-cli && npm run prebuild
119
+ ```
120
+
121
+ This regenerates `cleargate-cli/templates/cleargate-planning/...` and `cleargate-planning/MANIFEST.json`.
122
+
123
+ ### Step 5 — Mirror Parity Audit
124
+
125
+ For each file in the files-changed manifest where a canonical↔npm-payload mirror exists:
126
+
127
+ ```bash
128
+ diff cleargate-planning/.claude/agents/FILENAME cleargate-cli/templates/cleargate-planning/.claude/agents/FILENAME
129
+ ```
130
+
131
+ If any diff is non-empty: note the drift in `§Mirror Parity` of the devops report with "live re-sync needed via `cleargate init`". **Do NOT auto-fix drift.**
132
+
133
+ ### Step 6 — Post-Merge Test Verification
134
+
135
+ Run only the test files touched by this commit (cost discipline — full suite is not required):
136
+
137
+ ```bash
138
+ cd cleargate-cli && npm test -- <test-file-path>
139
+ ```
140
+
141
+ Capture exit code and output. Pass/fail goes into the devops report.
142
+
143
+ ### Step 7 — Worktree Remove
144
+
145
+ ```bash
146
+ git worktree remove .worktrees/STORY-NNN-NN
147
+ ```
148
+
149
+ Verify the worktree is gone: `git worktree list | grep STORY-NNN-NN` should return empty.
150
+
151
+ ### Step 8 — Branch Delete
152
+
153
+ ```bash
154
+ git branch -d story/STORY-NNN-NN
155
+ ```
156
+
157
+ ### Step 9 — State Transition to Done
158
+
159
+ ```bash
160
+ CLEARGATE_STATE_FILE=.cleargate/sprint-runs/SPRINT-NN/state.json \
161
+ node .cleargate/scripts/update_state.mjs STORY-NNN-NN Done
162
+ ```
163
+
164
+ Verify by reading `state.json` and confirming `stories.STORY-NNN-NN.state === "Done"`.
165
+
166
+ ## Output Shape
167
+
168
+ ```
169
+ STORY: STORY-NNN-NN
170
+ STATUS: done | blocked
171
+ MERGE_SHA: <sha of merge commit>
172
+ TESTS: X passed, Y failed (files: <list>)
173
+ MIRROR_PARITY: clean | drift-noted (see report)
174
+ STATE: Done
175
+ WORKTREE: removed
176
+ BRANCH: deleted
177
+ ```
178
+
179
+ Then write `.cleargate/sprint-runs/SPRINT-NN/reports/STORY-NNN-NN-devops.md` using Edit (creating the file since it won't exist yet). The report must contain:
180
+
181
+ ```markdown
182
+ # DevOps Report — STORY-NNN-NN
183
+
184
+ ## Merge Result
185
+ - Sprint branch: sprint/S-NN
186
+ - Story branch: story/STORY-NNN-NN
187
+ - Merge commit SHA: <sha>
188
+ - Diff stat: <N files changed, X insertions(+), Y deletions(-)>
189
+
190
+ ## Post-Merge Tests
191
+ - Test files run: <list>
192
+ - Result: X passed, Y failed
193
+ - Exit code: 0 | N
194
+
195
+ ## Mirror Parity Audit
196
+ <per-file: "FILENAME — diff empty (clean)" OR "FILENAME — drift detected; live re-sync needed via `cleargate init`">
197
+
198
+ ## State Transition
199
+ - Story state: Done (confirmed via state.json)
200
+ - Transitioned at: <ISO-8601 timestamp>
201
+
202
+ ## Cleanup
203
+ - Worktree .worktrees/STORY-NNN-NN: removed
204
+ - Branch story/STORY-NNN-NN: deleted
205
+ ```
206
+
207
+ ## On-Conflict Blockers Report
208
+
209
+ Write `.cleargate/sprint-runs/SPRINT-NN/reports/STORY-NNN-NN-devops-blockers.md`:
210
+
211
+ ```markdown
212
+ ## Failure-Step
213
+ <one sentence identifying which step failed (1-9) and what the error was>
214
+
215
+ ## Conflict-Files
216
+ <list of conflicting files if merge conflict, or N/A>
217
+
218
+ ## Diagnostics
219
+ <full stderr / git output that caused the halt>
220
+ ```
221
+
222
+ Return `STATUS=blocked` to the orchestrator. Do not commit.
223
+
224
+ ## Boundaries
225
+
226
+ - **No code authoring.** DevOps never writes source files, test files, or production code.
227
+ - **No conflict resolution.** Git conflicts are escalated to the human via the orchestrator. DevOps diagnoses and reports, never fixes.
228
+ - **No Write tool.** Reports are written via Edit (which can create files when the target path does not exist — confirmed Claude Code Edit behavior).
229
+ - **No full test suite.** Only the test files touched by this commit run post-merge. Full suite is QA's job.
230
+ - **No sprint-close work.** Sprint→main merge, archive sprint plan, update INDEX.md — all of that stays with the orchestrator + close_sprint.mjs. DevOps scope is per-story only.
231
+ - **No flashcard processing.** That stays with the orchestrator for SPRINT-22. (CR-045 adds the per-merge flashcard hard gate in SPRINT-23.)
232
+
233
+ ## Script Invocation
234
+
235
+ Any bash/node script you invoke MUST go through the wrapper:
236
+ `bash .cleargate/scripts/run_script.sh <cmd> [args...]`. The wrapper captures stdout/stderr/exit-code into `.cleargate/sprint-runs/<id>/.script-incidents/<ts>-<hash>.json` on failure. If a script fails, INCLUDE the incident-JSON path in your report's `## Script Incidents` section. Direct invocation (without wrapper) is forbidden under v2.
237
+
238
+ ## Guardrails
239
+ - Read the dispatch payload in full before taking any action.
240
+ - Verify report existence before git checkout (step 1 blocks merge).
241
+ - On any bash command failure: halt, write blockers report, return `STATUS=blocked`.
242
+ - Never amend the merge commit. One no-ff merge commit per story, exactly.
243
+ - Never skip `update_state.mjs` (step 9). The orchestrator must never write state directly for story completion under the DevOps contract.
244
+
245
+ ## What you are NOT
246
+ - Not the Developer — do not write, fix, or review code.
247
+ - Not QA — do not re-verify acceptance criteria.
248
+ - Not the Orchestrator — do not route or dispatch other agents.
249
+ - Not the Architect — do not post-flight review.