@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.
- package/CHANGELOG.md +126 -0
- package/install/_common.mjs +48 -0
- package/install/_dev-only-files.mjs +125 -5
- package/install/claude.mjs +14 -8
- package/install/copilot.mjs +5 -8
- package/package.json +17 -2
- package/pipeline/commands/multi-agent/analysis/SKILL.md +1 -1
- package/pipeline/lib/credential-store.sh +20 -0
- package/pipeline/multi-agent-refs/_account-picker.md +1 -1
- package/pipeline/multi-agent-refs/_dev-context.md +1 -1
- package/pipeline/multi-agent-refs/_repo-picker.md +1 -1
- package/pipeline/multi-agent-refs/phases/operations.md +28 -0
- package/pipeline/multi-agent-refs/phases/phase-0-init.md +1 -0
- package/pipeline/multi-agent-refs/phases/phase-2-planning.md +1 -1
- package/pipeline/multi-agent-refs/phases/phase-3-dev.md +1 -2
- package/pipeline/multi-agent-refs/phases/phase-4-review.md +49 -4
- package/pipeline/schemas/prefs.schema.json +6 -0
- package/pipeline/scripts/_smoke-root.sh +61 -0
- package/pipeline/scripts/audit-log.sh +25 -0
- package/pipeline/scripts/smoke-cross-cli-behavior.sh +21 -7
- package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-1-analysis.json +0 -25
- package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-2-plan.json +0 -30
- package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-4-review.json +0 -20
- package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/expected/phase-4-triage.json +0 -15
- package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/metadata.json +0 -14
- package/pipeline/eval/golden-tasks/01-ios-bugfix-darkmode/task.json +0 -12
- package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-1-analysis.json +0 -29
- package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-2-plan.json +0 -43
- package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-4-review.json +0 -35
- package/pipeline/eval/golden-tasks/02-android-feature-compose/expected/phase-4-triage.json +0 -35
- package/pipeline/eval/golden-tasks/02-android-feature-compose/metadata.json +0 -14
- package/pipeline/eval/golden-tasks/02-android-feature-compose/task.json +0 -12
- package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-1-analysis.json +0 -29
- package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-2-plan.json +0 -42
- package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-4-review.json +0 -20
- package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/expected/phase-4-triage.json +0 -15
- package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/metadata.json +0 -14
- package/pipeline/eval/golden-tasks/03-backend-python-ratelimit/task.json +0 -12
- package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-1-analysis.json +0 -29
- package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-2-plan.json +0 -40
- package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-4-review.json +0 -20
- package/pipeline/eval/golden-tasks/04-frontend-next-hydration/expected/phase-4-triage.json +0 -15
- package/pipeline/eval/golden-tasks/04-frontend-next-hydration/metadata.json +0 -14
- package/pipeline/eval/golden-tasks/04-frontend-next-hydration/task.json +0 -12
- package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-1-analysis.json +0 -29
- package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-2-plan.json +0 -42
- package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-4-review.json +0 -28
- package/pipeline/eval/golden-tasks/05-ios-security-keychain/expected/phase-4-triage.json +0 -27
- package/pipeline/eval/golden-tasks/05-ios-security-keychain/metadata.json +0 -14
- package/pipeline/eval/golden-tasks/05-ios-security-keychain/task.json +0 -12
- package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-1-analysis.json +0 -29
- package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-2-plan.json +0 -41
- package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-4-review.json +0 -12
- package/pipeline/eval/golden-tasks/06-android-refactor-usecase/expected/phase-4-triage.json +0 -6
- package/pipeline/eval/golden-tasks/06-android-refactor-usecase/metadata.json +0 -14
- package/pipeline/eval/golden-tasks/06-android-refactor-usecase/task.json +0 -12
- package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-1-analysis.json +0 -29
- package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-2-plan.json +0 -42
- package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-4-review.json +0 -28
- package/pipeline/eval/golden-tasks/07-backend-node-idempotency/expected/phase-4-triage.json +0 -27
- package/pipeline/eval/golden-tasks/07-backend-node-idempotency/metadata.json +0 -14
- package/pipeline/eval/golden-tasks/07-backend-node-idempotency/task.json +0 -12
- package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-1-analysis.json +0 -25
- package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-2-plan.json +0 -31
- package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-4-review.json +0 -12
- package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/expected/phase-4-triage.json +0 -18
- package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/metadata.json +0 -14
- package/pipeline/eval/golden-tasks/08-ios-auth-consensus-unverified/task.json +0 -12
- package/pipeline/eval/golden-tasks/README.md +0 -65
- package/pipeline/eval/intent-cases.json +0 -40
- package/pipeline/eval/run-metrics-fixture.json +0 -93
- package/pipeline/eval/triage/01-empty-findings/expected.json +0 -6
- package/pipeline/eval/triage/01-empty-findings/input.json +0 -5
- package/pipeline/eval/triage/01-empty-findings/notes.md +0 -7
- package/pipeline/eval/triage/02-real-blocker/expected.json +0 -15
- package/pipeline/eval/triage/02-real-blocker/input.json +0 -14
- package/pipeline/eval/triage/02-real-blocker/notes.md +0 -7
- package/pipeline/eval/triage/03-out-of-scope-defer/expected.json +0 -18
- package/pipeline/eval/triage/03-out-of-scope-defer/input.json +0 -14
- package/pipeline/eval/triage/03-out-of-scope-defer/notes.md +0 -10
- package/pipeline/eval/triage/04-false-positive-reject/expected.json +0 -18
- package/pipeline/eval/triage/04-false-positive-reject/input.json +0 -14
- package/pipeline/eval/triage/04-false-positive-reject/notes.md +0 -10
- package/pipeline/eval/triage/05-mixed-classification/expected.json +0 -43
- package/pipeline/eval/triage/05-mixed-classification/input.json +0 -38
- package/pipeline/eval/triage/05-mixed-classification/notes.md +0 -17
- package/pipeline/eval/triage/06-severity-mismatch/expected.json +0 -15
- package/pipeline/eval/triage/06-severity-mismatch/input.json +0 -14
- package/pipeline/eval/triage/06-severity-mismatch/notes.md +0 -9
- package/pipeline/eval/triage/07-duplicate-reviewers/expected.json +0 -27
- package/pipeline/eval/triage/07-duplicate-reviewers/input.json +0 -22
- package/pipeline/eval/triage/07-duplicate-reviewers/notes.md +0 -9
- package/pipeline/eval/triage/08-style-misclassified/expected.json +0 -18
- package/pipeline/eval/triage/08-style-misclassified/input.json +0 -14
- package/pipeline/eval/triage/08-style-misclassified/notes.md +0 -9
- package/pipeline/eval/triage/09-cascading-finding/expected.json +0 -23
- package/pipeline/eval/triage/09-cascading-finding/input.json +0 -22
- package/pipeline/eval/triage/09-cascading-finding/notes.md +0 -9
- package/pipeline/eval/triage/10-deferred-crossref/expected.json +0 -18
- package/pipeline/eval/triage/10-deferred-crossref/input.json +0 -14
- package/pipeline/eval/triage/10-deferred-crossref/notes.md +0 -9
- package/pipeline/eval/triage/11-vercel-token-leak-blocker/expected.json +0 -27
- package/pipeline/eval/triage/11-vercel-token-leak-blocker/input.json +0 -22
- package/pipeline/eval/triage/11-vercel-token-leak-blocker/notes.md +0 -14
- package/pipeline/eval/triage/README.md +0 -54
- package/pipeline/scripts/benchmark-phase-0.sh +0 -128
- package/pipeline/scripts/check-md-links.mjs +0 -88
- package/pipeline/scripts/eval-golden-tasks-live.mjs +0 -302
- package/pipeline/scripts/eval-golden-tasks.mjs +0 -224
- package/pipeline/scripts/eval-intent.mjs +0 -107
- package/pipeline/scripts/eval-mine-corpus.mjs +0 -211
- package/pipeline/scripts/eval-triage.mjs +0 -171
- package/pipeline/scripts/fixtures/diff-risk-android.diff +0 -40
- package/pipeline/scripts/fixtures/diff-risk-ios.diff +0 -48
- package/pipeline/scripts/fixtures/diff-risk-test-removal.diff +0 -40
- package/pipeline/scripts/fixtures/install-layout.tsv +0 -19
- package/pipeline/scripts/fixtures/pack-expected-count.txt +0 -1
- package/pipeline/scripts/fixtures/test-gap-node.diff +0 -30
- package/pipeline/scripts/fixtures/test-gap-python.diff +0 -32
- package/pipeline/scripts/lint-mcp-refs.mjs +0 -218
- package/pipeline/scripts/lint-skills.mjs +0 -154
- package/pipeline/scripts/run-smokes.mjs +0 -130
- package/pipeline/scripts/scorecard.mjs +0 -258
- package/pipeline/scripts/smoke-add-detail.sh +0 -137
- package/pipeline/scripts/smoke-agent-guard.sh +0 -74
- package/pipeline/scripts/smoke-agent-log-cost.sh +0 -262
- package/pipeline/scripts/smoke-agent-model-routing.sh +0 -87
- package/pipeline/scripts/smoke-ask-choice.sh +0 -42
- package/pipeline/scripts/smoke-autopilot-circuit-breaker.sh +0 -36
- package/pipeline/scripts/smoke-bitbucket-contract.sh +0 -255
- package/pipeline/scripts/smoke-changelog-version.sh +0 -47
- package/pipeline/scripts/smoke-channels-approval-gate.sh +0 -60
- package/pipeline/scripts/smoke-channels-flow.sh +0 -130
- package/pipeline/scripts/smoke-ci-workflows.sh +0 -88
- package/pipeline/scripts/smoke-clarify.sh +0 -148
- package/pipeline/scripts/smoke-command-inventory.sh +0 -81
- package/pipeline/scripts/smoke-commands-skills-parity.sh +0 -87
- package/pipeline/scripts/smoke-community-gates.sh +0 -75
- package/pipeline/scripts/smoke-compliance-skills.sh +0 -119
- package/pipeline/scripts/smoke-config-hygiene.sh +0 -58
- package/pipeline/scripts/smoke-context-budget.sh +0 -72
- package/pipeline/scripts/smoke-cost-budget.sh +0 -70
- package/pipeline/scripts/smoke-cost-summary.sh +0 -139
- package/pipeline/scripts/smoke-cross-phase-cohesion.sh +0 -128
- package/pipeline/scripts/smoke-description-tr.sh +0 -82
- package/pipeline/scripts/smoke-dev-critic.sh +0 -144
- package/pipeline/scripts/smoke-diff-explain.sh +0 -147
- package/pipeline/scripts/smoke-diff-risk.sh +0 -190
- package/pipeline/scripts/smoke-dynamic-skill-loading.sh +0 -160
- package/pipeline/scripts/smoke-eval-live.sh +0 -136
- package/pipeline/scripts/smoke-evidence-gate.sh +0 -93
- package/pipeline/scripts/smoke-extract-conventions.sh +0 -163
- package/pipeline/scripts/smoke-fetchers-offline.sh +0 -448
- package/pipeline/scripts/smoke-figma-dispatch.sh +0 -112
- package/pipeline/scripts/smoke-gate-hooks.sh +0 -74
- package/pipeline/scripts/smoke-gc-tmp.sh +0 -130
- package/pipeline/scripts/smoke-gc-worktrees.sh +0 -125
- package/pipeline/scripts/smoke-generate-issue.sh +0 -120
- package/pipeline/scripts/smoke-handoff-contract.sh +0 -92
- package/pipeline/scripts/smoke-identity-isolation.sh +0 -70
- package/pipeline/scripts/smoke-install-layout.sh +0 -248
- package/pipeline/scripts/smoke-intent-guard.sh +0 -86
- package/pipeline/scripts/smoke-issue-comment-template.sh +0 -86
- package/pipeline/scripts/smoke-issue-jira-triad.sh +0 -120
- package/pipeline/scripts/smoke-keychain.sh +0 -158
- package/pipeline/scripts/smoke-language-axis.sh +0 -109
- package/pipeline/scripts/smoke-learning-curve.sh +0 -61
- package/pipeline/scripts/smoke-learnings-ledger.sh +0 -86
- package/pipeline/scripts/smoke-lib-scripts.sh +0 -448
- package/pipeline/scripts/smoke-mcp-gate.sh +0 -68
- package/pipeline/scripts/smoke-md-links.sh +0 -8
- package/pipeline/scripts/smoke-md2confluence.sh +0 -126
- package/pipeline/scripts/smoke-metrics-cache-ratio.sh +0 -72
- package/pipeline/scripts/smoke-migrate-state.sh +0 -102
- package/pipeline/scripts/smoke-mode-dispatch-drift.sh +0 -161
- package/pipeline/scripts/smoke-model-fallback.sh +0 -89
- package/pipeline/scripts/smoke-multi-repo-integration.sh +0 -116
- package/pipeline/scripts/smoke-multi-repo-worktree.sh +0 -61
- package/pipeline/scripts/smoke-no-mcp-in-dev-phases.sh +0 -194
- package/pipeline/scripts/smoke-no-token-prompt.sh +0 -85
- package/pipeline/scripts/smoke-own-punctuation.sh +0 -103
- package/pipeline/scripts/smoke-pack-contents.sh +0 -140
- package/pipeline/scripts/smoke-pat-audit.sh +0 -128
- package/pipeline/scripts/smoke-per-repo-memory.sh +0 -156
- package/pipeline/scripts/smoke-phase-0-multi-repo.sh +0 -170
- package/pipeline/scripts/smoke-phase-6-multi.sh +0 -79
- package/pipeline/scripts/smoke-phase-banner.sh +0 -101
- package/pipeline/scripts/smoke-phase-tracker.sh +0 -324
- package/pipeline/scripts/smoke-phase0-bridge-contract.sh +0 -241
- package/pipeline/scripts/smoke-phase4-gates.sh +0 -45
- package/pipeline/scripts/smoke-phase4-triage.sh +0 -229
- package/pipeline/scripts/smoke-plan-approval-gate.sh +0 -71
- package/pipeline/scripts/smoke-plan-safety.sh +0 -139
- package/pipeline/scripts/smoke-plan-todos.sh +0 -196
- package/pipeline/scripts/smoke-pr-review-actions.sh +0 -152
- package/pipeline/scripts/smoke-pre-commit.sh +0 -170
- package/pipeline/scripts/smoke-pref-migration.sh +0 -226
- package/pipeline/scripts/smoke-prefs-language.sh +0 -134
- package/pipeline/scripts/smoke-progress-contract.sh +0 -127
- package/pipeline/scripts/smoke-prune-logs.sh +0 -137
- package/pipeline/scripts/smoke-purge.sh +0 -138
- package/pipeline/scripts/smoke-push-retry.sh +0 -75
- package/pipeline/scripts/smoke-repo-map.sh +0 -300
- package/pipeline/scripts/smoke-review-readiness.sh +0 -92
- package/pipeline/scripts/smoke-review-watch.sh +0 -146
- package/pipeline/scripts/smoke-routines.sh +0 -84
- package/pipeline/scripts/smoke-run-aggregator.sh +0 -216
- package/pipeline/scripts/smoke-run-metrics.sh +0 -50
- package/pipeline/scripts/smoke-search.sh +0 -187
- package/pipeline/scripts/smoke-shadow-git.sh +0 -224
- package/pipeline/scripts/smoke-skill-authoring.sh +0 -137
- package/pipeline/scripts/smoke-skill-language.sh +0 -83
- package/pipeline/scripts/smoke-skill-manifest.sh +0 -138
- package/pipeline/scripts/smoke-skill-scan.sh +0 -198
- package/pipeline/scripts/smoke-source-parity.sh +0 -85
- package/pipeline/scripts/smoke-subagent-validators.sh +0 -108
- package/pipeline/scripts/smoke-sync-parity.sh +0 -92
- package/pipeline/scripts/smoke-tasklist-ordering.sh +0 -112
- package/pipeline/scripts/smoke-telemetry.sh +0 -147
- package/pipeline/scripts/smoke-test-gap.sh +0 -183
- package/pipeline/scripts/smoke-token-budget.sh +0 -67
- package/pipeline/scripts/smoke-token-preflight.sh +0 -82
- package/pipeline/scripts/smoke-tracker-contract.sh +0 -191
- package/pipeline/scripts/smoke-tracker-tokens-invocation.sh +0 -73
- package/pipeline/scripts/smoke-triage-memory.sh +0 -174
- package/pipeline/scripts/smoke-update-check.sh +0 -135
- package/pipeline/scripts/smoke-url-enrichment.sh +0 -70
- package/pipeline/scripts/smoke-validate-analysis-doc.sh +0 -161
- package/pipeline/scripts/smoke-validator-contradiction.sh +0 -67
- package/pipeline/scripts/smoke-validator-gates.sh +0 -164
- package/pipeline/scripts/smoke-vercel-deploy-redact.sh +0 -129
- package/pipeline/scripts/smoke-verify-by-test.sh +0 -148
- package/pipeline/scripts/smoke-wiki-integration.sh +0 -122
- package/pipeline/scripts/smoke-work-summary.sh +0 -163
- package/pipeline/scripts/smoke-workflow-audit.sh +0 -101
- package/pipeline/scripts/smoke-worktree-path-convention.sh +0 -86
- package/pipeline/scripts/smoke-wrapper-preservation.sh +0 -68
- package/pipeline/scripts/smoke-write-state.sh +0 -159
- package/pipeline/scripts/sync-parity-check.sh +0 -135
- package/pipeline/scripts/test-gap-rules/android.json +0 -25
- package/pipeline/scripts/test-gap-rules/ios.json +0 -34
- package/pipeline/scripts/test-gap-rules/node.json +0 -29
- package/pipeline/scripts/test-gap-rules/python.json +0 -25
- 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
|