@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,216 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-run-aggregator.sh - v7.8.0 Paket C: unified telemetry aggregator.
3
- #
4
- # Validates run-aggregator.mjs reads phase-tracker + otel-spans + cost table
5
- # and emits a normalized pipeline-run.jsonl with:
6
- # 1. Time-sorted events
7
- # 2. Correct cost computation per cost-table.json
8
- # 3. Span passthrough with task_id stamping
9
- # 4. Summary as last event with totals
10
- # 5. Unknown model graceful degradation
11
- # 6. --summary-only mode
12
- # 7. Read-only contract (no writes to source files)
13
- # 8. Missing inputs handled with clear errors
14
- # 9. Idempotent (running twice produces identical output)
15
-
16
- set -uo pipefail
17
-
18
- REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
19
- SCRIPT="$REPO_ROOT/pipeline/scripts/run-aggregator.mjs"
20
-
21
- PASS=0
22
- FAIL=0
23
- pass() { PASS=$((PASS + 1)); echo " ✓ $1"; }
24
- fail() { FAIL=$((FAIL + 1)); echo " ✗ $1"; }
25
-
26
- cleanup() { [ -n "${TMP:-}" ] && rm -rf "$TMP"; }
27
- trap cleanup EXIT
28
- TMP=$(mktemp -d)
29
-
30
- # ──────────────────────────────────────────────────────────────────────────
31
- echo "→ 1. Setup synthetic task dir + tracker + spans"
32
- cat > "$TMP/phase-tracker.json" <<'EOF'
33
- {
34
- "task_id": "PROJ-100",
35
- "started_at": "2026-04-27T10:00:00Z",
36
- "phases": [
37
- {"id":"0","name":"Init","status":"completed","started_at":"2026-04-27T10:00:00Z","completed_at":"2026-04-27T10:00:30Z","tokens_in":1000,"tokens_out":200,"model":"sonnet","subs":[]},
38
- {"id":"1","name":"Analysis","status":"completed","started_at":"2026-04-27T10:00:30Z","completed_at":"2026-04-27T10:05:00Z","tokens_in":50000,"tokens_out":3000,"model":"opus","subs":[{"id":"1.0","name":"Explore","status":"completed"}]},
39
- {"id":"3","name":"Dev","status":"failed","started_at":"2026-04-27T10:10:00Z","completed_at":"2026-04-27T10:30:00Z","tokens_in":10000,"tokens_out":2000,"model":"sonnet","subs":[]}
40
- ]
41
- }
42
- EOF
43
- cat > "$TMP/otel-spans.jsonl" <<'EOF'
44
- {"name":"phase.update","ts":"2026-04-27T10:00:30Z","attributes":{"multi_agent.status":"completed"}}
45
- {"name":"phase.tokens","ts":"2026-04-27T10:25:00Z","attributes":{"multi_agent.tokens_in_delta":10000}}
46
- EOF
47
- [ -f "$TMP/phase-tracker.json" ] && pass "synthetic phase-tracker.json written"
48
- [ -f "$TMP/otel-spans.jsonl" ] && pass "synthetic otel-spans.jsonl written"
49
-
50
- # Compute hash of source files BEFORE running aggregator
51
- HASH_BEFORE=$(md5 -q "$TMP/phase-tracker.json" "$TMP/otel-spans.jsonl" 2>/dev/null || \
52
- md5sum "$TMP/phase-tracker.json" "$TMP/otel-spans.jsonl" 2>/dev/null | awk '{print $1}' | tr -d '\n')
53
-
54
- # ──────────────────────────────────────────────────────────────────────────
55
- echo "→ 2. Run aggregator → pipeline-run.jsonl produced"
56
- node "$SCRIPT" --task-dir "$TMP" 2>/dev/null
57
- if [ -f "$TMP/pipeline-run.jsonl" ]; then
58
- pass "pipeline-run.jsonl created"
59
- else
60
- fail "pipeline-run.jsonl not created"
61
- fi
62
-
63
- LINE_COUNT=$(wc -l < "$TMP/pipeline-run.jsonl" | tr -d ' ')
64
- if [ "$LINE_COUNT" -ge 8 ]; then
65
- pass "output has $LINE_COUNT events (≥ 8 expected)"
66
- else
67
- fail "too few events: $LINE_COUNT"
68
- fi
69
-
70
- # ──────────────────────────────────────────────────────────────────────────
71
- echo "→ 3. Read-only contract - source files untouched"
72
- HASH_AFTER=$(md5 -q "$TMP/phase-tracker.json" "$TMP/otel-spans.jsonl" 2>/dev/null || \
73
- md5sum "$TMP/phase-tracker.json" "$TMP/otel-spans.jsonl" 2>/dev/null | awk '{print $1}' | tr -d '\n')
74
- if [ "$HASH_BEFORE" = "$HASH_AFTER" ]; then
75
- pass "source files unchanged after aggregation"
76
- else
77
- fail "source files were modified (hash drift)"
78
- fi
79
-
80
- # Static check: aggregator script does not write to phase-tracker or otel-spans
81
- if grep -qE "writeFileSync.*phase-tracker|writeFileSync.*otel-spans" "$SCRIPT"; then
82
- fail "run-aggregator.mjs writes to source telemetry files (read-only contract violated)"
83
- else
84
- pass "no writes to source telemetry files in aggregator"
85
- fi
86
-
87
- # ──────────────────────────────────────────────────────────────────────────
88
- echo "→ 4. Time-sorted events"
89
- # Extract ts values and verify sorted (lexicographic = time-sorted for ISO 8601)
90
- TSS=$(grep -oE '"ts":"[^"]*"' "$TMP/pipeline-run.jsonl" | sed 's/"ts":"//;s/"//')
91
- if [ "$TSS" = "$(echo "$TSS" | sort)" ]; then
92
- pass "events time-sorted (ISO ts ascending)"
93
- else
94
- fail "events out of time order"
95
- fi
96
-
97
- # ──────────────────────────────────────────────────────────────────────────
98
- echo "→ 5. Cost computation correct"
99
- # sonnet 1000+200 = 0.001*3 + 0.0002*15 = 0.003 + 0.003 = 0.006
100
- # opus 50000+3000 = 0.05*5 + 0.003*25 = 0.25 + 0.075 = 0.325
101
- # sonnet 10000+2000 = 0.01*3 + 0.002*15 = 0.03 + 0.03 = 0.060
102
- # total = 0.006 + 0.325 + 0.060 = 0.391
103
- SUMMARY=$(tail -1 "$TMP/pipeline-run.jsonl")
104
- TOTAL=$(echo "$SUMMARY" | grep -oE '"total_cost_usd":[^,}]*' | sed 's/"total_cost_usd"://')
105
- if [ "$TOTAL" = "0.391" ]; then
106
- pass "total_cost_usd = $TOTAL (matches expected)"
107
- else
108
- fail "total_cost_usd = $TOTAL (expected 0.391)"
109
- fi
110
-
111
- # ──────────────────────────────────────────────────────────────────────────
112
- echo "→ 6. Summary as last event"
113
- LAST_KIND=$(tail -1 "$TMP/pipeline-run.jsonl" | grep -oE '"kind":"[^"]*"' | head -1)
114
- if [ "$LAST_KIND" = '"kind":"summary"' ]; then
115
- pass "summary is the final event"
116
- else
117
- fail "last event is not summary: $LAST_KIND"
118
- fi
119
-
120
- # ──────────────────────────────────────────────────────────────────────────
121
- echo "→ 7. Phase status counted correctly"
122
- COMPLETED=$(echo "$SUMMARY" | grep -oE '"phases_completed":[0-9]+' | grep -oE '[0-9]+')
123
- FAILED=$(echo "$SUMMARY" | grep -oE '"phases_failed":[0-9]+' | grep -oE '[0-9]+')
124
- if [ "$COMPLETED" = "2" ] && [ "$FAILED" = "1" ]; then
125
- pass "phases_completed=$COMPLETED phases_failed=$FAILED (matches fixture)"
126
- else
127
- fail "phase counts wrong: completed=$COMPLETED failed=$FAILED (expected 2/1)"
128
- fi
129
-
130
- # ──────────────────────────────────────────────────────────────────────────
131
- echo "→ 8. Span passthrough with task_id stamping"
132
- SPAN_COUNT=$(grep -c '"kind":"span"' "$TMP/pipeline-run.jsonl" || true)
133
- if [ "$SPAN_COUNT" = "2" ]; then
134
- pass "all 2 spans passed through"
135
- else
136
- fail "span passthrough count wrong: $SPAN_COUNT (expected 2)"
137
- fi
138
- if grep -q '"kind":"span".*"task_id":"PROJ-100"' "$TMP/pipeline-run.jsonl"; then
139
- pass "spans stamped with task_id"
140
- else
141
- fail "spans missing task_id stamp"
142
- fi
143
-
144
- # ──────────────────────────────────────────────────────────────────────────
145
- echo "→ 9. --summary-only mode"
146
- SUMMARY_OUT=$(node "$SCRIPT" --task-dir "$TMP" --stdout --summary-only 2>/dev/null)
147
- SUMMARY_LINES=$(echo "$SUMMARY_OUT" | grep -c "^{" || true)
148
- if [ "$SUMMARY_LINES" = "1" ]; then
149
- pass "--summary-only emits exactly 1 line"
150
- else
151
- fail "--summary-only emitted $SUMMARY_LINES lines"
152
- fi
153
-
154
- # ──────────────────────────────────────────────────────────────────────────
155
- echo "→ 10. Unknown model graceful degradation"
156
- cat > "$TMP/phase-tracker.json" <<'EOF'
157
- {
158
- "task_id": "PROJ-200",
159
- "started_at": "2026-04-27T11:00:00Z",
160
- "phases": [
161
- {"id":"0","name":"Init","status":"completed","started_at":"2026-04-27T11:00:00Z","completed_at":"2026-04-27T11:00:10Z","tokens_in":500,"tokens_out":50,"model":"made-up-model","subs":[]}
162
- ]
163
- }
164
- EOF
165
- rm -f "$TMP/otel-spans.jsonl"
166
- node "$SCRIPT" --task-dir "$TMP" --stdout 2>/dev/null > "$TMP/run.jsonl"
167
- if grep -q '"cost_unknown_model":true' "$TMP/run.jsonl"; then
168
- pass "unknown model marked with cost_unknown_model flag"
169
- else
170
- fail "unknown model not flagged"
171
- fi
172
- SUMMARY=$(tail -1 "$TMP/run.jsonl")
173
- if echo "$SUMMARY" | grep -q '"unknown_model_phases":1'; then
174
- pass "summary records unknown_model_phases count"
175
- else
176
- fail "summary missing unknown_model_phases counter"
177
- fi
178
-
179
- # ──────────────────────────────────────────────────────────────────────────
180
- echo "→ 11. Missing task-dir errors clearly"
181
- set +e
182
- node "$SCRIPT" --task-dir /nonexistent/path 2>"$TMP/err.txt"
183
- EC=$?
184
- set -e
185
- if [ "$EC" -ne 0 ] && grep -qE "not found" "$TMP/err.txt"; then
186
- pass "missing task-dir exits $EC with 'not found' error"
187
- else
188
- fail "missing task-dir error handling weak (exit=$EC)"
189
- fi
190
-
191
- # ──────────────────────────────────────────────────────────────────────────
192
- echo "→ 12. Idempotent - second run produces identical content"
193
- # Restore the first fixture
194
- cat > "$TMP/phase-tracker.json" <<'EOF'
195
- {
196
- "task_id": "PROJ-100",
197
- "started_at": "2026-04-27T10:00:00Z",
198
- "phases": [
199
- {"id":"0","name":"Init","status":"completed","started_at":"2026-04-27T10:00:00Z","completed_at":"2026-04-27T10:00:30Z","tokens_in":1000,"tokens_out":200,"model":"sonnet","subs":[]}
200
- ]
201
- }
202
- EOF
203
- node "$SCRIPT" --task-dir "$TMP" 2>/dev/null
204
- H1=$(md5 -q "$TMP/pipeline-run.jsonl" 2>/dev/null || md5sum "$TMP/pipeline-run.jsonl" | awk '{print $1}')
205
- node "$SCRIPT" --task-dir "$TMP" 2>/dev/null
206
- H2=$(md5 -q "$TMP/pipeline-run.jsonl" 2>/dev/null || md5sum "$TMP/pipeline-run.jsonl" | awk '{print $1}')
207
- if [ "$H1" = "$H2" ]; then
208
- pass "two consecutive runs produce identical output"
209
- else
210
- fail "output drift between runs ($H1 vs $H2)"
211
- fi
212
-
213
- # ──────────────────────────────────────────────────────────────────────────
214
- echo ""
215
- echo "══ run-aggregator smoke: $PASS passed, $FAIL failed ══"
216
- [ "$FAIL" -eq 0 ]
@@ -1,50 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-run-metrics.sh - run-metrics.mjs extracts the right outcome numbers
3
- # from an agent-state.json. This is the evidence-collection harness: run it
4
- # after each real task and the corpus becomes the real-world validation.
5
- #
6
- # Exit 0 = all pass, 1 = any failure.
7
-
8
- set -uo pipefail
9
-
10
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
11
- M="$ROOT/pipeline/scripts/run-metrics.mjs"
12
- FIX="$ROOT/pipeline/eval/run-metrics-fixture.json"
13
- PASS=0; FAIL=0
14
- pass() { PASS=$((PASS+1)); echo " ✓ $1"; }
15
- fail() { FAIL=$((FAIL+1)); echo " ✗ $1"; }
16
- command -v node >/dev/null 2>&1 || { echo "error: node required" >&2; exit 127; }
17
- command -v jq >/dev/null 2>&1 || { echo "error: jq required" >&2; exit 127; }
18
- [ -f "$M" ] || { echo "FAIL: run-metrics.mjs missing" >&2; exit 1; }
19
- [ -f "$FIX" ] || { echo "FAIL: fixture missing" >&2; exit 1; }
20
-
21
- out=$(node "$M" --state "$FIX" 2>/dev/null)
22
-
23
- check() { # jq-expr desc
24
- if jq -e "$1" >/dev/null 2>&1 <<< "$out"; then pass "$2"; else fail "$2 (got: $(jq -c "$3" <<< "$out" 2>/dev/null))"; fi
25
- }
26
-
27
- echo "→ 1. core outcome fields"
28
- check '.status == "complete"' "status parsed" '.status'
29
- check '.reviewIterations == 2' "review iterations counted (rework loop)" '.reviewIterations'
30
- check '.firstPassClean == false' "first-pass-clean detects iteration-1 blocker" '.firstPassClean'
31
- check '.buildPassed == true' "build outcome aggregated across repos" '.buildPassed'
32
-
33
- echo ""
34
- echo "→ 2. review signal-to-noise"
35
- check '.reviewSignal.rawFindings == 3' "raw reviewer findings summed" '.reviewSignal.rawFindings'
36
- check '.reviewSignal.acceptedAll == 1' "accepted summed across iterations" '.reviewSignal.acceptedAll'
37
- check '.reviewSignal.acceptedRatio == 0.33' "accepted ratio (signal-to-noise)" '.reviewSignal.acceptedRatio'
38
-
39
- echo ""
40
- echo "→ 3. consensus surfaced"
41
- check '.consensusVerdict == "unanimous-pass"' "consensus verdict extracted" '.consensusVerdict'
42
-
43
- echo ""
44
- echo "→ 4. stdin + missing-field resilience"
45
- echo '{"taskId":"X","status":"failed"}' | node "$M" --state - >/dev/null 2>&1 && pass "minimal state via stdin does not crash" || fail "stdin/minimal state crashed"
46
- node "$M" 2>/dev/null; [ "$?" = "2" ] && pass "no --state -> usage exit 2" || fail "missing --state wrong exit"
47
-
48
- echo ""
49
- echo "══ run-metrics smoke: $PASS passed, $FAIL failed ══"
50
- [ "$FAIL" -eq 0 ]
@@ -1,187 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-search.sh - WS v5.1.0 log-search self-verification.
3
- #
4
- # Verifies (on synthetic fixture tree, never touches real ~/.claude/logs/):
5
- # 1. Script executable, --help shows banner.
6
- # 2. Plain query returns matching tasks.
7
- # 3. --project filter narrows results.
8
- # 4. --since 7d drops old files.
9
- # 5. --phase N limits search to phase section.
10
- # 6. --limit caps results.
11
- # 7. JSON output is valid JSON with matched_tasks count.
12
- # 8. TSV output has header + one row per task.
13
- # 9. No-match returns exit 1 + friendly message.
14
- # 10. Ranking: recent matches score higher than old ones.
15
-
16
- set -uo pipefail
17
-
18
- HERE="$(cd "$(dirname "$0")" && pwd)"
19
- ROOT="$(cd "$HERE/../.." && pwd)"
20
- SEARCH="$ROOT/pipeline/scripts/search-logs.sh"
21
-
22
- PASS=0
23
- FAIL=0
24
- pass() { PASS=$((PASS+1)); echo " ✓ $1"; }
25
- fail() { FAIL=$((FAIL+1)); echo " ✗ $1"; }
26
-
27
- need() { command -v "$1" >/dev/null 2>&1 || { echo "error: $1 required" >&2; exit 127; }; }
28
- need jq
29
-
30
- FIX=$(mktemp -d)
31
- trap 'rm -rf "$FIX"' EXIT
32
-
33
- # --- Fixture tree --------------------------------------------------------
34
-
35
- # Shape: $FIX/<project>/<task_id>/agent-log.md
36
-
37
- mkdir -p "$FIX/app/PROJ-1234" "$FIX/app/PROJ-1337" "$FIX/api/API-42" "$FIX/app/PROJ-OLD"
38
-
39
- cat > "$FIX/app/PROJ-1234/agent-log.md" <<'EOF'
40
- # PROJ-1234 - Add flight price filter
41
-
42
- **Branch**: feature/PROJ-1234-flight-filter | **Project**: app
43
-
44
- ## Phase 1: Analysis
45
- Explored the flight booking module.
46
-
47
- ## Phase 3: Dev
48
- Wrote FlightFilterView. Null check added for optional price range.
49
-
50
- ## Phase 4: Review
51
- 0 blocking, 2 important, 5 suggestion.
52
- EOF
53
-
54
- cat > "$FIX/app/PROJ-1337/agent-log.md" <<'EOF'
55
- # PROJ-1337 - Guard null in BookingViewModel
56
-
57
- **Branch**: bugfix/PROJ-1337-null-deref | **Project**: app
58
-
59
- ## Phase 3: Dev
60
- Null-deref fixed at BookingViewModel.swift:142 via guard let.
61
- Added regression test.
62
-
63
- ## Phase 4: Review
64
- Reviewer flagged the null check as important. Blocking.
65
- EOF
66
-
67
- cat > "$FIX/api/API-42/agent-log.md" <<'EOF'
68
- # API-42 - Rate limit header mismatch
69
-
70
- **Branch**: bugfix/API-42-rate-limit | **Project**: api
71
-
72
- ## Phase 3: Dev
73
- Fixed X-RateLimit-Remaining header emission.
74
- EOF
75
-
76
- cat > "$FIX/app/PROJ-OLD/agent-log.md" <<'EOF'
77
- # PROJ-OLD - Old task
78
-
79
- **Branch**: feature/PROJ-OLD-archive | **Project**: app
80
-
81
- ## Phase 3: Dev
82
- Contains the word null but from long ago.
83
- EOF
84
- # make PROJ-OLD old: 60 days ago
85
- OLD_EPOCH=$(date -v-60d +%s 2>/dev/null || date -d "-60 days" +%s)
86
- touch -t "$(date -r "$OLD_EPOCH" +%Y%m%d%H%M 2>/dev/null || date -d "@$OLD_EPOCH" +%Y%m%d%H%M)" "$FIX/app/PROJ-OLD/agent-log.md"
87
-
88
- # --- 1. Executable + help -----------------------------------------------
89
-
90
- echo "→ 1. search-logs.sh executable + help"
91
- [ -x "$SEARCH" ] && pass "search-logs.sh is executable" || fail "search-logs.sh not executable"
92
- bash "$SEARCH" --help 2>&1 | head -1 | grep -q "search-logs" && pass "--help banner present" || fail "--help banner missing"
93
-
94
- # --- 2. Plain query -----------------------------------------------------
95
-
96
- echo ""
97
- echo "→ 2. plain query returns matching tasks"
98
- OUT=$(bash "$SEARCH" --root "$FIX" "null" 2>&1)
99
- echo "$OUT" | grep -q "PROJ-1337" && pass "PROJ-1337 (high match count) returned" || fail "PROJ-1337 missing"
100
- echo "$OUT" | grep -q "PROJ-1234" && pass "PROJ-1234 (single match) returned" || fail "PROJ-1234 missing"
101
- echo "$OUT" | grep -q "API-42" && fail "API-42 wrongly returned (no 'null')" || pass "API-42 correctly excluded (no 'null')"
102
-
103
- # --- 3. --project filter ------------------------------------------------
104
-
105
- echo ""
106
- echo "→ 3. --project filter narrows results"
107
- OUT=$(bash "$SEARCH" --root "$FIX" --project api "null" 2>&1)
108
- echo "$OUT" | grep -q "no matches" && pass "api project has no 'null' → correctly empty" || fail "api project filter leaked"
109
- OUT=$(bash "$SEARCH" --root "$FIX" --project app "null" 2>&1)
110
- echo "$OUT" | grep -q "PROJ-1234" && pass "app project filter includes PROJ-1234" || fail "app project filter broken"
111
-
112
- # --- 4. --since filter --------------------------------------------------
113
-
114
- echo ""
115
- echo "→ 4. --since 7d drops old tasks"
116
- OUT=$(bash "$SEARCH" --root "$FIX" --since 7d "null" 2>&1)
117
- echo "$OUT" | grep -q "PROJ-OLD" && fail "PROJ-OLD (60d) wrongly included with --since 7d" || pass "PROJ-OLD correctly dropped with --since 7d"
118
- echo "$OUT" | grep -q "PROJ-1337" && pass "recent PROJ-1337 still included with --since 7d" || fail "recent task lost with --since 7d"
119
-
120
- # --- 5. --phase filter --------------------------------------------------
121
-
122
- echo ""
123
- echo "→ 5. --phase 4 limits to phase section"
124
- OUT=$(bash "$SEARCH" --root "$FIX" --phase 4 "blocking" 2>&1)
125
- echo "$OUT" | grep -q "PROJ-1337" && pass "--phase 4 matches Phase 4 content" || fail "--phase 4 broke"
126
-
127
- # --- 6. --limit -----------------------------------------------------
128
-
129
- echo ""
130
- echo "→ 6. --limit caps results"
131
- OUT=$(bash "$SEARCH" --root "$FIX" --limit 1 "null" 2>&1)
132
- count=$(echo "$OUT" | grep -c "^PROJ-\|^API-\|^FIX-")
133
- # just verify command runs and limits in JSON (safer check)
134
- OUT=$(bash "$SEARCH" --root "$FIX" --limit 1 "null" --json 2>&1)
135
- count=$(echo "$OUT" | jq -r '.tasks | length')
136
- [ "$count" -eq 1 ] && pass "--limit 1 returns exactly 1 task" || fail "--limit 1 returned $count tasks"
137
-
138
- # --- 7. JSON output -----------------------------------------------------
139
-
140
- echo ""
141
- echo "→ 7. JSON output valid"
142
- OUT=$(bash "$SEARCH" --root "$FIX" "null" --json 2>&1)
143
- if echo "$OUT" | jq . >/dev/null 2>&1; then
144
- pass "JSON is valid"
145
- else
146
- fail "JSON invalid"
147
- fi
148
- MATCHED=$(echo "$OUT" | jq -r '.matched_tasks')
149
- [ "$MATCHED" -ge 2 ] && pass "JSON matched_tasks ≥ 2 (got $MATCHED)" || fail "JSON matched_tasks = $MATCHED"
150
-
151
- # --- 8. TSV output ------------------------------------------------------
152
-
153
- echo ""
154
- echo "→ 8. TSV output has header + rows"
155
- OUT=$(bash "$SEARCH" --root "$FIX" "null" --tsv 2>&1)
156
- echo "$OUT" | head -1 | grep -q "^score" && pass "TSV has header row" || fail "TSV missing header"
157
- BODY_LINES=$(echo "$OUT" | tail -n +2 | wc -l | tr -d ' ')
158
- [ "$BODY_LINES" -ge 2 ] && pass "TSV has ≥ 2 body rows" || fail "TSV body rows = $BODY_LINES"
159
-
160
- # --- 9. No-match path ---------------------------------------------------
161
-
162
- echo ""
163
- echo "→ 9. no-match → exit 1 + friendly message"
164
- set +e
165
- bash "$SEARCH" --root "$FIX" "nonexistent-string-xyz" > /tmp/search-out 2>&1
166
- RC=$?
167
- set -e
168
- [ "$RC" -eq 1 ] && pass "no-match exit code = 1" || fail "expected 1, got $RC"
169
- grep -q "no matches" /tmp/search-out && pass "no-match message shown" || fail "no-match message missing"
170
-
171
- # --- 10. Ranking: recent > old ------------------------------------------
172
-
173
- echo ""
174
- echo "→ 10. ranking prefers recent matches (score = matches × recency)"
175
- # PROJ-1234: 1 match, recent → score=100 (100% weight)
176
- # PROJ-1337: multiple matches, recent → score>100
177
- # PROJ-OLD: 1 match, 60d old → score=20 (20% weight)
178
- OUT=$(bash "$SEARCH" --root "$FIX" "null" --json 2>&1)
179
- FIRST_ID=$(echo "$OUT" | jq -r '.tasks[0].task_id')
180
- FIRST_SCORE=$(echo "$OUT" | jq -r '.tasks[0].score')
181
- [ "$FIRST_ID" = "PROJ-1337" ] && pass "highest score is PROJ-1337 ($FIRST_SCORE)" || fail "expected PROJ-1337 on top, got $FIRST_ID"
182
-
183
- # --- Summary ------------------------------------------------------------
184
-
185
- echo ""
186
- echo "══ search smoke: $PASS passed, $FAIL failed ══"
187
- [ "$FAIL" -eq 0 ]