@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,376 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# gsd-path project runtime
|
|
3
|
+
"""Lint build task briefs against the layer base before dispatch."""
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import json
|
|
7
|
+
import re
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path, PurePosixPath
|
|
10
|
+
from typing import Dict, List, Optional, Sequence, Set, Tuple
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
import _common
|
|
14
|
+
except ImportError: # pragma: no cover - package import used by tests
|
|
15
|
+
from scripts import _common
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
DEFAULT_TASKS_DIR = ".project/tasks"
|
|
19
|
+
REQUIRED_FIELDS = (
|
|
20
|
+
"id",
|
|
21
|
+
"title",
|
|
22
|
+
"wave",
|
|
23
|
+
"deps",
|
|
24
|
+
"status",
|
|
25
|
+
"agent",
|
|
26
|
+
"base",
|
|
27
|
+
"worktree",
|
|
28
|
+
"task_branch",
|
|
29
|
+
"files",
|
|
30
|
+
)
|
|
31
|
+
FORBIDDEN_FIELDS = ("commit",)
|
|
32
|
+
REQUIRED_SECTIONS = (
|
|
33
|
+
"Context",
|
|
34
|
+
"Approach",
|
|
35
|
+
"Interface contract",
|
|
36
|
+
"Intent coverage",
|
|
37
|
+
"Acceptance criteria",
|
|
38
|
+
"Verify",
|
|
39
|
+
"Log",
|
|
40
|
+
)
|
|
41
|
+
PROSE_SECTIONS = ("Context", "Approach", "Interface contract")
|
|
42
|
+
FIELD_PATTERN = _common.FIELD_PATTERN
|
|
43
|
+
INLINE_LIST_PATTERN = _common.INLINE_LIST_PATTERN
|
|
44
|
+
LIST_ITEM_PATTERN = _common.LIST_ITEM_PATTERN
|
|
45
|
+
HEADING_PATTERN = re.compile(r"(?m)^## (?P<name>.+?)\s*$")
|
|
46
|
+
COMMENT_PATTERN = re.compile(r"<!--.*?-->", re.DOTALL)
|
|
47
|
+
BACKTICK_PATTERN = re.compile(r"`([^`\n]+)`")
|
|
48
|
+
PATH_TOKEN_PATTERN = re.compile(r"[A-Za-z0-9._~/-]+")
|
|
49
|
+
VERIFY_BLOCK_PATTERN = re.compile(r"```bash[ \t]*\n(?P<block>.*?)```", re.DOTALL)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class BriefError(RuntimeError):
|
|
53
|
+
"""Raised when task briefs fail the layer-prep lint or inputs are unusable."""
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
_run_git = _common.run_git
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _resolve_base(repo: Path, base: str) -> str:
|
|
60
|
+
result = _run_git(repo, "rev-parse", "--verify", "--quiet", f"{base}^{{commit}}")
|
|
61
|
+
if result.returncode != 0:
|
|
62
|
+
raise BriefError(f"--base does not resolve to a commit: {base}")
|
|
63
|
+
return result.stdout.strip()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _base_exists(repo: Path, base: str, path: str) -> bool:
|
|
67
|
+
return _run_git(repo, "cat-file", "-e", f"{base}:{path}").returncode == 0
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _supplied_contract(repo: Path, task: Path, token: str) -> bool:
|
|
71
|
+
"""Plan approval checkpoints these supplied inputs after the brief gate."""
|
|
72
|
+
track = task.parent.parent.relative_to(repo).as_posix()
|
|
73
|
+
if track not in {".project", ".project/next"}:
|
|
74
|
+
return False
|
|
75
|
+
if token not in {
|
|
76
|
+
f"{track}/intent/INTENT.md",
|
|
77
|
+
f"{track}/research/SYNTHESIS.md",
|
|
78
|
+
}:
|
|
79
|
+
return False
|
|
80
|
+
path = repo / token
|
|
81
|
+
return path.is_file() and path.resolve() == repo.resolve() / token
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
_strip_yaml_comment = _common.strip_yaml_comment
|
|
85
|
+
_unquote = _common.unquote
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _frontmatter(text: str) -> Tuple[Optional[Dict[str, object]], Optional[str]]:
|
|
89
|
+
lines = text.splitlines()
|
|
90
|
+
if not lines or lines[0] != "---":
|
|
91
|
+
return None, "missing YAML frontmatter"
|
|
92
|
+
fields: Dict[str, object] = {}
|
|
93
|
+
index = 1
|
|
94
|
+
while index < len(lines):
|
|
95
|
+
line = lines[index]
|
|
96
|
+
if line == "---":
|
|
97
|
+
return fields, None
|
|
98
|
+
match = FIELD_PATTERN.match(line)
|
|
99
|
+
if match:
|
|
100
|
+
key = match.group("key")
|
|
101
|
+
if key in fields:
|
|
102
|
+
return None, f"frontmatter repeats field: {key}"
|
|
103
|
+
value = _strip_yaml_comment(match.group("value"))
|
|
104
|
+
inline = INLINE_LIST_PATTERN.fullmatch(value)
|
|
105
|
+
if inline is not None:
|
|
106
|
+
body = inline.group("body").strip()
|
|
107
|
+
fields[key] = [
|
|
108
|
+
_unquote(item)
|
|
109
|
+
for item in body.split(",")
|
|
110
|
+
if item.strip()
|
|
111
|
+
]
|
|
112
|
+
index += 1
|
|
113
|
+
continue
|
|
114
|
+
if value:
|
|
115
|
+
fields[key] = _unquote(value)
|
|
116
|
+
index += 1
|
|
117
|
+
continue
|
|
118
|
+
items: List[str] = []
|
|
119
|
+
cursor = index + 1
|
|
120
|
+
while cursor < len(lines):
|
|
121
|
+
item = LIST_ITEM_PATTERN.match(lines[cursor])
|
|
122
|
+
if not item:
|
|
123
|
+
break
|
|
124
|
+
items.append(_unquote(item.group("value")))
|
|
125
|
+
cursor += 1
|
|
126
|
+
fields[key] = items
|
|
127
|
+
index = cursor
|
|
128
|
+
continue
|
|
129
|
+
if line.strip() and not line.lstrip().startswith("#"):
|
|
130
|
+
return None, f"malformed frontmatter line: {line}"
|
|
131
|
+
index += 1
|
|
132
|
+
return None, "frontmatter is not closed"
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _sections(text: str) -> Dict[str, str]:
|
|
136
|
+
headings = list(HEADING_PATTERN.finditer(text))
|
|
137
|
+
sections: Dict[str, str] = {}
|
|
138
|
+
for position, heading in enumerate(headings):
|
|
139
|
+
end = headings[position + 1].start() if position + 1 < len(headings) else len(text)
|
|
140
|
+
sections[heading.group("name")] = text[heading.end() : end]
|
|
141
|
+
return sections
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _clean(body: str) -> str:
|
|
145
|
+
return COMMENT_PATTERN.sub("", body).strip()
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _looks_like_path(token: str) -> bool:
|
|
149
|
+
return (
|
|
150
|
+
"/" in token
|
|
151
|
+
and PATH_TOKEN_PATTERN.fullmatch(token) is not None
|
|
152
|
+
and "://" not in token
|
|
153
|
+
and not token.startswith(("-", "/")) # /api/users is a route, not a repo path
|
|
154
|
+
and "<" not in token
|
|
155
|
+
and ">" not in token
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _normalize(path: str) -> str:
|
|
160
|
+
return str(PurePosixPath(path))
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _prose_tokens(body: str) -> List[str]:
|
|
164
|
+
cleaned = COMMENT_PATTERN.sub("", body)
|
|
165
|
+
return [
|
|
166
|
+
_normalize(match.group(1).strip())
|
|
167
|
+
for match in BACKTICK_PATTERN.finditer(cleaned)
|
|
168
|
+
if _looks_like_path(match.group(1).strip())
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def _verify_tokens(block: str) -> List[str]:
|
|
173
|
+
tokens = []
|
|
174
|
+
for line in block.splitlines():
|
|
175
|
+
parts = line.split()
|
|
176
|
+
for token in parts[1:]:
|
|
177
|
+
token = token.strip("\"'")
|
|
178
|
+
if _looks_like_path(token):
|
|
179
|
+
tokens.append(_normalize(token))
|
|
180
|
+
return tokens
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def _lint_task(
|
|
184
|
+
repo: Path, base: str, path: Path,
|
|
185
|
+
dependency_files: Optional[Dict[str, Set[str]]] = None,
|
|
186
|
+
landed_bases: Optional[Dict[str, str]] = None,
|
|
187
|
+
) -> Tuple[str, List[str], Optional[str], int]:
|
|
188
|
+
text = path.read_text(encoding="utf-8")
|
|
189
|
+
fields, error = _frontmatter(text)
|
|
190
|
+
task_id = path.stem
|
|
191
|
+
if fields and isinstance(fields.get("id"), str):
|
|
192
|
+
task_id = fields["id"] # type: ignore[assignment]
|
|
193
|
+
base = (landed_bases or {}).get(task_id, base)
|
|
194
|
+
problems: List[str] = []
|
|
195
|
+
checked = 0
|
|
196
|
+
if fields is None:
|
|
197
|
+
return task_id, [error or "invalid frontmatter"], None, checked
|
|
198
|
+
|
|
199
|
+
for field in REQUIRED_FIELDS:
|
|
200
|
+
if field not in fields:
|
|
201
|
+
problems.append(f"missing frontmatter field: {field}")
|
|
202
|
+
for field in FORBIDDEN_FIELDS:
|
|
203
|
+
if field in fields:
|
|
204
|
+
problems.append(f"forbidden frontmatter field: {field}")
|
|
205
|
+
|
|
206
|
+
sections = _sections(text)
|
|
207
|
+
for name in REQUIRED_SECTIONS:
|
|
208
|
+
body = sections.get(name)
|
|
209
|
+
if body is None:
|
|
210
|
+
problems.append(f"missing ## {name} section")
|
|
211
|
+
elif not _clean(body):
|
|
212
|
+
problems.append(f"## {name} section is empty")
|
|
213
|
+
|
|
214
|
+
supplied = (dependency_files or {}).get(task_id, set())
|
|
215
|
+
declared: Set[str] = set()
|
|
216
|
+
files = fields.get("files")
|
|
217
|
+
if isinstance(files, str):
|
|
218
|
+
problems.append("frontmatter files must be a list")
|
|
219
|
+
elif isinstance(files, list):
|
|
220
|
+
for entry in files:
|
|
221
|
+
candidate = PurePosixPath(entry)
|
|
222
|
+
if candidate.is_absolute():
|
|
223
|
+
problems.append(f"files entry is not repo-relative: {entry}")
|
|
224
|
+
continue
|
|
225
|
+
if ".." in candidate.parts:
|
|
226
|
+
problems.append(f"files entry must not contain '..': {entry}")
|
|
227
|
+
continue
|
|
228
|
+
normalized = str(candidate)
|
|
229
|
+
declared.add(normalized)
|
|
230
|
+
checked += 1
|
|
231
|
+
if ".git" in candidate.parts:
|
|
232
|
+
problems.append(f"files entry must not enter .git: {normalized}")
|
|
233
|
+
continue
|
|
234
|
+
for parent in candidate.parents:
|
|
235
|
+
if str(parent) == ".":
|
|
236
|
+
break
|
|
237
|
+
kind = _run_git(repo, "cat-file", "-t", f"{base}:{parent}")
|
|
238
|
+
if kind.returncode == 0 and kind.stdout.strip() != "tree":
|
|
239
|
+
problems.append(
|
|
240
|
+
f"files entry {normalized} has non-directory ancestor "
|
|
241
|
+
f"{parent} at the layer base"
|
|
242
|
+
)
|
|
243
|
+
break
|
|
244
|
+
|
|
245
|
+
for name in PROSE_SECTIONS:
|
|
246
|
+
body = sections.get(name)
|
|
247
|
+
if body is None or not _clean(body):
|
|
248
|
+
continue
|
|
249
|
+
for token in _prose_tokens(body):
|
|
250
|
+
checked += 1
|
|
251
|
+
if (
|
|
252
|
+
token not in declared
|
|
253
|
+
and token not in supplied
|
|
254
|
+
and not _supplied_contract(repo, path, token)
|
|
255
|
+
and not _base_exists(repo, base, token)
|
|
256
|
+
):
|
|
257
|
+
problems.append(f"## {name} names a path missing at the layer base: {token}")
|
|
258
|
+
|
|
259
|
+
verify_body = sections.get("Verify")
|
|
260
|
+
if verify_body is not None and _clean(verify_body):
|
|
261
|
+
block = VERIFY_BLOCK_PATTERN.search(verify_body)
|
|
262
|
+
if block is None or not block.group("block").strip():
|
|
263
|
+
problems.append("## Verify must contain a non-empty fenced bash block")
|
|
264
|
+
else:
|
|
265
|
+
for token in _verify_tokens(block.group("block")):
|
|
266
|
+
checked += 1
|
|
267
|
+
if token not in declared and token not in supplied and not _base_exists(repo, base, token):
|
|
268
|
+
problems.append(f"## Verify names a path missing at the layer base: {token}")
|
|
269
|
+
|
|
270
|
+
contract = None
|
|
271
|
+
contract_body = sections.get("Interface contract")
|
|
272
|
+
if contract_body is not None:
|
|
273
|
+
normalized = " ".join(_clean(contract_body).split())
|
|
274
|
+
if normalized and normalized not in {"None", "- None"}:
|
|
275
|
+
contract = _clean(contract_body)
|
|
276
|
+
|
|
277
|
+
return task_id, problems, contract, checked
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def validate_task_briefs(
|
|
281
|
+
root: Path, base: str, tasks_dir: str = DEFAULT_TASKS_DIR,
|
|
282
|
+
*, dependency_files: Optional[Dict[str, Set[str]]] = None,
|
|
283
|
+
landed_bases: Optional[Dict[str, str]] = None,
|
|
284
|
+
) -> Dict[str, object]:
|
|
285
|
+
"""Lint task briefs using the caller's validation bases.
|
|
286
|
+
|
|
287
|
+
Dispatch uses the layer base without overrides. Plan approval supplies
|
|
288
|
+
transitive dependency files for pending tasks and resolved historical bases
|
|
289
|
+
for landed tasks, whose immutable briefs must survive later file changes.
|
|
290
|
+
The caller validates the task graph and landed metadata before supplying
|
|
291
|
+
these mappings; landed tasks receive no dependency-file allowance.
|
|
292
|
+
"""
|
|
293
|
+
|
|
294
|
+
resolved_base = _resolve_base(root, base)
|
|
295
|
+
tasks_path = root / tasks_dir
|
|
296
|
+
if not tasks_path.is_dir():
|
|
297
|
+
raise BriefError(f"tasks directory not found: {tasks_dir}")
|
|
298
|
+
|
|
299
|
+
problems: List[str] = []
|
|
300
|
+
contracts: Dict[str, Set[str]] = {}
|
|
301
|
+
checked = 0
|
|
302
|
+
task_files = sorted(tasks_path.glob("*.md"))
|
|
303
|
+
if not task_files:
|
|
304
|
+
raise BriefError(f"no task briefs found in {tasks_dir}")
|
|
305
|
+
for path in task_files:
|
|
306
|
+
task_id, task_problems, contract, task_checked = _lint_task(
|
|
307
|
+
root, resolved_base, path, dependency_files, landed_bases
|
|
308
|
+
)
|
|
309
|
+
problems.extend(f"{task_id}: {problem}" for problem in task_problems)
|
|
310
|
+
if contract is not None:
|
|
311
|
+
for entry in re.split(r"(?m)^-[ \t]+", contract):
|
|
312
|
+
shape = " ".join(entry.split())
|
|
313
|
+
if shape:
|
|
314
|
+
contracts.setdefault(shape, set()).add(task_id)
|
|
315
|
+
checked += task_checked
|
|
316
|
+
|
|
317
|
+
for shape, task_ids in contracts.items():
|
|
318
|
+
if len(task_ids) == 1:
|
|
319
|
+
task_id = next(iter(task_ids))
|
|
320
|
+
problems.append(
|
|
321
|
+
f"{task_id}: interface contract is not shared by any other task: {shape}"
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
if problems:
|
|
325
|
+
raise BriefError("\n".join(problems))
|
|
326
|
+
return {"base": resolved_base, "checked": checked, "tasks": len(task_files)}
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def _tasks_dir(value: str) -> str:
|
|
330
|
+
"""Argparse type for --tasks-dir: a relative POSIX-style path."""
|
|
331
|
+
|
|
332
|
+
path = PurePosixPath(value)
|
|
333
|
+
if path.is_absolute():
|
|
334
|
+
raise argparse.ArgumentTypeError(
|
|
335
|
+
f"--tasks-dir must be a relative path, found absolute: {value}"
|
|
336
|
+
)
|
|
337
|
+
if ".." in path.parts:
|
|
338
|
+
raise argparse.ArgumentTypeError(
|
|
339
|
+
f"--tasks-dir must not contain '..', found: {value}"
|
|
340
|
+
)
|
|
341
|
+
return str(path)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def parser() -> argparse.ArgumentParser:
|
|
345
|
+
argument_parser = argparse.ArgumentParser(description=__doc__)
|
|
346
|
+
argument_parser.add_argument("--repo", type=Path, required=True)
|
|
347
|
+
argument_parser.add_argument(
|
|
348
|
+
"--base",
|
|
349
|
+
required=True,
|
|
350
|
+
help="full SHA of the clean layer base commit the briefs are checked against",
|
|
351
|
+
)
|
|
352
|
+
argument_parser.add_argument(
|
|
353
|
+
"--tasks-dir",
|
|
354
|
+
type=_tasks_dir,
|
|
355
|
+
default=DEFAULT_TASKS_DIR,
|
|
356
|
+
help="relative POSIX-style directory under --repo holding the task files "
|
|
357
|
+
"(default: .project/tasks)",
|
|
358
|
+
)
|
|
359
|
+
return argument_parser
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
363
|
+
arguments = parser().parse_args(argv)
|
|
364
|
+
try:
|
|
365
|
+
result = validate_task_briefs(
|
|
366
|
+
arguments.repo.resolve(), arguments.base, arguments.tasks_dir
|
|
367
|
+
)
|
|
368
|
+
except BriefError as error:
|
|
369
|
+
print(f"task brief validation failed: {error}", file=sys.stderr)
|
|
370
|
+
return 1
|
|
371
|
+
print(json.dumps(result, sort_keys=True))
|
|
372
|
+
return 0
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
if __name__ == "__main__":
|
|
376
|
+
raise SystemExit(main())
|