@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,262 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-agent-log-cost.sh - v8.3.0
3
- #
4
- # Verifies the agent-log Cost Breakdown pipeline:
5
- # 1. render-agent-log-cost.sh exits 2 when no tracker data available
6
- # 2. Renders 4-column markdown (Phase | Model | Tokens in | Tokens out | Est. USD)
7
- # from a hand-built object-shaped phase-tracker.json
8
- # 3. Renders identical block from the array-shaped phase-tracker.json that
9
- # phase-tracker.sh actually writes
10
- # 4. Unknown model degrades to " - " with footnote, never blocks
11
- # 5. log-metric.sh forwards tokens + model to tracker when LOG_METRIC_FORWARD_TO_TRACKER=1
12
- # 6. log-format.md ref doc declares the Tokens column + Cost Breakdown section
13
- #
14
- # Exit 0 = all pass, 1 = any failure.
15
-
16
- set -euo pipefail
17
-
18
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
19
- RENDERER="$ROOT/pipeline/scripts/render-agent-log-cost.sh"
20
- TRACKER="$ROOT/pipeline/scripts/phase-tracker.sh"
21
- LOG_METRIC="$ROOT/pipeline/scripts/log-metric.sh"
22
- TABLE="$ROOT/pipeline/scripts/cost-table.json"
23
- LOG_FORMAT_DOC="$ROOT/pipeline/multi-agent-refs/phases/log-format.md"
24
-
25
- pass=0
26
- fail=0
27
- failures=()
28
- record_pass() { pass=$((pass + 1)); printf ' \033[0;32mPASS\033[0m %s\n' "$1"; }
29
- record_fail() { fail=$((fail + 1)); failures+=("$1"); printf ' \033[0;31mFAIL\033[0m %s\n' "$1"; }
30
-
31
- printf '→ smoke-agent-log-cost (v8.3.0): agent-log Cost Breakdown contract\n'
32
-
33
- [ -x "$RENDERER" ] || { record_fail "renderer not executable: $RENDERER"; exit 1; }
34
-
35
- # --- 1: missing-data path returns exit 2 ---
36
- tmp=$(mktemp -d)
37
- pushd "$tmp" >/dev/null
38
- set +e
39
- bash "$RENDERER" GHOST-1 >/dev/null 2>&1
40
- rc=$?
41
- set -e
42
- if [ "$rc" -eq 2 ]; then
43
- record_pass "renderer exits 2 when no tracker data"
44
- else
45
- record_fail "renderer should exit 2 with no data (got $rc)"
46
- fi
47
- popd >/dev/null
48
- rm -rf "$tmp"
49
-
50
- # --- 2: object-shaped fixture renders 4-column markdown ---
51
- tmp=$(mktemp -d)
52
- pushd "$tmp" >/dev/null
53
- mkdir -p .worktrees/DEMO-1
54
- cat > .worktrees/DEMO-1/phase-tracker.json <<'JSON'
55
- {"taskId":"DEMO-1","phases":{
56
- "1":{"name":"1. Analysis","model":"opus","tokens_in":12480,"tokens_out":3210},
57
- "3":{"name":"3. Dev","model":"sonnet","tokens_in":42310,"tokens_out":9880},
58
- "4":{"name":"4. Review","model":"opus","tokens_in":8200,"tokens_out":1500}
59
- }}
60
- JSON
61
- out=$(bash "$RENDERER" DEMO-1 2>/dev/null)
62
- if grep -qE '^\| Phase \| Model \| Tokens in \| Tokens out \| Est\. USD \|' <<< "$out"; then
63
- record_pass "object-shape: header row rendered"
64
- else
65
- record_fail "object-shape: header row missing"
66
- fi
67
- if grep -q '## Cost Breakdown' <<< "$out"; then
68
- record_pass "object-shape: Cost Breakdown section heading present"
69
- else
70
- record_fail "object-shape: section heading missing"
71
- fi
72
- if grep -qE '\| 1\. Analysis \| opus \| 12,480 \| 3,210 \| \$' <<< "$out"; then
73
- record_pass "object-shape: Phase 1 row formatted with comma-grouped tokens + USD"
74
- else
75
- record_fail "object-shape: Phase 1 row formatting wrong"
76
- printf '%s\n' "$out" | head -10 >&2
77
- fi
78
- if grep -qE '\| \*\*Total\*\* .* \| \*\*\$' <<< "$out"; then
79
- record_pass "object-shape: Total row rendered"
80
- else
81
- record_fail "object-shape: Total row missing"
82
- fi
83
- popd >/dev/null
84
- rm -rf "$tmp"
85
-
86
- # --- 3: array-shaped fixture (the shape phase-tracker.sh actually writes) ---
87
- tmp=$(mktemp -d)
88
- pushd "$tmp" >/dev/null
89
- mkdir -p .worktrees/PROJ-2
90
- cat > .worktrees/PROJ-2/phase-tracker.json <<'JSON'
91
- {"task_id":"PROJ-2","started_at":"2026-05-05T10:00:00Z","phases":[
92
- {"id":"1","name":"Analysis","status":"completed","model":"opus","tokens_in":10000,"tokens_out":2000,"subs":[]},
93
- {"id":"3","name":"Dev","status":"completed","model":"sonnet","tokens_in":50000,"tokens_out":8000,"subs":[]}
94
- ]}
95
- JSON
96
- out=$(bash "$RENDERER" PROJ-2 2>/dev/null)
97
- if grep -qE '\| Analysis \| opus \| 10,000 \| 2,000 \| \$' <<< "$out"; then
98
- record_pass "array-shape: Phase 1 row rendered correctly"
99
- else
100
- record_fail "array-shape: Phase 1 row wrong"
101
- printf '%s\n' "$out" | head -10 >&2
102
- fi
103
- if grep -qE '\| Dev \| sonnet \| 50,000 \| 8,000 \| \$' <<< "$out"; then
104
- record_pass "array-shape: Phase 3 row rendered correctly"
105
- else
106
- record_fail "array-shape: Phase 3 row wrong"
107
- fi
108
- popd >/dev/null
109
- rm -rf "$tmp"
110
-
111
- # --- 4: unknown model degrades gracefully ---
112
- tmp=$(mktemp -d)
113
- pushd "$tmp" >/dev/null
114
- mkdir -p .worktrees/UNK-1
115
- cat > .worktrees/UNK-1/phase-tracker.json <<'JSON'
116
- {"task_id":"UNK-1","phases":[
117
- {"id":"3","name":"Dev","model":"made-up-9000","tokens_in":1000,"tokens_out":200,"subs":[]}
118
- ]}
119
- JSON
120
- out=$(bash "$RENDERER" UNK-1 2>/dev/null)
121
- if grep -qF '| made-up-9000 |' <<< "$out" && grep -qF '| - |' <<< "$out"; then
122
- record_pass "unknown model row renders with USD as - "
123
- else
124
- record_fail "unknown model handling broken"
125
- fi
126
- if grep -q 'cost-table.json' <<< "$out"; then
127
- record_pass "unknown model footnote points to cost-table.json"
128
- else
129
- record_fail "unknown model footnote missing"
130
- fi
131
- popd >/dev/null
132
- rm -rf "$tmp"
133
-
134
- # --- 5: log-metric forwarder writes to phase-tracker ---
135
- tmp=$(mktemp -d)
136
- export METRICS_FILE="$tmp/metrics.jsonl"
137
- export TRACKER_FILE="$tmp/tracker.json"
138
- # Bootstrap tracker with one phase
139
- bash "$TRACKER" init "FWD-1" >/dev/null 2>&1 || true
140
- # init writes to $HOME/.claude/logs/multi-agent/FWD-1/tracker-state.json - override via TRACKER_FILE
141
- cat > "$TRACKER_FILE" <<'JSON'
142
- {"task_id":"FWD-1","started_at":"2026-05-05T00:00:00Z","phases":[
143
- {"id":"4","name":"Review","status":"in_progress","subs":[]}
144
- ]}
145
- JSON
146
- LOG_METRIC_FORWARD_TO_TRACKER=1 TRACKER_QUIET=1 \
147
- bash "$LOG_METRIC" FWD-1 4 review.reviewer_call \
148
- model=opus tokens_in=1234 tokens_out=567 tokens_cached=400 duration_ms=1000 >/dev/null 2>&1 || true
149
- if jq -e '.phases[0].tokens_in == 1234 and .phases[0].tokens_out == 567 and .phases[0].model == "opus"' "$TRACKER_FILE" >/dev/null 2>&1; then
150
- record_pass "log-metric forwards tokens + model to tracker"
151
- else
152
- record_fail "log-metric forwarder did not update tracker"
153
- cat "$TRACKER_FILE" >&2
154
- fi
155
- # End-to-end: tokens_cached must flow log-metric -> phase-tracker -> tracker state
156
- if jq -e '.phases[0].tokens_cached == 400' "$TRACKER_FILE" >/dev/null 2>&1; then
157
- record_pass "log-metric forwards tokens_cached end-to-end"
158
- else
159
- record_fail "tokens_cached did not reach the tracker"
160
- cat "$TRACKER_FILE" >&2
161
- fi
162
- # A malformed tokens_cached must NOT poison the call (in/out must still land).
163
- cat > "$TRACKER_FILE" <<'JSON'
164
- {"task_id":"FWD-2","phases":[{"id":"4","name":"Review","status":"in_progress","subs":[]}]}
165
- JSON
166
- LOG_METRIC_FORWARD_TO_TRACKER=1 TRACKER_QUIET=1 \
167
- bash "$LOG_METRIC" FWD-2 4 review.reviewer_call \
168
- model=opus tokens_in=999 tokens_out=111 tokens_cached=abc duration_ms=1 >/dev/null 2>&1 || true
169
- if jq -e '.phases[0].tokens_in == 999 and .phases[0].tokens_out == 111 and (.phases[0].tokens_cached // 0) == 0' "$TRACKER_FILE" >/dev/null 2>&1; then
170
- record_pass "malformed tokens_cached sanitized to 0; in/out preserved"
171
- else
172
- record_fail "malformed tokens_cached poisoned the tokens call"
173
- cat "$TRACKER_FILE" >&2
174
- fi
175
- unset METRICS_FILE TRACKER_FILE
176
- rm -rf "$tmp"
177
-
178
- # --- 5b: cached tokens are priced at the cache-read rate + surfaced ---
179
- tmp=$(mktemp -d)
180
- pushd "$tmp" >/dev/null
181
- mkdir -p .worktrees/CACHE-1
182
- cat > .worktrees/CACHE-1/phase-tracker.json <<'JSON'
183
- {"task_id":"CACHE-1","phases":[
184
- {"id":"1","name":"Analysis","model":"opus","tokens_in":20000,"tokens_out":3000,"tokens_cached":15000,"subs":[]},
185
- {"id":"3","name":"Dev","model":"sonnet","tokens_in":60000,"tokens_out":10000,"subs":[]}
186
- ]}
187
- JSON
188
- out=$(bash "$RENDERER" CACHE-1 2>/dev/null)
189
- # Cache-exclusive: tokens_in (20000) and tokens_cached (15000) are disjoint.
190
- # 20000 fresh @5 + 15000 cached @0.50 + 3000 out @25 = 0.1825 -> floor-to-cents $0.18.
191
- # Without the cache discount (cached billed @5) it would be 0.25 -> $0.25, so the
192
- # discounted rate is what drives the row down to $0.18.
193
- if grep -qE '\| Analysis \| opus \| 20,000 \| 3,000 \| \$0\.18 \|' <<< "$out"; then
194
- record_pass "cached tokens priced at cache-read rate (opus row = \$0.18)"
195
- else
196
- record_fail "cached-token pricing wrong"
197
- printf '%s\n' "$out" | head -12 >&2
198
- fi
199
- if grep -q 'Cache reads: 15,000 tokens' <<< "$out"; then
200
- record_pass "cache-read footer surfaced when tokens_cached present"
201
- else
202
- record_fail "cache-read footer missing"
203
- fi
204
- if grep -qE 'Top cost driver:' <<< "$out"; then
205
- record_pass "top cost driver line rendered"
206
- else
207
- record_fail "top cost driver line missing"
208
- fi
209
- popd >/dev/null
210
- rm -rf "$tmp"
211
-
212
- # --- 5c: no cache footer when no cached tokens (object-shape regression) ---
213
- tmp=$(mktemp -d)
214
- pushd "$tmp" >/dev/null
215
- mkdir -p .worktrees/NOCACHE-1
216
- cat > .worktrees/NOCACHE-1/phase-tracker.json <<'JSON'
217
- {"task_id":"NOCACHE-1","phases":[
218
- {"id":"3","name":"Dev","model":"sonnet","tokens_in":50000,"tokens_out":8000,"subs":[]}
219
- ]}
220
- JSON
221
- out=$(bash "$RENDERER" NOCACHE-1 2>/dev/null)
222
- if grep -q 'Cache reads:' <<< "$out"; then
223
- record_fail "cache-read footer should be absent when no cached tokens"
224
- else
225
- record_pass "no cache-read footer when tokens_cached absent"
226
- fi
227
- # Sonnet 50000 @3 + 8000 @15 = 0.27 -> $0.27 (unchanged from pre-cache behavior)
228
- if grep -qE '\| Dev \| sonnet \| 50,000 \| 8,000 \| \$0\.27 \|' <<< "$out"; then
229
- record_pass "no-cache USD unchanged (backward-compatible)"
230
- else
231
- record_fail "no-cache USD changed unexpectedly"
232
- printf '%s\n' "$out" | head -12 >&2
233
- fi
234
- popd >/dev/null
235
- rm -rf "$tmp"
236
-
237
- # --- 6: log-format.md declares Tokens + Cost Breakdown ---
238
- if grep -q 'Tokens (in/out)' "$LOG_FORMAT_DOC"; then
239
- record_pass "log-format.md declares Tokens (in/out) column"
240
- else
241
- record_fail "log-format.md missing Tokens column declaration"
242
- fi
243
- if grep -q '## Cost Breakdown' "$LOG_FORMAT_DOC"; then
244
- record_pass "log-format.md declares Cost Breakdown section"
245
- else
246
- record_fail "log-format.md missing Cost Breakdown section"
247
- fi
248
- if grep -q 'render-agent-log-cost.sh' "$LOG_FORMAT_DOC"; then
249
- record_pass "log-format.md references render-agent-log-cost.sh"
250
- else
251
- record_fail "log-format.md does not reference renderer"
252
- fi
253
-
254
- # --- Summary ---
255
- total=$((pass + fail))
256
- printf '\n→ smoke-agent-log-cost: %d/%d passed\n' "$pass" "$total"
257
- if [ "$fail" -ne 0 ]; then
258
- printf '\nFailures:\n'
259
- for f in "${failures[@]}"; do printf ' - %s\n' "$f"; done
260
- exit 1
261
- fi
262
- exit 0
@@ -1,87 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-agent-model-routing.sh - v6.1.D
3
- #
4
- # Asserts per-persona model routing contract:
5
- # 1. Every agent file in pipeline/agents/ has a `preferredModel` frontmatter field.
6
- # 2. `preferredModel` is one of: fable | opus | sonnet | haiku.
7
- # 3. `model:` (Claude-Code-native) matches `preferredModel` (single source of truth).
8
- # 4. Orchestrator docs mention `CLAUDE_CODE_SUBAGENT_MODEL` and `preferredModel`.
9
- # 5. Phase 4 review doc references the per-dispatch override mechanism.
10
- #
11
- # Exit 0 = all assertions pass, 1 = any failure.
12
-
13
- set -euo pipefail
14
-
15
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
16
- AGENTS_DIR="$ROOT/pipeline/agents"
17
- ORCH_SKILL="$ROOT/pipeline/skills/shared/core/multi-agent/SKILL.md"
18
- ORCH_CMD="$ROOT/pipeline/commands/multi-agent/SKILL.md"
19
- PHASE4="$ROOT/pipeline/multi-agent-refs/phases/phase-4-review.md"
20
-
21
- pass=0
22
- fail=0
23
- failures=()
24
-
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-agent-model-routing (v6.1.D): per-persona model routing contract\n'
29
-
30
- # --- 1/2/3: per-agent frontmatter ---
31
- expected=(code-reviewer explorer ios-architect android-architect backend-architect security-auditor)
32
- for name in "${expected[@]}"; do
33
- f="$AGENTS_DIR/$name.md"
34
- if [ ! -f "$f" ]; then
35
- record_fail "$name.md missing"
36
- continue
37
- fi
38
- pref=$(awk '/^preferredModel:/ {print $2; exit}' "$f" | tr -d '"'"'")
39
- mdl=$(awk '/^model:/ {print $2; exit}' "$f" | tr -d '"'"'")
40
- case "$pref" in
41
- fable|opus|sonnet|haiku)
42
- record_pass "$name has preferredModel=$pref"
43
- ;;
44
- *)
45
- record_fail "$name preferredModel invalid or missing (got '$pref')"
46
- ;;
47
- esac
48
- if [ -n "$pref" ] && [ "$pref" != "$mdl" ]; then
49
- record_fail "$name model/preferredModel mismatch (model=$mdl preferredModel=$pref)"
50
- elif [ -n "$pref" ]; then
51
- record_pass "$name model == preferredModel ($pref)"
52
- fi
53
- if grep -q '^modelRationale:' "$f"; then
54
- record_pass "$name has modelRationale"
55
- else
56
- record_fail "$name missing modelRationale"
57
- fi
58
- done
59
-
60
- # --- 4: orchestrator SKILL.md references ---
61
- if grep -q 'CLAUDE_CODE_SUBAGENT_MODEL' "$ORCH_SKILL" && grep -q 'preferredModel' "$ORCH_SKILL"; then
62
- record_pass "orchestrator SKILL.md documents dispatch contract"
63
- else
64
- record_fail "orchestrator SKILL.md missing dispatch contract"
65
- fi
66
-
67
- # --- 4b: orchestrator command file references ---
68
- if grep -q 'preferredModel' "$ORCH_CMD"; then
69
- record_pass "commands/multi-agent/SKILL.md references preferredModel"
70
- else
71
- record_fail "commands/multi-agent/SKILL.md missing preferredModel reference"
72
- fi
73
-
74
- # --- 5: Phase 4 review doc references override ---
75
- if grep -q 'PHASE_MODEL_OVERRIDE\|preferredModel' "$PHASE4"; then
76
- record_pass "phase-4-review.md documents per-reviewer override"
77
- else
78
- record_fail "phase-4-review.md missing per-reviewer override doc"
79
- fi
80
-
81
- printf '\n══ agent-model-routing smoke: %d passed, %d failed ══\n' "$pass" "$fail"
82
- if [ "$fail" -gt 0 ]; then
83
- printf '\nFailures:\n'
84
- for msg in "${failures[@]}"; do printf ' - %s\n' "$msg"; done
85
- exit 1
86
- fi
87
- exit 0
@@ -1,42 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-ask-choice.sh - the portable picker fallback used on platforms without
3
- # a native AskUserQuestion. Exercises default-by-index, default-by-label,
4
- # non-interactive first-option, label-vs-index resolution, and usage errors.
5
-
6
- set -uo pipefail
7
-
8
- REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
9
- ASK="$REPO_ROOT/pipeline/lib/ask-choice.sh"
10
-
11
- PASS=0
12
- FAIL=0
13
- pass() { PASS=$((PASS + 1)); echo " ✓ $1"; }
14
- fail() { FAIL=$((FAIL + 1)); echo " ✗ $1"; }
15
-
16
- echo "→ 1. usage error with <3 args (exit 64)"
17
- bash "$ASK" "only a question" >/dev/null 2>&1
18
- [ "$?" -eq 64 ] && pass "too-few-args exits 64" || fail "too-few-args should exit 64"
19
-
20
- echo "→ 2. ASK_CHOICE_DEFAULT by 1-based index"
21
- out=$(ASK_CHOICE_DEFAULT=2 bash "$ASK" "Approve this plan?" "Approve" "Cancel" "Edit" 2>/dev/null)
22
- [ "$out" = "Cancel" ] && pass "index default 2 -> 'Cancel'" || fail "index default gave '$out' (expected Cancel)"
23
-
24
- echo "→ 3. ASK_CHOICE_DEFAULT by label (case-insensitive)"
25
- out=$(ASK_CHOICE_DEFAULT=approve bash "$ASK" "Approve this plan?" "Approve" "Cancel" 2>/dev/null)
26
- [ "$out" = "Approve" ] && pass "label default 'approve' -> 'Approve'" || fail "label default gave '$out'"
27
-
28
- echo "→ 4. out-of-range / unmatched default falls through to first option (non-TTY)"
29
- out=$(ASK_CHOICE_DEFAULT=99 bash "$ASK" "Pick" "A" "B" </dev/null 2>/dev/null)
30
- [ "$out" = "A" ] && pass "bad default + no TTY -> first option 'A'" || fail "bad default gave '$out'"
31
-
32
- echo "→ 5. non-interactive (no TTY, no default) selects first option, never blocks"
33
- out=$(bash "$ASK" "Continue?" "Yes" "No" </dev/null 2>/dev/null)
34
- [ "$out" = "Yes" ] && pass "no TTY -> first option 'Yes'" || fail "no TTY gave '$out'"
35
-
36
- echo "→ 6. stdout carries ONLY the label (menu/prompt go to stderr)"
37
- out=$(ASK_CHOICE_DEFAULT=1 bash "$ASK" "Q" "Only" "Other" 2>/dev/null)
38
- [ "$out" = "Only" ] && pass "stdout is clean single label" || fail "stdout not clean: '$out'"
39
-
40
- echo ""
41
- echo "══ ask-choice smoke: $PASS passed, $FAIL failed ══"
42
- [ "$FAIL" -eq 0 ]
@@ -1,36 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-autopilot-circuit-breaker.sh - wiring contract for the autopilot
3
- # circuit-breaker feature: the doc exists, enumerates the five trip conditions,
4
- # and is referenced from the modes "what never skips" list.
5
- #
6
- # Exit 0 = all pass, 1 = any failure.
7
-
8
- set -uo pipefail
9
-
10
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
11
- DOC="$ROOT/pipeline/multi-agent-refs/features/autopilot-circuit-breaker.md"
12
- MODES="$ROOT/pipeline/multi-agent-refs/phases/modes.md"
13
-
14
- PASS=0; FAIL=0
15
- pass() { PASS=$((PASS+1)); echo " ✓ $1"; }
16
- fail() { FAIL=$((FAIL+1)); echo " ✗ $1"; }
17
-
18
- [ -f "$DOC" ] && pass "feature doc exists" || fail "feature doc missing"
19
- [ -f "$MODES" ] && pass "modes doc exists" || fail "modes doc missing"
20
-
21
- echo "→ five trip conditions documented"
22
- for t in "No-progress stall" "Identical repeated failure" "Rework storm" "Cost drift" "Merge/rebase conflict"; do
23
- grep -Fq "$t" "$DOC" && pass "trigger: $t" || fail "trigger missing: $t"
24
- done
25
-
26
- echo "→ action + safety invariants"
27
- grep -Fq "resume" "$DOC" && pass "documents resume path" || fail "no resume path"
28
- grep -Eiq "never auto-resolve|does not paper over|no force-anything" "$DOC" && pass "no-self-heal invariant present" || fail "missing no-self-heal invariant"
29
-
30
- echo "→ wired into modes 'what never skips'"
31
- grep -Fq "autopilot-circuit-breaker.md" "$MODES" && pass "modes references the feature doc" || fail "modes does not reference the feature"
32
- grep -Fiq "Circuit-breaker" "$MODES" && pass "modes lists circuit-breaker under never-skip" || fail "modes missing circuit-breaker bullet"
33
-
34
- echo ""
35
- echo "══ autopilot-circuit-breaker smoke: $PASS passed, $FAIL failed ══"
36
- [ "$FAIL" -eq 0 ]