@mmerterden/multi-agent-pipeline 12.7.0 → 12.8.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 (244) hide show
  1. package/CHANGELOG.md +126 -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/phases/operations.md +28 -0
  13. package/pipeline/multi-agent-refs/phases/phase-0-init.md +1 -0
  14. package/pipeline/multi-agent-refs/phases/phase-2-planning.md +1 -1
  15. package/pipeline/multi-agent-refs/phases/phase-3-dev.md +1 -2
  16. package/pipeline/multi-agent-refs/phases/phase-4-review.md +49 -4
  17. package/pipeline/schemas/prefs.schema.json +6 -0
  18. package/pipeline/scripts/_smoke-root.sh +61 -0
  19. package/pipeline/scripts/audit-log.sh +25 -0
  20. package/pipeline/scripts/smoke-cross-cli-behavior.sh +21 -7
  21. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-1-analysis.json +0 -25
  22. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-2-plan.json +0 -30
  23. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-4-review.json +0 -20
  24. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-4-triage.json +0 -15
  25. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/metadata.json +0 -14
  26. package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/task.json +0 -12
  27. package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-1-analysis.json +0 -29
  28. package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-2-plan.json +0 -43
  29. package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-4-review.json +0 -35
  30. package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-4-triage.json +0 -35
  31. package/pipeline/eval/golden-tasks/02-android-feature-compose/metadata.json +0 -14
  32. package/pipeline/eval/golden-tasks/02-android-feature-compose/task.json +0 -12
  33. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-1-analysis.json +0 -29
  34. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-2-plan.json +0 -42
  35. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-4-review.json +0 -20
  36. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-4-triage.json +0 -15
  37. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/metadata.json +0 -14
  38. package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/task.json +0 -12
  39. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-1-analysis.json +0 -29
  40. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-2-plan.json +0 -40
  41. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-4-review.json +0 -20
  42. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-4-triage.json +0 -15
  43. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/metadata.json +0 -14
  44. package/pipeline/eval/golden-tasks/04-frontend-next-hydration/task.json +0 -12
  45. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-1-analysis.json +0 -29
  46. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-2-plan.json +0 -42
  47. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-4-review.json +0 -28
  48. package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-4-triage.json +0 -27
  49. package/pipeline/eval/golden-tasks/05-ios-security-keychain/metadata.json +0 -14
  50. package/pipeline/eval/golden-tasks/05-ios-security-keychain/task.json +0 -12
  51. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-1-analysis.json +0 -29
  52. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-2-plan.json +0 -41
  53. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-4-review.json +0 -12
  54. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-4-triage.json +0 -6
  55. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/metadata.json +0 -14
  56. package/pipeline/eval/golden-tasks/06-android-refactor-usecase/task.json +0 -12
  57. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-1-analysis.json +0 -29
  58. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-2-plan.json +0 -42
  59. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-4-review.json +0 -28
  60. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-4-triage.json +0 -27
  61. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/metadata.json +0 -14
  62. package/pipeline/eval/golden-tasks/07-backend-node-idempotency/task.json +0 -12
  63. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-1-analysis.json +0 -25
  64. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-2-plan.json +0 -31
  65. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-4-review.json +0 -12
  66. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-4-triage.json +0 -18
  67. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/metadata.json +0 -14
  68. package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/task.json +0 -12
  69. package/pipeline/eval/golden-tasks/README.md +0 -65
  70. package/pipeline/eval/intent-cases.json +0 -40
  71. package/pipeline/eval/run-metrics-fixture.json +0 -93
  72. package/pipeline/eval/triage/01-empty-findings/expected.json +0 -6
  73. package/pipeline/eval/triage/01-empty-findings/input.json +0 -5
  74. package/pipeline/eval/triage/01-empty-findings/notes.md +0 -7
  75. package/pipeline/eval/triage/02-real-blocker/expected.json +0 -15
  76. package/pipeline/eval/triage/02-real-blocker/input.json +0 -14
  77. package/pipeline/eval/triage/02-real-blocker/notes.md +0 -7
  78. package/pipeline/eval/triage/03-out-of-scope-defer/expected.json +0 -18
  79. package/pipeline/eval/triage/03-out-of-scope-defer/input.json +0 -14
  80. package/pipeline/eval/triage/03-out-of-scope-defer/notes.md +0 -10
  81. package/pipeline/eval/triage/04-false-positive-reject/expected.json +0 -18
  82. package/pipeline/eval/triage/04-false-positive-reject/input.json +0 -14
  83. package/pipeline/eval/triage/04-false-positive-reject/notes.md +0 -10
  84. package/pipeline/eval/triage/05-mixed-classification/expected.json +0 -43
  85. package/pipeline/eval/triage/05-mixed-classification/input.json +0 -38
  86. package/pipeline/eval/triage/05-mixed-classification/notes.md +0 -17
  87. package/pipeline/eval/triage/06-severity-mismatch/expected.json +0 -15
  88. package/pipeline/eval/triage/06-severity-mismatch/input.json +0 -14
  89. package/pipeline/eval/triage/06-severity-mismatch/notes.md +0 -9
  90. package/pipeline/eval/triage/07-duplicate-reviewers/expected.json +0 -27
  91. package/pipeline/eval/triage/07-duplicate-reviewers/input.json +0 -22
  92. package/pipeline/eval/triage/07-duplicate-reviewers/notes.md +0 -9
  93. package/pipeline/eval/triage/08-style-misclassified/expected.json +0 -18
  94. package/pipeline/eval/triage/08-style-misclassified/input.json +0 -14
  95. package/pipeline/eval/triage/08-style-misclassified/notes.md +0 -9
  96. package/pipeline/eval/triage/09-cascading-finding/expected.json +0 -23
  97. package/pipeline/eval/triage/09-cascading-finding/input.json +0 -22
  98. package/pipeline/eval/triage/09-cascading-finding/notes.md +0 -9
  99. package/pipeline/eval/triage/10-deferred-crossref/expected.json +0 -18
  100. package/pipeline/eval/triage/10-deferred-crossref/input.json +0 -14
  101. package/pipeline/eval/triage/10-deferred-crossref/notes.md +0 -9
  102. package/pipeline/eval/triage/11-vercel-token-leak-blocker/expected.json +0 -27
  103. package/pipeline/eval/triage/11-vercel-token-leak-blocker/input.json +0 -22
  104. package/pipeline/eval/triage/11-vercel-token-leak-blocker/notes.md +0 -14
  105. package/pipeline/eval/triage/README.md +0 -54
  106. package/pipeline/scripts/benchmark-phase-0.sh +0 -128
  107. package/pipeline/scripts/check-md-links.mjs +0 -88
  108. package/pipeline/scripts/eval-golden-tasks-live.mjs +0 -302
  109. package/pipeline/scripts/eval-golden-tasks.mjs +0 -224
  110. package/pipeline/scripts/eval-intent.mjs +0 -107
  111. package/pipeline/scripts/eval-mine-corpus.mjs +0 -211
  112. package/pipeline/scripts/eval-triage.mjs +0 -171
  113. package/pipeline/scripts/fixtures/diff-risk-android.diff +0 -40
  114. package/pipeline/scripts/fixtures/diff-risk-ios.diff +0 -48
  115. package/pipeline/scripts/fixtures/diff-risk-test-removal.diff +0 -40
  116. package/pipeline/scripts/fixtures/install-layout.tsv +0 -19
  117. package/pipeline/scripts/fixtures/pack-expected-count.txt +0 -1
  118. package/pipeline/scripts/fixtures/test-gap-node.diff +0 -30
  119. package/pipeline/scripts/fixtures/test-gap-python.diff +0 -32
  120. package/pipeline/scripts/lint-mcp-refs.mjs +0 -218
  121. package/pipeline/scripts/lint-skills.mjs +0 -154
  122. package/pipeline/scripts/run-smokes.mjs +0 -130
  123. package/pipeline/scripts/scorecard.mjs +0 -258
  124. package/pipeline/scripts/smoke-add-detail.sh +0 -137
  125. package/pipeline/scripts/smoke-agent-guard.sh +0 -74
  126. package/pipeline/scripts/smoke-agent-log-cost.sh +0 -262
  127. package/pipeline/scripts/smoke-agent-model-routing.sh +0 -87
  128. package/pipeline/scripts/smoke-ask-choice.sh +0 -42
  129. package/pipeline/scripts/smoke-autopilot-circuit-breaker.sh +0 -36
  130. package/pipeline/scripts/smoke-bitbucket-contract.sh +0 -255
  131. package/pipeline/scripts/smoke-changelog-version.sh +0 -47
  132. package/pipeline/scripts/smoke-channels-approval-gate.sh +0 -60
  133. package/pipeline/scripts/smoke-channels-flow.sh +0 -130
  134. package/pipeline/scripts/smoke-ci-workflows.sh +0 -88
  135. package/pipeline/scripts/smoke-clarify.sh +0 -148
  136. package/pipeline/scripts/smoke-command-inventory.sh +0 -81
  137. package/pipeline/scripts/smoke-commands-skills-parity.sh +0 -87
  138. package/pipeline/scripts/smoke-community-gates.sh +0 -75
  139. package/pipeline/scripts/smoke-compliance-skills.sh +0 -119
  140. package/pipeline/scripts/smoke-config-hygiene.sh +0 -58
  141. package/pipeline/scripts/smoke-context-budget.sh +0 -72
  142. package/pipeline/scripts/smoke-cost-budget.sh +0 -70
  143. package/pipeline/scripts/smoke-cost-summary.sh +0 -139
  144. package/pipeline/scripts/smoke-cross-phase-cohesion.sh +0 -128
  145. package/pipeline/scripts/smoke-description-tr.sh +0 -82
  146. package/pipeline/scripts/smoke-dev-critic.sh +0 -144
  147. package/pipeline/scripts/smoke-diff-explain.sh +0 -147
  148. package/pipeline/scripts/smoke-diff-risk.sh +0 -190
  149. package/pipeline/scripts/smoke-dynamic-skill-loading.sh +0 -160
  150. package/pipeline/scripts/smoke-eval-live.sh +0 -136
  151. package/pipeline/scripts/smoke-evidence-gate.sh +0 -93
  152. package/pipeline/scripts/smoke-extract-conventions.sh +0 -163
  153. package/pipeline/scripts/smoke-fetchers-offline.sh +0 -448
  154. package/pipeline/scripts/smoke-figma-dispatch.sh +0 -112
  155. package/pipeline/scripts/smoke-gate-hooks.sh +0 -74
  156. package/pipeline/scripts/smoke-gc-tmp.sh +0 -130
  157. package/pipeline/scripts/smoke-gc-worktrees.sh +0 -125
  158. package/pipeline/scripts/smoke-generate-issue.sh +0 -120
  159. package/pipeline/scripts/smoke-handoff-contract.sh +0 -92
  160. package/pipeline/scripts/smoke-identity-isolation.sh +0 -70
  161. package/pipeline/scripts/smoke-install-layout.sh +0 -248
  162. package/pipeline/scripts/smoke-intent-guard.sh +0 -86
  163. package/pipeline/scripts/smoke-issue-comment-template.sh +0 -86
  164. package/pipeline/scripts/smoke-issue-jira-triad.sh +0 -120
  165. package/pipeline/scripts/smoke-keychain.sh +0 -158
  166. package/pipeline/scripts/smoke-language-axis.sh +0 -109
  167. package/pipeline/scripts/smoke-learning-curve.sh +0 -61
  168. package/pipeline/scripts/smoke-learnings-ledger.sh +0 -86
  169. package/pipeline/scripts/smoke-lib-scripts.sh +0 -448
  170. package/pipeline/scripts/smoke-mcp-gate.sh +0 -68
  171. package/pipeline/scripts/smoke-md-links.sh +0 -8
  172. package/pipeline/scripts/smoke-md2confluence.sh +0 -126
  173. package/pipeline/scripts/smoke-metrics-cache-ratio.sh +0 -72
  174. package/pipeline/scripts/smoke-migrate-state.sh +0 -102
  175. package/pipeline/scripts/smoke-mode-dispatch-drift.sh +0 -161
  176. package/pipeline/scripts/smoke-model-fallback.sh +0 -89
  177. package/pipeline/scripts/smoke-multi-repo-integration.sh +0 -116
  178. package/pipeline/scripts/smoke-multi-repo-worktree.sh +0 -61
  179. package/pipeline/scripts/smoke-no-mcp-in-dev-phases.sh +0 -194
  180. package/pipeline/scripts/smoke-no-token-prompt.sh +0 -85
  181. package/pipeline/scripts/smoke-own-punctuation.sh +0 -103
  182. package/pipeline/scripts/smoke-pack-contents.sh +0 -140
  183. package/pipeline/scripts/smoke-pat-audit.sh +0 -128
  184. package/pipeline/scripts/smoke-per-repo-memory.sh +0 -156
  185. package/pipeline/scripts/smoke-phase-0-multi-repo.sh +0 -170
  186. package/pipeline/scripts/smoke-phase-6-multi.sh +0 -79
  187. package/pipeline/scripts/smoke-phase-banner.sh +0 -101
  188. package/pipeline/scripts/smoke-phase-tracker.sh +0 -324
  189. package/pipeline/scripts/smoke-phase0-bridge-contract.sh +0 -241
  190. package/pipeline/scripts/smoke-phase4-gates.sh +0 -45
  191. package/pipeline/scripts/smoke-phase4-triage.sh +0 -229
  192. package/pipeline/scripts/smoke-plan-approval-gate.sh +0 -71
  193. package/pipeline/scripts/smoke-plan-safety.sh +0 -139
  194. package/pipeline/scripts/smoke-plan-todos.sh +0 -196
  195. package/pipeline/scripts/smoke-pr-review-actions.sh +0 -152
  196. package/pipeline/scripts/smoke-pre-commit.sh +0 -170
  197. package/pipeline/scripts/smoke-pref-migration.sh +0 -226
  198. package/pipeline/scripts/smoke-prefs-language.sh +0 -134
  199. package/pipeline/scripts/smoke-progress-contract.sh +0 -127
  200. package/pipeline/scripts/smoke-prune-logs.sh +0 -137
  201. package/pipeline/scripts/smoke-purge.sh +0 -138
  202. package/pipeline/scripts/smoke-push-retry.sh +0 -75
  203. package/pipeline/scripts/smoke-repo-map.sh +0 -300
  204. package/pipeline/scripts/smoke-review-readiness.sh +0 -92
  205. package/pipeline/scripts/smoke-review-watch.sh +0 -146
  206. package/pipeline/scripts/smoke-routines.sh +0 -84
  207. package/pipeline/scripts/smoke-run-aggregator.sh +0 -216
  208. package/pipeline/scripts/smoke-run-metrics.sh +0 -50
  209. package/pipeline/scripts/smoke-search.sh +0 -187
  210. package/pipeline/scripts/smoke-shadow-git.sh +0 -224
  211. package/pipeline/scripts/smoke-skill-authoring.sh +0 -137
  212. package/pipeline/scripts/smoke-skill-language.sh +0 -83
  213. package/pipeline/scripts/smoke-skill-manifest.sh +0 -138
  214. package/pipeline/scripts/smoke-skill-scan.sh +0 -198
  215. package/pipeline/scripts/smoke-source-parity.sh +0 -85
  216. package/pipeline/scripts/smoke-subagent-validators.sh +0 -108
  217. package/pipeline/scripts/smoke-sync-parity.sh +0 -92
  218. package/pipeline/scripts/smoke-tasklist-ordering.sh +0 -112
  219. package/pipeline/scripts/smoke-telemetry.sh +0 -147
  220. package/pipeline/scripts/smoke-test-gap.sh +0 -183
  221. package/pipeline/scripts/smoke-token-budget.sh +0 -67
  222. package/pipeline/scripts/smoke-token-preflight.sh +0 -82
  223. package/pipeline/scripts/smoke-tracker-contract.sh +0 -191
  224. package/pipeline/scripts/smoke-tracker-tokens-invocation.sh +0 -73
  225. package/pipeline/scripts/smoke-triage-memory.sh +0 -174
  226. package/pipeline/scripts/smoke-update-check.sh +0 -135
  227. package/pipeline/scripts/smoke-url-enrichment.sh +0 -70
  228. package/pipeline/scripts/smoke-validate-analysis-doc.sh +0 -161
  229. package/pipeline/scripts/smoke-validator-contradiction.sh +0 -67
  230. package/pipeline/scripts/smoke-validator-gates.sh +0 -164
  231. package/pipeline/scripts/smoke-vercel-deploy-redact.sh +0 -129
  232. package/pipeline/scripts/smoke-verify-by-test.sh +0 -148
  233. package/pipeline/scripts/smoke-wiki-integration.sh +0 -122
  234. package/pipeline/scripts/smoke-work-summary.sh +0 -163
  235. package/pipeline/scripts/smoke-workflow-audit.sh +0 -101
  236. package/pipeline/scripts/smoke-worktree-path-convention.sh +0 -86
  237. package/pipeline/scripts/smoke-wrapper-preservation.sh +0 -68
  238. package/pipeline/scripts/smoke-write-state.sh +0 -159
  239. package/pipeline/scripts/sync-parity-check.sh +0 -135
  240. package/pipeline/scripts/test-gap-rules/android.json +0 -25
  241. package/pipeline/scripts/test-gap-rules/ios.json +0 -34
  242. package/pipeline/scripts/test-gap-rules/node.json +0 -29
  243. package/pipeline/scripts/test-gap-rules/python.json +0 -25
  244. package/pipeline/scripts/validate-schemas.mjs +0 -88
@@ -1,248 +0,0 @@
1
- #!/usr/bin/env bash
2
- #
3
- # smoke-install-layout.sh - verify install.js shim + install/* modules produce
4
- # the same on-disk output as the pre-v8.0.0 monolithic installer.
5
- #
6
- # v8.0.0 split install.js (1246 LOC) into ./install/{index,claude,copilot,
7
- # _common,_platform-filter,_telemetry,_dev-only-files,
8
- # _copilot-instructions}.mjs. The legacy install.js stayed as a thin shim
9
- # that imports install/index.mjs and calls runInstall(process.argv).
10
- #
11
- # This smoke runs the live installer into a temp HOME and asserts:
12
- # 1. install runs without error for --claude, --copilot, and --all
13
- # 2. expected directory structure under ~/.claude and ~/.copilot is present
14
- # 3. core file counts match what the source ships
15
- # 4. settings.json hook + env are written
16
- # 5. CLAUDE.md / preferences template are written when missing
17
- # 6. copilot-instructions.md contains the pipeline marker block
18
- #
19
- # Failure here means the modular installer drifted from the legacy contract.
20
- # Fix by aligning install/*.mjs with the source tree, never by relaxing this
21
- # gate.
22
- #
23
- # Exit codes: 0=pass, 1=structural drift, 2=installer crash
24
-
25
- set -euo pipefail
26
-
27
- REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
28
- INSTALL_JS="$REPO_ROOT/install.js"
29
- INSTALL_DIR="$REPO_ROOT/install"
30
-
31
- [ -f "$INSTALL_JS" ] || { echo "FAIL: install.js missing"; exit 2; }
32
- [ -d "$INSTALL_DIR" ] || { echo "FAIL: install/ directory missing"; exit 2; }
33
-
34
- PASS=0
35
- FAIL=0
36
- note() { echo " → $*"; }
37
- pass() { echo " ✓ $*"; PASS=$((PASS + 1)); }
38
- fail() { echo " ✗ $*"; FAIL=$((FAIL + 1)); }
39
-
40
- assert_file() {
41
- local path="$1" label="$2"
42
- if [ -f "$path" ]; then pass "$label exists"; else fail "$label missing ($path)"; fi
43
- }
44
-
45
- assert_dir() {
46
- local path="$1" label="$2"
47
- if [ -d "$path" ]; then pass "$label exists"; else fail "$label missing ($path)"; fi
48
- }
49
-
50
- assert_dir_nonempty() {
51
- local path="$1" label="$2"
52
- if [ -d "$path" ] && [ "$(find "$path" -mindepth 1 -print -quit 2>/dev/null)" ]; then
53
- pass "$label populated"
54
- else
55
- fail "$label empty or missing ($path)"
56
- fi
57
- }
58
-
59
- # -----------------------------------------------------------------------------
60
- note "1. install/ module layout matches v8.0.0 split"
61
- # -----------------------------------------------------------------------------
62
- expected_modules=(
63
- "index.mjs"
64
- "claude.mjs"
65
- "copilot.mjs"
66
- "_common.mjs"
67
- "_platform-filter.mjs"
68
- "_telemetry.mjs"
69
- "_copilot-instructions.mjs"
70
- "_dev-only-files.mjs"
71
- )
72
- for mod in "${expected_modules[@]}"; do
73
- assert_file "$INSTALL_DIR/$mod" "install/$mod"
74
- done
75
-
76
- # -----------------------------------------------------------------------------
77
- note "2. install.js is a thin shim that imports install/index.mjs"
78
- # -----------------------------------------------------------------------------
79
- shim_lines=$(wc -l < "$INSTALL_JS" | tr -d ' ')
80
- if [ "$shim_lines" -lt 50 ]; then
81
- pass "install.js is $shim_lines lines (shim, <50)"
82
- else
83
- fail "install.js is $shim_lines lines - expected shim under 50"
84
- fi
85
- if grep -q "from \"./install/index.mjs\"" "$INSTALL_JS"; then
86
- pass "install.js delegates to install/index.mjs"
87
- else
88
- fail "install.js does not import install/index.mjs"
89
- fi
90
-
91
- # -----------------------------------------------------------------------------
92
- note "3. Live install --claude into temp HOME"
93
- # -----------------------------------------------------------------------------
94
- TMP_CLAUDE=$(mktemp -d)
95
- trap 'rm -rf "$TMP_CLAUDE" "$TMP_COPILOT" "$TMP_ALL" 2>/dev/null || true' EXIT
96
-
97
- if HOME="$TMP_CLAUDE" node "$INSTALL_JS" --claude > /tmp/smoke-install-layout-claude.log 2>&1; then
98
- pass "node install.js --claude exited 0"
99
- else
100
- fail "install --claude crashed - see /tmp/smoke-install-layout-claude.log"
101
- exit 2
102
- fi
103
-
104
- assert_dir_nonempty "$TMP_CLAUDE/.claude/commands/multi-agent" "~/.claude/commands/multi-agent"
105
- assert_dir_nonempty "$TMP_CLAUDE/.claude/scripts" "~/.claude/scripts"
106
- assert_dir_nonempty "$TMP_CLAUDE/.claude/agents" "~/.claude/agents"
107
- assert_dir_nonempty "$TMP_CLAUDE/.claude/rules" "~/.claude/rules"
108
- assert_dir_nonempty "$TMP_CLAUDE/.claude/skills" "~/.claude/skills"
109
- assert_file "$TMP_CLAUDE/.claude/CLAUDE.md" "~/.claude/CLAUDE.md"
110
- assert_file "$TMP_CLAUDE/.claude/multi-agent-preferences.json" "~/.claude/multi-agent-preferences.json"
111
- assert_file "$TMP_CLAUDE/.claude/settings.json" "~/.claude/settings.json"
112
-
113
- # settings.json must have the secret-detection hook. v11.4.1 changed the
114
- # matcher from the dead "Bash(git commit:*)" (tool-name matchers never matched
115
- # it) to "Bash"; command-level filtering happens inside pre-commit-check.sh.
116
- if grep -q '"matcher": "Bash"' "$TMP_CLAUDE/.claude/settings.json" \
117
- && grep -q "pre-commit-check.sh" "$TMP_CLAUDE/.claude/settings.json"; then
118
- pass "settings.json registers PreToolUse secret-scan hook (matcher Bash)"
119
- else
120
- fail "settings.json missing PreToolUse secret-scan hook with matcher Bash"
121
- fi
122
- if grep -q "Bash(git commit:\*)" "$TMP_CLAUDE/.claude/settings.json"; then
123
- fail "settings.json still contains the dead Bash(git commit:*) matcher"
124
- else
125
- pass "settings.json has no dead Bash(git commit:*) matcher"
126
- fi
127
- if grep -q "CLAUDE_AUTOCOMPACT_PCT_OVERRIDE" "$TMP_CLAUDE/.claude/settings.json"; then
128
- pass "settings.json sets CLAUDE_AUTOCOMPACT_PCT_OVERRIDE"
129
- else
130
- fail "settings.json missing CLAUDE_AUTOCOMPACT_PCT_OVERRIDE env"
131
- fi
132
-
133
- # Claude side must have the multi-agent skill dirs pruned (slash commands cover
134
- # them). Confirm by absence of any `multi-agent` directory under skills/.
135
- if find "$TMP_CLAUDE/.claude/skills" -maxdepth 1 -type d -name 'multi-agent*' | grep -q .; then
136
- fail "~/.claude/skills/ still contains multi-agent-* dirs (should be pruned)"
137
- else
138
- pass "~/.claude/skills/ has multi-agent-* skill dirs pruned"
139
- fi
140
-
141
- # -----------------------------------------------------------------------------
142
- note "4. Live install --copilot into a fresh temp HOME"
143
- # -----------------------------------------------------------------------------
144
- TMP_COPILOT=$(mktemp -d)
145
- if HOME="$TMP_COPILOT" node "$INSTALL_JS" --copilot > /tmp/smoke-install-layout-copilot.log 2>&1; then
146
- pass "node install.js --copilot exited 0"
147
- else
148
- fail "install --copilot crashed - see /tmp/smoke-install-layout-copilot.log"
149
- exit 2
150
- fi
151
-
152
- assert_file "$TMP_COPILOT/.copilot/copilot-instructions.md" "~/.copilot/copilot-instructions.md"
153
- assert_dir_nonempty "$TMP_COPILOT/.copilot/scripts" "~/.copilot/scripts"
154
- assert_dir_nonempty "$TMP_COPILOT/.copilot/agents" "~/.copilot/agents"
155
- assert_dir_nonempty "$TMP_COPILOT/.copilot/skills" "~/.copilot/skills"
156
-
157
- if grep -q "^# Multi-Agent Development Pipeline" "$TMP_COPILOT/.copilot/copilot-instructions.md"; then
158
- pass "copilot-instructions.md has pipeline marker"
159
- else
160
- fail "copilot-instructions.md missing pipeline marker"
161
- fi
162
-
163
- # Copilot side keeps multi-agent-* skill dirs (no slash commands there)
164
- if find "$TMP_COPILOT/.copilot/skills" -maxdepth 1 -type d -name 'multi-agent*' | grep -q .; then
165
- pass "~/.copilot/skills/ retains multi-agent-* dirs (Copilot uses skills as commands)"
166
- else
167
- fail "~/.copilot/skills/ missing multi-agent-* dirs (Copilot needs them)"
168
- fi
169
-
170
- # -----------------------------------------------------------------------------
171
- note "5. Live install --all writes both targets in one pass"
172
- # -----------------------------------------------------------------------------
173
- TMP_ALL=$(mktemp -d)
174
- if HOME="$TMP_ALL" node "$INSTALL_JS" --all > /tmp/smoke-install-layout-all.log 2>&1; then
175
- pass "node install.js --all exited 0"
176
- else
177
- fail "install --all crashed - see /tmp/smoke-install-layout-all.log"
178
- exit 2
179
- fi
180
- assert_dir_nonempty "$TMP_ALL/.claude" "~/.claude (--all)"
181
- assert_dir_nonempty "$TMP_ALL/.copilot" "~/.copilot (--all)"
182
-
183
- # -----------------------------------------------------------------------------
184
- note "6. Cross-target file-count parity for shared scripts"
185
- # -----------------------------------------------------------------------------
186
- claude_scripts=$(find "$TMP_ALL/.claude/scripts" -type f 2>/dev/null | wc -l | tr -d ' ')
187
- copilot_scripts=$(find "$TMP_ALL/.copilot/scripts" -type f 2>/dev/null | wc -l | tr -d ' ')
188
- if [ "$claude_scripts" = "$copilot_scripts" ] && [ "$claude_scripts" -gt 0 ]; then
189
- pass "scripts file count parity ($claude_scripts files in both)"
190
- else
191
- fail "scripts file count drift: claude=$claude_scripts copilot=$copilot_scripts"
192
- fi
193
-
194
- claude_agents=$(find "$TMP_ALL/.claude/agents" -type f 2>/dev/null | wc -l | tr -d ' ')
195
- copilot_agents=$(find "$TMP_ALL/.copilot/agents" -type f 2>/dev/null | wc -l | tr -d ' ')
196
- if [ "$claude_agents" = "$copilot_agents" ] && [ "$claude_agents" -gt 0 ]; then
197
- pass "agents file count parity ($claude_agents files in both)"
198
- else
199
- fail "agents file count drift: claude=$claude_agents copilot=$copilot_agents"
200
- fi
201
-
202
- # -----------------------------------------------------------------------------
203
- echo ""
204
- echo "→ 7. v8.0.0 layout fingerprint matches the fixture"
205
- # -----------------------------------------------------------------------------
206
- # Compare a path → file-count fingerprint against pipeline/scripts/fixtures/
207
- # install-layout.tsv. This catches structural drift (a directory renamed,
208
- # a file moved out of the install tree, the skills tree losing a category)
209
- # while staying robust to legitimate skill content edits.
210
- #
211
- # To regenerate the fixture after an intentional layout change:
212
- # tmp=$(mktemp -d) && HOME="$tmp" node install.js --all >/dev/null 2>&1
213
- # ( cd "$tmp" && find . -type f | awk -F/ '{ print $2"/"$3 }' \
214
- # | LC_ALL=C sort -u | while read d; do
215
- # c=$(find "$d" -type f 2>/dev/null | wc -l | tr -d ' ')
216
- # printf '%s\t%s\n' "$d" "$c"
217
- # done ) > pipeline/scripts/fixtures/install-layout.tsv
218
- FIXTURE="$REPO_ROOT/pipeline/scripts/fixtures/install-layout.tsv"
219
- if [ ! -f "$FIXTURE" ]; then
220
- fail "install-layout.tsv fixture missing - see header for regeneration recipe"
221
- else
222
- ACTUAL_FP=$(
223
- cd "$TMP_ALL" && find . -type f \
224
- | awk -F/ '{ print $2"/"$3 }' \
225
- | LC_ALL=C sort -u \
226
- | while read d; do
227
- c=$(find "$d" -type f 2>/dev/null | wc -l | tr -d ' ')
228
- printf '%s\t%s\n' "$d" "$c"
229
- done
230
- )
231
- # Normalize both sides to a trailing newline before hashing - the fixture
232
- # is committed with one, the in-shell capture lacks one. Without this, the
233
- # smoke would always fail on the byte-level diff.
234
- if [ "$(printf '%s\n' "$ACTUAL_FP" | shasum -a 256 | cut -d' ' -f1)" = \
235
- "$(shasum -a 256 < "$FIXTURE" | cut -d' ' -f1)" ]; then
236
- pass "install layout fingerprint matches fixture"
237
- else
238
- fail "install layout drift - fingerprint changed"
239
- diff <(printf '%s\n' "$ACTUAL_FP") "$FIXTURE" | head -20 | sed 's/^/ /'
240
- fi
241
- fi
242
-
243
- # -----------------------------------------------------------------------------
244
- echo ""
245
- echo "══ smoke-install-layout: $PASS passed, $FAIL failed ══"
246
-
247
- if [ "$FAIL" -gt 0 ]; then exit 1; fi
248
- exit 0
@@ -1,86 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-intent-guard.sh - contract check for the Phase 0 conceptual-vs-edit guard.
3
- #
4
- # Verifies:
5
- # 1. classify-intent.sh returns task|question|ambiguous for representative
6
- # EN + TR inputs (the deterministic classifier the guard relies on).
7
- # 2. Imperative verbs win over a trailing "?" (actionable requests are tasks).
8
- # 3. Empty input is ambiguous (never blocks).
9
- # 4. phase-0-init.md documents the guard and prefs.schema.json exposes the toggle.
10
- #
11
- # Exit 0 = all pass, 1 = any failure.
12
-
13
- set -uo pipefail
14
-
15
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
16
- CLASSIFY="$ROOT/pipeline/lib/classify-intent.sh"
17
- PHASE0="$ROOT/pipeline/multi-agent-refs/phases/phase-0-init.md"
18
- PREFS="$ROOT/pipeline/schemas/prefs.schema.json"
19
-
20
- PASS=0
21
- FAIL=0
22
- pass() { PASS=$((PASS+1)); echo " ✓ $1"; }
23
- fail() { FAIL=$((FAIL+1)); echo " ✗ $1"; }
24
-
25
- [ -f "$CLASSIFY" ] || { echo "FAIL: classify-intent.sh missing" >&2; exit 1; }
26
-
27
- expect() {
28
- local input="$1" want="$2"
29
- local got
30
- got="$(bash "$CLASSIFY" "$input")"
31
- if [ "$got" = "$want" ]; then
32
- pass "[$want] $input"
33
- else
34
- fail "expected [$want] got [$got] for: $input"
35
- fi
36
- }
37
-
38
- echo "→ 1. Questions (no dev chain)"
39
- expect "how does the login flow work?" question
40
- expect "should I use Keychain or UserDefaults?" question
41
- expect "explain the auth module" question
42
- expect "nasıl çalışıyor bu akış?" question
43
- expect "Keychain mı UserDefaults mı kullanmalıyım?" question
44
-
45
- echo ""
46
- echo "→ 2. Tasks (proceed to dev chain)"
47
- expect "fix the login bug" task
48
- expect "refactor the cache layer" task
49
- expect "LoginView dark mode fix" task
50
- expect "login ekranına retry ekle" task
51
-
52
- echo ""
53
- echo "→ 3. Polite request beats interrogative; interrogative beats bare imperative"
54
- expect "can you add a retry to the network layer?" task
55
- expect "can you split this file" task
56
- expect "please rename the helper" task
57
- # Regression: action verb inside a question must NOT be read as a task
58
- expect "does it support offline mode" question
59
- expect "should we enable caching" question
60
-
61
- echo ""
62
- echo "→ 4. Empty / vague"
63
- expect "" ambiguous
64
- expect "the navigation feels slow" ambiguous
65
-
66
- echo ""
67
- echo "→ 5. Wiring + docs"
68
- if grep -q "classify-intent.sh" "$PHASE0"; then
69
- pass "phase-0-init.md invokes classify-intent.sh"
70
- else
71
- fail "phase-0-init.md does not reference the guard"
72
- fi
73
- if grep -q "Intent guard" "$PHASE0"; then
74
- pass "phase-0-init.md documents the intent guard step"
75
- else
76
- fail "phase-0-init.md missing intent-guard step"
77
- fi
78
- if grep -q '"intentGuard"' "$PREFS"; then
79
- pass "prefs.schema.json exposes intentGuard toggle"
80
- else
81
- fail "prefs.schema.json missing intentGuard"
82
- fi
83
-
84
- echo ""
85
- echo "══ intent-guard smoke: $PASS passed, $FAIL failed ══"
86
- [ "$FAIL" -eq 0 ]
@@ -1,86 +0,0 @@
1
- #!/usr/bin/env bash
2
- #
3
- # smoke-issue-comment-template.sh
4
- #
5
- # Asserts the canonical issue comment template (refs/channels/issue-comment.md)
6
- # is wired into Phase 7 and that the template file itself contains the required
7
- # section anchors.
8
- #
9
- # This is a lint, not a behavioural test - it does NOT post a real comment.
10
- # A behavioural drift check (regex against the most recent 5 issue comments by
11
- # the configured Git identity) lives in the e2e suite.
12
-
13
- set -euo pipefail
14
-
15
- SELF_DIR=$(cd "$(dirname "$0")" && pwd)
16
- PIPELINE_ROOT=$(cd "$SELF_DIR/.." && pwd)
17
-
18
- cd "$PIPELINE_ROOT"
19
-
20
- FAIL=0
21
-
22
- TEMPLATE="multi-agent-refs/channels/issue-comment.md"
23
- PHASE7="multi-agent-refs/phases/phase-7-report.md"
24
-
25
- # 1. Template file exists.
26
- if [ ! -f "$TEMPLATE" ]; then
27
- echo "FAIL [smoke-issue-comment-template]: $TEMPLATE missing"
28
- exit 1
29
- fi
30
-
31
- # 2. Template contains all canonical section anchors (English versions; the TR
32
- # headers map 1:1 via the template's bilingual contract).
33
- declare -a REQUIRED_ANCHORS=(
34
- "Geliştirme Detayı"
35
- "Pull Requests / Branches"
36
- "Acceptance Criteria"
37
- "Build & Test"
38
- "Sonraki Adımlar"
39
- "Ref: #"
40
- )
41
-
42
- for anchor in "${REQUIRED_ANCHORS[@]}"; do
43
- if ! grep -qF "$anchor" "$TEMPLATE"; then
44
- echo "FAIL [smoke-issue-comment-template]: template missing required anchor: $anchor"
45
- FAIL=$((FAIL + 1))
46
- fi
47
- done
48
-
49
- # 3. Phase 7 wires the issue channel - must reference both the template and
50
- # the progress sync script in the same step.
51
- if ! grep -qF "refs/channels/issue-comment.md" "$PHASE7"; then
52
- echo "FAIL [smoke-issue-comment-template]: $PHASE7 must reference refs/channels/issue-comment.md"
53
- FAIL=$((FAIL + 1))
54
- fi
55
-
56
- if ! grep -qF "update-issue-progress.sh" "$PHASE7"; then
57
- echo "FAIL [smoke-issue-comment-template]: $PHASE7 must wire update-issue-progress.sh"
58
- FAIL=$((FAIL + 1))
59
- fi
60
-
61
- # 4. The two paired actions (comment + flag sync) must appear in the same step
62
- # block - comment FIRST, flags SECOND.
63
- COMMENT_LINE=$(grep -n "gh issue comment" "$PHASE7" | head -1 | cut -d: -f1 || echo "")
64
- SYNC_LINE=$(grep -n "update-issue-progress.sh" "$PHASE7" | head -1 | cut -d: -f1 || echo "")
65
-
66
- if [ -n "$COMMENT_LINE" ] && [ -n "$SYNC_LINE" ]; then
67
- if [ "$COMMENT_LINE" -gt "$SYNC_LINE" ]; then
68
- echo "FAIL [smoke-issue-comment-template]: comment must precede progress sync in $PHASE7 (comment line $COMMENT_LINE > sync line $SYNC_LINE)"
69
- FAIL=$((FAIL + 1))
70
- fi
71
- fi
72
-
73
- # 5. update-issue-progress.sh exists and is executable.
74
- PROGRESS_SCRIPT="scripts/update-issue-progress.sh"
75
- if [ ! -x "$PROGRESS_SCRIPT" ]; then
76
- echo "FAIL [smoke-issue-comment-template]: $PROGRESS_SCRIPT missing or not executable"
77
- FAIL=$((FAIL + 1))
78
- fi
79
-
80
- if [ "$FAIL" -gt 0 ]; then
81
- echo ""
82
- echo "smoke-issue-comment-template: $FAIL violation(s)."
83
- exit 1
84
- fi
85
-
86
- echo "smoke-issue-comment-template: ok"
@@ -1,120 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-issue-jira-triad.sh - WS-6 contract for issue → jira → wiki triad.
3
- #
4
- # Verifies:
5
- # 1. prefs.schema.json declares autoJiraFromGithubIssue (enum ask/always/never).
6
- # 2. prefs.schema.json declares wikiToJiraComment (bool, default true).
7
- # 3. Phase 0 Step 1 GitHub-issue path references the triad policy.
8
- # 4. Phase 7 Report Step 2 mentions the wiki → Jira comment pass.
9
- # 5. refs/issue-jira-triad.md exists with the canonical sections.
10
- # 6. Autopilot semantics documented (ask → always under autopilot).
11
-
12
- set -euo pipefail
13
-
14
- HERE="$(cd "$(dirname "$0")" && pwd)"
15
- ROOT="$(cd "$HERE/../.." && pwd)"
16
- PREFS="$ROOT/pipeline/schemas/prefs.schema.json"
17
- PHASE0="$ROOT/pipeline/multi-agent-refs/phases/phase-0-init.md"
18
- PHASE7="$ROOT/pipeline/multi-agent-refs/phases/phase-7-report.md"
19
- TRIAD="$ROOT/pipeline/multi-agent-refs/issue-jira-triad.md"
20
-
21
- PASS=0
22
- FAIL=0
23
- pass() { PASS=$((PASS+1)); echo " ✓ $1"; }
24
- fail() { FAIL=$((FAIL+1)); echo " ✗ $1"; }
25
-
26
- need() { command -v "$1" >/dev/null 2>&1 || { echo "error: $1 required" >&2; exit 127; }; }
27
- need jq
28
-
29
- for f in "$PREFS" "$PHASE0" "$PHASE7" "$TRIAD"; do
30
- [ -f "$f" ] || { echo "error: missing $f" >&2; exit 1; }
31
- done
32
-
33
- echo "→ 1. prefs declares autoJiraFromGithubIssue"
34
- ENUM=$(jq -c '.properties.global.properties.autoJiraFromGithubIssue.enum' "$PREFS")
35
- EXPECTED='["ask","always","never"]'
36
- [ "$ENUM" = "$EXPECTED" ] && pass "autoJiraFromGithubIssue enum exact match" || fail "enum mismatch: $ENUM"
37
- DEFAULT=$(jq -r '.properties.global.properties.autoJiraFromGithubIssue.default' "$PREFS")
38
- [ "$DEFAULT" = "ask" ] && pass "default = ask" || fail "default = '$DEFAULT' (want ask)"
39
-
40
- echo ""
41
- echo "→ 2. prefs declares wikiToJiraComment (bool, default true)"
42
- TYPE=$(jq -r '.properties.global.properties.wikiToJiraComment.type // "missing"' "$PREFS")
43
- WTJ_DEFAULT=$(jq -r '.properties.global.properties.wikiToJiraComment.default // "missing"' "$PREFS")
44
- [ "$TYPE" = "boolean" ] && pass "wikiToJiraComment is boolean" || fail "type = '$TYPE'"
45
- [ "$WTJ_DEFAULT" = "true" ] && pass "wikiToJiraComment default = true" || fail "default = '$WTJ_DEFAULT'"
46
-
47
- echo ""
48
- echo "→ 3. Phase 0 Step 1 (GitHub issue) points at the triad policy"
49
- if grep -Fq "GitHub-issue Jira auto-create" "$PHASE0" || grep -Fq "autoJiraFromGithubIssue" "$PHASE0"; then
50
- pass "Phase 0 references the auto-create policy"
51
- else
52
- fail "Phase 0 missing auto-create reference"
53
- fi
54
- if grep -Fq "issue-jira-triad.md" "$PHASE0"; then
55
- pass "Phase 0 links to the triad ref doc"
56
- else
57
- fail "Phase 0 missing link to refs/issue-jira-triad.md"
58
- fi
59
-
60
- echo ""
61
- echo "→ 4. Channels Wiki adapter documents wiki → Jira auto-link"
62
- CHANNELS="$(cd "$HERE/../.." && pwd)/pipeline/commands/multi-agent/channels/SKILL.md"
63
- if grep -Fq "Wiki → Jira" "$CHANNELS" || grep -Fq "wiki summary to Jira" "$CHANNELS" \
64
- || grep -Fq "Wiki → Jira comment" "$CHANNELS" || grep -Fq "wiki pages" "$CHANNELS"; then
65
- pass "channels.md documents the wiki → Jira report"
66
- else
67
- fail "channels.md missing wiki → Jira report"
68
- fi
69
- if grep -Fq "wikiToJiraComment" "$CHANNELS"; then
70
- pass "channels.md references wikiToJiraComment preference"
71
- else
72
- fail "channels.md missing wikiToJiraComment reference"
73
- fi
74
-
75
- echo ""
76
- echo "→ 5. triad ref doc has canonical sections"
77
- for section in "## The triad at a glance" "## Phase 0 auto-create policy" "## Phase 7 wiki → Jira comment" "## Autopilot behaviour" "## Cross-CLI parity"; do
78
- if grep -Fq "$section" "$TRIAD"; then
79
- pass "section present: $section"
80
- else
81
- fail "section missing: $section"
82
- fi
83
- done
84
-
85
- echo ""
86
- echo "→ 6. autopilot forces ask → always"
87
- # Look for the table row "treat as `always`" OR the prose "ask` → `always`".
88
- if grep -Fq "treat as \`always\`" "$TRIAD" || grep -qE 'ask[^a-z]{1,6}always' "$TRIAD"; then
89
- pass "autopilot override documented"
90
- else
91
- fail "autopilot override missing"
92
- fi
93
-
94
- echo ""
95
- echo "→ 7. GitHub-issue body patched after create"
96
- if grep -Fq "Patch the GitHub issue body" "$TRIAD" || grep -Fq "patch the GitHub issue body" "$TRIAD"; then
97
- pass "body-patch step documented"
98
- else
99
- fail "body-patch step missing"
100
- fi
101
-
102
- echo ""
103
- echo "→ 8. humanizer skill mandatory on wiki → Jira comment"
104
- if grep -qi "humanizer" "$TRIAD"; then
105
- pass "humanizer referenced"
106
- else
107
- fail "humanizer not referenced"
108
- fi
109
-
110
- echo ""
111
- echo "→ 9. failure isolation documented"
112
- if grep -Fq "non-blocking" "$TRIAD" || grep -Fq "do not halt" "$TRIAD" || grep -Fq "Failure isolation" "$TRIAD"; then
113
- pass "failure isolation documented"
114
- else
115
- fail "failure isolation not documented"
116
- fi
117
-
118
- echo ""
119
- echo "══ issue-jira-triad smoke: $PASS passed, $FAIL failed ══"
120
- [ "$FAIL" -eq 0 ]