prizmkit 1.1.100 → 1.1.102
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/bin/create-prizmkit.js +4 -4
- package/bundled/VERSION.json +3 -3
- package/bundled/dev-pipeline/.env.example +3 -3
- package/bundled/dev-pipeline/README.md +110 -90
- package/bundled/dev-pipeline/assets/prizm-dev-team-integration.md +1 -1
- package/bundled/dev-pipeline/cli.py +27 -0
- package/bundled/dev-pipeline/prizmkit_runtime/__init__.py +13 -0
- package/bundled/dev-pipeline/prizmkit_runtime/__main__.py +9 -0
- package/bundled/dev-pipeline/prizmkit_runtime/cli.py +193 -0
- package/bundled/dev-pipeline/prizmkit_runtime/commands.py +313 -0
- package/bundled/dev-pipeline/prizmkit_runtime/compat.py +32 -0
- package/bundled/dev-pipeline/prizmkit_runtime/config.py +410 -0
- package/bundled/dev-pipeline/prizmkit_runtime/daemon.py +478 -0
- package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +734 -0
- package/bundled/dev-pipeline/prizmkit_runtime/heartbeat.py +256 -0
- package/bundled/dev-pipeline/prizmkit_runtime/interoperability.py +109 -0
- package/bundled/dev-pipeline/prizmkit_runtime/paths.py +110 -0
- package/bundled/dev-pipeline/prizmkit_runtime/processes.py +373 -0
- package/bundled/dev-pipeline/prizmkit_runtime/reset.py +389 -0
- package/bundled/dev-pipeline/prizmkit_runtime/runner_bookkeeping.py +51 -0
- package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +179 -0
- package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +355 -0
- package/bundled/dev-pipeline/prizmkit_runtime/runner_prompts.py +118 -0
- package/bundled/dev-pipeline/prizmkit_runtime/runner_recovery.py +187 -0
- package/bundled/dev-pipeline/prizmkit_runtime/runner_status.py +153 -0
- package/bundled/dev-pipeline/prizmkit_runtime/runners.py +425 -0
- package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +560 -0
- package/bundled/dev-pipeline/prizmkit_runtime/status.py +71 -0
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +51 -36
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +20 -5
- package/bundled/dev-pipeline/scripts/generate-recovery-prompt.py +2 -2
- package/bundled/dev-pipeline/scripts/parse-stream-progress.py +39 -0
- package/bundled/dev-pipeline/templates/agent-prompts/dev-implement.md +8 -2
- package/bundled/dev-pipeline/templates/agent-prompts/reviewer-review.md +1 -1
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +6 -2
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +14 -6
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +14 -4
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +14 -4
- package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +2 -0
- package/bundled/dev-pipeline/templates/sections/log-size-awareness.md +9 -30
- package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-agent-suffix.md +15 -7
- package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +42 -29
- package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +41 -39
- package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +8 -17
- package/bundled/dev-pipeline/templates/sections/phase-prizmkit-test.md +2 -2
- package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +1 -3
- package/bundled/dev-pipeline/templates/sections/phase-review-full.md +1 -3
- package/bundled/dev-pipeline/templates/sections/phase0-test-baseline.md +3 -8
- package/bundled/dev-pipeline/templates/sections/test-failure-recovery-agent.md +6 -2
- package/bundled/dev-pipeline/templates/sections/test-failure-recovery-lite.md +5 -1
- package/bundled/dev-pipeline/tests/test_auto_skip.py +436 -14
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +115 -7
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +40 -0
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +1226 -0
- package/bundled/dev-pipeline/tests/test_unified_cli.py +1045 -0
- package/bundled/skills/_metadata.json +1 -1
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +29 -34
- package/bundled/skills/bugfix-pipeline-launcher/references/configuration.md +6 -5
- package/bundled/skills/feature-pipeline-launcher/SKILL.md +29 -35
- package/bundled/skills/feature-pipeline-launcher/references/configuration.md +7 -6
- package/bundled/skills/feature-workflow/SKILL.md +3 -6
- package/bundled/skills/recovery-workflow/SKILL.md +23 -32
- package/bundled/skills/refactor-pipeline-launcher/SKILL.md +29 -35
- package/bundled/skills/refactor-pipeline-launcher/references/configuration.md +7 -6
- package/bundled/skills/refactor-workflow/SKILL.md +3 -6
- package/bundled/templates/hooks/commit-intent.json +2 -2
- package/bundled/templates/hooks/diff-prizm-docs.py +226 -0
- package/bundled/templates/hooks/prizm-pre-commit.py +45 -0
- package/bundled/templates/hooks/validate-prizm-docs.py +240 -0
- package/package.json +1 -1
- package/src/config.js +42 -19
- package/src/external-skills.js +14 -14
- package/src/index.js +3 -6
- package/src/manifest.js +11 -5
- package/src/metadata.js +7 -18
- package/src/platforms.js +25 -0
- package/src/prompts.js +0 -12
- package/src/runtimes.js +18 -11
- package/src/scaffold.js +144 -122
- package/src/upgrade.js +12 -3
- package/bundled/dev-pipeline/launch-bugfix-daemon.sh +0 -500
- package/bundled/dev-pipeline/launch-feature-daemon.sh +0 -657
- package/bundled/dev-pipeline/launch-refactor-daemon.sh +0 -502
- package/bundled/dev-pipeline/lib/branch.sh +0 -326
- package/bundled/dev-pipeline/lib/common.sh +0 -1476
- package/bundled/dev-pipeline/lib/heartbeat.sh +0 -469
- package/bundled/dev-pipeline/reset-bug.sh +0 -425
- package/bundled/dev-pipeline/reset-feature.sh +0 -436
- package/bundled/dev-pipeline/reset-refactor.sh +0 -423
- package/bundled/dev-pipeline/run-bugfix.sh +0 -1430
- package/bundled/dev-pipeline/run-feature.sh +0 -1718
- package/bundled/dev-pipeline/run-recovery.sh +0 -648
- package/bundled/dev-pipeline/run-refactor.sh +0 -1463
- package/bundled/dev-pipeline/tests/test-path-resolution.sh +0 -100
- package/bundled/dev-pipeline-windows/.env.example +0 -36
- package/bundled/dev-pipeline-windows/README.md +0 -30
- package/bundled/dev-pipeline-windows/SCHEMA_ANALYSIS.md +0 -533
- package/bundled/dev-pipeline-windows/assets/feature-list-example.json +0 -146
- package/bundled/dev-pipeline-windows/assets/prizm-dev-team-integration.md +0 -137
- package/bundled/dev-pipeline-windows/launch-bugfix-daemon.ps1 +0 -9
- package/bundled/dev-pipeline-windows/launch-feature-daemon.ps1 +0 -9
- package/bundled/dev-pipeline-windows/launch-refactor-daemon.ps1 +0 -9
- package/bundled/dev-pipeline-windows/lib/branch.ps1 +0 -235
- package/bundled/dev-pipeline-windows/lib/common.ps1 +0 -991
- package/bundled/dev-pipeline-windows/lib/daemon.ps1 +0 -140
- package/bundled/dev-pipeline-windows/lib/pipeline.ps1 +0 -1051
- package/bundled/dev-pipeline-windows/lib/reset.ps1 +0 -121
- package/bundled/dev-pipeline-windows/reset-bug.ps1 +0 -10
- package/bundled/dev-pipeline-windows/reset-feature.ps1 +0 -10
- package/bundled/dev-pipeline-windows/reset-refactor.ps1 +0 -10
- package/bundled/dev-pipeline-windows/run-bugfix.ps1 +0 -9
- package/bundled/dev-pipeline-windows/run-feature.ps1 +0 -9
- package/bundled/dev-pipeline-windows/run-recovery.ps1 +0 -179
- package/bundled/dev-pipeline-windows/run-refactor.ps1 +0 -9
- package/bundled/dev-pipeline-windows/scripts/check-session-status.py +0 -301
- package/bundled/dev-pipeline-windows/scripts/continuation.py +0 -374
- package/bundled/dev-pipeline-windows/scripts/detect-stuck.py +0 -530
- package/bundled/dev-pipeline-windows/scripts/generate-bootstrap-prompt.py +0 -2279
- package/bundled/dev-pipeline-windows/scripts/generate-bugfix-prompt.py +0 -763
- package/bundled/dev-pipeline-windows/scripts/generate-recovery-prompt.py +0 -805
- package/bundled/dev-pipeline-windows/scripts/generate-refactor-prompt.py +0 -841
- package/bundled/dev-pipeline-windows/scripts/init-bugfix-pipeline.py +0 -316
- package/bundled/dev-pipeline-windows/scripts/init-dev-team.py +0 -134
- package/bundled/dev-pipeline-windows/scripts/init-pipeline.py +0 -382
- package/bundled/dev-pipeline-windows/scripts/init-refactor-pipeline.py +0 -399
- package/bundled/dev-pipeline-windows/scripts/parse-stream-progress.py +0 -1362
- package/bundled/dev-pipeline-windows/scripts/patch-completion-notes.py +0 -191
- package/bundled/dev-pipeline-windows/scripts/prizmkit-test-gate.py +0 -446
- package/bundled/dev-pipeline-windows/scripts/update-bug-status.py +0 -1121
- package/bundled/dev-pipeline-windows/scripts/update-checkpoint.py +0 -173
- package/bundled/dev-pipeline-windows/scripts/update-feature-status.py +0 -1789
- package/bundled/dev-pipeline-windows/scripts/update-refactor-status.py +0 -1327
- package/bundled/dev-pipeline-windows/scripts/utils.py +0 -542
- package/bundled/dev-pipeline-windows/templates/agent-prompts/critic-plan-challenge.md +0 -7
- package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-fix.md +0 -7
- package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-implement.md +0 -65
- package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-resume.md +0 -5
- package/bundled/dev-pipeline-windows/templates/agent-prompts/reviewer-review.md +0 -7
- package/bundled/dev-pipeline-windows/templates/bootstrap-prompt.md +0 -73
- package/bundled/dev-pipeline-windows/templates/bootstrap-tier1.md +0 -589
- package/bundled/dev-pipeline-windows/templates/bootstrap-tier2.md +0 -710
- package/bundled/dev-pipeline-windows/templates/bootstrap-tier3.md +0 -791
- package/bundled/dev-pipeline-windows/templates/bug-fix-list-schema.json +0 -263
- package/bundled/dev-pipeline-windows/templates/bugfix-bootstrap-prompt.md +0 -326
- package/bundled/dev-pipeline-windows/templates/feature-list-schema.json +0 -237
- package/bundled/dev-pipeline-windows/templates/refactor-bootstrap-prompt.md +0 -340
- package/bundled/dev-pipeline-windows/templates/refactor-list-schema.json +0 -270
- package/bundled/dev-pipeline-windows/templates/sections/ac-verification-checklist.md +0 -7
- package/bundled/dev-pipeline-windows/templates/sections/checkpoint-system.md +0 -91
- package/bundled/dev-pipeline-windows/templates/sections/context-budget-rules.md +0 -34
- package/bundled/dev-pipeline-windows/templates/sections/critical-paths-agent.md +0 -10
- package/bundled/dev-pipeline-windows/templates/sections/critical-paths-full.md +0 -12
- package/bundled/dev-pipeline-windows/templates/sections/critical-paths-lite.md +0 -7
- package/bundled/dev-pipeline-windows/templates/sections/directory-convention-agent.md +0 -8
- package/bundled/dev-pipeline-windows/templates/sections/directory-convention-full.md +0 -9
- package/bundled/dev-pipeline-windows/templates/sections/directory-convention-lite.md +0 -6
- package/bundled/dev-pipeline-windows/templates/sections/failure-capture.md +0 -21
- package/bundled/dev-pipeline-windows/templates/sections/feature-context.md +0 -21
- package/bundled/dev-pipeline-windows/templates/sections/log-size-awareness.md +0 -41
- package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-auto.md +0 -283
- package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-opencli.md +0 -112
- package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification.md +0 -168
- package/bundled/dev-pipeline-windows/templates/sections/phase-commit-full.md +0 -82
- package/bundled/dev-pipeline-windows/templates/sections/phase-commit.md +0 -75
- package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-agent-suffix.md +0 -23
- package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-base.md +0 -14
- package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-lite-suffix.md +0 -19
- package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan-full.md +0 -63
- package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan.md +0 -42
- package/bundled/dev-pipeline-windows/templates/sections/phase-implement-agent.md +0 -44
- package/bundled/dev-pipeline-windows/templates/sections/phase-implement-full.md +0 -59
- package/bundled/dev-pipeline-windows/templates/sections/phase-implement-lite.md +0 -39
- package/bundled/dev-pipeline-windows/templates/sections/phase-plan-agent.md +0 -27
- package/bundled/dev-pipeline-windows/templates/sections/phase-plan-lite.md +0 -27
- package/bundled/dev-pipeline-windows/templates/sections/phase-prizmkit-test.md +0 -39
- package/bundled/dev-pipeline-windows/templates/sections/phase-review-agent.md +0 -35
- package/bundled/dev-pipeline-windows/templates/sections/phase-review-full.md +0 -35
- package/bundled/dev-pipeline-windows/templates/sections/phase-specify-plan-full.md +0 -73
- package/bundled/dev-pipeline-windows/templates/sections/phase0-init.md +0 -13
- package/bundled/dev-pipeline-windows/templates/sections/phase0-test-baseline.md +0 -21
- package/bundled/dev-pipeline-windows/templates/sections/session-context.md +0 -5
- package/bundled/dev-pipeline-windows/templates/sections/subagent-timeout-recovery.md +0 -6
- package/bundled/dev-pipeline-windows/templates/sections/task-contract.md +0 -34
- package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-agent.md +0 -48
- package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-lite.md +0 -48
- package/bundled/dev-pipeline-windows/templates/session-status-schema.json +0 -83
- package/bundled/skills-windows/app-planner/SKILL.md +0 -296
- package/bundled/skills-windows/app-planner/assets/app-design-guide.md +0 -101
- package/bundled/skills-windows/app-planner/references/architecture-decisions.md +0 -52
- package/bundled/skills-windows/app-planner/references/brainstorm-guide.md +0 -101
- package/bundled/skills-windows/app-planner/references/frontend-design-guide.md +0 -71
- package/bundled/skills-windows/app-planner/references/infrastructure-convention-discovery.md +0 -108
- package/bundled/skills-windows/app-planner/references/project-brief-guide.md +0 -82
- package/bundled/skills-windows/app-planner/references/project-conventions-discovery.md +0 -59
- package/bundled/skills-windows/app-planner/references/project-state-detection.md +0 -90
- package/bundled/skills-windows/app-planner/references/red-team-checklist.md +0 -40
- package/bundled/skills-windows/app-planner/references/rules/backend/derivation-rules.md +0 -619
- package/bundled/skills-windows/app-planner/references/rules/backend/fixed-rules.md +0 -285
- package/bundled/skills-windows/app-planner/references/rules/backend/question-bank.md +0 -249
- package/bundled/skills-windows/app-planner/references/rules/backend/question-manifest.json +0 -46
- package/bundled/skills-windows/app-planner/references/rules/backend/template.md +0 -173
- package/bundled/skills-windows/app-planner/references/rules/database/derivation-rules.md +0 -382
- package/bundled/skills-windows/app-planner/references/rules/database/fixed-rules.md +0 -211
- package/bundled/skills-windows/app-planner/references/rules/database/question-bank.md +0 -184
- package/bundled/skills-windows/app-planner/references/rules/database/question-manifest.json +0 -39
- package/bundled/skills-windows/app-planner/references/rules/database/template.md +0 -158
- package/bundled/skills-windows/app-planner/references/rules/frontend/derivation-rules.md +0 -820
- package/bundled/skills-windows/app-planner/references/rules/frontend/fixed-rules.md +0 -188
- package/bundled/skills-windows/app-planner/references/rules/frontend/question-bank.md +0 -319
- package/bundled/skills-windows/app-planner/references/rules/frontend/question-manifest.json +0 -51
- package/bundled/skills-windows/app-planner/references/rules/frontend/template.md +0 -339
- package/bundled/skills-windows/app-planner/references/rules/mobile/derivation-rules.md +0 -649
- package/bundled/skills-windows/app-planner/references/rules/mobile/fixed-rules.md +0 -290
- package/bundled/skills-windows/app-planner/references/rules/mobile/question-bank.md +0 -232
- package/bundled/skills-windows/app-planner/references/rules/mobile/question-manifest.json +0 -47
- package/bundled/skills-windows/app-planner/references/rules/mobile/template.md +0 -175
- package/bundled/skills-windows/app-planner/references/rules-configuration.md +0 -46
- package/bundled/skills-windows/bug-fix-workflow/SKILL.md +0 -379
- package/bundled/skills-windows/bug-fix-workflow/references/bug-diagnosis.md +0 -41
- package/bundled/skills-windows/bug-planner/SKILL.md +0 -402
- package/bundled/skills-windows/bug-planner/assets/bug-confirmation-template.md +0 -43
- package/bundled/skills-windows/bug-planner/references/critic-and-verification.md +0 -44
- package/bundled/skills-windows/bug-planner/references/error-recovery.md +0 -73
- package/bundled/skills-windows/bug-planner/references/input-formats.md +0 -53
- package/bundled/skills-windows/bug-planner/references/schema-validation.md +0 -25
- package/bundled/skills-windows/bug-planner/references/severity-rules.md +0 -16
- package/bundled/skills-windows/bug-planner/scripts/validate-bug-list.py +0 -322
- package/bundled/skills-windows/bugfix-pipeline-launcher/SKILL.md +0 -304
- package/bundled/skills-windows/bugfix-pipeline-launcher/references/configuration.md +0 -84
- package/bundled/skills-windows/feature-pipeline-launcher/SKILL.md +0 -381
- package/bundled/skills-windows/feature-pipeline-launcher/references/configuration.md +0 -67
- package/bundled/skills-windows/feature-pipeline-launcher/scripts/preflight-check.py +0 -462
- package/bundled/skills-windows/feature-planner/SKILL.md +0 -397
- package/bundled/skills-windows/feature-planner/assets/evaluation-guide.md +0 -64
- package/bundled/skills-windows/feature-planner/assets/planning-guide.md +0 -214
- package/bundled/skills-windows/feature-planner/references/browser-interaction.md +0 -59
- package/bundled/skills-windows/feature-planner/references/completeness-review.md +0 -57
- package/bundled/skills-windows/feature-planner/references/decomposition-patterns.md +0 -75
- package/bundled/skills-windows/feature-planner/references/error-recovery.md +0 -90
- package/bundled/skills-windows/feature-planner/references/incremental-feature-planning.md +0 -112
- package/bundled/skills-windows/feature-planner/references/new-project-planning.md +0 -85
- package/bundled/skills-windows/feature-planner/scripts/validate-and-generate.py +0 -1020
- package/bundled/skills-windows/feature-workflow/SKILL.md +0 -374
- package/bundled/skills-windows/feature-workflow/references/brainstorm-guide.md +0 -137
- package/bundled/skills-windows/prizm-kit/SKILL.md +0 -93
- package/bundled/skills-windows/prizmkit-code-review/SKILL.md +0 -161
- package/bundled/skills-windows/prizmkit-code-review/references/dev-agent-prompt.md +0 -30
- package/bundled/skills-windows/prizmkit-code-review/references/review-report-template.md +0 -31
- package/bundled/skills-windows/prizmkit-code-review/references/reviewer-agent-prompt.md +0 -66
- package/bundled/skills-windows/prizmkit-code-review/scripts/check_loop.py +0 -186
- package/bundled/skills-windows/prizmkit-committer/SKILL.md +0 -89
- package/bundled/skills-windows/prizmkit-deploy/SKILL.md +0 -444
- package/bundled/skills-windows/prizmkit-deploy/references/ci-cd-workflows.md +0 -115
- package/bundled/skills-windows/prizmkit-deploy/references/cloud-platform-deploy.md +0 -93
- package/bundled/skills-windows/prizmkit-deploy/references/data-safety-examples.md +0 -120
- package/bundled/skills-windows/prizmkit-deploy/references/database-setup.md +0 -46
- package/bundled/skills-windows/prizmkit-deploy/references/deploy-config-schema.md +0 -148
- package/bundled/skills-windows/prizmkit-deploy/references/deploy-history-schema.md +0 -62
- package/bundled/skills-windows/prizmkit-deploy/references/deployment-modes.md +0 -50
- package/bundled/skills-windows/prizmkit-deploy/references/direct-upload.md +0 -26
- package/bundled/skills-windows/prizmkit-deploy/references/dns-setup.md +0 -42
- package/bundled/skills-windows/prizmkit-deploy/references/docker-deploy.md +0 -31
- package/bundled/skills-windows/prizmkit-deploy/references/firewall-setup.md +0 -37
- package/bundled/skills-windows/prizmkit-deploy/references/live-validation-notes.md +0 -21
- package/bundled/skills-windows/prizmkit-deploy/references/nginx-blue-green.md +0 -59
- package/bundled/skills-windows/prizmkit-deploy/references/ssh-bootstrap-flow.md +0 -49
- package/bundled/skills-windows/prizmkit-deploy/references/ssh-execution-flow.md +0 -41
- package/bundled/skills-windows/prizmkit-deploy/references/ssh-takeover.md +0 -20
- package/bundled/skills-windows/prizmkit-deploy/references/ssl-setup.md +0 -56
- package/bundled/skills-windows/prizmkit-implement/SKILL.md +0 -71
- package/bundled/skills-windows/prizmkit-init/SKILL.md +0 -356
- package/bundled/skills-windows/prizmkit-init/assets/project-brief-template.md +0 -82
- package/bundled/skills-windows/prizmkit-init/references/config-schema.md +0 -70
- package/bundled/skills-windows/prizmkit-init/references/rules/layer-detection.md +0 -41
- package/bundled/skills-windows/prizmkit-init/references/tech-stack-catalog.md +0 -13
- package/bundled/skills-windows/prizmkit-init/references/update-supplement.md +0 -9
- package/bundled/skills-windows/prizmkit-plan/SKILL.md +0 -102
- package/bundled/skills-windows/prizmkit-plan/assets/plan-template.md +0 -115
- package/bundled/skills-windows/prizmkit-plan/assets/spec-template.md +0 -73
- package/bundled/skills-windows/prizmkit-plan/references/clarify-guide.md +0 -67
- package/bundled/skills-windows/prizmkit-plan/references/examples.md +0 -85
- package/bundled/skills-windows/prizmkit-plan/references/verification-checklist.md +0 -60
- package/bundled/skills-windows/prizmkit-prizm-docs/SKILL.md +0 -129
- package/bundled/skills-windows/prizmkit-prizm-docs/assets/prizm-docs-format.md +0 -613
- package/bundled/skills-windows/prizmkit-prizm-docs/references/op-init.md +0 -45
- package/bundled/skills-windows/prizmkit-prizm-docs/references/op-rebuild.md +0 -15
- package/bundled/skills-windows/prizmkit-prizm-docs/references/op-status.md +0 -14
- package/bundled/skills-windows/prizmkit-prizm-docs/references/op-update.md +0 -19
- package/bundled/skills-windows/prizmkit-prizm-docs/references/op-validate.md +0 -17
- package/bundled/skills-windows/prizmkit-retrospective/SKILL.md +0 -87
- package/bundled/skills-windows/prizmkit-retrospective/references/knowledge-injection-steps.md +0 -50
- package/bundled/skills-windows/prizmkit-retrospective/references/structural-sync-steps.md +0 -43
- package/bundled/skills-windows/prizmkit-test/SKILL.md +0 -227
- package/bundled/skills-windows/prizmkit-test/references/boundary-coverage-protocol.md +0 -220
- package/bundled/skills-windows/prizmkit-test/references/examples.md +0 -143
- package/bundled/skills-windows/prizmkit-test/references/service-boundary-test-catalog.md +0 -225
- package/bundled/skills-windows/prizmkit-test/references/test-generation-steps.md +0 -109
- package/bundled/skills-windows/prizmkit-test/references/test-report-template.md +0 -111
- package/bundled/skills-windows/prizmkit-test/scripts/validate_boundary_report.py +0 -347
- package/bundled/skills-windows/recovery-workflow/SKILL.md +0 -355
- package/bundled/skills-windows/recovery-workflow/evals/evals.json +0 -46
- package/bundled/skills-windows/recovery-workflow/references/detection.md +0 -58
- package/bundled/skills-windows/recovery-workflow/scripts/detect-recovery-state.py +0 -544
- package/bundled/skills-windows/refactor-pipeline-launcher/SKILL.md +0 -346
- package/bundled/skills-windows/refactor-pipeline-launcher/references/configuration.md +0 -72
- package/bundled/skills-windows/refactor-planner/SKILL.md +0 -398
- package/bundled/skills-windows/refactor-planner/assets/planning-guide.md +0 -292
- package/bundled/skills-windows/refactor-planner/references/behavior-preservation.md +0 -301
- package/bundled/skills-windows/refactor-planner/references/fast-path.md +0 -59
- package/bundled/skills-windows/refactor-planner/references/planning-phases.md +0 -135
- package/bundled/skills-windows/refactor-planner/references/refactor-scoping-guide.md +0 -221
- package/bundled/skills-windows/refactor-planner/scripts/validate-and-generate-refactor.py +0 -858
- package/bundled/skills-windows/refactor-workflow/SKILL.md +0 -343
- package/bundled/skills-windows/refactor-workflow/references/brainstorm-guide.md +0 -116
- package/bundled/templates/hooks/diff-prizm-docs.sh +0 -158
- package/bundled/templates/hooks/prizm-pre-commit.sh +0 -108
- package/bundled/templates/hooks/validate-prizm-docs.sh +0 -139
|
@@ -1,1430 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
# ============================================================
|
|
5
|
-
# dev-pipeline/run-bugfix.sh - Autonomous Bug Fix Pipeline Runner
|
|
6
|
-
#
|
|
7
|
-
# Drives the prizm-dev-team through iterative AI CLI sessions to
|
|
8
|
-
# fix bugs from a .prizmkit/plans/bug-fix-list.json specification.
|
|
9
|
-
#
|
|
10
|
-
# Usage:
|
|
11
|
-
# ./run-bugfix.sh run [.prizmkit/plans/bug-fix-list.json] [options] Run all bugs
|
|
12
|
-
# ./run-bugfix.sh run <bug-id> [options] Run a single bug
|
|
13
|
-
# ./run-bugfix.sh status [.prizmkit/plans/bug-fix-list.json] Show pipeline status
|
|
14
|
-
# ./run-bugfix.sh reset Clear all state
|
|
15
|
-
#
|
|
16
|
-
# Environment Variables:
|
|
17
|
-
# MAX_RETRIES Max code retries per bug (default: 3)
|
|
18
|
-
# MAX_INFRA_RETRIES Max infrastructure/provider retries per bug (default: 3)
|
|
19
|
-
# AI_CLI AI CLI command name (auto-detected: cbc, claude, or codex)
|
|
20
|
-
# CODEBUDDY_CLI Legacy alias for AI_CLI (deprecated, use AI_CLI instead)
|
|
21
|
-
# PRIZMKIT_PLATFORM Platform hint for custom AI_CLI wrappers: codebuddy, claude, or codex
|
|
22
|
-
# VERBOSE Set to 1 to enable --verbose on AI CLI
|
|
23
|
-
# HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)
|
|
24
|
-
# STALE_KILL_THRESHOLD Auto-kill session after N seconds of no progress (default: 900)
|
|
25
|
-
# HEARTBEAT_STALE_THRESHOLD Heartbeat stale threshold in seconds (default: 600)
|
|
26
|
-
# MAX_LOG_SIZE Include passive log-size checkpoint guidance above this threshold (default: 2097152 = 2MB, set 0 to disable)
|
|
27
|
-
# DEV_BRANCH Custom dev branch name (default: auto-generated bugfix/pipeline-{run_id})
|
|
28
|
-
# AUTO_PUSH Auto-push to remote after successful bug fix (default: 0). Set to 1 to enable.
|
|
29
|
-
# STOP_ON_FAILURE Stop pipeline after a task exhausts all retries (default: 0). Set to 1 to stop.
|
|
30
|
-
# ============================================================
|
|
31
|
-
|
|
32
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
33
|
-
|
|
34
|
-
# Source shared common helpers (exports PIPELINE_DIR/PRIZMKIT_DIR/PROJECT_ROOT,
|
|
35
|
-
# CLI/platform detection, logs, deps)
|
|
36
|
-
source "$SCRIPT_DIR/lib/common.sh"
|
|
37
|
-
|
|
38
|
-
STATE_DIR="${PRIZMKIT_DIR}/state/bugfix"
|
|
39
|
-
SCRIPTS_DIR="$SCRIPT_DIR/scripts"
|
|
40
|
-
|
|
41
|
-
# Configuration
|
|
42
|
-
MAX_RETRIES=${MAX_RETRIES:-3}
|
|
43
|
-
MAX_INFRA_RETRIES=${MAX_INFRA_RETRIES:-3}
|
|
44
|
-
HEARTBEAT_STALE_THRESHOLD=${HEARTBEAT_STALE_THRESHOLD:-600}
|
|
45
|
-
HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-30}
|
|
46
|
-
STALE_KILL_THRESHOLD=${STALE_KILL_THRESHOLD:-900}
|
|
47
|
-
VERBOSE=${VERBOSE:-0}
|
|
48
|
-
MODEL=${MODEL:-""}
|
|
49
|
-
PRIZMKIT_EFFORT=${PRIZMKIT_EFFORT:-""}
|
|
50
|
-
DEV_BRANCH=${DEV_BRANCH:-""}
|
|
51
|
-
AUTO_PUSH=${AUTO_PUSH:-0}
|
|
52
|
-
STOP_ON_FAILURE=${STOP_ON_FAILURE:-0}
|
|
53
|
-
ENABLE_DEPLOY=${ENABLE_DEPLOY:-0}
|
|
54
|
-
|
|
55
|
-
# Source shared common helpers (CLI/platform detection + logs + deps)
|
|
56
|
-
prizm_detect_cli_and_platform
|
|
57
|
-
|
|
58
|
-
# Validate PRIZMKIT_EFFORT early (fail-fast before any sessions are spawned)
|
|
59
|
-
prizm_validate_effort
|
|
60
|
-
|
|
61
|
-
# Source shared heartbeat library
|
|
62
|
-
source "$SCRIPT_DIR/lib/heartbeat.sh"
|
|
63
|
-
|
|
64
|
-
# Source shared branch library
|
|
65
|
-
source "$SCRIPT_DIR/lib/branch.sh"
|
|
66
|
-
|
|
67
|
-
# Detect stream-json support
|
|
68
|
-
detect_stream_json_support "$CLI_CMD"
|
|
69
|
-
|
|
70
|
-
# Bug list path (set in main, used by cleanup trap)
|
|
71
|
-
BUG_LIST=""
|
|
72
|
-
|
|
73
|
-
# Branch tracking (for cleanup on interrupt)
|
|
74
|
-
_ORIGINAL_BRANCH=""
|
|
75
|
-
_DEV_BRANCH_NAME=""
|
|
76
|
-
|
|
77
|
-
# ============================================================
|
|
78
|
-
# Shared: Spawn AI CLI session and wait for result
|
|
79
|
-
# ============================================================
|
|
80
|
-
|
|
81
|
-
spawn_and_wait_session() {
|
|
82
|
-
local bug_id="$1"
|
|
83
|
-
local bug_list="$2"
|
|
84
|
-
local session_id="$3"
|
|
85
|
-
local bootstrap_prompt="$4"
|
|
86
|
-
local session_dir="$5"
|
|
87
|
-
local max_retries="$6"
|
|
88
|
-
local max_infra_retries="$7"
|
|
89
|
-
local item_model="${8:-}"
|
|
90
|
-
local base_branch="${9:-main}"
|
|
91
|
-
|
|
92
|
-
local session_log="$session_dir/logs/session.log"
|
|
93
|
-
local progress_json="$session_dir/logs/progress.json"
|
|
94
|
-
|
|
95
|
-
local effective_model=""
|
|
96
|
-
if [[ -n "$item_model" ]]; then
|
|
97
|
-
effective_model="$item_model"
|
|
98
|
-
elif [[ -n "${MODEL:-}" ]]; then
|
|
99
|
-
effective_model="$MODEL"
|
|
100
|
-
fi
|
|
101
|
-
|
|
102
|
-
# Log bootstrap prompt in test mode
|
|
103
|
-
prizm_log_bootstrap_prompt "$bootstrap_prompt" "$bug_id"
|
|
104
|
-
|
|
105
|
-
local cli_pid
|
|
106
|
-
prizm_start_ai_session "$bootstrap_prompt" "$session_log" "$effective_model"
|
|
107
|
-
cli_pid="$PRIZM_AI_PID"
|
|
108
|
-
|
|
109
|
-
# Start progress parser (no-op if stream-json not supported)
|
|
110
|
-
start_progress_parser "$session_log" "$progress_json" "$SCRIPTS_DIR"
|
|
111
|
-
local parser_pid="${_PARSER_PID:-}"
|
|
112
|
-
|
|
113
|
-
# Heartbeat monitor (with stale-kill protection)
|
|
114
|
-
start_heartbeat "$cli_pid" "$session_log" "$progress_json" "$HEARTBEAT_INTERVAL" "$STALE_KILL_THRESHOLD"
|
|
115
|
-
local heartbeat_pid="${_HEARTBEAT_PID:-}"
|
|
116
|
-
|
|
117
|
-
# Wait for AI CLI to finish
|
|
118
|
-
local exit_code=0
|
|
119
|
-
if wait "$cli_pid" 2>/dev/null; then
|
|
120
|
-
exit_code=0
|
|
121
|
-
else
|
|
122
|
-
exit_code=$?
|
|
123
|
-
fi
|
|
124
|
-
|
|
125
|
-
# Clean up heartbeat and parser
|
|
126
|
-
stop_heartbeat "$heartbeat_pid"
|
|
127
|
-
stop_progress_parser "$parser_pid"
|
|
128
|
-
|
|
129
|
-
# Recover session log from backup if truncated by subagent stdout redirection
|
|
130
|
-
prizm_recover_session_log "$session_log"
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
# Check for stale-kill marker (heartbeat killed the process due to no progress)
|
|
134
|
-
local stale_kill_marker="$session_dir/logs/stale-kill.json"
|
|
135
|
-
local was_stale_killed=false
|
|
136
|
-
if [[ -f "$stale_kill_marker" ]]; then
|
|
137
|
-
was_stale_killed=true
|
|
138
|
-
log_warn "Session was stale-killed by heartbeat monitor (no progress for too long)"
|
|
139
|
-
fi
|
|
140
|
-
|
|
141
|
-
local was_context_overflow=false
|
|
142
|
-
if prizm_detect_context_overflow_error "$session_log" "$progress_json"; then
|
|
143
|
-
was_context_overflow=true
|
|
144
|
-
fi
|
|
145
|
-
|
|
146
|
-
local was_ai_runtime_error=false
|
|
147
|
-
if prizm_detect_ai_runtime_error "$session_log" "$progress_json"; then
|
|
148
|
-
was_ai_runtime_error=true
|
|
149
|
-
fi
|
|
150
|
-
|
|
151
|
-
local was_infra_error=false
|
|
152
|
-
if [[ $exit_code -ne 0 ]] && prizm_detect_infra_error "$session_log" "$progress_json"; then
|
|
153
|
-
was_infra_error=true
|
|
154
|
-
fi
|
|
155
|
-
|
|
156
|
-
# Session summary
|
|
157
|
-
if [[ -f "$session_log" ]]; then
|
|
158
|
-
local final_size=$(wc -c < "$session_log" 2>/dev/null | tr -d ' ')
|
|
159
|
-
local final_lines=$(wc -l < "$session_log" 2>/dev/null | tr -d ' ')
|
|
160
|
-
log_info "Session log: $final_lines lines, $((final_size / 1024))KB"
|
|
161
|
-
if [[ "$final_size" -lt 1024 && "$exit_code" -eq 0 ]]; then
|
|
162
|
-
log_warn "Session log was truncated during execution (subagent stdout redirection may have severed it)"
|
|
163
|
-
log_warn "Proceeding with exit-code-only outcome detection — child transcripts and git state are still valid"
|
|
164
|
-
fi
|
|
165
|
-
fi
|
|
166
|
-
log_info "exit_code=$exit_code"
|
|
167
|
-
|
|
168
|
-
# ── Determine session outcome from observable signals ──────────────
|
|
169
|
-
local session_status
|
|
170
|
-
local project_root
|
|
171
|
-
project_root="$PROJECT_ROOT"
|
|
172
|
-
local default_branch="$base_branch"
|
|
173
|
-
|
|
174
|
-
local has_commits=""
|
|
175
|
-
if git -C "$project_root" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
176
|
-
has_commits=$(git -C "$project_root" log "${default_branch}..HEAD" --oneline 2>/dev/null | head -1)
|
|
177
|
-
fi
|
|
178
|
-
|
|
179
|
-
if [[ -n "$has_commits" ]]; then
|
|
180
|
-
session_status="success"
|
|
181
|
-
elif [[ "$was_context_overflow" == true ]]; then
|
|
182
|
-
log_warn "Session failed because the AI CLI exceeded the model context window"
|
|
183
|
-
log_warn "Context overflow is retried without consuming code retry budget"
|
|
184
|
-
session_status="context_overflow"
|
|
185
|
-
elif [[ "$was_ai_runtime_error" == true ]]; then
|
|
186
|
-
log_warn "Session failed due to structured AI runtime error"
|
|
187
|
-
log_warn "AI runtime errors are retried without consuming code retry budget"
|
|
188
|
-
session_status="infra_error"
|
|
189
|
-
elif [[ "$was_infra_error" == true ]]; then
|
|
190
|
-
log_warn "Session failed due to AI CLI/provider infrastructure error"
|
|
191
|
-
log_warn "Infrastructure errors are retried without consuming code retry budget"
|
|
192
|
-
session_status="infra_error"
|
|
193
|
-
elif [[ "$was_stale_killed" == true ]]; then
|
|
194
|
-
log_warn "Session stale-killed (no progress for ${STALE_KILL_THRESHOLD}s)"
|
|
195
|
-
log_warn "Stale-killed sessions are treated as failed; dev branch is preserved for inspection"
|
|
196
|
-
session_status="crashed"
|
|
197
|
-
elif [[ $exit_code -ne 0 ]]; then
|
|
198
|
-
log_warn "Session exited with code $exit_code"
|
|
199
|
-
session_status="crashed"
|
|
200
|
-
else
|
|
201
|
-
# Exit code 0 — check if the session actually produced commits
|
|
202
|
-
local has_commits=""
|
|
203
|
-
if git -C "$project_root" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
204
|
-
has_commits=$(git -C "$project_root" log "${default_branch}..HEAD" --oneline 2>/dev/null | head -1)
|
|
205
|
-
fi
|
|
206
|
-
|
|
207
|
-
if [[ -n "$has_commits" ]]; then
|
|
208
|
-
session_status="success"
|
|
209
|
-
else
|
|
210
|
-
local uncommitted=""
|
|
211
|
-
uncommitted=$(prizm_git_status_safe "$project_root" | head -1 || true)
|
|
212
|
-
if [[ -n "$uncommitted" ]]; then
|
|
213
|
-
log_warn "Session exited cleanly but produced no commits (uncommitted changes found) — auto-committing..."
|
|
214
|
-
prizm_git_add_all_safe "$project_root" || true
|
|
215
|
-
if git -C "$project_root" commit --no-verify -m "chore($bug_id): auto-commit session work" 2>/dev/null; then
|
|
216
|
-
log_info "Auto-commit succeeded"
|
|
217
|
-
session_status="success"
|
|
218
|
-
else
|
|
219
|
-
log_warn "Auto-commit failed — no changes to commit"
|
|
220
|
-
session_status="crashed"
|
|
221
|
-
fi
|
|
222
|
-
else
|
|
223
|
-
log_warn "Session exited cleanly but produced no commits and no changes"
|
|
224
|
-
session_status="crashed"
|
|
225
|
-
fi
|
|
226
|
-
fi
|
|
227
|
-
fi
|
|
228
|
-
|
|
229
|
-
# ── Post-success validation ──────────────────────────────────────────
|
|
230
|
-
if [[ "$session_status" == "success" ]]; then
|
|
231
|
-
if git -C "$project_root" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
232
|
-
local dirty_files=""
|
|
233
|
-
dirty_files=$(prizm_git_status_safe "$project_root" || true)
|
|
234
|
-
if [[ -n "$dirty_files" ]]; then
|
|
235
|
-
log_info "Auto-committing remaining session artifacts..."
|
|
236
|
-
prizm_git_add_all_safe "$project_root" || true
|
|
237
|
-
git -C "$project_root" commit --no-verify --amend --no-edit 2>/dev/null \
|
|
238
|
-
|| git -C "$project_root" commit --no-verify -m "chore($bug_id): include remaining session artifacts" 2>/dev/null \
|
|
239
|
-
|| true
|
|
240
|
-
fi
|
|
241
|
-
fi
|
|
242
|
-
fi
|
|
243
|
-
|
|
244
|
-
log_info "Session result: $session_status"
|
|
245
|
-
|
|
246
|
-
# Validate checkpoint completeness after successful session
|
|
247
|
-
if [[ "$session_status" == "success" ]]; then
|
|
248
|
-
local checkpoint_file="$PRIZMKIT_DIR/bugfix/${bug_id}/workflow-checkpoint.json"
|
|
249
|
-
if [[ -f "$checkpoint_file" ]]; then
|
|
250
|
-
local checkpoint_result
|
|
251
|
-
checkpoint_result=$(python3 -c "
|
|
252
|
-
import json, sys
|
|
253
|
-
try:
|
|
254
|
-
with open(sys.argv[1]) as f:
|
|
255
|
-
data = json.load(f)
|
|
256
|
-
except json.JSONDecodeError as e:
|
|
257
|
-
print('CORRUPTED: {}'.format(e))
|
|
258
|
-
sys.exit(2)
|
|
259
|
-
incomplete = [s for s in data['steps'] if s['status'] not in ('completed', 'skipped')]
|
|
260
|
-
if incomplete:
|
|
261
|
-
for s in incomplete:
|
|
262
|
-
print('INCOMPLETE: {} {} = {}'.format(s['id'], s['skill'], s['status']))
|
|
263
|
-
sys.exit(1)
|
|
264
|
-
print('ALL_COMPLETE')
|
|
265
|
-
sys.exit(0)
|
|
266
|
-
" "$checkpoint_file" 2>&1) || checkpoint_result="CHECK_FAILED"
|
|
267
|
-
local check_exit=$?
|
|
268
|
-
if [[ "$checkpoint_result" == "CHECK_FAILED" ]]; then
|
|
269
|
-
check_exit=2
|
|
270
|
-
elif [[ "$checkpoint_result" == *"INCOMPLETE"* ]]; then
|
|
271
|
-
check_exit=1
|
|
272
|
-
else
|
|
273
|
-
check_exit=0
|
|
274
|
-
fi
|
|
275
|
-
if [[ $check_exit -eq 2 ]]; then
|
|
276
|
-
log_warn "CHECKPOINT_CORRUPTED: workflow-checkpoint.json is not valid JSON"
|
|
277
|
-
elif [[ $check_exit -eq 1 ]]; then
|
|
278
|
-
log_warn "CHECKPOINT_INCOMPLETE: Not all workflow steps completed:"
|
|
279
|
-
echo "$checkpoint_result" | while read -r line; do log_warn " $line"; done
|
|
280
|
-
else
|
|
281
|
-
log_info "CHECKPOINT: All workflow steps completed"
|
|
282
|
-
fi
|
|
283
|
-
fi
|
|
284
|
-
fi
|
|
285
|
-
|
|
286
|
-
# Subagent detection
|
|
287
|
-
prizm_detect_subagents "$session_log"
|
|
288
|
-
|
|
289
|
-
# Final status updates happen after the caller returns to the original branch.
|
|
290
|
-
_SPAWN_RESULT="$session_status"
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
finalize_bug_status_after_branch_return() {
|
|
294
|
-
local bug_id="$1"
|
|
295
|
-
local bug_list="$2"
|
|
296
|
-
local session_id="$3"
|
|
297
|
-
local session_status="$4"
|
|
298
|
-
local max_retries="$5"
|
|
299
|
-
local max_infra_retries="$6"
|
|
300
|
-
local base_branch="${7:-main}"
|
|
301
|
-
local active_dev_branch="${8:-}"
|
|
302
|
-
local fatal_error_code="${9:-}"
|
|
303
|
-
local continuation_summary_path="${10:-}"
|
|
304
|
-
local no_progress_count="${11:-0}"
|
|
305
|
-
local progress_fingerprint="${12:-}"
|
|
306
|
-
|
|
307
|
-
# Update bug status on the original branch. The caller commits the resulting
|
|
308
|
-
# bug-list diff immediately after this helper returns.
|
|
309
|
-
local update_output
|
|
310
|
-
update_output=$(python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
311
|
-
--bug-list "$bug_list" \
|
|
312
|
-
--state-dir "$STATE_DIR" \
|
|
313
|
-
--bug-id "$bug_id" \
|
|
314
|
-
--session-status "$session_status" \
|
|
315
|
-
--session-id "$session_id" \
|
|
316
|
-
--max-retries "$max_retries" \
|
|
317
|
-
--max-infra-retries "$max_infra_retries" \
|
|
318
|
-
--active-dev-branch "$active_dev_branch" \
|
|
319
|
-
--base-branch "$base_branch" \
|
|
320
|
-
--last-fatal-error-code "$fatal_error_code" \
|
|
321
|
-
--continuation-summary-path "$continuation_summary_path" \
|
|
322
|
-
--no-progress-count "$no_progress_count" \
|
|
323
|
-
--progress-fingerprint "$progress_fingerprint" \
|
|
324
|
-
--action update) || {
|
|
325
|
-
log_error "Failed to update bug status: $update_output"
|
|
326
|
-
update_output=""
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
_SPAWN_ITEM_STATUS="$(printf '%s' "$update_output" | prizm_extract_update_new_status)"
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
# ============================================================
|
|
333
|
-
# Graceful Shutdown
|
|
334
|
-
# ============================================================
|
|
335
|
-
|
|
336
|
-
cleanup() {
|
|
337
|
-
echo ""
|
|
338
|
-
log_warn "Received interrupt signal. Saving state..."
|
|
339
|
-
|
|
340
|
-
# Kill all child processes (claude-internal, heartbeat, progress parser, etc.)
|
|
341
|
-
kill 0 2>/dev/null || true
|
|
342
|
-
|
|
343
|
-
# Log current branch info for recovery
|
|
344
|
-
if [[ -n "$_DEV_BRANCH_NAME" ]]; then
|
|
345
|
-
log_info "Development was on branch: $_DEV_BRANCH_NAME"
|
|
346
|
-
log_info "Original branch was: $_ORIGINAL_BRANCH"
|
|
347
|
-
fi
|
|
348
|
-
|
|
349
|
-
# Update status of currently in-progress bug to interrupted
|
|
350
|
-
if [[ -n "$BUG_LIST" && -f "$BUG_LIST" ]]; then
|
|
351
|
-
# Find any in-progress bug and mark it as failed
|
|
352
|
-
local _interrupted_id
|
|
353
|
-
_interrupted_id=$(python3 -c "
|
|
354
|
-
import json, sys
|
|
355
|
-
with open(sys.argv[1]) as f:
|
|
356
|
-
data = json.load(f)
|
|
357
|
-
for bug in data.get('bugs', []):
|
|
358
|
-
if bug.get('status') == 'in_progress':
|
|
359
|
-
print(bug['id'])
|
|
360
|
-
break
|
|
361
|
-
" "$BUG_LIST" 2>/dev/null || echo "")
|
|
362
|
-
|
|
363
|
-
if [[ -n "$_interrupted_id" ]]; then
|
|
364
|
-
python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
365
|
-
--bug-list "$BUG_LIST" \
|
|
366
|
-
--state-dir "$STATE_DIR" \
|
|
367
|
-
--bug-id "$_interrupted_id" \
|
|
368
|
-
--session-status "failed" \
|
|
369
|
-
--max-retries "$MAX_RETRIES" \
|
|
370
|
-
--max-infra-retries "$MAX_INFRA_RETRIES" \
|
|
371
|
-
--action update 2>/dev/null || true
|
|
372
|
-
log_info "Bug $_interrupted_id marked as failed due to interrupt"
|
|
373
|
-
fi
|
|
374
|
-
|
|
375
|
-
# Pause the pipeline
|
|
376
|
-
python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
377
|
-
--bug-list "$BUG_LIST" \
|
|
378
|
-
--state-dir "$STATE_DIR" \
|
|
379
|
-
--action pause 2>/dev/null || true
|
|
380
|
-
fi
|
|
381
|
-
|
|
382
|
-
# GUARANTEED: always return to original branch (save WIP on dev branch first)
|
|
383
|
-
branch_ensure_return "$PROJECT_ROOT" "$_ORIGINAL_BRANCH" "$_DEV_BRANCH_NAME"
|
|
384
|
-
|
|
385
|
-
log_info "Bug fix pipeline paused. Run './run-bugfix.sh run' to resume."
|
|
386
|
-
exit 130
|
|
387
|
-
}
|
|
388
|
-
trap cleanup SIGINT SIGTERM
|
|
389
|
-
|
|
390
|
-
# ============================================================
|
|
391
|
-
# Dependency Check
|
|
392
|
-
# ============================================================
|
|
393
|
-
|
|
394
|
-
check_dependencies() {
|
|
395
|
-
prizm_check_common_dependencies "$CLI_CMD"
|
|
396
|
-
local _project_root
|
|
397
|
-
_project_root="$PROJECT_ROOT"
|
|
398
|
-
prizm_ensure_git_repo "$_project_root"
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
# ============================================================
|
|
403
|
-
# run-one: Run a single bug fix
|
|
404
|
-
# ============================================================
|
|
405
|
-
|
|
406
|
-
run_one() {
|
|
407
|
-
local bug_id=""
|
|
408
|
-
local bug_list=""
|
|
409
|
-
local dry_run=false
|
|
410
|
-
local do_clean=false
|
|
411
|
-
local no_reset=false
|
|
412
|
-
local mode_override=""
|
|
413
|
-
local critic_override=""
|
|
414
|
-
|
|
415
|
-
while [[ $# -gt 0 ]]; do
|
|
416
|
-
case "$1" in
|
|
417
|
-
--dry-run) dry_run=true; shift ;;
|
|
418
|
-
--clean) do_clean=true; shift ;;
|
|
419
|
-
--no-reset) no_reset=true; shift ;;
|
|
420
|
-
--max-infra-retries)
|
|
421
|
-
shift
|
|
422
|
-
if [[ $# -eq 0 ]]; then
|
|
423
|
-
log_error "--max-infra-retries requires a value"
|
|
424
|
-
exit 1
|
|
425
|
-
fi
|
|
426
|
-
prizm_require_positive_int "--max-infra-retries" "$1"
|
|
427
|
-
MAX_INFRA_RETRIES="$1"
|
|
428
|
-
shift
|
|
429
|
-
;;
|
|
430
|
-
--mode)
|
|
431
|
-
shift
|
|
432
|
-
if [[ $# -eq 0 ]]; then
|
|
433
|
-
log_error "--mode requires a value (lite|standard|full)"
|
|
434
|
-
exit 1
|
|
435
|
-
fi
|
|
436
|
-
case "$1" in
|
|
437
|
-
lite|standard|full) mode_override="$1" ;;
|
|
438
|
-
*) log_error "Invalid mode: $1 (must be lite, standard, or full)"; exit 1 ;;
|
|
439
|
-
esac
|
|
440
|
-
shift
|
|
441
|
-
;;
|
|
442
|
-
--critic) critic_override="true"; shift ;;
|
|
443
|
-
--no-critic) critic_override="false"; shift ;;
|
|
444
|
-
B-*|b-*) bug_id="$1"; shift ;;
|
|
445
|
-
*) bug_list="$1"; shift ;;
|
|
446
|
-
esac
|
|
447
|
-
done
|
|
448
|
-
|
|
449
|
-
if [[ -z "$bug_id" ]]; then
|
|
450
|
-
log_error "Bug ID is required (e.g. B-001)"
|
|
451
|
-
echo ""
|
|
452
|
-
show_help
|
|
453
|
-
exit 1
|
|
454
|
-
fi
|
|
455
|
-
|
|
456
|
-
if [[ -z "$bug_list" ]]; then
|
|
457
|
-
bug_list="$PRIZMKIT_DIR/plans/bug-fix-list.json"
|
|
458
|
-
fi
|
|
459
|
-
if [[ ! "$bug_list" = /* ]]; then
|
|
460
|
-
bug_list="$(pwd)/$bug_list"
|
|
461
|
-
fi
|
|
462
|
-
BUG_LIST="$bug_list"
|
|
463
|
-
|
|
464
|
-
if [[ ! -f "$bug_list" ]]; then
|
|
465
|
-
log_error "Bug fix list not found: $bug_list"
|
|
466
|
-
exit 1
|
|
467
|
-
fi
|
|
468
|
-
|
|
469
|
-
check_dependencies
|
|
470
|
-
|
|
471
|
-
# Initialize state if needed
|
|
472
|
-
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
473
|
-
log_info "Initializing bugfix pipeline state..."
|
|
474
|
-
local init_result init_stderr init_tmpstderr
|
|
475
|
-
init_tmpstderr=$(mktemp)
|
|
476
|
-
if ! init_result=$(python3 "$SCRIPTS_DIR/init-bugfix-pipeline.py" \
|
|
477
|
-
--bug-list "$bug_list" \
|
|
478
|
-
--state-dir "$STATE_DIR" 2>"$init_tmpstderr"); then
|
|
479
|
-
init_stderr=$(cat "$init_tmpstderr" 2>/dev/null || true)
|
|
480
|
-
rm -f "$init_tmpstderr"
|
|
481
|
-
if [[ -n "$init_stderr" ]]; then
|
|
482
|
-
log_warn "$init_stderr"
|
|
483
|
-
fi
|
|
484
|
-
log_error "Bugfix pipeline initialization failed (script error)"
|
|
485
|
-
exit 1
|
|
486
|
-
fi
|
|
487
|
-
init_stderr=$(cat "$init_tmpstderr" 2>/dev/null || true)
|
|
488
|
-
rm -f "$init_tmpstderr"
|
|
489
|
-
|
|
490
|
-
if [[ -n "$init_stderr" ]]; then
|
|
491
|
-
log_warn "$init_stderr"
|
|
492
|
-
fi
|
|
493
|
-
|
|
494
|
-
local init_valid
|
|
495
|
-
init_valid=$(echo "$init_result" | python3 -c "import sys,json; print(json.load(sys.stdin).get('valid', False))" 2>/dev/null || echo "False")
|
|
496
|
-
|
|
497
|
-
if [[ "$init_valid" != "True" ]]; then
|
|
498
|
-
log_error "Bugfix pipeline initialization failed:"
|
|
499
|
-
echo "$init_result"
|
|
500
|
-
exit 1
|
|
501
|
-
fi
|
|
502
|
-
|
|
503
|
-
local bugs_count
|
|
504
|
-
bugs_count=$(echo "$init_result" | python3 -c "import sys,json; print(json.load(sys.stdin).get('bugs_count', 0))" 2>/dev/null || echo "0")
|
|
505
|
-
log_success "Bugfix pipeline initialized with $bugs_count bugs"
|
|
506
|
-
fi
|
|
507
|
-
|
|
508
|
-
# Verify bug exists
|
|
509
|
-
local bug_title
|
|
510
|
-
bug_title=$(python3 -c "
|
|
511
|
-
import json, sys
|
|
512
|
-
with open(sys.argv[1]) as f:
|
|
513
|
-
data = json.load(f)
|
|
514
|
-
for bug in data.get('bugs', []):
|
|
515
|
-
if bug.get('id') == sys.argv[2]:
|
|
516
|
-
print(bug.get('title', ''))
|
|
517
|
-
sys.exit(0)
|
|
518
|
-
sys.exit(1)
|
|
519
|
-
" "$bug_list" "$bug_id" 2>/dev/null) || {
|
|
520
|
-
log_error "Bug $bug_id not found in $bug_list"
|
|
521
|
-
exit 1
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
local bug_severity
|
|
525
|
-
bug_severity=$(python3 -c "
|
|
526
|
-
import json, sys
|
|
527
|
-
with open(sys.argv[1]) as f:
|
|
528
|
-
data = json.load(f)
|
|
529
|
-
for bug in data.get('bugs', []):
|
|
530
|
-
if bug.get('id') == sys.argv[2]:
|
|
531
|
-
print(bug.get('severity', 'medium'))
|
|
532
|
-
sys.exit(0)
|
|
533
|
-
sys.exit(1)
|
|
534
|
-
" "$bug_list" "$bug_id" 2>/dev/null) || bug_severity="medium"
|
|
535
|
-
|
|
536
|
-
# Optional Clean
|
|
537
|
-
if [[ "$do_clean" == true ]]; then
|
|
538
|
-
if [[ "$dry_run" == true ]]; then
|
|
539
|
-
log_warn "Dry-run mode: --clean ignored (no artifacts will be deleted)"
|
|
540
|
-
else
|
|
541
|
-
log_info "Cleaning artifacts for $bug_id..."
|
|
542
|
-
|
|
543
|
-
local project_root
|
|
544
|
-
project_root="$PROJECT_ROOT"
|
|
545
|
-
|
|
546
|
-
local bugfix_dir="$PRIZMKIT_DIR/bugfix/$bug_id"
|
|
547
|
-
if [[ -d "$bugfix_dir" ]]; then
|
|
548
|
-
rm -rf "$bugfix_dir"
|
|
549
|
-
log_info "Removed $bugfix_dir"
|
|
550
|
-
fi
|
|
551
|
-
|
|
552
|
-
local dev_team_dir="$project_root/.dev-team"
|
|
553
|
-
if [[ -d "$dev_team_dir" ]]; then
|
|
554
|
-
rm -rf "$dev_team_dir"
|
|
555
|
-
log_info "Removed $dev_team_dir"
|
|
556
|
-
fi
|
|
557
|
-
|
|
558
|
-
local bug_state_dir="$STATE_DIR/$bug_id"
|
|
559
|
-
if [[ -d "$bug_state_dir" ]]; then
|
|
560
|
-
rm -rf "$bug_state_dir"
|
|
561
|
-
log_info "Removed $bug_state_dir"
|
|
562
|
-
fi
|
|
563
|
-
fi
|
|
564
|
-
fi
|
|
565
|
-
|
|
566
|
-
# Reset bug status (conditional)
|
|
567
|
-
if [[ "$no_reset" == false && "$dry_run" == false ]]; then
|
|
568
|
-
python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
569
|
-
--bug-list "$bug_list" \
|
|
570
|
-
--state-dir "$STATE_DIR" \
|
|
571
|
-
--bug-id "$bug_id" \
|
|
572
|
-
--action reset >/dev/null 2>&1 || {
|
|
573
|
-
log_warn "Failed to reset bug status (may already be pending)"
|
|
574
|
-
}
|
|
575
|
-
elif [[ "$dry_run" == true && "$no_reset" == false ]]; then
|
|
576
|
-
log_info "Dry-run mode: skipping status reset"
|
|
577
|
-
fi
|
|
578
|
-
|
|
579
|
-
# Generate bootstrap prompt
|
|
580
|
-
local run_id session_id session_dir bootstrap_prompt
|
|
581
|
-
run_id=$(jq -r '.run_id' "$STATE_DIR/pipeline.json")
|
|
582
|
-
session_id="${bug_id}-$(date +%Y%m%d%H%M%S)"
|
|
583
|
-
session_dir="$STATE_DIR/$bug_id/sessions/$session_id"
|
|
584
|
-
mkdir -p "$session_dir/logs"
|
|
585
|
-
|
|
586
|
-
bootstrap_prompt="$session_dir/bootstrap-prompt.md"
|
|
587
|
-
|
|
588
|
-
# Read retry count from status.json
|
|
589
|
-
local retry_count
|
|
590
|
-
retry_count=$(python3 -c "
|
|
591
|
-
import json, os
|
|
592
|
-
status_path = os.path.join('$STATE_DIR', '$bug_id', 'status.json')
|
|
593
|
-
if os.path.isfile(status_path):
|
|
594
|
-
with open(status_path) as f:
|
|
595
|
-
d = json.load(f)
|
|
596
|
-
print(d.get('retry_count', 0))
|
|
597
|
-
else:
|
|
598
|
-
print(0)
|
|
599
|
-
" 2>/dev/null || echo "0")
|
|
600
|
-
local resume_phase
|
|
601
|
-
resume_phase=$(python3 -c "
|
|
602
|
-
import json, os
|
|
603
|
-
status_path = os.path.join('$STATE_DIR', '$bug_id', 'status.json')
|
|
604
|
-
if os.path.isfile(status_path):
|
|
605
|
-
with open(status_path) as f:
|
|
606
|
-
d = json.load(f)
|
|
607
|
-
print(d.get('resume_from_phase') or 'null')
|
|
608
|
-
else:
|
|
609
|
-
print('null')
|
|
610
|
-
" 2>/dev/null || echo "null")
|
|
611
|
-
|
|
612
|
-
log_info "Generating bugfix bootstrap prompt..."
|
|
613
|
-
local prompt_args=(
|
|
614
|
-
--bug-list "$bug_list"
|
|
615
|
-
--bug-id "$bug_id"
|
|
616
|
-
--session-id "$session_id"
|
|
617
|
-
--run-id "$run_id"
|
|
618
|
-
--retry-count "$retry_count"
|
|
619
|
-
--resume-phase "$resume_phase"
|
|
620
|
-
--state-dir "$STATE_DIR"
|
|
621
|
-
--output "$bootstrap_prompt"
|
|
622
|
-
)
|
|
623
|
-
|
|
624
|
-
if [[ -n "$mode_override" ]]; then
|
|
625
|
-
prompt_args+=(--mode "$mode_override")
|
|
626
|
-
elif [[ -n "${PIPELINE_MODE:-}" ]]; then
|
|
627
|
-
prompt_args+=(--mode "$PIPELINE_MODE")
|
|
628
|
-
fi
|
|
629
|
-
|
|
630
|
-
if [[ -n "${critic_override:-}" ]]; then
|
|
631
|
-
prompt_args+=(--critic "$critic_override")
|
|
632
|
-
elif [[ "${ENABLE_CRITIC:-}" == "true" || "${ENABLE_CRITIC:-}" == "1" ]]; then
|
|
633
|
-
prompt_args+=(--critic "true")
|
|
634
|
-
elif [[ "${ENABLE_CRITIC:-}" == "false" || "${ENABLE_CRITIC:-}" == "0" ]]; then
|
|
635
|
-
prompt_args+=(--critic "false")
|
|
636
|
-
fi
|
|
637
|
-
|
|
638
|
-
local gen_output
|
|
639
|
-
gen_output=$(python3 "$SCRIPTS_DIR/generate-bugfix-prompt.py" "${prompt_args[@]}" 2>/dev/null) || {
|
|
640
|
-
log_error "Failed to generate bootstrap prompt for $bug_id"
|
|
641
|
-
return 1
|
|
642
|
-
}
|
|
643
|
-
local bug_model pipeline_mode agent_count critic_enabled
|
|
644
|
-
bug_model=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))" 2>/dev/null || echo "")
|
|
645
|
-
pipeline_mode=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('pipeline_mode','standard'))" 2>/dev/null || echo "standard")
|
|
646
|
-
agent_count=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('agent_count',3))" 2>/dev/null || echo "3")
|
|
647
|
-
critic_enabled=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('critic_enabled','false'))" 2>/dev/null || echo "false")
|
|
648
|
-
|
|
649
|
-
if [[ "$dry_run" == true ]]; then
|
|
650
|
-
echo ""
|
|
651
|
-
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
652
|
-
echo -e "${BOLD} Dry Run: $bug_id — $bug_title${NC}"
|
|
653
|
-
echo -e "${BOLD} Severity: $bug_severity${NC}"
|
|
654
|
-
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
655
|
-
echo ""
|
|
656
|
-
log_info "Session ID: $session_id"
|
|
657
|
-
if [[ -n "$mode_override" ]]; then
|
|
658
|
-
log_info "Mode Override: $mode_override"
|
|
659
|
-
fi
|
|
660
|
-
log_info "Pipeline mode: $pipeline_mode"
|
|
661
|
-
log_info "Agents: $agent_count (critic: $([ "$critic_enabled" = "true" ] && echo "enabled" || echo "disabled"))"
|
|
662
|
-
if [[ -n "$bug_model" ]]; then
|
|
663
|
-
log_info "Bug Model: $bug_model"
|
|
664
|
-
elif [[ -n "$MODEL" ]]; then
|
|
665
|
-
log_info "Model (env): $MODEL"
|
|
666
|
-
else
|
|
667
|
-
log_info "Model: (CLI default)"
|
|
668
|
-
fi
|
|
669
|
-
echo ""
|
|
670
|
-
log_info "Bootstrap prompt written to:"
|
|
671
|
-
echo " $bootstrap_prompt"
|
|
672
|
-
echo ""
|
|
673
|
-
log_success "Dry run complete. Inspect full prompt with:"
|
|
674
|
-
echo " cat $bootstrap_prompt"
|
|
675
|
-
return 0
|
|
676
|
-
fi
|
|
677
|
-
|
|
678
|
-
echo ""
|
|
679
|
-
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
680
|
-
echo -e "${BOLD} Bug Fix: $bug_id — $bug_title${NC}"
|
|
681
|
-
echo -e "${BOLD} Severity: $bug_severity${NC}"
|
|
682
|
-
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
683
|
-
log_info "Session ID: $session_id"
|
|
684
|
-
log_info "Prompt: $bootstrap_prompt"
|
|
685
|
-
log_info "Log: $session_dir/logs/session.log"
|
|
686
|
-
local _run_one_mode_desc
|
|
687
|
-
case "$pipeline_mode" in
|
|
688
|
-
lite) _run_one_mode_desc="Tier 1 — Single Agent" ;;
|
|
689
|
-
standard) _run_one_mode_desc="Tier 2 — Orchestrator + Dev + Reviewer" ;;
|
|
690
|
-
full) _run_one_mode_desc="Tier 3 — Full Team (+ Multi-Critic)" ;;
|
|
691
|
-
*) _run_one_mode_desc="$pipeline_mode" ;;
|
|
692
|
-
esac
|
|
693
|
-
log_info "Pipeline mode: ${BOLD}$pipeline_mode${NC} ($_run_one_mode_desc)"
|
|
694
|
-
log_info "Agents: $agent_count (critic: $([ "$critic_enabled" = "true" ] && echo "enabled" || echo "disabled"))"
|
|
695
|
-
if [[ -n "$bug_model" ]]; then
|
|
696
|
-
log_info "Bug model: $bug_model"
|
|
697
|
-
fi
|
|
698
|
-
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
699
|
-
echo ""
|
|
700
|
-
|
|
701
|
-
cleanup_single_bug() {
|
|
702
|
-
echo ""
|
|
703
|
-
log_warn "Interrupted. Killing session..."
|
|
704
|
-
kill 0 2>/dev/null || true
|
|
705
|
-
# Log current branch info
|
|
706
|
-
if [[ -n "$_DEV_BRANCH_NAME" ]]; then
|
|
707
|
-
log_info "Development was on branch: $_DEV_BRANCH_NAME"
|
|
708
|
-
fi
|
|
709
|
-
log_info "Session log: $session_dir/logs/session.log"
|
|
710
|
-
|
|
711
|
-
# Update bug status to failed on interrupt
|
|
712
|
-
if [[ -n "$bug_list" && -f "$bug_list" ]]; then
|
|
713
|
-
python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
714
|
-
--bug-list "$bug_list" \
|
|
715
|
-
--state-dir "$STATE_DIR" \
|
|
716
|
-
--bug-id "$bug_id" \
|
|
717
|
-
--session-status "failed" \
|
|
718
|
-
--max-retries "$MAX_RETRIES" \
|
|
719
|
-
--max-infra-retries "$MAX_INFRA_RETRIES" \
|
|
720
|
-
--action update 2>/dev/null || true
|
|
721
|
-
log_info "Bug $bug_id marked as failed due to interrupt"
|
|
722
|
-
fi
|
|
723
|
-
|
|
724
|
-
# GUARANTEED: always return to original branch (save WIP on dev branch first)
|
|
725
|
-
branch_ensure_return "$PROJECT_ROOT" "$_ORIGINAL_BRANCH" "$_DEV_BRANCH_NAME"
|
|
726
|
-
exit 130
|
|
727
|
-
}
|
|
728
|
-
trap cleanup_single_bug SIGINT SIGTERM
|
|
729
|
-
|
|
730
|
-
_SPAWN_RESULT=""
|
|
731
|
-
_SPAWN_ITEM_STATUS=""
|
|
732
|
-
|
|
733
|
-
# Branch lifecycle: create and checkout bugfix branch
|
|
734
|
-
local _proj_root
|
|
735
|
-
_proj_root="$PROJECT_ROOT"
|
|
736
|
-
local _source_branch
|
|
737
|
-
_source_branch=$(git -C "$_proj_root" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
|
|
738
|
-
_ORIGINAL_BRANCH="$_source_branch"
|
|
739
|
-
|
|
740
|
-
# Mark bug as in-progress (update JSON for runtime monitoring, no commit)
|
|
741
|
-
# The status change will be committed together with the final status update
|
|
742
|
-
# after the session completes, avoiding an extra noise commit per bug.
|
|
743
|
-
python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
744
|
-
--bug-list "$bug_list" \
|
|
745
|
-
--state-dir "$STATE_DIR" \
|
|
746
|
-
--bug-id "$bug_id" \
|
|
747
|
-
--action start >/dev/null 2>&1 || true
|
|
748
|
-
|
|
749
|
-
local _branch_name="${DEV_BRANCH:-bugfix/${bug_id}-$(date +%s)}"
|
|
750
|
-
if branch_create "$_proj_root" "$_branch_name" "$_source_branch"; then
|
|
751
|
-
_DEV_BRANCH_NAME="$_branch_name"
|
|
752
|
-
else
|
|
753
|
-
log_error "Failed to create branch: $_branch_name from $_source_branch — aborting to avoid running on $_source_branch"
|
|
754
|
-
return 1
|
|
755
|
-
fi
|
|
756
|
-
|
|
757
|
-
spawn_and_wait_session \
|
|
758
|
-
"$bug_id" "$bug_list" "$session_id" \
|
|
759
|
-
"$bootstrap_prompt" "$session_dir" "$MAX_RETRIES" "$MAX_INFRA_RETRIES" "$bug_model" "$_ORIGINAL_BRANCH"
|
|
760
|
-
local session_status="$_SPAWN_RESULT"
|
|
761
|
-
|
|
762
|
-
local active_dev_branch_for_status="$_DEV_BRANCH_NAME"
|
|
763
|
-
local continuation_summary_path=""
|
|
764
|
-
local no_progress_count=0
|
|
765
|
-
local progress_after=""
|
|
766
|
-
|
|
767
|
-
# Merge dev branch back to original on success
|
|
768
|
-
if [[ "$session_status" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
|
|
769
|
-
if branch_merge "$_proj_root" "$_DEV_BRANCH_NAME" "$_ORIGINAL_BRANCH" "$AUTO_PUSH"; then
|
|
770
|
-
_DEV_BRANCH_NAME=""
|
|
771
|
-
else
|
|
772
|
-
log_warn "Auto-merge failed — dev branch preserved: $_DEV_BRANCH_NAME"
|
|
773
|
-
log_warn "Merge manually: git checkout $_ORIGINAL_BRANCH && git rebase $_DEV_BRANCH_NAME"
|
|
774
|
-
session_status="merge_conflict"
|
|
775
|
-
fi
|
|
776
|
-
elif [[ -n "$_DEV_BRANCH_NAME" ]]; then
|
|
777
|
-
# Session failed — preserve dev branch for inspection
|
|
778
|
-
log_warn "Session failed — dev branch preserved for inspection: $_DEV_BRANCH_NAME"
|
|
779
|
-
_DEV_BRANCH_NAME=""
|
|
780
|
-
fi
|
|
781
|
-
|
|
782
|
-
# GUARANTEED: always return to original branch regardless of success/failure/merge outcome
|
|
783
|
-
branch_ensure_return "$_proj_root" "$_ORIGINAL_BRANCH"
|
|
784
|
-
|
|
785
|
-
finalize_bug_status_after_branch_return \
|
|
786
|
-
"$bug_id" "$bug_list" "$session_id" "$session_status" "$MAX_RETRIES" "$MAX_INFRA_RETRIES" "$_ORIGINAL_BRANCH" "$active_dev_branch_for_status" "context_overflow" "$continuation_summary_path" "$no_progress_count" "${progress_after:-}"
|
|
787
|
-
|
|
788
|
-
# Commit bug status update on the original branch (after guaranteed return)
|
|
789
|
-
if ! git -C "$_proj_root" diff --quiet "$bug_list" 2>/dev/null; then
|
|
790
|
-
prizm_git_commit_paths "$_proj_root" "chore($bug_id): update bug status" "$bug_list"
|
|
791
|
-
fi
|
|
792
|
-
|
|
793
|
-
echo ""
|
|
794
|
-
if [[ "$session_status" == "success" ]]; then
|
|
795
|
-
log_success "════════════════════════════════════════════════════"
|
|
796
|
-
log_success " $bug_id fixed successfully!"
|
|
797
|
-
log_success "════════════════════════════════════════════════════"
|
|
798
|
-
else
|
|
799
|
-
log_error "════════════════════════════════════════════════════"
|
|
800
|
-
log_error " $bug_id result: $session_status"
|
|
801
|
-
log_error " Review log: $session_dir/logs/session.log"
|
|
802
|
-
log_error "════════════════════════════════════════════════════"
|
|
803
|
-
fi
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
# ============================================================
|
|
807
|
-
# Main Loop: Run all bugs
|
|
808
|
-
# ============================================================
|
|
809
|
-
|
|
810
|
-
main() {
|
|
811
|
-
local bug_list="$PRIZMKIT_DIR/plans/bug-fix-list.json"
|
|
812
|
-
|
|
813
|
-
while [[ $# -gt 0 ]]; do
|
|
814
|
-
case "$1" in
|
|
815
|
-
--max-infra-retries)
|
|
816
|
-
shift
|
|
817
|
-
if [[ $# -eq 0 ]]; then
|
|
818
|
-
log_error "--max-infra-retries requires a value"
|
|
819
|
-
exit 1
|
|
820
|
-
fi
|
|
821
|
-
prizm_require_positive_int "--max-infra-retries" "$1"
|
|
822
|
-
MAX_INFRA_RETRIES="$1"
|
|
823
|
-
shift
|
|
824
|
-
;;
|
|
825
|
-
--)
|
|
826
|
-
shift
|
|
827
|
-
break
|
|
828
|
-
;;
|
|
829
|
-
-*)
|
|
830
|
-
log_error "Unknown option: $1"
|
|
831
|
-
show_help
|
|
832
|
-
exit 1
|
|
833
|
-
;;
|
|
834
|
-
*)
|
|
835
|
-
bug_list="$1"
|
|
836
|
-
shift
|
|
837
|
-
;;
|
|
838
|
-
esac
|
|
839
|
-
done
|
|
840
|
-
|
|
841
|
-
if [[ $# -gt 0 ]]; then
|
|
842
|
-
log_error "Unexpected arguments: $*"
|
|
843
|
-
show_help
|
|
844
|
-
exit 1
|
|
845
|
-
fi
|
|
846
|
-
|
|
847
|
-
if [[ ! "$bug_list" = /* ]]; then
|
|
848
|
-
bug_list="$(pwd)/$bug_list"
|
|
849
|
-
fi
|
|
850
|
-
BUG_LIST="$bug_list"
|
|
851
|
-
|
|
852
|
-
if [[ ! -f "$bug_list" ]]; then
|
|
853
|
-
log_error "Bug fix list not found: $bug_list"
|
|
854
|
-
log_info "Create a bug fix list first using the bug-planner skill,"
|
|
855
|
-
log_info "or provide a path: ./run-bugfix.sh run <path-to-.prizmkit/plans/bug-fix-list.json>"
|
|
856
|
-
exit 1
|
|
857
|
-
fi
|
|
858
|
-
|
|
859
|
-
check_dependencies
|
|
860
|
-
|
|
861
|
-
# Initialize pipeline state if needed
|
|
862
|
-
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
863
|
-
log_info "Initializing bugfix pipeline state..."
|
|
864
|
-
local init_result init_stderr init_tmpstderr
|
|
865
|
-
init_tmpstderr=$(mktemp)
|
|
866
|
-
if ! init_result=$(python3 "$SCRIPTS_DIR/init-bugfix-pipeline.py" \
|
|
867
|
-
--bug-list "$bug_list" \
|
|
868
|
-
--state-dir "$STATE_DIR" 2>"$init_tmpstderr"); then
|
|
869
|
-
init_stderr=$(cat "$init_tmpstderr" 2>/dev/null || true)
|
|
870
|
-
rm -f "$init_tmpstderr"
|
|
871
|
-
if [[ -n "$init_stderr" ]]; then
|
|
872
|
-
log_warn "$init_stderr"
|
|
873
|
-
fi
|
|
874
|
-
log_error "Bugfix pipeline initialization failed (script error)"
|
|
875
|
-
exit 1
|
|
876
|
-
fi
|
|
877
|
-
init_stderr=$(cat "$init_tmpstderr" 2>/dev/null || true)
|
|
878
|
-
rm -f "$init_tmpstderr"
|
|
879
|
-
|
|
880
|
-
if [[ -n "$init_stderr" ]]; then
|
|
881
|
-
log_warn "$init_stderr"
|
|
882
|
-
fi
|
|
883
|
-
|
|
884
|
-
local init_valid
|
|
885
|
-
init_valid=$(echo "$init_result" | python3 -c "import sys,json; print(json.load(sys.stdin).get('valid', False))" 2>/dev/null || echo "False")
|
|
886
|
-
|
|
887
|
-
if [[ "$init_valid" != "True" ]]; then
|
|
888
|
-
log_error "Bugfix pipeline initialization failed:"
|
|
889
|
-
echo "$init_result"
|
|
890
|
-
exit 1
|
|
891
|
-
fi
|
|
892
|
-
|
|
893
|
-
local bugs_count
|
|
894
|
-
bugs_count=$(echo "$init_result" | python3 -c "import sys,json; print(json.load(sys.stdin).get('bugs_count', 0))" 2>/dev/null || echo "0")
|
|
895
|
-
log_success "Bugfix pipeline initialized with $bugs_count bugs"
|
|
896
|
-
else
|
|
897
|
-
log_info "Resuming existing bugfix pipeline..."
|
|
898
|
-
fi
|
|
899
|
-
|
|
900
|
-
# Print header
|
|
901
|
-
echo ""
|
|
902
|
-
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
903
|
-
echo -e "${BOLD} Bug-Fix Pipeline Runner Started${NC}"
|
|
904
|
-
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
905
|
-
log_info "Bug fix list: $bug_list"
|
|
906
|
-
log_info "Max code retries per bug: $MAX_RETRIES"
|
|
907
|
-
log_info "Max infrastructure retries per bug: $MAX_INFRA_RETRIES"
|
|
908
|
-
log_info "AI CLI: $CLI_CMD (platform: $PLATFORM)"
|
|
909
|
-
if [[ -n "${MODEL:-}" ]]; then
|
|
910
|
-
log_info "Default Model: $MODEL"
|
|
911
|
-
fi
|
|
912
|
-
if [[ "$STOP_ON_FAILURE" == "1" ]]; then
|
|
913
|
-
log_info "Stop on failure: enabled"
|
|
914
|
-
fi
|
|
915
|
-
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
916
|
-
echo ""
|
|
917
|
-
|
|
918
|
-
# Branch lifecycle: per-bug branches (like feature pipeline)
|
|
919
|
-
local _proj_root
|
|
920
|
-
_proj_root="$PROJECT_ROOT"
|
|
921
|
-
local _source_branch
|
|
922
|
-
_source_branch=$(git -C "$_proj_root" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
|
|
923
|
-
_ORIGINAL_BRANCH="$_source_branch"
|
|
924
|
-
|
|
925
|
-
local session_count=0
|
|
926
|
-
local total_subagent_calls=0
|
|
927
|
-
|
|
928
|
-
while true; do
|
|
929
|
-
# Safety net: ensure we're on the original branch at the start of each iteration.
|
|
930
|
-
# If a previous iteration's `continue` skipped branch_ensure_return, we could
|
|
931
|
-
# still be on a dev branch. This prevents cascading branch confusion.
|
|
932
|
-
if [[ -n "$_ORIGINAL_BRANCH" ]]; then
|
|
933
|
-
local _cur_branch
|
|
934
|
-
_cur_branch=$(git -C "$_proj_root" rev-parse --abbrev-ref HEAD 2>/dev/null || true)
|
|
935
|
-
if [[ -n "$_cur_branch" && "$_cur_branch" != "$_ORIGINAL_BRANCH" ]]; then
|
|
936
|
-
log_warn "Still on branch $_cur_branch at loop start — returning to $_ORIGINAL_BRANCH"
|
|
937
|
-
branch_ensure_return "$_proj_root" "$_ORIGINAL_BRANCH"
|
|
938
|
-
fi
|
|
939
|
-
fi
|
|
940
|
-
|
|
941
|
-
# Find next bug to process
|
|
942
|
-
local next_bug
|
|
943
|
-
if ! next_bug=$(python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
944
|
-
--bug-list "$bug_list" \
|
|
945
|
-
--state-dir "$STATE_DIR" \
|
|
946
|
-
--max-retries "$MAX_RETRIES" \
|
|
947
|
-
--max-infra-retries "$MAX_INFRA_RETRIES" \
|
|
948
|
-
--action get_next 2>/dev/null); then
|
|
949
|
-
log_error "Failed to get next bug"
|
|
950
|
-
break
|
|
951
|
-
fi
|
|
952
|
-
|
|
953
|
-
if [[ "$next_bug" == "PIPELINE_COMPLETE" ]]; then
|
|
954
|
-
echo ""
|
|
955
|
-
log_success "════════════════════════════════════════════════════"
|
|
956
|
-
log_success " All bugs processed! Bug fix pipeline finished."
|
|
957
|
-
log_success " Total sessions: $session_count"
|
|
958
|
-
log_success " Total subagent calls: $total_subagent_calls"
|
|
959
|
-
log_success "════════════════════════════════════════════════════"
|
|
960
|
-
|
|
961
|
-
# ── Deploy session (only if ENABLE_DEPLOY=1 and all bugs fixed) ──
|
|
962
|
-
if [[ "$ENABLE_DEPLOY" == "1" ]]; then
|
|
963
|
-
local incomplete_count
|
|
964
|
-
incomplete_count=$({ python3 -c "
|
|
965
|
-
import json, sys
|
|
966
|
-
with open(sys.argv[1]) as f:
|
|
967
|
-
data = json.load(f)
|
|
968
|
-
bad = [b for b in data.get('bugs', [])
|
|
969
|
-
if b.get('status') not in ('completed', 'skipped', 'needs_info')]
|
|
970
|
-
for b in bad:
|
|
971
|
-
print(f\" {b['id']}: {b.get('status', 'unknown')} — {b.get('title', '')}\")
|
|
972
|
-
print(len(bad))
|
|
973
|
-
" "$bug_list" 2>/dev/null || echo "0"; } | tee /dev/stderr | tail -1)
|
|
974
|
-
|
|
975
|
-
if [[ "$incomplete_count" -gt 0 ]]; then
|
|
976
|
-
echo ""
|
|
977
|
-
log_warn "DEPLOY BLOCKED: $incomplete_count bug(s) not fixed successfully."
|
|
978
|
-
log_warn "Fix failed bugs and re-run, or manually run /prizmkit-deploy."
|
|
979
|
-
else
|
|
980
|
-
echo ""
|
|
981
|
-
log_info "All bugs fixed — starting deploy session..."
|
|
982
|
-
log_info "ENABLE_DEPLOY=1"
|
|
983
|
-
|
|
984
|
-
local deploy_session_id="deploy-$(date +%Y%m%d%H%M%S)"
|
|
985
|
-
local deploy_session_dir="$STATE_DIR/deploy/$deploy_session_id"
|
|
986
|
-
mkdir -p "$deploy_session_dir/logs"
|
|
987
|
-
|
|
988
|
-
local deploy_prompt="$deploy_session_dir/bootstrap-prompt.md"
|
|
989
|
-
local _deploy_branch _deploy_commit
|
|
990
|
-
_deploy_branch=$(git -C "$_proj_root" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
|
991
|
-
_deploy_commit=$(git -C "$_proj_root" rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
|
992
|
-
cat > "$deploy_prompt" << DEPLOY_PROMPT_EOF
|
|
993
|
-
## Deploy
|
|
994
|
-
|
|
995
|
-
All bugs have been fixed successfully.
|
|
996
|
-
|
|
997
|
-
- Branch: $_deploy_branch
|
|
998
|
-
- Commit: $_deploy_commit
|
|
999
|
-
|
|
1000
|
-
Run /prizmkit-deploy to deploy the project. Read .prizmkit/deploy/deploy.config.json
|
|
1001
|
-
for deployment configuration. If no deploy config exists, guide the user through
|
|
1002
|
-
setting one up before deploying.
|
|
1003
|
-
DEPLOY_PROMPT_EOF
|
|
1004
|
-
|
|
1005
|
-
log_info "Deploy prompt: $deploy_prompt"
|
|
1006
|
-
log_info "Deploy log: $deploy_session_dir/logs/session.log"
|
|
1007
|
-
|
|
1008
|
-
prizm_run_ai_session "$deploy_prompt" "$deploy_session_dir/logs/session.log"
|
|
1009
|
-
local deploy_exit=$?
|
|
1010
|
-
|
|
1011
|
-
# Recover log from backup if truncated
|
|
1012
|
-
prizm_recover_session_log "$deploy_session_dir/logs/session.log"
|
|
1013
|
-
|
|
1014
|
-
if [[ $deploy_exit -eq 0 ]]; then
|
|
1015
|
-
log_success "Deploy session completed (exit 0)"
|
|
1016
|
-
else
|
|
1017
|
-
log_warn "Deploy session exited with code $deploy_exit"
|
|
1018
|
-
log_warn "Review log: $deploy_session_dir/logs/session.log"
|
|
1019
|
-
fi
|
|
1020
|
-
fi
|
|
1021
|
-
fi
|
|
1022
|
-
|
|
1023
|
-
break
|
|
1024
|
-
fi
|
|
1025
|
-
|
|
1026
|
-
if [[ "$next_bug" == "PIPELINE_BLOCKED" ]]; then
|
|
1027
|
-
log_warn "All remaining bugs are blocked (needs_info/failed)."
|
|
1028
|
-
log_warn "Run './run-bugfix.sh status' to see details."
|
|
1029
|
-
log_warn "Waiting 60s before re-checking... (Ctrl+C to stop)"
|
|
1030
|
-
sleep 60
|
|
1031
|
-
continue
|
|
1032
|
-
fi
|
|
1033
|
-
|
|
1034
|
-
# Parse bug info
|
|
1035
|
-
local bug_id bug_title bug_severity retry_count infra_error_count resume_phase active_dev_branch base_branch continuation_pending continuation_reason context_overflow_count continuation_count previous_session_id no_progress_count
|
|
1036
|
-
bug_id=$(echo "$next_bug" | jq -r '.bug_id')
|
|
1037
|
-
bug_title=$(echo "$next_bug" | jq -r '.title')
|
|
1038
|
-
bug_severity=$(echo "$next_bug" | jq -r '.severity')
|
|
1039
|
-
retry_count=$(echo "$next_bug" | jq -r '.retry_count // 0')
|
|
1040
|
-
infra_error_count=$(echo "$next_bug" | jq -r '.infra_error_count // 0')
|
|
1041
|
-
resume_phase=$(echo "$next_bug" | jq -r '.resume_from_phase // "null"')
|
|
1042
|
-
active_dev_branch=$(echo "$next_bug" | jq -r '.active_dev_branch // ""')
|
|
1043
|
-
base_branch=$(echo "$next_bug" | jq -r '.base_branch // ""')
|
|
1044
|
-
continuation_pending=$(echo "$next_bug" | jq -r '.continuation_pending // false')
|
|
1045
|
-
continuation_reason=$(echo "$next_bug" | jq -r '.continuation_reason // ""')
|
|
1046
|
-
context_overflow_count=$(echo "$next_bug" | jq -r '.context_overflow_count // 0')
|
|
1047
|
-
continuation_count=$(echo "$next_bug" | jq -r '.continuation_count // 0')
|
|
1048
|
-
previous_session_id=$(echo "$next_bug" | jq -r '.last_context_overflow_session_id // ""')
|
|
1049
|
-
no_progress_count=$(echo "$next_bug" | jq -r '.no_progress_count // 0')
|
|
1050
|
-
|
|
1051
|
-
echo ""
|
|
1052
|
-
echo -e "${BOLD}────────────────────────────────────────────────────${NC}"
|
|
1053
|
-
log_info "Bug: ${BOLD}$bug_id${NC} — $bug_title"
|
|
1054
|
-
log_info "Severity: $bug_severity"
|
|
1055
|
-
log_info "Code retry: $retry_count / $MAX_RETRIES"
|
|
1056
|
-
log_info "Infrastructure retry: $infra_error_count / $MAX_INFRA_RETRIES"
|
|
1057
|
-
if [[ "$resume_phase" != "null" ]]; then
|
|
1058
|
-
log_info "Resuming from Phase $resume_phase"
|
|
1059
|
-
fi
|
|
1060
|
-
if [[ "$continuation_pending" == "true" && -n "$active_dev_branch" ]]; then
|
|
1061
|
-
log_info "Continuation pending (${continuation_reason:-context_overflow}); reusing dev branch: $active_dev_branch"
|
|
1062
|
-
log_info "Continuation count: $continuation_count (context overflows: $context_overflow_count)"
|
|
1063
|
-
fi
|
|
1064
|
-
echo -e "${BOLD}────────────────────────────────────────────────────${NC}"
|
|
1065
|
-
|
|
1066
|
-
# Auto-commit any uncommitted workspace changes before starting the pipeline.
|
|
1067
|
-
# This ensures a clean baseline without blocking execution.
|
|
1068
|
-
local _dirty_files=""
|
|
1069
|
-
_dirty_files=$(prizm_git_status_non_bookkeeping "$_proj_root" "$STATE_DIR" "$bug_list" || true)
|
|
1070
|
-
if [[ -n "$_dirty_files" ]]; then
|
|
1071
|
-
log_info "Auto-committing workspace changes before $bug_id..."
|
|
1072
|
-
prizm_git_add_all_safe "$_proj_root"
|
|
1073
|
-
git -C "$_proj_root" commit --no-verify -m "chore: workspace snapshot ready for run $bug_id" 2>/dev/null || true
|
|
1074
|
-
fi
|
|
1075
|
-
|
|
1076
|
-
local _bookkeeping_dirty=""
|
|
1077
|
-
_bookkeeping_dirty=$(prizm_git_status_bookkeeping "$_proj_root" "$STATE_DIR" "$bug_list" || true)
|
|
1078
|
-
if [[ -n "$_bookkeeping_dirty" ]]; then
|
|
1079
|
-
log_info "Committing pending pipeline bookkeeping before $bug_id..."
|
|
1080
|
-
prizm_git_commit_paths "$_proj_root" "chore($bug_id): include pipeline bookkeeping" "$bug_list" "$STATE_DIR"
|
|
1081
|
-
fi
|
|
1082
|
-
|
|
1083
|
-
# Mark bug as in-progress BEFORE creating dev branch
|
|
1084
|
-
# This ensures the in_progress status commit lands on the original branch,
|
|
1085
|
-
# not the dev branch — preventing rebase conflicts in branch_merge later.
|
|
1086
|
-
python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
1087
|
-
--bug-list "$bug_list" \
|
|
1088
|
-
--state-dir "$STATE_DIR" \
|
|
1089
|
-
--bug-id "$bug_id" \
|
|
1090
|
-
--action start >/dev/null 2>&1 || true
|
|
1091
|
-
# Commit the in_progress status on the original branch
|
|
1092
|
-
if ! git -C "$_proj_root" diff --quiet "$bug_list" 2>/dev/null; then
|
|
1093
|
-
prizm_git_commit_paths "$_proj_root" "chore($bug_id): mark in_progress" "$bug_list"
|
|
1094
|
-
fi
|
|
1095
|
-
|
|
1096
|
-
# Continuation base branch from runtime state is authoritative for branch reuse.
|
|
1097
|
-
if [[ "$continuation_pending" == "true" && -n "$base_branch" ]]; then
|
|
1098
|
-
_ORIGINAL_BRANCH="$base_branch"
|
|
1099
|
-
fi
|
|
1100
|
-
|
|
1101
|
-
# Create or reuse per-bug dev branch (from the now-updated original branch)
|
|
1102
|
-
local _bug_branch
|
|
1103
|
-
if [[ -n "$DEV_BRANCH" ]]; then
|
|
1104
|
-
_bug_branch="$DEV_BRANCH"
|
|
1105
|
-
elif [[ "$continuation_pending" == "true" && -n "$active_dev_branch" ]]; then
|
|
1106
|
-
_bug_branch="$active_dev_branch"
|
|
1107
|
-
else
|
|
1108
|
-
_bug_branch="bugfix/${bug_id}-$(date +%Y%m%d%H%M)"
|
|
1109
|
-
fi
|
|
1110
|
-
if branch_create "$_proj_root" "$_bug_branch" "$_ORIGINAL_BRANCH"; then
|
|
1111
|
-
_DEV_BRANCH_NAME="$_bug_branch"
|
|
1112
|
-
log_info "Dev branch: $_bug_branch"
|
|
1113
|
-
else
|
|
1114
|
-
log_error "Failed to create dev branch: $_bug_branch from $_ORIGINAL_BRANCH — aborting to avoid running on $_ORIGINAL_BRANCH"
|
|
1115
|
-
_DEV_BRANCH_NAME=""
|
|
1116
|
-
break
|
|
1117
|
-
fi
|
|
1118
|
-
|
|
1119
|
-
while true; do
|
|
1120
|
-
# Generate session
|
|
1121
|
-
local session_id run_id
|
|
1122
|
-
run_id=$(jq -r '.run_id' "$STATE_DIR/pipeline.json")
|
|
1123
|
-
session_id="${bug_id}-$(date +%Y%m%d%H%M%S)"
|
|
1124
|
-
|
|
1125
|
-
local session_dir="$STATE_DIR/$bug_id/sessions/$session_id"
|
|
1126
|
-
mkdir -p "$session_dir/logs"
|
|
1127
|
-
|
|
1128
|
-
local bootstrap_prompt="$session_dir/bootstrap-prompt.md"
|
|
1129
|
-
local continuation_summary_path=".prizmkit/bugfix/${bug_id}/continuation-summary.md"
|
|
1130
|
-
|
|
1131
|
-
local main_prompt_args=(
|
|
1132
|
-
--bug-list "$bug_list"
|
|
1133
|
-
--bug-id "$bug_id"
|
|
1134
|
-
--session-id "$session_id"
|
|
1135
|
-
--run-id "$run_id"
|
|
1136
|
-
--retry-count "$retry_count"
|
|
1137
|
-
--resume-phase "$resume_phase"
|
|
1138
|
-
--state-dir "$STATE_DIR"
|
|
1139
|
-
--output "$bootstrap_prompt"
|
|
1140
|
-
)
|
|
1141
|
-
|
|
1142
|
-
if [[ "$continuation_pending" == "true" ]]; then
|
|
1143
|
-
main_prompt_args+=(
|
|
1144
|
-
--continuation-mode "${continuation_reason:-context_overflow}"
|
|
1145
|
-
--previous-session-id "$previous_session_id"
|
|
1146
|
-
--continuation-count "$continuation_count"
|
|
1147
|
-
--context-overflow-count "$context_overflow_count"
|
|
1148
|
-
--task-type "bugfix"
|
|
1149
|
-
--active-dev-branch "$active_dev_branch"
|
|
1150
|
-
--base-branch "$base_branch"
|
|
1151
|
-
--continuation-summary-path "$continuation_summary_path"
|
|
1152
|
-
)
|
|
1153
|
-
fi
|
|
1154
|
-
|
|
1155
|
-
# Support PIPELINE_MODE env var (set by launch-bugfix-daemon.sh --mode)
|
|
1156
|
-
if [[ -n "${PIPELINE_MODE:-}" ]]; then
|
|
1157
|
-
main_prompt_args+=(--mode "$PIPELINE_MODE")
|
|
1158
|
-
fi
|
|
1159
|
-
|
|
1160
|
-
# Support ENABLE_CRITIC env var (set by launch-bugfix-daemon.sh --critic)
|
|
1161
|
-
if [[ "${ENABLE_CRITIC:-}" == "true" || "${ENABLE_CRITIC:-}" == "1" ]]; then
|
|
1162
|
-
main_prompt_args+=(--critic "true")
|
|
1163
|
-
elif [[ "${ENABLE_CRITIC:-}" == "false" || "${ENABLE_CRITIC:-}" == "0" ]]; then
|
|
1164
|
-
main_prompt_args+=(--critic "false")
|
|
1165
|
-
fi
|
|
1166
|
-
|
|
1167
|
-
local gen_output
|
|
1168
|
-
gen_output=$(python3 "$SCRIPTS_DIR/generate-bugfix-prompt.py" "${main_prompt_args[@]}" 2>/dev/null) || {
|
|
1169
|
-
log_error "Failed to generate bootstrap prompt for $bug_id"
|
|
1170
|
-
branch_ensure_return "$_proj_root" "$_ORIGINAL_BRANCH"
|
|
1171
|
-
_DEV_BRANCH_NAME=""
|
|
1172
|
-
continue 2
|
|
1173
|
-
}
|
|
1174
|
-
local bug_model pipeline_mode agent_count critic_enabled
|
|
1175
|
-
bug_model=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))" 2>/dev/null || echo "")
|
|
1176
|
-
pipeline_mode=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('pipeline_mode','standard'))" 2>/dev/null || echo "standard")
|
|
1177
|
-
agent_count=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('agent_count',3))" 2>/dev/null || echo "3")
|
|
1178
|
-
critic_enabled=$(echo "$gen_output" | python3 -c "import json,sys; print(json.load(sys.stdin).get('critic_enabled','false'))" 2>/dev/null || echo "false")
|
|
1179
|
-
|
|
1180
|
-
# Log pipeline mode and agent configuration
|
|
1181
|
-
local _mode_desc
|
|
1182
|
-
case "$pipeline_mode" in
|
|
1183
|
-
lite) _mode_desc="Tier 1 — Single Agent" ;;
|
|
1184
|
-
standard) _mode_desc="Tier 2 — Orchestrator + Dev + Reviewer" ;;
|
|
1185
|
-
full) _mode_desc="Tier 3 — Full Team (+ Multi-Critic)" ;;
|
|
1186
|
-
*) _mode_desc="$pipeline_mode" ;;
|
|
1187
|
-
esac
|
|
1188
|
-
log_info "Pipeline mode: ${BOLD}$pipeline_mode${NC} ($_mode_desc)"
|
|
1189
|
-
log_info "Agents: $agent_count (critic: $([ "$critic_enabled" = "true" ] && echo "enabled" || echo "disabled"))"
|
|
1190
|
-
if [[ -n "$bug_model" ]]; then
|
|
1191
|
-
log_info "Bug model: $bug_model"
|
|
1192
|
-
fi
|
|
1193
|
-
|
|
1194
|
-
local continuation_artifact_dir=".prizmkit/bugfix/${bug_id}"
|
|
1195
|
-
local continuation_checkpoint_path="$continuation_artifact_dir/workflow-checkpoint.json"
|
|
1196
|
-
local progress_before progress_after
|
|
1197
|
-
progress_before=$(prizm_context_progress_fingerprint "$_proj_root" "bugfix" "$bug_id" "$continuation_artifact_dir" "$continuation_checkpoint_path")
|
|
1198
|
-
|
|
1199
|
-
# Spawn session
|
|
1200
|
-
log_info "Spawning AI CLI session: $session_id"
|
|
1201
|
-
_SPAWN_RESULT=""
|
|
1202
|
-
_SPAWN_ITEM_STATUS=""
|
|
1203
|
-
|
|
1204
|
-
spawn_and_wait_session \
|
|
1205
|
-
"$bug_id" "$bug_list" "$session_id" \
|
|
1206
|
-
"$bootstrap_prompt" "$session_dir" "$MAX_RETRIES" "$MAX_INFRA_RETRIES" "$bug_model" "$_ORIGINAL_BRANCH"
|
|
1207
|
-
|
|
1208
|
-
local session_status="$_SPAWN_RESULT"
|
|
1209
|
-
|
|
1210
|
-
# Merge per-bug dev branch back to original on success
|
|
1211
|
-
local active_dev_branch_for_status="$_DEV_BRANCH_NAME"
|
|
1212
|
-
if [[ "$session_status" == "context_overflow" ]]; then
|
|
1213
|
-
progress_after=$(prizm_context_progress_fingerprint "$_proj_root" "bugfix" "$bug_id" "$continuation_artifact_dir" "$continuation_checkpoint_path")
|
|
1214
|
-
if prizm_context_progress_changed "$progress_before" "$progress_after"; then
|
|
1215
|
-
no_progress_count=0
|
|
1216
|
-
log_info "Context-overflow session made observable progress; continuing on $_DEV_BRANCH_NAME"
|
|
1217
|
-
else
|
|
1218
|
-
no_progress_count=$((no_progress_count + 1))
|
|
1219
|
-
log_warn "Context-overflow session made no observable progress ($no_progress_count consecutive)"
|
|
1220
|
-
fi
|
|
1221
|
-
if [[ "$no_progress_count" -ge 2 ]]; then
|
|
1222
|
-
log_warn "Pausing automatic continuation: context_overflow_without_git_checkpoint_or_artifact_progress"
|
|
1223
|
-
session_status="stalled_context_continuation"
|
|
1224
|
-
else
|
|
1225
|
-
finalize_bug_status_after_branch_return \
|
|
1226
|
-
"$bug_id" "$bug_list" "$session_id" "$session_status" "$MAX_RETRIES" "$MAX_INFRA_RETRIES" "$_ORIGINAL_BRANCH" "$active_dev_branch_for_status" "context_overflow" "$continuation_summary_path" "$no_progress_count" "$progress_after"
|
|
1227
|
-
session_count=$((session_count + 1))
|
|
1228
|
-
total_subagent_calls=$((total_subagent_calls + _SUBAGENT_COUNT))
|
|
1229
|
-
continuation_pending="true"
|
|
1230
|
-
continuation_reason="context_overflow"
|
|
1231
|
-
previous_session_id="$session_id"
|
|
1232
|
-
active_dev_branch="$_DEV_BRANCH_NAME"
|
|
1233
|
-
base_branch="$_ORIGINAL_BRANCH"
|
|
1234
|
-
context_overflow_count=$((context_overflow_count + 1))
|
|
1235
|
-
continuation_count=$((continuation_count + 1))
|
|
1236
|
-
log_info "Launching automatic continuation for $bug_id on same branch/worktree"
|
|
1237
|
-
continue
|
|
1238
|
-
fi
|
|
1239
|
-
fi
|
|
1240
|
-
|
|
1241
|
-
if [[ "$session_status" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
|
|
1242
|
-
if branch_merge "$_proj_root" "$_DEV_BRANCH_NAME" "$_ORIGINAL_BRANCH" "$AUTO_PUSH"; then
|
|
1243
|
-
_DEV_BRANCH_NAME=""
|
|
1244
|
-
else
|
|
1245
|
-
log_warn "Auto-merge failed — dev branch preserved: $_DEV_BRANCH_NAME"
|
|
1246
|
-
log_warn "Merge manually: git checkout $_ORIGINAL_BRANCH && git rebase $_DEV_BRANCH_NAME"
|
|
1247
|
-
session_status="merge_conflict"
|
|
1248
|
-
fi
|
|
1249
|
-
elif [[ -n "$_DEV_BRANCH_NAME" ]]; then
|
|
1250
|
-
# Session failed — preserve dev branch for inspection
|
|
1251
|
-
log_warn "Session failed — dev branch preserved for inspection: $_DEV_BRANCH_NAME"
|
|
1252
|
-
fi
|
|
1253
|
-
|
|
1254
|
-
# GUARANTEED: always return to original branch regardless of success/failure/merge outcome
|
|
1255
|
-
branch_ensure_return "$_proj_root" "$_ORIGINAL_BRANCH"
|
|
1256
|
-
|
|
1257
|
-
finalize_bug_status_after_branch_return \
|
|
1258
|
-
"$bug_id" "$bug_list" "$session_id" "$session_status" "$MAX_RETRIES" "$MAX_INFRA_RETRIES" "$_ORIGINAL_BRANCH" "$active_dev_branch_for_status" "context_overflow" "$continuation_summary_path" "$no_progress_count" "${progress_after:-}"
|
|
1259
|
-
local item_status_after_session="${_SPAWN_ITEM_STATUS:-}"
|
|
1260
|
-
|
|
1261
|
-
# Commit bug status update on the original branch (after guaranteed return)
|
|
1262
|
-
if ! git -C "$_proj_root" diff --quiet "$bug_list" 2>/dev/null; then
|
|
1263
|
-
prizm_git_commit_paths "$_proj_root" "chore($bug_id): update bug status" "$bug_list"
|
|
1264
|
-
fi
|
|
1265
|
-
|
|
1266
|
-
session_count=$((session_count + 1))
|
|
1267
|
-
total_subagent_calls=$((total_subagent_calls + _SUBAGENT_COUNT))
|
|
1268
|
-
break
|
|
1269
|
-
done
|
|
1270
|
-
|
|
1271
|
-
# Stop-on-failure: abort only after the task is actually marked failed.
|
|
1272
|
-
# Pending retry outcomes, including infrastructure errors, keep running.
|
|
1273
|
-
if [[ "$session_status" != "success" && "$STOP_ON_FAILURE" == "1" && "$item_status_after_session" == "failed" ]]; then
|
|
1274
|
-
echo ""
|
|
1275
|
-
log_error "════════════════════════════════════════════════════"
|
|
1276
|
-
log_error " STOP_ON_FAILURE: Pipeline halted after $bug_id exhausted retries."
|
|
1277
|
-
log_error " Total sessions completed: $session_count"
|
|
1278
|
-
log_error " Set STOP_ON_FAILURE=0 to continue past failures."
|
|
1279
|
-
log_error "════════════════════════════════════════════════════"
|
|
1280
|
-
break
|
|
1281
|
-
elif [[ "$session_status" != "success" && "$STOP_ON_FAILURE" == "1" ]]; then
|
|
1282
|
-
log_info "STOP_ON_FAILURE: $bug_id is ${item_status_after_session:-unknown}; code/infra retry budget not exhausted, continuing."
|
|
1283
|
-
fi
|
|
1284
|
-
|
|
1285
|
-
# Stuck detection
|
|
1286
|
-
if python3 "$SCRIPTS_DIR/detect-stuck.py" \
|
|
1287
|
-
--state-dir "$STATE_DIR" \
|
|
1288
|
-
--pipeline-type bugfix \
|
|
1289
|
-
--bug-list "$bug_list" \
|
|
1290
|
-
--max-retries "$MAX_RETRIES" \
|
|
1291
|
-
2>/dev/null | jq -e '.stuck_count > 0' >/dev/null 2>&1; then
|
|
1292
|
-
log_warn "STUCK_DETECTED: Some bugs may be stuck — run detect-stuck.py for details"
|
|
1293
|
-
fi
|
|
1294
|
-
|
|
1295
|
-
# Completion notes propagation (on success)
|
|
1296
|
-
if [ "$_SPAWN_RESULT" = "success" ]; then
|
|
1297
|
-
local _summary_path="$PRIZMKIT_DIR/bugfix/${bug_id}/completion-summary.json"
|
|
1298
|
-
if [ -f "$_summary_path" ]; then
|
|
1299
|
-
python3 "$SCRIPTS_DIR/patch-completion-notes.py" \
|
|
1300
|
-
--bug-list "$bug_list" \
|
|
1301
|
-
--bug-id "$bug_id" \
|
|
1302
|
-
--summary "$_summary_path" 2>/dev/null || true
|
|
1303
|
-
fi
|
|
1304
|
-
fi
|
|
1305
|
-
|
|
1306
|
-
log_info "Pausing 5s before next bug..."
|
|
1307
|
-
sleep 5
|
|
1308
|
-
done
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
# ============================================================
|
|
1312
|
-
# Entry Point
|
|
1313
|
-
# ============================================================
|
|
1314
|
-
|
|
1315
|
-
show_help() {
|
|
1316
|
-
echo "Usage: $0 <command> [options]"
|
|
1317
|
-
echo ""
|
|
1318
|
-
echo "Commands:"
|
|
1319
|
-
echo " run [.prizmkit/plans/bug-fix-list.json] [options] Run all bugs by severity/priority order"
|
|
1320
|
-
echo " run <bug-id> [options] Run a single bug fix"
|
|
1321
|
-
echo " status [.prizmkit/plans/bug-fix-list.json] Show bug fix pipeline status"
|
|
1322
|
-
echo " reset Clear all bugfix state"
|
|
1323
|
-
echo " help Show this help message"
|
|
1324
|
-
echo ""
|
|
1325
|
-
echo "Single Bug Options (run <bug-id>):"
|
|
1326
|
-
echo " --dry-run Generate bootstrap prompt only, don't spawn session"
|
|
1327
|
-
echo " --clean Delete artifacts and reset before running"
|
|
1328
|
-
echo " --no-reset Skip status reset (preserve retry count)"
|
|
1329
|
-
echo " --max-infra-retries N Max infrastructure/provider retries (default: 3)"
|
|
1330
|
-
echo " --mode <lite|standard|full> Override pipeline mode"
|
|
1331
|
-
echo " --critic Enable adversarial critic review"
|
|
1332
|
-
echo " --no-critic Disable adversarial critic review"
|
|
1333
|
-
echo ""
|
|
1334
|
-
echo "Pipeline Options (run all):"
|
|
1335
|
-
echo " --max-infra-retries N Max infrastructure/provider retries (default: 3)"
|
|
1336
|
-
echo ""
|
|
1337
|
-
echo "Environment Variables:"
|
|
1338
|
-
echo " MAX_RETRIES Max code retries per bug (default: 3)"
|
|
1339
|
-
echo " MAX_INFRA_RETRIES Max infrastructure/provider retries per bug (default: 3)"
|
|
1340
|
-
echo " MODEL Default AI model (overridden by per-bug model in bug list)"
|
|
1341
|
-
echo " PRIZMKIT_EFFORT AI reasoning effort (low|medium|high|xhigh|max; max is Claude Code only)"
|
|
1342
|
-
echo " PIPELINE_MODE Default pipeline mode: lite|standard|full (overridden by --mode)"
|
|
1343
|
-
echo " ENABLE_CRITIC Enable/disable critic: true|false|1|0 (overridden by --critic/--no-critic)"
|
|
1344
|
-
echo " AI_CLI AI CLI command name (auto-detected: cbc, claude, or codex)"
|
|
1345
|
-
echo " VERBOSE Set to 1 for verbose AI CLI output"
|
|
1346
|
-
echo " HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)"
|
|
1347
|
-
echo " STALE_KILL_THRESHOLD Auto-kill session after N seconds of no progress (default: 900)"
|
|
1348
|
-
echo " MAX_LOG_SIZE Include passive log-size checkpoint guidance above this threshold (default: 2097152 = 2MB, set 0 to disable)"
|
|
1349
|
-
echo " STOP_ON_FAILURE Stop pipeline when a task exhausts retries: 0|1 (default: 0)"
|
|
1350
|
-
echo ""
|
|
1351
|
-
echo "Examples:"
|
|
1352
|
-
echo " ./run-bugfix.sh run # Run all bugs"
|
|
1353
|
-
echo " ./run-bugfix.sh run .prizmkit/plans/bug-fix-list.json # Custom bug list"
|
|
1354
|
-
echo " ./run-bugfix.sh run B-001 --dry-run # Inspect generated prompt"
|
|
1355
|
-
echo " ./run-bugfix.sh run B-001 --clean # Clean artifacts + reset + run"
|
|
1356
|
-
echo " ./run-bugfix.sh run B-001 --no-reset # Retry without resetting status"
|
|
1357
|
-
echo " ./run-bugfix.sh status # Show status"
|
|
1358
|
-
echo " MAX_RETRIES=5 ./run-bugfix.sh run # Custom retries"
|
|
1359
|
-
}
|
|
1360
|
-
|
|
1361
|
-
case "${1:-run}" in
|
|
1362
|
-
run|resume)
|
|
1363
|
-
shift || true
|
|
1364
|
-
if [[ "${1:-}" =~ ^[Bb]-[0-9]+ ]]; then
|
|
1365
|
-
run_one "$@"
|
|
1366
|
-
else
|
|
1367
|
-
main "$@"
|
|
1368
|
-
fi
|
|
1369
|
-
;;
|
|
1370
|
-
status)
|
|
1371
|
-
check_dependencies
|
|
1372
|
-
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
1373
|
-
log_error "No bugfix pipeline state found. Run './run-bugfix.sh run' first."
|
|
1374
|
-
exit 1
|
|
1375
|
-
fi
|
|
1376
|
-
python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
1377
|
-
--bug-list "${2:-$PRIZMKIT_DIR/plans/bug-fix-list.json}" \
|
|
1378
|
-
--state-dir "$STATE_DIR" \
|
|
1379
|
-
--max-retries "$MAX_RETRIES" \
|
|
1380
|
-
--max-infra-retries "$MAX_INFRA_RETRIES" \
|
|
1381
|
-
--action status
|
|
1382
|
-
;;
|
|
1383
|
-
reset)
|
|
1384
|
-
log_warn "Resetting bugfix pipeline state..."
|
|
1385
|
-
rm -rf "$STATE_DIR"
|
|
1386
|
-
log_success "Bugfix state cleared. Run './run-bugfix.sh run' to start fresh."
|
|
1387
|
-
;;
|
|
1388
|
-
unskip)
|
|
1389
|
-
check_dependencies
|
|
1390
|
-
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
1391
|
-
log_error "No bugfix pipeline state found. Run './run-bugfix.sh run' first."
|
|
1392
|
-
exit 1
|
|
1393
|
-
fi
|
|
1394
|
-
_unskip_bug_list="$PRIZMKIT_DIR/plans/bug-fix-list.json"
|
|
1395
|
-
_unskip_bug_id=""
|
|
1396
|
-
shift || true
|
|
1397
|
-
# Parse arguments: optional bug-id and bug-list path
|
|
1398
|
-
while [[ $# -gt 0 ]]; do
|
|
1399
|
-
if [[ "$1" =~ ^[Bb]-[0-9]+ ]]; then
|
|
1400
|
-
_unskip_bug_id="$1"
|
|
1401
|
-
else
|
|
1402
|
-
_unskip_bug_list="$1"
|
|
1403
|
-
fi
|
|
1404
|
-
shift
|
|
1405
|
-
done
|
|
1406
|
-
_unskip_args=(
|
|
1407
|
-
--bug-list "$_unskip_bug_list"
|
|
1408
|
-
--state-dir "$STATE_DIR"
|
|
1409
|
-
--action unskip
|
|
1410
|
-
)
|
|
1411
|
-
if [[ -n "$_unskip_bug_id" ]]; then
|
|
1412
|
-
_unskip_args+=(--bug-id "$_unskip_bug_id")
|
|
1413
|
-
fi
|
|
1414
|
-
python3 "$SCRIPTS_DIR/update-bug-status.py" "${_unskip_args[@]}"
|
|
1415
|
-
|
|
1416
|
-
# Commit the status change
|
|
1417
|
-
if ! git diff --quiet "$_unskip_bug_list" 2>/dev/null; then
|
|
1418
|
-
git add "$_unskip_bug_list"
|
|
1419
|
-
git commit -m "chore: unskip skipped bugs" 2>/dev/null || true
|
|
1420
|
-
fi
|
|
1421
|
-
;;
|
|
1422
|
-
help|--help|-h)
|
|
1423
|
-
show_help
|
|
1424
|
-
;;
|
|
1425
|
-
*)
|
|
1426
|
-
log_error "Unknown command: $1"
|
|
1427
|
-
show_help
|
|
1428
|
-
exit 1
|
|
1429
|
-
;;
|
|
1430
|
-
esac
|