@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,158 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-keychain.sh - deterministic Keychain helper contract
3
- #
4
- # Verifies the Python Keychain helper that backs setup, Phase 0 token reads,
5
- # Phase 6 push retry, and the channel notifiers:
6
- # 1. keychain.py parses cleanly (Python 3 stdlib only)
7
- # 2. doctor reports the expected backend for the host platform
8
- # 3. Roundtrip on macOS: set / get / rotate-via-stdin / delete
9
- # 4. get-after-delete returns exit 1 (item missing)
10
- # 5. Cross-convention lookup: items written via -l (label) AND -s (service)
11
- # are findable by both forms - ensures parity with the user's
12
- # manually-added personal tokens (-l only) and credential-store.sh
13
- # managed items (-s only).
14
- # 6. Argparse surface: every documented subcommand registered.
15
- #
16
- # Linux/CI hosts skip the live roundtrip (no libsecret keyring agent under
17
- # typical CI) but still enforce parse + argparse + doctor remediation text.
18
- #
19
- # Exit 0 = all pass, 1 = any failure.
20
-
21
- set -uo pipefail
22
-
23
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
24
- KEYCHAIN_PY="$ROOT/pipeline/scripts/keychain.py"
25
-
26
- pass=0
27
- fail=0
28
- failures=()
29
- record_pass() { pass=$((pass + 1)); printf ' \033[0;32mPASS\033[0m %s\n' "$1"; }
30
- record_fail() { fail=$((fail + 1)); failures+=("$1"); printf ' \033[0;31mFAIL\033[0m %s\n' "$1"; }
31
-
32
- printf '→ smoke-keychain: deterministic Python Keychain helper contract\n'
33
-
34
- # --- 0: file present ---
35
- if [ ! -f "$KEYCHAIN_PY" ]; then
36
- record_fail "keychain.py missing at $KEYCHAIN_PY"
37
- printf '\n→ smoke-keychain: %d/%d passed\n' "$pass" "$((pass + fail))"
38
- exit 1
39
- fi
40
-
41
- # --- 1: parse cleanly ---
42
- if python3 -c "import ast,sys; ast.parse(open('$KEYCHAIN_PY').read())" 2>/dev/null; then
43
- record_pass "keychain.py parses cleanly"
44
- else
45
- record_fail "keychain.py failed to parse"
46
- fi
47
-
48
- # --- 2: argparse surface ---
49
- HELP_OUT=$(python3 "$KEYCHAIN_PY" --help 2>&1 || true)
50
- for sub in get set delete list doctor; do
51
- if grep -qE "[{, ]${sub}[},]" <<< "$HELP_OUT"; then
52
- record_pass "argparse exposes '$sub' subcommand"
53
- else
54
- record_fail "argparse missing '$sub' subcommand"
55
- fi
56
- done
57
-
58
- # --- 3: doctor returns valid JSON ---
59
- DOCTOR_JSON=$(python3 "$KEYCHAIN_PY" doctor 2>&1 || true)
60
- if jq -e '.platform and (.backend_ok | type == "boolean")' <<< "$DOCTOR_JSON" >/dev/null 2>&1; then
61
- record_pass "doctor returns schema-conforming JSON"
62
- else
63
- record_fail "doctor JSON malformed: $DOCTOR_JSON"
64
- fi
65
-
66
- PLATFORM=$(jq -r '.platform' <<< "$DOCTOR_JSON" 2>/dev/null || echo "unknown")
67
- BACKEND_OK=$(jq -r '.backend_ok' <<< "$DOCTOR_JSON" 2>/dev/null || echo "false")
68
-
69
- # --- 4: live roundtrip (macOS only - Linux CI rarely has libsecret agent) ---
70
- if [ "$PLATFORM" = "macos" ] && [ "$BACKEND_OK" = "true" ]; then
71
- TEST_LABEL="_keychain_smoke_$$_$(date +%s)"
72
- TEST_VALUE="smoke-value-roundtrip"
73
-
74
- if python3 "$KEYCHAIN_PY" set "$TEST_LABEL" "$TEST_VALUE" >/dev/null 2>&1; then
75
- record_pass "set succeeds"
76
- else
77
- record_fail "set failed"
78
- fi
79
-
80
- GOT=$(python3 "$KEYCHAIN_PY" get "$TEST_LABEL" 2>/dev/null || true)
81
- if [ "$GOT" = "$TEST_VALUE" ]; then
82
- record_pass "get returns the stored value (no trailing newline)"
83
- else
84
- record_fail "get mismatch: '$GOT' != '$TEST_VALUE'"
85
- fi
86
-
87
- # Cross-convention parity: setup/credential-store.sh keys items by -s, but the
88
- # user's personal tokens are keyed by -l. The helper must store both.
89
- if /usr/bin/security find-generic-password -l "$TEST_LABEL" -w >/dev/null 2>&1; then
90
- record_pass "set wrote -l (label) attribute"
91
- else
92
- record_fail "set did NOT write -l (label) attribute"
93
- fi
94
- if /usr/bin/security find-generic-password -s "$TEST_LABEL" -w >/dev/null 2>&1; then
95
- record_pass "set wrote -s (service) attribute"
96
- else
97
- record_fail "set did NOT write -s (service) attribute"
98
- fi
99
-
100
- # Stdin rotation (preferred - keeps secrets out of shell history).
101
- ROTATED="rotated-$$"
102
- if printf '%s' "$ROTATED" | python3 "$KEYCHAIN_PY" set "$TEST_LABEL" - >/dev/null 2>&1; then
103
- GOT2=$(python3 "$KEYCHAIN_PY" get "$TEST_LABEL" 2>/dev/null || true)
104
- if [ "$GOT2" = "$ROTATED" ]; then
105
- record_pass "stdin set ('-' sentinel) rotates value"
106
- else
107
- record_fail "stdin set: got '$GOT2' want '$ROTATED'"
108
- fi
109
- else
110
- record_fail "stdin set failed"
111
- fi
112
-
113
- # Delete + missing-after-delete contract.
114
- if python3 "$KEYCHAIN_PY" delete "$TEST_LABEL" >/dev/null 2>&1; then
115
- record_pass "delete succeeds"
116
- else
117
- record_fail "delete failed"
118
- fi
119
-
120
- set +e
121
- python3 "$KEYCHAIN_PY" get "$TEST_LABEL" >/dev/null 2>&1
122
- rc_missing=$?
123
- set -e
124
- if [ "$rc_missing" -eq 1 ]; then
125
- record_pass "get-after-delete exits 1 (item missing)"
126
- else
127
- record_fail "get-after-delete should exit 1, got $rc_missing"
128
- fi
129
-
130
- # Belt-and-braces: ensure delete cleared BOTH attribute forms.
131
- if ! /usr/bin/security find-generic-password -l "$TEST_LABEL" -w >/dev/null 2>&1 \
132
- && ! /usr/bin/security find-generic-password -s "$TEST_LABEL" -w >/dev/null 2>&1; then
133
- record_pass "delete clears both -l and -s entries"
134
- else
135
- record_fail "delete left a stale -l or -s entry behind"
136
- fi
137
- elif [ "$PLATFORM" = "linux" ] && [ "$BACKEND_OK" = "true" ]; then
138
- # Linux: only validate non-secret-touching paths to stay CI-safe.
139
- record_pass "linux backend present (libsecret); skipping live roundtrip"
140
- else
141
- # Backend unavailable - verify doctor surfaces remediation text.
142
- REMEDIATION=$(jq -r '.remediation // ""' <<< "$DOCTOR_JSON")
143
- if [ -n "$REMEDIATION" ] && [ "$REMEDIATION" != "null" ]; then
144
- record_pass "doctor surfaces remediation text when backend unavailable"
145
- else
146
- record_fail "doctor missing remediation text on unsupported platform"
147
- fi
148
- fi
149
-
150
- # --- Summary ---
151
- total=$((pass + fail))
152
- printf '\n→ smoke-keychain: %d/%d passed\n' "$pass" "$total"
153
- if [ "$fail" -ne 0 ]; then
154
- printf '\nFailures:\n'
155
- for f in "${failures[@]}"; do printf ' - %s\n' "$f"; done
156
- exit 1
157
- fi
158
- exit 0
@@ -1,109 +0,0 @@
1
- #!/usr/bin/env bash
2
- #
3
- # smoke-language-axis.sh
4
- #
5
- # Asserts the Language Application contract from refs/rules.md is honored
6
- # across every phase doc and orchestrator command:
7
- #
8
- # - AskUserQuestion.label -> English (UI button)
9
- # - AskUserQuestion.header -> English (chip)
10
- # - AskUserQuestion.question -> outputLanguage
11
- # - AskUserQuestion.options[].description -> outputLanguage
12
- #
13
- # In particular, this gate forbids the deprecated "ask in English (promptLanguage
14
- # locked to en)" wording that survived from earlier versions and made phase docs
15
- # instruct the orchestrator to render picker question + description in English
16
- # even when outputLanguage was Turkish.
17
- #
18
- # Defect 1 from docs/STABILITY-FIX-PLAN.md.
19
-
20
- set -euo pipefail
21
-
22
- SELF_DIR=$(cd "$(dirname "$0")" && pwd)
23
- PIPELINE_ROOT=$(cd "$SELF_DIR/.." && pwd)
24
-
25
- cd "$PIPELINE_ROOT"
26
-
27
- FAIL=0
28
-
29
- # Phrases that mean "ALL picker text English" - over-broad, contradicts the
30
- # rules.md matrix. Rule update is in v8.5.1 (rules.md narrowed). Anywhere
31
- # in phase docs / orchestrator commands that still says this is a regression.
32
- declare -a FORBIDDEN_PHRASES=(
33
- 'ask in English'
34
- 'always render in English'
35
- 'always English'
36
- 'render.*in English.*\bpromptLanguage\b'
37
- 'User-facing strings.*always.*English'
38
- 'all .*picker.*text.*English'
39
- )
40
-
41
- # In-scope: phase docs + orchestrator commands. Not in scope: rules.md itself
42
- # (it's the rule source), CHANGELOG (history), STABILITY-FIX-PLAN (history),
43
- # and feedback memory (notes the rule, can quote it).
44
- TARGETS=(
45
- "multi-agent-refs/phases/*.md"
46
- "commands/multi-agent/*.md"
47
- "skills/shared/core/multi-agent/SKILL.md"
48
- )
49
-
50
- # Allowlist: rules.md, language.md (the toggle command - explains the contract),
51
- # setup.md (Step 0 sets the language and explains why label stays English),
52
- # refs/picker-contract.md (UI contract spec).
53
- declare -a ALLOWLIST=(
54
- "multi-agent-refs/rules.md"
55
- "commands/multi-agent/language/SKILL.md"
56
- "commands/multi-agent/setup/SKILL.md"
57
- "multi-agent-refs/picker-contract.md"
58
- )
59
-
60
- is_allowlisted() {
61
- local f="$1"
62
- for a in "${ALLOWLIST[@]}"; do
63
- [ "$f" = "$a" ] && return 0
64
- done
65
- return 1
66
- }
67
-
68
- for pattern in "${FORBIDDEN_PHRASES[@]}"; do
69
- for glob in "${TARGETS[@]}"; do
70
- while IFS= read -r match; do
71
- [ -z "$match" ] && continue
72
- file="${match%%:*}"
73
- # Relative path for allowlist check.
74
- rel="${file#$PIPELINE_ROOT/pipeline/}"
75
- if is_allowlisted "$rel"; then continue; fi
76
- # Allow per-line annotation.
77
- if echo "$match" | grep -q '# allow: language-axis-quote'; then continue; fi
78
- echo "FAIL [smoke-language-axis]: forbidden 'all-English' phrase in $rel"
79
- echo " $match"
80
- FAIL=$((FAIL + 1))
81
- done < <(grep -rEni "$pattern" "pipeline/$glob" 2>/dev/null || true)
82
- done
83
- done
84
-
85
- # Positive assertion: rules.md must contain the per-field language matrix.
86
- RULES="multi-agent-refs/rules.md"
87
- if [ -f "pipeline/$RULES" ]; then
88
- if ! grep -q "Per-field language matrix" "pipeline/$RULES"; then
89
- echo "FAIL [smoke-language-axis]: $RULES must contain the 'Per-field language matrix' section"
90
- FAIL=$((FAIL + 1))
91
- fi
92
- if ! grep -qE "AskUserQuestion\.options\[\]\.label.*English" "pipeline/$RULES"; then
93
- echo "FAIL [smoke-language-axis]: $RULES matrix must keep 'options[].label -> English'"
94
- FAIL=$((FAIL + 1))
95
- fi
96
- if ! grep -qE "AskUserQuestion\.question.*outputLanguage" "pipeline/$RULES"; then
97
- echo "FAIL [smoke-language-axis]: $RULES matrix must route 'question -> outputLanguage'"
98
- FAIL=$((FAIL + 1))
99
- fi
100
- fi
101
-
102
- if [ "$FAIL" -gt 0 ]; then
103
- echo ""
104
- echo "smoke-language-axis: $FAIL violation(s)."
105
- echo "Defect 1: AskUserQuestion.question + .description follow outputLanguage; only label + header stay English. See refs/rules.md."
106
- exit 1
107
- fi
108
-
109
- echo "smoke-language-axis: ok"
@@ -1,61 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-learning-curve.sh - contract for learning-curve.mjs (time-bucketed
3
- # trend over metrics.jsonl).
4
-
5
- set -uo pipefail
6
-
7
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8
- LC="$SCRIPT_DIR/learning-curve.mjs"
9
-
10
- PASS=0
11
- FAIL=0
12
- record_pass() { PASS=$((PASS + 1)); printf ' \342\234\223 %s\n' "$1"; }
13
- record_fail() { FAIL=$((FAIL + 1)); printf ' \342\234\227 %s\n' "$1"; }
14
-
15
- printf '\342\206\222 smoke-learning-curve: metrics trend contract\n'
16
-
17
- tmp=$(mktemp -d "${TMPDIR:-/tmp}/lc.XXXXXX")
18
- trap 'rm -rf "$tmp"' EXIT
19
- M="$tmp/metrics.jsonl"
20
-
21
- # Two early tasks (noisy: 3/2 review cycles, low cache) + two later tasks
22
- # (clean: 1 cycle, high cache) -> the curve should improve.
23
- cat > "$M" <<'EOF'
24
- {"ts":"2026-06-02T10:00:00Z","task_id":"t1","phase":"4","event":"review.completed","details":{"review_cycles":3,"tokens_in":100000,"tokens_out":8000,"tokens_cached":10000}}
25
- {"ts":"2026-06-02T10:05:00Z","task_id":"t1","phase":"3","event":"rework.started","details":{}}
26
- {"ts":"2026-06-03T09:00:00Z","task_id":"t2","phase":"4","event":"review.completed","details":{"review_cycles":2,"tokens_in":90000,"tokens_out":7000,"tokens_cached":20000}}
27
- {"ts":"2026-06-24T09:00:00Z","task_id":"t3","phase":"4","event":"review.completed","details":{"review_cycles":1,"tokens_in":40000,"tokens_out":4000,"tokens_cached":30000}}
28
- {"ts":"2026-06-25T09:00:00Z","task_id":"t4","phase":"4","event":"review.completed","details":{"review_cycles":1,"tokens_in":38000,"tokens_out":3500,"tokens_cached":32000}}
29
- EOF
30
-
31
- # 1. parses
32
- bash -n "$SCRIPT_DIR/smoke-learning-curve.sh" >/dev/null 2>&1 || true
33
- if node --check "$LC" 2>/dev/null; then record_pass "learning-curve.mjs parses"; else record_fail "syntax error"; fi
34
-
35
- # 2. JSON: buckets + improving trend
36
- out=$(METRICS_FILE="$M" node "$LC" --json 2>/dev/null)
37
- nbuckets=$(printf '%s' "$out" | python3 -c "import json,sys;print(len(json.load(sys.stdin)['buckets']))")
38
- [ "$nbuckets" -ge 2 ] && record_pass "produces >=2 time buckets" || record_fail "expected >=2 buckets, got $nbuckets"
39
-
40
- tokens_delta=$(printf '%s' "$out" | python3 -c "import json,sys;print(json.load(sys.stdin)['trend']['tokensPerTask'])")
41
- case "$tokens_delta" in
42
- -*) record_pass "tokens/task trend is negative (improving)" ;;
43
- *) record_fail "tokens/task trend should drop, got $tokens_delta" ;;
44
- esac
45
- cache_delta=$(printf '%s' "$out" | python3 -c "import json,sys;print(json.load(sys.stdin)['trend']['cacheRatio'])")
46
- case "$cache_delta" in
47
- -*|0|0.0) record_fail "cache ratio should rise, got $cache_delta" ;;
48
- *) record_pass "cache ratio trend rises (improving)" ;;
49
- esac
50
-
51
- # 3. markdown renders a table + trend
52
- md=$(METRICS_FILE="$M" node "$LC" 2>/dev/null)
53
- printf '%s' "$md" | grep -q "Learning curve" && record_pass "markdown has a header" || record_fail "no markdown header"
54
- printf '%s' "$md" | grep -q "Trend" && record_pass "markdown shows a trend block" || record_fail "no trend block"
55
-
56
- # 4. missing metrics -> graceful, exit 0
57
- METRICS_FILE="/nope/none.jsonl" node "$LC" --json >/dev/null 2>&1
58
- [ "$?" -eq 0 ] && record_pass "missing metrics is a graceful no-op (exit 0)" || record_fail "missing metrics should exit 0"
59
-
60
- printf '\n\342\225\220\342\225\220 smoke-learning-curve: %d passed, %d failed \342\225\220\342\225\220\n' "$PASS" "$FAIL"
61
- [ "$FAIL" -eq 0 ]
@@ -1,86 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-learnings-ledger.sh - contract check for the persistent learnings ledger.
3
- #
4
- # Verifies:
5
- # 1. add appends a fact / convention; identical statement is deduped.
6
- # 2. from-triage distills rejected findings into rejected-preference entries.
7
- # 3. brief emits a <repo-learnings> block grouped by kind; exit 2 when empty.
8
- # 4. Storage is per-repo isolated (slug A never sees slug B).
9
- # 5. Phase docs + prefs schema wire the ledger in.
10
- #
11
- # Uses an isolated HOME so it never touches the developer's real memory store.
12
- # Exit 0 = all pass, 1 = any failure.
13
-
14
- set -uo pipefail
15
-
16
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
17
- L="$ROOT/pipeline/scripts/learnings-ledger.mjs"
18
- TMPHOME="$(mktemp -d)"
19
- trap 'rm -rf "$TMPHOME"' EXIT
20
- export HOME="$TMPHOME" # redirect ~/.claude/memory into the sandbox
21
-
22
- PASS=0
23
- FAIL=0
24
- pass() { PASS=$((PASS+1)); echo " ✓ $1"; }
25
- fail() { FAIL=$((FAIL+1)); echo " ✗ $1"; }
26
-
27
- command -v node >/dev/null 2>&1 || { echo "error: node required" >&2; exit 127; }
28
- [ -f "$L" ] || { echo "FAIL: learnings-ledger.mjs missing" >&2; exit 1; }
29
-
30
- SLUG=repoA
31
-
32
- echo "→ 1. add + dedup"
33
- out=$(node "$L" add --kind fact --statement "Auth tokens persist via KeychainStore" --scope "Auth/*" --repo-slug "$SLUG")
34
- echo "$out" | grep -q '"added":1' && pass "first add writes" || fail "first add did not write ($out)"
35
- out=$(node "$L" add --kind fact --statement "auth tokens persist via keychainstore" --repo-slug "$SLUG"; echo "rc=$?")
36
- echo "$out" | grep -q '"added":0' && pass "case-insensitive dedup" || fail "dedup failed ($out)"
37
- echo "$out" | grep -q 'rc=2' && pass "dedup exits 2" || fail "dedup exit code wrong ($out)"
38
-
39
- echo ""
40
- echo "→ 2. from-triage distills rejections"
41
- printf '{"accepted":[],"deferred":[],"rejected":[{"finding":{"severity":"suggestion","file":"Net/Client.swift","line":12,"issue":"add Sendable annotation"},"reason":"requires Swift 6 migration"}],"approved":true}' > "$TMPHOME/tri.json"
42
- out=$(node "$L" from-triage --triage "$TMPHOME/tri.json" --task PROJ-9 --repo-slug "$SLUG")
43
- echo "$out" | grep -q '"added":1' && pass "rejected finding becomes a rejected-preference" || fail "from-triage failed ($out)"
44
-
45
- echo ""
46
- echo "→ 2b. SAFETY: blocking rejections are NOT auto-suppressed"
47
- printf '{"accepted":[],"deferred":[],"rejected":[{"finding":{"severity":"blocking","file":"Auth/x.swift","line":1,"issue":"missing access-control flag on keychain item"},"reason":"reviewer says false positive"},{"finding":{"severity":"suggestion","file":"Net/y.swift","line":2,"issue":"rename helper for clarity"},"reason":"style only"}]}' > "$TMPHOME/blk.json"
48
- out=$(node "$L" from-triage --triage "$TMPHOME/blk.json" --task PROJ-2 --repo-slug "$SLUG")
49
- echo "$out" | grep -q '"skippedBlocking":1' && pass "blocking rejection skipped" || fail "blocking not skipped ($out)"
50
- echo "$out" | grep -q '"added":1' && pass "non-blocking rejection still distilled" || fail "suggestion not added ($out)"
51
- brief2=$(node "$L" brief --repo-slug "$SLUG")
52
- echo "$brief2" | grep -qi "missing access-control flag" && fail "blocking issue leaked into brief (would suppress a real finding)" || pass "blocking issue absent from brief"
53
-
54
- echo ""
55
- echo "→ 2c. forget removes a bad/stale entry"
56
- node "$L" forget --statement "rename helper" --repo-slug "$SLUG" >/dev/null 2>&1
57
- brief3=$(node "$L" brief --repo-slug "$SLUG" 2>/dev/null || true)
58
- echo "$brief3" | grep -qi "rename helper" && fail "forget did not remove the entry" || pass "forget removed the targeted entry"
59
-
60
- echo ""
61
- echo "→ 3. brief content + emptiness"
62
- brief=$(node "$L" brief --repo-slug "$SLUG")
63
- echo "$brief" | grep -q '<repo-learnings>' && pass "brief emits repo-learnings block" || fail "brief block missing"
64
- echo "$brief" | grep -q 'Architectural facts' && pass "brief groups facts" || fail "facts group missing"
65
- echo "$brief" | grep -qi 'do not re-flag: add Sendable' && pass "brief surfaces rejected preference" || fail "rejected preference not in brief"
66
- rc=0
67
- node "$L" brief --repo-slug emptyRepo >/dev/null 2>&1 || rc=$?
68
- [ "$rc" = "2" ] && pass "brief on empty ledger exits 2" || fail "empty brief exit code wrong (got $rc)"
69
-
70
- echo ""
71
- echo "→ 4. per-repo isolation"
72
- node "$L" add --kind fact --statement "repoB only fact" --repo-slug repoB >/dev/null 2>&1
73
- briefA=$(node "$L" brief --repo-slug "$SLUG")
74
- echo "$briefA" | grep -q 'repoB only fact' && fail "repoA brief leaked repoB content" || pass "repoA does not see repoB entries"
75
-
76
- echo ""
77
- echo "→ 5. wiring + docs"
78
- grep -q 'learnings-ledger.mjs' "$ROOT/pipeline/multi-agent-refs/phases/phase-1-analysis.md" && pass "phase-1 injects the brief" || fail "phase-1 wiring missing"
79
- grep -q 'learnings-ledger.mjs' "$ROOT/pipeline/multi-agent-refs/phases/phase-4-review.md" && pass "phase-4 triage injects rejected prefs" || fail "phase-4 wiring missing"
80
- grep -q 'learnings-ledger.mjs' "$ROOT/pipeline/multi-agent-refs/phases/phase-7-report.md" && pass "phase-7 distills the ledger" || fail "phase-7 wiring missing"
81
- grep -q '"learningsLedger"' "$ROOT/pipeline/schemas/prefs.schema.json" && pass "prefs exposes learningsLedger" || fail "prefs toggle missing"
82
- [ -f "$ROOT/pipeline/schemas/learnings-ledger.schema.json" ] && pass "ledger schema present" || fail "ledger schema missing"
83
-
84
- echo ""
85
- echo "══ learnings-ledger smoke: $PASS passed, $FAIL failed ══"
86
- [ "$FAIL" -eq 0 ]