@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,255 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-bitbucket-contract.sh - offline contract test for repo-cache.sh
3
- # Bitbucket Server backend.
4
- #
5
- # Replaces curl with a stub that serves a fixture JSON, then verifies the
6
- # python parser shape-converts the BB Server `/rest/api/1.0/projects/.../repos`
7
- # response into the canonical {fullName, name, owner, cloneUrl, provider}
8
- # schema that the picker consumes.
9
- #
10
- # Why offline: live Bitbucket Server REST requires a corporate host + project
11
- # key + valid token. Without those, contract drift would only surface in
12
- # production. This smoke pins the request URL, the response parsing, and the
13
- # auth header construction so changes that break either fail in CI.
14
-
15
- set -uo pipefail
16
-
17
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
18
- REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
19
- LIB_DIR="$REPO_ROOT/pipeline/lib"
20
-
21
- PASS=0; FAIL=0
22
- ok() { echo " ✓ $1"; PASS=$((PASS+1)); }
23
- fail() { echo " ✗ $1" >&2; FAIL=$((FAIL+1)); }
24
-
25
- REPO_CACHE="$LIB_DIR/repo-cache.sh"
26
- [ -x "$REPO_CACHE" ] || { fail "repo-cache.sh missing/not executable"; exit 1; }
27
-
28
- # --- Stub setup -------------------------------------------------------------
29
- TMP=$(mktemp -d)
30
- trap 'rm -rf "$TMP"' EXIT
31
-
32
- # Fixture: minimal but realistic BB Server response shape (as documented at
33
- # https://docs.atlassian.com/bitbucket-server/rest/7.21.0/bitbucket-rest.html)
34
- cat > "$TMP/fixture.json" <<'EOF'
35
- {
36
- "size": 2,
37
- "limit": 200,
38
- "isLastPage": true,
39
- "values": [
40
- {
41
- "slug": "my-ios-app",
42
- "name": "my-ios-app",
43
- "project": {"key": "MOBILE", "name": "Mobile Team"},
44
- "description": "iOS application",
45
- "links": {
46
- "clone": [
47
- {"href": "https://bitbucket.example.com/scm/mobile/my-ios-app.git", "name": "http"},
48
- {"href": "ssh://git@bitbucket.example.com/mobile/my-ios-app.git", "name": "ssh"}
49
- ]
50
- }
51
- },
52
- {
53
- "slug": "common-ui-kit",
54
- "name": "common-ui-kit",
55
- "project": {"key": "MOBILE", "name": "Mobile Team"},
56
- "description": "Shared UI components",
57
- "links": {
58
- "clone": [
59
- {"href": "https://bitbucket.example.com/scm/mobile/common-ui-kit.git", "name": "http"},
60
- {"href": "ssh://git@bitbucket.example.com/mobile/common-ui-kit.git", "name": "ssh"}
61
- ]
62
- }
63
- }
64
- ]
65
- }
66
- EOF
67
-
68
- # Stub curl that captures invocation and returns the fixture. PATH-shadows the
69
- # real curl for this smoke only. Auth travels via `-K <config-file>` (so the
70
- # token never hits argv); the stub dumps the config file so the smoke can
71
- # assert its contents.
72
- cat > "$TMP/curl" <<EOF
73
- #!/usr/bin/env bash
74
- # Capture every invocation so we can assert the URL + auth config shape.
75
- echo "INVOCATION:" "\$@" >> "$TMP/curl-calls.log"
76
- prev=""
77
- for arg in "\$@"; do
78
- if [ "\$prev" = "-K" ]; then
79
- echo "AUTH-CONFIG: \$(cat "\$arg" 2>/dev/null)" >> "$TMP/curl-calls.log"
80
- fi
81
- prev="\$arg"
82
- done
83
- # Echo the fixture body (BB Server response) to stdout - same as real curl -sf.
84
- cat "$TMP/fixture.json"
85
- exit 0
86
- EOF
87
- chmod +x "$TMP/curl"
88
-
89
- # Stub `security` so credential-store.sh `get` returns deterministic test values.
90
- # We do this rather than touching the real Keychain.
91
- cat > "$TMP/security" <<EOF
92
- #!/usr/bin/env bash
93
- # Mimic the relevant security subcommands used by credential-store.sh.
94
- case "\$1" in
95
- find-generic-password)
96
- # macOS path. Args: -s NAME -w
97
- while [ \$# -gt 0 ]; do
98
- case "\$1" in
99
- -s) shift; SVC="\$1" ;;
100
- esac
101
- shift || break
102
- done
103
- case "\$SVC" in
104
- mock_BB_Token) echo "test-bb-token" ;;
105
- mock_BB_User) echo "test-bb-user" ;;
106
- *) exit 44 ;;
107
- esac
108
- ;;
109
- dump-keychain) ;; # noop for list
110
- esac
111
- EOF
112
- chmod +x "$TMP/security"
113
-
114
- # Stub `secret-tool` for the same purpose on Linux - credential-store.sh
115
- # routes get() through libsecret there, so the macOS `security` stub alone
116
- # leaves BB_TOKEN empty and every downstream assertion blank.
117
- cat > "$TMP/secret-tool" <<EOF
118
- #!/usr/bin/env bash
119
- # Mimic: secret-tool lookup service <key>
120
- if [ "\$1" = "lookup" ]; then
121
- case "\$3" in
122
- mock_BB_Token) echo "test-bb-token" ;;
123
- mock_BB_User) echo "test-bb-user" ;;
124
- *) exit 1 ;;
125
- esac
126
- fi
127
- EOF
128
- chmod +x "$TMP/secret-tool"
129
-
130
- # Override repo-cache TTL and stub PATH so curl + security come from $TMP.
131
- export PATH="$TMP:$PATH"
132
- export REPO_CACHE_TTL=0 # skip cache, force fetch
133
- export BB_TOKEN_KEY="mock_BB_Token"
134
- export BB_USER_KEY="mock_BB_User"
135
- export BB_HOST="bitbucket.example.com"
136
-
137
- # Run with a sandboxed cache dir so we don't pollute the real one
138
- export HOME="$TMP/fakehome"
139
- mkdir -p "$HOME/.claude/cache/repos" "$HOME/.claude/lib"
140
- ln -sf "$LIB_DIR/credential-store.sh" "$HOME/.claude/lib/credential-store.sh"
141
-
142
- # --- Run the call -----------------------------------------------------------
143
- echo "→ 1. repo-cache.sh bitbucket MOBILE - invoke + parse"
144
- out=$("$REPO_CACHE" bitbucket MOBILE --refresh 2>&1)
145
- if [ $? -eq 0 ]; then
146
- ok "exit 0 with valid fixture"
147
- else
148
- fail "exit non-zero on valid fixture: $out"
149
- fi
150
-
151
- # --- Assert: curl called with correct URL + auth ----------------------------
152
- echo "→ 2. curl invocation captured the right URL"
153
- if grep -q "https://bitbucket.example.com/rest/api/1.0/projects/MOBILE/repos" "$TMP/curl-calls.log"; then
154
- ok "URL matches BB Server REST contract (/rest/api/1.0/projects/{key}/repos)"
155
- else
156
- fail "URL wrong; captured: $(cat "$TMP/curl-calls.log")"
157
- fi
158
-
159
- if grep -q "limit=200" "$TMP/curl-calls.log"; then
160
- ok "page limit=200 (the BB Server max)"
161
- else
162
- fail "limit param missing"
163
- fi
164
-
165
- if grep -q 'AUTH-CONFIG: user = "test-bb-user:test-bb-token"' "$TMP/curl-calls.log"; then
166
- ok "Basic auth uses {user}:{token} via curl -K config (not argv)"
167
- else
168
- fail "auth config wrong; captured: $(grep 'AUTH-CONFIG' "$TMP/curl-calls.log" || echo none)"
169
- fi
170
-
171
- # The raw token must never appear on curl argv (visible to ps).
172
- if grep "^INVOCATION:" "$TMP/curl-calls.log" | grep -q "test-bb-token"; then
173
- fail "token leaked onto curl argv"
174
- else
175
- ok "token absent from curl argv"
176
- fi
177
-
178
- # --- Assert: shape conversion produced canonical schema ---------------------
179
- echo "→ 3. parser converts BB shape → canonical schema"
180
- canonical=$(printf '%s' "$out" | python3 -c '
181
- import json, sys
182
- data = json.load(sys.stdin)
183
- required = {"fullName","name","owner","description","isFork","updatedAt","cloneUrl","provider"}
184
- for r in data:
185
- miss = required - set(r.keys())
186
- if miss:
187
- sys.stderr.write("MISS:" + str(sorted(miss)) + "\n")
188
- sys.exit(1)
189
- if r["provider"] != "bitbucket":
190
- sys.stderr.write("BAD_PROVIDER:" + r["provider"] + "\n")
191
- sys.exit(1)
192
- print(json.dumps(data))
193
- ')
194
- if [ -n "$canonical" ]; then
195
- ok "every output entry has the canonical fields + provider=bitbucket"
196
- else
197
- fail "shape conversion failed"
198
- fi
199
-
200
- count=$(printf '%s' "$canonical" | python3 -c 'import json,sys; print(len(json.load(sys.stdin)))')
201
- if [ "$count" = "2" ]; then
202
- ok "all values[] entries surfaced (count matches fixture)"
203
- else
204
- fail "count $count != 2"
205
- fi
206
-
207
- # Specific field plumbing
208
- first_full=$(printf '%s' "$canonical" | python3 -c 'import json,sys; print(json.load(sys.stdin)[0]["fullName"])')
209
- if [ "$first_full" = "MOBILE/my-ios-app" ]; then
210
- ok "fullName format: <projectKey>/<slug>"
211
- else
212
- fail "fullName wrong: $first_full"
213
- fi
214
-
215
- first_clone=$(printf '%s' "$canonical" | python3 -c 'import json,sys; print(json.load(sys.stdin)[0]["cloneUrl"])')
216
- if printf '%s' "$first_clone" | grep -q "^ssh://"; then
217
- ok "cloneUrl prefers ssh link when both available"
218
- else
219
- fail "cloneUrl should prefer ssh, got: $first_clone"
220
- fi
221
-
222
- # --- Assert: empty values[] handled cleanly ---------------------------------
223
- echo "→ 4. empty BB project (no repos) returns empty array"
224
- cat > "$TMP/fixture.json" <<'EOF'
225
- {"size": 0, "limit": 200, "isLastPage": true, "values": []}
226
- EOF
227
- out=$("$REPO_CACHE" bitbucket EMPTY --refresh 2>&1)
228
- parsed=$(printf '%s' "$out" | python3 -c 'import json,sys; print(len(json.load(sys.stdin)))' 2>/dev/null || echo "ERR")
229
- if [ "$parsed" = "0" ]; then
230
- ok "empty project → []"
231
- else
232
- fail "empty project parse failed (got: $parsed)"
233
- fi
234
-
235
- # --- Assert: missing token exits with diagnostic ----------------------------
236
- echo "→ 5. missing BB token → exit 3 with hint"
237
- unset BB_TOKEN_KEY
238
- err=$("$REPO_CACHE" bitbucket MOBILE --refresh 2>&1 >/dev/null) || true
239
- # repo-cache.sh fails with `BB_TOKEN_KEY required` from `: "${BB_TOKEN_KEY:?...}"`
240
- if printf '%s' "$err" | grep -q "BB_TOKEN_KEY"; then
241
- ok "missing BB_TOKEN_KEY produces a diagnostic"
242
- else
243
- fail "no diagnostic on missing token (got: $err)"
244
- fi
245
-
246
- # --- Summary ----------------------------------------------------------------
247
- echo ""
248
- TOTAL=$((PASS+FAIL))
249
- if [ $FAIL -eq 0 ]; then
250
- echo "══ bitbucket-contract smoke: $PASS passed, 0 failed ══"
251
- exit 0
252
- else
253
- echo "══ bitbucket-contract smoke: $PASS passed, $FAIL failed (of $TOTAL) ══" >&2
254
- exit 1
255
- fi
@@ -1,47 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-changelog-version.sh - fail when CHANGELOG.md and package.json drift.
3
- #
4
- # Gates (release.yml relies on both holding):
5
- # 1. The newest "## [X.Y.Z] - YYYY-MM-DD" entry in CHANGELOG.md matches
6
- # package.json "version".
7
- # 2. The entry's date is ISO formatted.
8
- # 3. CHANGELOG-archive.md is NOT listed in package.json files[] (repo-only).
9
- set -euo pipefail
10
-
11
- ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
12
- PASS=0
13
- FAIL=0
14
-
15
- record_pass() { PASS=$((PASS + 1)); printf ' PASS %s\n' "$1"; }
16
- record_fail() { FAIL=$((FAIL + 1)); printf ' FAIL %s\n' "$1"; }
17
-
18
- printf 'smoke-changelog-version: CHANGELOG.md <-> package.json drift gate\n'
19
-
20
- PKG_VERSION=$(jq -r .version "$ROOT/package.json")
21
- TOP_ENTRY=$(grep -m1 -E '^## \[[0-9]+\.[0-9]+\.[0-9]+\]' "$ROOT/CHANGELOG.md" || true)
22
-
23
- if [ -z "$TOP_ENTRY" ]; then
24
- record_fail "CHANGELOG.md has no '## [X.Y.Z] - YYYY-MM-DD' entry"
25
- else
26
- record_pass "CHANGELOG.md has a parseable top entry"
27
- TOP_VERSION=$(printf '%s' "$TOP_ENTRY" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
28
- if [ "$TOP_VERSION" = "$PKG_VERSION" ]; then
29
- record_pass "top entry $TOP_VERSION matches package.json $PKG_VERSION"
30
- else
31
- record_fail "top entry $TOP_VERSION != package.json $PKG_VERSION"
32
- fi
33
- if printf '%s' "$TOP_ENTRY" | grep -qE '[0-9]{4}-[0-9]{2}-[0-9]{2}'; then
34
- record_pass "top entry date is ISO formatted"
35
- else
36
- record_fail "top entry date is not ISO formatted: $TOP_ENTRY"
37
- fi
38
- fi
39
-
40
- if jq -e '.files | index("CHANGELOG-archive.md")' "$ROOT/package.json" >/dev/null 2>&1; then
41
- record_fail "CHANGELOG-archive.md must stay repo-only (remove from files[])"
42
- else
43
- record_pass "CHANGELOG-archive.md not shipped in npm tarball"
44
- fi
45
-
46
- printf 'smoke-changelog-version: %d passed, %d failed\n' "$PASS" "$FAIL"
47
- [ "$FAIL" -eq 0 ]
@@ -1,60 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-channels-approval-gate.sh - contract for the channels Step 6 body preview + approval gate.
3
- #
4
- # Verifies:
5
- # 1. channels.md has the Step 6 gate section with the four decision options.
6
- # 2. The two (and only two) bypass cases are documented: autopilot + --dry-run.
7
- # 3. Step 7 dispatch is gated on the Step 6 approval.
8
- # 4. Byte-identical post rule + re-approval-on-regeneration rule present.
9
- # 5. Phase 7 Step 1.5 (GitHub issue comment) references the same gate.
10
- # 6. Required rules include the approval-before-post bullet.
11
-
12
- set -euo pipefail
13
-
14
- HERE="$(cd "$(dirname "$0")" && pwd)"
15
- ROOT="$(cd "$HERE/../.." && pwd)"
16
- CHANNELS="$ROOT/pipeline/commands/multi-agent/channels/SKILL.md"
17
- PHASE7="$ROOT/pipeline/multi-agent-refs/phases/phase-7-report.md"
18
-
19
- PASS=0
20
- FAIL=0
21
- pass() { PASS=$((PASS+1)); echo " ✓ $1"; }
22
- fail() { FAIL=$((FAIL+1)); echo " ✗ $1"; }
23
-
24
- for f in "$CHANNELS" "$PHASE7"; do
25
- [ -f "$f" ] || { echo "error: missing $f" >&2; exit 1; }
26
- done
27
-
28
- echo "→ 1. Step 6 gate section + decision options"
29
- grep -Fq "Step 6 - Body preview + approval gate" "$CHANNELS" && pass "gate section present" || fail "gate section missing"
30
- for opt in "Approve & post" "Edit" "Skip channels" "Cancel"; do
31
- grep -Fq "$opt" "$CHANNELS" && pass "option: $opt" || fail "option missing: $opt"
32
- done
33
-
34
- echo ""
35
- echo "→ 2. bypass cases are exactly autopilot + --dry-run"
36
- grep -Fq "Skipped in exactly two cases" "$CHANNELS" && pass "two-case rule stated" || fail "two-case rule missing"
37
- grep -Fq "MULTI_AGENT_AUTOPILOT=1" "$CHANNELS" && pass "autopilot bypass documented" || fail "autopilot bypass missing"
38
- grep -Eq 'dry-run.*(redundant|without posting)' "$CHANNELS" && pass "dry-run bypass documented" || fail "dry-run bypass missing"
39
-
40
- echo ""
41
- echo "→ 3. dispatch gated on approval"
42
- grep -Fq "NEVER starts before the Step 6 gate resolves" "$CHANNELS" && pass "Step 6 gated" || fail "Step 6 gate wiring missing"
43
-
44
- echo ""
45
- echo "→ 4. byte-identical + re-approval rules"
46
- grep -Fq "byte-identical to the approved preview" "$CHANNELS" && pass "byte-identical rule" || fail "byte-identical rule missing"
47
- grep -Fq "invalidates the approval" "$CHANNELS" && pass "re-approval on regeneration" || fail "re-approval rule missing"
48
-
49
- echo ""
50
- echo "→ 5. Phase 7 issue-comment path uses the same gate"
51
- grep -Fq "same preview + approval gate as channels Step 6" "$PHASE7" && pass "Phase 7 Step 1.5 gated" || fail "Phase 7 Step 1.5 gate reference missing"
52
- grep -Fq "Autopilot posts directly" "$PHASE7" && pass "Phase 7 autopilot bypass" || fail "Phase 7 autopilot bypass missing"
53
-
54
- echo ""
55
- echo "→ 6. required-rules bullet"
56
- grep -Fq "**Approval before post**" "$CHANNELS" && pass "required-rules bullet present" || fail "required-rules bullet missing"
57
-
58
- echo ""
59
- echo "══ channels-approval-gate smoke: $PASS passed, $FAIL failed ══"
60
- [ "$FAIL" -eq 0 ]
@@ -1,130 +0,0 @@
1
- #!/usr/bin/env bash
2
- # smoke-channels-flow.sh - asserts the v5.7+ /multi-agent:channels contract:
3
- # 1. channels.md exists (Claude) + multi-agent-channels SKILL.md exists (Copilot)
4
- # 2. enrich.md is GONE (Claude) + multi-agent-enrich skill is GONE (Copilot)
5
- # 3. channels.md declares the 4 channels (pr, jira, confluence, wiki)
6
- # 4. channels.md declares the 4 content sources (normalAnalysis, testScenarios, auto-diff, manual-note)
7
- # 5. Reviewer-preserving Bitbucket PUT payload is present (title+description+reviewers+fromRef+toRef+version)
8
- # 6. 30-min timeout contract referenced in channels.md + phase-7-report.md + modes.md
9
- # 7. Phase 7 autopilot always-pause rule documented in modes.md
10
- # 8. Phase 7 report delegates to channels (does NOT inline Jira/Confluence/Wiki logic)
11
- # 9. schema has reportChannels, reportContent, autopilotReportTimeoutSeconds, wikiScope
12
- # 10. legacy jiraCommentDefault/confluenceDefault/wikiDefault REMOVED from schema
13
- # 11. migrate-prefs.mjs has migrateReportChannels() sub-migration
14
- # 12. preferences-template.json uses new fields (not legacy)
15
- #
16
- # Fails loudly on any violation. Intended to run as part of the full smoke suite.
17
-
18
- set -uo pipefail
19
-
20
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
21
- CLAUDE_CMD="$ROOT/pipeline/commands/multi-agent/channels/SKILL.md"
22
- COPILOT_SKILL="$ROOT/pipeline/skills/shared/core/multi-agent-channels/SKILL.md"
23
- ENRICH_CMD="$ROOT/pipeline/commands/multi-agent/enrich/SKILL.md"
24
- ENRICH_SKILL_DIR="$ROOT/pipeline/skills/shared/core/multi-agent-enrich"
25
- PHASE7="$ROOT/pipeline/multi-agent-refs/phases/phase-7-report.md"
26
- MODES="$ROOT/pipeline/multi-agent-refs/phases/modes.md"
27
- WIKI_CAPTURE="$ROOT/pipeline/multi-agent-refs/wiki-capture.md"
28
- SCHEMA="$ROOT/pipeline/schemas/prefs.schema.json"
29
- MIGRATE="$ROOT/pipeline/scripts/migrate-prefs.mjs"
30
- TEMPLATE="$ROOT/pipeline/preferences-template.json"
31
-
32
- PASS=0
33
- FAIL=0
34
- pass() { PASS=$((PASS + 1)); echo " ✓ $1"; }
35
- fail() { FAIL=$((FAIL + 1)); echo " ✗ $1"; }
36
-
37
- check() {
38
- local label="$1" cmd="$2"
39
- if eval "$cmd" > /dev/null 2>&1; then pass "$label"; else fail "$label"; fi
40
- }
41
-
42
- echo "→ 1. channels command exists (both CLIs)"
43
- check "Claude channels.md present" "[ -f '$CLAUDE_CMD' ]"
44
- check "Copilot multi-agent-channels SKILL.md" "[ -f '$COPILOT_SKILL' ]"
45
-
46
- echo ""
47
- echo "→ 2. enrich command + skill REMOVED"
48
- check "Claude enrich.md absent" "[ ! -f '$ENRICH_CMD' ]"
49
- check "Copilot multi-agent-enrich dir absent" "[ ! -d '$ENRICH_SKILL_DIR' ]"
50
-
51
- echo ""
52
- echo "→ 3. channels.md declares 4 kanals"
53
- check "mentions PR description" "grep -Fq 'PR description' '$CLAUDE_CMD'"
54
- check "mentions Jira comment" "grep -Fq 'Jira comment' '$CLAUDE_CMD'"
55
- check "mentions Confluence page" "grep -Fq 'Confluence' '$CLAUDE_CMD'"
56
- check "mentions Wiki (component-only)" "grep -Fq 'Wiki' '$CLAUDE_CMD'"
57
-
58
- echo ""
59
- echo "→ 4. channels.md declares 5 content sources (v5.7.3+ adds teknik analiz)"
60
- check "Normal analiz content option" "grep -Fq 'Normal analiz' '$CLAUDE_CMD'"
61
- check "Teknik analiz content option" "grep -Fq 'Teknik analiz' '$CLAUDE_CMD'"
62
- check "Test senaryoları content option" "grep -Fq 'Test senaryoları' '$CLAUDE_CMD'"
63
- check "Auto-diff content option" "grep -Fq 'Auto-diff' '$CLAUDE_CMD'"
64
- check "Manuel not content option" "grep -Fq 'Manuel not' '$CLAUDE_CMD'"
65
-
66
- echo ""
67
- echo "→ 5. Reviewer-preserving Bitbucket PUT payload"
68
- check "mentions reviewers field mandatory" "grep -Fq 'reviewers' '$CLAUDE_CMD'"
69
- check "mentions fromRef field mandatory" "grep -Fq 'fromRef' '$CLAUDE_CMD'"
70
- check "mentions toRef field mandatory" "grep -Fq 'toRef' '$CLAUDE_CMD'"
71
- check "mentions version field mandatory" "grep -Fq 'version' '$CLAUDE_CMD'"
72
- check "jq --rawfile pattern (real newlines)" "grep -Eq 'jq --rawfile|jq -n' '$CLAUDE_CMD'"
73
-
74
- echo ""
75
- echo "→ 6. 30-min timeout contract"
76
- check "channels.md mentions 30-min timeout" "grep -Eq '30.min|30-min|30 min' '$CLAUDE_CMD'"
77
- check "phase-7-report.md mentions timeout" "grep -Eq '30.min|30-min|30 min|channelsTimeout' '$PHASE7'"
78
- check "modes.md mentions timeout" "grep -Eq '30.min|30-min|30 min|timeout' '$MODES'"
79
-
80
- echo ""
81
- echo "→ 7. Phase 7 autopilot always-pause rule"
82
- check "modes.md: Phase 7 autopilot exception" "grep -Fq 'Phase 7 autopilot exception' '$MODES'"
83
- check "modes.md: STILL PAUSES" "grep -Fq 'STILL PAUSES' '$MODES'"
84
- check "phase-7-report.md: always pauses" "grep -Eq 'ALWAYS pauses|always pauses' '$PHASE7'"
85
-
86
- echo ""
87
- echo "→ 8. Phase 7 delegates to channels (no inline adapters)"
88
- check "phase-7-report.md invokes channels" "grep -Eq 'multi-agent:channels|multi-agent-channels' '$PHASE7'"
89
- check "phase-7-report.md has state bundle" "grep -Fq 'state bundle' '$PHASE7'"
90
- # Old inline per-channel sub-step list (Jira-Comment/Wiki+Figma/Confluence) should be gone
91
- if grep -Fq 'Jira-Comment' "$PHASE7" && grep -Fq 'Wiki+Figma' "$PHASE7" && grep -Fq 'Confluence' "$PHASE7"; then
92
- # All three together = old 5-sub-step inline layout
93
- fail "phase-7-report.md still has old inline 5-sub-step layout (Jira-Comment/Wiki+Figma/Confluence all three)"
94
- else
95
- pass "phase-7-report.md no longer inlines old 5-sub-step layout"
96
- fi
97
-
98
- echo ""
99
- echo "→ 9. schema has new v5.7+ fields"
100
- check "schema has reportChannels" "grep -Fq 'reportChannels' '$SCHEMA'"
101
- check "schema has reportContent" "grep -Fq 'reportContent' '$SCHEMA'"
102
- check "schema has autopilotReportTimeoutSeconds" "grep -Fq 'autopilotReportTimeoutSeconds' '$SCHEMA'"
103
- check "schema has wikiScope" "grep -Fq 'wikiScope' '$SCHEMA'"
104
-
105
- echo ""
106
- echo "→ 10. schema PURGED of legacy fields"
107
- check "schema has NO jiraCommentDefault property" "! grep -Eq '\"jiraCommentDefault\"\\s*:' '$SCHEMA'"
108
- check "schema has NO confluenceDefault property" "! grep -Eq '\"confluenceDefault\"\\s*:' '$SCHEMA'"
109
- check "schema has NO wikiDefault property" "! grep -Eq '\"wikiDefault\"\\s*:' '$SCHEMA'"
110
-
111
- echo ""
112
- echo "→ 11. migrate-prefs.mjs handles v5.7 migration"
113
- check "migrate-prefs has migrateReportChannels()" "grep -Fq 'migrateReportChannels' '$MIGRATE'"
114
- check "migrate-prefs prunes jiraCommentDefault" "grep -Fq 'jiraCommentDefault' '$MIGRATE'"
115
- check "migrate-prefs prunes confluenceDefault" "grep -Fq 'confluenceDefault' '$MIGRATE'"
116
- check "migrate-prefs prunes wikiDefault" "grep -Fq 'wikiDefault' '$MIGRATE'"
117
-
118
- echo ""
119
- echo "→ 12. template uses new fields (not legacy)"
120
- check "template has reportChannels" "grep -Fq 'reportChannels' '$TEMPLATE'"
121
- check "template has reportContent" "grep -Fq 'reportContent' '$TEMPLATE'"
122
- check "template has wikiScope" "grep -Fq 'wikiScope' '$TEMPLATE'"
123
- check "template NO jiraCommentDefault" "! grep -Eq '\"jiraCommentDefault\"\\s*:' '$TEMPLATE'"
124
- check "template NO confluenceDefault" "! grep -Eq '\"confluenceDefault\"\\s*:' '$TEMPLATE'"
125
- check "template NO wikiDefault" "! grep -Eq '\"wikiDefault\"\\s*:' '$TEMPLATE'"
126
-
127
- echo ""
128
- echo "══ channels-flow smoke: $PASS passed, $FAIL failed ══"
129
- if [ "$FAIL" -gt 0 ]; then exit 1; fi
130
- exit 0
@@ -1,88 +0,0 @@
1
- #!/usr/bin/env bash
2
- #
3
- # smoke-ci-workflows.sh - structural validator for `.github/workflows/*.yml`.
4
- #
5
- # We don't have `act` (or PyYAML) as a hard dependency, and we don't run
6
- # workflows on GitHub during this smoke (billing-friendly stance). This
7
- # smoke catches the obvious classes of breakage:
8
- #
9
- # - Missing `on:` block / no triggers
10
- # - Missing `jobs:` block
11
- # - At least one `steps:` block per job
12
- # - workflow_dispatch trigger present (project policy: every workflow
13
- # must be runnable on demand while billing is paused)
14
- # - Each `uses:` references a pinned major version (no @main / @master)
15
- # - No `--token=` argv pattern in shell steps (Vercel leak shape)
16
- #
17
- # The full job semantics (Docker image resolution, secret resolution,
18
- # matrix expansion) are NOT checked - install `act` and run
19
- # `act -W .github/workflows/<file> --list` for that.
20
- #
21
- # Exit codes: 0=pass, 1=structural break
22
-
23
- set -euo pipefail
24
-
25
- REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
26
- WF_DIR="$REPO_ROOT/.github/workflows"
27
-
28
- [ -d "$WF_DIR" ] || { echo "FAIL: .github/workflows/ missing"; exit 2; }
29
-
30
- PASS=0
31
- FAIL=0
32
- pass() { echo " ✓ $*"; PASS=$((PASS + 1)); }
33
- fail() { echo " ✗ $*"; FAIL=$((FAIL + 1)); }
34
-
35
- WORKFLOWS=$(find "$WF_DIR" -maxdepth 1 -type f \( -name "*.yml" -o -name "*.yaml" \) | sort)
36
- [ -n "$WORKFLOWS" ] || { echo "FAIL: no workflows in $WF_DIR"; exit 1; }
37
-
38
- for wf in $WORKFLOWS; do
39
- name=$(basename "$wf")
40
- echo ""
41
- echo "→ $name"
42
-
43
- if grep -Eq '^on:' "$wf"; then
44
- pass "$name has on: trigger block"
45
- else
46
- fail "$name missing 'on:' block"
47
- fi
48
-
49
- if grep -Eq '^jobs:' "$wf"; then
50
- pass "$name declares jobs:"
51
- else
52
- fail "$name missing 'jobs:' block"
53
- fi
54
-
55
- if grep -Eq '^[[:space:]]+steps:' "$wf"; then
56
- pass "$name has at least one steps: block"
57
- else
58
- fail "$name has no steps: block"
59
- fi
60
-
61
- if grep -q 'workflow_dispatch' "$wf"; then
62
- pass "$name supports workflow_dispatch (manual run)"
63
- else
64
- fail "$name missing workflow_dispatch - won't be runnable while billing is paused"
65
- fi
66
-
67
- # Pin check: `uses: foo/bar@vN` good; `uses: foo/bar@main` bad
68
- if grep -E '^[[:space:]]+- uses: [^@]+@(main|master)[^[:alnum:]]?' "$wf" >/dev/null 2>&1; then
69
- fail "$name has uses: pinned to a moving branch (main/master) - pin to a version"
70
- else
71
- pass "$name uses: lines are not pinned to main/master"
72
- fi
73
-
74
- # Vercel leak shape: `--token=` or `--token ` in a `run:` block
75
- if grep -E "vercel.*--token[ =]" "$wf" >/dev/null 2>&1; then
76
- fail "$name contains 'vercel --token=...' - must use VERCEL_TOKEN env + wrapper instead"
77
- else
78
- pass "$name does not pass --token= to vercel"
79
- fi
80
- done
81
-
82
- echo ""
83
- echo "→ workflow inventory"
84
- echo "$WORKFLOWS" | sed 's|.*/| - |'
85
-
86
- echo ""
87
- echo "══ smoke-ci-workflows: $PASS passed, $FAIL failed ══"
88
- [ "$FAIL" -gt 0 ] && exit 1 || exit 0