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