@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,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 ]