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