@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,262 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# smoke-agent-log-cost.sh - v8.3.0
|
|
3
|
-
#
|
|
4
|
-
# Verifies the agent-log Cost Breakdown pipeline:
|
|
5
|
-
# 1. render-agent-log-cost.sh exits 2 when no tracker data available
|
|
6
|
-
# 2. Renders 4-column markdown (Phase | Model | Tokens in | Tokens out | Est. USD)
|
|
7
|
-
# from a hand-built object-shaped phase-tracker.json
|
|
8
|
-
# 3. Renders identical block from the array-shaped phase-tracker.json that
|
|
9
|
-
# phase-tracker.sh actually writes
|
|
10
|
-
# 4. Unknown model degrades to " - " with footnote, never blocks
|
|
11
|
-
# 5. log-metric.sh forwards tokens + model to tracker when LOG_METRIC_FORWARD_TO_TRACKER=1
|
|
12
|
-
# 6. log-format.md ref doc declares the Tokens column + Cost Breakdown section
|
|
13
|
-
#
|
|
14
|
-
# Exit 0 = all pass, 1 = any failure.
|
|
15
|
-
|
|
16
|
-
set -euo pipefail
|
|
17
|
-
|
|
18
|
-
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
19
|
-
RENDERER="$ROOT/pipeline/scripts/render-agent-log-cost.sh"
|
|
20
|
-
TRACKER="$ROOT/pipeline/scripts/phase-tracker.sh"
|
|
21
|
-
LOG_METRIC="$ROOT/pipeline/scripts/log-metric.sh"
|
|
22
|
-
TABLE="$ROOT/pipeline/scripts/cost-table.json"
|
|
23
|
-
LOG_FORMAT_DOC="$ROOT/pipeline/multi-agent-refs/phases/log-format.md"
|
|
24
|
-
|
|
25
|
-
pass=0
|
|
26
|
-
fail=0
|
|
27
|
-
failures=()
|
|
28
|
-
record_pass() { pass=$((pass + 1)); printf ' \033[0;32mPASS\033[0m %s\n' "$1"; }
|
|
29
|
-
record_fail() { fail=$((fail + 1)); failures+=("$1"); printf ' \033[0;31mFAIL\033[0m %s\n' "$1"; }
|
|
30
|
-
|
|
31
|
-
printf '→ smoke-agent-log-cost (v8.3.0): agent-log Cost Breakdown contract\n'
|
|
32
|
-
|
|
33
|
-
[ -x "$RENDERER" ] || { record_fail "renderer not executable: $RENDERER"; exit 1; }
|
|
34
|
-
|
|
35
|
-
# --- 1: missing-data path returns exit 2 ---
|
|
36
|
-
tmp=$(mktemp -d)
|
|
37
|
-
pushd "$tmp" >/dev/null
|
|
38
|
-
set +e
|
|
39
|
-
bash "$RENDERER" GHOST-1 >/dev/null 2>&1
|
|
40
|
-
rc=$?
|
|
41
|
-
set -e
|
|
42
|
-
if [ "$rc" -eq 2 ]; then
|
|
43
|
-
record_pass "renderer exits 2 when no tracker data"
|
|
44
|
-
else
|
|
45
|
-
record_fail "renderer should exit 2 with no data (got $rc)"
|
|
46
|
-
fi
|
|
47
|
-
popd >/dev/null
|
|
48
|
-
rm -rf "$tmp"
|
|
49
|
-
|
|
50
|
-
# --- 2: object-shaped fixture renders 4-column markdown ---
|
|
51
|
-
tmp=$(mktemp -d)
|
|
52
|
-
pushd "$tmp" >/dev/null
|
|
53
|
-
mkdir -p .worktrees/DEMO-1
|
|
54
|
-
cat > .worktrees/DEMO-1/phase-tracker.json <<'JSON'
|
|
55
|
-
{"taskId":"DEMO-1","phases":{
|
|
56
|
-
"1":{"name":"1. Analysis","model":"opus","tokens_in":12480,"tokens_out":3210},
|
|
57
|
-
"3":{"name":"3. Dev","model":"sonnet","tokens_in":42310,"tokens_out":9880},
|
|
58
|
-
"4":{"name":"4. Review","model":"opus","tokens_in":8200,"tokens_out":1500}
|
|
59
|
-
}}
|
|
60
|
-
JSON
|
|
61
|
-
out=$(bash "$RENDERER" DEMO-1 2>/dev/null)
|
|
62
|
-
if grep -qE '^\| Phase \| Model \| Tokens in \| Tokens out \| Est\. USD \|' <<< "$out"; then
|
|
63
|
-
record_pass "object-shape: header row rendered"
|
|
64
|
-
else
|
|
65
|
-
record_fail "object-shape: header row missing"
|
|
66
|
-
fi
|
|
67
|
-
if grep -q '## Cost Breakdown' <<< "$out"; then
|
|
68
|
-
record_pass "object-shape: Cost Breakdown section heading present"
|
|
69
|
-
else
|
|
70
|
-
record_fail "object-shape: section heading missing"
|
|
71
|
-
fi
|
|
72
|
-
if grep -qE '\| 1\. Analysis \| opus \| 12,480 \| 3,210 \| \$' <<< "$out"; then
|
|
73
|
-
record_pass "object-shape: Phase 1 row formatted with comma-grouped tokens + USD"
|
|
74
|
-
else
|
|
75
|
-
record_fail "object-shape: Phase 1 row formatting wrong"
|
|
76
|
-
printf '%s\n' "$out" | head -10 >&2
|
|
77
|
-
fi
|
|
78
|
-
if grep -qE '\| \*\*Total\*\* .* \| \*\*\$' <<< "$out"; then
|
|
79
|
-
record_pass "object-shape: Total row rendered"
|
|
80
|
-
else
|
|
81
|
-
record_fail "object-shape: Total row missing"
|
|
82
|
-
fi
|
|
83
|
-
popd >/dev/null
|
|
84
|
-
rm -rf "$tmp"
|
|
85
|
-
|
|
86
|
-
# --- 3: array-shaped fixture (the shape phase-tracker.sh actually writes) ---
|
|
87
|
-
tmp=$(mktemp -d)
|
|
88
|
-
pushd "$tmp" >/dev/null
|
|
89
|
-
mkdir -p .worktrees/PROJ-2
|
|
90
|
-
cat > .worktrees/PROJ-2/phase-tracker.json <<'JSON'
|
|
91
|
-
{"task_id":"PROJ-2","started_at":"2026-05-05T10:00:00Z","phases":[
|
|
92
|
-
{"id":"1","name":"Analysis","status":"completed","model":"opus","tokens_in":10000,"tokens_out":2000,"subs":[]},
|
|
93
|
-
{"id":"3","name":"Dev","status":"completed","model":"sonnet","tokens_in":50000,"tokens_out":8000,"subs":[]}
|
|
94
|
-
]}
|
|
95
|
-
JSON
|
|
96
|
-
out=$(bash "$RENDERER" PROJ-2 2>/dev/null)
|
|
97
|
-
if grep -qE '\| Analysis \| opus \| 10,000 \| 2,000 \| \$' <<< "$out"; then
|
|
98
|
-
record_pass "array-shape: Phase 1 row rendered correctly"
|
|
99
|
-
else
|
|
100
|
-
record_fail "array-shape: Phase 1 row wrong"
|
|
101
|
-
printf '%s\n' "$out" | head -10 >&2
|
|
102
|
-
fi
|
|
103
|
-
if grep -qE '\| Dev \| sonnet \| 50,000 \| 8,000 \| \$' <<< "$out"; then
|
|
104
|
-
record_pass "array-shape: Phase 3 row rendered correctly"
|
|
105
|
-
else
|
|
106
|
-
record_fail "array-shape: Phase 3 row wrong"
|
|
107
|
-
fi
|
|
108
|
-
popd >/dev/null
|
|
109
|
-
rm -rf "$tmp"
|
|
110
|
-
|
|
111
|
-
# --- 4: unknown model degrades gracefully ---
|
|
112
|
-
tmp=$(mktemp -d)
|
|
113
|
-
pushd "$tmp" >/dev/null
|
|
114
|
-
mkdir -p .worktrees/UNK-1
|
|
115
|
-
cat > .worktrees/UNK-1/phase-tracker.json <<'JSON'
|
|
116
|
-
{"task_id":"UNK-1","phases":[
|
|
117
|
-
{"id":"3","name":"Dev","model":"made-up-9000","tokens_in":1000,"tokens_out":200,"subs":[]}
|
|
118
|
-
]}
|
|
119
|
-
JSON
|
|
120
|
-
out=$(bash "$RENDERER" UNK-1 2>/dev/null)
|
|
121
|
-
if grep -qF '| made-up-9000 |' <<< "$out" && grep -qF '| - |' <<< "$out"; then
|
|
122
|
-
record_pass "unknown model row renders with USD as - "
|
|
123
|
-
else
|
|
124
|
-
record_fail "unknown model handling broken"
|
|
125
|
-
fi
|
|
126
|
-
if grep -q 'cost-table.json' <<< "$out"; then
|
|
127
|
-
record_pass "unknown model footnote points to cost-table.json"
|
|
128
|
-
else
|
|
129
|
-
record_fail "unknown model footnote missing"
|
|
130
|
-
fi
|
|
131
|
-
popd >/dev/null
|
|
132
|
-
rm -rf "$tmp"
|
|
133
|
-
|
|
134
|
-
# --- 5: log-metric forwarder writes to phase-tracker ---
|
|
135
|
-
tmp=$(mktemp -d)
|
|
136
|
-
export METRICS_FILE="$tmp/metrics.jsonl"
|
|
137
|
-
export TRACKER_FILE="$tmp/tracker.json"
|
|
138
|
-
# Bootstrap tracker with one phase
|
|
139
|
-
bash "$TRACKER" init "FWD-1" >/dev/null 2>&1 || true
|
|
140
|
-
# init writes to $HOME/.claude/logs/multi-agent/FWD-1/tracker-state.json - override via TRACKER_FILE
|
|
141
|
-
cat > "$TRACKER_FILE" <<'JSON'
|
|
142
|
-
{"task_id":"FWD-1","started_at":"2026-05-05T00:00:00Z","phases":[
|
|
143
|
-
{"id":"4","name":"Review","status":"in_progress","subs":[]}
|
|
144
|
-
]}
|
|
145
|
-
JSON
|
|
146
|
-
LOG_METRIC_FORWARD_TO_TRACKER=1 TRACKER_QUIET=1 \
|
|
147
|
-
bash "$LOG_METRIC" FWD-1 4 review.reviewer_call \
|
|
148
|
-
model=opus tokens_in=1234 tokens_out=567 tokens_cached=400 duration_ms=1000 >/dev/null 2>&1 || true
|
|
149
|
-
if jq -e '.phases[0].tokens_in == 1234 and .phases[0].tokens_out == 567 and .phases[0].model == "opus"' "$TRACKER_FILE" >/dev/null 2>&1; then
|
|
150
|
-
record_pass "log-metric forwards tokens + model to tracker"
|
|
151
|
-
else
|
|
152
|
-
record_fail "log-metric forwarder did not update tracker"
|
|
153
|
-
cat "$TRACKER_FILE" >&2
|
|
154
|
-
fi
|
|
155
|
-
# End-to-end: tokens_cached must flow log-metric -> phase-tracker -> tracker state
|
|
156
|
-
if jq -e '.phases[0].tokens_cached == 400' "$TRACKER_FILE" >/dev/null 2>&1; then
|
|
157
|
-
record_pass "log-metric forwards tokens_cached end-to-end"
|
|
158
|
-
else
|
|
159
|
-
record_fail "tokens_cached did not reach the tracker"
|
|
160
|
-
cat "$TRACKER_FILE" >&2
|
|
161
|
-
fi
|
|
162
|
-
# A malformed tokens_cached must NOT poison the call (in/out must still land).
|
|
163
|
-
cat > "$TRACKER_FILE" <<'JSON'
|
|
164
|
-
{"task_id":"FWD-2","phases":[{"id":"4","name":"Review","status":"in_progress","subs":[]}]}
|
|
165
|
-
JSON
|
|
166
|
-
LOG_METRIC_FORWARD_TO_TRACKER=1 TRACKER_QUIET=1 \
|
|
167
|
-
bash "$LOG_METRIC" FWD-2 4 review.reviewer_call \
|
|
168
|
-
model=opus tokens_in=999 tokens_out=111 tokens_cached=abc duration_ms=1 >/dev/null 2>&1 || true
|
|
169
|
-
if jq -e '.phases[0].tokens_in == 999 and .phases[0].tokens_out == 111 and (.phases[0].tokens_cached // 0) == 0' "$TRACKER_FILE" >/dev/null 2>&1; then
|
|
170
|
-
record_pass "malformed tokens_cached sanitized to 0; in/out preserved"
|
|
171
|
-
else
|
|
172
|
-
record_fail "malformed tokens_cached poisoned the tokens call"
|
|
173
|
-
cat "$TRACKER_FILE" >&2
|
|
174
|
-
fi
|
|
175
|
-
unset METRICS_FILE TRACKER_FILE
|
|
176
|
-
rm -rf "$tmp"
|
|
177
|
-
|
|
178
|
-
# --- 5b: cached tokens are priced at the cache-read rate + surfaced ---
|
|
179
|
-
tmp=$(mktemp -d)
|
|
180
|
-
pushd "$tmp" >/dev/null
|
|
181
|
-
mkdir -p .worktrees/CACHE-1
|
|
182
|
-
cat > .worktrees/CACHE-1/phase-tracker.json <<'JSON'
|
|
183
|
-
{"task_id":"CACHE-1","phases":[
|
|
184
|
-
{"id":"1","name":"Analysis","model":"opus","tokens_in":20000,"tokens_out":3000,"tokens_cached":15000,"subs":[]},
|
|
185
|
-
{"id":"3","name":"Dev","model":"sonnet","tokens_in":60000,"tokens_out":10000,"subs":[]}
|
|
186
|
-
]}
|
|
187
|
-
JSON
|
|
188
|
-
out=$(bash "$RENDERER" CACHE-1 2>/dev/null)
|
|
189
|
-
# Cache-exclusive: tokens_in (20000) and tokens_cached (15000) are disjoint.
|
|
190
|
-
# 20000 fresh @5 + 15000 cached @0.50 + 3000 out @25 = 0.1825 -> floor-to-cents $0.18.
|
|
191
|
-
# Without the cache discount (cached billed @5) it would be 0.25 -> $0.25, so the
|
|
192
|
-
# discounted rate is what drives the row down to $0.18.
|
|
193
|
-
if grep -qE '\| Analysis \| opus \| 20,000 \| 3,000 \| \$0\.18 \|' <<< "$out"; then
|
|
194
|
-
record_pass "cached tokens priced at cache-read rate (opus row = \$0.18)"
|
|
195
|
-
else
|
|
196
|
-
record_fail "cached-token pricing wrong"
|
|
197
|
-
printf '%s\n' "$out" | head -12 >&2
|
|
198
|
-
fi
|
|
199
|
-
if grep -q 'Cache reads: 15,000 tokens' <<< "$out"; then
|
|
200
|
-
record_pass "cache-read footer surfaced when tokens_cached present"
|
|
201
|
-
else
|
|
202
|
-
record_fail "cache-read footer missing"
|
|
203
|
-
fi
|
|
204
|
-
if grep -qE 'Top cost driver:' <<< "$out"; then
|
|
205
|
-
record_pass "top cost driver line rendered"
|
|
206
|
-
else
|
|
207
|
-
record_fail "top cost driver line missing"
|
|
208
|
-
fi
|
|
209
|
-
popd >/dev/null
|
|
210
|
-
rm -rf "$tmp"
|
|
211
|
-
|
|
212
|
-
# --- 5c: no cache footer when no cached tokens (object-shape regression) ---
|
|
213
|
-
tmp=$(mktemp -d)
|
|
214
|
-
pushd "$tmp" >/dev/null
|
|
215
|
-
mkdir -p .worktrees/NOCACHE-1
|
|
216
|
-
cat > .worktrees/NOCACHE-1/phase-tracker.json <<'JSON'
|
|
217
|
-
{"task_id":"NOCACHE-1","phases":[
|
|
218
|
-
{"id":"3","name":"Dev","model":"sonnet","tokens_in":50000,"tokens_out":8000,"subs":[]}
|
|
219
|
-
]}
|
|
220
|
-
JSON
|
|
221
|
-
out=$(bash "$RENDERER" NOCACHE-1 2>/dev/null)
|
|
222
|
-
if grep -q 'Cache reads:' <<< "$out"; then
|
|
223
|
-
record_fail "cache-read footer should be absent when no cached tokens"
|
|
224
|
-
else
|
|
225
|
-
record_pass "no cache-read footer when tokens_cached absent"
|
|
226
|
-
fi
|
|
227
|
-
# Sonnet 50000 @3 + 8000 @15 = 0.27 -> $0.27 (unchanged from pre-cache behavior)
|
|
228
|
-
if grep -qE '\| Dev \| sonnet \| 50,000 \| 8,000 \| \$0\.27 \|' <<< "$out"; then
|
|
229
|
-
record_pass "no-cache USD unchanged (backward-compatible)"
|
|
230
|
-
else
|
|
231
|
-
record_fail "no-cache USD changed unexpectedly"
|
|
232
|
-
printf '%s\n' "$out" | head -12 >&2
|
|
233
|
-
fi
|
|
234
|
-
popd >/dev/null
|
|
235
|
-
rm -rf "$tmp"
|
|
236
|
-
|
|
237
|
-
# --- 6: log-format.md declares Tokens + Cost Breakdown ---
|
|
238
|
-
if grep -q 'Tokens (in/out)' "$LOG_FORMAT_DOC"; then
|
|
239
|
-
record_pass "log-format.md declares Tokens (in/out) column"
|
|
240
|
-
else
|
|
241
|
-
record_fail "log-format.md missing Tokens column declaration"
|
|
242
|
-
fi
|
|
243
|
-
if grep -q '## Cost Breakdown' "$LOG_FORMAT_DOC"; then
|
|
244
|
-
record_pass "log-format.md declares Cost Breakdown section"
|
|
245
|
-
else
|
|
246
|
-
record_fail "log-format.md missing Cost Breakdown section"
|
|
247
|
-
fi
|
|
248
|
-
if grep -q 'render-agent-log-cost.sh' "$LOG_FORMAT_DOC"; then
|
|
249
|
-
record_pass "log-format.md references render-agent-log-cost.sh"
|
|
250
|
-
else
|
|
251
|
-
record_fail "log-format.md does not reference renderer"
|
|
252
|
-
fi
|
|
253
|
-
|
|
254
|
-
# --- Summary ---
|
|
255
|
-
total=$((pass + fail))
|
|
256
|
-
printf '\n→ smoke-agent-log-cost: %d/%d passed\n' "$pass" "$total"
|
|
257
|
-
if [ "$fail" -ne 0 ]; then
|
|
258
|
-
printf '\nFailures:\n'
|
|
259
|
-
for f in "${failures[@]}"; do printf ' - %s\n' "$f"; done
|
|
260
|
-
exit 1
|
|
261
|
-
fi
|
|
262
|
-
exit 0
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# smoke-agent-model-routing.sh - v6.1.D
|
|
3
|
-
#
|
|
4
|
-
# Asserts per-persona model routing contract:
|
|
5
|
-
# 1. Every agent file in pipeline/agents/ has a `preferredModel` frontmatter field.
|
|
6
|
-
# 2. `preferredModel` is one of: fable | opus | sonnet | haiku.
|
|
7
|
-
# 3. `model:` (Claude-Code-native) matches `preferredModel` (single source of truth).
|
|
8
|
-
# 4. Orchestrator docs mention `CLAUDE_CODE_SUBAGENT_MODEL` and `preferredModel`.
|
|
9
|
-
# 5. Phase 4 review doc references the per-dispatch override mechanism.
|
|
10
|
-
#
|
|
11
|
-
# Exit 0 = all assertions pass, 1 = any failure.
|
|
12
|
-
|
|
13
|
-
set -euo pipefail
|
|
14
|
-
|
|
15
|
-
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
16
|
-
AGENTS_DIR="$ROOT/pipeline/agents"
|
|
17
|
-
ORCH_SKILL="$ROOT/pipeline/skills/shared/core/multi-agent/SKILL.md"
|
|
18
|
-
ORCH_CMD="$ROOT/pipeline/commands/multi-agent/SKILL.md"
|
|
19
|
-
PHASE4="$ROOT/pipeline/multi-agent-refs/phases/phase-4-review.md"
|
|
20
|
-
|
|
21
|
-
pass=0
|
|
22
|
-
fail=0
|
|
23
|
-
failures=()
|
|
24
|
-
|
|
25
|
-
record_pass() { pass=$((pass + 1)); printf ' \033[0;32mPASS\033[0m %s\n' "$1"; }
|
|
26
|
-
record_fail() { fail=$((fail + 1)); failures+=("$1"); printf ' \033[0;31mFAIL\033[0m %s\n' "$1"; }
|
|
27
|
-
|
|
28
|
-
printf '→ smoke-agent-model-routing (v6.1.D): per-persona model routing contract\n'
|
|
29
|
-
|
|
30
|
-
# --- 1/2/3: per-agent frontmatter ---
|
|
31
|
-
expected=(code-reviewer explorer ios-architect android-architect backend-architect security-auditor)
|
|
32
|
-
for name in "${expected[@]}"; do
|
|
33
|
-
f="$AGENTS_DIR/$name.md"
|
|
34
|
-
if [ ! -f "$f" ]; then
|
|
35
|
-
record_fail "$name.md missing"
|
|
36
|
-
continue
|
|
37
|
-
fi
|
|
38
|
-
pref=$(awk '/^preferredModel:/ {print $2; exit}' "$f" | tr -d '"'"'")
|
|
39
|
-
mdl=$(awk '/^model:/ {print $2; exit}' "$f" | tr -d '"'"'")
|
|
40
|
-
case "$pref" in
|
|
41
|
-
fable|opus|sonnet|haiku)
|
|
42
|
-
record_pass "$name has preferredModel=$pref"
|
|
43
|
-
;;
|
|
44
|
-
*)
|
|
45
|
-
record_fail "$name preferredModel invalid or missing (got '$pref')"
|
|
46
|
-
;;
|
|
47
|
-
esac
|
|
48
|
-
if [ -n "$pref" ] && [ "$pref" != "$mdl" ]; then
|
|
49
|
-
record_fail "$name model/preferredModel mismatch (model=$mdl preferredModel=$pref)"
|
|
50
|
-
elif [ -n "$pref" ]; then
|
|
51
|
-
record_pass "$name model == preferredModel ($pref)"
|
|
52
|
-
fi
|
|
53
|
-
if grep -q '^modelRationale:' "$f"; then
|
|
54
|
-
record_pass "$name has modelRationale"
|
|
55
|
-
else
|
|
56
|
-
record_fail "$name missing modelRationale"
|
|
57
|
-
fi
|
|
58
|
-
done
|
|
59
|
-
|
|
60
|
-
# --- 4: orchestrator SKILL.md references ---
|
|
61
|
-
if grep -q 'CLAUDE_CODE_SUBAGENT_MODEL' "$ORCH_SKILL" && grep -q 'preferredModel' "$ORCH_SKILL"; then
|
|
62
|
-
record_pass "orchestrator SKILL.md documents dispatch contract"
|
|
63
|
-
else
|
|
64
|
-
record_fail "orchestrator SKILL.md missing dispatch contract"
|
|
65
|
-
fi
|
|
66
|
-
|
|
67
|
-
# --- 4b: orchestrator command file references ---
|
|
68
|
-
if grep -q 'preferredModel' "$ORCH_CMD"; then
|
|
69
|
-
record_pass "commands/multi-agent/SKILL.md references preferredModel"
|
|
70
|
-
else
|
|
71
|
-
record_fail "commands/multi-agent/SKILL.md missing preferredModel reference"
|
|
72
|
-
fi
|
|
73
|
-
|
|
74
|
-
# --- 5: Phase 4 review doc references override ---
|
|
75
|
-
if grep -q 'PHASE_MODEL_OVERRIDE\|preferredModel' "$PHASE4"; then
|
|
76
|
-
record_pass "phase-4-review.md documents per-reviewer override"
|
|
77
|
-
else
|
|
78
|
-
record_fail "phase-4-review.md missing per-reviewer override doc"
|
|
79
|
-
fi
|
|
80
|
-
|
|
81
|
-
printf '\n══ agent-model-routing smoke: %d passed, %d failed ══\n' "$pass" "$fail"
|
|
82
|
-
if [ "$fail" -gt 0 ]; then
|
|
83
|
-
printf '\nFailures:\n'
|
|
84
|
-
for msg in "${failures[@]}"; do printf ' - %s\n' "$msg"; done
|
|
85
|
-
exit 1
|
|
86
|
-
fi
|
|
87
|
-
exit 0
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# smoke-ask-choice.sh - the portable picker fallback used on platforms without
|
|
3
|
-
# a native AskUserQuestion. Exercises default-by-index, default-by-label,
|
|
4
|
-
# non-interactive first-option, label-vs-index resolution, and usage errors.
|
|
5
|
-
|
|
6
|
-
set -uo pipefail
|
|
7
|
-
|
|
8
|
-
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
9
|
-
ASK="$REPO_ROOT/pipeline/lib/ask-choice.sh"
|
|
10
|
-
|
|
11
|
-
PASS=0
|
|
12
|
-
FAIL=0
|
|
13
|
-
pass() { PASS=$((PASS + 1)); echo " ✓ $1"; }
|
|
14
|
-
fail() { FAIL=$((FAIL + 1)); echo " ✗ $1"; }
|
|
15
|
-
|
|
16
|
-
echo "→ 1. usage error with <3 args (exit 64)"
|
|
17
|
-
bash "$ASK" "only a question" >/dev/null 2>&1
|
|
18
|
-
[ "$?" -eq 64 ] && pass "too-few-args exits 64" || fail "too-few-args should exit 64"
|
|
19
|
-
|
|
20
|
-
echo "→ 2. ASK_CHOICE_DEFAULT by 1-based index"
|
|
21
|
-
out=$(ASK_CHOICE_DEFAULT=2 bash "$ASK" "Approve this plan?" "Approve" "Cancel" "Edit" 2>/dev/null)
|
|
22
|
-
[ "$out" = "Cancel" ] && pass "index default 2 -> 'Cancel'" || fail "index default gave '$out' (expected Cancel)"
|
|
23
|
-
|
|
24
|
-
echo "→ 3. ASK_CHOICE_DEFAULT by label (case-insensitive)"
|
|
25
|
-
out=$(ASK_CHOICE_DEFAULT=approve bash "$ASK" "Approve this plan?" "Approve" "Cancel" 2>/dev/null)
|
|
26
|
-
[ "$out" = "Approve" ] && pass "label default 'approve' -> 'Approve'" || fail "label default gave '$out'"
|
|
27
|
-
|
|
28
|
-
echo "→ 4. out-of-range / unmatched default falls through to first option (non-TTY)"
|
|
29
|
-
out=$(ASK_CHOICE_DEFAULT=99 bash "$ASK" "Pick" "A" "B" </dev/null 2>/dev/null)
|
|
30
|
-
[ "$out" = "A" ] && pass "bad default + no TTY -> first option 'A'" || fail "bad default gave '$out'"
|
|
31
|
-
|
|
32
|
-
echo "→ 5. non-interactive (no TTY, no default) selects first option, never blocks"
|
|
33
|
-
out=$(bash "$ASK" "Continue?" "Yes" "No" </dev/null 2>/dev/null)
|
|
34
|
-
[ "$out" = "Yes" ] && pass "no TTY -> first option 'Yes'" || fail "no TTY gave '$out'"
|
|
35
|
-
|
|
36
|
-
echo "→ 6. stdout carries ONLY the label (menu/prompt go to stderr)"
|
|
37
|
-
out=$(ASK_CHOICE_DEFAULT=1 bash "$ASK" "Q" "Only" "Other" 2>/dev/null)
|
|
38
|
-
[ "$out" = "Only" ] && pass "stdout is clean single label" || fail "stdout not clean: '$out'"
|
|
39
|
-
|
|
40
|
-
echo ""
|
|
41
|
-
echo "══ ask-choice smoke: $PASS passed, $FAIL failed ══"
|
|
42
|
-
[ "$FAIL" -eq 0 ]
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# smoke-autopilot-circuit-breaker.sh - wiring contract for the autopilot
|
|
3
|
-
# circuit-breaker feature: the doc exists, enumerates the five trip conditions,
|
|
4
|
-
# and is referenced from the modes "what never skips" list.
|
|
5
|
-
#
|
|
6
|
-
# Exit 0 = all pass, 1 = any failure.
|
|
7
|
-
|
|
8
|
-
set -uo pipefail
|
|
9
|
-
|
|
10
|
-
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
11
|
-
DOC="$ROOT/pipeline/multi-agent-refs/features/autopilot-circuit-breaker.md"
|
|
12
|
-
MODES="$ROOT/pipeline/multi-agent-refs/phases/modes.md"
|
|
13
|
-
|
|
14
|
-
PASS=0; FAIL=0
|
|
15
|
-
pass() { PASS=$((PASS+1)); echo " ✓ $1"; }
|
|
16
|
-
fail() { FAIL=$((FAIL+1)); echo " ✗ $1"; }
|
|
17
|
-
|
|
18
|
-
[ -f "$DOC" ] && pass "feature doc exists" || fail "feature doc missing"
|
|
19
|
-
[ -f "$MODES" ] && pass "modes doc exists" || fail "modes doc missing"
|
|
20
|
-
|
|
21
|
-
echo "→ five trip conditions documented"
|
|
22
|
-
for t in "No-progress stall" "Identical repeated failure" "Rework storm" "Cost drift" "Merge/rebase conflict"; do
|
|
23
|
-
grep -Fq "$t" "$DOC" && pass "trigger: $t" || fail "trigger missing: $t"
|
|
24
|
-
done
|
|
25
|
-
|
|
26
|
-
echo "→ action + safety invariants"
|
|
27
|
-
grep -Fq "resume" "$DOC" && pass "documents resume path" || fail "no resume path"
|
|
28
|
-
grep -Eiq "never auto-resolve|does not paper over|no force-anything" "$DOC" && pass "no-self-heal invariant present" || fail "missing no-self-heal invariant"
|
|
29
|
-
|
|
30
|
-
echo "→ wired into modes 'what never skips'"
|
|
31
|
-
grep -Fq "autopilot-circuit-breaker.md" "$MODES" && pass "modes references the feature doc" || fail "modes does not reference the feature"
|
|
32
|
-
grep -Fiq "Circuit-breaker" "$MODES" && pass "modes lists circuit-breaker under never-skip" || fail "modes missing circuit-breaker bullet"
|
|
33
|
-
|
|
34
|
-
echo ""
|
|
35
|
-
echo "══ autopilot-circuit-breaker smoke: $PASS passed, $FAIL failed ══"
|
|
36
|
-
[ "$FAIL" -eq 0 ]
|