cleargate 0.14.0 → 0.15.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 (149) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/MANIFEST.json +71 -15
  3. package/dist/admin-api/index.cjs +0 -1
  4. package/dist/admin-api/index.js +1 -2
  5. package/dist/auth/factory.cjs +0 -1
  6. package/dist/auth/factory.js +2 -3
  7. package/dist/auth/require-token.cjs +0 -1
  8. package/dist/auth/require-token.js +1 -2
  9. package/dist/auth/token-store.cjs +0 -1
  10. package/dist/auth/token-store.js +1 -2
  11. package/dist/{bootstrap-root-QKSA5V75.js → bootstrap-root-2H5HVTCC.js} +1 -2
  12. package/dist/{chunk-PDE37WFQ.js → chunk-A7MSQUU7.js} +2 -3
  13. package/dist/{chunk-BTSZOEWC.js → chunk-P6KEDAK2.js} +0 -1
  14. package/dist/{chunk-E3X7IE5E.js → chunk-PY6FHGV5.js} +1 -2
  15. package/dist/{chunk-5DI2Z3C2.js → chunk-Y53ZZYYU.js} +1 -2
  16. package/dist/cli.cjs +1564 -1414
  17. package/dist/cli.js +1514 -1364
  18. package/dist/lib/ledger.cjs +0 -1
  19. package/dist/lib/ledger.js +1 -2
  20. package/dist/lib/lifecycle-reconcile.cjs +0 -1
  21. package/dist/lib/lifecycle-reconcile.js +2 -3
  22. package/dist/{whoami-EANGN46Z.js → whoami-JKQQPABQ.js} +3 -4
  23. package/package.json +4 -3
  24. package/templates/cleargate-planning/.claude/agents/architect.md +4 -2
  25. package/templates/cleargate-planning/.claude/agents/developer.md +4 -11
  26. package/templates/cleargate-planning/.claude/agents/qa.md +14 -6
  27. package/templates/cleargate-planning/.claude/hooks/pending-task-sentinel.sh +2 -2
  28. package/templates/cleargate-planning/.claude/skills/sprint-execution/SKILL.md +19 -1
  29. package/templates/cleargate-planning/.cleargate/config.example.yml +16 -0
  30. package/templates/cleargate-planning/.cleargate/scripts/close_sprint.deferred-verify.red.node.test.ts +245 -0
  31. package/templates/cleargate-planning/.cleargate/scripts/close_sprint.mjs +227 -0
  32. package/templates/cleargate-planning/.cleargate/scripts/gate-checks.json +5 -4
  33. package/templates/cleargate-planning/.cleargate/scripts/init_sprint.mjs +75 -2
  34. package/templates/cleargate-planning/.cleargate/scripts/pre_gate_common.sh +48 -0
  35. package/templates/cleargate-planning/.cleargate/scripts/pre_gate_runner.sh +57 -1
  36. package/templates/cleargate-planning/.cleargate/scripts/provision_worktree_config.sh +155 -0
  37. package/templates/cleargate-planning/.cleargate/scripts/qa_red_lint.mjs +380 -0
  38. package/templates/cleargate-planning/.cleargate/scripts/run_script.sh +34 -1
  39. package/templates/cleargate-planning/.cleargate/scripts/test/cr077_eviction.red.sh +113 -0
  40. package/templates/cleargate-planning/.cleargate/scripts/test/cr078_init.test.sh +309 -0
  41. package/templates/cleargate-planning/.cleargate/scripts/test/cr079_provision.red.sh +262 -0
  42. package/templates/cleargate-planning/.cleargate/scripts/test/cr080_wrapper.test.sh +177 -0
  43. package/templates/cleargate-planning/.cleargate/scripts/test/cr081_qa_red_lint.red.sh +348 -0
  44. package/templates/cleargate-planning/.cleargate/sprint-runs/_off-sprint/.session-totals.json +1 -0
  45. package/templates/cleargate-planning/.cleargate/sprint-runs/_off-sprint/token-ledger.jsonl +27 -0
  46. package/templates/cleargate-planning/.cleargate/templates/sprint_context.md +17 -0
  47. package/templates/cleargate-planning/.cleargate/templates/story.md +1 -0
  48. package/templates/cleargate-planning/MANIFEST.json +71 -15
  49. package/dist/admin-api/index.cjs.map +0 -1
  50. package/dist/admin-api/index.js.map +0 -1
  51. package/dist/auth/factory.cjs.map +0 -1
  52. package/dist/auth/factory.js.map +0 -1
  53. package/dist/auth/require-token.cjs.map +0 -1
  54. package/dist/auth/require-token.js.map +0 -1
  55. package/dist/auth/token-store.cjs.map +0 -1
  56. package/dist/auth/token-store.js.map +0 -1
  57. package/dist/bootstrap-root-QKSA5V75.js.map +0 -1
  58. package/dist/chunk-5DI2Z3C2.js.map +0 -1
  59. package/dist/chunk-BTSZOEWC.js.map +0 -1
  60. package/dist/chunk-E3X7IE5E.js.map +0 -1
  61. package/dist/chunk-PDE37WFQ.js.map +0 -1
  62. package/dist/cli.cjs.map +0 -1
  63. package/dist/cli.js.map +0 -1
  64. package/dist/lib/ledger.cjs.map +0 -1
  65. package/dist/lib/ledger.js.map +0 -1
  66. package/dist/lib/lifecycle-reconcile.cjs.map +0 -1
  67. package/dist/lib/lifecycle-reconcile.js.map +0 -1
  68. package/dist/templates/cleargate-planning/.claude/agents/architect-reader.md +0 -61
  69. package/dist/templates/cleargate-planning/.claude/agents/architect-synth.md +0 -124
  70. package/dist/templates/cleargate-planning/.claude/agents/architect.md +0 -230
  71. package/dist/templates/cleargate-planning/.claude/agents/cleargate-wiki-contradict.md +0 -108
  72. package/dist/templates/cleargate-planning/.claude/agents/cleargate-wiki-ingest.md +0 -194
  73. package/dist/templates/cleargate-planning/.claude/agents/cleargate-wiki-lint.md +0 -261
  74. package/dist/templates/cleargate-planning/.claude/agents/cleargate-wiki-query.md +0 -143
  75. package/dist/templates/cleargate-planning/.claude/agents/developer.md +0 -185
  76. package/dist/templates/cleargate-planning/.claude/agents/devops.md +0 -257
  77. package/dist/templates/cleargate-planning/.claude/agents/qa.md +0 -171
  78. package/dist/templates/cleargate-planning/.claude/agents/reporter.md +0 -274
  79. package/dist/templates/cleargate-planning/.claude/hooks/pending-task-sentinel.sh +0 -209
  80. package/dist/templates/cleargate-planning/.claude/hooks/pre-commit-surface-gate.sh +0 -33
  81. package/dist/templates/cleargate-planning/.claude/hooks/pre-commit-test-ratchet.sh +0 -58
  82. package/dist/templates/cleargate-planning/.claude/hooks/pre-commit.sh +0 -19
  83. package/dist/templates/cleargate-planning/.claude/hooks/pre-edit-gate.sh +0 -162
  84. package/dist/templates/cleargate-planning/.claude/hooks/pre-tool-use-autonomy.sh +0 -58
  85. package/dist/templates/cleargate-planning/.claude/hooks/pre-tool-use-task.sh +0 -148
  86. package/dist/templates/cleargate-planning/.claude/hooks/session-start.sh +0 -75
  87. package/dist/templates/cleargate-planning/.claude/hooks/stamp-and-gate.sh +0 -43
  88. package/dist/templates/cleargate-planning/.claude/hooks/token-ledger.sh +0 -590
  89. package/dist/templates/cleargate-planning/.claude/settings.json +0 -68
  90. package/dist/templates/cleargate-planning/.claude/skills/flashcard/SKILL.md +0 -102
  91. package/dist/templates/cleargate-planning/.claude/skills/sprint-execution/SKILL.md +0 -742
  92. package/dist/templates/cleargate-planning/.cleargate/FLASHCARD.md +0 -7
  93. package/dist/templates/cleargate-planning/.cleargate/config.example.yml +0 -67
  94. package/dist/templates/cleargate-planning/.cleargate/config.yml +0 -18
  95. package/dist/templates/cleargate-planning/.cleargate/delivery/archive/.gitkeep +0 -0
  96. package/dist/templates/cleargate-planning/.cleargate/delivery/pending-sync/.gitkeep +0 -0
  97. package/dist/templates/cleargate-planning/.cleargate/knowledge/cleargate-enforcement.md +0 -551
  98. package/dist/templates/cleargate-planning/.cleargate/knowledge/cleargate-protocol.md +0 -878
  99. package/dist/templates/cleargate-planning/.cleargate/knowledge/mid-sprint-triage-rubric.md +0 -160
  100. package/dist/templates/cleargate-planning/.cleargate/knowledge/readiness-gates.md +0 -213
  101. package/dist/templates/cleargate-planning/.cleargate/knowledge/sprint-closeout-checklist.md +0 -71
  102. package/dist/templates/cleargate-planning/.cleargate/scripts/_migrate-schema-v3.mjs +0 -120
  103. package/dist/templates/cleargate-planning/.cleargate/scripts/assert_story_files.mjs +0 -265
  104. package/dist/templates/cleargate-planning/.cleargate/scripts/close_sprint.mjs +0 -1012
  105. package/dist/templates/cleargate-planning/.cleargate/scripts/collision_surface.sh +0 -114
  106. package/dist/templates/cleargate-planning/.cleargate/scripts/constants.mjs +0 -62
  107. package/dist/templates/cleargate-planning/.cleargate/scripts/dedupe_frontmatter.mjs +0 -219
  108. package/dist/templates/cleargate-planning/.cleargate/scripts/file_surface_diff.sh +0 -320
  109. package/dist/templates/cleargate-planning/.cleargate/scripts/gate-checks.json +0 -15
  110. package/dist/templates/cleargate-planning/.cleargate/scripts/init_gate_config.sh +0 -38
  111. package/dist/templates/cleargate-planning/.cleargate/scripts/init_sprint.mjs +0 -240
  112. package/dist/templates/cleargate-planning/.cleargate/scripts/launch_wave.mjs +0 -341
  113. package/dist/templates/cleargate-planning/.cleargate/scripts/lib/report-filename.mjs +0 -54
  114. package/dist/templates/cleargate-planning/.cleargate/scripts/pre_gate_common.sh +0 -206
  115. package/dist/templates/cleargate-planning/.cleargate/scripts/pre_gate_runner.sh +0 -371
  116. package/dist/templates/cleargate-planning/.cleargate/scripts/prefill_report.mjs +0 -280
  117. package/dist/templates/cleargate-planning/.cleargate/scripts/prep_doc_refresh.mjs +0 -378
  118. package/dist/templates/cleargate-planning/.cleargate/scripts/prep_qa_context.mjs +0 -888
  119. package/dist/templates/cleargate-planning/.cleargate/scripts/run_script.sh +0 -209
  120. package/dist/templates/cleargate-planning/.cleargate/scripts/sprint_trends.mjs +0 -71
  121. package/dist/templates/cleargate-planning/.cleargate/scripts/state.schema.json +0 -127
  122. package/dist/templates/cleargate-planning/.cleargate/scripts/suggest_improvements.mjs +0 -717
  123. package/dist/templates/cleargate-planning/.cleargate/scripts/surface-whitelist.txt +0 -27
  124. package/dist/templates/cleargate-planning/.cleargate/scripts/test/test_assert_story_files.sh +0 -261
  125. package/dist/templates/cleargate-planning/.cleargate/scripts/test/test_file_surface.sh +0 -210
  126. package/dist/templates/cleargate-planning/.cleargate/scripts/test/test_flashcard_gate.sh +0 -190
  127. package/dist/templates/cleargate-planning/.cleargate/scripts/test/test_prep_qa_context.sh +0 -482
  128. package/dist/templates/cleargate-planning/.cleargate/scripts/test/test_test_ratchet.sh +0 -327
  129. package/dist/templates/cleargate-planning/.cleargate/scripts/test_ratchet.mjs +0 -261
  130. package/dist/templates/cleargate-planning/.cleargate/scripts/update_state.mjs +0 -246
  131. package/dist/templates/cleargate-planning/.cleargate/scripts/validate_bounce_readiness.mjs +0 -111
  132. package/dist/templates/cleargate-planning/.cleargate/scripts/validate_state.mjs +0 -184
  133. package/dist/templates/cleargate-planning/.cleargate/scripts/write_dispatch.sh +0 -172
  134. package/dist/templates/cleargate-planning/.cleargate/templates/Bug.md +0 -126
  135. package/dist/templates/cleargate-planning/.cleargate/templates/CR.md +0 -130
  136. package/dist/templates/cleargate-planning/.cleargate/templates/Sprint Plan Template.md +0 -137
  137. package/dist/templates/cleargate-planning/.cleargate/templates/epic.md +0 -166
  138. package/dist/templates/cleargate-planning/.cleargate/templates/hotfix.md +0 -111
  139. package/dist/templates/cleargate-planning/.cleargate/templates/initiative.md +0 -122
  140. package/dist/templates/cleargate-planning/.cleargate/templates/sprint_context.md +0 -50
  141. package/dist/templates/cleargate-planning/.cleargate/templates/sprint_report.md +0 -224
  142. package/dist/templates/cleargate-planning/.cleargate/templates/story.md +0 -213
  143. package/dist/templates/cleargate-planning/CLAUDE.md +0 -66
  144. package/dist/templates/cleargate-planning/MANIFEST.json +0 -503
  145. package/dist/templates/synthesis/active-sprint.md +0 -30
  146. package/dist/templates/synthesis/open-gates.md +0 -38
  147. package/dist/templates/synthesis/product-state.md +0 -31
  148. package/dist/templates/synthesis/roadmap.md +0 -63
  149. package/dist/whoami-EANGN46Z.js.map +0 -1
@@ -1,27 +0,0 @@
1
- # surface-whitelist.txt — Files always admitted by the pre-commit surface gate
2
- # regardless of the active story's §3.1 declared surface.
3
- #
4
- # Format: one pattern per line. Supports bash glob patterns.
5
- # * matches any non-path-separator sequence
6
- # ** matches any sequence (including path separators)
7
- # Lines starting with # are comments; blank lines are ignored.
8
- #
9
- # These patterns are matched against repo-root-relative staged file paths.
10
-
11
- # Build manifest (regenerated by npm run build)
12
- cleargate-planning/MANIFEST.json
13
-
14
- # Hook execution logs
15
- .cleargate/hook-log/*
16
-
17
- # Token ledger files (auto-generated by SubagentStop hook)
18
- .cleargate/sprint-runs/**/token-ledger.jsonl
19
-
20
- # Pending-task sentinel files (auto-generated by PreToolUse hook)
21
- .cleargate/sprint-runs/**/.pending-task-*.json
22
-
23
- # Sprint state files (auto-managed)
24
- .cleargate/sprint-runs/**/state.json
25
-
26
- # Gate check log (auto-generated)
27
- .cleargate/hook-log/gate-check.log
@@ -1,261 +0,0 @@
1
- #!/usr/bin/env bash
2
- # test_assert_story_files.sh — 4-scenario Gherkin test for STORY-014-02
3
- #
4
- # Tests:
5
- # Scenario 1: v2 init refuses when stories are missing
6
- # Scenario 2: v2 init succeeds when all stories exist
7
- # Scenario 3: v1 init warns but does not block
8
- # Scenario 4: assert_story_files standalone CLI
9
- #
10
- # Run: bash .cleargate/scripts/test/test_assert_story_files.sh
11
- # Requires Node 24+.
12
- #
13
- # Story IDs must use digit-only parts (STORY-\d+-\d+), e.g. STORY-099-01.
14
-
15
- set -euo pipefail
16
-
17
- SCRIPTS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
18
- REPO_ROOT="$(cd "${SCRIPTS_DIR}/../.." && pwd)"
19
-
20
- PASS=0
21
- FAIL=0
22
- ERRORS=()
23
-
24
- assert_eq() {
25
- local label="$1" expected="$2" actual="$3"
26
- if [ "$expected" = "$actual" ]; then
27
- echo " PASS: $label"
28
- PASS=$((PASS + 1))
29
- else
30
- echo " FAIL: $label"
31
- echo " expected: $expected"
32
- echo " actual: $actual"
33
- FAIL=$((FAIL + 1))
34
- ERRORS+=("$label")
35
- fi
36
- }
37
-
38
- assert_contains() {
39
- local label="$1" needle="$2" haystack="$3"
40
- if echo "$haystack" | grep -qF "$needle"; then
41
- echo " PASS: $label"
42
- PASS=$((PASS + 1))
43
- else
44
- echo " FAIL: $label (needle not found)"
45
- echo " needle: $needle"
46
- echo " haystack: $haystack"
47
- FAIL=$((FAIL + 1))
48
- ERRORS+=("$label")
49
- fi
50
- }
51
-
52
- assert_not_exists() {
53
- local label="$1" filepath="$2"
54
- if [ ! -e "$filepath" ]; then
55
- echo " PASS: $label"
56
- PASS=$((PASS + 1))
57
- else
58
- echo " FAIL: $label (file exists but should not)"
59
- echo " path: $filepath"
60
- FAIL=$((FAIL + 1))
61
- ERRORS+=("$label")
62
- fi
63
- }
64
-
65
- assert_exists() {
66
- local label="$1" filepath="$2"
67
- if [ -e "$filepath" ]; then
68
- echo " PASS: $label"
69
- PASS=$((PASS + 1))
70
- else
71
- echo " FAIL: $label (file does not exist)"
72
- echo " path: $filepath"
73
- FAIL=$((FAIL + 1))
74
- ERRORS+=("$label")
75
- fi
76
- }
77
-
78
- # Create a minimal sprint file with given execution_mode
79
- # Story IDs must be STORY-\d+-\d+ (all numeric parts) for the regex to match.
80
- # Usage: make_sprint_file <dir> <sprint-id> <execution_mode> <story-id-1> [<story-id-2> ...]
81
- make_sprint_file() {
82
- local dir="$1" sprint_id="$2" exec_mode="$3"
83
- shift 3
84
- local story_ids=("$@")
85
-
86
- local sprint_file="${dir}/.cleargate/delivery/pending-sync/${sprint_id}_Test_Sprint.md"
87
- mkdir -p "$(dirname "$sprint_file")"
88
-
89
- {
90
- echo "---"
91
- echo "sprint_id: \"${sprint_id}\""
92
- echo "execution_mode: \"${exec_mode}\""
93
- echo "approved: true"
94
- echo "---"
95
- echo ""
96
- echo "# ${sprint_id}: Test Sprint"
97
- echo ""
98
- echo "## 1. Consolidated Deliverables"
99
- echo ""
100
- echo "| Story | Complexity | Milestone |"
101
- echo "|---|---|---|"
102
- for sid in "${story_ids[@]}"; do
103
- echo "| [\`${sid}\`](${sid}_Placeholder.md) Placeholder | L2 | M1 |"
104
- done
105
- echo ""
106
- echo "## 2. Other Section"
107
- echo ""
108
- echo "Some content here."
109
- } > "$sprint_file"
110
-
111
- echo "$sprint_file"
112
- }
113
-
114
- # Create a minimal story file in pending-sync/
115
- make_story_file() {
116
- local dir="$1" story_id="$2"
117
- local pending_sync="${dir}/.cleargate/delivery/pending-sync"
118
- mkdir -p "$pending_sync"
119
- echo "# ${story_id}: Placeholder" > "${pending_sync}/${story_id}_Placeholder.md"
120
- }
121
-
122
- # ---------------------------------------------------------------------------
123
- echo ""
124
- echo "=== Scenario 1: v2 init refuses when stories are missing ==="
125
- # ---------------------------------------------------------------------------
126
- TMP1="$(mktemp -d)"
127
- trap 'rm -rf "$TMP1"' EXIT
128
-
129
- SPRINT_ID="SPRINT-099"
130
- make_sprint_file "$TMP1" "$SPRINT_ID" "v2" \
131
- "STORY-099-01" "STORY-099-02" "STORY-099-03" > /dev/null
132
-
133
- # Only create STORY-099-01, leave 02 and 03 missing
134
- make_story_file "$TMP1" "STORY-099-01"
135
-
136
- STATE_JSON="${TMP1}/.cleargate/sprint-runs/${SPRINT_ID}/state.json"
137
-
138
- STDERR_OUT=""
139
- EXIT_CODE=0
140
- STDERR_OUT="$(CLEARGATE_REPO_ROOT="$TMP1" node "$SCRIPTS_DIR/init_sprint.mjs" \
141
- "$SPRINT_ID" --stories "STORY-099-01,STORY-099-02,STORY-099-03" 2>&1 >/dev/null)" || EXIT_CODE=$?
142
-
143
- assert_eq "Sc1: exit code non-zero" "1" "$EXIT_CODE"
144
- assert_contains "Sc1: stderr mentions STORY-099-02" "STORY-099-02" "$STDERR_OUT"
145
- assert_contains "Sc1: stderr mentions STORY-099-03" "STORY-099-03" "$STDERR_OUT"
146
- assert_not_exists "Sc1: state.json NOT created" "$STATE_JSON"
147
-
148
- trap - EXIT
149
- rm -rf "$TMP1"
150
-
151
- # ---------------------------------------------------------------------------
152
- echo ""
153
- echo "=== Scenario 2: v2 init succeeds when all stories exist ==="
154
- # ---------------------------------------------------------------------------
155
- TMP2="$(mktemp -d)"
156
- trap 'rm -rf "$TMP2"' EXIT
157
-
158
- SPRINT_ID="SPRINT-098"
159
- make_sprint_file "$TMP2" "$SPRINT_ID" "v2" \
160
- "STORY-098-01" "STORY-098-02" "STORY-098-03" > /dev/null
161
-
162
- make_story_file "$TMP2" "STORY-098-01"
163
- make_story_file "$TMP2" "STORY-098-02"
164
- make_story_file "$TMP2" "STORY-098-03"
165
-
166
- STATE_JSON="${TMP2}/.cleargate/sprint-runs/${SPRINT_ID}/state.json"
167
-
168
- EXIT_CODE=0
169
- CLEARGATE_REPO_ROOT="$TMP2" node "$SCRIPTS_DIR/init_sprint.mjs" \
170
- "$SPRINT_ID" --stories "STORY-098-01,STORY-098-02,STORY-098-03" 2>/dev/null || EXIT_CODE=$?
171
-
172
- assert_eq "Sc2: exit code 0" "0" "$EXIT_CODE"
173
- assert_exists "Sc2: state.json created" "$STATE_JSON"
174
-
175
- # Verify execution_mode in state.json is v2
176
- if [ -f "$STATE_JSON" ]; then
177
- EM="$(node -e "const s=JSON.parse(require('fs').readFileSync('$STATE_JSON','utf8')); console.log(s.execution_mode)")"
178
- assert_eq "Sc2: state.json execution_mode=v2" "v2" "$EM"
179
- fi
180
-
181
- trap - EXIT
182
- rm -rf "$TMP2"
183
-
184
- # ---------------------------------------------------------------------------
185
- echo ""
186
- echo "=== Scenario 3: v1 init warns but does not block ==="
187
- # ---------------------------------------------------------------------------
188
- TMP3="$(mktemp -d)"
189
- trap 'rm -rf "$TMP3"' EXIT
190
-
191
- SPRINT_ID="SPRINT-097"
192
- make_sprint_file "$TMP3" "$SPRINT_ID" "v1" \
193
- "STORY-097-01" "STORY-097-02" > /dev/null
194
-
195
- # Only create STORY-097-01, leave 02 missing
196
- make_story_file "$TMP3" "STORY-097-01"
197
-
198
- STATE_JSON="${TMP3}/.cleargate/sprint-runs/${SPRINT_ID}/state.json"
199
-
200
- EXIT_CODE=0
201
- STDERR_OUT="$(CLEARGATE_REPO_ROOT="$TMP3" node "$SCRIPTS_DIR/init_sprint.mjs" \
202
- "$SPRINT_ID" --stories "STORY-097-01,STORY-097-02" 2>&1 >/dev/null)" || EXIT_CODE=$?
203
-
204
- assert_eq "Sc3: exit code 0 (v1 warns but continues)" "0" "$EXIT_CODE"
205
- assert_exists "Sc3: state.json created despite missing file" "$STATE_JSON"
206
- assert_contains "Sc3: stderr contains WARN" "WARN" "$STDERR_OUT"
207
- assert_contains "Sc3: stderr mentions STORY-097-02" "STORY-097-02" "$STDERR_OUT"
208
-
209
- trap - EXIT
210
- rm -rf "$TMP3"
211
-
212
- # ---------------------------------------------------------------------------
213
- echo ""
214
- echo "=== Scenario 4: assert_story_files standalone CLI ==="
215
- # ---------------------------------------------------------------------------
216
- TMP4="$(mktemp -d)"
217
- trap 'rm -rf "$TMP4"' EXIT
218
-
219
- SPRINT_ID="SPRINT-096"
220
- SPRINT_FILE="$(make_sprint_file "$TMP4" "$SPRINT_ID" "v2" \
221
- "STORY-096-01" "STORY-096-02")"
222
-
223
- # Only create STORY-096-01, leave 02 missing
224
- make_story_file "$TMP4" "STORY-096-01"
225
-
226
- # Run standalone assert_story_files.mjs — should exit 1 with missing list
227
- STDERR_OUT=""
228
- EXIT_CODE=0
229
- STDERR_OUT="$(CLEARGATE_REPO_ROOT="$TMP4" node "$SCRIPTS_DIR/assert_story_files.mjs" \
230
- "$SPRINT_FILE" 2>&1 >/dev/null)" || EXIT_CODE=$?
231
-
232
- assert_eq "Sc4: standalone exits non-zero when missing" "1" "$EXIT_CODE"
233
- assert_contains "Sc4: stderr lists STORY-096-02 as missing" "STORY-096-02" "$STDERR_OUT"
234
-
235
- # Now add the missing story file and re-run — should exit 0
236
- make_story_file "$TMP4" "STORY-096-02"
237
-
238
- EXIT_CODE=0
239
- STDOUT_OUT="$(CLEARGATE_REPO_ROOT="$TMP4" node "$SCRIPTS_DIR/assert_story_files.mjs" \
240
- "$SPRINT_FILE" 2>/dev/null)" || EXIT_CODE=$?
241
-
242
- assert_eq "Sc4: standalone exits 0 when all present" "0" "$EXIT_CODE"
243
- assert_contains "Sc4: stdout confirms all present" "OK:" "$STDOUT_OUT"
244
-
245
- trap - EXIT
246
- rm -rf "$TMP4"
247
-
248
- # ---------------------------------------------------------------------------
249
- echo ""
250
- echo "=== Summary ==="
251
- echo "Passed: $PASS"
252
- echo "Failed: $FAIL"
253
- if [ ${#ERRORS[@]} -gt 0 ]; then
254
- echo "Failing scenarios:"
255
- for e in "${ERRORS[@]}"; do
256
- echo " - $e"
257
- done
258
- exit 1
259
- fi
260
- echo "All tests passed."
261
- exit 0
@@ -1,210 +0,0 @@
1
- #!/usr/bin/env bash
2
- # test_file_surface.sh — Gherkin-style tests for file_surface_diff.sh
3
- # Tests all 4 scenarios from STORY-014-01 §2.1
4
- #
5
- # Usage: bash .cleargate/scripts/test/test_file_surface.sh
6
- # Exit: 0 if all pass, 1 if any fail
7
-
8
- set -euo pipefail
9
-
10
- # Navigate up 3 levels: test/ -> scripts/ -> .cleargate/ -> repo-root/
11
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
- REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
13
- SCRIPT="${REPO_ROOT}/.cleargate/scripts/file_surface_diff.sh"
14
- PASS=0
15
- FAIL=0
16
- TOTAL=0
17
-
18
- pass() { echo " PASS: $1"; PASS=$((PASS+1)); TOTAL=$((TOTAL+1)); }
19
- fail() { echo " FAIL: $1 --- $2"; FAIL=$((FAIL+1)); TOTAL=$((TOTAL+1)); }
20
-
21
- echo "REPO_ROOT: ${REPO_ROOT}"
22
- echo "SCRIPT: ${SCRIPT}"
23
- if [[ ! -f "${SCRIPT}" ]]; then
24
- echo "ERROR: file_surface_diff.sh not found at ${SCRIPT}"
25
- exit 1
26
- fi
27
-
28
- # ============================================================================
29
- # Setup helpers
30
- # ============================================================================
31
-
32
- setup_git_repo() {
33
- local dir="$1"
34
- git init -q "${dir}"
35
- git -C "${dir}" config user.email "test@test.com"
36
- git -C "${dir}" config user.name "Test"
37
- git -C "${dir}" commit -q --allow-empty -m "init"
38
- }
39
-
40
- create_story_file() {
41
- local dir="$1"
42
- shift
43
- # remaining args are file paths to declare in §3.1
44
- mkdir -p "${dir}/.cleargate/delivery/pending-sync"
45
- local story="${dir}/.cleargate/delivery/pending-sync/STORY-014-01_Test.md"
46
- {
47
- echo "---"
48
- echo "story_id: STORY-014-01"
49
- echo "---"
50
- echo ""
51
- echo "# Test Story"
52
- echo ""
53
- echo "## 3. Implementation Guide"
54
- echo ""
55
- echo "### 3.1 Context & Files"
56
- echo ""
57
- echo "| Item | Value |"
58
- echo "|---|---|"
59
- for f in "$@"; do
60
- echo "| New script | \`${f}\` |"
61
- done
62
- echo ""
63
- echo "### 3.2 Technical Logic"
64
- echo "test"
65
- } > "${story}"
66
- }
67
-
68
- create_sprint_state() {
69
- local dir="$1"
70
- local mode="${2:-v2}"
71
- mkdir -p "${dir}/.cleargate/sprint-runs/SPRINT-10"
72
- echo "SPRINT-10" > "${dir}/.cleargate/sprint-runs/.active"
73
- echo "{\"execution_mode\":\"${mode}\",\"stories\":{\"STORY-014-01\":{\"state\":\"In Progress\",\"updated_at\":\"2026-04-21T12:00:00Z\"}}}" > "${dir}/.cleargate/sprint-runs/SPRINT-10/state.json"
74
- }
75
-
76
- # ============================================================================
77
- # Scenario 1: Gate catches off-surface edit
78
- # ============================================================================
79
-
80
- echo ""
81
- echo "Scenario 1: Gate catches off-surface edit"
82
-
83
- TMPDIR1="$(mktemp -d)"
84
- setup_git_repo "${TMPDIR1}"
85
- create_story_file "${TMPDIR1}" "hello.mjs" "README.md"
86
- create_sprint_state "${TMPDIR1}" "v2"
87
-
88
- touch "${TMPDIR1}/hello.mjs" "${TMPDIR1}/README.md" "${TMPDIR1}/unrelated.txt"
89
- git -C "${TMPDIR1}" add hello.mjs README.md unrelated.txt
90
-
91
- EXIT_CODE=0
92
- STDERR_OUT="$(CLEARGATE_REPO_ROOT="${TMPDIR1}" bash "${SCRIPT}" 2>&1 >/dev/null)" || EXIT_CODE=$?
93
-
94
- if [[ "${EXIT_CODE}" -ne 0 ]]; then
95
- pass "exit code is non-zero"
96
- else
97
- fail "exit code is non-zero" "got exit 0"
98
- fi
99
-
100
- if echo "${STDERR_OUT}" | grep -q "unrelated.txt"; then
101
- pass "stderr lists unrelated.txt as off-surface"
102
- else
103
- fail "stderr lists unrelated.txt as off-surface" "stderr was: ${STDERR_OUT}"
104
- fi
105
-
106
- rm -rf "${TMPDIR1}"
107
-
108
- # ============================================================================
109
- # Scenario 2: Gate passes when staged files match surface
110
- # ============================================================================
111
-
112
- echo ""
113
- echo "Scenario 2: Gate passes when staged files match surface"
114
-
115
- TMPDIR2="$(mktemp -d)"
116
- setup_git_repo "${TMPDIR2}"
117
- create_story_file "${TMPDIR2}" "hello.mjs" "README.md"
118
- create_sprint_state "${TMPDIR2}" "v2"
119
-
120
- touch "${TMPDIR2}/hello.mjs" "${TMPDIR2}/README.md"
121
- git -C "${TMPDIR2}" add hello.mjs README.md
122
-
123
- EXIT_CODE=0
124
- CLEARGATE_REPO_ROOT="${TMPDIR2}" bash "${SCRIPT}" 2>/dev/null || EXIT_CODE=$?
125
-
126
- if [[ "${EXIT_CODE}" -eq 0 ]]; then
127
- pass "exit code is 0"
128
- else
129
- fail "exit code is 0" "got exit ${EXIT_CODE}"
130
- fi
131
-
132
- rm -rf "${TMPDIR2}"
133
-
134
- # ============================================================================
135
- # Scenario 3: Whitelist admits generated files
136
- # ============================================================================
137
-
138
- echo ""
139
- echo "Scenario 3: Whitelist admits generated files"
140
-
141
- TMPDIR3="$(mktemp -d)"
142
- setup_git_repo "${TMPDIR3}"
143
- create_story_file "${TMPDIR3}" "hello.mjs"
144
- create_sprint_state "${TMPDIR3}" "v2"
145
-
146
- mkdir -p "${TMPDIR3}/.cleargate/scripts"
147
- {
148
- echo "cleargate-planning/MANIFEST.json"
149
- echo ".cleargate/hook-log/*"
150
- } > "${TMPDIR3}/.cleargate/scripts/surface-whitelist.txt"
151
-
152
- touch "${TMPDIR3}/hello.mjs"
153
- mkdir -p "${TMPDIR3}/cleargate-planning"
154
- touch "${TMPDIR3}/cleargate-planning/MANIFEST.json"
155
- git -C "${TMPDIR3}" add hello.mjs cleargate-planning/MANIFEST.json
156
-
157
- EXIT_CODE=0
158
- CLEARGATE_REPO_ROOT="${TMPDIR3}" bash "${SCRIPT}" 2>/dev/null || EXIT_CODE=$?
159
-
160
- if [[ "${EXIT_CODE}" -eq 0 ]]; then
161
- pass "MANIFEST.json not flagged (whitelisted)"
162
- else
163
- fail "MANIFEST.json not flagged (whitelisted)" "got exit ${EXIT_CODE}"
164
- fi
165
-
166
- rm -rf "${TMPDIR3}"
167
-
168
- # ============================================================================
169
- # Scenario 4: v1 mode is advisory
170
- # ============================================================================
171
-
172
- echo ""
173
- echo "Scenario 4: v1 mode is advisory"
174
-
175
- TMPDIR4="$(mktemp -d)"
176
- setup_git_repo "${TMPDIR4}"
177
- create_story_file "${TMPDIR4}" "hello.mjs"
178
- create_sprint_state "${TMPDIR4}" "v1"
179
-
180
- touch "${TMPDIR4}/hello.mjs" "${TMPDIR4}/unrelated.txt"
181
- git -C "${TMPDIR4}" add hello.mjs unrelated.txt
182
-
183
- EXIT_CODE=0
184
- STDERR_OUT="$(CLEARGATE_REPO_ROOT="${TMPDIR4}" bash "${SCRIPT}" 2>&1 >/dev/null)" || EXIT_CODE=$?
185
-
186
- if [[ "${EXIT_CODE}" -eq 0 ]]; then
187
- pass "v1 mode exits 0 (advisory)"
188
- else
189
- fail "v1 mode exits 0" "got exit ${EXIT_CODE}"
190
- fi
191
-
192
- if echo "${STDERR_OUT}" | grep -qi "warning"; then
193
- pass "v1 mode prints warning"
194
- else
195
- fail "v1 mode prints warning" "stderr was: ${STDERR_OUT}"
196
- fi
197
-
198
- rm -rf "${TMPDIR4}"
199
-
200
- # ============================================================================
201
- # Summary
202
- # ============================================================================
203
-
204
- echo ""
205
- echo "Results: ${PASS}/${TOTAL} passed, ${FAIL} failed"
206
-
207
- if [[ "${FAIL}" -gt 0 ]]; then
208
- exit 1
209
- fi
210
- exit 0
@@ -1,190 +0,0 @@
1
- #!/usr/bin/env bash
2
- # test_flashcard_gate.sh — STORY-013-06: Immediate Flashcard Hard-Gate
3
- # Gherkin scenario: "Gate blocks next worktree creation until flashcards processed"
4
- #
5
- # Strategy: grep-based. Creates a synthetic dev-report fixture with
6
- # flashcards_flagged, simulates a mock worktree-creation step, and asserts
7
- # the gate contract documented in protocol §18 and the agent output-shape
8
- # blocks in developer.md + qa.md.
9
- #
10
- # Usage: bash .cleargate/scripts/test/test_flashcard_gate.sh
11
- # Exit: 0 if all assertions pass, 1 on first failure.
12
-
13
- set -euo pipefail
14
-
15
- REPO_ROOT="${CLEARGATE_REPO_ROOT:-$(cd "$(dirname "$0")/../../.." && pwd)}"
16
- PASS=0
17
- FAIL=0
18
-
19
- pass() { echo "PASS: $1"; PASS=$((PASS + 1)); }
20
- fail() { echo "FAIL: $1"; FAIL=$((FAIL + 1)); }
21
-
22
- # ---------------------------------------------------------------------------
23
- # Scenario: Gate blocks next worktree creation until flashcards processed
24
- # ---------------------------------------------------------------------------
25
- # §2.1 Gherkin from STORY-013-06:
26
- # Given STORY-014-05 has just merged into sprint/S-XX
27
- # And STORY-014-05-dev.md has flashcards_flagged: [...]
28
- # When the orchestrator attempts to create .worktrees/STORY-014-06/
29
- # Then the gate presents each flagged flashcard to the user for approval
30
- # And upon approval each card is appended to .cleargate/FLASHCARD.md
31
- # And only then does worktree creation proceed
32
- #
33
- # This script validates the contract (protocol §18 + output-shape fields)
34
- # that makes the scenario enforceable. The gate logic itself is orchestrator-
35
- # out-of-band (v1: informational; v2: mandatory). The test therefore checks:
36
- # (a) developer.md output-shape contains flashcards_flagged field
37
- # (b) qa.md output-shape contains flashcards_flagged field
38
- # (c) protocol.md §18 exists with the correct heading
39
- # (d) §18 specifies the approve/reject processing rule
40
- # (e) §18 specifies the worktree creation gate
41
- # (f) live vs mirror diff is empty for all three files
42
-
43
- DEV_MD="$REPO_ROOT/.claude/agents/developer.md"
44
- QA_MD="$REPO_ROOT/.claude/agents/qa.md"
45
- PROTOCOL_MD="$REPO_ROOT/.cleargate/knowledge/cleargate-protocol.md"
46
-
47
- PLANNING_DEV_MD="$REPO_ROOT/cleargate-planning/.claude/agents/developer.md"
48
- PLANNING_QA_MD="$REPO_ROOT/cleargate-planning/.claude/agents/qa.md"
49
- PLANNING_PROTOCOL_MD="$REPO_ROOT/cleargate-planning/.cleargate/knowledge/cleargate-protocol.md"
50
-
51
- # (a) developer.md has flashcards_flagged in output-shape block
52
- if grep -q "flashcards_flagged:" "$DEV_MD"; then
53
- pass "developer.md output-shape contains flashcards_flagged field"
54
- else
55
- fail "developer.md missing flashcards_flagged field in output-shape"
56
- fi
57
-
58
- # (b) qa.md has flashcards_flagged in output-shape block
59
- if grep -q "flashcards_flagged:" "$QA_MD"; then
60
- pass "qa.md output-shape contains flashcards_flagged field"
61
- else
62
- fail "qa.md missing flashcards_flagged field in output-shape"
63
- fi
64
-
65
- # (c) protocol.md §18 heading exists
66
- if grep -q "^## 18. Immediate Flashcard Gate (v2)" "$PROTOCOL_MD"; then
67
- pass "protocol.md contains ## 18. Immediate Flashcard Gate (v2)"
68
- else
69
- fail "protocol.md missing ## 18. Immediate Flashcard Gate (v2)"
70
- fi
71
-
72
- # (d) §18 specifies approve + reject processing
73
- if grep -q "Approve" "$PROTOCOL_MD" && grep -q "Reject" "$PROTOCOL_MD"; then
74
- pass "protocol §18 documents Approve/Reject processing rule"
75
- else
76
- fail "protocol §18 missing Approve/Reject processing rule"
77
- fi
78
-
79
- # (e) §18 specifies the worktree creation gate
80
- if grep -q "Worktree creation gate\|worktree creation gate\|MUST NOT.*worktree\|worktree.*MUST NOT" "$PROTOCOL_MD"; then
81
- pass "protocol §18 documents worktree creation gate"
82
- else
83
- fail "protocol §18 missing worktree creation gate rule"
84
- fi
85
-
86
- # (f) qa.md says QA list is additive to Developer's
87
- if grep -q "additive" "$QA_MD"; then
88
- pass "qa.md notes that flashcards_flagged list is additive to Developer's"
89
- else
90
- fail "qa.md missing note that flashcards_flagged is additive"
91
- fi
92
-
93
- # (g) developer.md references protocol §18
94
- if grep -q "protocol §18\|§18" "$DEV_MD"; then
95
- pass "developer.md references protocol §18"
96
- else
97
- fail "developer.md does not reference protocol §18"
98
- fi
99
-
100
- # (h) qa.md references protocol §18
101
- if grep -q "protocol §18\|§18" "$QA_MD"; then
102
- pass "qa.md references protocol §18"
103
- else
104
- fail "qa.md does not reference protocol §18"
105
- fi
106
-
107
- # (i) three-surface diff: live developer.md vs mirror
108
- if diff -q "$DEV_MD" "$PLANNING_DEV_MD" > /dev/null 2>&1; then
109
- pass "developer.md live vs mirror diff is empty"
110
- else
111
- fail "developer.md live vs mirror diff is NOT empty"
112
- fi
113
-
114
- # (j) three-surface diff: live qa.md vs mirror
115
- if diff -q "$QA_MD" "$PLANNING_QA_MD" > /dev/null 2>&1; then
116
- pass "qa.md live vs mirror diff is empty"
117
- else
118
- fail "qa.md live vs mirror diff is NOT empty"
119
- fi
120
-
121
- # (k) three-surface diff: live protocol.md vs mirror
122
- if diff -q "$PROTOCOL_MD" "$PLANNING_PROTOCOL_MD" > /dev/null 2>&1; then
123
- pass "cleargate-protocol.md live vs mirror diff is empty"
124
- else
125
- fail "cleargate-protocol.md live vs mirror diff is NOT empty"
126
- fi
127
-
128
- # (l) synthetic fixture: dev report with flashcards_flagged triggers gate
129
- # Simulate: write a temp dev report with flashcards_flagged, grep for it
130
- TMPDIR_FIXTURE="$(mktemp -d)"
131
- trap 'rm -rf "$TMPDIR_FIXTURE"' EXIT
132
-
133
- cat > "$TMPDIR_FIXTURE/STORY-014-05-dev.md" << 'FIXTURE'
134
- STORY: STORY-014-05
135
- STATUS: done
136
- COMMIT: abc1234
137
- TYPECHECK: pass
138
- TESTS: 5 passed, 0 failed
139
- FILES_CHANGED: src/foo.ts
140
- NOTES: all green
141
- flashcards_flagged:
142
- - "2026-04-22 · #test-harness · vitest fake-timers conflict with worker.spawn"
143
- FIXTURE
144
-
145
- # Assert the fixture has the flashcard entry
146
- if grep -q "flashcards_flagged:" "$TMPDIR_FIXTURE/STORY-014-05-dev.md"; then
147
- pass "synthetic dev-report fixture contains flashcards_flagged field"
148
- else
149
- fail "synthetic dev-report fixture missing flashcards_flagged field"
150
- fi
151
-
152
- # Assert extraction of the flagged card matches the FLASHCARD.md format
153
- EXTRACTED=$(grep -A1 "flashcards_flagged:" "$TMPDIR_FIXTURE/STORY-014-05-dev.md" | tail -1 | sed 's/^[[:space:]]*- "//' | sed 's/"$//')
154
- if echo "$EXTRACTED" | grep -qE "^[0-9]{4}-[0-9]{2}-[0-9]{2} · #[a-z-]+ · .+"; then
155
- pass "extracted flashcard matches YYYY-MM-DD · #tag · lesson format"
156
- else
157
- fail "extracted flashcard does NOT match expected format: '$EXTRACTED'"
158
- fi
159
-
160
- # Mock worktree guard: confirm the gate would block by checking the field is non-empty
161
- FLAGGED_COUNT=$(grep -c " - " "$TMPDIR_FIXTURE/STORY-014-05-dev.md" || true)
162
- if [ "$FLAGGED_COUNT" -gt 0 ]; then
163
- pass "gate detects non-empty flashcards_flagged — worktree creation would be blocked"
164
- else
165
- fail "gate failed to detect non-empty flashcards_flagged list"
166
- fi
167
-
168
- # Mock approval: append to a temp FLASHCARD.md and confirm it was written
169
- TEMP_FLASHCARD="$TMPDIR_FIXTURE/FLASHCARD.md"
170
- echo "# ClearGate Flashcards" > "$TEMP_FLASHCARD"
171
- echo "" >> "$TEMP_FLASHCARD"
172
- echo "$EXTRACTED" >> "$TEMP_FLASHCARD"
173
-
174
- if grep -q "vitest fake-timers conflict" "$TEMP_FLASHCARD"; then
175
- pass "approved flashcard appended to FLASHCARD.md mock"
176
- else
177
- fail "approved flashcard NOT found in FLASHCARD.md mock"
178
- fi
179
-
180
- # ---------------------------------------------------------------------------
181
- # Summary
182
- # ---------------------------------------------------------------------------
183
- TOTAL=$((PASS + FAIL))
184
- echo ""
185
- echo "Results: $PASS/$TOTAL passed"
186
-
187
- if [ "$FAIL" -gt 0 ]; then
188
- exit 1
189
- fi
190
- exit 0