@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,130 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-gc-tmp.sh - gc-tmp.sh sweeps only known scratch prefixes, is dry-run
3
- # by default, never touches unrelated files, refuses unsafe scratch roots,
4
- # never deletes the root itself, and spares fresh scratch by default.
5
- #
6
- # Exit 0 = all pass, 1 = any failure.
7
-
8
- set -uo pipefail
9
-
10
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
11
- GC="$ROOT/pipeline/scripts/gc-tmp.sh"
12
- PASS=0
13
- FAIL=0
14
- pass() {
15
- PASS=$((PASS + 1))
16
- echo " ✓ $1"
17
- }
18
- fail() {
19
- FAIL=$((FAIL + 1))
20
- echo " ✗ $1"
21
- }
22
- [ -f "$GC" ] || {
23
- echo "FAIL: gc-tmp.sh missing" >&2
24
- exit 1
25
- }
26
-
27
- SB="$(mktemp -d)"
28
- trap 'rm -rf "$SB"' EXIT
29
-
30
- seed() {
31
- rm -rf "${SB:?}"/*
32
- mkdir -p "$SB/multi-agent-review-PROJ-1-x" "$SB/analysis-foo-123"
33
- touch "$SB/multi-agent-picker-PROJ-1.json" \
34
- "$SB/issue-progress-PROJ-1-ab.md" \
35
- "$SB/channels-PROJ-1-pr.md" \
36
- "$SB/context-links-PROJ-1.json" \
37
- "$SB/context-by-type-PROJ-1.json" \
38
- "$SB/unrelated-file.txt"
39
- }
40
-
41
- echo "→ 1. dry-run lists matches and deletes nothing"
42
- seed
43
- before=$(find "$SB" -mindepth 1 | wc -l | tr -d ' ')
44
- out=$(GC_TMP_ROOT="$SB" GC_TMP_GRACE_MIN=0 bash "$GC" 2>&1)
45
- after=$(find "$SB" -mindepth 1 | wc -l | tr -d ' ')
46
- echo "$out" | grep -q "DRY-RUN" && pass "dry-run banner shown" || fail "dry-run banner missing"
47
- [ "$before" = "$after" ] && pass "dry-run deleted nothing ($after entries intact)" || fail "dry-run changed the tree ($before -> $after)"
48
- echo "$out" | grep -q "unrelated-file.txt" && fail "dry-run matched an unrelated file" || pass "unrelated file not matched"
49
-
50
- echo ""
51
- echo "→ 2. --yes removes only matched scratch"
52
- seed
53
- GC_TMP_ROOT="$SB" GC_TMP_GRACE_MIN=0 bash "$GC" --yes >/dev/null 2>&1
54
- [ -f "$SB/unrelated-file.txt" ] && pass "unrelated file preserved" || fail "unrelated file was deleted"
55
- [ ! -e "$SB/multi-agent-picker-PROJ-1.json" ] && pass "multi-agent-* file removed" || fail "multi-agent-* file survived"
56
- [ ! -e "$SB/multi-agent-review-PROJ-1-x" ] && pass "scratch dir removed" || fail "scratch dir survived"
57
- [ ! -e "$SB/analysis-foo-123" ] && pass "analysis draft dir removed" || fail "analysis draft survived"
58
- [ ! -e "$SB/channels-PROJ-1-pr.md" ] && pass "channels payload removed" || fail "channels payload survived"
59
- remaining=$(find "$SB" -mindepth 1 | wc -l | tr -d ' ')
60
- [ "$remaining" = "1" ] && pass "exactly the 1 unrelated entry remains" || fail "expected 1 survivor, got $remaining"
61
-
62
- echo ""
63
- echo "→ 3. --older-than excludes fresh scratch"
64
- seed
65
- out=$(GC_TMP_ROOT="$SB" GC_TMP_GRACE_MIN=0 bash "$GC" --older-than=1 2>&1)
66
- echo "$out" | grep -q "nothing to do" && pass "freshly-created scratch excluded by --older-than=1" || fail "--older-than did not exclude fresh files"
67
-
68
- echo ""
69
- echo "→ 4. usage errors exit 2"
70
- GC_TMP_ROOT="$SB" bash "$GC" --bogus >/dev/null 2>&1
71
- [ "$?" = "2" ] && pass "unknown argument exits 2" || fail "unknown argument did not exit 2"
72
- GC_TMP_ROOT="$SB" bash "$GC" --older-than=abc >/dev/null 2>&1
73
- [ "$?" = "2" ] && pass "non-numeric --older-than exits 2" || fail "bad --older-than did not exit 2"
74
-
75
- echo ""
76
- echo "→ 5. empty root is a clean no-op"
77
- EMPTY="$(mktemp -d)"
78
- out=$(GC_TMP_ROOT="$EMPTY" bash "$GC" 2>&1)
79
- rc=$?
80
- rm -rf "$EMPTY"
81
- { [ "$rc" = "0" ] && echo "$out" | grep -q "nothing to do"; } && pass "empty root exits 0 with no-op message" || fail "empty root not a clean no-op"
82
-
83
- echo ""
84
- echo "→ 6. unsafe scratch roots are refused (exit 2)"
85
- GC_TMP_ROOT="$HOME" bash "$GC" >/dev/null 2>&1
86
- [ "$?" = "2" ] && pass "\$HOME as scratch root refused" || fail "\$HOME as scratch root not refused"
87
- GC_TMP_ROOT="/" bash "$GC" >/dev/null 2>&1
88
- [ "$?" = "2" ] && pass "/ as scratch root refused" || fail "/ as scratch root not refused"
89
- GITROOT="$(mktemp -d)"
90
- mkdir -p "$GITROOT/.git"
91
- touch "$GITROOT/multi-agent-bait.json"
92
- GC_TMP_ROOT="$GITROOT" bash "$GC" --yes >/dev/null 2>&1
93
- rc=$?
94
- [ "$rc" = "2" ] && pass "git work tree as scratch root refused" || fail "git work tree as scratch root not refused"
95
- [ -f "$GITROOT/multi-agent-bait.json" ] && pass "bait file inside refused root untouched" || fail "refused root was still swept"
96
- rm -rf "$GITROOT"
97
-
98
- echo ""
99
- echo "→ 7. a root itself named like scratch is never deleted"
100
- SR="$(mktemp -d)"
101
- mkdir -p "$SR/multi-agent-root"
102
- touch "$SR/multi-agent-root/multi-agent-inner.json"
103
- GC_TMP_ROOT="$SR/multi-agent-root" GC_TMP_GRACE_MIN=0 bash "$GC" --yes >/dev/null 2>&1
104
- [ -d "$SR/multi-agent-root" ] && pass "matching-named root survives --yes" || fail "root dir itself was deleted"
105
- [ ! -e "$SR/multi-agent-root/multi-agent-inner.json" ] && pass "inner scratch still removed" || fail "inner scratch survived"
106
- rm -rf "$SR"
107
-
108
- echo ""
109
- echo "→ 8. symlinked scratch is unlinked without following it"
110
- seed
111
- VICTIM="$(mktemp -d)"
112
- echo keep >"$VICTIM/keep.txt"
113
- ln -s "$VICTIM" "$SB/multi-agent-linked"
114
- GC_TMP_ROOT="$SB" GC_TMP_GRACE_MIN=0 bash "$GC" --yes >/dev/null 2>&1
115
- [ ! -e "$SB/multi-agent-linked" ] && pass "symlink itself removed" || fail "symlink survived"
116
- [ -f "$VICTIM/keep.txt" ] && pass "symlink target untouched" || fail "symlink target was deleted"
117
- rm -rf "$VICTIM"
118
-
119
- echo ""
120
- echo "→ 9. default grace spares fresh scratch"
121
- seed
122
- out=$(GC_TMP_ROOT="$SB" bash "$GC" --yes 2>&1)
123
- rc=$?
124
- [ "$rc" = "0" ] && pass "grace run exits 0" || fail "grace run exited $rc"
125
- [ -f "$SB/multi-agent-picker-PROJ-1.json" ] && pass "fresh scratch spared by default grace" || fail "default grace deleted fresh scratch"
126
- echo "$out" | grep -qi "spared" && pass "output mentions spared fresh items" || fail "no spared note in output"
127
-
128
- echo ""
129
- echo "══ gc-tmp smoke: $PASS passed, $FAIL failed ══"
130
- [ "$FAIL" -eq 0 ]
@@ -1,125 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-gc-worktrees.sh - contract of the worktree residue sweeper.
3
- #
4
- # Verifies gc-worktrees.sh: dry-run-by-default, orphan-dir removal only with
5
- # --yes, registered worktrees untouched, gitlink residue unstaged, exclude
6
- # guard added idempotently, --older-than sparing, non-repo no-op, and flag
7
- # validation.
8
-
9
- set -uo pipefail
10
-
11
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
12
- SCRIPT="$SCRIPT_DIR/gc-worktrees.sh"
13
-
14
- PASS=0
15
- FAIL=0
16
- record_pass() { PASS=$((PASS + 1)); printf ' \342\234\223 %s\n' "$1"; }
17
- record_fail() { FAIL=$((FAIL + 1)); printf ' \342\234\227 %s\n' "$1"; }
18
-
19
- printf '\342\206\222 smoke-gc-worktrees: worktree residue sweep contract\n'
20
-
21
- tmpdir=$(mktemp -d)
22
- trap 'rm -rf "$tmpdir"' EXIT
23
-
24
- # Fixture repo: one registered worktree, one orphan dir, one gitlink residue.
25
- REPO="$tmpdir/repo"
26
- mkdir -p "$REPO"
27
- git -C "$REPO" init -q -b main
28
- git -C "$REPO" config user.email smoke@test
29
- git -C "$REPO" config user.name smoke
30
- echo hi > "$REPO/f.txt"
31
- git -C "$REPO" add f.txt
32
- git -C "$REPO" commit -qm init
33
- git -C "$REPO" worktree add -q "$REPO/.worktrees/REG" -b reg-branch
34
- mkdir -p "$REPO/.worktrees/ORPHAN"
35
- echo x > "$REPO/.worktrees/ORPHAN/file"
36
- git -C "$REPO" update-index --add --cacheinfo "160000,$(git -C "$REPO" rev-parse HEAD),.worktrees/GONE"
37
-
38
- # 1. Script parses
39
- if bash -n "$SCRIPT" 2>/dev/null; then
40
- record_pass "gc-worktrees.sh parses (bash -n)"
41
- else
42
- record_fail "gc-worktrees.sh has syntax errors"
43
- fi
44
-
45
- # 2. Dry-run lists all three findings and deletes nothing
46
- out=$(bash "$SCRIPT" --repo "$REPO" 2>&1); rc=$?
47
- if [ "$rc" -eq 0 ] \
48
- && printf '%s' "$out" | grep -q "would remove orphan worktree dir: .worktrees/ORPHAN" \
49
- && printf '%s' "$out" | grep -q "would unstage gitlink residue from the index: .worktrees/GONE" \
50
- && printf '%s' "$out" | grep -q "would add .worktrees/ to .git/info/exclude"; then
51
- record_pass "dry-run lists orphan dir + gitlink + missing guard"
52
- else
53
- record_fail "dry-run should list all three findings (rc=$rc): $out"
54
- fi
55
- if [ -d "$REPO/.worktrees/ORPHAN" ] && git -C "$REPO" ls-files -s -- .worktrees | grep -q 160000; then
56
- record_pass "dry-run changed nothing"
57
- else
58
- record_fail "dry-run must not delete or unstage anything"
59
- fi
60
-
61
- # 3. --older-than spares the freshly-touched orphan
62
- out=$(bash "$SCRIPT" --repo "$REPO" --older-than=60 2>&1)
63
- if printf '%s' "$out" | grep -q "would remove orphan"; then
64
- record_fail "--older-than=60 should spare the fresh orphan dir"
65
- else
66
- record_pass "--older-than spares recently-touched orphan dirs"
67
- fi
68
-
69
- # 4. --yes applies all three
70
- out=$(bash "$SCRIPT" --repo "$REPO" --yes 2>&1); rc=$?
71
- if [ "$rc" -eq 0 ] && [ ! -d "$REPO/.worktrees/ORPHAN" ]; then
72
- record_pass "--yes removes the orphan dir"
73
- else
74
- record_fail "--yes should remove the orphan dir (rc=$rc): $out"
75
- fi
76
- if git -C "$REPO" ls-files -s -- .worktrees | grep -q 160000; then
77
- record_fail "--yes should unstage the gitlink residue"
78
- else
79
- record_pass "--yes unstages the gitlink residue"
80
- fi
81
- if [ "$(grep -cxF '.worktrees/' "$REPO/.git/info/exclude" 2>/dev/null)" = "1" ]; then
82
- record_pass "--yes adds the exclude guard exactly once"
83
- else
84
- record_fail "exclude guard missing or duplicated"
85
- fi
86
-
87
- # 5. Registered worktree untouched
88
- if [ -d "$REPO/.worktrees/REG" ] && git -C "$REPO" worktree list | grep -q "REG"; then
89
- record_pass "registered worktree left untouched"
90
- else
91
- record_fail "registered worktree must never be touched"
92
- fi
93
-
94
- # 6. Re-run -> nothing to do, guard not duplicated
95
- out=$(bash "$SCRIPT" --repo "$REPO" 2>&1); rc=$?
96
- if [ "$rc" -eq 0 ] && printf '%s' "$out" | grep -q "nothing to do"; then
97
- record_pass "clean repo -> nothing to do (exit 0)"
98
- else
99
- record_fail "clean repo should be a no-op (rc=$rc): $out"
100
- fi
101
- bash "$SCRIPT" --repo "$REPO" --yes >/dev/null 2>&1
102
- if [ "$(grep -cxF '.worktrees/' "$REPO/.git/info/exclude")" = "1" ]; then
103
- record_pass "exclude guard is idempotent across --yes reruns"
104
- else
105
- record_fail "exclude guard duplicated on rerun"
106
- fi
107
-
108
- # 7. Non-repo -> silent no-op exit 0
109
- out=$(bash "$SCRIPT" --repo "$tmpdir" 2>&1); rc=$?
110
- if [ "$rc" -eq 0 ] && printf '%s' "$out" | grep -q "not a git work tree"; then
111
- record_pass "non-repo -> exit 0 no-op"
112
- else
113
- record_fail "non-repo should exit 0 with a no-op message (rc=$rc)"
114
- fi
115
-
116
- # 8. Unknown flag -> usage error exit 2
117
- bash "$SCRIPT" --definitely-not-a-flag >/dev/null 2>&1; rc=$?
118
- if [ "$rc" -eq 2 ]; then
119
- record_pass "unknown flag -> exit 2"
120
- else
121
- record_fail "unknown flag should exit 2 (got $rc)"
122
- fi
123
-
124
- printf '\n\342\225\220\342\225\220 smoke-gc-worktrees: %d passed, %d failed \342\225\220\342\225\220\n' "$PASS" "$FAIL"
125
- [ "$FAIL" -eq 0 ]
@@ -1,120 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-generate-issue.sh - contract for /multi-agent:create-jira.
3
- #
4
- # Verifies:
5
- # 1. All 3 files exist (1 command, shared ref, 1 Copilot/plugin SKILL.md).
6
- # 2. Frontmatter keys present on both surfaces.
7
- # 3. Command delegates to refs/generate-issue.md and asks the issue type.
8
- # 4. Approval gate documented and marked unskippable in the ref.
9
- # 5. Convention mining + createmeta + Agile sprint endpoints present.
10
- # 6. UTF-8 verbatim POST path (--rawfile + --data-binary) present.
11
- # 7. Standard template vocab: Task/Story (Scope/Acceptance/Test Scenarios), Bug (Steps/Expected/Actual/Environment), Swagger.
12
- # 8. Registration: dispatcher rows, inventory lists, count derived from the command tree.
13
- # 9. Forbidden strings absent (em-dash, section sign, the M-word, unicode_escape).
14
-
15
- set -euo pipefail
16
-
17
- HERE="$(cd "$(dirname "$0")" && pwd)"
18
- ROOT="$(cd "$HERE/../.." && pwd)"
19
- CMD="$ROOT/pipeline/commands/multi-agent/create-jira/SKILL.md"
20
- REF="$ROOT/pipeline/multi-agent-refs/generate-issue.md"
21
- SKILL="$ROOT/pipeline/skills/shared/core/multi-agent-create-jira/SKILL.md"
22
- DISPATCHER="$ROOT/pipeline/commands/multi-agent/SKILL.md"
23
- CONTRACT="$ROOT/pipeline/multi-agent-refs/cross-cli-contract.md"
24
- CMD_COUNT=$(find "$ROOT/pipeline/commands/multi-agent" -mindepth 1 -maxdepth 1 -type d | wc -l | tr -d ' ')
25
- SYNC="$ROOT/pipeline/commands/multi-agent/sync/SKILL.md"
26
- HELP="$ROOT/pipeline/commands/multi-agent/help/SKILL.md"
27
-
28
- PASS=0
29
- FAIL=0
30
- pass() { PASS=$((PASS+1)); echo " ✓ $1"; }
31
- fail() { FAIL=$((FAIL+1)); echo " ✗ $1"; }
32
-
33
- echo "→ 1. files exist"
34
- for f in "$CMD" "$REF" "$SKILL"; do
35
- if [ -f "$f" ]; then pass "exists: ${f#$ROOT/}"; else fail "missing: ${f#$ROOT/}"; fi
36
- done
37
- # old split commands must be gone
38
- for f in "$ROOT/pipeline/commands/multi-agent/generate-task/SKILL.md" "$ROOT/pipeline/commands/multi-agent/generate-bug/SKILL.md"; do
39
- if [ -f "$f" ]; then fail "stale file present: ${f#$ROOT/}"; else pass "removed: ${f##*/}"; fi
40
- done
41
- [ "$FAIL" -eq 0 ] || { echo "══ generate-issue smoke: $PASS passed, $FAIL failed ══"; exit 1; }
42
-
43
- echo ""
44
- echo "→ 2. frontmatter keys"
45
- head -5 "$CMD" | grep -q '^description:' && pass "description: ${CMD##*/}" || fail "description missing: ${CMD##*/}"
46
- head -5 "$CMD" | grep -q '^argument-hint:' && pass "argument-hint: ${CMD##*/}" || fail "argument-hint missing: ${CMD##*/}"
47
- head -8 "$SKILL" | grep -q '^name: multi-agent-create-jira$' && pass "name: multi-agent-create-jira" || fail "name wrong: $SKILL"
48
- head -8 "$SKILL" | grep -q '^language: en' && pass "language en" || fail "language missing: $SKILL"
49
- head -8 "$SKILL" | grep -q '^user-invocable: true' && pass "user-invocable" || fail "user-invocable missing: $SKILL"
50
-
51
- echo ""
52
- echo "→ 3. command delegates to the shared ref and asks the type"
53
- grep -Fq "refs/generate-issue.md" "$CMD" && pass "ref link present" || fail "ref link missing"
54
- for t in "Task" "Bug" "Story"; do
55
- grep -Fq "$t" "$CMD" && pass "type offered: $t" || fail "type missing: $t"
56
- done
57
- grep -Fqi "Pick issue type" "$REF" && pass "type-selection step present" || fail "type-selection step missing"
58
-
59
- echo ""
60
- echo "→ 4. approval gate documented and unskippable"
61
- grep -Fq "Full preview + approval gate (never skipped)" "$REF" && pass "gate section present" || fail "gate section missing"
62
- for marker in "Approve" "Edit" "Cancel" "no bypass" "Nothing was created"; do
63
- grep -Fqi "$marker" "$REF" && pass "gate marker: $marker" || fail "gate marker missing: $marker"
64
- done
65
- grep -Fq "no autopilot variant" "$REF" && pass "no-autopilot rule" || fail "no-autopilot rule missing"
66
-
67
- echo ""
68
- echo "→ 5. mining + createmeta + agile endpoints"
69
- for marker in "rest/api/2/search" "rest/api/2/issue/createmeta" "rest/agile/1.0/board" "sprint?state=active" 'sprint/${SPRINT_ID}/issue' "remotelink" "attachments"; do
70
- grep -Fq "$marker" "$REF" && pass "endpoint marker: $marker" || fail "endpoint marker missing: $marker"
71
- done
72
- grep -Fq "gh-sprint" "$REF" && pass "generic sprint-field detection" || fail "generic sprint-field detection missing"
73
-
74
- echo ""
75
- echo "→ 6. UTF-8 verbatim POST path"
76
- grep -Fq -- "--rawfile" "$REF" && pass "--rawfile present" || fail "--rawfile missing"
77
- grep -Fq -- "--data-binary" "$REF" && pass "--data-binary present" || fail "--data-binary missing"
78
- grep -Fqi "humanizer" "$REF" && pass "humanizer pass referenced" || fail "humanizer missing"
79
-
80
- echo ""
81
- echo "→ 7. standard template vocabulary + auto-sizing + swagger"
82
- for s in "Scope" "Acceptance Criteria" "Test Scenarios"; do
83
- grep -Fq "$s" "$REF" && pass "task/story section: $s" || fail "task/story section missing: $s"
84
- done
85
- for s in "Steps to Reproduce" "Expected Result" "Actual Result" "Environment"; do
86
- grep -Fq "$s" "$REF" && pass "bug section: $s" || fail "bug section missing: $s"
87
- done
88
- grep -Fqi "auto-sizing" "$REF" && pass "auto-sizing rule present" || fail "auto-sizing rule missing"
89
- grep -Fqi "swagger" "$REF" && pass "swagger context present" || fail "swagger context missing"
90
-
91
- echo ""
92
- echo "→ 8. registration + count consistency (derived)"
93
- grep -Fq '| `create-jira ' "$DISPATCHER" && pass "dispatcher routing: create-jira" || fail "dispatcher routing missing: generate"
94
- grep -Fq "create-jira/SKILL.md" "$DISPATCHER" && pass "dispatcher loading row" || fail "dispatcher loading row missing"
95
- grep -Fq "## 1. Command Inventory ($CMD_COUNT commands)" "$CONTRACT" && pass "contract count = $CMD_COUNT (derived)" || fail "contract count wrong"
96
- grep -Eq '(^|[ ,])create-jira([ ,]|$)' "$CONTRACT" && pass "contract list has create-jira" || fail "contract list missing generate"
97
- grep -Fq "**$CMD_COUNT commands are synced**" "$SYNC" && pass "sync count = $CMD_COUNT (derived)" || fail "sync count wrong"
98
- SYNC_SKILL="$ROOT/pipeline/skills/shared/core/multi-agent-sync/SKILL.md"
99
- grep -Fq "**$CMD_COUNT commands are synced**" "$SYNC_SKILL" && pass "sync SKILL count = $CMD_COUNT (derived)" || fail "sync SKILL count wrong (Copilot parity)"
100
- grep -Fq "create-jira" "$ROOT/pipeline/skills/shared/core/multi-agent-help/SKILL.md" && pass "help SKILL lists create-jira" || fail "help SKILL missing create-jira (Copilot parity)"
101
- grep -c "multi-agent:create-jira" "$HELP" | awk '{exit !($1>=2)}' && pass "help.md has EN + TR entries" || fail "help.md entries incomplete"
102
- # no stale split-command references anywhere in the synced surfaces
103
- if grep -rqE "generate-task|generate-bug" "$DISPATCHER" "$CONTRACT" "$SYNC" "$HELP" "$CMD" "$REF" "$SKILL"; then
104
- fail "stale generate-task/generate-bug reference found"
105
- else
106
- pass "no stale split-command references"
107
- fi
108
-
109
- echo ""
110
- echo "→ 9. forbidden strings absent"
111
- MWORD="MAN""DATORY"
112
- for f in "$CMD" "$REF" "$SKILL"; do
113
- if grep -q $'—\|§\|…' "$f"; then fail "forbidden unicode punctuation in ${f##*/}"; else pass "punctuation clean: ${f##*/}"; fi
114
- if grep -q "$MWORD" "$f"; then fail "forbidden word in ${f##*/}"; else pass "vocabulary clean: ${f##*/}"; fi
115
- if grep -q "unicode_escape" "$f" && ! grep -q "Never round-trip" "$f"; then fail "unicode_escape misuse in ${f##*/}"; else pass "encoding rule clean: ${f##*/}"; fi
116
- done
117
-
118
- echo ""
119
- echo "══ generate-issue smoke: $PASS passed, $FAIL failed ══"
120
- [ "$FAIL" -eq 0 ]
@@ -1,92 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-handoff-contract.sh
3
- #
4
- # Verifies the v10.8.0 structured-handoff contract (fresh-context re-entry):
5
- # 1. operations.md documents the Handoff block with all 5 required lines
6
- # 2. operations.md compaction trigger re-reads state AND the latest handoff
7
- # 3. log-format.md documents the Handoff section in the canonical log shape
8
- # 4. resume.md Step 3 reads the latest handoff FIRST with pre-v10.8 fallback
9
- #
10
- # Exit 0 = all pass, 1 = any failure.
11
-
12
- set -euo pipefail
13
-
14
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
15
- OPS="$ROOT/pipeline/multi-agent-refs/phases/operations.md"
16
- LOGFMT="$ROOT/pipeline/multi-agent-refs/phases/log-format.md"
17
- RESUME="$ROOT/pipeline/commands/multi-agent/resume/SKILL.md"
18
-
19
- pass=0
20
- fail=0
21
- failures=()
22
- record_pass() { pass=$((pass + 1)); printf ' \033[0;32mPASS\033[0m %s\n' "$1"; }
23
- record_fail() { fail=$((fail + 1)); failures+=("$1"); printf ' \033[0;31mFAIL\033[0m %s\n' "$1"; }
24
-
25
- printf '→ smoke-handoff-contract: structured handoff (fresh-context re-entry)\n'
26
-
27
- # 1. operations.md documents the Handoff block with the 5 required lines
28
- if [ ! -f "$OPS" ]; then
29
- record_fail "operations.md missing"
30
- else
31
- if grep -qF "Handoff block (v10.8.0)" "$OPS"; then
32
- record_pass "operations.md documents the Handoff block"
33
- else
34
- record_fail "operations.md missing 'Handoff block (v10.8.0)' spec"
35
- fi
36
- for line in "- Done:" "- Remaining:" "- Decisions:" "- Open findings:" "- Next:"; do
37
- if grep -qF -- "$line" "$OPS"; then
38
- record_pass "operations.md handoff spec has '$line'"
39
- else
40
- record_fail "operations.md handoff spec missing '$line'"
41
- fi
42
- done
43
- if grep -qF "no agent dispatch, no extra LLM call" "$OPS"; then
44
- record_pass "operations.md states handoff is orchestrator-written (no LLM call)"
45
- else
46
- record_fail "operations.md must state the handoff costs no LLM call"
47
- fi
48
- fi
49
-
50
- # 2. Compaction trigger re-reads state AND latest handoff
51
- if grep -qE 'agent-state\.json.*AND the latest.*Handoff' "$OPS"; then
52
- record_pass "compaction trigger re-reads state + latest handoff"
53
- else
54
- record_fail "operations.md compaction trigger must re-read agent-state.json AND the latest Handoff block"
55
- fi
56
-
57
- # 3. log-format.md documents the Handoff section
58
- if grep -qF "## Handoff - end of Phase" "$LOGFMT"; then
59
- record_pass "log-format.md documents the Handoff section"
60
- else
61
- record_fail "log-format.md missing the Handoff section"
62
- fi
63
- if grep -qF "LATEST block is authoritative" "$LOGFMT"; then
64
- record_pass "log-format.md states latest-block-wins semantics"
65
- else
66
- record_fail "log-format.md must state the latest handoff block is authoritative"
67
- fi
68
-
69
- # 4. resume.md reads handoff first, with fallback for older logs
70
- if grep -qE 'LATEST .?## Handoff.? block' "$RESUME"; then
71
- record_pass "resume.md Step 3 reads the latest Handoff block first"
72
- else
73
- record_fail "resume.md Step 3 must read the latest Handoff block first"
74
- fi
75
- if grep -qiF "fall back to per-phase findings" "$RESUME"; then
76
- record_pass "resume.md keeps the pre-v10.8 per-phase fallback"
77
- else
78
- record_fail "resume.md must keep the pre-v10.8 per-phase findings fallback"
79
- fi
80
- if grep -qF "trust state on mismatch" "$RESUME"; then
81
- record_pass "resume.md defines state-wins conflict rule"
82
- else
83
- record_fail "resume.md must define the handoff-vs-state conflict rule (state wins)"
84
- fi
85
-
86
- printf '\n══ handoff-contract smoke: %d passed, %d failed ══\n' "$pass" "$fail"
87
- if [ "$fail" -gt 0 ]; then
88
- printf '\nFailures:\n'
89
- for msg in "${failures[@]}"; do printf ' - %s\n' "$msg"; done
90
- exit 1
91
- fi
92
- exit 0
@@ -1,70 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-identity-isolation.sh - asserts identity isolation rules from section18.3
3
- # of REFACTOR_PLAN_v3.7.md are documented & wired:
4
- #
5
- # • Identity lookup happens via platformIdentityRouting only - NEVER fall
6
- # back to "try all PATs"
7
- # • If no routing match, prompt user - do not guess
8
- # • servicePatMap is checked per-identity - corp identity cannot accidentally
9
- # use personal identity's PAT even if the keychain name is discoverable
10
- #
11
- # Doc-shape smoke (no fake keychain entries; pure spec assertion).
12
-
13
- set -uo pipefail
14
-
15
- # Read from source (authoritative) - installed tree may lag behind on
16
- # machines that haven't re-run install.js after a pipeline update.
17
- HERE="$(cd "$(dirname "$0")" && pwd)"
18
- ROOT="$(cd "$HERE/../.." && pwd)"
19
- PHASE0="$ROOT/pipeline/multi-agent-refs/phases/phase-0-init.md"
20
- SETUP="$ROOT/pipeline/commands/multi-agent/setup/SKILL.md"
21
- PREFS_SCHEMA="$ROOT/pipeline/schemas/prefs.schema.json"
22
-
23
- PASS=0; FAIL=0
24
- pass() { PASS=$((PASS+1)); echo " ✓ $1"; }
25
- fail() { FAIL=$((FAIL+1)); echo " ✗ $1"; }
26
-
27
- echo "→ 1. servicePatMap is per-identity (schema)"
28
- grep -q "servicePatMap" "$PREFS_SCHEMA" \
29
- && pass "Schema declares identities[].servicePatMap" \
30
- || fail "Schema missing servicePatMap on identities"
31
- grep -q "Enables cross-identity isolation\|cross-identity isolation" "$PREFS_SCHEMA" \
32
- && pass "Schema description articulates cross-identity isolation invariant" \
33
- || fail "Schema description missing isolation invariant"
34
-
35
- echo ""
36
- echo "→ 2. Phase 0 routing - no silent fallback to 'try all PATs'"
37
- grep -q "platformIdentityRouting" "$PHASE0" \
38
- && pass "Phase 0 Step 6 references platformIdentityRouting" \
39
- || fail "Phase 0 missing platformIdentityRouting reference"
40
- # Post-10caff1 wording: the resolution order ends with an explicit "ask once"
41
- # clause for the multi-identity case - same invariant as the older
42
- # "multi-identity picker" text.
43
- grep -q "Multiple identities, no routing rule" "$PHASE0" \
44
- && pass "Phase 0 handles 'no routing match, multiple identities' branch" \
45
- || fail "Phase 0 missing no-match + multi-identity handling"
46
- grep -q "No identities" "$PHASE0" \
47
- && pass "Phase 0 handles 'no identities ever' branch (Token Save Flow)" \
48
- || fail "Phase 0 missing 'no identities' branch"
49
- grep -qE "save routing rule so it never asks again" "$PHASE0" \
50
- && pass "Phase 0 persists routing on first ask (no silent guess)" \
51
- || fail "Phase 0 missing routing-persistence guarantee"
52
-
53
- echo ""
54
- echo "→ 3. Setup Step 4 wires per-identity service ownership"
55
- grep -q "servicePatMap" "$SETUP" \
56
- && pass "Setup Step 4 documents servicePatMap" \
57
- || fail "Setup Step 4 missing servicePatMap"
58
- grep -qE "own tokens for|owns.*jira|per-identity" "$SETUP" \
59
- && pass "Setup Step 4 describes per-identity ownership" \
60
- || fail "Setup Step 4 missing per-identity ownership description"
61
-
62
- echo ""
63
- echo "→ 4. Multi-repo: identity routed per-repo (not shared)"
64
- grep -qE "per repo( independently)?|routed per-repo" "$PHASE0" \
65
- && pass "Multi-repo Step 6 routes identity per-repo" \
66
- || fail "Multi-repo per-repo identity routing missing"
67
-
68
- echo ""
69
- echo "══ identity-isolation smoke: $PASS passed, $FAIL failed ══"
70
- [ "$FAIL" -eq 0 ]