@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,440 @@
1
+ #!/usr/bin/env bash
2
+ # Pre-Synthesis Readiness Check
3
+ # Validates all readiness conditions before PR submission in the synthesis workflow.
4
+ #
5
+ # Usage: pre-synthesis-check.sh --state-file <path> [--repo-root <path>] [--skip-tests] [--skip-stack]
6
+ #
7
+ # Exit codes:
8
+ # 0 = all checks pass
9
+ # 1 = one or more checks failed
10
+ # 2 = usage error (missing required args)
11
+
12
+ set -euo pipefail
13
+
14
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
+ REPO_ROOT="$(dirname "$SCRIPT_DIR")"
16
+
17
+ # Colors
18
+ RED='\033[0;31m'
19
+ GREEN='\033[0;32m'
20
+ YELLOW='\033[1;33m'
21
+ NC='\033[0m'
22
+
23
+ # ============================================================
24
+ # ARGUMENT PARSING
25
+ # ============================================================
26
+
27
+ STATE_FILE=""
28
+ SKIP_TESTS=false
29
+ SKIP_STACK=false
30
+
31
+ usage() {
32
+ cat << 'USAGE'
33
+ Usage: pre-synthesis-check.sh --state-file <path> [--repo-root <path>] [--skip-tests] [--skip-stack]
34
+
35
+ Required:
36
+ --state-file <path> Path to the workflow state JSON file
37
+
38
+ Optional:
39
+ --repo-root <path> Repository root (default: parent of script directory)
40
+ --skip-tests Skip test execution check (npm run test:run && npm run typecheck)
41
+ --skip-stack Skip Graphite stack existence check (gt log --short)
42
+ --help Show this help message
43
+
44
+ Exit codes:
45
+ 0 All checks pass
46
+ 1 One or more checks failed
47
+ 2 Usage error (missing required args)
48
+ USAGE
49
+ }
50
+
51
+ while [[ $# -gt 0 ]]; do
52
+ case "$1" in
53
+ --state-file)
54
+ if [[ -z "${2:-}" ]]; then
55
+ echo "Error: --state-file requires a path argument" >&2
56
+ exit 2
57
+ fi
58
+ STATE_FILE="$2"
59
+ shift 2
60
+ ;;
61
+ --repo-root)
62
+ if [[ -z "${2:-}" ]]; then
63
+ echo "Error: --repo-root requires a path argument" >&2
64
+ exit 2
65
+ fi
66
+ REPO_ROOT="$2"
67
+ shift 2
68
+ ;;
69
+ --skip-tests)
70
+ SKIP_TESTS=true
71
+ shift
72
+ ;;
73
+ --skip-stack)
74
+ SKIP_STACK=true
75
+ shift
76
+ ;;
77
+ --help)
78
+ usage
79
+ exit 0
80
+ ;;
81
+ *)
82
+ echo "Error: Unknown argument '$1'" >&2
83
+ usage >&2
84
+ exit 2
85
+ ;;
86
+ esac
87
+ done
88
+
89
+ if [[ -z "$STATE_FILE" ]]; then
90
+ echo "Error: --state-file is required" >&2
91
+ usage >&2
92
+ exit 2
93
+ fi
94
+
95
+ # ============================================================
96
+ # DEPENDENCY CHECK
97
+ # ============================================================
98
+
99
+ if ! command -v jq &>/dev/null; then
100
+ echo "Error: jq is required but not installed" >&2
101
+ exit 2
102
+ fi
103
+
104
+ # ============================================================
105
+ # CHECK FUNCTIONS
106
+ # ============================================================
107
+
108
+ CHECK_PASS=0
109
+ CHECK_FAIL=0
110
+ RESULTS=()
111
+
112
+ check_pass() {
113
+ local name="$1"
114
+ RESULTS+=("- **PASS**: $name")
115
+ CHECK_PASS=$((CHECK_PASS + 1))
116
+ }
117
+
118
+ check_fail() {
119
+ local name="$1"
120
+ local detail="${2:-}"
121
+ if [[ -n "$detail" ]]; then
122
+ RESULTS+=("- **FAIL**: $name — $detail")
123
+ else
124
+ RESULTS+=("- **FAIL**: $name")
125
+ fi
126
+ CHECK_FAIL=$((CHECK_FAIL + 1))
127
+ }
128
+
129
+ check_skip() {
130
+ local name="$1"
131
+ RESULTS+=("- **SKIP**: $name")
132
+ }
133
+
134
+ # ============================================================
135
+ # CHECK 1: State file exists and is valid JSON
136
+ # ============================================================
137
+
138
+ check_state_file() {
139
+ if [[ ! -f "$STATE_FILE" ]]; then
140
+ check_fail "State file exists" "File not found: $STATE_FILE"
141
+ return 1
142
+ fi
143
+
144
+ if ! jq empty "$STATE_FILE" 2>/dev/null; then
145
+ check_fail "State file exists" "Invalid JSON: $STATE_FILE"
146
+ return 1
147
+ fi
148
+
149
+ check_pass "State file exists"
150
+ return 0
151
+ }
152
+
153
+ # ============================================================
154
+ # CHECK 2: Phase readiness (is workflow at or near synthesize?)
155
+ # ============================================================
156
+
157
+ check_phase_readiness() {
158
+ local phase
159
+ local workflow_type
160
+ phase="$(jq -r '.phase // "unknown"' "$STATE_FILE")"
161
+ workflow_type="$(jq -r '.workflowType // "feature"' "$STATE_FILE")"
162
+
163
+ if [[ "$phase" == "synthesize" ]]; then
164
+ check_pass "Phase is synthesize"
165
+ return 0
166
+ fi
167
+
168
+ # Determine the transition path and missing prerequisites
169
+ local missing=()
170
+
171
+ case "$workflow_type" in
172
+ feature)
173
+ case "$phase" in
174
+ review)
175
+ missing+=("Transition: review → synthesize (guard: allReviewsPassed)")
176
+ ;;
177
+ *)
178
+ check_fail "Phase is synthesize" "Current phase '$phase' — manual phase advancement needed for $workflow_type workflow"
179
+ return 1
180
+ ;;
181
+ esac
182
+ ;;
183
+ refactor)
184
+ case "$phase" in
185
+ overhaul-delegate)
186
+ missing+=("Transition: overhaul-delegate → overhaul-review (guard: allTasksComplete)")
187
+ missing+=("Transition: overhaul-review → overhaul-update-docs (guard: allReviewsPassed — set reviews)")
188
+ missing+=("Transition: overhaul-update-docs → synthesize (guard: docsUpdated — set validation.docsUpdated=true)")
189
+ ;;
190
+ overhaul-review)
191
+ missing+=("Transition: overhaul-review → overhaul-update-docs (guard: allReviewsPassed — set reviews)")
192
+ missing+=("Transition: overhaul-update-docs → synthesize (guard: docsUpdated — set validation.docsUpdated=true)")
193
+ ;;
194
+ overhaul-update-docs)
195
+ missing+=("Transition: overhaul-update-docs → synthesize (guard: docsUpdated — set validation.docsUpdated=true)")
196
+ ;;
197
+ *)
198
+ check_fail "Phase is synthesize" "Current phase '$phase' — manual phase advancement needed for $workflow_type workflow"
199
+ return 1
200
+ ;;
201
+ esac
202
+ ;;
203
+ debug)
204
+ case "$phase" in
205
+ validate)
206
+ missing+=("Transition: validate → synthesize (guard: allTestsPass — set validation.testsPass=true)")
207
+ ;;
208
+ *)
209
+ check_fail "Phase is synthesize" "Current phase '$phase' — manual phase advancement needed for $workflow_type workflow"
210
+ return 1
211
+ ;;
212
+ esac
213
+ ;;
214
+ esac
215
+
216
+ if [[ ${#missing[@]} -gt 0 ]]; then
217
+ local detail
218
+ detail="Phase is '$phase', need ${#missing[@]} transition(s):"
219
+ for m in "${missing[@]}"; do
220
+ detail+="\n - $m"
221
+ done
222
+ check_fail "Phase is synthesize" "$detail"
223
+ return 1
224
+ fi
225
+ }
226
+
227
+ # ============================================================
228
+ # CHECK 3: All tasks complete
229
+ # ============================================================
230
+
231
+ check_all_tasks_complete() {
232
+ local task_count
233
+ local incomplete_count
234
+ local incomplete_tasks
235
+
236
+ task_count="$(jq '.tasks | length' "$STATE_FILE")"
237
+ if [[ "$task_count" -eq 0 ]]; then
238
+ check_fail "All tasks complete" "No tasks found in state file"
239
+ return 1
240
+ fi
241
+
242
+ incomplete_count="$(jq '[.tasks[] | select(.status != "complete")] | length' "$STATE_FILE")"
243
+ if [[ "$incomplete_count" -gt 0 ]]; then
244
+ incomplete_tasks="$(jq -r '[.tasks[] | select(.status != "complete") | "\(.id) (\(.status))"] | join(", ")' "$STATE_FILE")"
245
+ check_fail "All tasks complete" "$incomplete_count incomplete: $incomplete_tasks"
246
+ return 1
247
+ fi
248
+
249
+ check_pass "All tasks complete ($task_count/$task_count)"
250
+ return 0
251
+ }
252
+
253
+ # ============================================================
254
+ # CHECK 4: Reviews passed
255
+ # ============================================================
256
+
257
+ check_reviews_passed() {
258
+ local reviews_json
259
+ reviews_json="$(jq '.reviews // {}' "$STATE_FILE")"
260
+
261
+ # Count review entries
262
+ local entry_count
263
+ entry_count="$(echo "$reviews_json" | jq 'keys | length')"
264
+ if [[ "$entry_count" -eq 0 ]]; then
265
+ check_fail "Reviews passed" "No review entries found in state.reviews"
266
+ return 1
267
+ fi
268
+
269
+ # Collect all statuses from both flat and nested review shapes:
270
+ # Flat: reviews.overhaul = { status: "approved" }
271
+ # Nested: reviews.T1 = { specReview: { status: "pass" }, qualityReview: { status: "approved" } }
272
+ # Legacy: reviews.T1 = { passed: true }
273
+ local failed_reviews
274
+ failed_reviews="$(echo "$reviews_json" | jq -r '
275
+ to_entries[] |
276
+ .key as $key |
277
+ .value |
278
+ if .status then
279
+ # Flat shape
280
+ if (.status | test("^(pass|passed|approved)$")) then empty
281
+ else "\($key) (status: \(.status))"
282
+ end
283
+ elif .specReview or .qualityReview then
284
+ # Nested shape — check both sub-reviews
285
+ [
286
+ (if .specReview.status then
287
+ if (.specReview.status | test("^(pass|passed|approved)$")) then empty
288
+ else "\($key).specReview (status: \(.specReview.status))"
289
+ end
290
+ else empty end),
291
+ (if .qualityReview.status then
292
+ if (.qualityReview.status | test("^(pass|passed|approved)$")) then empty
293
+ else "\($key).qualityReview (status: \(.qualityReview.status))"
294
+ end
295
+ else empty end)
296
+ ][]
297
+ elif .passed == true then
298
+ # Legacy shape
299
+ empty
300
+ elif .passed == false then
301
+ "\($key) (passed: false)"
302
+ else
303
+ "\($key) (no recognizable status)"
304
+ end
305
+ ')"
306
+
307
+ if [[ -n "$failed_reviews" ]]; then
308
+ check_fail "Reviews passed" "Failing reviews: $failed_reviews"
309
+ return 1
310
+ fi
311
+
312
+ check_pass "Reviews passed ($entry_count review entries, all passing)"
313
+ return 0
314
+ }
315
+
316
+ # ============================================================
317
+ # CHECK 5: No outstanding fix requests
318
+ # ============================================================
319
+
320
+ check_no_fix_requests() {
321
+ local fix_count
322
+ local fix_tasks
323
+
324
+ fix_count="$(jq '[.tasks[] | select(.status == "needs_fixes")] | length' "$STATE_FILE")"
325
+ if [[ "$fix_count" -gt 0 ]]; then
326
+ fix_tasks="$(jq -r '[.tasks[] | select(.status == "needs_fixes") | .id] | join(", ")' "$STATE_FILE")"
327
+ check_fail "No outstanding fix requests" "$fix_count tasks need fixes: $fix_tasks"
328
+ return 1
329
+ fi
330
+
331
+ check_pass "No outstanding fix requests"
332
+ return 0
333
+ }
334
+
335
+ # ============================================================
336
+ # CHECK 6: Graphite stack exists
337
+ # ============================================================
338
+
339
+ check_graphite_stack() {
340
+ if [[ "$SKIP_STACK" == true ]]; then
341
+ check_skip "Graphite stack exists (--skip-stack)"
342
+ return 0
343
+ fi
344
+
345
+ if ! command -v gt &>/dev/null; then
346
+ check_fail "Graphite stack exists" "gt CLI not found in PATH"
347
+ return 1
348
+ fi
349
+
350
+ local gt_output
351
+ gt_output="$(gt log --short 2>&1)" || true
352
+
353
+ # Check that gt log produced at least one branch line
354
+ local branch_count
355
+ branch_count="$(echo "$gt_output" | grep -cE '\S' || true)"
356
+ if [[ "$branch_count" -lt 2 ]]; then
357
+ check_fail "Graphite stack exists" "No stack branches found (gt log --short returned $branch_count lines)"
358
+ return 1
359
+ fi
360
+
361
+ check_pass "Graphite stack exists ($branch_count branches)"
362
+ return 0
363
+ }
364
+
365
+ # ============================================================
366
+ # CHECK 7: Tests pass
367
+ # ============================================================
368
+
369
+ check_tests_pass() {
370
+ if [[ "$SKIP_TESTS" == true ]]; then
371
+ check_skip "Tests pass (--skip-tests)"
372
+ return 0
373
+ fi
374
+
375
+ local test_output
376
+ if ! test_output="$(cd "$REPO_ROOT" && npm run test:run 2>&1)"; then
377
+ check_fail "Tests pass" "npm run test:run failed"
378
+ return 1
379
+ fi
380
+
381
+ local typecheck_output
382
+ if ! typecheck_output="$(cd "$REPO_ROOT" && npm run typecheck 2>&1)"; then
383
+ check_fail "Tests pass" "npm run typecheck failed"
384
+ return 1
385
+ fi
386
+
387
+ check_pass "Tests pass"
388
+ return 0
389
+ }
390
+
391
+ # ============================================================
392
+ # EXECUTE CHECKS
393
+ # ============================================================
394
+
395
+ # Check 1: State file — all other checks depend on this
396
+ if check_state_file; then
397
+ # Check 2: Phase readiness
398
+ check_phase_readiness || true
399
+
400
+ # Check 3: All tasks complete
401
+ check_all_tasks_complete || true
402
+
403
+ # Check 4: Reviews passed
404
+ check_reviews_passed || true
405
+
406
+ # Check 5: No outstanding fix requests
407
+ check_no_fix_requests || true
408
+ fi
409
+
410
+ # Check 6: Graphite stack (independent of state file)
411
+ check_graphite_stack || true
412
+
413
+ # Check 7: Tests (independent of state file)
414
+ check_tests_pass || true
415
+
416
+ # ============================================================
417
+ # STRUCTURED OUTPUT
418
+ # ============================================================
419
+
420
+ echo "## Pre-Synthesis Readiness Report"
421
+ echo ""
422
+ echo "**State file:** \`$STATE_FILE\`"
423
+ echo ""
424
+
425
+ for result in "${RESULTS[@]}"; do
426
+ printf '%b\n' "$result"
427
+ done
428
+
429
+ echo ""
430
+ TOTAL=$((CHECK_PASS + CHECK_FAIL))
431
+ echo "---"
432
+ echo ""
433
+
434
+ if [[ $CHECK_FAIL -eq 0 ]]; then
435
+ echo "**Result: PASS** ($CHECK_PASS/$TOTAL checks passed)"
436
+ exit 0
437
+ else
438
+ echo "**Result: FAIL** ($CHECK_FAIL/$TOTAL checks failed)"
439
+ exit 1
440
+ fi