@opengsd/gsd-path 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +397 -0
- package/DOCS.md +341 -0
- package/FULL.md +475 -0
- package/GUIDE.md +23 -0
- package/HOOKS.md +273 -0
- package/LICENSE +21 -0
- package/MIGRATE.md +100 -0
- package/QUICK.md +146 -0
- package/README.md +280 -0
- package/RUNTIME.md +229 -0
- package/UPDATE.md +196 -0
- package/WORKFLOW.md +683 -0
- package/package.json +80 -0
- package/platforms/claude/dispatch.md +63 -0
- package/platforms/copilot/dispatch.md +61 -0
- package/platforms/cursor/agent.md +17 -0
- package/platforms/cursor/dispatch.md +63 -0
- package/platforms/grok/dispatch.md +61 -0
- package/platforms/kimi/dispatch.md +64 -0
- package/platforms/kiro/dispatch.md +58 -0
- package/platforms/opencode/dispatch.md +62 -0
- package/platforms/qwen/dispatch.md +60 -0
- package/platforms/shared-agents/dispatch.md +131 -0
- package/plugin.json +14 -0
- package/scripts/_common.py +180 -0
- package/scripts/archive_milestone.py +2265 -0
- package/scripts/bootstrap_repository.py +710 -0
- package/scripts/build_state.py +854 -0
- package/scripts/check_docs_audit.py +463 -0
- package/scripts/check_handoffs.py +1855 -0
- package/scripts/check_task_briefs.py +376 -0
- package/scripts/check_update.py +93 -0
- package/scripts/core_hook_gate.py +34 -0
- package/scripts/core_hook_settings.py +119 -0
- package/scripts/detect_project.py +1517 -0
- package/scripts/discussion_records.py +619 -0
- package/scripts/discussion_validate.py +1321 -0
- package/scripts/dispatch_driver.py +1812 -0
- package/scripts/git_guard.py +759 -0
- package/scripts/guard_hook.py +2124 -0
- package/scripts/install.mjs +3239 -0
- package/scripts/install.py +3008 -0
- package/scripts/integration.py +1433 -0
- package/scripts/isolation.py +3538 -0
- package/scripts/lean_verification.py +256 -0
- package/scripts/loop_run.py +837 -0
- package/scripts/migrate_core.py +169 -0
- package/scripts/pipeline_diagnose.py +715 -0
- package/scripts/pipeline_git.py +940 -0
- package/scripts/pipeline_state.py +2291 -0
- package/scripts/pipeline_undo.py +1039 -0
- package/scripts/promote_lookahead.py +415 -0
- package/scripts/review_findings.py +714 -0
- package/scripts/review_panel.py +553 -0
- package/scripts/skill-resources.json +340 -0
- package/scripts/state_checkpoint.py +1039 -0
- package/scripts/state_promote.py +743 -0
- package/scripts/status_runtime.py +122 -0
- package/scripts/sync_skill_resources.py +259 -0
- package/scripts/token_budget.py +146 -0
- package/scripts/wizard.mjs +179 -0
- package/scripts/workflow_run.py +117 -0
- package/skills/gsd-path/BUILD.md +700 -0
- package/skills/gsd-path/DECIDE.md +115 -0
- package/skills/gsd-path/DEFINE.md +297 -0
- package/skills/gsd-path/DOCS-AUDIT.md +190 -0
- package/skills/gsd-path/INSPECT.md +167 -0
- package/skills/gsd-path/PLAN.md +411 -0
- package/skills/gsd-path/RESEARCH.md +159 -0
- package/skills/gsd-path/ROADMAP.md +215 -0
- package/skills/gsd-path/SHIP.md +412 -0
- package/skills/gsd-path/SKILL.md +471 -0
- package/skills/gsd-path/agents/openai.yaml +6 -0
- package/skills/gsd-path/references/codebase-mapper.md +52 -0
- package/skills/gsd-path/references/coder.md +90 -0
- package/skills/gsd-path/references/decider.md +36 -0
- package/skills/gsd-path/references/dispatch.md +131 -0
- package/skills/gsd-path/references/docs-auditor.md +60 -0
- package/skills/gsd-path/references/planner.md +104 -0
- package/skills/gsd-path/references/researcher.md +42 -0
- package/skills/gsd-path/references/reviewer.md +188 -0
- package/skills/gsd-path/references/roadmapper.md +48 -0
- package/skills/gsd-path/scripts/_common.py +180 -0
- package/skills/gsd-path/scripts/archive_milestone.py +2265 -0
- package/skills/gsd-path/scripts/bootstrap_repository.py +710 -0
- package/skills/gsd-path/scripts/build_state.py +854 -0
- package/skills/gsd-path/scripts/check_docs_audit.py +463 -0
- package/skills/gsd-path/scripts/check_handoffs.py +1855 -0
- package/skills/gsd-path/scripts/check_task_briefs.py +376 -0
- package/skills/gsd-path/scripts/check_update.py +93 -0
- package/skills/gsd-path/scripts/detect_project.py +1517 -0
- package/skills/gsd-path/scripts/discussion_records.py +619 -0
- package/skills/gsd-path/scripts/discussion_validate.py +1321 -0
- package/skills/gsd-path/scripts/dispatch_driver.py +1812 -0
- package/skills/gsd-path/scripts/integration.py +1433 -0
- package/skills/gsd-path/scripts/isolation.py +3538 -0
- package/skills/gsd-path/scripts/lean_verification.py +256 -0
- package/skills/gsd-path/scripts/loop_run.py +837 -0
- package/skills/gsd-path/scripts/pipeline_git.py +940 -0
- package/skills/gsd-path/scripts/pipeline_state.py +2291 -0
- package/skills/gsd-path/scripts/promote_lookahead.py +415 -0
- package/skills/gsd-path/scripts/review_findings.py +714 -0
- package/skills/gsd-path/scripts/review_panel.py +553 -0
- package/skills/gsd-path/scripts/state_checkpoint.py +1039 -0
- package/skills/gsd-path/scripts/state_promote.py +743 -0
- package/skills/gsd-path/scripts/token_budget.py +146 -0
- package/skills/gsd-path/scripts/workflow_run.py +117 -0
- package/skills/gsd-path/templates/answers.md +29 -0
- package/skills/gsd-path/templates/archive-manifest.md +37 -0
- package/skills/gsd-path/templates/charter.md +50 -0
- package/skills/gsd-path/templates/codebase.md +46 -0
- package/skills/gsd-path/templates/dialogue.md +21 -0
- package/skills/gsd-path/templates/docs-audit.md +69 -0
- package/skills/gsd-path/templates/evidence.md +24 -0
- package/skills/gsd-path/templates/final-review.md +27 -0
- package/skills/gsd-path/templates/gap-review.md +20 -0
- package/skills/gsd-path/templates/intent.md +98 -0
- package/skills/gsd-path/templates/loop.md +59 -0
- package/skills/gsd-path/templates/patch-findings.md +16 -0
- package/skills/gsd-path/templates/plan-panel.md +25 -0
- package/skills/gsd-path/templates/plan.md +89 -0
- package/skills/gsd-path/templates/repository.md +16 -0
- package/skills/gsd-path/templates/research-handoff.md +25 -0
- package/skills/gsd-path/templates/roadmap.md +38 -0
- package/skills/gsd-path/templates/skeptic.md +36 -0
- package/skills/gsd-path/templates/state.md +27 -0
- package/skills/gsd-path/templates/synthesis.md +36 -0
- package/skills/gsd-path/templates/task.md +74 -0
- package/skills/gsd-path/templates/wave-panel.md +25 -0
- package/skills/gsd-path/templates/wave-review.md +64 -0
- package/skills/gsd-path-build/SKILL.md +700 -0
- package/skills/gsd-path-build/agents/openai.yaml +6 -0
- package/skills/gsd-path-build/references/coder.md +90 -0
- package/skills/gsd-path-build/references/dispatch.md +131 -0
- package/skills/gsd-path-build/references/reviewer.md +188 -0
- package/skills/gsd-path-build/scripts/_common.py +180 -0
- package/skills/gsd-path-build/scripts/archive_milestone.py +2265 -0
- package/skills/gsd-path-build/scripts/build_state.py +854 -0
- package/skills/gsd-path-build/scripts/check_handoffs.py +1855 -0
- package/skills/gsd-path-build/scripts/check_task_briefs.py +376 -0
- package/skills/gsd-path-build/scripts/discussion_records.py +619 -0
- package/skills/gsd-path-build/scripts/discussion_validate.py +1321 -0
- package/skills/gsd-path-build/scripts/dispatch_driver.py +1812 -0
- package/skills/gsd-path-build/scripts/integration.py +1433 -0
- package/skills/gsd-path-build/scripts/isolation.py +3538 -0
- package/skills/gsd-path-build/scripts/loop_run.py +837 -0
- package/skills/gsd-path-build/scripts/pipeline_git.py +940 -0
- package/skills/gsd-path-build/scripts/pipeline_state.py +2291 -0
- package/skills/gsd-path-build/scripts/review_findings.py +714 -0
- package/skills/gsd-path-build/scripts/review_panel.py +553 -0
- package/skills/gsd-path-build/scripts/state_checkpoint.py +1039 -0
- package/skills/gsd-path-build/scripts/state_promote.py +743 -0
- package/skills/gsd-path-build/scripts/token_budget.py +146 -0
- package/skills/gsd-path-build/scripts/workflow_run.py +117 -0
- package/skills/gsd-path-build/templates/skeptic.md +36 -0
- package/skills/gsd-path-build/templates/task.md +74 -0
- package/skills/gsd-path-build/templates/wave-panel.md +25 -0
- package/skills/gsd-path-build/templates/wave-review.md +64 -0
- package/skills/gsd-path-decide/SKILL.md +115 -0
- package/skills/gsd-path-decide/agents/openai.yaml +6 -0
- package/skills/gsd-path-decide/references/decider.md +36 -0
- package/skills/gsd-path-decide/references/dispatch.md +131 -0
- package/skills/gsd-path-decide/scripts/_common.py +180 -0
- package/skills/gsd-path-decide/scripts/check_handoffs.py +1855 -0
- package/skills/gsd-path-decide/scripts/check_task_briefs.py +376 -0
- package/skills/gsd-path-decide/scripts/discussion_records.py +619 -0
- package/skills/gsd-path-decide/scripts/isolation.py +3538 -0
- package/skills/gsd-path-decide/scripts/pipeline_git.py +940 -0
- package/skills/gsd-path-decide/scripts/pipeline_state.py +2291 -0
- package/skills/gsd-path-decide/scripts/state_checkpoint.py +1039 -0
- package/skills/gsd-path-decide/scripts/state_promote.py +743 -0
- package/skills/gsd-path-decide/templates/synthesis.md +36 -0
- package/skills/gsd-path-define/SKILL.md +297 -0
- package/skills/gsd-path-define/agents/openai.yaml +6 -0
- package/skills/gsd-path-define/scripts/_common.py +180 -0
- package/skills/gsd-path-define/scripts/check_handoffs.py +1855 -0
- package/skills/gsd-path-define/scripts/check_task_briefs.py +376 -0
- package/skills/gsd-path-define/scripts/detect_project.py +1517 -0
- package/skills/gsd-path-define/scripts/discussion_records.py +619 -0
- package/skills/gsd-path-define/scripts/isolation.py +3538 -0
- package/skills/gsd-path-define/scripts/pipeline_git.py +940 -0
- package/skills/gsd-path-define/scripts/pipeline_state.py +2291 -0
- package/skills/gsd-path-define/scripts/state_checkpoint.py +1039 -0
- package/skills/gsd-path-define/scripts/state_promote.py +743 -0
- package/skills/gsd-path-define/templates/charter.md +50 -0
- package/skills/gsd-path-define/templates/intent.md +98 -0
- package/skills/gsd-path-define/templates/state.md +27 -0
- package/skills/gsd-path-discuss/SKILL.md +162 -0
- package/skills/gsd-path-discuss/agents/openai.yaml +6 -0
- package/skills/gsd-path-discuss/scripts/_common.py +180 -0
- package/skills/gsd-path-discuss/scripts/discussion_records.py +619 -0
- package/skills/gsd-path-discuss/templates/answers.md +29 -0
- package/skills/gsd-path-discuss/templates/dialogue.md +21 -0
- package/skills/gsd-path-docs-audit/SKILL.md +190 -0
- package/skills/gsd-path-docs-audit/agents/openai.yaml +6 -0
- package/skills/gsd-path-docs-audit/references/dispatch.md +131 -0
- package/skills/gsd-path-docs-audit/references/docs-auditor.md +60 -0
- package/skills/gsd-path-docs-audit/scripts/_common.py +180 -0
- package/skills/gsd-path-docs-audit/scripts/check_docs_audit.py +463 -0
- package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +1855 -0
- package/skills/gsd-path-docs-audit/scripts/check_task_briefs.py +376 -0
- package/skills/gsd-path-docs-audit/scripts/discussion_records.py +619 -0
- package/skills/gsd-path-docs-audit/scripts/isolation.py +3538 -0
- package/skills/gsd-path-docs-audit/scripts/pipeline_git.py +940 -0
- package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +2291 -0
- package/skills/gsd-path-docs-audit/scripts/state_checkpoint.py +1039 -0
- package/skills/gsd-path-docs-audit/scripts/state_promote.py +743 -0
- package/skills/gsd-path-docs-audit/templates/docs-audit.md +69 -0
- package/skills/gsd-path-forensics/SKILL.md +39 -0
- package/skills/gsd-path-forensics/agents/openai.yaml +6 -0
- package/skills/gsd-path-forensics/scripts/_common.py +180 -0
- package/skills/gsd-path-forensics/scripts/discussion_records.py +619 -0
- package/skills/gsd-path-forensics/scripts/pipeline_diagnose.py +715 -0
- package/skills/gsd-path-forensics/scripts/pipeline_undo.py +1039 -0
- package/skills/gsd-path-inspect/SKILL.md +167 -0
- package/skills/gsd-path-inspect/agents/openai.yaml +6 -0
- package/skills/gsd-path-inspect/references/codebase-mapper.md +52 -0
- package/skills/gsd-path-inspect/references/dispatch.md +131 -0
- package/skills/gsd-path-inspect/references/docs-auditor.md +60 -0
- package/skills/gsd-path-inspect/scripts/_common.py +180 -0
- package/skills/gsd-path-inspect/scripts/check_docs_audit.py +463 -0
- package/skills/gsd-path-inspect/scripts/check_handoffs.py +1855 -0
- package/skills/gsd-path-inspect/scripts/check_task_briefs.py +376 -0
- package/skills/gsd-path-inspect/scripts/detect_project.py +1517 -0
- package/skills/gsd-path-inspect/scripts/discussion_records.py +619 -0
- package/skills/gsd-path-inspect/scripts/isolation.py +3538 -0
- package/skills/gsd-path-inspect/scripts/pipeline_git.py +940 -0
- package/skills/gsd-path-inspect/scripts/pipeline_state.py +2291 -0
- package/skills/gsd-path-inspect/scripts/state_checkpoint.py +1039 -0
- package/skills/gsd-path-inspect/scripts/state_promote.py +743 -0
- package/skills/gsd-path-inspect/templates/codebase.md +46 -0
- package/skills/gsd-path-inspect/templates/docs-audit.md +69 -0
- package/skills/gsd-path-inspect/templates/state.md +27 -0
- package/skills/gsd-path-loop/SKILL.md +98 -0
- package/skills/gsd-path-loop/agents/openai.yaml +6 -0
- package/skills/gsd-path-loop/examples/ci-repair.LOOP.md +61 -0
- package/skills/gsd-path-loop/scripts/_common.py +180 -0
- package/skills/gsd-path-loop/scripts/discussion_records.py +619 -0
- package/skills/gsd-path-loop/scripts/loop_run.py +837 -0
- package/skills/gsd-path-loop/templates/loop.md +59 -0
- package/skills/gsd-path-migrate/SKILL.md +134 -0
- package/skills/gsd-path-migrate/agents/openai.yaml +6 -0
- package/skills/gsd-path-migrate/scripts/core_hook_gate.py +34 -0
- package/skills/gsd-path-migrate/scripts/core_hook_settings.py +119 -0
- package/skills/gsd-path-migrate/scripts/discussion_records.py +619 -0
- package/skills/gsd-path-migrate/scripts/migrate_core.py +169 -0
- package/skills/gsd-path-plan/SKILL.md +411 -0
- package/skills/gsd-path-plan/agents/openai.yaml +6 -0
- package/skills/gsd-path-plan/references/dispatch.md +131 -0
- package/skills/gsd-path-plan/references/planner.md +104 -0
- package/skills/gsd-path-plan/scripts/_common.py +180 -0
- package/skills/gsd-path-plan/scripts/check_handoffs.py +1855 -0
- package/skills/gsd-path-plan/scripts/check_task_briefs.py +376 -0
- package/skills/gsd-path-plan/scripts/discussion_records.py +619 -0
- package/skills/gsd-path-plan/scripts/isolation.py +3538 -0
- package/skills/gsd-path-plan/scripts/pipeline_git.py +940 -0
- package/skills/gsd-path-plan/scripts/pipeline_state.py +2291 -0
- package/skills/gsd-path-plan/scripts/review_panel.py +553 -0
- package/skills/gsd-path-plan/scripts/state_checkpoint.py +1039 -0
- package/skills/gsd-path-plan/scripts/state_promote.py +743 -0
- package/skills/gsd-path-plan/scripts/workflow_run.py +117 -0
- package/skills/gsd-path-plan/templates/patch-findings.md +16 -0
- package/skills/gsd-path-plan/templates/plan-panel.md +25 -0
- package/skills/gsd-path-plan/templates/plan.md +89 -0
- package/skills/gsd-path-plan/templates/task.md +74 -0
- package/skills/gsd-path-research/SKILL.md +159 -0
- package/skills/gsd-path-research/agents/openai.yaml +6 -0
- package/skills/gsd-path-research/references/dispatch.md +131 -0
- package/skills/gsd-path-research/references/researcher.md +42 -0
- package/skills/gsd-path-research/scripts/_common.py +180 -0
- package/skills/gsd-path-research/scripts/check_handoffs.py +1855 -0
- package/skills/gsd-path-research/scripts/check_task_briefs.py +376 -0
- package/skills/gsd-path-research/scripts/discussion_records.py +619 -0
- package/skills/gsd-path-research/scripts/isolation.py +3538 -0
- package/skills/gsd-path-research/scripts/pipeline_git.py +940 -0
- package/skills/gsd-path-research/scripts/pipeline_state.py +2291 -0
- package/skills/gsd-path-research/scripts/state_checkpoint.py +1039 -0
- package/skills/gsd-path-research/scripts/state_promote.py +743 -0
- package/skills/gsd-path-research/templates/evidence.md +24 -0
- package/skills/gsd-path-research/templates/research-handoff.md +25 -0
- package/skills/gsd-path-roadmap/SKILL.md +215 -0
- package/skills/gsd-path-roadmap/agents/openai.yaml +6 -0
- package/skills/gsd-path-roadmap/references/dispatch.md +131 -0
- package/skills/gsd-path-roadmap/references/roadmapper.md +48 -0
- package/skills/gsd-path-roadmap/scripts/_common.py +180 -0
- package/skills/gsd-path-roadmap/scripts/archive_milestone.py +2265 -0
- package/skills/gsd-path-roadmap/scripts/check_handoffs.py +1855 -0
- package/skills/gsd-path-roadmap/scripts/check_task_briefs.py +376 -0
- package/skills/gsd-path-roadmap/scripts/detect_project.py +1517 -0
- package/skills/gsd-path-roadmap/scripts/discussion_records.py +619 -0
- package/skills/gsd-path-roadmap/scripts/discussion_validate.py +1321 -0
- package/skills/gsd-path-roadmap/scripts/integration.py +1433 -0
- package/skills/gsd-path-roadmap/scripts/isolation.py +3538 -0
- package/skills/gsd-path-roadmap/scripts/pipeline_git.py +940 -0
- package/skills/gsd-path-roadmap/scripts/pipeline_state.py +2291 -0
- package/skills/gsd-path-roadmap/scripts/promote_lookahead.py +415 -0
- package/skills/gsd-path-roadmap/scripts/review_panel.py +553 -0
- package/skills/gsd-path-roadmap/scripts/state_checkpoint.py +1039 -0
- package/skills/gsd-path-roadmap/scripts/state_promote.py +743 -0
- package/skills/gsd-path-roadmap/templates/roadmap.md +38 -0
- package/skills/gsd-path-ship/SKILL.md +412 -0
- package/skills/gsd-path-ship/agents/openai.yaml +6 -0
- package/skills/gsd-path-ship/references/dispatch.md +131 -0
- package/skills/gsd-path-ship/references/reviewer.md +188 -0
- package/skills/gsd-path-ship/scripts/_common.py +180 -0
- package/skills/gsd-path-ship/scripts/archive_milestone.py +2265 -0
- package/skills/gsd-path-ship/scripts/build_state.py +854 -0
- package/skills/gsd-path-ship/scripts/check_handoffs.py +1855 -0
- package/skills/gsd-path-ship/scripts/check_task_briefs.py +376 -0
- package/skills/gsd-path-ship/scripts/discussion_records.py +619 -0
- package/skills/gsd-path-ship/scripts/discussion_validate.py +1321 -0
- package/skills/gsd-path-ship/scripts/integration.py +1433 -0
- package/skills/gsd-path-ship/scripts/isolation.py +3538 -0
- package/skills/gsd-path-ship/scripts/lean_verification.py +256 -0
- package/skills/gsd-path-ship/scripts/pipeline_git.py +940 -0
- package/skills/gsd-path-ship/scripts/pipeline_state.py +2291 -0
- package/skills/gsd-path-ship/scripts/review_panel.py +553 -0
- package/skills/gsd-path-ship/scripts/state_checkpoint.py +1039 -0
- package/skills/gsd-path-ship/scripts/state_promote.py +743 -0
- package/skills/gsd-path-ship/scripts/workflow_run.py +117 -0
- package/skills/gsd-path-ship/templates/archive-manifest.md +37 -0
- package/skills/gsd-path-ship/templates/final-review.md +27 -0
- package/skills/gsd-path-ship/templates/gap-review.md +20 -0
- package/skills/gsd-path-ship/templates/patch-findings.md +16 -0
- package/skills/gsd-path-ship/templates/wave-review.md +64 -0
- package/skills/gsd-path-undo/SKILL.md +45 -0
- package/skills/gsd-path-undo/agents/openai.yaml +6 -0
- package/skills/gsd-path-undo/scripts/_common.py +180 -0
- package/skills/gsd-path-undo/scripts/discussion_records.py +619 -0
- package/skills/gsd-path-undo/scripts/pipeline_undo.py +1039 -0
- package/skills/path/BUILD.md +700 -0
- package/skills/path/DECIDE.md +115 -0
- package/skills/path/DEFINE.md +297 -0
- package/skills/path/DOCS-AUDIT.md +190 -0
- package/skills/path/INSPECT.md +167 -0
- package/skills/path/PLAN.md +411 -0
- package/skills/path/RESEARCH.md +159 -0
- package/skills/path/ROADMAP.md +215 -0
- package/skills/path/SHIP.md +412 -0
- package/skills/path/SKILL.md +471 -0
- package/skills/path/agents/openai.yaml +6 -0
- package/skills/path/references/codebase-mapper.md +52 -0
- package/skills/path/references/coder.md +90 -0
- package/skills/path/references/decider.md +36 -0
- package/skills/path/references/dispatch.md +131 -0
- package/skills/path/references/docs-auditor.md +60 -0
- package/skills/path/references/planner.md +104 -0
- package/skills/path/references/researcher.md +42 -0
- package/skills/path/references/reviewer.md +188 -0
- package/skills/path/references/roadmapper.md +48 -0
- package/skills/path/scripts/_common.py +180 -0
- package/skills/path/scripts/archive_milestone.py +2265 -0
- package/skills/path/scripts/bootstrap_repository.py +710 -0
- package/skills/path/scripts/build_state.py +854 -0
- package/skills/path/scripts/check_docs_audit.py +463 -0
- package/skills/path/scripts/check_handoffs.py +1855 -0
- package/skills/path/scripts/check_task_briefs.py +376 -0
- package/skills/path/scripts/check_update.py +93 -0
- package/skills/path/scripts/detect_project.py +1517 -0
- package/skills/path/scripts/discussion_records.py +619 -0
- package/skills/path/scripts/discussion_validate.py +1321 -0
- package/skills/path/scripts/dispatch_driver.py +1812 -0
- package/skills/path/scripts/integration.py +1433 -0
- package/skills/path/scripts/isolation.py +3538 -0
- package/skills/path/scripts/lean_verification.py +256 -0
- package/skills/path/scripts/loop_run.py +837 -0
- package/skills/path/scripts/pipeline_git.py +940 -0
- package/skills/path/scripts/pipeline_state.py +2291 -0
- package/skills/path/scripts/promote_lookahead.py +415 -0
- package/skills/path/scripts/review_findings.py +714 -0
- package/skills/path/scripts/review_panel.py +553 -0
- package/skills/path/scripts/state_checkpoint.py +1039 -0
- package/skills/path/scripts/state_promote.py +743 -0
- package/skills/path/scripts/token_budget.py +146 -0
- package/skills/path/scripts/workflow_run.py +117 -0
- package/skills/path/templates/answers.md +29 -0
- package/skills/path/templates/archive-manifest.md +37 -0
- package/skills/path/templates/charter.md +50 -0
- package/skills/path/templates/codebase.md +46 -0
- package/skills/path/templates/dialogue.md +21 -0
- package/skills/path/templates/docs-audit.md +69 -0
- package/skills/path/templates/evidence.md +24 -0
- package/skills/path/templates/final-review.md +27 -0
- package/skills/path/templates/gap-review.md +20 -0
- package/skills/path/templates/intent.md +98 -0
- package/skills/path/templates/loop.md +59 -0
- package/skills/path/templates/patch-findings.md +16 -0
- package/skills/path/templates/plan-panel.md +25 -0
- package/skills/path/templates/plan.md +89 -0
- package/skills/path/templates/repository.md +16 -0
- package/skills/path/templates/research-handoff.md +25 -0
- package/skills/path/templates/roadmap.md +38 -0
- package/skills/path/templates/skeptic.md +36 -0
- package/skills/path/templates/state.md +27 -0
- package/skills/path/templates/synthesis.md +36 -0
- package/skills/path/templates/task.md +74 -0
- package/skills/path/templates/wave-panel.md +25 -0
- package/skills/path/templates/wave-review.md +64 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Charter — <program name>
|
|
2
|
+
|
|
3
|
+
<!-- Written by $gsd-path-define program mode. Enduring program intent:
|
|
4
|
+
vetoes and constraints here override every milestone. Amended only by an
|
|
5
|
+
explicit user ruling recorded under Corrections. Lives at .project/
|
|
6
|
+
top level and persists across milestones; it never archives. -->
|
|
7
|
+
|
|
8
|
+
Review panel: off <!-- off | detected | claude,gpt,grok,composer,gemini,
|
|
9
|
+
deepseek,kimi,qwen — durable
|
|
10
|
+
program default for optional cross-model plan and
|
|
11
|
+
wave review. Milestone INTENT copies this value and
|
|
12
|
+
may override it. off is the default. Named values
|
|
13
|
+
name at most 3 families. -->
|
|
14
|
+
|
|
15
|
+
## Vision
|
|
16
|
+
|
|
17
|
+
<2–4 sentences: the program's end state and why it matters.>
|
|
18
|
+
|
|
19
|
+
## Full scope: in
|
|
20
|
+
|
|
21
|
+
<!-- Everything the program will deliver, grouped by capability area. The
|
|
22
|
+
roadmap slices this list; every item must map to at least one milestone. -->
|
|
23
|
+
- <capability area>: <what it includes>
|
|
24
|
+
|
|
25
|
+
## Full scope: out (vetoes)
|
|
26
|
+
|
|
27
|
+
<!-- Hard limits. No milestone, research dispatch, plan, or task may include
|
|
28
|
+
these. -->
|
|
29
|
+
- <vetoed item> — <user's stated reason, verbatim where possible>
|
|
30
|
+
|
|
31
|
+
## Constraints
|
|
32
|
+
|
|
33
|
+
<Program-level stack, budget, deadline, integrations, compliance.>
|
|
34
|
+
|
|
35
|
+
## Program success criteria
|
|
36
|
+
|
|
37
|
+
<!-- Observable statements checked when the last milestone ships. -->
|
|
38
|
+
1. <criterion — a thing you can run/measure/see>
|
|
39
|
+
|
|
40
|
+
## Open questions
|
|
41
|
+
|
|
42
|
+
<!-- Unresolved at program define end. Tags: RESEARCH (program research
|
|
43
|
+
answers it), NEEDS-USER (a human decision, surface at next checkpoint). -->
|
|
44
|
+
- [RESEARCH] <question>
|
|
45
|
+
- [NEEDS-USER] <question>
|
|
46
|
+
|
|
47
|
+
## Corrections
|
|
48
|
+
|
|
49
|
+
<!-- Verbatim user rulings that amend this charter. Append-only. -->
|
|
50
|
+
- <date>: "<what the user said>"
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Intent — <project name>
|
|
2
|
+
|
|
3
|
+
<!-- Written by $gsd-path-define. Every downstream agent reads this first.
|
|
4
|
+
Constraints and vetoes here override everything downstream. -->
|
|
5
|
+
|
|
6
|
+
Lane: standard <!-- standard | quick | milestone — quick: at most two
|
|
7
|
+
deliverable-sized tasks in one wave, no RESEARCH or
|
|
8
|
+
NEEDS-USER items, no cross-wave risk; set by define at
|
|
9
|
+
approval. Quick skips research and decide. Milestone:
|
|
10
|
+
derived from an approved ROADMAP.md entry in a program;
|
|
11
|
+
research/decide run only when the entry has open
|
|
12
|
+
questions. -->
|
|
13
|
+
|
|
14
|
+
Review panel: off <!-- off | detected | claude,gpt,grok,composer,gemini,deepseek,kimi,qwen — this
|
|
15
|
+
milestone's panel setting. In program flow, copy
|
|
16
|
+
CHARTER.md's durable default and override only when
|
|
17
|
+
the user says so. off is the default. detected uses
|
|
18
|
+
advertised host families except the parent, at most 3.
|
|
19
|
+
Named families are an assertion, at most 3. Quick
|
|
20
|
+
lane stays off. -->
|
|
21
|
+
|
|
22
|
+
Finding skeptics: off <!-- off | on — build spawns one read-only skeptic
|
|
23
|
+
per blocking deep-review finding before fix tasks
|
|
24
|
+
are opened; a refuted finding spawns no fix task unless
|
|
25
|
+
the user explicitly overrides all cycle refutations.
|
|
26
|
+
off is the default. Quick lane stays off. -->
|
|
27
|
+
|
|
28
|
+
Surfaces: none <!-- none | comma-separated list of the human-facing
|
|
29
|
+
surfaces this milestone delivers: a web app, a CLI, an
|
|
30
|
+
HTTP API. Anything a person opens, sees, or types into
|
|
31
|
+
is a surface. Use none only when nobody touches this
|
|
32
|
+
work directly — a library, a migration, internals.
|
|
33
|
+
Every named surface needs a success criterion
|
|
34
|
+
observable there and a PLAN.md Surface contract. -->
|
|
35
|
+
|
|
36
|
+
## Summary
|
|
37
|
+
|
|
38
|
+
<3–5 sentences: the problem, who has it, what the first release does. This is the
|
|
39
|
+
paragraph the user signed off on — do not edit without a new sign-off.>
|
|
40
|
+
|
|
41
|
+
## Problem
|
|
42
|
+
|
|
43
|
+
<What hurts today, for whom, how badly. Evidence if the user gave any.>
|
|
44
|
+
|
|
45
|
+
## Users
|
|
46
|
+
|
|
47
|
+
<Who, how many, how technical, what they use today.>
|
|
48
|
+
|
|
49
|
+
## Success criteria
|
|
50
|
+
|
|
51
|
+
<!-- Observable statements, numbered from 1. PLAN.md maps each to a task
|
|
52
|
+
AC and Verify as SC1, SC2, …. Wave review checks the SCs a wave owns.
|
|
53
|
+
Final review checks every SC.
|
|
54
|
+
Every surface named above needs at least one criterion a person can
|
|
55
|
+
observe at that surface — a screen reached, an output seen — never a
|
|
56
|
+
passing test standing in for the experience. -->
|
|
57
|
+
1. <criterion — a thing you can run/measure/see>
|
|
58
|
+
2. ...
|
|
59
|
+
|
|
60
|
+
## Scope: in
|
|
61
|
+
|
|
62
|
+
<The smallest version that hits the success criteria. Bullet list.>
|
|
63
|
+
|
|
64
|
+
## Scope: out (vetoes)
|
|
65
|
+
|
|
66
|
+
<!-- Hard constraints. Nothing in research, plans, or tasks may include these. -->
|
|
67
|
+
- <vetoed item> — <user's stated reason, verbatim where possible>
|
|
68
|
+
|
|
69
|
+
## Constraints
|
|
70
|
+
|
|
71
|
+
<Stack preferences, deadline, budget, existing code, integrations, compliance.>
|
|
72
|
+
|
|
73
|
+
## Current state (brownfield only)
|
|
74
|
+
|
|
75
|
+
<!-- Filled from evidence-codebase.md during brownfield define. Omit the
|
|
76
|
+
section entirely for greenfield projects. -->
|
|
77
|
+
- **What exists**: <stack, architecture, maturity in 2–3 sentences>
|
|
78
|
+
- **Must not break**: <existing behavior the user ruled protected — these are vetoes>
|
|
79
|
+
- **Doc-vs-code rulings**: <each DOCS-AUDIT conflict → user's ruling: fix-doc | fix-code | accept-drift>
|
|
80
|
+
- **Ground truth**: `<track>/research/evidence-codebase.md`, `<track>/research/DOCS-AUDIT.md`
|
|
81
|
+
|
|
82
|
+
## Risks
|
|
83
|
+
|
|
84
|
+
<!-- What the user is most unsure about. Research prioritizes these. -->
|
|
85
|
+
- <risk>
|
|
86
|
+
|
|
87
|
+
## Open questions
|
|
88
|
+
|
|
89
|
+
<!-- Unresolved at define end. Tags: RESEARCH (research phase answers it),
|
|
90
|
+
NEEDS-USER (a human decision, surface at next checkpoint). -->
|
|
91
|
+
- [RESEARCH] <question>
|
|
92
|
+
- [NEEDS-USER] <question>
|
|
93
|
+
|
|
94
|
+
## Corrections
|
|
95
|
+
|
|
96
|
+
<!-- Verbatim user corrections from playback and later phases. Append-only.
|
|
97
|
+
These are the highest-signal intent data in the file. -->
|
|
98
|
+
- <date>: "<what the user said>"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
pipeline: gsd-path/v2
|
|
3
|
+
project: <slug>
|
|
4
|
+
milestone: null # set by define; names the archive directory at ship
|
|
5
|
+
phase: define # v2 tokens: inspect | define | research | decide | roadmap | plan | build | ship | shipped
|
|
6
|
+
# inspect only for brownfield; greenfield starts at define
|
|
7
|
+
# roadmap only in program flow (CHARTER.md exists)
|
|
8
|
+
status: active # active | done | blocked; shipped is only phase: shipped + status: done
|
|
9
|
+
branch: null # bound per milestone as gsd-path/M00N; after integration
|
|
10
|
+
# the router rebinds before any next-milestone file change
|
|
11
|
+
# the bound branch is never main; ship integrates it there
|
|
12
|
+
archive: null # persisted archive transaction path; never recomputed
|
|
13
|
+
integration_default: direct # direct | pull-request; project setting
|
|
14
|
+
integration: direct # current milestone; may override the default before build
|
|
15
|
+
integration_source: default # default | milestone; preserves override provenance
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Project State
|
|
19
|
+
|
|
20
|
+
One file, always current. The router reads this first; every phase updates
|
|
21
|
+
it on completion. If this file and the artifacts disagree, the artifacts win
|
|
22
|
+
— fix this file.
|
|
23
|
+
|
|
24
|
+
## Log
|
|
25
|
+
|
|
26
|
+
<!-- append one line per transition: date, phase, event -->
|
|
27
|
+
- YYYY-MM-DD — <phase> — project initialized
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gsd-path-discuss
|
|
3
|
+
description: Hold an explicit, evidence-grounded discussion about an active GSD Path milestone from any phase, preserve the verbatim dialogue and answer records under .project/discuss/, use local code and existing artifacts before focused research, challenge unsupported assumptions, and identify the phase owner for follow-up. Use only when the user explicitly invokes $gsd-path-discuss to ask questions, explore a decision, request a progress explanation, or close a discussion without advancing the pipeline.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GSD Path Discussion
|
|
7
|
+
|
|
8
|
+
Use this skill as an interruptible sidecar to the active GSD Path pipeline. Keep
|
|
9
|
+
the conversation in the main user thread, ground claims in the repository and
|
|
10
|
+
the current phase artifacts, and save the exchange before returning the answer.
|
|
11
|
+
|
|
12
|
+
Routing instructions are caller handoffs under the AGENTS.md handoff rule;
|
|
13
|
+
tell the user which phase owns the follow-up and never invoke it yourself.
|
|
14
|
+
|
|
15
|
+
## Preconditions and ownership
|
|
16
|
+
|
|
17
|
+
1. Resolve the project root from the working directory. Read `AGENTS.md`,
|
|
18
|
+
`WORKFLOW.md`, and `.project/STATE.md` before answering.
|
|
19
|
+
2. Require a real `.project/STATE.md` whose frontmatter contains
|
|
20
|
+
`pipeline: gsd-path/v2`. If it is missing, foreign, malformed, or a
|
|
21
|
+
symlink, stop and tell the user to invoke `$gsd-path` for ownership recovery.
|
|
22
|
+
Do not create state merely to hold a discussion.
|
|
23
|
+
3. Accept any active milestone phase except `shipped`: inspect,
|
|
24
|
+
define, research, decide, roadmap, plan, build, or ship. Use the
|
|
25
|
+
state status currently recorded on disk. A shipped milestone is archived and must not be
|
|
26
|
+
reopened by this sidecar; start a new milestone first.
|
|
27
|
+
4. Resolve the bundled `scripts/discussion_records.py`,
|
|
28
|
+
[dialogue template](templates/dialogue.md), and
|
|
29
|
+
[answers template](templates/answers.md) to absolute paths. Run its `prepare`
|
|
30
|
+
command with the absolute repository and template paths before reading any
|
|
31
|
+
records. This deterministic helper validates STATE ownership, locks STATE,
|
|
32
|
+
recovers interrupted paired appends, restores an uncommitted review archive
|
|
33
|
+
without editing it, creates the exact record pair when absent, and fails on
|
|
34
|
+
stale or malformed state. Do not reproduce those operations manually.
|
|
35
|
+
5. Read only the helper-returned absolute DIALOGUE.md and ANSWERS.md paths.
|
|
36
|
+
6. Do not change `STATE.md`, phase status, `INTENT.md`, `SYNTHESIS.md`,
|
|
37
|
+
`PLAN.md`, task frontmatter, review verdicts, or archive
|
|
38
|
+
contents. Discussion can propose a change and name its owner; the owning
|
|
39
|
+
phase must apply it through its normal gate.
|
|
40
|
+
|
|
41
|
+
The helper serializes writers and rechecks STATE immediately before a paired
|
|
42
|
+
publication. Never commit the records: the current phase orchestrator is their
|
|
43
|
+
checkpoint owner and includes them as append-only bookkeeping in its next
|
|
44
|
+
normal `.project/` checkpoint. The answer's named next owner separately owns
|
|
45
|
+
the target artifact and disposition receipt.
|
|
46
|
+
|
|
47
|
+
## Grounding and pushback
|
|
48
|
+
|
|
49
|
+
Use the authority order from `AGENTS.md`:
|
|
50
|
+
|
|
51
|
+
- Treat the user's current words as the question, but treat intent vetoes and
|
|
52
|
+
recorded corrections as hard constraints.
|
|
53
|
+
- Treat settled synthesis decisions and the current plan/task contract as
|
|
54
|
+
governing phase inputs. Surface a conflict; never average sources or quietly
|
|
55
|
+
override a gate.
|
|
56
|
+
- Inspect the relevant implementation, callers, tests, and phase artifacts.
|
|
57
|
+
Use search to locate evidence, then read the code or run an allowed,
|
|
58
|
+
meaningful check before claiming behavior. Cite exact repository paths and
|
|
59
|
+
line numbers when practical. Never describe an unrun command as passing.
|
|
60
|
+
- Separate observed fact, inference, recommendation, and user decision. If the
|
|
61
|
+
premise is weak, push back plainly with the evidence and explain the smallest
|
|
62
|
+
safer alternative.
|
|
63
|
+
|
|
64
|
+
Read only the phase-specific inputs needed for the question:
|
|
65
|
+
|
|
66
|
+
| Phase | Start with |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| inspect | codebase map and docs audit |
|
|
69
|
+
| define | intent and inspection evidence |
|
|
70
|
+
| research | intent, research manifest, and relevant evidence |
|
|
71
|
+
| decide | intent, evidence, and synthesis |
|
|
72
|
+
| roadmap | charter, program synthesis, and the roadmap |
|
|
73
|
+
| `plan` | intent, synthesis, plan, and affected task contracts |
|
|
74
|
+
| `build` | intent, synthesis, plan, task frontmatter/logs, wave reviews, and STATE log |
|
|
75
|
+
| ship | intent, plan, task frontmatter, STATE log, and relevant review artifacts |
|
|
76
|
+
|
|
77
|
+
Then inspect the code that can prove or disprove the claim. Do not reread the
|
|
78
|
+
whole repository when a focused path set answers the question.
|
|
79
|
+
|
|
80
|
+
## Focused research
|
|
81
|
+
|
|
82
|
+
Use existing `.project/research/` evidence first. If the question depends on a
|
|
83
|
+
current external fact, an unfamiliar library behavior, or an unresolved intent
|
|
84
|
+
risk, perform focused research during the discussion when the required search
|
|
85
|
+
or source-reading capability is available. Record the query/scope, checked
|
|
86
|
+
sources, and confidence in the answer record.
|
|
87
|
+
|
|
88
|
+
Do not launch the full `$gsd-path-research` phase from this sidecar. That phase
|
|
89
|
+
owns a legal state transition and a gated `RESEARCH.md` handoff; invoking it
|
|
90
|
+
from an arbitrary phase would bypass the pipeline contract. If the result must
|
|
91
|
+
become formal milestone evidence, record a `[RESEARCH]` follow-up and name
|
|
92
|
+
`gsd-path-research` as the next owner. If research is unavailable, mark the
|
|
93
|
+
answer `NEEDS-USER` or `unverifiable` instead of filling the gap from memory.
|
|
94
|
+
|
|
95
|
+
## Discussion loop
|
|
96
|
+
|
|
97
|
+
For each invocation:
|
|
98
|
+
|
|
99
|
+
1. Identify the current phase/status and discussion thread. Run the helper's
|
|
100
|
+
`threads` command to list existing thread ids, topics, and statuses; do not
|
|
101
|
+
parse DIALOGUE.md for them. Reuse a stable thread id
|
|
102
|
+
(`T###`) when the user is continuing a topic; request `new` for a
|
|
103
|
+
distinct topic and let the helper allocate its id. Classify the
|
|
104
|
+
request as a fact check, diagnosis, decision, challenge, progress question,
|
|
105
|
+
or follow-up request.
|
|
106
|
+
2. Gather the smallest sufficient local evidence, then focused research only
|
|
107
|
+
when needed. Record conflicts and uncertainty before forming a conclusion.
|
|
108
|
+
3. Answer in the main conversation. State the conclusion first, then the
|
|
109
|
+
reasoning, evidence, pushback or alternatives, confidence, and the phase
|
|
110
|
+
owner for any action. When a formal follow-up is required, tell the user to
|
|
111
|
+
invoke `$gsd-path`; the router will route the pending answer to that owner.
|
|
112
|
+
Do not leave the user with only an owner name or direct phase command. Ask
|
|
113
|
+
only the next question required to resolve the user's decision; use the
|
|
114
|
+
host's interactive input facility when available.
|
|
115
|
+
4. Before returning, provide the semantic turn fields to the helper's `append`
|
|
116
|
+
command as one JSON object via `--input`, passing the same absolute template
|
|
117
|
+
paths as `prepare`. The object requires these non-empty fields:
|
|
118
|
+
`topic`, `user`, `assistant`,
|
|
119
|
+
`question`, `status`, `thread_status`, `conclusion`, `reasoning`,
|
|
120
|
+
`evidence`, `research`, `confidence`, `unresolved`, `next_owner`,
|
|
121
|
+
`target_artifact`, and `follow_up`. `thread` is optional: pass an existing
|
|
122
|
+
`T###` id to continue a thread, or omit it (or pass `new`) to let the
|
|
123
|
+
helper allocate the next thread id. An optional `date` field overrides the
|
|
124
|
+
record date (`YYYY-MM-DD`). Every listed field except `user` and
|
|
125
|
+
`assistant` must be a single line; the helper rejects an incomplete payload
|
|
126
|
+
and names every missing or multi-line field in one error. The helper allocates D/A ids,
|
|
127
|
+
reply and supersession links, records the current phase/status, and publishes
|
|
128
|
+
DIALOGUE.md and ANSWERS.md as a recoverable pair. Preserve the user's message
|
|
129
|
+
and returned assistant answer verbatim in `user` and `assistant`.
|
|
130
|
+
5. Use `working` only when the answer is explicitly
|
|
131
|
+
provisional or asks another question, `NEEDS-USER` when a human choice or
|
|
132
|
+
missing evidence blocks it, and `final` when it resolves the bounded question
|
|
133
|
+
or the user accepts/closes the thread. Set `Follow-up: required` only when a
|
|
134
|
+
named phase must update the named target artifact; otherwise use `none`. A
|
|
135
|
+
final answer record is durable context, not approval to advance a phase.
|
|
136
|
+
|
|
137
|
+
If the user corrects a fact, sets a veto, or makes a decision, preserve the
|
|
138
|
+
words verbatim in both the dialogue and answer records and identify which
|
|
139
|
+
formal artifact the owning phase must update. Such a record uses `Follow-up:
|
|
140
|
+
required`; it remains pending until the owner appends a fixed-format
|
|
141
|
+
`Disposition X###` receipt. The discussion sidecar never writes its own
|
|
142
|
+
disposition. After a helper failure, do not claim the dialogue or answer was
|
|
143
|
+
saved; the next `prepare` recovers an interrupted paired publication before
|
|
144
|
+
accepting another turn.
|
|
145
|
+
|
|
146
|
+
## Output contract
|
|
147
|
+
|
|
148
|
+
Every completed turn leaves these project-local artifacts:
|
|
149
|
+
|
|
150
|
+
- `.project/discuss/DIALOGUE.md` — append-only transcript of the exchange.
|
|
151
|
+
- `.project/discuss/ANSWERS.md` — append-only answer and decision records,
|
|
152
|
+
with final answers clearly marked `final`.
|
|
153
|
+
|
|
154
|
+
Keep answer records concise but self-contained: question, phase/status,
|
|
155
|
+
conclusion, reasoning or pushback, evidence/citations, research used or why it
|
|
156
|
+
was not needed, confidence, unresolved tags, next owner, target artifact, and
|
|
157
|
+
follow-up state. Do not duplicate a formal phase handoff or silently edit one
|
|
158
|
+
on the user's behalf. End the user response with **Outcome**, Markdown
|
|
159
|
+
**Review** links to the resolved absolute DIALOGUE.md and ANSWERS.md paths. For
|
|
160
|
+
a required follow-up, **Next** names the pending owner and tells the user to
|
|
161
|
+
invoke `$gsd-path`; otherwise it gives the next discussion question or says
|
|
162
|
+
that no action is required.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "GSD Path Discussion"
|
|
3
|
+
short_description: "Discuss any phase with durable answers"
|
|
4
|
+
default_prompt: "Use $gsd-path-discuss to reason through this GSD Path question and save the dialogue and final answer."
|
|
5
|
+
policy:
|
|
6
|
+
allow_implicit_invocation: false
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# gsd-path project runtime
|
|
3
|
+
"""Helpers shared by the gsd-path scripts.
|
|
4
|
+
|
|
5
|
+
Every consuming script binds the names it used before (for example
|
|
6
|
+
``run_git = _common.run_git``) so callers and tests that patch the name on the
|
|
7
|
+
consuming module keep working.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import os
|
|
14
|
+
import re
|
|
15
|
+
import subprocess
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import Optional
|
|
18
|
+
|
|
19
|
+
PIPELINE_MARKER = "gsd-path/v2"
|
|
20
|
+
BOUND_BRANCH_RE = re.compile(r"^gsd-path/M(\d{3,})$")
|
|
21
|
+
|
|
22
|
+
FIELD_PATTERN = re.compile(r"^(?P<key>[a-z_]+):\s*(?P<value>.*)$")
|
|
23
|
+
INLINE_LIST_PATTERN = re.compile(r"^\[(?P<body>.*)\]$")
|
|
24
|
+
LIST_ITEM_PATTERN = re.compile(r"^\s*-\s+(?P<value>.*)$")
|
|
25
|
+
VERIFY_LEDGER_PATH = ".project/build/verify-ledger.jsonl"
|
|
26
|
+
VERIFY_RESULTS = ("pass", "fail")
|
|
27
|
+
VERIFY_LEDGER_SCHEMA = "gsd-path/verify-ledger/v2"
|
|
28
|
+
VERIFY_BLOCK_PATTERN = re.compile(r"```bash[ \t]*\n(?P<block>.*?)```", re.DOTALL)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def section_body(text: str, heading: str) -> Optional[str]:
|
|
32
|
+
"""The text under `## <heading>` up to the next `## `, or None when absent."""
|
|
33
|
+
match = re.search(
|
|
34
|
+
rf"(?ms)^## {re.escape(heading)}\s*\n(?P<body>.*?)(?=^## |\Z)", text
|
|
35
|
+
)
|
|
36
|
+
return match.group("body") if match else None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def task_verify_command(task_text: str) -> str:
|
|
40
|
+
"""The Verify shell text, excluding the closing fence's separator newline."""
|
|
41
|
+
body = section_body(task_text, "Verify")
|
|
42
|
+
block = VERIFY_BLOCK_PATTERN.search(body) if body is not None else None
|
|
43
|
+
return block.group("block").removesuffix("\n") if block else ""
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def latest_verify_entry(entries: list, command: str, commit: str) -> Optional[dict]:
|
|
47
|
+
for entry in reversed(entries):
|
|
48
|
+
if (entry.get("schema") == VERIFY_LEDGER_SCHEMA
|
|
49
|
+
and entry["command"] == command and entry["commit"] == commit):
|
|
50
|
+
return entry
|
|
51
|
+
return None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def verify_ledger_entries(path: Path) -> list:
|
|
55
|
+
"""Parsed verify-ledger rows; raises ValueError on a malformed line."""
|
|
56
|
+
if not path.exists():
|
|
57
|
+
return []
|
|
58
|
+
return parse_verify_ledger(path.read_text(encoding="utf-8"))
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def parse_verify_ledger(text: str) -> list:
|
|
62
|
+
entries = []
|
|
63
|
+
for number, line in enumerate(text.splitlines(), start=1):
|
|
64
|
+
if not line.strip():
|
|
65
|
+
continue
|
|
66
|
+
try:
|
|
67
|
+
entry = json.loads(line)
|
|
68
|
+
except json.JSONDecodeError as error:
|
|
69
|
+
raise ValueError(f"{VERIFY_LEDGER_PATH} line {number} is not JSON: {error}") from error
|
|
70
|
+
if (
|
|
71
|
+
not isinstance(entry, dict)
|
|
72
|
+
or not isinstance(entry.get("command"), str)
|
|
73
|
+
or not isinstance(entry.get("commit"), str)
|
|
74
|
+
or entry.get("result") not in VERIFY_RESULTS
|
|
75
|
+
or not isinstance(entry.get("recorded_at"), str)
|
|
76
|
+
):
|
|
77
|
+
raise ValueError(f"{VERIFY_LEDGER_PATH} line {number} has invalid fields")
|
|
78
|
+
entries.append(entry)
|
|
79
|
+
return entries
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def run_command(
|
|
83
|
+
*arguments: str, cwd: Optional[Path] = None
|
|
84
|
+
) -> subprocess.CompletedProcess[str]:
|
|
85
|
+
return subprocess.run(
|
|
86
|
+
arguments,
|
|
87
|
+
cwd=cwd,
|
|
88
|
+
text=True,
|
|
89
|
+
capture_output=True,
|
|
90
|
+
check=False,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def run_git(
|
|
95
|
+
repo: Path, *arguments: str, input: Optional[str] = None
|
|
96
|
+
) -> subprocess.CompletedProcess[str]:
|
|
97
|
+
return subprocess.run(
|
|
98
|
+
("git", "-C", str(repo), *arguments),
|
|
99
|
+
input=input,
|
|
100
|
+
text=True,
|
|
101
|
+
capture_output=True,
|
|
102
|
+
check=False,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def atomic_replace(path: Path, temporary_path: Path, content: str) -> None:
|
|
107
|
+
temporary_path.parent.mkdir(parents=True, exist_ok=True)
|
|
108
|
+
descriptor = None
|
|
109
|
+
try:
|
|
110
|
+
if temporary_path.exists() or temporary_path.is_symlink():
|
|
111
|
+
temporary_path.unlink()
|
|
112
|
+
descriptor = os.open(
|
|
113
|
+
temporary_path,
|
|
114
|
+
os.O_WRONLY | os.O_CREAT | os.O_EXCL,
|
|
115
|
+
0o666,
|
|
116
|
+
)
|
|
117
|
+
handle = os.fdopen(descriptor, "w", encoding="utf-8")
|
|
118
|
+
descriptor = None
|
|
119
|
+
with handle:
|
|
120
|
+
handle.write(content)
|
|
121
|
+
os.replace(temporary_path, path)
|
|
122
|
+
finally:
|
|
123
|
+
if descriptor is not None:
|
|
124
|
+
os.close(descriptor)
|
|
125
|
+
if temporary_path.exists() or temporary_path.is_symlink():
|
|
126
|
+
temporary_path.unlink()
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def atomic_write(path: Path, content: str) -> None:
|
|
130
|
+
atomic_replace(path, path.parent / f".{path.name}.gsd-path-tmp", content)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def strip_yaml_comment(value: str) -> str:
|
|
134
|
+
quote = None
|
|
135
|
+
previous_significant = None
|
|
136
|
+
inline_list = value.lstrip().startswith("[")
|
|
137
|
+
index = 0
|
|
138
|
+
while index < len(value):
|
|
139
|
+
character = value[index]
|
|
140
|
+
if quote == '"':
|
|
141
|
+
if character == "\\" and index + 1 < len(value):
|
|
142
|
+
index += 2
|
|
143
|
+
continue
|
|
144
|
+
if character == quote:
|
|
145
|
+
quote = None
|
|
146
|
+
elif quote == "'":
|
|
147
|
+
if (
|
|
148
|
+
character == quote
|
|
149
|
+
and index + 1 < len(value)
|
|
150
|
+
and value[index + 1] == quote
|
|
151
|
+
):
|
|
152
|
+
index += 2
|
|
153
|
+
continue
|
|
154
|
+
if character == quote:
|
|
155
|
+
quote = None
|
|
156
|
+
else:
|
|
157
|
+
if character in {"'", '"'} and (
|
|
158
|
+
previous_significant is None
|
|
159
|
+
or (inline_list and previous_significant in {"[", ","})
|
|
160
|
+
):
|
|
161
|
+
quote = character
|
|
162
|
+
elif character == "#" and (
|
|
163
|
+
index == 0 or value[index - 1].isspace()
|
|
164
|
+
):
|
|
165
|
+
return value[:index].rstrip()
|
|
166
|
+
if quote is None and not character.isspace():
|
|
167
|
+
previous_significant = character
|
|
168
|
+
index += 1
|
|
169
|
+
return value.strip()
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def unquote(value: str) -> str:
|
|
173
|
+
cleaned = strip_yaml_comment(value).strip()
|
|
174
|
+
if (
|
|
175
|
+
len(cleaned) >= 2
|
|
176
|
+
and cleaned[0] == cleaned[-1]
|
|
177
|
+
and cleaned[0] in {"'", '"'}
|
|
178
|
+
):
|
|
179
|
+
return cleaned[1:-1]
|
|
180
|
+
return cleaned
|