prizmkit 1.1.100 → 1.1.101
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 +345 -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 +147 -0
- package/bundled/dev-pipeline/prizmkit_runtime/runners.py +422 -0
- package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +552 -0
- package/bundled/dev-pipeline/prizmkit_runtime/status.py +71 -0
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +38 -23
- 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 +7 -1
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +4 -0
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +12 -3
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +13 -3
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +13 -3
- 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/test-failure-recovery-agent.md +4 -0
- package/bundled/dev-pipeline/templates/sections/test-failure-recovery-lite.md +4 -0
- package/bundled/dev-pipeline/tests/test_auto_skip.py +436 -14
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +104 -0
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +40 -0
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +1138 -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 +33 -12
- package/src/index.js +3 -6
- package/src/manifest.js +3 -2
- package/src/metadata.js +7 -18
- package/src/prompts.js +0 -12
- package/src/runtimes.js +18 -11
- package/src/scaffold.js +133 -116
- package/src/upgrade.js +1 -1
- 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
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
"""Data models and legacy argument normalization for Python pipeline runners."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from collections.abc import Mapping, Sequence
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from .paths import RuntimePaths
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class RunnerFamily:
|
|
15
|
+
"""Static metadata for one foreground pipeline family."""
|
|
16
|
+
|
|
17
|
+
kind: str
|
|
18
|
+
id_prefix: str
|
|
19
|
+
list_key: str
|
|
20
|
+
list_arg: str
|
|
21
|
+
item_id_arg: str
|
|
22
|
+
state_dir: Path
|
|
23
|
+
plan_path: Path
|
|
24
|
+
updater_script: Path
|
|
25
|
+
prompt_script: Path
|
|
26
|
+
branch_prefix: str
|
|
27
|
+
artifact_root_name: str
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def task_type(self) -> str:
|
|
31
|
+
return self.kind
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass(frozen=True)
|
|
35
|
+
class RunnerEnvironment:
|
|
36
|
+
"""Legacy runner environment controls modeled as one cohesive unit."""
|
|
37
|
+
|
|
38
|
+
stop_on_failure: bool = False
|
|
39
|
+
auto_push: bool = False
|
|
40
|
+
use_worktree: bool = True
|
|
41
|
+
dev_branch: str = ""
|
|
42
|
+
enable_deploy: bool = False
|
|
43
|
+
verbose: bool = False
|
|
44
|
+
heartbeat_interval_seconds: int = 30
|
|
45
|
+
heartbeat_stale_threshold_seconds: int = 600
|
|
46
|
+
stale_kill_threshold_seconds: int = 600
|
|
47
|
+
max_log_size: int | None = None
|
|
48
|
+
strict_behavior_check: bool = True
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def from_env(cls, env: Mapping[str, str] | None = None) -> "RunnerEnvironment":
|
|
52
|
+
values = dict(os.environ if env is None else env)
|
|
53
|
+
return cls(
|
|
54
|
+
stop_on_failure=_truthy(values.get("STOP_ON_FAILURE")),
|
|
55
|
+
auto_push=_truthy(values.get("AUTO_PUSH")),
|
|
56
|
+
use_worktree=not _falsey(values.get("USE_WORKTREE")),
|
|
57
|
+
dev_branch=values.get("DEV_BRANCH", ""),
|
|
58
|
+
enable_deploy=_truthy(values.get("ENABLE_DEPLOY")),
|
|
59
|
+
verbose=_truthy(values.get("VERBOSE")),
|
|
60
|
+
heartbeat_interval_seconds=_int_value(values, "HEARTBEAT_INTERVAL", 30),
|
|
61
|
+
heartbeat_stale_threshold_seconds=_int_value(
|
|
62
|
+
values,
|
|
63
|
+
"HEARTBEAT_STALE_THRESHOLD",
|
|
64
|
+
_int_value(values, "HEARTBEAT_TIMEOUT_SECONDS", 600),
|
|
65
|
+
),
|
|
66
|
+
stale_kill_threshold_seconds=_int_value(values, "STALE_KILL_THRESHOLD", 600),
|
|
67
|
+
max_log_size=_optional_int(values.get("MAX_LOG_SIZE")),
|
|
68
|
+
strict_behavior_check=not _falsey(values.get("STRICT_BEHAVIOR_CHECK")),
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass(frozen=True)
|
|
73
|
+
class RunnerInvocation:
|
|
74
|
+
"""Normalized legacy CLI arguments for one runner invocation."""
|
|
75
|
+
|
|
76
|
+
action: str
|
|
77
|
+
list_path: Path
|
|
78
|
+
item_id: str = ""
|
|
79
|
+
item_filter: str = ""
|
|
80
|
+
max_infra_retries: int = 3
|
|
81
|
+
mode: str | None = None
|
|
82
|
+
critic: bool | None = None
|
|
83
|
+
dry_run: bool = False
|
|
84
|
+
clean: bool = False
|
|
85
|
+
no_reset: bool = False
|
|
86
|
+
resume_phase: str = "null"
|
|
87
|
+
help_requested: bool = False
|
|
88
|
+
unknown_args: tuple[str, ...] = ()
|
|
89
|
+
raw_args: tuple[str, ...] = ()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@dataclass(frozen=True)
|
|
93
|
+
class PromptGenerationResult:
|
|
94
|
+
"""Structured output from the existing prompt generators."""
|
|
95
|
+
|
|
96
|
+
output_path: Path
|
|
97
|
+
model: str = ""
|
|
98
|
+
pipeline_mode: str = ""
|
|
99
|
+
agent_count: int = 0
|
|
100
|
+
critic_enabled: bool = False
|
|
101
|
+
checkpoint_path: Path | None = None
|
|
102
|
+
artifact_path: Path | None = None
|
|
103
|
+
raw: Mapping[str, object] = field(default_factory=dict)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@dataclass(frozen=True)
|
|
107
|
+
class SessionPaths:
|
|
108
|
+
"""Canonical per-session runtime paths."""
|
|
109
|
+
|
|
110
|
+
session_dir: Path
|
|
111
|
+
prompt_path: Path
|
|
112
|
+
logs_dir: Path
|
|
113
|
+
session_log: Path
|
|
114
|
+
progress_json: Path
|
|
115
|
+
heartbeat_json: Path
|
|
116
|
+
session_status_json: Path
|
|
117
|
+
|
|
118
|
+
@classmethod
|
|
119
|
+
def for_item(cls, state_dir: Path, item_id: str, session_id: str) -> "SessionPaths":
|
|
120
|
+
session_dir = state_dir / item_id / "sessions" / session_id
|
|
121
|
+
logs_dir = session_dir / "logs"
|
|
122
|
+
return cls(
|
|
123
|
+
session_dir=session_dir,
|
|
124
|
+
prompt_path=session_dir / "bootstrap-prompt.md",
|
|
125
|
+
logs_dir=logs_dir,
|
|
126
|
+
session_log=logs_dir / "session.log",
|
|
127
|
+
progress_json=logs_dir / "progress.json",
|
|
128
|
+
heartbeat_json=logs_dir / "heartbeat.json",
|
|
129
|
+
session_status_json=session_dir / "session-status.json",
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@dataclass(frozen=True)
|
|
134
|
+
class ContinuationState:
|
|
135
|
+
"""Context-overflow continuation inputs for the next prompt/status update."""
|
|
136
|
+
|
|
137
|
+
active: bool = False
|
|
138
|
+
previous_session_id: str = ""
|
|
139
|
+
continuation_count: int = 0
|
|
140
|
+
context_overflow_count: int = 0
|
|
141
|
+
no_progress_count: int = 0
|
|
142
|
+
summary_path: Path | None = None
|
|
143
|
+
active_dev_branch: str = ""
|
|
144
|
+
base_branch: str = ""
|
|
145
|
+
fatal_error_code: str = "context_overflow"
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@dataclass(frozen=True)
|
|
149
|
+
class SessionClassification:
|
|
150
|
+
"""Final runner-owned session outcome before status updater mutation."""
|
|
151
|
+
|
|
152
|
+
session_status: str
|
|
153
|
+
reason: str = ""
|
|
154
|
+
fatal_error_code: str = ""
|
|
155
|
+
progress_fingerprint: Mapping[str, object] = field(default_factory=dict)
|
|
156
|
+
no_progress_count: int = 0
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@dataclass(frozen=True)
|
|
160
|
+
class PipelineRunResult:
|
|
161
|
+
"""Aggregated result for one foreground runner command."""
|
|
162
|
+
|
|
163
|
+
completed: bool
|
|
164
|
+
processed: int
|
|
165
|
+
stopped_reason: str = ""
|
|
166
|
+
last_status: str = ""
|
|
167
|
+
details: tuple[str, ...] = ()
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
FAMILY_KINDS = ("feature", "bugfix", "refactor")
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def family_for(kind: str, paths: RuntimePaths) -> RunnerFamily:
|
|
174
|
+
"""Return runner metadata for a supported pipeline family."""
|
|
175
|
+
script_dir = paths.pipeline_root / "scripts"
|
|
176
|
+
if kind == "feature":
|
|
177
|
+
return RunnerFamily(
|
|
178
|
+
kind="feature",
|
|
179
|
+
id_prefix="F-",
|
|
180
|
+
list_key="features",
|
|
181
|
+
list_arg="--feature-list",
|
|
182
|
+
item_id_arg="--feature-id",
|
|
183
|
+
state_dir=paths.feature_state_dir,
|
|
184
|
+
plan_path=paths.feature_plan,
|
|
185
|
+
updater_script=script_dir / "update-feature-status.py",
|
|
186
|
+
prompt_script=script_dir / "generate-bootstrap-prompt.py",
|
|
187
|
+
branch_prefix="dev",
|
|
188
|
+
artifact_root_name="specs",
|
|
189
|
+
)
|
|
190
|
+
if kind == "bugfix":
|
|
191
|
+
return RunnerFamily(
|
|
192
|
+
kind="bugfix",
|
|
193
|
+
id_prefix="B-",
|
|
194
|
+
list_key="bugs",
|
|
195
|
+
list_arg="--bug-list",
|
|
196
|
+
item_id_arg="--bug-id",
|
|
197
|
+
state_dir=paths.bugfix_state_dir,
|
|
198
|
+
plan_path=paths.bugfix_plan,
|
|
199
|
+
updater_script=script_dir / "update-bug-status.py",
|
|
200
|
+
prompt_script=script_dir / "generate-bugfix-prompt.py",
|
|
201
|
+
branch_prefix="bugfix",
|
|
202
|
+
artifact_root_name="bugfix",
|
|
203
|
+
)
|
|
204
|
+
if kind == "refactor":
|
|
205
|
+
return RunnerFamily(
|
|
206
|
+
kind="refactor",
|
|
207
|
+
id_prefix="R-",
|
|
208
|
+
list_key="refactors",
|
|
209
|
+
list_arg="--refactor-list",
|
|
210
|
+
item_id_arg="--refactor-id",
|
|
211
|
+
state_dir=paths.refactor_state_dir,
|
|
212
|
+
plan_path=paths.refactor_plan,
|
|
213
|
+
updater_script=script_dir / "update-refactor-status.py",
|
|
214
|
+
prompt_script=script_dir / "generate-refactor-prompt.py",
|
|
215
|
+
branch_prefix="refactor",
|
|
216
|
+
artifact_root_name="refactor",
|
|
217
|
+
)
|
|
218
|
+
raise ValueError(f"Unsupported runner family: {kind}")
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def parse_invocation(
|
|
222
|
+
family: RunnerFamily,
|
|
223
|
+
action: str,
|
|
224
|
+
legacy_args: Sequence[str] = (),
|
|
225
|
+
) -> RunnerInvocation:
|
|
226
|
+
"""Normalize legacy shell runner arguments without redesigning the interface."""
|
|
227
|
+
args = tuple(str(arg) for arg in legacy_args)
|
|
228
|
+
list_path = family.plan_path
|
|
229
|
+
item_id = ""
|
|
230
|
+
item_filter = ""
|
|
231
|
+
max_infra_retries = 3
|
|
232
|
+
mode: str | None = None
|
|
233
|
+
critic: bool | None = None
|
|
234
|
+
dry_run = False
|
|
235
|
+
clean = False
|
|
236
|
+
no_reset = False
|
|
237
|
+
resume_phase = "null"
|
|
238
|
+
unknown: list[str] = []
|
|
239
|
+
positional: list[str] = []
|
|
240
|
+
help_requested = False
|
|
241
|
+
|
|
242
|
+
index = 0
|
|
243
|
+
while index < len(args):
|
|
244
|
+
arg = args[index]
|
|
245
|
+
if arg in {"--help", "-h", "help"}:
|
|
246
|
+
help_requested = True
|
|
247
|
+
elif arg == "--dry-run":
|
|
248
|
+
dry_run = True
|
|
249
|
+
elif arg == "--clean":
|
|
250
|
+
clean = True
|
|
251
|
+
elif arg == "--no-reset":
|
|
252
|
+
no_reset = True
|
|
253
|
+
elif arg == "--critic":
|
|
254
|
+
critic = True
|
|
255
|
+
elif arg == "--no-critic":
|
|
256
|
+
critic = False
|
|
257
|
+
elif arg == "--features" and index + 1 < len(args):
|
|
258
|
+
index += 1
|
|
259
|
+
item_filter = args[index]
|
|
260
|
+
elif arg.startswith("--features="):
|
|
261
|
+
item_filter = arg.split("=", 1)[1]
|
|
262
|
+
elif arg == "--max-infra-retries" and index + 1 < len(args):
|
|
263
|
+
index += 1
|
|
264
|
+
max_infra_retries = _safe_int(args[index], 3)
|
|
265
|
+
elif arg.startswith("--max-infra-retries="):
|
|
266
|
+
max_infra_retries = _safe_int(arg.split("=", 1)[1], 3)
|
|
267
|
+
elif arg == "--mode" and index + 1 < len(args):
|
|
268
|
+
index += 1
|
|
269
|
+
mode = args[index]
|
|
270
|
+
elif arg.startswith("--mode="):
|
|
271
|
+
mode = arg.split("=", 1)[1]
|
|
272
|
+
elif arg == "--resume-phase" and index + 1 < len(args):
|
|
273
|
+
index += 1
|
|
274
|
+
resume_phase = args[index]
|
|
275
|
+
elif arg.startswith("--resume-phase="):
|
|
276
|
+
resume_phase = arg.split("=", 1)[1]
|
|
277
|
+
elif arg.startswith("-"):
|
|
278
|
+
unknown.append(arg)
|
|
279
|
+
else:
|
|
280
|
+
positional.append(arg)
|
|
281
|
+
index += 1
|
|
282
|
+
|
|
283
|
+
for value in positional:
|
|
284
|
+
if _looks_like_item_id(value, family.id_prefix) and not item_id:
|
|
285
|
+
item_id = _normalize_item_id(value, family.id_prefix)
|
|
286
|
+
elif list_path == family.plan_path:
|
|
287
|
+
list_path = Path(value).expanduser()
|
|
288
|
+
else:
|
|
289
|
+
unknown.append(value)
|
|
290
|
+
|
|
291
|
+
return RunnerInvocation(
|
|
292
|
+
action=action,
|
|
293
|
+
list_path=list_path,
|
|
294
|
+
item_id=item_id,
|
|
295
|
+
item_filter=item_filter,
|
|
296
|
+
max_infra_retries=max_infra_retries,
|
|
297
|
+
mode=mode,
|
|
298
|
+
critic=critic,
|
|
299
|
+
dry_run=dry_run,
|
|
300
|
+
clean=clean,
|
|
301
|
+
no_reset=no_reset,
|
|
302
|
+
resume_phase=resume_phase or "null",
|
|
303
|
+
help_requested=help_requested,
|
|
304
|
+
unknown_args=tuple(unknown),
|
|
305
|
+
raw_args=args,
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def _looks_like_item_id(value: str, prefix: str) -> bool:
|
|
310
|
+
upper = value.upper()
|
|
311
|
+
return upper.startswith(prefix.upper())
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def _normalize_item_id(value: str, prefix: str) -> str:
|
|
315
|
+
upper = value.upper()
|
|
316
|
+
if upper.startswith(prefix.upper()):
|
|
317
|
+
suffix = upper[len(prefix) :]
|
|
318
|
+
if suffix.isdigit():
|
|
319
|
+
return f"{prefix}{int(suffix):03d}"
|
|
320
|
+
return upper
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def _truthy(value: str | None) -> bool:
|
|
324
|
+
return str(value or "").strip().lower() in {"1", "true", "yes", "on"}
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def _falsey(value: str | None) -> bool:
|
|
328
|
+
return str(value or "").strip().lower() in {"0", "false", "no", "off"}
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def _safe_int(value: str | None, default: int) -> int:
|
|
332
|
+
try:
|
|
333
|
+
return int(str(value))
|
|
334
|
+
except (TypeError, ValueError):
|
|
335
|
+
return default
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def _int_value(values: Mapping[str, str], name: str, default: int) -> int:
|
|
339
|
+
return _safe_int(values.get(name), default)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def _optional_int(value: str | None) -> int | None:
|
|
343
|
+
if value is None or str(value).strip() == "":
|
|
344
|
+
return None
|
|
345
|
+
return _safe_int(value, 0)
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Prompt generator bridge for Python foreground runners."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from .runner_models import PromptGenerationResult, RunnerFamily, RunnerInvocation, SessionPaths
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def generate_prompt(
|
|
14
|
+
family: RunnerFamily,
|
|
15
|
+
invocation: RunnerInvocation,
|
|
16
|
+
*,
|
|
17
|
+
item_id: str,
|
|
18
|
+
session_id: str,
|
|
19
|
+
run_id: str,
|
|
20
|
+
retry_count: int,
|
|
21
|
+
session_paths: SessionPaths,
|
|
22
|
+
project_root: Path,
|
|
23
|
+
execution_root: Path | None = None,
|
|
24
|
+
continuation: dict[str, object] | None = None,
|
|
25
|
+
) -> PromptGenerationResult:
|
|
26
|
+
"""Run the existing prompt generator and return its structured JSON result."""
|
|
27
|
+
visible_root = execution_root or project_root
|
|
28
|
+
command = [
|
|
29
|
+
sys.executable,
|
|
30
|
+
str(family.prompt_script),
|
|
31
|
+
family.list_arg,
|
|
32
|
+
str(invocation.list_path),
|
|
33
|
+
family.item_id_arg,
|
|
34
|
+
item_id,
|
|
35
|
+
"--session-id",
|
|
36
|
+
session_id,
|
|
37
|
+
"--run-id",
|
|
38
|
+
run_id,
|
|
39
|
+
"--retry-count",
|
|
40
|
+
str(retry_count),
|
|
41
|
+
"--resume-phase",
|
|
42
|
+
invocation.resume_phase,
|
|
43
|
+
"--state-dir",
|
|
44
|
+
str(family.state_dir),
|
|
45
|
+
"--project-root",
|
|
46
|
+
str(visible_root),
|
|
47
|
+
"--output",
|
|
48
|
+
str(session_paths.prompt_path),
|
|
49
|
+
]
|
|
50
|
+
if invocation.mode:
|
|
51
|
+
command.extend(["--mode", invocation.mode])
|
|
52
|
+
if invocation.critic is not None:
|
|
53
|
+
command.extend(["--critic", "true" if invocation.critic else "false"])
|
|
54
|
+
if continuation:
|
|
55
|
+
command.extend(["--continuation-mode", "context_overflow"])
|
|
56
|
+
for flag, key in (
|
|
57
|
+
("--previous-session-id", "previous_session_id"),
|
|
58
|
+
("--continuation-count", "continuation_count"),
|
|
59
|
+
("--context-overflow-count", "context_overflow_count"),
|
|
60
|
+
("--task-type", "task_type"),
|
|
61
|
+
("--active-dev-branch", "active_dev_branch"),
|
|
62
|
+
("--base-branch", "base_branch"),
|
|
63
|
+
("--continuation-summary-path", "continuation_summary_path"),
|
|
64
|
+
):
|
|
65
|
+
value = continuation.get(key)
|
|
66
|
+
if value not in (None, ""):
|
|
67
|
+
command.extend([flag, str(value)])
|
|
68
|
+
|
|
69
|
+
completed = subprocess.run(
|
|
70
|
+
command,
|
|
71
|
+
cwd=str(project_root),
|
|
72
|
+
stdout=subprocess.PIPE,
|
|
73
|
+
stderr=subprocess.PIPE,
|
|
74
|
+
text=True,
|
|
75
|
+
check=False,
|
|
76
|
+
)
|
|
77
|
+
if completed.returncode != 0:
|
|
78
|
+
raise RuntimeError(completed.stdout.strip() or completed.stderr.strip() or "prompt generation failed")
|
|
79
|
+
try:
|
|
80
|
+
data = json.loads(completed.stdout)
|
|
81
|
+
except json.JSONDecodeError as exc:
|
|
82
|
+
raise RuntimeError(f"prompt generator returned non-JSON output: {completed.stdout[:500]}") from exc
|
|
83
|
+
if not data.get("success"):
|
|
84
|
+
raise RuntimeError(str(data.get("error") or "prompt generation failed"))
|
|
85
|
+
|
|
86
|
+
checkpoint = data.get("checkpoint_path")
|
|
87
|
+
output_path = Path(str(data.get("output_path") or session_paths.prompt_path))
|
|
88
|
+
return PromptGenerationResult(
|
|
89
|
+
output_path=output_path,
|
|
90
|
+
model=str(data.get("model") or ""),
|
|
91
|
+
pipeline_mode=str(data.get("pipeline_mode") or ""),
|
|
92
|
+
agent_count=int(data.get("agent_count") or 0),
|
|
93
|
+
critic_enabled=_truthy(data.get("critic_enabled")),
|
|
94
|
+
checkpoint_path=Path(str(checkpoint)) if checkpoint else None,
|
|
95
|
+
artifact_path=_artifact_path(family, visible_root, item_id, data),
|
|
96
|
+
raw=data,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _artifact_path(
|
|
101
|
+
family: RunnerFamily,
|
|
102
|
+
project_root: Path,
|
|
103
|
+
item_id: str,
|
|
104
|
+
data: dict[str, object],
|
|
105
|
+
) -> Path:
|
|
106
|
+
if family.kind == "feature" and data.get("checkpoint_path"):
|
|
107
|
+
return Path(str(data["checkpoint_path"])).parent
|
|
108
|
+
if family.kind == "bugfix":
|
|
109
|
+
return project_root / ".prizmkit" / "bugfix" / item_id
|
|
110
|
+
if family.kind == "refactor":
|
|
111
|
+
return project_root / ".prizmkit" / "refactor" / item_id
|
|
112
|
+
return project_root / ".prizmkit" / family.artifact_root_name / item_id
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _truthy(value: object) -> bool:
|
|
116
|
+
if isinstance(value, bool):
|
|
117
|
+
return value
|
|
118
|
+
return str(value or "").strip().lower() in {"1", "true", "yes", "on"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"""Recovery detection and execution for Python foreground runner commands."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
import time
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from .config import load_runtime_config
|
|
13
|
+
from .paths import RuntimePaths
|
|
14
|
+
from .runner_models import RunnerEnvironment, SessionPaths
|
|
15
|
+
from .sessions import AISessionConfig, AISessionLauncher
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(frozen=True)
|
|
19
|
+
class RecoveryDetectorResolver:
|
|
20
|
+
"""Resolve recovery detector sources without coupling to one platform copy."""
|
|
21
|
+
|
|
22
|
+
paths: RuntimePaths
|
|
23
|
+
|
|
24
|
+
def candidates(self) -> tuple[Path, ...]:
|
|
25
|
+
project = self.paths.project_root
|
|
26
|
+
return (
|
|
27
|
+
project / ".agents" / "skills" / "recovery-workflow" / "scripts" / "detect-recovery-state.py",
|
|
28
|
+
project / ".claude" / "command-assets" / "recovery-workflow" / "scripts" / "detect-recovery-state.py",
|
|
29
|
+
project / ".codebuddy" / "skills" / "recovery-workflow" / "scripts" / "detect-recovery-state.py",
|
|
30
|
+
project
|
|
31
|
+
/ "core"
|
|
32
|
+
/ "skills"
|
|
33
|
+
/ "orchestration-skill"
|
|
34
|
+
/ "workflows"
|
|
35
|
+
/ "recovery-workflow"
|
|
36
|
+
/ "scripts"
|
|
37
|
+
/ "detect-recovery-state.py",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def resolve(self) -> Path:
|
|
41
|
+
for candidate in self.candidates():
|
|
42
|
+
if candidate.is_file():
|
|
43
|
+
return candidate
|
|
44
|
+
raise FileNotFoundError("recovery detector script not found")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def run_recovery_detect(paths: RuntimePaths) -> tuple[int, str, str, dict[str, object] | None]:
|
|
48
|
+
"""Run recovery state detection and parse the JSON report."""
|
|
49
|
+
detector = RecoveryDetectorResolver(paths).resolve()
|
|
50
|
+
completed = subprocess.run(
|
|
51
|
+
[sys.executable, str(detector), "--project-root", str(paths.project_root)],
|
|
52
|
+
cwd=str(paths.project_root),
|
|
53
|
+
stdout=subprocess.PIPE,
|
|
54
|
+
stderr=subprocess.PIPE,
|
|
55
|
+
text=True,
|
|
56
|
+
check=False,
|
|
57
|
+
)
|
|
58
|
+
data = None
|
|
59
|
+
if completed.stdout.strip():
|
|
60
|
+
try:
|
|
61
|
+
data = json.loads(completed.stdout)
|
|
62
|
+
except json.JSONDecodeError:
|
|
63
|
+
data = None
|
|
64
|
+
return completed.returncode, completed.stdout, completed.stderr, data
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def run_recovery(paths: RuntimePaths, legacy_args: tuple[str, ...] = ()) -> tuple[int, str, str]:
|
|
68
|
+
"""Detect recovery state, render a prompt, launch an AI session, and classify."""
|
|
69
|
+
dry_run = "--dry-run" in legacy_args
|
|
70
|
+
model_override = _option_value(legacy_args, "--model")
|
|
71
|
+
code, stdout, stderr, detection = run_recovery_detect(paths)
|
|
72
|
+
if code != 0 or not detection:
|
|
73
|
+
return code or 1, stdout, stderr
|
|
74
|
+
if not detection.get("detected"):
|
|
75
|
+
return 0, stdout, stderr
|
|
76
|
+
|
|
77
|
+
session_id = "recovery-{}-{}".format(
|
|
78
|
+
str(detection.get("workflow_type") or "workflow"),
|
|
79
|
+
time.strftime("%Y%m%d-%H%M%S"),
|
|
80
|
+
)
|
|
81
|
+
session_dir = paths.recovery_state_dir / session_id
|
|
82
|
+
session_paths = SessionPaths(
|
|
83
|
+
session_dir=session_dir,
|
|
84
|
+
prompt_path=session_dir / "bootstrap-prompt.md",
|
|
85
|
+
logs_dir=session_dir / "logs",
|
|
86
|
+
session_log=session_dir / "logs" / "session.log",
|
|
87
|
+
progress_json=session_dir / "logs" / "progress.json",
|
|
88
|
+
heartbeat_json=session_dir / "logs" / "heartbeat.json",
|
|
89
|
+
session_status_json=session_dir / "session-status.json",
|
|
90
|
+
)
|
|
91
|
+
detection_json = session_paths.session_dir / "detection.json"
|
|
92
|
+
session_paths.session_dir.mkdir(parents=True, exist_ok=True)
|
|
93
|
+
detection_json.write_text(json.dumps(detection, indent=2, ensure_ascii=False), encoding="utf-8")
|
|
94
|
+
prompt_output = session_paths.prompt_path
|
|
95
|
+
generator = paths.pipeline_root / "scripts" / "generate-recovery-prompt.py"
|
|
96
|
+
prompt_cmd = [
|
|
97
|
+
sys.executable,
|
|
98
|
+
str(generator),
|
|
99
|
+
"--detection-json",
|
|
100
|
+
str(detection_json),
|
|
101
|
+
"--output",
|
|
102
|
+
str(prompt_output),
|
|
103
|
+
"--project-root",
|
|
104
|
+
str(paths.project_root),
|
|
105
|
+
"--session-id",
|
|
106
|
+
session_id,
|
|
107
|
+
]
|
|
108
|
+
prompt_result = subprocess.run(
|
|
109
|
+
prompt_cmd,
|
|
110
|
+
cwd=str(paths.project_root),
|
|
111
|
+
stdout=subprocess.PIPE,
|
|
112
|
+
stderr=subprocess.PIPE,
|
|
113
|
+
text=True,
|
|
114
|
+
check=False,
|
|
115
|
+
)
|
|
116
|
+
if prompt_result.returncode != 0:
|
|
117
|
+
return prompt_result.returncode, prompt_result.stdout, prompt_result.stderr
|
|
118
|
+
if dry_run:
|
|
119
|
+
return 0, prompt_result.stdout, prompt_result.stderr
|
|
120
|
+
|
|
121
|
+
config = load_runtime_config(paths)
|
|
122
|
+
if not config.ai_client.command:
|
|
123
|
+
return 1, "", "No supported AI CLI command was found for recovery\n"
|
|
124
|
+
env = RunnerEnvironment.from_env()
|
|
125
|
+
launcher = AISessionLauncher(
|
|
126
|
+
AISessionConfig(
|
|
127
|
+
cli_command=config.ai_client.command,
|
|
128
|
+
platform=config.ai_client.platform or "codebuddy",
|
|
129
|
+
model=model_override or config.model,
|
|
130
|
+
prompt_path=prompt_output,
|
|
131
|
+
cwd=paths.project_root,
|
|
132
|
+
log_path=session_paths.session_log,
|
|
133
|
+
progress_path=session_paths.progress_json,
|
|
134
|
+
heartbeat_path=session_paths.heartbeat_json,
|
|
135
|
+
effort=config.effort,
|
|
136
|
+
verbose=env.verbose,
|
|
137
|
+
stale_kill_threshold_seconds=env.stale_kill_threshold_seconds,
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
result = launcher.run()
|
|
141
|
+
outcome = _recovery_outcome(paths.project_root, result.exit_code)
|
|
142
|
+
session_paths.session_status_json.write_text(
|
|
143
|
+
json.dumps({"session_id": session_id, "outcome": outcome}, indent=2) + "\n",
|
|
144
|
+
encoding="utf-8",
|
|
145
|
+
)
|
|
146
|
+
return 0 if outcome in {"success", "success_wip", "no_changes"} else 1, outcome + "\n", ""
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _option_value(args: tuple[str, ...], flag: str) -> str | None:
|
|
150
|
+
for index, arg in enumerate(args):
|
|
151
|
+
if arg == flag and index + 1 < len(args):
|
|
152
|
+
return args[index + 1]
|
|
153
|
+
if arg.startswith(flag + "="):
|
|
154
|
+
return arg.split("=", 1)[1]
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _recovery_outcome(project_root: Path, exit_code: int | None) -> str:
|
|
159
|
+
commits = subprocess.run(
|
|
160
|
+
["git", "-C", str(project_root), "rev-list", "--count", "HEAD", "^main"],
|
|
161
|
+
stdout=subprocess.PIPE,
|
|
162
|
+
stderr=subprocess.DEVNULL,
|
|
163
|
+
text=True,
|
|
164
|
+
check=False,
|
|
165
|
+
)
|
|
166
|
+
if commits.returncode == 0 and commits.stdout.strip() not in {"", "0"}:
|
|
167
|
+
return "success"
|
|
168
|
+
status = subprocess.run(
|
|
169
|
+
["git", "-C", str(project_root), "status", "--porcelain"],
|
|
170
|
+
stdout=subprocess.PIPE,
|
|
171
|
+
stderr=subprocess.DEVNULL,
|
|
172
|
+
text=True,
|
|
173
|
+
check=False,
|
|
174
|
+
)
|
|
175
|
+
has_changes = bool(status.stdout.strip())
|
|
176
|
+
if exit_code == 0 and has_changes:
|
|
177
|
+
subprocess.run(["git", "-C", str(project_root), "add", "-A"], check=False)
|
|
178
|
+
subprocess.run(
|
|
179
|
+
["git", "-C", str(project_root), "commit", "--no-verify", "-m", "chore: save recovery work"],
|
|
180
|
+
stdout=subprocess.DEVNULL,
|
|
181
|
+
stderr=subprocess.DEVNULL,
|
|
182
|
+
check=False,
|
|
183
|
+
)
|
|
184
|
+
return "success_wip"
|
|
185
|
+
if exit_code == 0:
|
|
186
|
+
return "no_changes"
|
|
187
|
+
return "partial" if has_changes else "failed"
|