autonomous-coding-toolkit 1.0.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/.claude-plugin/marketplace.json +22 -0
- package/.claude-plugin/plugin.json +13 -0
- package/LICENSE +21 -0
- package/Makefile +21 -0
- package/README.md +140 -0
- package/SECURITY.md +28 -0
- package/agents/bash-expert.md +113 -0
- package/agents/dependency-auditor.md +138 -0
- package/agents/integration-tester.md +120 -0
- package/agents/lesson-scanner.md +149 -0
- package/agents/python-expert.md +179 -0
- package/agents/service-monitor.md +141 -0
- package/agents/shell-expert.md +147 -0
- package/benchmarks/runner.sh +147 -0
- package/benchmarks/tasks/01-rest-endpoint/rubric.sh +29 -0
- package/benchmarks/tasks/01-rest-endpoint/task.md +17 -0
- package/benchmarks/tasks/02-refactor-module/task.md +8 -0
- package/benchmarks/tasks/03-fix-integration-bug/task.md +8 -0
- package/benchmarks/tasks/04-add-test-coverage/task.md +8 -0
- package/benchmarks/tasks/05-multi-file-feature/task.md +8 -0
- package/bin/act.js +238 -0
- package/commands/autocode.md +6 -0
- package/commands/cancel-ralph.md +18 -0
- package/commands/code-factory.md +53 -0
- package/commands/create-prd.md +55 -0
- package/commands/ralph-loop.md +18 -0
- package/commands/run-plan.md +117 -0
- package/commands/submit-lesson.md +122 -0
- package/docs/ARCHITECTURE.md +630 -0
- package/docs/CONTRIBUTING.md +125 -0
- package/docs/lessons/0001-bare-exception-swallowing.md +34 -0
- package/docs/lessons/0002-async-def-without-await.md +28 -0
- package/docs/lessons/0003-create-task-without-callback.md +28 -0
- package/docs/lessons/0004-hardcoded-test-counts.md +28 -0
- package/docs/lessons/0005-sqlite-without-closing.md +33 -0
- package/docs/lessons/0006-venv-pip-path.md +27 -0
- package/docs/lessons/0007-runner-state-self-rejection.md +35 -0
- package/docs/lessons/0008-quality-gate-blind-spot.md +33 -0
- package/docs/lessons/0009-parser-overcount-empty-batches.md +36 -0
- package/docs/lessons/0010-local-outside-function-bash.md +33 -0
- package/docs/lessons/0011-batch-tests-for-unimplemented-code.md +36 -0
- package/docs/lessons/0012-api-markdown-unescaped-chars.md +33 -0
- package/docs/lessons/0013-export-prefix-env-parsing.md +33 -0
- package/docs/lessons/0014-decorator-registry-import-side-effect.md +43 -0
- package/docs/lessons/0015-frontend-backend-schema-drift.md +43 -0
- package/docs/lessons/0016-event-driven-cold-start-seeding.md +44 -0
- package/docs/lessons/0017-copy-paste-logic-diverges.md +43 -0
- package/docs/lessons/0018-layer-passes-pipeline-broken.md +45 -0
- package/docs/lessons/0019-systemd-envfile-ignores-export.md +41 -0
- package/docs/lessons/0020-persist-state-incrementally.md +44 -0
- package/docs/lessons/0021-dual-axis-testing.md +48 -0
- package/docs/lessons/0022-jsx-factory-shadowing.md +43 -0
- package/docs/lessons/0023-static-analysis-spiral.md +51 -0
- package/docs/lessons/0024-shared-pipeline-implementation.md +55 -0
- package/docs/lessons/0025-defense-in-depth-all-entry-points.md +65 -0
- package/docs/lessons/0026-linter-no-rules-false-enforcement.md +54 -0
- package/docs/lessons/0027-jsx-silent-prop-drop.md +64 -0
- package/docs/lessons/0028-no-infrastructure-in-client-code.md +49 -0
- package/docs/lessons/0029-never-write-secrets-to-files.md +61 -0
- package/docs/lessons/0030-cache-merge-not-replace.md +62 -0
- package/docs/lessons/0031-verify-units-at-boundaries.md +66 -0
- package/docs/lessons/0032-module-lifecycle-subscribe-unsubscribe.md +89 -0
- package/docs/lessons/0033-async-iteration-mutable-snapshot.md +72 -0
- package/docs/lessons/0034-caller-missing-await-silent-discard.md +65 -0
- package/docs/lessons/0035-duplicate-registration-silent-overwrite.md +85 -0
- package/docs/lessons/0036-websocket-dirty-disconnect.md +33 -0
- package/docs/lessons/0037-parallel-agents-worktree-corruption.md +31 -0
- package/docs/lessons/0038-subscribe-no-stored-ref.md +36 -0
- package/docs/lessons/0039-fallback-or-default-hides-bugs.md +34 -0
- package/docs/lessons/0040-event-firehose-filter-first.md +36 -0
- package/docs/lessons/0041-ambiguous-base-dir-path-nesting.md +32 -0
- package/docs/lessons/0042-spec-compliance-insufficient.md +36 -0
- package/docs/lessons/0043-exact-count-extensible-collections.md +32 -0
- package/docs/lessons/0044-relative-file-deps-worktree.md +39 -0
- package/docs/lessons/0045-iterative-design-improvement.md +33 -0
- package/docs/lessons/0046-plan-assertion-math-bugs.md +38 -0
- package/docs/lessons/0047-pytest-single-threaded-default.md +37 -0
- package/docs/lessons/0048-integration-wiring-batch.md +40 -0
- package/docs/lessons/0049-ab-verification.md +41 -0
- package/docs/lessons/0050-editing-sourced-files-during-execution.md +33 -0
- package/docs/lessons/0051-infrastructure-fixes-cant-self-heal.md +30 -0
- package/docs/lessons/0052-uncommitted-changes-poison-quality-gates.md +31 -0
- package/docs/lessons/0053-jq-compact-flag-inconsistency.md +31 -0
- package/docs/lessons/0054-parser-matches-inside-code-blocks.md +30 -0
- package/docs/lessons/0055-agents-compensate-for-garbled-prompts.md +31 -0
- package/docs/lessons/0056-grep-count-exit-code-on-zero.md +42 -0
- package/docs/lessons/0057-new-artifacts-break-git-clean-gates.md +42 -0
- package/docs/lessons/0058-dead-config-keys-never-consumed.md +49 -0
- package/docs/lessons/0059-contract-test-shared-structures.md +53 -0
- package/docs/lessons/0060-set-e-silent-death-in-runners.md +53 -0
- package/docs/lessons/0061-context-injection-dirty-state.md +50 -0
- package/docs/lessons/0062-sibling-bug-neighborhood-scan.md +29 -0
- package/docs/lessons/0063-one-flag-two-lifetimes.md +31 -0
- package/docs/lessons/0064-test-passes-wrong-reason.md +31 -0
- package/docs/lessons/0065-pipefail-grep-count-double-output.md +39 -0
- package/docs/lessons/0066-local-keyword-outside-function.md +37 -0
- package/docs/lessons/0067-stdin-hang-non-interactive-shell.md +36 -0
- package/docs/lessons/0068-agent-builds-wrong-thing-correctly.md +31 -0
- package/docs/lessons/0069-plan-quality-dominates-execution.md +30 -0
- package/docs/lessons/0070-spec-echo-back-prevents-drift.md +31 -0
- package/docs/lessons/0071-positive-instructions-outperform-negative.md +30 -0
- package/docs/lessons/0072-lost-in-the-middle-context-placement.md +30 -0
- package/docs/lessons/0073-unscoped-lessons-cause-false-positives.md +30 -0
- package/docs/lessons/0074-stale-context-injection-wrong-batch.md +32 -0
- package/docs/lessons/0075-research-artifacts-must-persist.md +32 -0
- package/docs/lessons/0076-wrong-decomposition-contaminates-downstream.md +30 -0
- package/docs/lessons/0077-cherry-pick-merges-need-manual-resolution.md +30 -0
- package/docs/lessons/0078-static-review-without-live-test.md +30 -0
- package/docs/lessons/0079-integration-wiring-batch-required.md +32 -0
- package/docs/lessons/FRAMEWORK.md +161 -0
- package/docs/lessons/SUMMARY.md +201 -0
- package/docs/lessons/TEMPLATE.md +85 -0
- package/docs/plans/2026-02-21-code-factory-v2-design.md +204 -0
- package/docs/plans/2026-02-21-code-factory-v2-implementation-plan.md +2189 -0
- package/docs/plans/2026-02-21-code-factory-v2-phase4-design.md +537 -0
- package/docs/plans/2026-02-21-code-factory-v2-phase4-implementation-plan.md +2012 -0
- package/docs/plans/2026-02-21-hardening-pass-design.md +108 -0
- package/docs/plans/2026-02-21-hardening-pass-plan.md +1378 -0
- package/docs/plans/2026-02-21-mab-research-report.md +406 -0
- package/docs/plans/2026-02-21-marketplace-restructure-design.md +240 -0
- package/docs/plans/2026-02-21-marketplace-restructure-plan.md +832 -0
- package/docs/plans/2026-02-21-phase4-completion-plan.md +697 -0
- package/docs/plans/2026-02-21-validator-suite-design.md +148 -0
- package/docs/plans/2026-02-21-validator-suite-plan.md +540 -0
- package/docs/plans/2026-02-22-mab-research-round2.md +556 -0
- package/docs/plans/2026-02-22-mab-run-design.md +462 -0
- package/docs/plans/2026-02-22-mab-run-plan.md +2046 -0
- package/docs/plans/2026-02-22-operations-design-methodology-research.md +681 -0
- package/docs/plans/2026-02-22-research-agent-failure-taxonomy.md +532 -0
- package/docs/plans/2026-02-22-research-code-guideline-policies.md +886 -0
- package/docs/plans/2026-02-22-research-codebase-audit-refactoring.md +908 -0
- package/docs/plans/2026-02-22-research-coding-standards-documentation.md +541 -0
- package/docs/plans/2026-02-22-research-competitive-landscape.md +687 -0
- package/docs/plans/2026-02-22-research-comprehensive-testing.md +1076 -0
- package/docs/plans/2026-02-22-research-context-utilization.md +459 -0
- package/docs/plans/2026-02-22-research-cost-quality-tradeoff.md +548 -0
- package/docs/plans/2026-02-22-research-lesson-transferability.md +508 -0
- package/docs/plans/2026-02-22-research-multi-agent-coordination.md +312 -0
- package/docs/plans/2026-02-22-research-phase-integration.md +602 -0
- package/docs/plans/2026-02-22-research-plan-quality.md +428 -0
- package/docs/plans/2026-02-22-research-prompt-engineering.md +558 -0
- package/docs/plans/2026-02-22-research-unconventional-perspectives.md +528 -0
- package/docs/plans/2026-02-22-research-user-adoption.md +638 -0
- package/docs/plans/2026-02-22-research-verification-effectiveness.md +433 -0
- package/docs/plans/2026-02-23-agent-suite-design.md +299 -0
- package/docs/plans/2026-02-23-agent-suite-plan.md +578 -0
- package/docs/plans/2026-02-23-phase3-cost-infrastructure-design.md +148 -0
- package/docs/plans/2026-02-23-phase3-cost-infrastructure-plan.md +1062 -0
- package/docs/plans/2026-02-23-research-bash-expert-agent.md +543 -0
- package/docs/plans/2026-02-23-research-dependency-auditor-agent.md +564 -0
- package/docs/plans/2026-02-23-research-improving-existing-agents.md +503 -0
- package/docs/plans/2026-02-23-research-integration-tester-agent.md +454 -0
- package/docs/plans/2026-02-23-research-python-expert-agent.md +429 -0
- package/docs/plans/2026-02-23-research-service-monitor-agent.md +425 -0
- package/docs/plans/2026-02-23-research-shell-expert-agent.md +533 -0
- package/docs/plans/2026-02-23-roadmap-to-completion.md +530 -0
- package/docs/plans/2026-02-24-headless-module-split-design.md +98 -0
- package/docs/plans/2026-02-24-headless-module-split.md +443 -0
- package/docs/plans/2026-02-24-lesson-scope-metadata-design.md +228 -0
- package/docs/plans/2026-02-24-lesson-scope-metadata-plan.md +968 -0
- package/docs/plans/2026-02-24-npm-packaging-design.md +841 -0
- package/docs/plans/2026-02-24-npm-packaging-plan.md +1965 -0
- package/docs/plans/audit-findings.md +186 -0
- package/docs/telegram-notification-format.md +98 -0
- package/examples/example-plan.md +51 -0
- package/examples/example-prd.json +72 -0
- package/examples/example-roadmap.md +33 -0
- package/examples/quickstart-plan.md +63 -0
- package/hooks/hooks.json +26 -0
- package/hooks/setup-symlinks.sh +48 -0
- package/hooks/stop-hook.sh +135 -0
- package/package.json +47 -0
- package/policies/bash.md +71 -0
- package/policies/python.md +71 -0
- package/policies/testing.md +61 -0
- package/policies/universal.md +60 -0
- package/scripts/analyze-report.sh +97 -0
- package/scripts/architecture-map.sh +145 -0
- package/scripts/auto-compound.sh +273 -0
- package/scripts/batch-audit.sh +42 -0
- package/scripts/batch-test.sh +101 -0
- package/scripts/entropy-audit.sh +221 -0
- package/scripts/failure-digest.sh +51 -0
- package/scripts/generate-ast-rules.sh +96 -0
- package/scripts/init.sh +112 -0
- package/scripts/lesson-check.sh +428 -0
- package/scripts/lib/common.sh +61 -0
- package/scripts/lib/cost-tracking.sh +153 -0
- package/scripts/lib/ollama.sh +60 -0
- package/scripts/lib/progress-writer.sh +128 -0
- package/scripts/lib/run-plan-context.sh +215 -0
- package/scripts/lib/run-plan-echo-back.sh +231 -0
- package/scripts/lib/run-plan-headless.sh +396 -0
- package/scripts/lib/run-plan-notify.sh +57 -0
- package/scripts/lib/run-plan-parser.sh +81 -0
- package/scripts/lib/run-plan-prompt.sh +215 -0
- package/scripts/lib/run-plan-quality-gate.sh +132 -0
- package/scripts/lib/run-plan-routing.sh +315 -0
- package/scripts/lib/run-plan-sampling.sh +170 -0
- package/scripts/lib/run-plan-scoring.sh +146 -0
- package/scripts/lib/run-plan-state.sh +142 -0
- package/scripts/lib/run-plan-team.sh +199 -0
- package/scripts/lib/telegram.sh +54 -0
- package/scripts/lib/thompson-sampling.sh +176 -0
- package/scripts/license-check.sh +74 -0
- package/scripts/mab-run.sh +575 -0
- package/scripts/module-size-check.sh +146 -0
- package/scripts/patterns/async-no-await.yml +5 -0
- package/scripts/patterns/bare-except.yml +6 -0
- package/scripts/patterns/empty-catch.yml +6 -0
- package/scripts/patterns/hardcoded-localhost.yml +9 -0
- package/scripts/patterns/retry-loop-no-backoff.yml +12 -0
- package/scripts/pipeline-status.sh +197 -0
- package/scripts/policy-check.sh +226 -0
- package/scripts/prior-art-search.sh +133 -0
- package/scripts/promote-mab-lessons.sh +126 -0
- package/scripts/prompts/agent-a-superpowers.md +29 -0
- package/scripts/prompts/agent-b-ralph.md +29 -0
- package/scripts/prompts/judge-agent.md +61 -0
- package/scripts/prompts/planner-agent.md +44 -0
- package/scripts/pull-community-lessons.sh +90 -0
- package/scripts/quality-gate.sh +266 -0
- package/scripts/research-gate.sh +90 -0
- package/scripts/run-plan.sh +329 -0
- package/scripts/scope-infer.sh +159 -0
- package/scripts/setup-ralph-loop.sh +155 -0
- package/scripts/telemetry.sh +230 -0
- package/scripts/tests/run-all-tests.sh +52 -0
- package/scripts/tests/test-act-cli.sh +46 -0
- package/scripts/tests/test-agents-md.sh +87 -0
- package/scripts/tests/test-analyze-report.sh +114 -0
- package/scripts/tests/test-architecture-map.sh +89 -0
- package/scripts/tests/test-auto-compound.sh +169 -0
- package/scripts/tests/test-batch-test.sh +65 -0
- package/scripts/tests/test-benchmark-runner.sh +25 -0
- package/scripts/tests/test-common.sh +168 -0
- package/scripts/tests/test-cost-tracking.sh +158 -0
- package/scripts/tests/test-echo-back.sh +180 -0
- package/scripts/tests/test-entropy-audit.sh +146 -0
- package/scripts/tests/test-failure-digest.sh +66 -0
- package/scripts/tests/test-generate-ast-rules.sh +145 -0
- package/scripts/tests/test-helpers.sh +82 -0
- package/scripts/tests/test-init.sh +47 -0
- package/scripts/tests/test-lesson-check.sh +278 -0
- package/scripts/tests/test-lesson-local.sh +55 -0
- package/scripts/tests/test-license-check.sh +109 -0
- package/scripts/tests/test-mab-run.sh +182 -0
- package/scripts/tests/test-ollama-lib.sh +49 -0
- package/scripts/tests/test-ollama.sh +60 -0
- package/scripts/tests/test-pipeline-status.sh +198 -0
- package/scripts/tests/test-policy-check.sh +124 -0
- package/scripts/tests/test-prior-art-search.sh +96 -0
- package/scripts/tests/test-progress-writer.sh +140 -0
- package/scripts/tests/test-promote-mab-lessons.sh +110 -0
- package/scripts/tests/test-pull-community-lessons.sh +149 -0
- package/scripts/tests/test-quality-gate.sh +241 -0
- package/scripts/tests/test-research-gate.sh +132 -0
- package/scripts/tests/test-run-plan-cli.sh +86 -0
- package/scripts/tests/test-run-plan-context.sh +305 -0
- package/scripts/tests/test-run-plan-e2e.sh +153 -0
- package/scripts/tests/test-run-plan-headless.sh +424 -0
- package/scripts/tests/test-run-plan-notify.sh +124 -0
- package/scripts/tests/test-run-plan-parser.sh +217 -0
- package/scripts/tests/test-run-plan-prompt.sh +254 -0
- package/scripts/tests/test-run-plan-quality-gate.sh +222 -0
- package/scripts/tests/test-run-plan-routing.sh +178 -0
- package/scripts/tests/test-run-plan-scoring.sh +148 -0
- package/scripts/tests/test-run-plan-state.sh +261 -0
- package/scripts/tests/test-run-plan-team.sh +157 -0
- package/scripts/tests/test-scope-infer.sh +150 -0
- package/scripts/tests/test-setup-ralph-loop.sh +63 -0
- package/scripts/tests/test-telegram-env.sh +38 -0
- package/scripts/tests/test-telegram.sh +121 -0
- package/scripts/tests/test-telemetry.sh +46 -0
- package/scripts/tests/test-thompson-sampling.sh +139 -0
- package/scripts/tests/test-validate-all.sh +60 -0
- package/scripts/tests/test-validate-commands.sh +89 -0
- package/scripts/tests/test-validate-hooks.sh +98 -0
- package/scripts/tests/test-validate-lessons.sh +150 -0
- package/scripts/tests/test-validate-plan-quality.sh +235 -0
- package/scripts/tests/test-validate-plans.sh +187 -0
- package/scripts/tests/test-validate-plugin.sh +106 -0
- package/scripts/tests/test-validate-prd.sh +184 -0
- package/scripts/tests/test-validate-skills.sh +134 -0
- package/scripts/validate-all.sh +57 -0
- package/scripts/validate-commands.sh +67 -0
- package/scripts/validate-hooks.sh +89 -0
- package/scripts/validate-lessons.sh +98 -0
- package/scripts/validate-plan-quality.sh +369 -0
- package/scripts/validate-plans.sh +120 -0
- package/scripts/validate-plugin.sh +86 -0
- package/scripts/validate-policies.sh +42 -0
- package/scripts/validate-prd.sh +118 -0
- package/scripts/validate-skills.sh +96 -0
- package/skills/autocode/SKILL.md +285 -0
- package/skills/autocode/ab-verification.md +51 -0
- package/skills/autocode/code-quality-standards.md +37 -0
- package/skills/autocode/competitive-mode.md +364 -0
- package/skills/brainstorming/SKILL.md +97 -0
- package/skills/capture-lesson/SKILL.md +187 -0
- package/skills/check-lessons/SKILL.md +116 -0
- package/skills/dispatching-parallel-agents/SKILL.md +110 -0
- package/skills/executing-plans/SKILL.md +85 -0
- package/skills/finishing-a-development-branch/SKILL.md +201 -0
- package/skills/receiving-code-review/SKILL.md +72 -0
- package/skills/requesting-code-review/SKILL.md +59 -0
- package/skills/requesting-code-review/code-reviewer.md +82 -0
- package/skills/research/SKILL.md +145 -0
- package/skills/roadmap/SKILL.md +115 -0
- package/skills/subagent-driven-development/SKILL.md +98 -0
- package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +18 -0
- package/skills/subagent-driven-development/implementer-prompt.md +73 -0
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +57 -0
- package/skills/systematic-debugging/SKILL.md +134 -0
- package/skills/systematic-debugging/condition-based-waiting.md +64 -0
- package/skills/systematic-debugging/defense-in-depth.md +32 -0
- package/skills/systematic-debugging/root-cause-tracing.md +55 -0
- package/skills/test-driven-development/SKILL.md +167 -0
- package/skills/using-git-worktrees/SKILL.md +219 -0
- package/skills/using-superpowers/SKILL.md +54 -0
- package/skills/verification-before-completion/SKILL.md +140 -0
- package/skills/verify/SKILL.md +82 -0
- package/skills/writing-plans/SKILL.md +128 -0
- package/skills/writing-skills/SKILL.md +93 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# quality-gate.sh — Composite quality gate for Ralph loop --quality-checks
|
|
3
|
+
# Runs lesson check + project test suite in sequence, fails fast on first failure.
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
|
|
7
|
+
source "$SCRIPT_DIR/lib/common.sh"
|
|
8
|
+
PROJECT_ROOT=""
|
|
9
|
+
QUICK=false
|
|
10
|
+
WITH_LICENSE=false
|
|
11
|
+
|
|
12
|
+
usage() {
|
|
13
|
+
cat <<'USAGE'
|
|
14
|
+
Usage: quality-gate.sh --project-root <dir> [--quick] [--with-license]
|
|
15
|
+
|
|
16
|
+
Composite quality gate for the Ralph loop. Runs checks in order, stops at first failure.
|
|
17
|
+
|
|
18
|
+
Checks:
|
|
19
|
+
0. Toolkit validation — runs validate-all.sh if present (toolkit self-check)
|
|
20
|
+
1. Lesson check — runs lesson-check.sh on git-changed files in project root
|
|
21
|
+
2. Lint check — ruff (Python) or eslint (Node) if available (skipped with --quick)
|
|
22
|
+
3. Project test suite — auto-detects pytest / npm test / make test
|
|
23
|
+
4. License check — flags GPL/AGPL deps (only with --with-license, skipped with --quick)
|
|
24
|
+
5. Memory warning — warns if available memory < 4G (never fails)
|
|
25
|
+
|
|
26
|
+
Options:
|
|
27
|
+
--project-root <dir> Project directory to check (required)
|
|
28
|
+
--quick Skip lint and license checks (fast inner-loop mode)
|
|
29
|
+
--with-license Include dependency license audit
|
|
30
|
+
--help, -h Show this help
|
|
31
|
+
|
|
32
|
+
Exit: 0 if all pass, 1 on first failure
|
|
33
|
+
USAGE
|
|
34
|
+
exit 0
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# --- Parse args ---
|
|
38
|
+
while [[ $# -gt 0 ]]; do
|
|
39
|
+
case "$1" in
|
|
40
|
+
--project-root)
|
|
41
|
+
PROJECT_ROOT="${2:-}"
|
|
42
|
+
shift 2
|
|
43
|
+
;;
|
|
44
|
+
--quick)
|
|
45
|
+
QUICK=true
|
|
46
|
+
shift
|
|
47
|
+
;;
|
|
48
|
+
--with-license)
|
|
49
|
+
WITH_LICENSE=true
|
|
50
|
+
shift
|
|
51
|
+
;;
|
|
52
|
+
--help|-h)
|
|
53
|
+
usage
|
|
54
|
+
;;
|
|
55
|
+
*)
|
|
56
|
+
echo "quality-gate: unknown option: $1" >&2
|
|
57
|
+
echo "Run with --help for usage." >&2
|
|
58
|
+
exit 1
|
|
59
|
+
;;
|
|
60
|
+
esac
|
|
61
|
+
done
|
|
62
|
+
|
|
63
|
+
if [[ -z "$PROJECT_ROOT" ]]; then
|
|
64
|
+
echo "quality-gate: --project-root is required" >&2
|
|
65
|
+
exit 1
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
if [[ ! -d "$PROJECT_ROOT" ]]; then
|
|
69
|
+
echo "quality-gate: directory not found: $PROJECT_ROOT" >&2
|
|
70
|
+
exit 1
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
cd "$PROJECT_ROOT"
|
|
74
|
+
|
|
75
|
+
# === Check 0: Toolkit Self-Validation ===
|
|
76
|
+
# Only runs when quality-gate is invoked from the toolkit itself
|
|
77
|
+
if [[ -f "$PROJECT_ROOT/scripts/validate-all.sh" ]]; then
|
|
78
|
+
echo "=== Quality Gate: Toolkit Validation ==="
|
|
79
|
+
if ! bash "$PROJECT_ROOT/scripts/validate-all.sh"; then
|
|
80
|
+
echo ""
|
|
81
|
+
echo "quality-gate: FAILED at toolkit validation"
|
|
82
|
+
exit 1
|
|
83
|
+
fi
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# === Check 1: Lesson check on changed files ===
|
|
87
|
+
echo "=== Quality Gate: Lesson Check ==="
|
|
88
|
+
changed_files=$(git diff --name-only 2>/dev/null || true)
|
|
89
|
+
if [[ -n "$changed_files" ]]; then
|
|
90
|
+
# Use an array to avoid word-splitting on filenames with spaces (#5).
|
|
91
|
+
readarray -t changed_array <<< "$changed_files"
|
|
92
|
+
if ! "$SCRIPT_DIR/lesson-check.sh" "${changed_array[@]}"; then
|
|
93
|
+
echo ""
|
|
94
|
+
echo "quality-gate: FAILED at lesson check"
|
|
95
|
+
exit 1
|
|
96
|
+
fi
|
|
97
|
+
else
|
|
98
|
+
echo "lesson-check: no changed files — skipped"
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# === Check 2: Lint Check (skipped with --quick) ===
|
|
102
|
+
if [[ "$QUICK" != true ]]; then
|
|
103
|
+
echo ""
|
|
104
|
+
echo "=== Quality Gate: Lint Check ==="
|
|
105
|
+
lint_ran=0
|
|
106
|
+
|
|
107
|
+
case "$(detect_project_type "$PROJECT_ROOT")" in
|
|
108
|
+
python)
|
|
109
|
+
if command -v ruff >/dev/null 2>&1; then
|
|
110
|
+
echo "Running: ruff check --select E,W,F"
|
|
111
|
+
if ! ruff check --select E,W,F "$PROJECT_ROOT" 2>/dev/null; then
|
|
112
|
+
echo ""
|
|
113
|
+
echo "quality-gate: FAILED at lint check"
|
|
114
|
+
exit 1
|
|
115
|
+
fi
|
|
116
|
+
lint_ran=1
|
|
117
|
+
else
|
|
118
|
+
echo "ruff not installed — skipping Python lint"
|
|
119
|
+
fi
|
|
120
|
+
;;
|
|
121
|
+
node)
|
|
122
|
+
if [[ -f "$PROJECT_ROOT/.eslintrc" || -f "$PROJECT_ROOT/.eslintrc.js" || -f "$PROJECT_ROOT/.eslintrc.json" || -f "$PROJECT_ROOT/eslint.config.js" ]]; then
|
|
123
|
+
echo "Running: npx eslint"
|
|
124
|
+
if ! npx eslint "$PROJECT_ROOT" 2>/dev/null; then
|
|
125
|
+
echo ""
|
|
126
|
+
echo "quality-gate: FAILED at lint check"
|
|
127
|
+
exit 1
|
|
128
|
+
fi
|
|
129
|
+
lint_ran=1
|
|
130
|
+
else
|
|
131
|
+
echo "No eslint config found — skipping Node lint"
|
|
132
|
+
fi
|
|
133
|
+
;;
|
|
134
|
+
esac
|
|
135
|
+
|
|
136
|
+
if [[ $lint_ran -eq 0 ]]; then
|
|
137
|
+
echo "No linter configured — skipped"
|
|
138
|
+
fi
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
# === Check 2.5: ast-grep structural analysis (optional, advisory) ===
|
|
142
|
+
if [[ "$QUICK" != true ]]; then
|
|
143
|
+
echo ""
|
|
144
|
+
echo "=== Quality Gate: Structural Analysis (ast-grep) ==="
|
|
145
|
+
if command -v ast-grep >/dev/null 2>&1; then
|
|
146
|
+
PATTERNS_DIR="$SCRIPT_DIR/patterns"
|
|
147
|
+
ast_violations=0
|
|
148
|
+
if [[ -d "$PATTERNS_DIR" ]]; then
|
|
149
|
+
for pattern_file in "$PATTERNS_DIR"/*.yml; do
|
|
150
|
+
[[ -f "$pattern_file" ]] || continue
|
|
151
|
+
matches=$(ast-grep scan --rule "$pattern_file" "$PROJECT_ROOT" 2>/dev/null || true)
|
|
152
|
+
if [[ -n "$matches" ]]; then
|
|
153
|
+
echo "WARNING: $(basename "$pattern_file" .yml): $(echo "$matches" | wc -l) matches"
|
|
154
|
+
echo "$matches" | head -3
|
|
155
|
+
ast_violations=$((ast_violations + 1))
|
|
156
|
+
fi
|
|
157
|
+
done
|
|
158
|
+
fi
|
|
159
|
+
if [[ $ast_violations -gt 0 ]]; then
|
|
160
|
+
echo "ast-grep: $ast_violations pattern(s) matched (advisory)"
|
|
161
|
+
else
|
|
162
|
+
echo "ast-grep: clean"
|
|
163
|
+
fi
|
|
164
|
+
else
|
|
165
|
+
echo "ast-grep not installed — skipping structural analysis"
|
|
166
|
+
fi
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
# === Check 2.7: Module size check (advisory) ===
|
|
170
|
+
if [[ "$QUICK" != true ]]; then
|
|
171
|
+
echo ""
|
|
172
|
+
echo "=== Quality Gate: Module Size Check ==="
|
|
173
|
+
if [[ -x "$SCRIPT_DIR/module-size-check.sh" ]]; then
|
|
174
|
+
_size_exit=0
|
|
175
|
+
"$SCRIPT_DIR/module-size-check.sh" --project-root "$PROJECT_ROOT" || _size_exit=$?
|
|
176
|
+
if [[ $_size_exit -ne 0 ]]; then
|
|
177
|
+
echo "module-size-check: $( [ $_size_exit -eq 1 ] && echo "oversized modules detected (advisory)" || echo "error (exit $_size_exit)")"
|
|
178
|
+
fi
|
|
179
|
+
else
|
|
180
|
+
echo "module-size-check.sh not found — skipped"
|
|
181
|
+
fi
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
# === Check 3: Project test suite (auto-detect) ===
|
|
185
|
+
echo ""
|
|
186
|
+
echo "=== Quality Gate: Test Suite ==="
|
|
187
|
+
test_ran=0
|
|
188
|
+
|
|
189
|
+
project_type=$(detect_project_type "$PROJECT_ROOT")
|
|
190
|
+
case "$project_type" in
|
|
191
|
+
python)
|
|
192
|
+
echo "Detected: pytest project"
|
|
193
|
+
.venv/bin/python -m pytest --timeout=120 -x -q
|
|
194
|
+
test_ran=1
|
|
195
|
+
;;
|
|
196
|
+
node)
|
|
197
|
+
if grep -q '"test"' "$PROJECT_ROOT/package.json" 2>/dev/null; then
|
|
198
|
+
echo "Detected: npm project"
|
|
199
|
+
npm test
|
|
200
|
+
test_ran=1
|
|
201
|
+
fi
|
|
202
|
+
;;
|
|
203
|
+
make)
|
|
204
|
+
if grep -q '^test:' "$PROJECT_ROOT/Makefile" 2>/dev/null; then
|
|
205
|
+
echo "Detected: Makefile project"
|
|
206
|
+
make test
|
|
207
|
+
test_ran=1
|
|
208
|
+
fi
|
|
209
|
+
;;
|
|
210
|
+
bash)
|
|
211
|
+
if [[ -x "$PROJECT_ROOT/scripts/tests/run-all-tests.sh" ]]; then
|
|
212
|
+
echo "Detected: bash project (run-all-tests.sh)"
|
|
213
|
+
"$PROJECT_ROOT/scripts/tests/run-all-tests.sh"
|
|
214
|
+
test_ran=1
|
|
215
|
+
fi
|
|
216
|
+
;;
|
|
217
|
+
esac
|
|
218
|
+
|
|
219
|
+
if [[ $test_ran -eq 0 ]]; then
|
|
220
|
+
echo "No test suite detected (no pyproject.toml/setup.py/pytest.ini, no npm test script, no Makefile test target) — skipped"
|
|
221
|
+
fi
|
|
222
|
+
|
|
223
|
+
# === Check 4: License Check (only with --with-license, skipped with --quick) ===
|
|
224
|
+
if [[ "$WITH_LICENSE" == true ]]; then
|
|
225
|
+
echo ""
|
|
226
|
+
echo "=== Quality Gate: License Check ==="
|
|
227
|
+
if ! "$SCRIPT_DIR/license-check.sh" --project-root "$PROJECT_ROOT"; then
|
|
228
|
+
echo "quality-gate: FAILED at license check"
|
|
229
|
+
exit 1
|
|
230
|
+
fi
|
|
231
|
+
fi
|
|
232
|
+
|
|
233
|
+
# === Check 5: Memory warning (advisory only) ===
|
|
234
|
+
echo ""
|
|
235
|
+
echo "=== Quality Gate: Memory Check ==="
|
|
236
|
+
_mem_exit=0
|
|
237
|
+
check_memory_available 4 || _mem_exit=$?
|
|
238
|
+
if [[ $_mem_exit -eq 0 ]]; then
|
|
239
|
+
available_mb=$(free -m 2>/dev/null | awk '/Mem:/{print $7}')
|
|
240
|
+
available_display=$(awk "BEGIN {printf \"%.1f\", ${available_mb:-0} / 1024}")
|
|
241
|
+
echo "Memory OK (${available_display}G available)"
|
|
242
|
+
elif [[ $_mem_exit -eq 2 ]]; then
|
|
243
|
+
echo "WARNING: Memory check skipped (cannot determine available memory)"
|
|
244
|
+
else
|
|
245
|
+
echo "WARNING: Consider -n 0 for pytest"
|
|
246
|
+
fi
|
|
247
|
+
|
|
248
|
+
echo ""
|
|
249
|
+
echo "quality-gate: ALL PASSED"
|
|
250
|
+
|
|
251
|
+
# === Telemetry capture (append batch result) ===
|
|
252
|
+
# Only record if TELEMETRY_BATCH_NUMBER is set (called from run-plan context)
|
|
253
|
+
if [[ -n "${TELEMETRY_BATCH_NUMBER:-}" ]]; then
|
|
254
|
+
"$SCRIPT_DIR/telemetry.sh" record \
|
|
255
|
+
--project-root "$PROJECT_ROOT" \
|
|
256
|
+
--batch-number "${TELEMETRY_BATCH_NUMBER}" \
|
|
257
|
+
--passed true \
|
|
258
|
+
--strategy "${TELEMETRY_STRATEGY:-unknown}" \
|
|
259
|
+
--duration "${TELEMETRY_DURATION:-0}" \
|
|
260
|
+
--cost "${TELEMETRY_COST:-0}" \
|
|
261
|
+
--test-delta "${TELEMETRY_TEST_DELTA:-0}" \
|
|
262
|
+
--batch-type "${TELEMETRY_BATCH_TYPE:-unknown}" \
|
|
263
|
+
2>/dev/null || true # Never fail the gate for telemetry errors
|
|
264
|
+
fi
|
|
265
|
+
|
|
266
|
+
exit 0
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# research-gate.sh — Blocks PRD generation if research has unresolved blocking issues
|
|
3
|
+
#
|
|
4
|
+
# Usage: research-gate.sh <research-json> [--force]
|
|
5
|
+
#
|
|
6
|
+
# Reads tasks/research-<slug>.json and checks:
|
|
7
|
+
# - File exists and is valid JSON
|
|
8
|
+
# - No blocking_issues with resolved: false
|
|
9
|
+
#
|
|
10
|
+
# Exit 0 = clear (proceed to PRD)
|
|
11
|
+
# Exit 1 = blocked (unresolved issues)
|
|
12
|
+
# --force = override (exit 0 regardless, with warning)
|
|
13
|
+
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
FORCE=false
|
|
17
|
+
|
|
18
|
+
usage() {
|
|
19
|
+
cat <<'EOF'
|
|
20
|
+
research-gate.sh — Research phase gate for PRD generation
|
|
21
|
+
|
|
22
|
+
USAGE:
|
|
23
|
+
research-gate.sh <research-json> [--force]
|
|
24
|
+
|
|
25
|
+
OPTIONS:
|
|
26
|
+
--force Override blocking issues (exit 0 with warning)
|
|
27
|
+
-h, --help Show this help
|
|
28
|
+
|
|
29
|
+
EXIT CODES:
|
|
30
|
+
0 Clear — no unresolved blocking issues
|
|
31
|
+
1 Blocked — unresolved blocking issues found
|
|
32
|
+
EOF
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# Parse args
|
|
36
|
+
RESEARCH_FILE=""
|
|
37
|
+
while [[ $# -gt 0 ]]; do
|
|
38
|
+
case $1 in
|
|
39
|
+
--force) FORCE=true; shift ;;
|
|
40
|
+
-h|--help) usage; exit 0 ;;
|
|
41
|
+
-*) echo "Unknown option: $1" >&2; exit 1 ;;
|
|
42
|
+
*) RESEARCH_FILE="$1"; shift ;;
|
|
43
|
+
esac
|
|
44
|
+
done
|
|
45
|
+
|
|
46
|
+
if [[ -z "$RESEARCH_FILE" ]]; then
|
|
47
|
+
echo "Error: research JSON file required" >&2
|
|
48
|
+
echo "Usage: research-gate.sh <research-json> [--force]" >&2
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
if [[ ! -f "$RESEARCH_FILE" ]]; then
|
|
53
|
+
echo "Error: file not found: $RESEARCH_FILE" >&2
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# Validate JSON
|
|
58
|
+
if ! jq empty "$RESEARCH_FILE" 2>/dev/null; then
|
|
59
|
+
echo "Error: invalid JSON: $RESEARCH_FILE" >&2
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# Check for unresolved blocking issues
|
|
64
|
+
unresolved_count=$(jq '[.blocking_issues[]? | select(.resolved == false)] | length' "$RESEARCH_FILE" 2>/dev/null || echo "0")
|
|
65
|
+
|
|
66
|
+
if [[ "$unresolved_count" -gt 0 ]]; then
|
|
67
|
+
echo "RESEARCH GATE: $unresolved_count unresolved blocking issue(s)"
|
|
68
|
+
jq -r '.blocking_issues[]? | select(.resolved == false) | " - \(.issue)"' "$RESEARCH_FILE" 2>/dev/null
|
|
69
|
+
|
|
70
|
+
if [[ "$FORCE" == "true" ]]; then
|
|
71
|
+
echo ""
|
|
72
|
+
echo "WARNING: --force used, proceeding despite blocking issues"
|
|
73
|
+
exit 0
|
|
74
|
+
else
|
|
75
|
+
echo ""
|
|
76
|
+
echo "Resolve blocking issues or use --force to override"
|
|
77
|
+
exit 1
|
|
78
|
+
fi
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# Check for warnings (informational, never blocks)
|
|
82
|
+
warning_count=$(jq '[.warnings[]?] | length' "$RESEARCH_FILE" 2>/dev/null || echo "0")
|
|
83
|
+
if [[ "$warning_count" -gt 0 ]]; then
|
|
84
|
+
echo "RESEARCH GATE: clear ($warning_count warning(s))"
|
|
85
|
+
jq -r '.warnings[]? | " ⚠ \(.)"' "$RESEARCH_FILE" 2>/dev/null
|
|
86
|
+
else
|
|
87
|
+
echo "RESEARCH GATE: clear (no blocking issues, no warnings)"
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
exit 0
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# run-plan.sh — Execute implementation plans via headless Claude batches
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# run-plan.sh <plan-file> [options]
|
|
6
|
+
# run-plan.sh --resume [options]
|
|
7
|
+
#
|
|
8
|
+
# Modes:
|
|
9
|
+
# headless (default) — bash loop calling claude -p per batch
|
|
10
|
+
# team — prints launch command for Claude agent team mode
|
|
11
|
+
# competitive — prints launch command for competitive agent mode
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
|
|
15
|
+
|
|
16
|
+
# --- Signal handling ---
|
|
17
|
+
# Log unexpected exits for diagnostics (silent death prevention)
|
|
18
|
+
_run_plan_exit_code=0
|
|
19
|
+
_run_plan_exit_logged=false
|
|
20
|
+
_log_exit() {
|
|
21
|
+
local code=${1:-$?}
|
|
22
|
+
[[ "$_run_plan_exit_logged" == true ]] && return
|
|
23
|
+
_run_plan_exit_logged=true
|
|
24
|
+
if [[ $code -ne 0 ]]; then
|
|
25
|
+
echo "" >&2
|
|
26
|
+
echo "run-plan: EXIT with code $code at $(date -u +%Y-%m-%dT%H:%M:%SZ)" >&2
|
|
27
|
+
# Print last few lines of bash call stack
|
|
28
|
+
local i
|
|
29
|
+
for ((i = 0; i < ${#FUNCNAME[@]}; i++)); do
|
|
30
|
+
echo " ${BASH_SOURCE[$i]:-unknown}:${BASH_LINENO[$i]:-?} in ${FUNCNAME[$i]:-main}" >&2
|
|
31
|
+
done
|
|
32
|
+
fi
|
|
33
|
+
}
|
|
34
|
+
trap '_log_exit $?' EXIT
|
|
35
|
+
|
|
36
|
+
# Ignore HUP and PIPE so background execution survives terminal disconnect
|
|
37
|
+
# and broken pipe from task manager stdout (confirmed root cause: exit 141 = SIGPIPE)
|
|
38
|
+
trap '' HUP PIPE
|
|
39
|
+
|
|
40
|
+
# Source all lib functions
|
|
41
|
+
source "$SCRIPT_DIR/lib/run-plan-parser.sh"
|
|
42
|
+
source "$SCRIPT_DIR/lib/run-plan-state.sh"
|
|
43
|
+
source "$SCRIPT_DIR/lib/run-plan-quality-gate.sh"
|
|
44
|
+
source "$SCRIPT_DIR/lib/run-plan-notify.sh"
|
|
45
|
+
source "$SCRIPT_DIR/lib/run-plan-prompt.sh"
|
|
46
|
+
source "$SCRIPT_DIR/lib/progress-writer.sh"
|
|
47
|
+
source "$SCRIPT_DIR/lib/run-plan-echo-back.sh"
|
|
48
|
+
source "$SCRIPT_DIR/lib/run-plan-sampling.sh"
|
|
49
|
+
source "$SCRIPT_DIR/lib/run-plan-headless.sh"
|
|
50
|
+
source "$SCRIPT_DIR/lib/run-plan-context.sh"
|
|
51
|
+
source "$SCRIPT_DIR/lib/progress-writer.sh"
|
|
52
|
+
source "$SCRIPT_DIR/lib/run-plan-scoring.sh"
|
|
53
|
+
source "$SCRIPT_DIR/lib/cost-tracking.sh"
|
|
54
|
+
source "$SCRIPT_DIR/lib/run-plan-team.sh"
|
|
55
|
+
source "$SCRIPT_DIR/lib/thompson-sampling.sh"
|
|
56
|
+
|
|
57
|
+
# --- Defaults ---
|
|
58
|
+
PLAN_FILE=""
|
|
59
|
+
MODE="headless"
|
|
60
|
+
START_BATCH=""
|
|
61
|
+
END_BATCH=""
|
|
62
|
+
WORKTREE="$(pwd)"
|
|
63
|
+
PYTHON="python3"
|
|
64
|
+
QUALITY_GATE_CMD="$SCRIPT_DIR/quality-gate.sh --project-root ."
|
|
65
|
+
ON_FAILURE="stop"
|
|
66
|
+
MAX_RETRIES=2
|
|
67
|
+
COMPETITIVE_BATCHES=""
|
|
68
|
+
SAMPLE_COUNT=0 # 0 = disabled
|
|
69
|
+
NOTIFY=false
|
|
70
|
+
VERIFY=false
|
|
71
|
+
RESUME=false
|
|
72
|
+
SKIP_PLAN_QUALITY=false
|
|
73
|
+
SKIP_ECHO_BACK=false
|
|
74
|
+
STRICT_ECHO_BACK=false
|
|
75
|
+
MAB=false
|
|
76
|
+
MAX_BUDGET=""
|
|
77
|
+
|
|
78
|
+
# --- Usage ---
|
|
79
|
+
usage() {
|
|
80
|
+
cat <<'USAGE'
|
|
81
|
+
run-plan — Execute implementation plans via headless Claude batches
|
|
82
|
+
|
|
83
|
+
Usage:
|
|
84
|
+
run-plan.sh <plan-file> [options]
|
|
85
|
+
run-plan.sh --resume [options]
|
|
86
|
+
|
|
87
|
+
Options:
|
|
88
|
+
--mode <headless|team|competitive> Execution mode (default: headless)
|
|
89
|
+
--start-batch N First batch to execute
|
|
90
|
+
--end-batch N Last batch to execute
|
|
91
|
+
--worktree <path> Working directory (default: cwd)
|
|
92
|
+
--python <path> Python interpreter (default: python3)
|
|
93
|
+
--quality-gate <cmd> Quality gate command
|
|
94
|
+
(default: "scripts/quality-gate.sh --project-root .")
|
|
95
|
+
--on-failure <stop|skip|retry> Failure handling (default: stop)
|
|
96
|
+
--max-retries N Max retries per batch (default: 2)
|
|
97
|
+
--competitive-batches N,N,... Batches for competitive mode
|
|
98
|
+
--sample N Parallel patch sampling (N candidates, default 3)
|
|
99
|
+
--no-sample Disable sampling (default)
|
|
100
|
+
--notify Send Telegram notifications
|
|
101
|
+
--verify Run verification after all batches
|
|
102
|
+
--skip-plan-quality Skip plan quality scorecard check
|
|
103
|
+
--skip-echo-back Skip spec echo-back verification
|
|
104
|
+
--resume Resume from saved state
|
|
105
|
+
--max-budget <dollars> Stop if total cost exceeds this amount
|
|
106
|
+
--skip-echo-back Disable echo-back spec check entirely
|
|
107
|
+
--strict-echo-back Make echo-back blocking (aborts batch on mismatch)
|
|
108
|
+
--mab Enable MAB routing (competing agents via Thompson Sampling)
|
|
109
|
+
-h, --help Show this help message
|
|
110
|
+
|
|
111
|
+
Modes:
|
|
112
|
+
headless Bash loop calling claude -p per batch (runs locally)
|
|
113
|
+
team Multi-agent team mode (prints Claude launch command)
|
|
114
|
+
competitive Competitive agent mode (prints Claude launch command)
|
|
115
|
+
|
|
116
|
+
Examples:
|
|
117
|
+
run-plan.sh docs/plans/2026-02-20-feature.md
|
|
118
|
+
run-plan.sh docs/plans/2026-02-20-feature.md --mode headless --start-batch 2
|
|
119
|
+
run-plan.sh --resume --worktree /path/to/worktree
|
|
120
|
+
run-plan.sh docs/plans/feature.md --on-failure retry --max-retries 3 --notify
|
|
121
|
+
USAGE
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
# --- Argument parsing ---
|
|
125
|
+
# shellcheck disable=SC2034 # Globals consumed by sourced lib scripts
|
|
126
|
+
parse_args() {
|
|
127
|
+
while [[ $# -gt 0 ]]; do
|
|
128
|
+
case "$1" in
|
|
129
|
+
-h|--help)
|
|
130
|
+
usage
|
|
131
|
+
exit 0
|
|
132
|
+
;;
|
|
133
|
+
--mode)
|
|
134
|
+
MODE="$2"; shift 2
|
|
135
|
+
;;
|
|
136
|
+
--start-batch)
|
|
137
|
+
START_BATCH="$2"; shift 2
|
|
138
|
+
;;
|
|
139
|
+
--end-batch)
|
|
140
|
+
END_BATCH="$2"; shift 2
|
|
141
|
+
;;
|
|
142
|
+
--worktree)
|
|
143
|
+
WORKTREE="$2"; shift 2
|
|
144
|
+
;;
|
|
145
|
+
--python)
|
|
146
|
+
PYTHON="$2"; shift 2
|
|
147
|
+
;;
|
|
148
|
+
--quality-gate)
|
|
149
|
+
QUALITY_GATE_CMD="$2"; shift 2
|
|
150
|
+
;;
|
|
151
|
+
--on-failure)
|
|
152
|
+
ON_FAILURE="$2"; shift 2
|
|
153
|
+
;;
|
|
154
|
+
--max-retries)
|
|
155
|
+
MAX_RETRIES="$2"; shift 2
|
|
156
|
+
;;
|
|
157
|
+
--competitive-batches)
|
|
158
|
+
COMPETITIVE_BATCHES="$2"; shift 2
|
|
159
|
+
;;
|
|
160
|
+
--sample)
|
|
161
|
+
SAMPLE_COUNT="${2:-3}"; shift 2
|
|
162
|
+
;;
|
|
163
|
+
--no-sample)
|
|
164
|
+
SAMPLE_COUNT=0; shift
|
|
165
|
+
;;
|
|
166
|
+
--notify)
|
|
167
|
+
NOTIFY=true; shift
|
|
168
|
+
;;
|
|
169
|
+
--verify)
|
|
170
|
+
VERIFY=true; shift
|
|
171
|
+
;;
|
|
172
|
+
--skip-plan-quality)
|
|
173
|
+
SKIP_PLAN_QUALITY=true; shift
|
|
174
|
+
;;
|
|
175
|
+
--skip-echo-back)
|
|
176
|
+
SKIP_ECHO_BACK=true; shift
|
|
177
|
+
;;
|
|
178
|
+
--resume)
|
|
179
|
+
RESUME=true; shift
|
|
180
|
+
;;
|
|
181
|
+
--max-budget)
|
|
182
|
+
MAX_BUDGET="$2"; shift 2
|
|
183
|
+
;;
|
|
184
|
+
--skip-echo-back) SKIP_ECHO_BACK=true; shift ;;
|
|
185
|
+
--strict-echo-back) STRICT_ECHO_BACK=true; shift ;;
|
|
186
|
+
--mab) MAB=true; shift ;;
|
|
187
|
+
-*)
|
|
188
|
+
echo "ERROR: Unknown option: $1" >&2
|
|
189
|
+
usage >&2
|
|
190
|
+
exit 1
|
|
191
|
+
;;
|
|
192
|
+
*)
|
|
193
|
+
# Positional arg = plan file
|
|
194
|
+
if [[ -z "$PLAN_FILE" ]]; then
|
|
195
|
+
PLAN_FILE="$1"
|
|
196
|
+
else
|
|
197
|
+
echo "ERROR: Unexpected argument: $1" >&2
|
|
198
|
+
exit 1
|
|
199
|
+
fi
|
|
200
|
+
shift
|
|
201
|
+
;;
|
|
202
|
+
esac
|
|
203
|
+
done
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
# --- Validation ---
|
|
207
|
+
validate_args() {
|
|
208
|
+
# Resume mode: load state file
|
|
209
|
+
if [[ "$RESUME" == true ]]; then
|
|
210
|
+
local state_file="$WORKTREE/.run-plan-state.json"
|
|
211
|
+
if [[ ! -f "$state_file" ]]; then
|
|
212
|
+
echo "ERROR: No state file found at $state_file" >&2
|
|
213
|
+
echo "Cannot resume without a previous run." >&2
|
|
214
|
+
exit 1
|
|
215
|
+
fi
|
|
216
|
+
# Load defaults from state
|
|
217
|
+
if [[ -z "$PLAN_FILE" ]]; then
|
|
218
|
+
PLAN_FILE=$(read_state_field "$WORKTREE" "plan_file")
|
|
219
|
+
fi
|
|
220
|
+
if [[ -z "$MODE" || "$MODE" == "headless" ]]; then
|
|
221
|
+
local saved_mode
|
|
222
|
+
saved_mode=$(read_state_field "$WORKTREE" "mode")
|
|
223
|
+
if [[ -n "$saved_mode" && "$saved_mode" != "null" ]]; then
|
|
224
|
+
MODE="$saved_mode"
|
|
225
|
+
fi
|
|
226
|
+
fi
|
|
227
|
+
if [[ -z "$START_BATCH" ]]; then
|
|
228
|
+
START_BATCH=$(read_state_field "$WORKTREE" "current_batch")
|
|
229
|
+
fi
|
|
230
|
+
fi
|
|
231
|
+
|
|
232
|
+
# Must have a plan file
|
|
233
|
+
if [[ -z "$PLAN_FILE" ]]; then
|
|
234
|
+
echo "ERROR: No plan file specified. Use: run-plan.sh <plan-file> or --resume" >&2
|
|
235
|
+
exit 1
|
|
236
|
+
fi
|
|
237
|
+
|
|
238
|
+
# Plan file must exist
|
|
239
|
+
if [[ ! -f "$PLAN_FILE" ]]; then
|
|
240
|
+
echo "ERROR: Plan file not found: $PLAN_FILE" >&2
|
|
241
|
+
exit 1
|
|
242
|
+
fi
|
|
243
|
+
|
|
244
|
+
# Validate mode
|
|
245
|
+
case "$MODE" in
|
|
246
|
+
headless|team|competitive) ;;
|
|
247
|
+
*)
|
|
248
|
+
echo "ERROR: Invalid mode: $MODE (must be headless, team, or competitive)" >&2
|
|
249
|
+
exit 1
|
|
250
|
+
;;
|
|
251
|
+
esac
|
|
252
|
+
|
|
253
|
+
# Validate on-failure
|
|
254
|
+
case "$ON_FAILURE" in
|
|
255
|
+
stop|skip|retry) ;;
|
|
256
|
+
*)
|
|
257
|
+
echo "ERROR: Invalid --on-failure: $ON_FAILURE (must be stop, skip, or retry)" >&2
|
|
258
|
+
exit 1
|
|
259
|
+
;;
|
|
260
|
+
esac
|
|
261
|
+
|
|
262
|
+
# Set batch range defaults
|
|
263
|
+
local total
|
|
264
|
+
total=$(count_batches "$PLAN_FILE")
|
|
265
|
+
if [[ -z "$START_BATCH" ]]; then
|
|
266
|
+
START_BATCH=1
|
|
267
|
+
fi
|
|
268
|
+
if [[ -z "$END_BATCH" ]]; then
|
|
269
|
+
END_BATCH="$total"
|
|
270
|
+
fi
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
# --- Banner ---
|
|
274
|
+
print_banner() {
|
|
275
|
+
local total
|
|
276
|
+
total=$(count_batches "$PLAN_FILE")
|
|
277
|
+
local plan_display
|
|
278
|
+
plan_display=$(basename "$PLAN_FILE")
|
|
279
|
+
|
|
280
|
+
cat <<BANNER
|
|
281
|
+
╔══════════════════════════════════════════════════════╗
|
|
282
|
+
║ run-plan — $MODE mode
|
|
283
|
+
║ Plan: $plan_display
|
|
284
|
+
║ Batches: $START_BATCH → $END_BATCH (of $total)
|
|
285
|
+
║ Worktree: $WORKTREE
|
|
286
|
+
╚══════════════════════════════════════════════════════╝
|
|
287
|
+
BANNER
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
# --- Mode stubs ---
|
|
291
|
+
run_mode_competitive() {
|
|
292
|
+
echo "Competitive mode requires a Claude session with agent teams enabled."
|
|
293
|
+
echo ""
|
|
294
|
+
echo "Launch command:"
|
|
295
|
+
echo " CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 claude -p \"/run-plan $PLAN_FILE --mode competitive --start-batch $START_BATCH --end-batch $END_BATCH --worktree $WORKTREE\" --allowedTools '*' --permission-mode bypassPermissions"
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
# --- Main ---
|
|
299
|
+
main() {
|
|
300
|
+
parse_args "$@"
|
|
301
|
+
validate_args
|
|
302
|
+
print_banner
|
|
303
|
+
|
|
304
|
+
# Plan quality gate (skip on resume or explicit flag)
|
|
305
|
+
if [[ "$SKIP_PLAN_QUALITY" != true && "$RESUME" != true ]]; then
|
|
306
|
+
echo ""
|
|
307
|
+
echo "Running plan quality check..."
|
|
308
|
+
if ! bash "$SCRIPT_DIR/validate-plan-quality.sh" "$PLAN_FILE" --min-score 60; then
|
|
309
|
+
echo ""
|
|
310
|
+
echo "Plan quality below threshold. Use --skip-plan-quality to override."
|
|
311
|
+
exit 1
|
|
312
|
+
fi
|
|
313
|
+
echo ""
|
|
314
|
+
fi
|
|
315
|
+
|
|
316
|
+
case "$MODE" in
|
|
317
|
+
headless)
|
|
318
|
+
run_mode_headless
|
|
319
|
+
;;
|
|
320
|
+
team)
|
|
321
|
+
run_mode_team
|
|
322
|
+
;;
|
|
323
|
+
competitive)
|
|
324
|
+
run_mode_competitive
|
|
325
|
+
;;
|
|
326
|
+
esac
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
main "$@"
|