@mmerterden/multi-agent-pipeline 12.7.0 → 12.9.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 (247) hide show
  1. package/CHANGELOG.md +207 -0
  2. package/install/_common.mjs +48 -0
  3. package/install/_dev-only-files.mjs +125 -5
  4. package/install/claude.mjs +14 -8
  5. package/install/copilot.mjs +5 -8
  6. package/package.json +17 -2
  7. package/pipeline/commands/multi-agent/analysis/SKILL.md +1 -1
  8. package/pipeline/lib/credential-store.sh +20 -0
  9. package/pipeline/multi-agent-refs/_account-picker.md +1 -1
  10. package/pipeline/multi-agent-refs/_dev-context.md +1 -1
  11. package/pipeline/multi-agent-refs/_repo-picker.md +1 -1
  12. package/pipeline/multi-agent-refs/features/review-multi-repo.md +65 -0
  13. package/pipeline/multi-agent-refs/features/url-enrichment.md +93 -0
  14. package/pipeline/multi-agent-refs/phases/operations.md +28 -0
  15. package/pipeline/multi-agent-refs/phases/phase-0-init.md +3 -83
  16. package/pipeline/multi-agent-refs/phases/phase-2-planning.md +1 -1
  17. package/pipeline/multi-agent-refs/phases/phase-3-dev.md +1 -2
  18. package/pipeline/multi-agent-refs/phases/phase-4-review.md +50 -62
  19. package/pipeline/schemas/prefs.schema.json +6 -0
  20. package/pipeline/scripts/_smoke-root.sh +61 -0
  21. package/pipeline/scripts/agent-guard.py +57 -3
  22. package/pipeline/scripts/audit-log.sh +25 -0
  23. package/pipeline/scripts/smoke-cross-cli-behavior.sh +21 -7
  24. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-1-analysis.json +0 -25
  25. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-2-plan.json +0 -30
  26. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-4-review.json +0 -20
  27. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-4-triage.json +0 -15
  28. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/metadata.json +0 -14
  29. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/task.json +0 -12
  30. package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-1-analysis.json +0 -29
  31. package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-2-plan.json +0 -43
  32. package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-4-review.json +0 -35
  33. package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-4-triage.json +0 -35
  34. package/pipeline/eval/golden-tasks/02-android-feature-compose/metadata.json +0 -14
  35. package/pipeline/eval/golden-tasks/02-android-feature-compose/task.json +0 -12
  36. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-1-analysis.json +0 -29
  37. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-2-plan.json +0 -42
  38. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-4-review.json +0 -20
  39. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-4-triage.json +0 -15
  40. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/metadata.json +0 -14
  41. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/task.json +0 -12
  42. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-1-analysis.json +0 -29
  43. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-2-plan.json +0 -40
  44. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-4-review.json +0 -20
  45. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-4-triage.json +0 -15
  46. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/metadata.json +0 -14
  47. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/task.json +0 -12
  48. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-1-analysis.json +0 -29
  49. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-2-plan.json +0 -42
  50. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-4-review.json +0 -28
  51. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-4-triage.json +0 -27
  52. package/pipeline/eval/golden-tasks/05-ios-security-keychain/metadata.json +0 -14
  53. package/pipeline/eval/golden-tasks/05-ios-security-keychain/task.json +0 -12
  54. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-1-analysis.json +0 -29
  55. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-2-plan.json +0 -41
  56. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-4-review.json +0 -12
  57. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-4-triage.json +0 -6
  58. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/metadata.json +0 -14
  59. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/task.json +0 -12
  60. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-1-analysis.json +0 -29
  61. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-2-plan.json +0 -42
  62. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-4-review.json +0 -28
  63. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-4-triage.json +0 -27
  64. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/metadata.json +0 -14
  65. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/task.json +0 -12
  66. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-1-analysis.json +0 -25
  67. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-2-plan.json +0 -31
  68. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-4-review.json +0 -12
  69. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-4-triage.json +0 -18
  70. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/metadata.json +0 -14
  71. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/task.json +0 -12
  72. package/pipeline/eval/golden-tasks/README.md +0 -65
  73. package/pipeline/eval/intent-cases.json +0 -40
  74. package/pipeline/eval/run-metrics-fixture.json +0 -93
  75. package/pipeline/eval/triage/01-empty-findings/expected.json +0 -6
  76. package/pipeline/eval/triage/01-empty-findings/input.json +0 -5
  77. package/pipeline/eval/triage/01-empty-findings/notes.md +0 -7
  78. package/pipeline/eval/triage/02-real-blocker/expected.json +0 -15
  79. package/pipeline/eval/triage/02-real-blocker/input.json +0 -14
  80. package/pipeline/eval/triage/02-real-blocker/notes.md +0 -7
  81. package/pipeline/eval/triage/03-out-of-scope-defer/expected.json +0 -18
  82. package/pipeline/eval/triage/03-out-of-scope-defer/input.json +0 -14
  83. package/pipeline/eval/triage/03-out-of-scope-defer/notes.md +0 -10
  84. package/pipeline/eval/triage/04-false-positive-reject/expected.json +0 -18
  85. package/pipeline/eval/triage/04-false-positive-reject/input.json +0 -14
  86. package/pipeline/eval/triage/04-false-positive-reject/notes.md +0 -10
  87. package/pipeline/eval/triage/05-mixed-classification/expected.json +0 -43
  88. package/pipeline/eval/triage/05-mixed-classification/input.json +0 -38
  89. package/pipeline/eval/triage/05-mixed-classification/notes.md +0 -17
  90. package/pipeline/eval/triage/06-severity-mismatch/expected.json +0 -15
  91. package/pipeline/eval/triage/06-severity-mismatch/input.json +0 -14
  92. package/pipeline/eval/triage/06-severity-mismatch/notes.md +0 -9
  93. package/pipeline/eval/triage/07-duplicate-reviewers/expected.json +0 -27
  94. package/pipeline/eval/triage/07-duplicate-reviewers/input.json +0 -22
  95. package/pipeline/eval/triage/07-duplicate-reviewers/notes.md +0 -9
  96. package/pipeline/eval/triage/08-style-misclassified/expected.json +0 -18
  97. package/pipeline/eval/triage/08-style-misclassified/input.json +0 -14
  98. package/pipeline/eval/triage/08-style-misclassified/notes.md +0 -9
  99. package/pipeline/eval/triage/09-cascading-finding/expected.json +0 -23
  100. package/pipeline/eval/triage/09-cascading-finding/input.json +0 -22
  101. package/pipeline/eval/triage/09-cascading-finding/notes.md +0 -9
  102. package/pipeline/eval/triage/10-deferred-crossref/expected.json +0 -18
  103. package/pipeline/eval/triage/10-deferred-crossref/input.json +0 -14
  104. package/pipeline/eval/triage/10-deferred-crossref/notes.md +0 -9
  105. package/pipeline/eval/triage/11-vercel-token-leak-blocker/expected.json +0 -27
  106. package/pipeline/eval/triage/11-vercel-token-leak-blocker/input.json +0 -22
  107. package/pipeline/eval/triage/11-vercel-token-leak-blocker/notes.md +0 -14
  108. package/pipeline/eval/triage/README.md +0 -54
  109. package/pipeline/scripts/benchmark-phase-0.sh +0 -128
  110. package/pipeline/scripts/check-md-links.mjs +0 -88
  111. package/pipeline/scripts/eval-golden-tasks-live.mjs +0 -302
  112. package/pipeline/scripts/eval-golden-tasks.mjs +0 -224
  113. package/pipeline/scripts/eval-intent.mjs +0 -107
  114. package/pipeline/scripts/eval-mine-corpus.mjs +0 -211
  115. package/pipeline/scripts/eval-triage.mjs +0 -171
  116. package/pipeline/scripts/fixtures/diff-risk-android.diff +0 -40
  117. package/pipeline/scripts/fixtures/diff-risk-ios.diff +0 -48
  118. package/pipeline/scripts/fixtures/diff-risk-test-removal.diff +0 -40
  119. package/pipeline/scripts/fixtures/install-layout.tsv +0 -19
  120. package/pipeline/scripts/fixtures/pack-expected-count.txt +0 -1
  121. package/pipeline/scripts/fixtures/test-gap-node.diff +0 -30
  122. package/pipeline/scripts/fixtures/test-gap-python.diff +0 -32
  123. package/pipeline/scripts/lint-mcp-refs.mjs +0 -218
  124. package/pipeline/scripts/lint-skills.mjs +0 -154
  125. package/pipeline/scripts/run-smokes.mjs +0 -130
  126. package/pipeline/scripts/scorecard.mjs +0 -258
  127. package/pipeline/scripts/smoke-add-detail.sh +0 -137
  128. package/pipeline/scripts/smoke-agent-guard.sh +0 -74
  129. package/pipeline/scripts/smoke-agent-log-cost.sh +0 -262
  130. package/pipeline/scripts/smoke-agent-model-routing.sh +0 -87
  131. package/pipeline/scripts/smoke-ask-choice.sh +0 -42
  132. package/pipeline/scripts/smoke-autopilot-circuit-breaker.sh +0 -36
  133. package/pipeline/scripts/smoke-bitbucket-contract.sh +0 -255
  134. package/pipeline/scripts/smoke-changelog-version.sh +0 -47
  135. package/pipeline/scripts/smoke-channels-approval-gate.sh +0 -60
  136. package/pipeline/scripts/smoke-channels-flow.sh +0 -130
  137. package/pipeline/scripts/smoke-ci-workflows.sh +0 -88
  138. package/pipeline/scripts/smoke-clarify.sh +0 -148
  139. package/pipeline/scripts/smoke-command-inventory.sh +0 -81
  140. package/pipeline/scripts/smoke-commands-skills-parity.sh +0 -87
  141. package/pipeline/scripts/smoke-community-gates.sh +0 -75
  142. package/pipeline/scripts/smoke-compliance-skills.sh +0 -119
  143. package/pipeline/scripts/smoke-config-hygiene.sh +0 -58
  144. package/pipeline/scripts/smoke-context-budget.sh +0 -72
  145. package/pipeline/scripts/smoke-cost-budget.sh +0 -70
  146. package/pipeline/scripts/smoke-cost-summary.sh +0 -139
  147. package/pipeline/scripts/smoke-cross-phase-cohesion.sh +0 -128
  148. package/pipeline/scripts/smoke-description-tr.sh +0 -82
  149. package/pipeline/scripts/smoke-dev-critic.sh +0 -144
  150. package/pipeline/scripts/smoke-diff-explain.sh +0 -147
  151. package/pipeline/scripts/smoke-diff-risk.sh +0 -190
  152. package/pipeline/scripts/smoke-dynamic-skill-loading.sh +0 -160
  153. package/pipeline/scripts/smoke-eval-live.sh +0 -136
  154. package/pipeline/scripts/smoke-evidence-gate.sh +0 -93
  155. package/pipeline/scripts/smoke-extract-conventions.sh +0 -163
  156. package/pipeline/scripts/smoke-fetchers-offline.sh +0 -448
  157. package/pipeline/scripts/smoke-figma-dispatch.sh +0 -112
  158. package/pipeline/scripts/smoke-gate-hooks.sh +0 -74
  159. package/pipeline/scripts/smoke-gc-tmp.sh +0 -130
  160. package/pipeline/scripts/smoke-gc-worktrees.sh +0 -125
  161. package/pipeline/scripts/smoke-generate-issue.sh +0 -120
  162. package/pipeline/scripts/smoke-handoff-contract.sh +0 -92
  163. package/pipeline/scripts/smoke-identity-isolation.sh +0 -70
  164. package/pipeline/scripts/smoke-install-layout.sh +0 -248
  165. package/pipeline/scripts/smoke-intent-guard.sh +0 -86
  166. package/pipeline/scripts/smoke-issue-comment-template.sh +0 -86
  167. package/pipeline/scripts/smoke-issue-jira-triad.sh +0 -120
  168. package/pipeline/scripts/smoke-keychain.sh +0 -158
  169. package/pipeline/scripts/smoke-language-axis.sh +0 -109
  170. package/pipeline/scripts/smoke-learning-curve.sh +0 -61
  171. package/pipeline/scripts/smoke-learnings-ledger.sh +0 -86
  172. package/pipeline/scripts/smoke-lib-scripts.sh +0 -448
  173. package/pipeline/scripts/smoke-mcp-gate.sh +0 -68
  174. package/pipeline/scripts/smoke-md-links.sh +0 -8
  175. package/pipeline/scripts/smoke-md2confluence.sh +0 -126
  176. package/pipeline/scripts/smoke-metrics-cache-ratio.sh +0 -72
  177. package/pipeline/scripts/smoke-migrate-state.sh +0 -102
  178. package/pipeline/scripts/smoke-mode-dispatch-drift.sh +0 -161
  179. package/pipeline/scripts/smoke-model-fallback.sh +0 -89
  180. package/pipeline/scripts/smoke-multi-repo-integration.sh +0 -116
  181. package/pipeline/scripts/smoke-multi-repo-worktree.sh +0 -61
  182. package/pipeline/scripts/smoke-no-mcp-in-dev-phases.sh +0 -194
  183. package/pipeline/scripts/smoke-no-token-prompt.sh +0 -85
  184. package/pipeline/scripts/smoke-own-punctuation.sh +0 -103
  185. package/pipeline/scripts/smoke-pack-contents.sh +0 -140
  186. package/pipeline/scripts/smoke-pat-audit.sh +0 -128
  187. package/pipeline/scripts/smoke-per-repo-memory.sh +0 -156
  188. package/pipeline/scripts/smoke-phase-0-multi-repo.sh +0 -170
  189. package/pipeline/scripts/smoke-phase-6-multi.sh +0 -79
  190. package/pipeline/scripts/smoke-phase-banner.sh +0 -101
  191. package/pipeline/scripts/smoke-phase-tracker.sh +0 -324
  192. package/pipeline/scripts/smoke-phase0-bridge-contract.sh +0 -241
  193. package/pipeline/scripts/smoke-phase4-gates.sh +0 -45
  194. package/pipeline/scripts/smoke-phase4-triage.sh +0 -229
  195. package/pipeline/scripts/smoke-plan-approval-gate.sh +0 -71
  196. package/pipeline/scripts/smoke-plan-safety.sh +0 -139
  197. package/pipeline/scripts/smoke-plan-todos.sh +0 -196
  198. package/pipeline/scripts/smoke-pr-review-actions.sh +0 -152
  199. package/pipeline/scripts/smoke-pre-commit.sh +0 -170
  200. package/pipeline/scripts/smoke-pref-migration.sh +0 -226
  201. package/pipeline/scripts/smoke-prefs-language.sh +0 -134
  202. package/pipeline/scripts/smoke-progress-contract.sh +0 -127
  203. package/pipeline/scripts/smoke-prune-logs.sh +0 -137
  204. package/pipeline/scripts/smoke-purge.sh +0 -138
  205. package/pipeline/scripts/smoke-push-retry.sh +0 -75
  206. package/pipeline/scripts/smoke-repo-map.sh +0 -300
  207. package/pipeline/scripts/smoke-review-readiness.sh +0 -92
  208. package/pipeline/scripts/smoke-review-watch.sh +0 -146
  209. package/pipeline/scripts/smoke-routines.sh +0 -84
  210. package/pipeline/scripts/smoke-run-aggregator.sh +0 -216
  211. package/pipeline/scripts/smoke-run-metrics.sh +0 -50
  212. package/pipeline/scripts/smoke-search.sh +0 -187
  213. package/pipeline/scripts/smoke-shadow-git.sh +0 -224
  214. package/pipeline/scripts/smoke-skill-authoring.sh +0 -137
  215. package/pipeline/scripts/smoke-skill-language.sh +0 -83
  216. package/pipeline/scripts/smoke-skill-manifest.sh +0 -138
  217. package/pipeline/scripts/smoke-skill-scan.sh +0 -198
  218. package/pipeline/scripts/smoke-source-parity.sh +0 -85
  219. package/pipeline/scripts/smoke-subagent-validators.sh +0 -108
  220. package/pipeline/scripts/smoke-sync-parity.sh +0 -92
  221. package/pipeline/scripts/smoke-tasklist-ordering.sh +0 -112
  222. package/pipeline/scripts/smoke-telemetry.sh +0 -147
  223. package/pipeline/scripts/smoke-test-gap.sh +0 -183
  224. package/pipeline/scripts/smoke-token-budget.sh +0 -67
  225. package/pipeline/scripts/smoke-token-preflight.sh +0 -82
  226. package/pipeline/scripts/smoke-tracker-contract.sh +0 -191
  227. package/pipeline/scripts/smoke-tracker-tokens-invocation.sh +0 -73
  228. package/pipeline/scripts/smoke-triage-memory.sh +0 -174
  229. package/pipeline/scripts/smoke-update-check.sh +0 -135
  230. package/pipeline/scripts/smoke-url-enrichment.sh +0 -70
  231. package/pipeline/scripts/smoke-validate-analysis-doc.sh +0 -161
  232. package/pipeline/scripts/smoke-validator-contradiction.sh +0 -67
  233. package/pipeline/scripts/smoke-validator-gates.sh +0 -164
  234. package/pipeline/scripts/smoke-vercel-deploy-redact.sh +0 -129
  235. package/pipeline/scripts/smoke-verify-by-test.sh +0 -148
  236. package/pipeline/scripts/smoke-wiki-integration.sh +0 -122
  237. package/pipeline/scripts/smoke-work-summary.sh +0 -163
  238. package/pipeline/scripts/smoke-workflow-audit.sh +0 -101
  239. package/pipeline/scripts/smoke-worktree-path-convention.sh +0 -86
  240. package/pipeline/scripts/smoke-wrapper-preservation.sh +0 -68
  241. package/pipeline/scripts/smoke-write-state.sh +0 -159
  242. package/pipeline/scripts/sync-parity-check.sh +0 -135
  243. package/pipeline/scripts/test-gap-rules/android.json +0 -25
  244. package/pipeline/scripts/test-gap-rules/ios.json +0 -34
  245. package/pipeline/scripts/test-gap-rules/node.json +0 -29
  246. package/pipeline/scripts/test-gap-rules/python.json +0 -25
  247. package/pipeline/scripts/validate-schemas.mjs +0 -88
@@ -1,73 +0,0 @@
1
- #!/usr/bin/env bash
2
- #
3
- # smoke-tracker-tokens-invocation.sh
4
- #
5
- # Asserts every LLM-heavy phase doc invokes `phase-tracker.sh tokens <N> <in> <out>`
6
- # at least once, so the per-phase + cumulative token counter in the tracker's
7
- # render output stays accurate for every run. Without this gate, phase docs
8
- # tend to drop the token call as they get edited and the user loses cost
9
- # visibility - exactly Defect 5 from the GH1241 review.
10
- #
11
- # Phase 3 (Dev) and Phase 4 (Review) are the LLM-intensive ones. Phase 1+2
12
- # also do LLM work. Phase 0/5/6/7 are mostly orchestration.
13
-
14
- set -euo pipefail
15
-
16
- SELF_DIR=$(cd "$(dirname "$0")" && pwd)
17
- PIPELINE_ROOT=$(cd "$SELF_DIR/.." && pwd)
18
-
19
- cd "$PIPELINE_ROOT"
20
-
21
- FAIL=0
22
-
23
- # Every phase doc that runs LLM calls MUST mention `phase-tracker.sh tokens`
24
- # at least once (either in a code fence or inline).
25
- declare -a LLM_PHASES=(
26
- "multi-agent-refs/phases/phase-1-analysis.md:1"
27
- "multi-agent-refs/phases/phase-2-planning.md:2"
28
- "multi-agent-refs/phases/phase-3-dev.md:3"
29
- "multi-agent-refs/phases/phase-4-review.md:4"
30
- )
31
-
32
- for entry in "${LLM_PHASES[@]}"; do
33
- doc="${entry%:*}"
34
- phase_id="${entry##*:}"
35
- full="$doc"
36
- if [ ! -f "$full" ]; then
37
- echo "FAIL [smoke-tracker-tokens-invocation]: $doc missing"
38
- FAIL=$((FAIL + 1))
39
- continue
40
- fi
41
- if ! grep -qE "phase-tracker\.sh tokens" "$full"; then
42
- echo "FAIL [smoke-tracker-tokens-invocation]: $doc must invoke 'phase-tracker.sh tokens $phase_id <in> <out>' after every LLM call"
43
- FAIL=$((FAIL + 1))
44
- fi
45
- done
46
-
47
- # tracker-contract.md is the canonical location for the tokens API. Make sure
48
- # it documents the invocation pattern with both args.
49
- CONTRACT="multi-agent-refs/tracker-contract.md"
50
- if [ ! -f "$CONTRACT" ]; then
51
- echo "FAIL [smoke-tracker-tokens-invocation]: $CONTRACT missing"
52
- FAIL=$((FAIL + 1))
53
- elif ! grep -qE "phase-tracker\.sh tokens .*<in>.*<out>|phase-tracker\.sh tokens .*<input.*<output" "$CONTRACT"; then
54
- echo "FAIL [smoke-tracker-tokens-invocation]: $CONTRACT must document the tokens <N> <in> <out> signature"
55
- FAIL=$((FAIL + 1))
56
- fi
57
-
58
- # v9.10.2: the contract must also mandate the per-phase completion narration
59
- # line - the TaskList widget shows duration only, so without the chat line the
60
- # user never sees live per-phase tokens.
61
- if ! grep -q "per-phase token narration on completion" "$CONTRACT"; then
62
- echo "FAIL [smoke-tracker-tokens-invocation]: $CONTRACT must mandate the per-phase token narration line on completion"
63
- FAIL=$((FAIL + 1))
64
- fi
65
-
66
- if [ "$FAIL" -gt 0 ]; then
67
- echo ""
68
- echo "smoke-tracker-tokens-invocation: $FAIL violation(s)."
69
- echo "Defect 5: phase docs must invoke 'phase-tracker.sh tokens <N> <in> <out>' after every LLM call so the tracker render shows live cost."
70
- exit 1
71
- fi
72
-
73
- echo "smoke-tracker-tokens-invocation: ok"
@@ -1,174 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-triage-memory.sh - v8.3.0
3
- #
4
- # Verifies the triage-memory persistence layer:
5
- # 1. ingest writes JSONL rows for accepted/deferred/rejected and tags
6
- # task_id, classification, severity, file, issue, reason
7
- # 2. ingest is idempotent - re-running with the same input writes 0 rows
8
- # 3. stats reports correct row counts grouped by classification
9
- # 4. query ranks rows by token overlap, returns top-N hits
10
- # 5. query --file-glob filters by path
11
- # 6. path subcommand resolves to <slug>/triage-corpus.jsonl under HOME
12
- # 7. empty corpus query returns total=0 + exit 2
13
- # 8. validate-schemas accepts triage-corpus.schema.json
14
- # 9. phase-7-report.md ref doc declares the ingest call
15
- # 10. phase-4-review.md ref doc declares prior-art lookup
16
- # 11. prefs.schema.json exposes priorArtEnrichment toggle
17
- #
18
- # Uses HOME override so we never touch the user's real ~/.claude/memory.
19
- #
20
- # Exit 0 = all pass, 1 = any failure.
21
-
22
- set -uo pipefail
23
-
24
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
25
- TM="$ROOT/pipeline/scripts/triage-memory.mjs"
26
- PHASE7="$ROOT/pipeline/multi-agent-refs/phases/phase-7-report.md"
27
- PHASE4="$ROOT/pipeline/multi-agent-refs/phases/phase-4-review.md"
28
- PREFS="$ROOT/pipeline/schemas/prefs.schema.json"
29
- SCHEMA="$ROOT/pipeline/schemas/triage-corpus.schema.json"
30
-
31
- pass=0
32
- fail=0
33
- failures=()
34
- record_pass() { pass=$((pass + 1)); printf ' \033[0;32mPASS\033[0m %s\n' "$1"; }
35
- record_fail() { fail=$((fail + 1)); failures+=("$1"); printf ' \033[0;31mFAIL\033[0m %s\n' "$1"; }
36
-
37
- printf '→ smoke-triage-memory (v8.3.0): semantic memory contract\n'
38
-
39
- [ -f "$SCHEMA" ] || { record_fail "schema missing: $SCHEMA"; exit 1; }
40
-
41
- TMP_HOME=$(mktemp -d)
42
- trap 'rm -rf "$TMP_HOME"' EXIT
43
- export HOME="$TMP_HOME"
44
- export MULTI_AGENT_REPO_SLUG="smoke-corpus"
45
-
46
- # Build a fixture triage JSON
47
- TRIAGE_FIXTURE="$TMP_HOME/triage.json"
48
- cat > "$TRIAGE_FIXTURE" <<'JSON'
49
- {
50
- "accepted": [
51
- {"severity":"blocking","file":"Auth/KeychainStore.swift","line":42,"issue":"Force-unwrap on optional token","fix":"Use guard let","reviewer":"opus"},
52
- {"severity":"important","file":"Networking/ApiClient.swift","line":11,"issue":"Missing timeout configuration","fix":"Set request timeout","reviewer":"sonnet"}
53
- ],
54
- "deferred": [
55
- {"finding":{"severity":"suggestion","file":"Views/SettingsView.swift","line":50,"issue":"Could extract subview","fix":"refactor"},"reason":"out of scope"}
56
- ],
57
- "rejected": [
58
- {"finding":{"severity":"important","file":"Auth/KeychainStore.swift","line":99,"issue":"Use Sendable annotation","fix":"add Sendable"},"reason":"requires Swift 6 migration"}
59
- ],
60
- "approved": false
61
- }
62
- JSON
63
-
64
- # --- 1: first ingest writes rows ---
65
- out1=$(node "$TM" ingest --triage "$TRIAGE_FIXTURE" --task-id PROJ-100 --task-title "Auth refactor" --stack ios 2>/dev/null)
66
- ingested=$(echo "$out1" | jq -r '.ingested')
67
- if [ "$ingested" = "4" ]; then
68
- record_pass "ingest writes 4 rows (2 accepted + 1 deferred + 1 rejected)"
69
- else
70
- record_fail "ingest expected 4, got $ingested"
71
- fi
72
-
73
- # --- 2: idempotent re-ingest writes 0 rows ---
74
- out2=$(node "$TM" ingest --triage "$TRIAGE_FIXTURE" --task-id PROJ-100 --task-title "Auth refactor" --stack ios 2>/dev/null; echo "EC=$?")
75
- ingested2=$(echo "$out2" | grep -v EC= | jq -r '.ingested')
76
- ec2=$(echo "$out2" | grep "EC=" | sed 's/.*EC=//')
77
- if [ "$ingested2" = "0" ] && [ "$ec2" = "2" ]; then
78
- record_pass "re-ingest is idempotent (0 rows + exit 2)"
79
- else
80
- record_fail "re-ingest should write 0 rows + exit 2, got rows=$ingested2 ec=$ec2"
81
- fi
82
-
83
- # --- 3: stats counts ---
84
- stats=$(node "$TM" stats 2>/dev/null)
85
- acc=$(echo "$stats" | jq -r '.counts.accepted')
86
- def=$(echo "$stats" | jq -r '.counts.deferred')
87
- rej=$(echo "$stats" | jq -r '.counts.rejected')
88
- if [ "$acc" = "2" ] && [ "$def" = "1" ] && [ "$rej" = "1" ]; then
89
- record_pass "stats reports accepted=2 deferred=1 rejected=1"
90
- else
91
- record_fail "stats wrong: accepted=$acc deferred=$def rejected=$rej"
92
- fi
93
-
94
- # --- 4: query ranks by token overlap ---
95
- q1=$(node "$TM" query --issue "force unwrap optional" --top 2 2>/dev/null)
96
- top1=$(echo "$q1" | jq -r '.hits[0].file')
97
- top1_issue=$(echo "$q1" | jq -r '.hits[0].issue')
98
- if [[ "$top1" == *"KeychainStore.swift" ]] && [[ "$top1_issue" == *"Force-unwrap"* ]]; then
99
- record_pass "query: 'force unwrap optional' top hit = KeychainStore force-unwrap finding"
100
- else
101
- record_fail "query top hit wrong: $top1 / $top1_issue"
102
- fi
103
-
104
- # --- 5: file-glob filter ---
105
- q2=$(node "$TM" query --issue "timeout" --file-glob "Networking/*" 2>/dev/null)
106
- n2=$(echo "$q2" | jq -r '.hits | length')
107
- top2=$(echo "$q2" | jq -r '.hits[0].file' 2>/dev/null || echo "")
108
- if [ "$n2" = "1" ] && [[ "$top2" == "Networking/ApiClient.swift" ]]; then
109
- record_pass "query: --file-glob narrows to Networking/* path"
110
- else
111
- record_fail "file-glob narrow wrong: hits=$n2 top=$top2"
112
- fi
113
-
114
- # --- 6: path subcommand ---
115
- p=$(node "$TM" path 2>/dev/null)
116
- expected="$TMP_HOME/.claude/memory/multi-agent/smoke-corpus/triage-corpus.jsonl"
117
- if [ "$p" = "$expected" ]; then
118
- record_pass "path resolves to <HOME>/.claude/memory/multi-agent/<slug>/triage-corpus.jsonl"
119
- else
120
- record_fail "path wrong: $p (expected $expected)"
121
- fi
122
-
123
- # --- 7: empty-corpus query exits 2 with empty hits ---
124
- export MULTI_AGENT_REPO_SLUG="empty-corpus"
125
- set +e
126
- empty_out=$(node "$TM" query --issue "anything" 2>/dev/null)
127
- ec=$?
128
- set -e
129
- hits=$(echo "$empty_out" | jq -r '.hits | length')
130
- total=$(echo "$empty_out" | jq -r '.total')
131
- if [ "$ec" = "2" ] && [ "$hits" = "0" ] && [ "$total" = "0" ]; then
132
- record_pass "empty-corpus query: exit 2, hits=[], total=0"
133
- else
134
- record_fail "empty-corpus wrong: ec=$ec hits=$hits total=$total"
135
- fi
136
- export MULTI_AGENT_REPO_SLUG="smoke-corpus"
137
-
138
- # --- 8: schema present + valid JSON ---
139
- if jq -e '.title and .properties.classification' "$SCHEMA" >/dev/null 2>&1; then
140
- record_pass "triage-corpus schema present and well-formed"
141
- else
142
- record_fail "triage-corpus schema malformed"
143
- fi
144
-
145
- # --- 9: phase-7-report.md declares ingest ---
146
- if grep -q 'triage-memory.mjs' "$PHASE7"; then
147
- record_pass "phase-7-report.md references triage-memory.mjs"
148
- else
149
- record_fail "phase-7-report.md missing triage-memory.mjs reference"
150
- fi
151
-
152
- # --- 10: phase-4-review.md declares prior-art lookup ---
153
- if grep -qE 'prior.art|triage-memory' "$PHASE4"; then
154
- record_pass "phase-4-review.md declares prior-art lookup"
155
- else
156
- record_fail "phase-4-review.md missing prior-art lookup"
157
- fi
158
-
159
- # --- 11: prefs schema exposes priorArtEnrichment ---
160
- if jq -e '.properties.global.properties.priorArtEnrichment' "$PREFS" >/dev/null 2>&1; then
161
- record_pass "prefs schema exposes priorArtEnrichment toggle"
162
- else
163
- record_fail "prefs.schema.json missing global.priorArtEnrichment"
164
- fi
165
-
166
- # --- Summary ---
167
- total=$((pass + fail))
168
- printf '\n→ smoke-triage-memory: %d/%d passed\n' "$pass" "$total"
169
- if [ "$fail" -ne 0 ]; then
170
- printf '\nFailures:\n'
171
- for f in "${failures[@]}"; do printf ' - %s\n' "$f"; done
172
- exit 1
173
- fi
174
- exit 0
@@ -1,135 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-update-check.sh
3
- #
4
- # Verifies the Phase 0 Step 0.6 advisory update-check contract:
5
- # 1. update-check.sh exists, parses (bash -n), and honors the advisory contract
6
- # offline: exit 0 + empty stdout when the registry is unreachable
7
- # 2. Cached path: fresh cache short-circuits without a network call
8
- # 3. Newer latest -> "<local>|<latest>"; same or older latest -> silent
9
- # 4. prefs.schema.json exposes updateCheck.{enabled,ttlHours,autoUpdate}
10
- # with the documented defaults (enabled=true, autoUpdate=false)
11
- # 5. phase-0-init.md documents Step 0.6 with the autopilot log-only rule
12
- #
13
- # Exit 0 = all pass, 1 = any failure.
14
-
15
- set -euo pipefail
16
-
17
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
18
- SCRIPT="$ROOT/pipeline/scripts/update-check.sh"
19
- PREFS_SCHEMA="$ROOT/pipeline/schemas/prefs.schema.json"
20
- PHASE0_DOC="$ROOT/pipeline/multi-agent-refs/phases/phase-0-init.md"
21
-
22
- pass=0
23
- fail=0
24
- failures=()
25
- record_pass() { pass=$((pass + 1)); printf ' \033[0;32mPASS\033[0m %s\n' "$1"; }
26
- record_fail() { fail=$((fail + 1)); failures+=("$1"); printf ' \033[0;31mFAIL\033[0m %s\n' "$1"; }
27
-
28
- printf '→ smoke-update-check: Phase 0 Step 0.6 advisory contract\n'
29
-
30
- tmpdir=$(mktemp -d)
31
- trap 'rm -rf "$tmpdir"' EXIT
32
- CACHE="$tmpdir/update-check-cache"
33
-
34
- # 1. Script parses
35
- if bash -n "$SCRIPT" 2>/dev/null; then
36
- record_pass "update-check.sh parses (bash -n)"
37
- else
38
- record_fail "update-check.sh has syntax errors"
39
- fi
40
-
41
- now=$(date +%s)
42
-
43
- # 2. Fresh cache with newer latest -> reports, no network needed
44
- printf '%s|99.0.0\n' "$now" > "$CACHE"
45
- out=$(UPDATE_CHECK_CACHE="$CACHE" bash "$SCRIPT" --local 10.0.0 2>/dev/null); rc=$?
46
- if [ "$rc" -eq 0 ] && [ "$out" = "10.0.0|99.0.0" ]; then
47
- record_pass "newer cached latest -> '<local>|<latest>' (exit 0)"
48
- else
49
- record_fail "newer cached latest should print '10.0.0|99.0.0' (got '$out', rc=$rc)"
50
- fi
51
-
52
- # 3. Same version -> silent
53
- printf '%s|10.0.0\n' "$now" > "$CACHE"
54
- out=$(UPDATE_CHECK_CACHE="$CACHE" bash "$SCRIPT" --local 10.0.0 2>/dev/null); rc=$?
55
- if [ "$rc" -eq 0 ] && [ -z "$out" ]; then
56
- record_pass "same version -> silent"
57
- else
58
- record_fail "same version should be silent (got '$out', rc=$rc)"
59
- fi
60
-
61
- # 3b. Local ahead of registry (dev machine) -> silent
62
- printf '%s|10.0.0\n' "$now" > "$CACHE"
63
- out=$(UPDATE_CHECK_CACHE="$CACHE" bash "$SCRIPT" --local 10.1.0 2>/dev/null); rc=$?
64
- if [ "$rc" -eq 0 ] && [ -z "$out" ]; then
65
- record_pass "local ahead of registry -> silent (no downgrade prompt)"
66
- else
67
- record_fail "local-ahead should be silent (got '$out', rc=$rc)"
68
- fi
69
-
70
- # 3b2. No --local, no repo clone -> falls back to the install-time version
71
- # marker (npx-only installs have no clone to read a version from)
72
- marker_home="$tmpdir/marker-home"
73
- mkdir -p "$marker_home/.claude"
74
- printf '10.0.0\n' > "$marker_home/.claude/.pipeline-version"
75
- printf '%s|99.0.0\n' "$now" > "$CACHE"
76
- out=$(HOME="$marker_home" UPDATE_CHECK_CACHE="$CACHE" bash "$SCRIPT" 2>/dev/null); rc=$?
77
- if [ "$rc" -eq 0 ] && [ "$out" = "10.0.0|99.0.0" ]; then
78
- record_pass "no clone -> .pipeline-version marker fallback works"
79
- else
80
- record_fail "marker fallback should print '10.0.0|99.0.0' (got '$out', rc=$rc)"
81
- fi
82
-
83
- # 3c. Offline + stale cache -> silent exit 0 (advisory: never blocks)
84
- printf '0|10.0.0\n' > "$CACHE"
85
- out=$(UPDATE_CHECK_CACHE="$CACHE" http_proxy="http://127.0.0.1:1" https_proxy="http://127.0.0.1:1" \
86
- bash "$SCRIPT" --local 10.0.0 2>/dev/null); rc=$?
87
- if [ "$rc" -eq 0 ] && [ -z "$out" ]; then
88
- record_pass "offline + stale cache -> silent exit 0"
89
- else
90
- record_fail "offline should be a silent no-op (got '$out', rc=$rc)"
91
- fi
92
-
93
- # 4. Prefs schema knobs + defaults
94
- for prop in enabled ttlHours autoUpdate; do
95
- if jq -e ".properties.global.properties.updateCheck.properties.${prop}" "$PREFS_SCHEMA" >/dev/null 2>&1; then
96
- record_pass "prefs schema exposes updateCheck.${prop}"
97
- else
98
- record_fail "prefs schema missing updateCheck.${prop}"
99
- fi
100
- done
101
- if jq -e '.properties.global.properties.updateCheck.properties.enabled.default == true' "$PREFS_SCHEMA" >/dev/null 2>&1; then
102
- record_pass "updateCheck.enabled defaults to true (notify-only, bounded cost)"
103
- else
104
- record_fail "updateCheck.enabled must default to true"
105
- fi
106
- if jq -e '.properties.global.properties.updateCheck.properties.autoUpdate | has("default") and .default == false' "$PREFS_SCHEMA" >/dev/null 2>&1; then
107
- record_pass "updateCheck.autoUpdate defaults to false (no silent self-modify)"
108
- else
109
- record_fail "updateCheck.autoUpdate must default to false"
110
- fi
111
-
112
- # 5. Phase 0 doc wiring
113
- if grep -qF "Step 0.6 - Update check" "$PHASE0_DOC"; then
114
- record_pass "phase-0-init.md documents Step 0.6"
115
- else
116
- record_fail "phase-0-init.md missing Step 0.6"
117
- fi
118
- if grep -qF "update-check.sh" "$PHASE0_DOC"; then
119
- record_pass "phase-0-init.md invokes update-check.sh"
120
- else
121
- record_fail "phase-0-init.md must invoke update-check.sh"
122
- fi
123
- if grep -qF "log-only" "$PHASE0_DOC" && grep -qF "never ask (zero-interaction contract)" "$PHASE0_DOC"; then
124
- record_pass "phase-0-init.md states the autopilot log-only rule"
125
- else
126
- record_fail "phase-0-init.md must state autopilot never asks (log-only)"
127
- fi
128
-
129
- printf '\n══ update-check smoke: %d passed, %d failed ══\n' "$pass" "$fail"
130
- if [ "$fail" -gt 0 ]; then
131
- printf '\nFailures:\n'
132
- for msg in "${failures[@]}"; do printf ' - %s\n' "$msg"; done
133
- exit 1
134
- fi
135
- exit 0
@@ -1,70 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Smoke: Phase 0 Step 1b URL enrichment - Crashlytics + Fortify
3
- # Verifies that:
4
- # 1. phase-0-init.md documents Step 1b with both URL patterns
5
- # 2. state.crashContext and state.fortifyFinding shapes are specified
6
- # 3. prefs.schema.json has hosts.fortify
7
- # 4. setup.md Step 3.5 prompts for fortify host (and skips firebase)
8
- # 5. Token Save Flow routing includes fortify
9
-
10
- set -u
11
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
12
- PASS=0
13
- FAIL=0
14
-
15
- check() {
16
- local label="$1" cmd="$2"
17
- if eval "$cmd" > /dev/null 2>&1; then
18
- printf " ✓ %s\n" "$label"
19
- PASS=$((PASS+1))
20
- else
21
- printf " ✗ %s\n" "$label"
22
- FAIL=$((FAIL+1))
23
- fi
24
- }
25
-
26
- PHASE0="$ROOT/pipeline/multi-agent-refs/phases/phase-0-init.md"
27
- SETUP="$ROOT/pipeline/commands/multi-agent/setup/SKILL.md"
28
- SCHEMA="$ROOT/pipeline/schemas/prefs.schema.json"
29
-
30
- echo "→ 1. phase-0-init.md documents Step 1b URL Enrichment"
31
- check "Step 1b section present" "grep -Fq 'Step 1b - URL Enrichment' '$PHASE0'"
32
- check "Crashlytics pattern block present" "grep -Fq 'console.firebase.google.com' '$PHASE0'"
33
- check "Fortify pattern block present" "grep -Eq 'hosts\.fortify.*ssc/html|ssc/html.*version' '$PHASE0'"
34
-
35
- echo
36
- echo "→ 2. state enrichment shapes specified"
37
- check "state.crashContext documented" "grep -Fq 'state.crashContext' '$PHASE0'"
38
- check "state.fortifyFinding documented" "grep -Fq 'state.fortifyFinding' '$PHASE0'"
39
- check "Phase 1 prepend mention for crash" "grep -Fq 'Known Crash Context' '$PHASE0'"
40
- check "Phase 2 inject mention for fortify" "grep -Fq 'Known Security Finding' '$PHASE0'"
41
-
42
- echo
43
- echo "→ 3. Progress contract line documented"
44
- check "URL context log line shape" "grep -Fq 'URL deep fetch: crashlytics=' '$PHASE0'"
45
-
46
- echo
47
- echo "→ 4. prefs.schema.json has hosts.fortify"
48
- check "hosts.fortify field exists" "grep -Fq '\"fortify\":' '$SCHEMA' && grep -Fq 'Fortify SSC host' '$SCHEMA'"
49
- check "FORTIFY_HOST placeholder referenced" "grep -Fq '{FORTIFY_HOST}' '$SCHEMA'"
50
-
51
- echo
52
- echo "→ 5. Firebase description = 'Firebase JSON' (not 'SA JSON')"
53
- check "schema firebase (servicePatMap) renamed" "! grep -F 'Firebase Service Account JSON' '$SCHEMA'"
54
- check "schema firebase (keychainMapping) renamed" "grep -c '\"Firebase JSON' '$SCHEMA' | grep -q '[2-9]'"
55
-
56
- echo
57
- echo "→ 6. setup.md Step 3.5 routes fortify (not firebase)"
58
- check "Step 3.5 lists fortify" "grep -Eq 'jira.*confluence.*bitbucket.*fortify|fortify.*host' '$SETUP'"
59
- check "firebase skip note in Step 3.5" "grep -Fiq 'firebase is skipped' '$SETUP' || grep -Fiq 'Firebase tokens skip' '$SETUP'"
60
- check "Resulting shape has fortify host" "grep -Fq '\"fortify\":' '$SETUP'"
61
- check "FORTIFY_HOST placeholder listed" "grep -Fq '{FORTIFY_HOST}' '$SETUP'"
62
-
63
- echo
64
- echo "→ 7. Token Source Mapping shows 'Firebase JSON' label"
65
- check "setup.md Token Source Mapping renamed" "grep -Fq 'Firebase JSON (base64)' '$SETUP'"
66
- check "multi-agent-setup SKILL.md renamed" "grep -Fq 'Firebase JSON (base64)' '$ROOT/pipeline/skills/shared/core/multi-agent-setup/SKILL.md'"
67
-
68
- echo
69
- echo "══ url-enrichment smoke: $PASS passed, $FAIL failed ══"
70
- [ "$FAIL" -eq 0 ]
@@ -1,161 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-validate-analysis-doc.sh - contract for validate-analysis-doc.mjs,
3
- # the deterministic gate over an emitted /multi-agent:analysis document.
4
-
5
- set -uo pipefail
6
-
7
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8
- V="$SCRIPT_DIR/validate-analysis-doc.mjs"
9
-
10
- PASS=0
11
- FAIL=0
12
- record_pass() { PASS=$((PASS + 1)); printf ' \342\234\223 %s\n' "$1"; }
13
- record_fail() { FAIL=$((FAIL + 1)); printf ' \342\234\227 %s\n' "$1"; }
14
-
15
- printf '\342\206\222 smoke-validate-analysis-doc: emitted-doc gate\n'
16
-
17
- tmp=$(mktemp -d "${TMPDIR:-/tmp}/vdoc.XXXXXX")
18
- trap 'rm -rf "$tmp"' EXIT
19
-
20
- # A well-formed Full-mode doc (neutral UserProfile domain, BR referenced downstream).
21
- cat > "$tmp/good.md" <<'MD'
22
- ---
23
- feature: UserProfile
24
- platform: ios
25
- language: tr
26
- mode: full
27
- template_version: v3
28
- ---
29
- ## 1. Özet
30
- Profile screen.
31
- ## 2. Hedefler ve Karşı Hedefler
32
- goals.
33
- ## 4. Kullanıcı Hikayeleri
34
- ### 4.4 İş Kuralları
35
- | BR-profile-01 | rule | source | Given/When/Then |
36
- ## 9. API Kontratları
37
- api.
38
- ## 13. Mimari Plan
39
- arch.
40
- ## 14. Eklenecek Dosyalar
41
- files.
42
- ## 15. Test Planı
43
- BR-profile-01 happy path.
44
- ## 20. Riskler ve Açık Sorular
45
- risk.
46
- ## 21. Referanslar
47
- refs.
48
- MD
49
-
50
- if node "$V" "$tmp/good.md" >/dev/null 2>&1; then
51
- record_pass "well-formed Full doc passes (exit 0)"
52
- else
53
- record_fail "well-formed doc should pass"
54
- fi
55
-
56
- # Lite doc without Section 15 must still pass (Locked 31 mode-aware).
57
- cat > "$tmp/lite.md" <<'MD'
58
- ---
59
- feature: UserProfile
60
- platform: ios
61
- language: en
62
- mode: lite
63
- template_version: v3
64
- ---
65
- ## 1. Summary
66
- s
67
- ## 2. Goals and Non-Goals
68
- g
69
- ## 4. User Stories
70
- ### 4.4 Business Rules
71
- | BR-profile-01 | rule | source | Given/When/Then |
72
- ## 9. API Contracts
73
- a
74
- ## 13. Architecture
75
- x
76
- ## 14. Files to Add
77
- f
78
- ## 20. Risks and Open Questions
79
- r
80
- ## 21. References
81
- ref
82
- MD
83
- if node "$V" "$tmp/lite.md" >/dev/null 2>&1; then
84
- record_pass "Lite doc (no Section 15) passes - mode-aware Locked 31"
85
- else
86
- record_fail "Lite doc without Section 15 must pass"
87
- fi
88
-
89
- # Missing front-matter -> ERROR.
90
- printf '## 1. Summary\nno front matter\n' > "$tmp/nofm.md"
91
- node "$V" "$tmp/nofm.md" >/dev/null 2>&1
92
- [ "$?" -eq 1 ] && record_pass "missing front-matter fails (exit 1)" || record_fail "missing front-matter should fail"
93
-
94
- # Banned punctuation (em-dash) -> ERROR.
95
- cp "$tmp/good.md" "$tmp/emdash.md"
96
- printf 'A line with an em-dash \342\200\224 here.\n' >> "$tmp/emdash.md"
97
- # Capture first (pipefail + node's nonzero exit would poison a direct pipe).
98
- emdash_out=$(node "$V" "$tmp/emdash.md" 2>&1 || true)
99
- if printf '%s' "$emdash_out" | grep -q "em-dash"; then
100
- record_pass "em-dash flagged (Locked 7)"
101
- else
102
- record_fail "em-dash should be flagged"
103
- fi
104
-
105
- # Missing a never-omitted section (References) -> ERROR.
106
- grep -v "Referanslar\|References" "$tmp/good.md" > "$tmp/noref.md"
107
- node "$V" "$tmp/noref.md" >/dev/null 2>&1
108
- [ "$?" -eq 1 ] && record_pass "missing References section fails" || record_fail "missing References should fail"
109
-
110
- # Define-only BR under --strict -> fail (WARN promoted).
111
- cat > "$tmp/orphan.md" <<'MD'
112
- ---
113
- feature: UserProfile
114
- platform: ios
115
- language: en
116
- mode: full
117
- template_version: v3
118
- ---
119
- ## 1. Summary
120
- s
121
- ## 2. Goals
122
- g
123
- ## 4. User Stories
124
- ### 4.4 Business Rules
125
- | BR-profile-42 | rule | source | Given/When/Then |
126
- ## 9. API Contracts
127
- a
128
- ## 13. Architecture
129
- x
130
- ## 14. Files to Add
131
- f
132
- ## 15. Test Plan
133
- no BR reference here
134
- ## 20. Risks
135
- r
136
- ## 21. References
137
- ref
138
- MD
139
- node "$V" "$tmp/orphan.md" >/dev/null 2>&1
140
- [ "$?" -eq 0 ] && record_pass "define-only BR is WARN, not error (default)" || record_fail "orphan BR should not hard-fail by default"
141
- node "$V" "$tmp/orphan.md" --strict >/dev/null 2>&1
142
- [ "$?" -eq 1 ] && record_pass "define-only BR fails under --strict" || record_fail "orphan BR should fail under --strict"
143
-
144
- # ui_tests: true but no Section 15.6 -> ERROR.
145
- sed 's/^mode: full/mode: full\nui_tests: true\na11y_depth: basic/' "$tmp/good.md" > "$tmp/uimiss.md"
146
- node "$V" "$tmp/uimiss.md" >/dev/null 2>&1
147
- [ "$?" -eq 1 ] && record_pass "ui_tests:true without Section 15.6 fails" || record_fail "ui_tests:true must require 15.6"
148
-
149
- # ui_tests: true WITH a Section 15.6 heading -> passes.
150
- cp "$tmp/uimiss.md" "$tmp/uiok.md"
151
- printf '## 15.6 UI test senaryolari\nUI-profile-01 flow.\n' >> "$tmp/uiok.md"
152
- node "$V" "$tmp/uiok.md" >/dev/null 2>&1
153
- [ "$?" -eq 0 ] && record_pass "ui_tests:true with Section 15.6 passes" || record_fail "ui_tests:true + 15.6 should pass"
154
-
155
- # a11y_depth: full but no Section 16.2 walkthrough -> ERROR.
156
- sed 's/^mode: full/mode: full\nui_tests: false\na11y_depth: full/' "$tmp/good.md" > "$tmp/a11ymiss.md"
157
- node "$V" "$tmp/a11ymiss.md" >/dev/null 2>&1
158
- [ "$?" -eq 1 ] && record_pass "a11y_depth:full without Section 16.2 fails" || record_fail "a11y_depth:full must require 16.2"
159
-
160
- printf '\n\342\225\220\342\225\220 smoke-validate-analysis-doc: %d passed, %d failed \342\225\220\342\225\220\n' "$PASS" "$FAIL"
161
- [ "$FAIL" -eq 0 ]