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,142 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# run-plan-state.sh — Track batch progress in a JSON state file
|
|
3
|
+
#
|
|
4
|
+
# State file: <worktree>/.run-plan-state.json
|
|
5
|
+
# Requires: jq
|
|
6
|
+
#
|
|
7
|
+
# Functions:
|
|
8
|
+
# init_state <worktree> <plan_file> <mode> -> create state file
|
|
9
|
+
# read_state_field <worktree> <field> -> read top-level field
|
|
10
|
+
# complete_batch <worktree> <batch_num> <test_count> [duration] -> mark batch done
|
|
11
|
+
# get_previous_test_count <worktree> -> last completed batch's test count (0 if none, -1 if missing)
|
|
12
|
+
# set_quality_gate <worktree> <batch_num> <passed> <test_count> -> record quality gate result
|
|
13
|
+
|
|
14
|
+
_state_file() {
|
|
15
|
+
echo "$1/.run-plan-state.json"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
init_state() {
|
|
19
|
+
local worktree="$1" plan_file="$2" mode="$3"
|
|
20
|
+
local sf
|
|
21
|
+
sf=$(_state_file "$worktree")
|
|
22
|
+
local now
|
|
23
|
+
now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
24
|
+
|
|
25
|
+
jq -n \
|
|
26
|
+
--arg plan_file "$plan_file" \
|
|
27
|
+
--arg mode "$mode" \
|
|
28
|
+
--arg started_at "$now" \
|
|
29
|
+
'{
|
|
30
|
+
plan_file: $plan_file,
|
|
31
|
+
mode: $mode,
|
|
32
|
+
current_batch: 1,
|
|
33
|
+
completed_batches: [],
|
|
34
|
+
test_counts: {},
|
|
35
|
+
durations: {},
|
|
36
|
+
costs: {},
|
|
37
|
+
total_cost_usd: 0,
|
|
38
|
+
started_at: $started_at,
|
|
39
|
+
last_quality_gate: null
|
|
40
|
+
}' > "$sf"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
read_state_field() {
|
|
44
|
+
local worktree="$1" field="$2"
|
|
45
|
+
local sf
|
|
46
|
+
sf=$(_state_file "$worktree")
|
|
47
|
+
jq -c -r --arg f "$field" '.[$f]' "$sf"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
complete_batch() {
|
|
51
|
+
local worktree="$1" batch_num="$2" test_count="$3" duration="${4:-0}"
|
|
52
|
+
local sf tmp
|
|
53
|
+
sf=$(_state_file "$worktree")
|
|
54
|
+
tmp=$(mktemp)
|
|
55
|
+
|
|
56
|
+
# batch_num may be non-numeric (e.g. 'final'), so use --arg and convert in jq.
|
|
57
|
+
# current_batch is only meaningful for numeric batch sequences — it tracks
|
|
58
|
+
# the next expected numeric batch. Non-numeric batches (like 'final') are
|
|
59
|
+
# recorded in completed_batches and test_counts but do not advance current_batch.
|
|
60
|
+
if [[ "$batch_num" =~ ^[0-9]+$ ]]; then
|
|
61
|
+
jq \
|
|
62
|
+
--argjson batch "$batch_num" \
|
|
63
|
+
--argjson tc "$test_count" \
|
|
64
|
+
--argjson dur "$duration" \
|
|
65
|
+
'
|
|
66
|
+
.completed_batches += [$batch] |
|
|
67
|
+
.current_batch = ($batch + 1) |
|
|
68
|
+
.test_counts[($batch | tostring)] = $tc |
|
|
69
|
+
.durations[($batch | tostring)] = $dur
|
|
70
|
+
' "$sf" > "$tmp" && mv "$tmp" "$sf"
|
|
71
|
+
else
|
|
72
|
+
jq \
|
|
73
|
+
--arg batch "$batch_num" \
|
|
74
|
+
--argjson tc "$test_count" \
|
|
75
|
+
--argjson dur "$duration" \
|
|
76
|
+
'
|
|
77
|
+
.completed_batches += [$batch] |
|
|
78
|
+
.test_counts[$batch] = $tc |
|
|
79
|
+
.durations[$batch] = $dur
|
|
80
|
+
' "$sf" > "$tmp" && mv "$tmp" "$sf"
|
|
81
|
+
fi
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
get_previous_test_count() {
|
|
85
|
+
local worktree="$1"
|
|
86
|
+
local sf
|
|
87
|
+
sf=$(_state_file "$worktree")
|
|
88
|
+
|
|
89
|
+
jq -r '
|
|
90
|
+
if (.completed_batches | length) == 0 then "0"
|
|
91
|
+
else (.test_counts[(.completed_batches | last | tostring)] // -1) | tostring
|
|
92
|
+
end
|
|
93
|
+
' "$sf"
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
set_quality_gate() {
|
|
97
|
+
local worktree="$1" batch_num="$2" passed="$3" test_count="$4"
|
|
98
|
+
local sf tmp now
|
|
99
|
+
sf=$(_state_file "$worktree")
|
|
100
|
+
tmp=$(mktemp)
|
|
101
|
+
now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
102
|
+
|
|
103
|
+
# Normalize passed to a JSON boolean so --argjson never receives an
|
|
104
|
+
# unexpected value (#8). Callers pass "true"/"false" conventionally, but
|
|
105
|
+
# "1"/"0" or "yes"/"no" would crash jq with --argjson.
|
|
106
|
+
if [[ "$passed" == "true" || "$passed" == "1" || "$passed" == "yes" ]]; then
|
|
107
|
+
passed="true"
|
|
108
|
+
else
|
|
109
|
+
passed="false"
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
# batch_num may be non-numeric (e.g. 'final'), so use --arg and convert in jq
|
|
113
|
+
if [[ "$batch_num" =~ ^[0-9]+$ ]]; then
|
|
114
|
+
jq \
|
|
115
|
+
--argjson batch "$batch_num" \
|
|
116
|
+
--argjson passed "$passed" \
|
|
117
|
+
--argjson tc "$test_count" \
|
|
118
|
+
--arg ts "$now" \
|
|
119
|
+
'
|
|
120
|
+
.last_quality_gate = {
|
|
121
|
+
batch: $batch,
|
|
122
|
+
passed: $passed,
|
|
123
|
+
test_count: $tc,
|
|
124
|
+
timestamp: $ts
|
|
125
|
+
}
|
|
126
|
+
' "$sf" > "$tmp" && mv "$tmp" "$sf"
|
|
127
|
+
else
|
|
128
|
+
jq \
|
|
129
|
+
--arg batch "$batch_num" \
|
|
130
|
+
--argjson passed "$passed" \
|
|
131
|
+
--argjson tc "$test_count" \
|
|
132
|
+
--arg ts "$now" \
|
|
133
|
+
'
|
|
134
|
+
.last_quality_gate = {
|
|
135
|
+
batch: $batch,
|
|
136
|
+
passed: $passed,
|
|
137
|
+
test_count: $tc,
|
|
138
|
+
timestamp: $ts
|
|
139
|
+
}
|
|
140
|
+
' "$sf" > "$tmp" && mv "$tmp" "$sf"
|
|
141
|
+
fi
|
|
142
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# run-plan-team.sh — Team mode execution with parallel batch groups
|
|
3
|
+
#
|
|
4
|
+
# Analyzes plan dependency graph and executes batches in parallel groups.
|
|
5
|
+
# Each group's batches have all dependencies satisfied by prior groups.
|
|
6
|
+
# Headless version uses parallel `claude -p` processes.
|
|
7
|
+
#
|
|
8
|
+
# Requires sourced: run-plan-parser.sh, run-plan-routing.sh, run-plan-prompt.sh,
|
|
9
|
+
# run-plan-quality-gate.sh, run-plan-state.sh, run-plan-context.sh, run-plan-scoring.sh
|
|
10
|
+
#
|
|
11
|
+
# Functions:
|
|
12
|
+
# compute_parallel_groups <dep_graph_json> <start_batch> <end_batch> -> JSON [[1],[2,3],[4]]
|
|
13
|
+
# run_mode_team (uses globals: PLAN_FILE, WORKTREE, etc.)
|
|
14
|
+
|
|
15
|
+
# --- Compute parallel execution groups from dependency graph ---
|
|
16
|
+
# Takes a JSON dependency graph and batch range, returns JSON array of arrays.
|
|
17
|
+
# Each inner array is a group of batches that can run in parallel.
|
|
18
|
+
compute_parallel_groups() {
|
|
19
|
+
local dep_graph="$1" start_batch="$2" end_batch="$3"
|
|
20
|
+
|
|
21
|
+
# Collect all batch numbers in range
|
|
22
|
+
local batches=()
|
|
23
|
+
for ((b = start_batch; b <= end_batch; b++)); do
|
|
24
|
+
batches+=("$b")
|
|
25
|
+
done
|
|
26
|
+
|
|
27
|
+
local completed=""
|
|
28
|
+
local groups="["
|
|
29
|
+
local first_group=true
|
|
30
|
+
local remaining=${#batches[@]}
|
|
31
|
+
|
|
32
|
+
while [[ "$remaining" -gt 0 ]]; do
|
|
33
|
+
local group="["
|
|
34
|
+
local first_in_group=true
|
|
35
|
+
local new_completed=""
|
|
36
|
+
local group_size=0
|
|
37
|
+
|
|
38
|
+
for b in "${batches[@]}"; do
|
|
39
|
+
# Skip already completed
|
|
40
|
+
[[ "$completed" == *"|$b|"* ]] && continue
|
|
41
|
+
|
|
42
|
+
# Check if all deps are satisfied (completed or outside range)
|
|
43
|
+
local deps
|
|
44
|
+
deps=$(echo "$dep_graph" | jq -r ".\"$b\"[]" 2>/dev/null || true)
|
|
45
|
+
local all_met=true
|
|
46
|
+
while IFS= read -r dep; do
|
|
47
|
+
[[ -z "$dep" ]] && continue
|
|
48
|
+
local dep_num=$((dep + 0))
|
|
49
|
+
# Deps outside our batch range are treated as satisfied
|
|
50
|
+
if [[ "$dep_num" -ge "$start_batch" && "$dep_num" -le "$end_batch" ]]; then
|
|
51
|
+
if [[ "$completed" != *"|$dep|"* ]]; then
|
|
52
|
+
all_met=false
|
|
53
|
+
break
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
done <<< "$deps"
|
|
57
|
+
|
|
58
|
+
if [[ "$all_met" == true ]]; then
|
|
59
|
+
[[ "$first_in_group" != true ]] && group+=","
|
|
60
|
+
group+="$b"
|
|
61
|
+
first_in_group=false
|
|
62
|
+
new_completed+="|$b|"
|
|
63
|
+
group_size=$((group_size + 1))
|
|
64
|
+
remaining=$((remaining - 1))
|
|
65
|
+
fi
|
|
66
|
+
done
|
|
67
|
+
|
|
68
|
+
group+="]"
|
|
69
|
+
completed+="$new_completed"
|
|
70
|
+
|
|
71
|
+
if [[ "$group_size" -gt 0 ]]; then
|
|
72
|
+
[[ "$first_group" != true ]] && groups+=","
|
|
73
|
+
groups+="$group"
|
|
74
|
+
first_group=false
|
|
75
|
+
else
|
|
76
|
+
break # No progress — circular dependency or error
|
|
77
|
+
fi
|
|
78
|
+
done
|
|
79
|
+
|
|
80
|
+
groups+="]"
|
|
81
|
+
echo "$groups"
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# --- Team mode execution (headless parallel) ---
|
|
85
|
+
run_mode_team() {
|
|
86
|
+
# WARNING: Team mode uses a shared worktree. Concurrent git operations
|
|
87
|
+
# (add, commit, stash) from parallel claude processes may conflict and
|
|
88
|
+
# corrupt the staging area. Each batch in a group runs against the same
|
|
89
|
+
# filesystem; the batches within a group are independent by design
|
|
90
|
+
# (no shared files per the dependency graph), but git state is global.
|
|
91
|
+
# For full isolation, run batches sequentially (headless mode) or ensure
|
|
92
|
+
# batches in each parallel group touch strictly non-overlapping files.
|
|
93
|
+
echo "WARNING: Team mode uses a shared worktree. Concurrent git operations may conflict." >&2
|
|
94
|
+
|
|
95
|
+
local dep_graph
|
|
96
|
+
dep_graph=$(build_dependency_graph "$PLAN_FILE")
|
|
97
|
+
|
|
98
|
+
local groups
|
|
99
|
+
groups=$(compute_parallel_groups "$dep_graph" "$START_BATCH" "$END_BATCH")
|
|
100
|
+
local group_count
|
|
101
|
+
group_count=$(echo "$groups" | jq 'length')
|
|
102
|
+
|
|
103
|
+
mkdir -p "$WORKTREE/logs"
|
|
104
|
+
|
|
105
|
+
# Initialize state if not resuming
|
|
106
|
+
if [[ "$RESUME" != true ]]; then
|
|
107
|
+
init_state "$WORKTREE" "$PLAN_FILE" "$MODE"
|
|
108
|
+
if [[ "$START_BATCH" -gt 1 ]]; then
|
|
109
|
+
for ((b = 1; b < START_BATCH; b++)); do
|
|
110
|
+
complete_batch "$WORKTREE" "$b" 0
|
|
111
|
+
done
|
|
112
|
+
fi
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
log_routing_decision "$WORKTREE" "MODE" "team mode selected ($group_count groups)"
|
|
116
|
+
|
|
117
|
+
for ((g = 0; g < group_count; g++)); do
|
|
118
|
+
local group_batches
|
|
119
|
+
group_batches=$(echo "$groups" | jq -r ".[$g][]")
|
|
120
|
+
local batch_count
|
|
121
|
+
batch_count=$(echo "$group_batches" | wc -l)
|
|
122
|
+
|
|
123
|
+
echo ""
|
|
124
|
+
echo "================================================================"
|
|
125
|
+
echo " Group $((g+1))/$group_count: batches $(echo "$group_batches" | tr '\n' ',' | sed 's/,$//')"
|
|
126
|
+
echo " ($batch_count batches in parallel)"
|
|
127
|
+
echo "================================================================"
|
|
128
|
+
|
|
129
|
+
local pids=()
|
|
130
|
+
local batch_logs=()
|
|
131
|
+
local batch_list=()
|
|
132
|
+
|
|
133
|
+
for batch in $group_batches; do
|
|
134
|
+
local title
|
|
135
|
+
title=$(get_batch_title "$PLAN_FILE" "$batch")
|
|
136
|
+
local model
|
|
137
|
+
model=$(classify_batch_model "$PLAN_FILE" "$batch")
|
|
138
|
+
local log_file="$WORKTREE/logs/batch-${batch}-team.log"
|
|
139
|
+
batch_logs+=("$log_file")
|
|
140
|
+
batch_list+=("$batch")
|
|
141
|
+
|
|
142
|
+
local prev_test_count
|
|
143
|
+
prev_test_count=$(get_previous_test_count "$WORKTREE")
|
|
144
|
+
|
|
145
|
+
local prompt
|
|
146
|
+
prompt=$(build_batch_prompt "$PLAN_FILE" "$batch" "$WORKTREE" "$PYTHON" "$QUALITY_GATE_CMD" "$prev_test_count")
|
|
147
|
+
|
|
148
|
+
log_routing_decision "$WORKTREE" "PARALLEL" "batch $batch ($title) [$model] in group $((g+1))"
|
|
149
|
+
|
|
150
|
+
echo " Starting batch $batch: $title ($model)..."
|
|
151
|
+
CLAUDECODE='' claude -p "$prompt" \
|
|
152
|
+
--model "$model" \
|
|
153
|
+
--allowedTools "Bash,Read,Write,Edit,Grep,Glob" \
|
|
154
|
+
--permission-mode bypassPermissions \
|
|
155
|
+
> "$log_file" 2>&1 &
|
|
156
|
+
pids+=($!)
|
|
157
|
+
done
|
|
158
|
+
|
|
159
|
+
# Wait for all batches in group
|
|
160
|
+
local all_passed=true
|
|
161
|
+
for i in "${!pids[@]}"; do
|
|
162
|
+
local pid=${pids[$i]}
|
|
163
|
+
local batch=${batch_list[$i]}
|
|
164
|
+
wait "$pid" || true
|
|
165
|
+
|
|
166
|
+
# Run quality gate
|
|
167
|
+
local gate_exit=0
|
|
168
|
+
run_quality_gate "$WORKTREE" "$QUALITY_GATE_CMD" "$batch" "0" || gate_exit=$?
|
|
169
|
+
if [[ $gate_exit -eq 0 ]]; then
|
|
170
|
+
echo " Batch $batch PASSED"
|
|
171
|
+
log_routing_decision "$WORKTREE" "GATE_PASS" "batch $batch passed quality gate"
|
|
172
|
+
else
|
|
173
|
+
echo " Batch $batch FAILED quality gate"
|
|
174
|
+
log_routing_decision "$WORKTREE" "GATE_FAIL" "batch $batch failed quality gate"
|
|
175
|
+
all_passed=false
|
|
176
|
+
fi
|
|
177
|
+
done
|
|
178
|
+
|
|
179
|
+
if [[ "$all_passed" != true ]]; then
|
|
180
|
+
echo ""
|
|
181
|
+
echo "Group $((g+1)) had failures. Stopping."
|
|
182
|
+
exit 1
|
|
183
|
+
fi
|
|
184
|
+
done
|
|
185
|
+
|
|
186
|
+
echo ""
|
|
187
|
+
echo "================================================================"
|
|
188
|
+
echo " All groups complete ($group_count groups, batches $START_BATCH → $END_BATCH)"
|
|
189
|
+
echo "================================================================"
|
|
190
|
+
|
|
191
|
+
if [[ "$VERIFY" == true ]]; then
|
|
192
|
+
echo ""
|
|
193
|
+
echo "Running final verification..."
|
|
194
|
+
run_quality_gate "$WORKTREE" "$QUALITY_GATE_CMD" "final" || {
|
|
195
|
+
echo "FINAL VERIFICATION FAILED"
|
|
196
|
+
exit 1
|
|
197
|
+
}
|
|
198
|
+
fi
|
|
199
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# telegram.sh — Shared Telegram notification helpers
|
|
3
|
+
#
|
|
4
|
+
# Functions:
|
|
5
|
+
# _load_telegram_env [env_file] -> load TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID
|
|
6
|
+
# _send_telegram <message> -> send via Telegram Bot API
|
|
7
|
+
|
|
8
|
+
_load_telegram_env() {
|
|
9
|
+
local env_file="${1:-${ACT_ENV_FILE:-$HOME/.env}}"
|
|
10
|
+
|
|
11
|
+
if [[ ! -f "$env_file" ]]; then
|
|
12
|
+
echo "WARNING: env file not found: $env_file" >&2
|
|
13
|
+
return 1
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
# Extract values and strip surrounding single or double quotes (#7).
|
|
17
|
+
# .env files may store values as TELEGRAM_BOT_TOKEN="abc123" or
|
|
18
|
+
# TELEGRAM_BOT_TOKEN='abc123' — the cut captures the raw quoted string.
|
|
19
|
+
TELEGRAM_BOT_TOKEN=$(grep -E '^(export )?TELEGRAM_BOT_TOKEN=' "$env_file" | head -1 | sed 's/^export //' | cut -d= -f2- | sed "s/^['\"]//; s/['\"]$//")
|
|
20
|
+
TELEGRAM_CHAT_ID=$(grep -E '^(export )?TELEGRAM_CHAT_ID=' "$env_file" | head -1 | sed 's/^export //' | cut -d= -f2- | sed "s/^['\"]//; s/['\"]$//")
|
|
21
|
+
|
|
22
|
+
if [[ -z "${TELEGRAM_BOT_TOKEN:-}" || -z "${TELEGRAM_CHAT_ID:-}" ]]; then
|
|
23
|
+
echo "WARNING: TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID not found in $env_file" >&2
|
|
24
|
+
return 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
export TELEGRAM_BOT_TOKEN TELEGRAM_CHAT_ID
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
_send_telegram() {
|
|
31
|
+
local message="$1"
|
|
32
|
+
|
|
33
|
+
if [[ -z "${TELEGRAM_BOT_TOKEN:-}" || -z "${TELEGRAM_CHAT_ID:-}" ]]; then
|
|
34
|
+
echo "WARNING: Telegram credentials not set — skipping notification" >&2
|
|
35
|
+
return 0
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
local url="https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage"
|
|
39
|
+
|
|
40
|
+
local http_code
|
|
41
|
+
http_code=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$url" \
|
|
42
|
+
-d chat_id="$TELEGRAM_CHAT_ID" \
|
|
43
|
+
-d text="$message" \
|
|
44
|
+
-d parse_mode="Markdown" \
|
|
45
|
+
--max-time 10 2>/dev/null) || {
|
|
46
|
+
echo "WARNING: Failed to send Telegram notification (curl error)" >&2
|
|
47
|
+
return 1
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if [[ "$http_code" != "200" ]]; then
|
|
51
|
+
echo "WARNING: Telegram API returned HTTP $http_code" >&2
|
|
52
|
+
return 1
|
|
53
|
+
fi
|
|
54
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# thompson-sampling.sh — Thompson Sampling for MAB strategy routing
|
|
3
|
+
#
|
|
4
|
+
# Functions:
|
|
5
|
+
# thompson_sample <wins> <losses> — Beta approximation, returns float [0,1]
|
|
6
|
+
# thompson_route <batch_type> <perf_file> — Returns "superpowers"|"ralph"|"mab"
|
|
7
|
+
# init_strategy_perf <file> — Creates JSON with 4 batch types + calibration
|
|
8
|
+
# update_strategy_perf <file> <batch_type> <winner_strategy> — Increments counters
|
|
9
|
+
#
|
|
10
|
+
# Routing logic:
|
|
11
|
+
# - Missing file or < 5 points per strategy → "mab" (compete)
|
|
12
|
+
# - integration batch type → always "mab" (most variable)
|
|
13
|
+
# - Win rate spread < 15% → "mab" (too close to call)
|
|
14
|
+
# - Clear winner (≥70%, 10+ points) → return strategy name
|
|
15
|
+
# - Otherwise → Thompson sample both, return higher sample
|
|
16
|
+
|
|
17
|
+
# Thompson sample from Beta(alpha, beta) using Box-Muller approximation.
|
|
18
|
+
# For Beta(a,b) with a,b > 1, a good approximation is:
|
|
19
|
+
# mean = a/(a+b), variance = ab/((a+b)^2*(a+b+1))
|
|
20
|
+
# sample ≈ mean + sqrt(variance) * normal_noise
|
|
21
|
+
# Clamped to [0.01, 0.99] to avoid degenerate values.
|
|
22
|
+
#
|
|
23
|
+
# Args: <wins> <losses>
|
|
24
|
+
# Output: float in [0,1]
|
|
25
|
+
thompson_sample() {
|
|
26
|
+
local wins="${1:-0}" losses="${2:-0}"
|
|
27
|
+
local alpha=$((wins + 1))
|
|
28
|
+
local beta=$((losses + 1))
|
|
29
|
+
|
|
30
|
+
# Use central limit theorem for a pseudo-normal: sum 12 uniform [0,1), subtract 6 → approx N(0,1).
|
|
31
|
+
# Seed with bash $RANDOM + PID — PROCINFO["pid"] is gawk-only, mawk silently ignores it,
|
|
32
|
+
# producing identical samples within the same second (kills Thompson Sampling).
|
|
33
|
+
local noise
|
|
34
|
+
noise=$(awk -v seed="$((RANDOM + $$))" 'BEGIN {
|
|
35
|
+
srand(systime() * 1000 + seed);
|
|
36
|
+
s = 0;
|
|
37
|
+
for (i = 0; i < 12; i++) s += rand();
|
|
38
|
+
printf "%.6f", s - 6;
|
|
39
|
+
}' 2>/dev/null || echo "0")
|
|
40
|
+
|
|
41
|
+
# Compute Beta sample approximation
|
|
42
|
+
bc -l <<EOF
|
|
43
|
+
scale=6
|
|
44
|
+
a = $alpha
|
|
45
|
+
b = $beta
|
|
46
|
+
mean = a / (a + b)
|
|
47
|
+
var = (a * b) / ((a + b) * (a + b) * (a + b + 1))
|
|
48
|
+
sd = sqrt(var)
|
|
49
|
+
sample = mean + sd * $noise
|
|
50
|
+
if (sample < 0.01) sample = 0.01
|
|
51
|
+
if (sample > 0.99) sample = 0.99
|
|
52
|
+
sample
|
|
53
|
+
EOF
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# Route a batch type to a strategy or "mab" (compete).
|
|
57
|
+
#
|
|
58
|
+
# Args: <batch_type> <perf_file>
|
|
59
|
+
# Output: "superpowers" | "ralph" | "mab"
|
|
60
|
+
thompson_route() {
|
|
61
|
+
local batch_type="$1"
|
|
62
|
+
local perf_file="$2"
|
|
63
|
+
|
|
64
|
+
# Missing file → compete
|
|
65
|
+
if [[ ! -f "$perf_file" ]]; then
|
|
66
|
+
echo "mab"
|
|
67
|
+
return
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# Integration → always compete (most variable)
|
|
71
|
+
if [[ "$batch_type" == "integration" ]]; then
|
|
72
|
+
echo "mab"
|
|
73
|
+
return
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# Read strategy data
|
|
77
|
+
local sp_wins sp_losses ralph_wins ralph_losses
|
|
78
|
+
sp_wins=$(jq -r --arg bt "$batch_type" '.[$bt].superpowers.wins // 0' "$perf_file" 2>/dev/null || echo "0")
|
|
79
|
+
sp_losses=$(jq -r --arg bt "$batch_type" '.[$bt].superpowers.losses // 0' "$perf_file" 2>/dev/null || echo "0")
|
|
80
|
+
ralph_wins=$(jq -r --arg bt "$batch_type" '.[$bt].ralph.wins // 0' "$perf_file" 2>/dev/null || echo "0")
|
|
81
|
+
ralph_losses=$(jq -r --arg bt "$batch_type" '.[$bt].ralph.losses // 0' "$perf_file" 2>/dev/null || echo "0")
|
|
82
|
+
|
|
83
|
+
local sp_total=$((sp_wins + sp_losses))
|
|
84
|
+
local ralph_total=$((ralph_wins + ralph_losses))
|
|
85
|
+
|
|
86
|
+
# < 5 data points per strategy → compete
|
|
87
|
+
if [[ "$sp_total" -lt 5 || "$ralph_total" -lt 5 ]]; then
|
|
88
|
+
echo "mab"
|
|
89
|
+
return
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# Compute win rates
|
|
93
|
+
local sp_rate ralph_rate spread
|
|
94
|
+
sp_rate=$(echo "scale=2; $sp_wins * 100 / $sp_total" | bc -l)
|
|
95
|
+
ralph_rate=$(echo "scale=2; $ralph_wins * 100 / $ralph_total" | bc -l)
|
|
96
|
+
|
|
97
|
+
# Spread check (< 15% → too close)
|
|
98
|
+
spread=$(echo "scale=2; x=$sp_rate - $ralph_rate; if (x < 0) -x else x" | bc -l)
|
|
99
|
+
local spread_too_close
|
|
100
|
+
spread_too_close=$(echo "$spread < 15" | bc -l)
|
|
101
|
+
if [[ "$spread_too_close" == "1" ]]; then
|
|
102
|
+
echo "mab"
|
|
103
|
+
return
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# Clear winner check (≥70%, 10+ points)
|
|
107
|
+
local sp_clear ralph_clear
|
|
108
|
+
sp_clear=$(echo "$sp_rate >= 70" | bc -l)
|
|
109
|
+
ralph_clear=$(echo "$ralph_rate >= 70" | bc -l)
|
|
110
|
+
|
|
111
|
+
if [[ "$sp_clear" == "1" && "$sp_total" -ge 10 ]]; then
|
|
112
|
+
echo "superpowers"
|
|
113
|
+
return
|
|
114
|
+
fi
|
|
115
|
+
if [[ "$ralph_clear" == "1" && "$ralph_total" -ge 10 ]]; then
|
|
116
|
+
echo "ralph"
|
|
117
|
+
return
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# Thompson sample both — higher sample wins
|
|
121
|
+
local sp_sample ralph_sample
|
|
122
|
+
sp_sample=$(thompson_sample "$sp_wins" "$sp_losses")
|
|
123
|
+
ralph_sample=$(thompson_sample "$ralph_wins" "$ralph_losses")
|
|
124
|
+
|
|
125
|
+
local sp_higher
|
|
126
|
+
sp_higher=$(echo "$sp_sample > $ralph_sample" | bc -l)
|
|
127
|
+
if [[ "$sp_higher" == "1" ]]; then
|
|
128
|
+
echo "superpowers"
|
|
129
|
+
else
|
|
130
|
+
echo "ralph"
|
|
131
|
+
fi
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
# Initialize strategy performance file with zero counters.
|
|
135
|
+
#
|
|
136
|
+
# Args: <file>
|
|
137
|
+
init_strategy_perf() {
|
|
138
|
+
local file="$1"
|
|
139
|
+
mkdir -p "$(dirname "$file")"
|
|
140
|
+
cat > "$file" <<'JSON'
|
|
141
|
+
{
|
|
142
|
+
"new-file": {"superpowers": {"wins": 0, "losses": 0}, "ralph": {"wins": 0, "losses": 0}},
|
|
143
|
+
"refactoring": {"superpowers": {"wins": 0, "losses": 0}, "ralph": {"wins": 0, "losses": 0}},
|
|
144
|
+
"integration": {"superpowers": {"wins": 0, "losses": 0}, "ralph": {"wins": 0, "losses": 0}},
|
|
145
|
+
"test-only": {"superpowers": {"wins": 0, "losses": 0}, "ralph": {"wins": 0, "losses": 0}},
|
|
146
|
+
"calibration_count": 0,
|
|
147
|
+
"calibration_complete": false
|
|
148
|
+
}
|
|
149
|
+
JSON
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
# Update strategy performance after a MAB run.
|
|
153
|
+
# Winner gets +1 win, loser gets +1 loss.
|
|
154
|
+
#
|
|
155
|
+
# Args: <file> <batch_type> <winner_strategy>
|
|
156
|
+
update_strategy_perf() {
|
|
157
|
+
local file="$1" batch_type="$2" winner="$3"
|
|
158
|
+
|
|
159
|
+
if [[ ! -f "$file" ]]; then
|
|
160
|
+
init_strategy_perf "$file"
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
local loser
|
|
164
|
+
if [[ "$winner" == "superpowers" ]]; then
|
|
165
|
+
loser="ralph"
|
|
166
|
+
else
|
|
167
|
+
loser="superpowers"
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
local tmp
|
|
171
|
+
tmp=$(mktemp)
|
|
172
|
+
jq --arg bt "$batch_type" --arg w "$winner" --arg l "$loser" '
|
|
173
|
+
.[$bt][$w].wins += 1 |
|
|
174
|
+
.[$bt][$l].losses += 1
|
|
175
|
+
' "$file" > "$tmp" && mv "$tmp" "$file"
|
|
176
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# license-check.sh — Check dependencies for license compatibility
|
|
3
|
+
#
|
|
4
|
+
# Usage: license-check.sh [--project-root <dir>]
|
|
5
|
+
# Flags GPL/AGPL in MIT-licensed projects.
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
source "$SCRIPT_DIR/lib/common.sh"
|
|
10
|
+
|
|
11
|
+
PROJECT_ROOT="."
|
|
12
|
+
|
|
13
|
+
while [[ $# -gt 0 ]]; do
|
|
14
|
+
case "$1" in
|
|
15
|
+
--project-root) PROJECT_ROOT="$2"; shift 2 ;;
|
|
16
|
+
-h|--help)
|
|
17
|
+
echo "license-check.sh — Check dependency licenses"
|
|
18
|
+
echo "Usage: license-check.sh [--project-root <dir>]"
|
|
19
|
+
echo "Flags GPL/AGPL in MIT-licensed projects."
|
|
20
|
+
exit 0 ;;
|
|
21
|
+
*) echo "Unknown: $1" >&2; exit 1 ;;
|
|
22
|
+
esac
|
|
23
|
+
done
|
|
24
|
+
|
|
25
|
+
cd "$PROJECT_ROOT"
|
|
26
|
+
project_type=$(detect_project_type ".")
|
|
27
|
+
|
|
28
|
+
echo "=== License Check ==="
|
|
29
|
+
violations=0
|
|
30
|
+
|
|
31
|
+
case "$project_type" in
|
|
32
|
+
python)
|
|
33
|
+
if [[ -d ".venv" ]] && command -v pip-licenses >/dev/null 2>&1; then
|
|
34
|
+
echo "Checking Python dependencies..."
|
|
35
|
+
gpl_deps=$(.venv/bin/python -m pip-licenses --format=csv 2>/dev/null | grep -iE 'GPL|AGPL' | grep -v 'LGPL' || true)
|
|
36
|
+
if [[ -n "$gpl_deps" ]]; then
|
|
37
|
+
echo "WARNING: GPL/AGPL dependencies found:"
|
|
38
|
+
echo "$gpl_deps" | sed 's/^/ /'
|
|
39
|
+
violations=$((violations + 1))
|
|
40
|
+
else
|
|
41
|
+
echo " No GPL/AGPL dependencies"
|
|
42
|
+
fi
|
|
43
|
+
else
|
|
44
|
+
echo " pip-licenses not available — skipping"
|
|
45
|
+
fi
|
|
46
|
+
;;
|
|
47
|
+
node)
|
|
48
|
+
if command -v npx >/dev/null 2>&1; then
|
|
49
|
+
echo "Checking Node dependencies..."
|
|
50
|
+
gpl_deps=$(npx license-checker --csv 2>/dev/null | grep -iE 'GPL|AGPL' | grep -v 'LGPL' || true)
|
|
51
|
+
if [[ -n "$gpl_deps" ]]; then
|
|
52
|
+
echo "WARNING: GPL/AGPL dependencies found:"
|
|
53
|
+
echo "$gpl_deps" | head -10 | sed 's/^/ /'
|
|
54
|
+
violations=$((violations + 1))
|
|
55
|
+
else
|
|
56
|
+
echo " No GPL/AGPL dependencies"
|
|
57
|
+
fi
|
|
58
|
+
else
|
|
59
|
+
echo " license-checker not available — skipping"
|
|
60
|
+
fi
|
|
61
|
+
;;
|
|
62
|
+
*)
|
|
63
|
+
echo " No license check for project type: $project_type"
|
|
64
|
+
;;
|
|
65
|
+
esac
|
|
66
|
+
|
|
67
|
+
if [[ $violations -gt 0 ]]; then
|
|
68
|
+
echo ""
|
|
69
|
+
echo "license-check: $violations issue(s) found"
|
|
70
|
+
exit 1
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
echo "license-check: CLEAN"
|
|
74
|
+
exit 0
|