@lvlup-sw/exarchos 2.0.1

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 (153) hide show
  1. package/.claude-plugin/marketplace.json +22 -0
  2. package/.claude-plugin/plugin.json +17 -0
  3. package/.mcp.json +17 -0
  4. package/AGENTS.md +59 -0
  5. package/CLAUDE.md.template +62 -0
  6. package/LICENSE +202 -0
  7. package/README.md +258 -0
  8. package/commands/autocompact.md +37 -0
  9. package/commands/checkpoint.md +85 -0
  10. package/commands/cleanup.md +99 -0
  11. package/commands/debug.md +145 -0
  12. package/commands/delegate.md +56 -0
  13. package/commands/ideate.md +82 -0
  14. package/commands/plan.md +150 -0
  15. package/commands/refactor.md +139 -0
  16. package/commands/reload.md +37 -0
  17. package/commands/resume.md +130 -0
  18. package/commands/review.md +51 -0
  19. package/commands/sync-schemas.md +74 -0
  20. package/commands/synthesize.md +122 -0
  21. package/commands/tdd.md +58 -0
  22. package/dist/exarchos-cli.js +8828 -0
  23. package/dist/exarchos-mcp.js +50 -0
  24. package/hooks/hooks.json +53 -0
  25. package/package.json +59 -0
  26. package/rules/coding-standards.md +46 -0
  27. package/rules/mcp-tool-guidance.md +26 -0
  28. package/rules/pr-descriptions.md +12 -0
  29. package/rules/rm-safety.md +9 -0
  30. package/rules/skill-path-resolution.md +10 -0
  31. package/rules/tdd.md +41 -0
  32. package/rules/telemetry-awareness.md +9 -0
  33. package/scripts/assess-refactor-scope.sh +239 -0
  34. package/scripts/check-benchmark-regression.sh +229 -0
  35. package/scripts/check-coderabbit.sh +288 -0
  36. package/scripts/check-coverage-thresholds.sh +194 -0
  37. package/scripts/check-polish-scope.sh +245 -0
  38. package/scripts/check-property-tests.sh +167 -0
  39. package/scripts/check-tdd-compliance.sh +265 -0
  40. package/scripts/coderabbit-review-gate.sh +518 -0
  41. package/scripts/debug-review-gate.sh +201 -0
  42. package/scripts/extract-fix-tasks.sh +179 -0
  43. package/scripts/extract-task.sh +67 -0
  44. package/scripts/generate-traceability.sh +209 -0
  45. package/scripts/investigation-timer.sh +171 -0
  46. package/scripts/needs-schema-sync.sh +174 -0
  47. package/scripts/new-project.sh +103 -0
  48. package/scripts/post-delegation-check.sh +317 -0
  49. package/scripts/pre-synthesis-check.sh +440 -0
  50. package/scripts/reconcile-state.sh +346 -0
  51. package/scripts/reconstruct-stack.sh +432 -0
  52. package/scripts/review-diff.sh +63 -0
  53. package/scripts/review-verdict.sh +169 -0
  54. package/scripts/security-scan.sh +248 -0
  55. package/scripts/select-debug-track.sh +186 -0
  56. package/scripts/setup-worktree.sh +323 -0
  57. package/scripts/spec-coverage-check.sh +230 -0
  58. package/scripts/static-analysis-gate.sh +236 -0
  59. package/scripts/sync-labels.sh +122 -0
  60. package/scripts/validate-companion.sh +161 -0
  61. package/scripts/validate-dotnet-standards.sh +267 -0
  62. package/scripts/validate-installation.sh +101 -0
  63. package/scripts/validate-plugin.sh +223 -0
  64. package/scripts/validate-refactor.sh +234 -0
  65. package/scripts/validate-rm.sh +93 -0
  66. package/scripts/verify-delegation-saga.sh +240 -0
  67. package/scripts/verify-doc-links.sh +211 -0
  68. package/scripts/verify-ideate-artifacts.sh +296 -0
  69. package/scripts/verify-plan-coverage.sh +228 -0
  70. package/scripts/verify-review-triage.sh +219 -0
  71. package/scripts/verify-worktree-baseline.sh +159 -0
  72. package/scripts/verify-worktree.sh +84 -0
  73. package/settings.json +47 -0
  74. package/skills/brainstorming/SKILL.md +127 -0
  75. package/skills/brainstorming/references/design-template.md +65 -0
  76. package/skills/cleanup/SKILL.md +147 -0
  77. package/skills/cleanup/references/merge-verification.md +40 -0
  78. package/skills/debug/SKILL.md +204 -0
  79. package/skills/debug/references/hotfix-track.md +134 -0
  80. package/skills/debug/references/investigation-checklist.md +217 -0
  81. package/skills/debug/references/rca-template.md +150 -0
  82. package/skills/debug/references/state-schema.md +294 -0
  83. package/skills/debug/references/thorough-track.md +194 -0
  84. package/skills/debug/references/triage-questions.md +155 -0
  85. package/skills/debug/references/troubleshooting.md +47 -0
  86. package/skills/delegation/SKILL.md +150 -0
  87. package/skills/delegation/references/adaptive-orchestration.md +31 -0
  88. package/skills/delegation/references/agent-teams-saga.md +248 -0
  89. package/skills/delegation/references/fix-mode.md +74 -0
  90. package/skills/delegation/references/fixer-prompt.md +162 -0
  91. package/skills/delegation/references/implementer-prompt.md +322 -0
  92. package/skills/delegation/references/parallel-strategy.md +124 -0
  93. package/skills/delegation/references/pbt-patterns.md +172 -0
  94. package/skills/delegation/references/pr-fixes-mode.md +154 -0
  95. package/skills/delegation/references/state-management.md +51 -0
  96. package/skills/delegation/references/testing-patterns.md +129 -0
  97. package/skills/delegation/references/troubleshooting.md +33 -0
  98. package/skills/delegation/references/workflow-steps.md +127 -0
  99. package/skills/delegation/references/worktree-enforcement.md +64 -0
  100. package/skills/dotnet-standards/SKILL.md +269 -0
  101. package/skills/dotnet-standards/references/csharp-standards.md +120 -0
  102. package/skills/dotnet-standards/templates/.editorconfig +366 -0
  103. package/skills/dotnet-standards/templates/Directory.Build.props +56 -0
  104. package/skills/dotnet-standards/templates/Directory.Packages.props +69 -0
  105. package/skills/dotnet-standards/templates/global.json +6 -0
  106. package/skills/dotnet-standards/templates/nuget.config +9 -0
  107. package/skills/dotnet-standards/templates/stylecop.json +37 -0
  108. package/skills/git-worktrees/SKILL.md +255 -0
  109. package/skills/implementation-planning/SKILL.md +233 -0
  110. package/skills/implementation-planning/references/plan-document-template.md +42 -0
  111. package/skills/implementation-planning/references/spec-tracing-guide.md +51 -0
  112. package/skills/implementation-planning/references/task-template.md +43 -0
  113. package/skills/implementation-planning/references/testing-strategy-guide.md +88 -0
  114. package/skills/quality-review/SKILL.md +278 -0
  115. package/skills/quality-review/references/code-quality-checklist.md +159 -0
  116. package/skills/quality-review/references/review-report-template.md +65 -0
  117. package/skills/quality-review/references/security-checklist.md +79 -0
  118. package/skills/quality-review/references/typescript-standards.md +24 -0
  119. package/skills/refactor/COMMAND.md +67 -0
  120. package/skills/refactor/SKILL.md +198 -0
  121. package/skills/refactor/phases/auto-chain.md +262 -0
  122. package/skills/refactor/phases/brief.md +176 -0
  123. package/skills/refactor/phases/explore.md +132 -0
  124. package/skills/refactor/phases/overhaul-delegate.md +136 -0
  125. package/skills/refactor/phases/overhaul-plan.md +312 -0
  126. package/skills/refactor/phases/overhaul-review.md +304 -0
  127. package/skills/refactor/phases/polish-implement.md +349 -0
  128. package/skills/refactor/phases/polish-validate.md +218 -0
  129. package/skills/refactor/phases/update-docs.md +234 -0
  130. package/skills/refactor/references/brief-template.md +81 -0
  131. package/skills/refactor/references/doc-update-checklist.md +110 -0
  132. package/skills/refactor/references/explore-checklist.md +73 -0
  133. package/skills/refactor/references/overhaul-track.md +215 -0
  134. package/skills/refactor/references/polish-track.md +170 -0
  135. package/skills/shared/prompts/context-reading.md +58 -0
  136. package/skills/shared/prompts/report-format.md +54 -0
  137. package/skills/shared/prompts/tdd-requirements.md +39 -0
  138. package/skills/shepherd/SKILL.md +264 -0
  139. package/skills/shepherd/references/assess-checklist.md +124 -0
  140. package/skills/shepherd/references/fix-strategies.md +191 -0
  141. package/skills/spec-review/SKILL.md +229 -0
  142. package/skills/spec-review/references/review-checklist.md +60 -0
  143. package/skills/sync-schemas/SKILL.md +114 -0
  144. package/skills/sync-schemas/references/configuration.md +73 -0
  145. package/skills/synthesis/SKILL.md +129 -0
  146. package/skills/synthesis/references/pr-descriptions.md +87 -0
  147. package/skills/synthesis/references/synthesis-steps.md +109 -0
  148. package/skills/synthesis/references/troubleshooting.md +115 -0
  149. package/skills/validate-all-skills.sh +57 -0
  150. package/skills/validate-frontmatter.sh +237 -0
  151. package/skills/workflow-state/SKILL.md +210 -0
  152. package/skills/workflow-state/references/mcp-tool-reference.md +111 -0
  153. package/skills/workflow-state/references/phase-transitions.md +141 -0
@@ -0,0 +1,323 @@
1
+ #!/usr/bin/env bash
2
+ # setup-worktree.sh — Atomic worktree creation with validation
3
+ # Replaces the "Pre-Dispatch Checklist" prose in delegation SKILL.md.
4
+ #
5
+ # Usage: setup-worktree.sh --repo-root <path> --task-id <id> --task-name <name> [--base-branch main] [--skip-tests]
6
+ #
7
+ # Exit codes:
8
+ # 0 = worktree ready
9
+ # 1 = setup failed
10
+ # 2 = usage error (missing required args)
11
+
12
+ set -euo pipefail
13
+
14
+ # ============================================================
15
+ # ARGUMENT PARSING
16
+ # ============================================================
17
+
18
+ REPO_ROOT=""
19
+ TASK_ID=""
20
+ TASK_NAME=""
21
+ BASE_BRANCH="main"
22
+ SKIP_TESTS=false
23
+
24
+ usage() {
25
+ cat << 'USAGE'
26
+ Usage: setup-worktree.sh --repo-root <path> --task-id <id> --task-name <name> [--base-branch main] [--skip-tests]
27
+
28
+ Required:
29
+ --repo-root <path> Repository root directory
30
+ --task-id <id> Task identifier (e.g., task-001)
31
+ --task-name <name> Task name slug (e.g., user-model)
32
+
33
+ Optional:
34
+ --base-branch <name> Base branch to create from (default: main)
35
+ --skip-tests Skip baseline test verification
36
+ --help Show this help message
37
+
38
+ Exit codes:
39
+ 0 Worktree ready
40
+ 1 Setup failed
41
+ 2 Usage error (missing required args)
42
+ USAGE
43
+ }
44
+
45
+ while [[ $# -gt 0 ]]; do
46
+ case "$1" in
47
+ --repo-root)
48
+ if [[ -z "${2:-}" ]]; then
49
+ echo "Error: --repo-root requires a path argument" >&2
50
+ exit 2
51
+ fi
52
+ REPO_ROOT="$2"
53
+ shift 2
54
+ ;;
55
+ --task-id)
56
+ if [[ -z "${2:-}" ]]; then
57
+ echo "Error: --task-id requires an argument" >&2
58
+ exit 2
59
+ fi
60
+ TASK_ID="$2"
61
+ shift 2
62
+ ;;
63
+ --task-name)
64
+ if [[ -z "${2:-}" ]]; then
65
+ echo "Error: --task-name requires an argument" >&2
66
+ exit 2
67
+ fi
68
+ TASK_NAME="$2"
69
+ shift 2
70
+ ;;
71
+ --base-branch)
72
+ if [[ -z "${2:-}" ]]; then
73
+ echo "Error: --base-branch requires an argument" >&2
74
+ exit 2
75
+ fi
76
+ BASE_BRANCH="$2"
77
+ shift 2
78
+ ;;
79
+ --skip-tests)
80
+ SKIP_TESTS=true
81
+ shift
82
+ ;;
83
+ --help)
84
+ usage
85
+ exit 0
86
+ ;;
87
+ *)
88
+ echo "Error: Unknown argument '$1'" >&2
89
+ usage >&2
90
+ exit 2
91
+ ;;
92
+ esac
93
+ done
94
+
95
+ if [[ -z "$REPO_ROOT" ]]; then
96
+ echo "Error: --repo-root is required" >&2
97
+ usage >&2
98
+ exit 2
99
+ fi
100
+
101
+ if [[ -z "$TASK_ID" ]]; then
102
+ echo "Error: --task-id is required" >&2
103
+ usage >&2
104
+ exit 2
105
+ fi
106
+
107
+ if [[ -z "$TASK_NAME" ]]; then
108
+ echo "Error: --task-name is required" >&2
109
+ usage >&2
110
+ exit 2
111
+ fi
112
+
113
+ # ============================================================
114
+ # DERIVED VALUES
115
+ # ============================================================
116
+
117
+ WORKTREE_NAME="${TASK_ID}-${TASK_NAME}"
118
+ BRANCH_NAME="feature/${WORKTREE_NAME}"
119
+ WORKTREE_PATH="$REPO_ROOT/.worktrees/$WORKTREE_NAME"
120
+
121
+ # ============================================================
122
+ # CHECK FUNCTIONS
123
+ # ============================================================
124
+
125
+ CHECK_PASS=0
126
+ CHECK_FAIL=0
127
+ RESULTS=()
128
+
129
+ check_pass() {
130
+ local name="$1"
131
+ RESULTS+=("- **PASS**: $name")
132
+ CHECK_PASS=$((CHECK_PASS + 1))
133
+ }
134
+
135
+ check_fail() {
136
+ local name="$1"
137
+ local detail="${2:-}"
138
+ if [[ -n "$detail" ]]; then
139
+ RESULTS+=("- **FAIL**: $name — $detail")
140
+ else
141
+ RESULTS+=("- **FAIL**: $name")
142
+ fi
143
+ CHECK_FAIL=$((CHECK_FAIL + 1))
144
+ }
145
+
146
+ check_skip() {
147
+ local name="$1"
148
+ RESULTS+=("- **SKIP**: $name")
149
+ }
150
+
151
+ # ============================================================
152
+ # STEP 1: Ensure .worktrees is gitignored
153
+ # ============================================================
154
+
155
+ ensure_gitignored() {
156
+ # git check-ignore requires trailing slash for directory patterns
157
+ if (cd "$REPO_ROOT" && git check-ignore -q .worktrees/) 2>/dev/null; then
158
+ check_pass ".worktrees is gitignored"
159
+ return 0
160
+ fi
161
+
162
+ # Add to .gitignore
163
+ local gitignore="$REPO_ROOT/.gitignore"
164
+ if [[ -f "$gitignore" ]]; then
165
+ echo ".worktrees/" >> "$gitignore"
166
+ else
167
+ echo ".worktrees/" > "$gitignore"
168
+ fi
169
+
170
+ # Verify it worked
171
+ if (cd "$REPO_ROOT" && git check-ignore -q .worktrees/) 2>/dev/null; then
172
+ check_pass ".worktrees is gitignored (added to .gitignore)"
173
+ return 0
174
+ else
175
+ check_fail ".worktrees is gitignored" "Failed to add to .gitignore"
176
+ return 1
177
+ fi
178
+ }
179
+
180
+ # ============================================================
181
+ # STEP 2: Create feature branch
182
+ # ============================================================
183
+
184
+ create_branch() {
185
+ # Check if branch already exists
186
+ if git -C "$REPO_ROOT" show-ref --verify --quiet "refs/heads/$BRANCH_NAME" 2>/dev/null; then
187
+ check_pass "Branch created ($BRANCH_NAME already exists)"
188
+ return 0
189
+ fi
190
+
191
+ if git -C "$REPO_ROOT" branch "$BRANCH_NAME" "$BASE_BRANCH" 2>/dev/null; then
192
+ check_pass "Branch created ($BRANCH_NAME from $BASE_BRANCH)"
193
+ return 0
194
+ else
195
+ check_fail "Branch created" "Failed to create $BRANCH_NAME from $BASE_BRANCH"
196
+ return 1
197
+ fi
198
+ }
199
+
200
+ # ============================================================
201
+ # STEP 3: Create worktree
202
+ # ============================================================
203
+
204
+ create_worktree() {
205
+ # Check if worktree already exists
206
+ if [[ -d "$WORKTREE_PATH" ]]; then
207
+ # Verify it's a valid worktree
208
+ if git -C "$WORKTREE_PATH" rev-parse --git-dir &>/dev/null; then
209
+ check_pass "Worktree created ($WORKTREE_PATH already exists)"
210
+ return 0
211
+ else
212
+ check_fail "Worktree created" "$WORKTREE_PATH exists but is not a valid worktree"
213
+ return 1
214
+ fi
215
+ fi
216
+
217
+ if git -C "$REPO_ROOT" worktree add "$WORKTREE_PATH" "$BRANCH_NAME" 2>/dev/null; then
218
+ check_pass "Worktree created ($WORKTREE_PATH)"
219
+ return 0
220
+ else
221
+ check_fail "Worktree created" "git worktree add failed for $WORKTREE_PATH"
222
+ return 1
223
+ fi
224
+ }
225
+
226
+ # ============================================================
227
+ # STEP 4: Run npm install
228
+ # ============================================================
229
+
230
+ run_npm_install() {
231
+ # Only run if package.json exists in worktree
232
+ if [[ ! -f "$WORKTREE_PATH/package.json" ]]; then
233
+ check_skip "npm install (no package.json in worktree)"
234
+ return 0
235
+ fi
236
+
237
+ if (cd "$WORKTREE_PATH" && npm install --silent 2>/dev/null); then
238
+ check_pass "npm install completed"
239
+ return 0
240
+ else
241
+ check_fail "npm install completed" "npm install failed in $WORKTREE_PATH"
242
+ return 1
243
+ fi
244
+ }
245
+
246
+ # ============================================================
247
+ # STEP 5: Baseline tests
248
+ # ============================================================
249
+
250
+ run_baseline_tests() {
251
+ if [[ "$SKIP_TESTS" == true ]]; then
252
+ check_skip "Baseline tests pass (--skip-tests)"
253
+ return 0
254
+ fi
255
+
256
+ if [[ ! -f "$WORKTREE_PATH/package.json" ]]; then
257
+ check_skip "Baseline tests pass (no package.json in worktree)"
258
+ return 0
259
+ fi
260
+
261
+ if (cd "$WORKTREE_PATH" && npm run test:run 2>/dev/null); then
262
+ check_pass "Baseline tests pass"
263
+ return 0
264
+ else
265
+ check_fail "Baseline tests pass" "npm run test:run failed in $WORKTREE_PATH"
266
+ return 1
267
+ fi
268
+ }
269
+
270
+ # ============================================================
271
+ # EXECUTE STEPS
272
+ # ============================================================
273
+
274
+ # Step 1: Gitignore
275
+ ensure_gitignored || true
276
+
277
+ # Step 2: Branch (depends on step 1 not fatally failing)
278
+ create_branch || true
279
+
280
+ # Step 3: Worktree (depends on branch existing)
281
+ create_worktree || true
282
+
283
+ # Step 4: npm install (depends on worktree existing)
284
+ if [[ -d "$WORKTREE_PATH" ]]; then
285
+ run_npm_install || true
286
+ else
287
+ check_skip "npm install (worktree not available)"
288
+ fi
289
+
290
+ # Step 5: Baseline tests (depends on npm install)
291
+ if [[ -d "$WORKTREE_PATH" ]]; then
292
+ run_baseline_tests || true
293
+ else
294
+ check_skip "Baseline tests pass (worktree not available)"
295
+ fi
296
+
297
+ # ============================================================
298
+ # STRUCTURED OUTPUT
299
+ # ============================================================
300
+
301
+ echo "## Worktree Setup Report"
302
+ echo ""
303
+ echo "**Task:** \`$TASK_ID\` — $TASK_NAME"
304
+ echo "**Branch:** \`$BRANCH_NAME\`"
305
+ echo "**Worktree:** \`$WORKTREE_PATH\`"
306
+ echo ""
307
+
308
+ for result in "${RESULTS[@]}"; do
309
+ echo "$result"
310
+ done
311
+
312
+ echo ""
313
+ TOTAL=$((CHECK_PASS + CHECK_FAIL))
314
+ echo "---"
315
+ echo ""
316
+
317
+ if [[ $CHECK_FAIL -eq 0 ]]; then
318
+ echo "**Result: PASS** ($CHECK_PASS/$TOTAL checks passed)"
319
+ exit 0
320
+ else
321
+ echo "**Result: FAIL** ($CHECK_FAIL/$TOTAL checks failed)"
322
+ exit 1
323
+ fi
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env bash
2
+ # Spec Coverage Check
3
+ # Verify test coverage for spec compliance. Replaces spec-review "Compare to Spec" prose.
4
+ #
5
+ # Usage: spec-coverage-check.sh --plan-file <path> --repo-root <path> [--skip-run]
6
+ #
7
+ # Exit codes:
8
+ # 0 = coverage met (all planned tests exist and pass)
9
+ # 1 = gaps found (missing test files or test failures)
10
+ # 2 = usage error (missing required args)
11
+
12
+ set -euo pipefail
13
+
14
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
+
16
+ # Colors
17
+ RED='\033[0;31m'
18
+ GREEN='\033[0;32m'
19
+ YELLOW='\033[1;33m'
20
+ NC='\033[0m'
21
+
22
+ # ============================================================
23
+ # ARGUMENT PARSING
24
+ # ============================================================
25
+
26
+ PLAN_FILE=""
27
+ REPO_ROOT=""
28
+ SKIP_RUN=false
29
+
30
+ usage() {
31
+ cat << 'USAGE'
32
+ Usage: spec-coverage-check.sh --plan-file <path> --repo-root <path> [--skip-run]
33
+
34
+ Required:
35
+ --plan-file <path> Path to the implementation plan markdown file
36
+ --repo-root <path> Repository root directory
37
+
38
+ Optional:
39
+ --skip-run Skip running tests (only check file existence)
40
+ --help Show this help message
41
+
42
+ Exit codes:
43
+ 0 Coverage met (all planned tests exist and pass)
44
+ 1 Gaps found (missing test files or test failures)
45
+ 2 Usage error (missing required args)
46
+ USAGE
47
+ }
48
+
49
+ while [[ $# -gt 0 ]]; do
50
+ case "$1" in
51
+ --plan-file)
52
+ if [[ -z "${2:-}" ]]; then
53
+ echo "Error: --plan-file requires a path argument" >&2
54
+ exit 2
55
+ fi
56
+ PLAN_FILE="$2"
57
+ shift 2
58
+ ;;
59
+ --repo-root)
60
+ if [[ -z "${2:-}" ]]; then
61
+ echo "Error: --repo-root requires a path argument" >&2
62
+ exit 2
63
+ fi
64
+ REPO_ROOT="$2"
65
+ shift 2
66
+ ;;
67
+ --skip-run)
68
+ SKIP_RUN=true
69
+ shift
70
+ ;;
71
+ --help)
72
+ usage
73
+ exit 0
74
+ ;;
75
+ *)
76
+ echo "Error: Unknown argument '$1'" >&2
77
+ usage >&2
78
+ exit 2
79
+ ;;
80
+ esac
81
+ done
82
+
83
+ if [[ -z "$PLAN_FILE" || -z "$REPO_ROOT" ]]; then
84
+ echo "Error: --plan-file and --repo-root are required" >&2
85
+ usage >&2
86
+ exit 2
87
+ fi
88
+
89
+ if [[ ! -f "$PLAN_FILE" ]]; then
90
+ echo "Error: Plan file not found: $PLAN_FILE" >&2
91
+ exit 2
92
+ fi
93
+
94
+ if [[ ! -d "$REPO_ROOT" ]]; then
95
+ echo "Error: Repo root directory not found: $REPO_ROOT" >&2
96
+ exit 2
97
+ fi
98
+
99
+ # ============================================================
100
+ # CHECK FUNCTIONS
101
+ # ============================================================
102
+
103
+ CHECK_PASS=0
104
+ CHECK_FAIL=0
105
+ RESULTS=()
106
+
107
+ check_pass() {
108
+ local name="$1"
109
+ RESULTS+=("- **PASS**: $name")
110
+ CHECK_PASS=$((CHECK_PASS + 1))
111
+ }
112
+
113
+ check_fail() {
114
+ local name="$1"
115
+ local detail="${2:-}"
116
+ if [[ -n "$detail" ]]; then
117
+ RESULTS+=("- **FAIL**: $name — $detail")
118
+ else
119
+ RESULTS+=("- **FAIL**: $name")
120
+ fi
121
+ CHECK_FAIL=$((CHECK_FAIL + 1))
122
+ }
123
+
124
+ check_skip() {
125
+ local name="$1"
126
+ RESULTS+=("- **SKIP**: $name")
127
+ }
128
+
129
+ # ============================================================
130
+ # EXTRACT TEST FILES FROM PLAN
131
+ # ============================================================
132
+
133
+ # Extract test file paths from **Test file:** lines in the plan
134
+ TEST_FILES=()
135
+ while IFS= read -r line; do
136
+ # Match lines like: **Test file:** `src/widget.test.ts`
137
+ if [[ "$line" =~ \*\*Test\ file:\*\*[[:space:]]*\`([^\`]+)\` ]]; then
138
+ TEST_FILES+=("${BASH_REMATCH[1]}")
139
+ fi
140
+ done < "$PLAN_FILE"
141
+
142
+ # ============================================================
143
+ # CHECK: Test files referenced in plan
144
+ # ============================================================
145
+
146
+ if [[ ${#TEST_FILES[@]} -eq 0 ]]; then
147
+ check_fail "Test files in plan" "No test files referenced in plan document"
148
+ fi
149
+
150
+ # ============================================================
151
+ # CHECK: Each test file exists on disk
152
+ # ============================================================
153
+
154
+ FOUND=0
155
+ MISSING=0
156
+ MISSING_LIST=()
157
+
158
+ for test_file in "${TEST_FILES[@]}"; do
159
+ full_path="$REPO_ROOT/$test_file"
160
+ if [[ -f "$full_path" ]]; then
161
+ check_pass "Test file exists: $test_file"
162
+ FOUND=$((FOUND + 1))
163
+ else
164
+ check_fail "Test file exists: $test_file" "Not found at $full_path"
165
+ MISSING=$((MISSING + 1))
166
+ MISSING_LIST+=("$test_file")
167
+ fi
168
+ done
169
+
170
+ # ============================================================
171
+ # CHECK: Tests pass (unless --skip-run)
172
+ # ============================================================
173
+
174
+ if [[ "$SKIP_RUN" == true ]]; then
175
+ check_skip "Test execution (--skip-run)"
176
+ elif [[ ${#TEST_FILES[@]} -gt 0 && $MISSING -eq 0 ]]; then
177
+ for test_file in "${TEST_FILES[@]}"; do
178
+ if ! npx vitest run --root "$REPO_ROOT" "$test_file" >/dev/null 2>&1; then
179
+ check_fail "Test passes: $test_file"
180
+ else
181
+ check_pass "Test passes: $test_file"
182
+ fi
183
+ done
184
+ fi
185
+
186
+ # ============================================================
187
+ # STRUCTURED OUTPUT
188
+ # ============================================================
189
+
190
+ echo "## Spec Coverage Report"
191
+ echo ""
192
+ echo "**Plan file:** \`$PLAN_FILE\`"
193
+ echo "**Repo root:** \`$REPO_ROOT\`"
194
+ echo ""
195
+
196
+ TOTAL_TESTS=${#TEST_FILES[@]}
197
+ echo "### Coverage Summary"
198
+ echo ""
199
+ echo "- Planned test files: $TOTAL_TESTS"
200
+ echo "- Found on disk: $FOUND"
201
+ echo "- Missing: $MISSING"
202
+ echo ""
203
+
204
+ if [[ ${#MISSING_LIST[@]} -gt 0 ]]; then
205
+ echo "### Missing Test Files"
206
+ echo ""
207
+ for f in "${MISSING_LIST[@]}"; do
208
+ echo "- \`$f\`"
209
+ done
210
+ echo ""
211
+ fi
212
+
213
+ echo "### Check Results"
214
+ echo ""
215
+ for result in "${RESULTS[@]}"; do
216
+ echo "$result"
217
+ done
218
+
219
+ echo ""
220
+ TOTAL=$((CHECK_PASS + CHECK_FAIL))
221
+ echo "---"
222
+ echo ""
223
+
224
+ if [[ $CHECK_FAIL -eq 0 && $TOTAL_TESTS -gt 0 ]]; then
225
+ echo "**Result: PASS** ($CHECK_PASS/$TOTAL checks passed)"
226
+ exit 0
227
+ else
228
+ echo "**Result: FAIL** ($CHECK_FAIL/$TOTAL checks failed)"
229
+ exit 1
230
+ fi