@opengsd/gsd-path 1.4.0 → 1.6.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/CHANGELOG.md +460 -341
- package/DOCS.md +16 -5
- package/FULL.md +67 -6
- package/HOOKS.md +158 -10
- package/MIGRATE.md +12 -0
- package/QUICK.md +4 -2
- package/README.md +136 -116
- package/RUNTIME.md +24 -6
- package/UPDATE.md +39 -3
- package/WORKFLOW.md +80 -4
- package/package.json +5 -2
- package/platforms/shared-agents/dispatch.md +13 -0
- package/scripts/_common.py +256 -2
- package/scripts/archive_milestone.py +14 -13
- package/scripts/build_recovery.py +155 -58
- package/scripts/build_state.py +274 -8
- package/scripts/check_docs_audit.py +77 -4
- package/scripts/check_handoffs.py +635 -57
- package/scripts/check_task_briefs.py +293 -32
- package/scripts/detect_project.py +260 -20
- package/scripts/discussion_records.py +9 -1
- package/scripts/discussion_validate.py +93 -35
- package/scripts/dispatch_driver.py +549 -53
- package/scripts/git_guard.py +27 -8
- package/scripts/guard_hook.py +2630 -210
- package/scripts/install.mjs +99 -11
- package/scripts/install.py +231 -46
- package/scripts/integration.py +244 -65
- package/scripts/isolation.py +539 -70
- package/scripts/loop_run.py +16 -4
- package/scripts/members.py +77 -32
- package/scripts/migrate_core.py +2 -0
- package/scripts/model_policy.py +5 -1
- package/scripts/path_config.py +3 -3
- package/scripts/pipeline_diagnose.py +17 -2
- package/scripts/pipeline_git.py +131 -42
- package/scripts/pipeline_state.py +139 -39
- package/scripts/pipeline_undo.py +118 -16
- package/scripts/promote_lookahead.py +3 -3
- package/scripts/review_findings.py +180 -44
- package/scripts/roadmap.py +9 -1
- package/scripts/runtime_store.py +21 -2
- package/scripts/skill-resources.json +9 -2
- package/scripts/state_checkpoint.py +39 -36
- package/scripts/state_promote.py +15 -4
- package/scripts/status_runtime.py +22 -4
- package/scripts/task_context.py +14 -3
- package/scripts/wizard.mjs +1 -0
- package/scripts/workflow_run.py +14 -4
- package/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path/DEFINE.md +34 -5
- package/skills/gsd-path/PLAN.md +14 -3
- package/skills/gsd-path/RESEARCH.md +11 -0
- package/skills/gsd-path/ROADMAP.md +16 -6
- package/skills/gsd-path/SHIP.md +32 -5
- package/skills/gsd-path/SKILL.md +52 -24
- package/skills/gsd-path/references/build-native.md +112 -10
- package/skills/gsd-path/references/build-recovery.md +13 -0
- package/skills/gsd-path/references/coder.md +7 -3
- package/skills/gsd-path/references/dispatch.md +13 -0
- package/skills/gsd-path/references/docs-auditor.md +5 -0
- package/skills/gsd-path/references/operating-rules.md +11 -3
- package/skills/gsd-path/references/planner.md +26 -4
- package/skills/gsd-path/references/reviewer-final.md +20 -2
- package/skills/gsd-path/references/reviewer-wave.md +56 -12
- package/skills/gsd-path/references/reviewer.md +3 -1
- package/skills/gsd-path/references/runtime-selection.md +9 -0
- package/skills/gsd-path/references/spec-probes.md +150 -0
- package/skills/gsd-path/scripts/_common.py +256 -2
- package/skills/gsd-path/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path/scripts/build_recovery.py +155 -58
- package/skills/gsd-path/scripts/build_state.py +274 -8
- package/skills/gsd-path/scripts/check_docs_audit.py +77 -4
- package/skills/gsd-path/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path/scripts/detect_project.py +260 -20
- package/skills/gsd-path/scripts/discussion_records.py +9 -1
- package/skills/gsd-path/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path/scripts/dispatch_driver.py +549 -53
- package/skills/gsd-path/scripts/git_guard.py +27 -8
- package/skills/gsd-path/scripts/integration.py +244 -65
- package/skills/gsd-path/scripts/isolation.py +539 -70
- package/skills/gsd-path/scripts/loop_run.py +16 -4
- package/skills/gsd-path/scripts/members.py +77 -32
- package/skills/gsd-path/scripts/model_policy.py +5 -1
- package/skills/gsd-path/scripts/path_config.py +3 -3
- package/skills/gsd-path/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path/scripts/review_findings.py +180 -44
- package/skills/gsd-path/scripts/roadmap.py +9 -1
- package/skills/gsd-path/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path/scripts/state_promote.py +15 -4
- package/skills/gsd-path/scripts/status_runtime.py +22 -4
- package/skills/gsd-path/scripts/task_context.py +14 -3
- package/skills/gsd-path/scripts/workflow_run.py +14 -4
- package/skills/gsd-path/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path/templates/docs-audit.md +5 -1
- package/skills/gsd-path/templates/final-review.md +11 -2
- package/skills/gsd-path/templates/intent.md +30 -0
- package/skills/gsd-path/templates/patch-findings.md +3 -3
- package/skills/gsd-path/templates/plan.md +17 -2
- package/skills/gsd-path/templates/research-handoff.md +14 -3
- package/skills/gsd-path/templates/state.md +2 -1
- package/skills/gsd-path/templates/task.md +1 -0
- package/skills/gsd-path/templates/wave-review.md +28 -9
- package/skills/gsd-path-build/references/build-native.md +112 -10
- package/skills/gsd-path-build/references/build-recovery.md +13 -0
- package/skills/gsd-path-build/references/coder.md +7 -3
- package/skills/gsd-path-build/references/dispatch.md +13 -0
- package/skills/gsd-path-build/references/operating-rules.md +11 -3
- package/skills/gsd-path-build/references/reviewer-final.md +20 -2
- package/skills/gsd-path-build/references/reviewer-wave.md +56 -12
- package/skills/gsd-path-build/references/reviewer.md +3 -1
- package/skills/gsd-path-build/references/runtime-selection.md +9 -0
- package/skills/gsd-path-build/references/spec-probes.md +150 -0
- package/skills/gsd-path-build/scripts/_common.py +256 -2
- package/skills/gsd-path-build/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-build/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-build/scripts/build_state.py +274 -8
- package/skills/gsd-path-build/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-build/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-build/scripts/detect_project.py +260 -20
- package/skills/gsd-path-build/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-build/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-build/scripts/dispatch_driver.py +549 -53
- package/skills/gsd-path-build/scripts/integration.py +244 -65
- package/skills/gsd-path-build/scripts/isolation.py +539 -70
- package/skills/gsd-path-build/scripts/loop_run.py +16 -4
- package/skills/gsd-path-build/scripts/members.py +77 -32
- package/skills/gsd-path-build/scripts/model_policy.py +5 -1
- package/skills/gsd-path-build/scripts/path_config.py +3 -3
- package/skills/gsd-path-build/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-build/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-build/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-build/scripts/review_findings.py +180 -44
- package/skills/gsd-path-build/scripts/roadmap.py +9 -1
- package/skills/gsd-path-build/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-build/scripts/state_promote.py +15 -4
- package/skills/gsd-path-build/scripts/task_context.py +14 -3
- package/skills/gsd-path-build/scripts/workflow_run.py +14 -4
- package/skills/gsd-path-build/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-build/templates/task.md +1 -0
- package/skills/gsd-path-build/templates/wave-review.md +28 -9
- package/skills/gsd-path-decide/references/dispatch.md +13 -0
- package/skills/gsd-path-decide/references/operating-rules.md +11 -3
- package/skills/gsd-path-decide/references/runtime-selection.md +9 -0
- package/skills/gsd-path-decide/scripts/_common.py +256 -2
- package/skills/gsd-path-decide/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-decide/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-decide/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-decide/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-decide/scripts/detect_project.py +260 -20
- package/skills/gsd-path-decide/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-decide/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-decide/scripts/integration.py +244 -65
- package/skills/gsd-path-decide/scripts/isolation.py +539 -70
- package/skills/gsd-path-decide/scripts/loop_run.py +16 -4
- package/skills/gsd-path-decide/scripts/members.py +77 -32
- package/skills/gsd-path-decide/scripts/model_policy.py +5 -1
- package/skills/gsd-path-decide/scripts/path_config.py +3 -3
- package/skills/gsd-path-decide/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-decide/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-decide/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-decide/scripts/roadmap.py +9 -1
- package/skills/gsd-path-decide/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-decide/scripts/state_promote.py +15 -4
- package/skills/gsd-path-decide/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-define/SKILL.md +34 -5
- package/skills/gsd-path-define/references/build-recovery.md +13 -0
- package/skills/gsd-path-define/references/operating-rules.md +11 -3
- package/skills/gsd-path-define/references/runtime-selection.md +9 -0
- package/skills/gsd-path-define/references/spec-probes.md +150 -0
- package/skills/gsd-path-define/scripts/_common.py +256 -2
- package/skills/gsd-path-define/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-define/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-define/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-define/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-define/scripts/detect_project.py +260 -20
- package/skills/gsd-path-define/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-define/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-define/scripts/integration.py +244 -65
- package/skills/gsd-path-define/scripts/isolation.py +539 -70
- package/skills/gsd-path-define/scripts/loop_run.py +16 -4
- package/skills/gsd-path-define/scripts/members.py +77 -32
- package/skills/gsd-path-define/scripts/model_policy.py +5 -1
- package/skills/gsd-path-define/scripts/path_config.py +3 -3
- package/skills/gsd-path-define/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-define/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-define/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-define/scripts/roadmap.py +9 -1
- package/skills/gsd-path-define/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-define/scripts/state_promote.py +15 -4
- package/skills/gsd-path-define/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-define/templates/intent.md +30 -0
- package/skills/gsd-path-define/templates/state.md +2 -1
- package/skills/gsd-path-discuss/references/operating-rules.md +11 -3
- package/skills/gsd-path-discuss/references/runtime-selection.md +9 -0
- package/skills/gsd-path-discuss/scripts/_common.py +256 -2
- package/skills/gsd-path-discuss/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-discuss/scripts/loop_run.py +16 -4
- package/skills/gsd-path-discuss/scripts/model_policy.py +5 -1
- package/skills/gsd-path-discuss/scripts/path_config.py +3 -3
- package/skills/gsd-path-discuss/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-docs-audit/references/dispatch.md +13 -0
- package/skills/gsd-path-docs-audit/references/docs-auditor.md +5 -0
- package/skills/gsd-path-docs-audit/references/operating-rules.md +11 -3
- package/skills/gsd-path-docs-audit/references/runtime-selection.md +9 -0
- package/skills/gsd-path-docs-audit/scripts/_common.py +256 -2
- package/skills/gsd-path-docs-audit/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-docs-audit/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-docs-audit/scripts/check_docs_audit.py +77 -4
- package/skills/gsd-path-docs-audit/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-docs-audit/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-docs-audit/scripts/detect_project.py +260 -20
- package/skills/gsd-path-docs-audit/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-docs-audit/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-docs-audit/scripts/integration.py +244 -65
- package/skills/gsd-path-docs-audit/scripts/isolation.py +539 -70
- package/skills/gsd-path-docs-audit/scripts/loop_run.py +16 -4
- package/skills/gsd-path-docs-audit/scripts/members.py +77 -32
- package/skills/gsd-path-docs-audit/scripts/model_policy.py +5 -1
- package/skills/gsd-path-docs-audit/scripts/path_config.py +3 -3
- package/skills/gsd-path-docs-audit/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-docs-audit/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-docs-audit/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-docs-audit/scripts/roadmap.py +9 -1
- package/skills/gsd-path-docs-audit/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-docs-audit/scripts/state_promote.py +15 -4
- package/skills/gsd-path-docs-audit/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-docs-audit/templates/docs-audit.md +5 -1
- package/skills/gsd-path-forensics/references/operating-rules.md +11 -3
- package/skills/gsd-path-forensics/references/runtime-selection.md +9 -0
- package/skills/gsd-path-forensics/scripts/_common.py +256 -2
- package/skills/gsd-path-forensics/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-forensics/scripts/loop_run.py +16 -4
- package/skills/gsd-path-forensics/scripts/model_policy.py +5 -1
- package/skills/gsd-path-forensics/scripts/path_config.py +3 -3
- package/skills/gsd-path-forensics/scripts/pipeline_diagnose.py +17 -2
- package/skills/gsd-path-forensics/scripts/pipeline_undo.py +118 -16
- package/skills/gsd-path-forensics/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-inspect/references/dispatch.md +13 -0
- package/skills/gsd-path-inspect/references/docs-auditor.md +5 -0
- package/skills/gsd-path-inspect/references/operating-rules.md +11 -3
- package/skills/gsd-path-inspect/references/runtime-selection.md +9 -0
- package/skills/gsd-path-inspect/scripts/_common.py +256 -2
- package/skills/gsd-path-inspect/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-inspect/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-inspect/scripts/check_docs_audit.py +77 -4
- package/skills/gsd-path-inspect/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-inspect/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-inspect/scripts/detect_project.py +260 -20
- package/skills/gsd-path-inspect/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-inspect/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-inspect/scripts/integration.py +244 -65
- package/skills/gsd-path-inspect/scripts/isolation.py +539 -70
- package/skills/gsd-path-inspect/scripts/loop_run.py +16 -4
- package/skills/gsd-path-inspect/scripts/members.py +77 -32
- package/skills/gsd-path-inspect/scripts/model_policy.py +5 -1
- package/skills/gsd-path-inspect/scripts/path_config.py +3 -3
- package/skills/gsd-path-inspect/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-inspect/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-inspect/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-inspect/scripts/roadmap.py +9 -1
- package/skills/gsd-path-inspect/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-inspect/scripts/state_promote.py +15 -4
- package/skills/gsd-path-inspect/scripts/workflow_run.py +14 -4
- package/skills/gsd-path-inspect/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-inspect/templates/docs-audit.md +5 -1
- package/skills/gsd-path-inspect/templates/state.md +2 -1
- package/skills/gsd-path-loop/references/operating-rules.md +11 -3
- package/skills/gsd-path-loop/references/runtime-selection.md +9 -0
- package/skills/gsd-path-loop/scripts/_common.py +256 -2
- package/skills/gsd-path-loop/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-loop/scripts/loop_run.py +16 -4
- package/skills/gsd-path-loop/scripts/model_policy.py +5 -1
- package/skills/gsd-path-loop/scripts/path_config.py +3 -3
- package/skills/gsd-path-loop/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-migrate/SKILL.md +8 -0
- package/skills/gsd-path-migrate/references/operating-rules.md +11 -3
- package/skills/gsd-path-migrate/references/runtime-selection.md +9 -0
- package/skills/gsd-path-migrate/scripts/_common.py +256 -2
- package/skills/gsd-path-migrate/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-migrate/scripts/loop_run.py +16 -4
- package/skills/gsd-path-migrate/scripts/migrate_core.py +2 -0
- package/skills/gsd-path-migrate/scripts/model_policy.py +5 -1
- package/skills/gsd-path-migrate/scripts/path_config.py +3 -3
- package/skills/gsd-path-plan/SKILL.md +14 -3
- package/skills/gsd-path-plan/references/build-recovery.md +13 -0
- package/skills/gsd-path-plan/references/dispatch.md +13 -0
- package/skills/gsd-path-plan/references/operating-rules.md +11 -3
- package/skills/gsd-path-plan/references/planner.md +26 -4
- package/skills/gsd-path-plan/references/runtime-selection.md +9 -0
- package/skills/gsd-path-plan/references/spec-probes.md +150 -0
- package/skills/gsd-path-plan/scripts/_common.py +256 -2
- package/skills/gsd-path-plan/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-plan/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-plan/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-plan/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-plan/scripts/detect_project.py +260 -20
- package/skills/gsd-path-plan/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-plan/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-plan/scripts/integration.py +244 -65
- package/skills/gsd-path-plan/scripts/isolation.py +539 -70
- package/skills/gsd-path-plan/scripts/loop_run.py +16 -4
- package/skills/gsd-path-plan/scripts/members.py +77 -32
- package/skills/gsd-path-plan/scripts/model_policy.py +5 -1
- package/skills/gsd-path-plan/scripts/path_config.py +3 -3
- package/skills/gsd-path-plan/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-plan/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-plan/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-plan/scripts/roadmap.py +9 -1
- package/skills/gsd-path-plan/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-plan/scripts/state_promote.py +15 -4
- package/skills/gsd-path-plan/scripts/workflow_run.py +14 -4
- package/skills/gsd-path-plan/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-plan/templates/patch-findings.md +3 -3
- package/skills/gsd-path-plan/templates/plan.md +17 -2
- package/skills/gsd-path-plan/templates/task.md +1 -0
- package/skills/gsd-path-research/SKILL.md +11 -0
- package/skills/gsd-path-research/references/dispatch.md +13 -0
- package/skills/gsd-path-research/references/operating-rules.md +11 -3
- package/skills/gsd-path-research/references/runtime-selection.md +9 -0
- package/skills/gsd-path-research/scripts/_common.py +256 -2
- package/skills/gsd-path-research/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-research/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-research/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-research/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-research/scripts/detect_project.py +260 -20
- package/skills/gsd-path-research/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-research/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-research/scripts/integration.py +244 -65
- package/skills/gsd-path-research/scripts/isolation.py +539 -70
- package/skills/gsd-path-research/scripts/loop_run.py +16 -4
- package/skills/gsd-path-research/scripts/members.py +77 -32
- package/skills/gsd-path-research/scripts/model_policy.py +5 -1
- package/skills/gsd-path-research/scripts/path_config.py +3 -3
- package/skills/gsd-path-research/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-research/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-research/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-research/scripts/roadmap.py +9 -1
- package/skills/gsd-path-research/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-research/scripts/state_promote.py +15 -4
- package/skills/gsd-path-research/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-research/templates/research-handoff.md +14 -3
- package/skills/gsd-path-roadmap/SKILL.md +16 -6
- package/skills/gsd-path-roadmap/references/dispatch.md +13 -0
- package/skills/gsd-path-roadmap/references/operating-rules.md +11 -3
- package/skills/gsd-path-roadmap/references/runtime-selection.md +9 -0
- package/skills/gsd-path-roadmap/scripts/_common.py +256 -2
- package/skills/gsd-path-roadmap/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-roadmap/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-roadmap/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-roadmap/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-roadmap/scripts/detect_project.py +260 -20
- package/skills/gsd-path-roadmap/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-roadmap/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-roadmap/scripts/integration.py +244 -65
- package/skills/gsd-path-roadmap/scripts/isolation.py +539 -70
- package/skills/gsd-path-roadmap/scripts/loop_run.py +16 -4
- package/skills/gsd-path-roadmap/scripts/members.py +77 -32
- package/skills/gsd-path-roadmap/scripts/model_policy.py +5 -1
- package/skills/gsd-path-roadmap/scripts/path_config.py +3 -3
- package/skills/gsd-path-roadmap/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-roadmap/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-roadmap/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-roadmap/scripts/roadmap.py +9 -1
- package/skills/gsd-path-roadmap/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-roadmap/scripts/state_promote.py +15 -4
- package/skills/gsd-path-roadmap/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-ship/SKILL.md +32 -5
- package/skills/gsd-path-ship/references/dispatch.md +13 -0
- package/skills/gsd-path-ship/references/operating-rules.md +11 -3
- package/skills/gsd-path-ship/references/reviewer-final.md +20 -2
- package/skills/gsd-path-ship/references/reviewer-wave.md +56 -12
- package/skills/gsd-path-ship/references/reviewer.md +3 -1
- package/skills/gsd-path-ship/references/runtime-selection.md +9 -0
- package/skills/gsd-path-ship/references/spec-probes.md +150 -0
- package/skills/gsd-path-ship/scripts/_common.py +256 -2
- package/skills/gsd-path-ship/scripts/archive_milestone.py +14 -13
- package/skills/gsd-path-ship/scripts/build_recovery.py +155 -58
- package/skills/gsd-path-ship/scripts/build_state.py +274 -8
- package/skills/gsd-path-ship/scripts/check_handoffs.py +635 -57
- package/skills/gsd-path-ship/scripts/check_task_briefs.py +293 -32
- package/skills/gsd-path-ship/scripts/detect_project.py +260 -20
- package/skills/gsd-path-ship/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-ship/scripts/discussion_validate.py +93 -35
- package/skills/gsd-path-ship/scripts/integration.py +244 -65
- package/skills/gsd-path-ship/scripts/isolation.py +539 -70
- package/skills/gsd-path-ship/scripts/loop_run.py +16 -4
- package/skills/gsd-path-ship/scripts/members.py +77 -32
- package/skills/gsd-path-ship/scripts/model_policy.py +5 -1
- package/skills/gsd-path-ship/scripts/path_config.py +3 -3
- package/skills/gsd-path-ship/scripts/pipeline_git.py +131 -42
- package/skills/gsd-path-ship/scripts/pipeline_state.py +139 -39
- package/skills/gsd-path-ship/scripts/promote_lookahead.py +3 -3
- package/skills/gsd-path-ship/scripts/roadmap.py +9 -1
- package/skills/gsd-path-ship/scripts/state_checkpoint.py +39 -36
- package/skills/gsd-path-ship/scripts/state_promote.py +15 -4
- package/skills/gsd-path-ship/scripts/workflow_run.py +14 -4
- package/skills/gsd-path-ship/scripts/worktree_paths.py +54 -2
- package/skills/gsd-path-ship/templates/final-review.md +11 -2
- package/skills/gsd-path-ship/templates/patch-findings.md +3 -3
- package/skills/gsd-path-ship/templates/wave-review.md +28 -9
- package/skills/gsd-path-undo/references/operating-rules.md +11 -3
- package/skills/gsd-path-undo/references/runtime-selection.md +9 -0
- package/skills/gsd-path-undo/scripts/_common.py +256 -2
- package/skills/gsd-path-undo/scripts/discussion_records.py +9 -1
- package/skills/gsd-path-undo/scripts/loop_run.py +16 -4
- package/skills/gsd-path-undo/scripts/model_policy.py +5 -1
- package/skills/gsd-path-undo/scripts/path_config.py +3 -3
- package/skills/gsd-path-undo/scripts/pipeline_undo.py +118 -16
- package/skills/gsd-path-undo/scripts/worktree_paths.py +54 -2
- package/skills/path/DEFINE.md +34 -5
- package/skills/path/PLAN.md +14 -3
- package/skills/path/RESEARCH.md +11 -0
- package/skills/path/ROADMAP.md +16 -6
- package/skills/path/SHIP.md +32 -5
- package/skills/path/SKILL.md +52 -24
- package/skills/path/references/build-native.md +112 -10
- package/skills/path/references/build-recovery.md +13 -0
- package/skills/path/references/coder.md +7 -3
- package/skills/path/references/dispatch.md +13 -0
- package/skills/path/references/docs-auditor.md +5 -0
- package/skills/path/references/operating-rules.md +11 -3
- package/skills/path/references/planner.md +26 -4
- package/skills/path/references/reviewer-final.md +20 -2
- package/skills/path/references/reviewer-wave.md +56 -12
- package/skills/path/references/reviewer.md +3 -1
- package/skills/path/references/runtime-selection.md +9 -0
- package/skills/path/references/spec-probes.md +150 -0
- package/skills/path/scripts/_common.py +256 -2
- package/skills/path/scripts/archive_milestone.py +14 -13
- package/skills/path/scripts/build_recovery.py +155 -58
- package/skills/path/scripts/build_state.py +274 -8
- package/skills/path/scripts/check_docs_audit.py +77 -4
- package/skills/path/scripts/check_handoffs.py +635 -57
- package/skills/path/scripts/check_task_briefs.py +293 -32
- package/skills/path/scripts/detect_project.py +260 -20
- package/skills/path/scripts/discussion_records.py +9 -1
- package/skills/path/scripts/discussion_validate.py +93 -35
- package/skills/path/scripts/dispatch_driver.py +549 -53
- package/skills/path/scripts/git_guard.py +27 -8
- package/skills/path/scripts/integration.py +244 -65
- package/skills/path/scripts/isolation.py +539 -70
- package/skills/path/scripts/loop_run.py +16 -4
- package/skills/path/scripts/members.py +77 -32
- package/skills/path/scripts/model_policy.py +5 -1
- package/skills/path/scripts/path_config.py +3 -3
- package/skills/path/scripts/pipeline_git.py +131 -42
- package/skills/path/scripts/pipeline_state.py +139 -39
- package/skills/path/scripts/promote_lookahead.py +3 -3
- package/skills/path/scripts/review_findings.py +180 -44
- package/skills/path/scripts/roadmap.py +9 -1
- package/skills/path/scripts/state_checkpoint.py +39 -36
- package/skills/path/scripts/state_promote.py +15 -4
- package/skills/path/scripts/status_runtime.py +22 -4
- package/skills/path/scripts/task_context.py +14 -3
- package/skills/path/scripts/workflow_run.py +14 -4
- package/skills/path/scripts/worktree_paths.py +54 -2
- package/skills/path/templates/docs-audit.md +5 -1
- package/skills/path/templates/final-review.md +11 -2
- package/skills/path/templates/intent.md +30 -0
- package/skills/path/templates/patch-findings.md +3 -3
- package/skills/path/templates/plan.md +17 -2
- package/skills/path/templates/research-handoff.md +14 -3
- package/skills/path/templates/state.md +2 -1
- package/skills/path/templates/task.md +1 -0
- package/skills/path/templates/wave-review.md +28 -9
- package/skills/gsd-path/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-build/scripts/__pycache__/check_handoffs.cpython-312.pyc +0 -0
- package/skills/gsd-path-inspect/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-plan/scripts/__pycache__/_common.cpython-312.pyc +0 -0
- package/skills/gsd-path-ship/scripts/__pycache__/_common.cpython-312.pyc +0 -0
|
@@ -55,10 +55,22 @@ try:
|
|
|
55
55
|
fcntl.flock(fd, fcntl.LOCK_EX)
|
|
56
56
|
|
|
57
57
|
except ImportError: # Windows does not provide POSIX file locks.
|
|
58
|
+
import errno
|
|
58
59
|
import msvcrt
|
|
60
|
+
import time
|
|
59
61
|
|
|
60
62
|
def lock_exclusive(fd: int) -> None:
|
|
61
|
-
|
|
63
|
+
delay = 0.01
|
|
64
|
+
while True:
|
|
65
|
+
try:
|
|
66
|
+
os.lseek(fd, 0, os.SEEK_SET)
|
|
67
|
+
msvcrt.locking(fd, msvcrt.LK_NBLCK, 1)
|
|
68
|
+
return
|
|
69
|
+
except OSError as error:
|
|
70
|
+
if error.errno not in (errno.EACCES, errno.EAGAIN, errno.EDEADLK):
|
|
71
|
+
raise
|
|
72
|
+
time.sleep(delay)
|
|
73
|
+
delay = min(delay * 2, 0.25)
|
|
62
74
|
|
|
63
75
|
|
|
64
76
|
IGNORE_DIRS = {
|
|
@@ -217,16 +229,20 @@ HTML_BLOCK_START = re.compile(
|
|
|
217
229
|
re.IGNORECASE,
|
|
218
230
|
)
|
|
219
231
|
REPARSE_NAME_SURROGATE = 0x20000000
|
|
220
|
-
|
|
232
|
+
_POSIX_ANCHORED_EVIDENCE_SUPPORTED = (
|
|
221
233
|
hasattr(os, "O_DIRECTORY")
|
|
222
234
|
and hasattr(os, "O_NOFOLLOW")
|
|
223
235
|
and os.open in os.supports_dir_fd
|
|
224
236
|
and os.stat in os.supports_dir_fd
|
|
225
237
|
and os.stat in os.supports_follow_symlinks
|
|
226
238
|
)
|
|
239
|
+
WINDOWS_ANCHORED_EVIDENCE_SUPPORTED = os.name == "nt"
|
|
240
|
+
ANCHORED_EVIDENCE_SUPPORTED = (
|
|
241
|
+
_POSIX_ANCHORED_EVIDENCE_SUPPORTED or WINDOWS_ANCHORED_EVIDENCE_SUPPORTED
|
|
242
|
+
)
|
|
227
243
|
LISTDIR_DIR_FD_SUPPORTED = os.listdir in getattr(os, "supports_fd", ())
|
|
228
244
|
ANCHORED_STATE_CREATE_SUPPORTED = (
|
|
229
|
-
|
|
245
|
+
_POSIX_ANCHORED_EVIDENCE_SUPPORTED
|
|
230
246
|
and LISTDIR_DIR_FD_SUPPORTED
|
|
231
247
|
and os.mkdir in getattr(os, "supports_dir_fd", ())
|
|
232
248
|
and os.unlink in getattr(os, "supports_dir_fd", ())
|
|
@@ -269,11 +285,12 @@ def is_link_like_status(status: os.stat_result) -> bool:
|
|
|
269
285
|
def is_link_like(path: Path, status: os.stat_result) -> bool:
|
|
270
286
|
if is_link_like_status(status):
|
|
271
287
|
return True
|
|
272
|
-
|
|
273
|
-
if os.name != "nt" or isjunction is None:
|
|
288
|
+
if os.name != "nt":
|
|
274
289
|
return False
|
|
275
290
|
try:
|
|
276
|
-
return
|
|
291
|
+
return is_link_like_status(os.lstat(path))
|
|
292
|
+
except FileNotFoundError:
|
|
293
|
+
return False
|
|
277
294
|
except OSError as error:
|
|
278
295
|
raise DetectError(f"cannot inspect link-like evidence: {path}: {error}") from error
|
|
279
296
|
|
|
@@ -332,7 +349,7 @@ def is_managed_pipeline_directory(relative: str, root: Path) -> bool:
|
|
|
332
349
|
return is_verified_skill_bundle(relative, root)
|
|
333
350
|
|
|
334
351
|
|
|
335
|
-
def is_verified_skill_bundle_at(relative: str, directory_fd: int) -> bool:
|
|
352
|
+
def is_verified_skill_bundle_at(relative: str, directory_fd: int, root: Path) -> bool:
|
|
336
353
|
parts = PurePosixPath(relative).parts
|
|
337
354
|
if not parts:
|
|
338
355
|
return False
|
|
@@ -342,19 +359,45 @@ def is_verified_skill_bundle_at(relative: str, directory_fd: int) -> bool:
|
|
|
342
359
|
return False
|
|
343
360
|
if is_verified_installer_bundle(parts):
|
|
344
361
|
return True
|
|
362
|
+
if _POSIX_ANCHORED_EVIDENCE_SUPPORTED:
|
|
363
|
+
try:
|
|
364
|
+
status = os.stat(
|
|
365
|
+
"SKILL.md",
|
|
366
|
+
dir_fd=directory_fd,
|
|
367
|
+
follow_symlinks=False,
|
|
368
|
+
)
|
|
369
|
+
except FileNotFoundError:
|
|
370
|
+
return False
|
|
371
|
+
except OSError as error:
|
|
372
|
+
raise DetectError(
|
|
373
|
+
f"cannot inspect managed skill bundle: {relative}: {error}"
|
|
374
|
+
) from error
|
|
375
|
+
return not is_link_like_status(status) and stat.S_ISREG(status.st_mode)
|
|
376
|
+
skill_fd = None
|
|
345
377
|
try:
|
|
346
|
-
|
|
378
|
+
win = get_windows_handles()
|
|
379
|
+
skill_fd = win.open_relative(
|
|
380
|
+
directory_fd,
|
|
347
381
|
"SKILL.md",
|
|
348
|
-
|
|
349
|
-
|
|
382
|
+
_FILE_READ_ATTRIBUTES,
|
|
383
|
+
_PIN_SHARE,
|
|
384
|
+
_FILE_OPEN,
|
|
385
|
+
0,
|
|
350
386
|
)
|
|
387
|
+
status = os.fstat(skill_fd)
|
|
351
388
|
except FileNotFoundError:
|
|
352
389
|
return False
|
|
353
390
|
except OSError as error:
|
|
391
|
+
if getattr(error, "winerror", None) == 2:
|
|
392
|
+
return False
|
|
354
393
|
raise DetectError(
|
|
355
394
|
f"cannot inspect managed skill bundle: {relative}: {error}"
|
|
356
395
|
) from error
|
|
357
|
-
|
|
396
|
+
finally:
|
|
397
|
+
if skill_fd is not None:
|
|
398
|
+
os.close(skill_fd)
|
|
399
|
+
skill = root.joinpath(*parts) / "SKILL.md"
|
|
400
|
+
return not is_link_like(skill, status) and stat.S_ISREG(status.st_mode)
|
|
358
401
|
|
|
359
402
|
|
|
360
403
|
def is_fixed_managed_pipeline_artifact(relative: str) -> bool:
|
|
@@ -423,13 +466,20 @@ def read_regular_evidence(
|
|
|
423
466
|
) from error
|
|
424
467
|
if not relative.parts:
|
|
425
468
|
raise DetectError(f"{evidence_name} evidence path is empty: {path}")
|
|
426
|
-
if
|
|
469
|
+
if _POSIX_ANCHORED_EVIDENCE_SUPPORTED:
|
|
427
470
|
return read_anchored_evidence(
|
|
428
471
|
relative,
|
|
429
472
|
root,
|
|
430
473
|
missing_ok=missing_ok,
|
|
431
474
|
evidence_name=evidence_name,
|
|
432
475
|
)
|
|
476
|
+
if WINDOWS_ANCHORED_EVIDENCE_SUPPORTED:
|
|
477
|
+
return read_windows_anchored_evidence(
|
|
478
|
+
relative,
|
|
479
|
+
root,
|
|
480
|
+
missing_ok=missing_ok,
|
|
481
|
+
evidence_name=evidence_name,
|
|
482
|
+
)
|
|
433
483
|
return read_lstat_open_evidence(
|
|
434
484
|
relative,
|
|
435
485
|
root,
|
|
@@ -447,6 +497,17 @@ def directory_flags() -> int:
|
|
|
447
497
|
)
|
|
448
498
|
|
|
449
499
|
|
|
500
|
+
def listdir_anchored(dir_fd: int) -> list[str]:
|
|
501
|
+
"""List names through a fresh directory descriptor under dir_fd."""
|
|
502
|
+
fresh = os.open(".", directory_flags(), dir_fd=dir_fd)
|
|
503
|
+
try:
|
|
504
|
+
if not os.path.samestat(os.fstat(fresh), os.fstat(dir_fd)):
|
|
505
|
+
raise DetectError("anchored directory listing lost its identity")
|
|
506
|
+
return os.listdir(fresh)
|
|
507
|
+
finally:
|
|
508
|
+
os.close(fresh)
|
|
509
|
+
|
|
510
|
+
|
|
450
511
|
def file_flags() -> int:
|
|
451
512
|
return (
|
|
452
513
|
os.O_RDONLY
|
|
@@ -766,9 +827,12 @@ def raise_walk_error(error: OSError) -> None:
|
|
|
766
827
|
|
|
767
828
|
|
|
768
829
|
def iter_worktree_files(root: Path) -> Iterable[str]:
|
|
769
|
-
if
|
|
830
|
+
if _POSIX_ANCHORED_EVIDENCE_SUPPORTED and LISTDIR_DIR_FD_SUPPORTED:
|
|
770
831
|
yield from iter_worktree_files_anchored(root)
|
|
771
832
|
return
|
|
833
|
+
if WINDOWS_ANCHORED_EVIDENCE_SUPPORTED:
|
|
834
|
+
yield from iter_worktree_files_windows_anchored(root)
|
|
835
|
+
return
|
|
772
836
|
for dirpath, dirnames, filenames in os.walk(
|
|
773
837
|
root,
|
|
774
838
|
followlinks=False,
|
|
@@ -826,7 +890,7 @@ def iter_from_dir_fd(
|
|
|
826
890
|
dir_fd: int, relative_dir: str, root: Path
|
|
827
891
|
) -> Iterable[str]:
|
|
828
892
|
try:
|
|
829
|
-
names =
|
|
893
|
+
names = listdir_anchored(dir_fd)
|
|
830
894
|
except OSError as error:
|
|
831
895
|
raise DetectError(f"cannot traverse filesystem evidence: {error}") from error
|
|
832
896
|
for name in names:
|
|
@@ -862,7 +926,7 @@ def iter_from_dir_fd(
|
|
|
862
926
|
raise DetectError(
|
|
863
927
|
f"filesystem evidence changed while traversing: {relative}"
|
|
864
928
|
)
|
|
865
|
-
if is_verified_skill_bundle_at(relative, child):
|
|
929
|
+
if is_verified_skill_bundle_at(relative, child, root):
|
|
866
930
|
continue
|
|
867
931
|
yield from iter_from_dir_fd(child, relative, root)
|
|
868
932
|
finally:
|
|
@@ -1227,10 +1291,17 @@ def project_slug(root: Path) -> str:
|
|
|
1227
1291
|
return slug or "project"
|
|
1228
1292
|
|
|
1229
1293
|
|
|
1230
|
-
def filled_state_template(
|
|
1294
|
+
def filled_state_template(
|
|
1295
|
+
template: str, slug: str, phase: str, default_branch: str = "main"
|
|
1296
|
+
) -> str:
|
|
1231
1297
|
if "<slug>" not in template:
|
|
1232
1298
|
raise DetectError("state template missing slug placeholder")
|
|
1233
1299
|
text = template.replace("<slug>", slug)
|
|
1300
|
+
text, count = re.subn(
|
|
1301
|
+
r"(?m)^default_branch: main\b", lambda _: f"default_branch: {default_branch}", text, count=1
|
|
1302
|
+
)
|
|
1303
|
+
if count != 1:
|
|
1304
|
+
raise DetectError("state template missing default_branch: main line")
|
|
1234
1305
|
text, count = re.subn(r"(?m)^phase: define\b", f"phase: {phase}", text, count=1)
|
|
1235
1306
|
if count != 1:
|
|
1236
1307
|
raise DetectError("state template missing phase: define line")
|
|
@@ -1302,7 +1373,7 @@ def close_file_descriptors(
|
|
|
1302
1373
|
|
|
1303
1374
|
def project_entries(project_fd: int, project: Path) -> set:
|
|
1304
1375
|
"""Names in .project without ignored OS junk (Finder may add .DS_Store at any time)."""
|
|
1305
|
-
entries = set(
|
|
1376
|
+
entries = set(listdir_anchored(project_fd))
|
|
1306
1377
|
for name in entries & _common.OS_JUNK_NAMES:
|
|
1307
1378
|
try:
|
|
1308
1379
|
status = os.stat(name, dir_fd=project_fd, follow_symlinks=False)
|
|
@@ -1413,12 +1484,12 @@ def write_state_anchored(
|
|
|
1413
1484
|
follow_symlinks=False,
|
|
1414
1485
|
)
|
|
1415
1486
|
except FileNotFoundError as error:
|
|
1416
|
-
if "STATE.md" in
|
|
1487
|
+
if "STATE.md" in listdir_anchored(project_fd):
|
|
1417
1488
|
raise DetectError("STATE.md already exists") from error
|
|
1418
1489
|
raise DetectError("temporary STATE.md disappeared") from error
|
|
1419
1490
|
if not os.path.samestat(created_status, named_temporary):
|
|
1420
1491
|
raise DetectError("temporary STATE.md changed before writing")
|
|
1421
|
-
if "STATE.md" in
|
|
1492
|
+
if "STATE.md" in listdir_anchored(project_fd):
|
|
1422
1493
|
raise DetectError("STATE.md already exists")
|
|
1423
1494
|
os.ftruncate(state_fd, 0)
|
|
1424
1495
|
write_all(state_fd, payload)
|
|
@@ -1653,6 +1724,167 @@ class _WindowsHandles:
|
|
|
1653
1724
|
raise ctypes.WinError(ctypes.get_last_error())
|
|
1654
1725
|
|
|
1655
1726
|
|
|
1727
|
+
_WINDOWS_HANDLES: Optional[_WindowsHandles] = None
|
|
1728
|
+
|
|
1729
|
+
|
|
1730
|
+
def get_windows_handles() -> _WindowsHandles:
|
|
1731
|
+
global _WINDOWS_HANDLES
|
|
1732
|
+
if _WINDOWS_HANDLES is None:
|
|
1733
|
+
_WINDOWS_HANDLES = _WindowsHandles()
|
|
1734
|
+
return _WINDOWS_HANDLES
|
|
1735
|
+
|
|
1736
|
+
|
|
1737
|
+
def _windows_missing_ok(error: OSError) -> bool:
|
|
1738
|
+
return getattr(error, "winerror", None) in {2, 3}
|
|
1739
|
+
|
|
1740
|
+
|
|
1741
|
+
def read_windows_anchored_evidence(
|
|
1742
|
+
relative: Path,
|
|
1743
|
+
root: Path,
|
|
1744
|
+
*,
|
|
1745
|
+
missing_ok: bool,
|
|
1746
|
+
evidence_name: str,
|
|
1747
|
+
) -> Optional[str]:
|
|
1748
|
+
win = get_windows_handles()
|
|
1749
|
+
descriptors: list[int] = []
|
|
1750
|
+
try:
|
|
1751
|
+
descriptors.append(win.open_root(root))
|
|
1752
|
+
opened_root = os.fstat(descriptors[-1])
|
|
1753
|
+
if not stat.S_ISDIR(opened_root.st_mode):
|
|
1754
|
+
raise DetectError(f"repo evidence is not a directory: {root}")
|
|
1755
|
+
for index, part in enumerate(relative.parts):
|
|
1756
|
+
current = root.joinpath(*relative.parts[: index + 1])
|
|
1757
|
+
final = index == len(relative.parts) - 1
|
|
1758
|
+
access = _GENERIC_READ if final else _DIRECTORY_ACCESS
|
|
1759
|
+
options = _FILE_NON_DIRECTORY_FILE if final else _FILE_DIRECTORY_FILE
|
|
1760
|
+
try:
|
|
1761
|
+
descriptor = win.open_relative(
|
|
1762
|
+
descriptors[-1],
|
|
1763
|
+
part,
|
|
1764
|
+
access,
|
|
1765
|
+
_PIN_SHARE,
|
|
1766
|
+
_FILE_OPEN,
|
|
1767
|
+
options,
|
|
1768
|
+
)
|
|
1769
|
+
except OSError as error:
|
|
1770
|
+
if missing_ok and _windows_missing_ok(error):
|
|
1771
|
+
return None
|
|
1772
|
+
raise DetectError(
|
|
1773
|
+
f"filesystem evidence disappeared: {root / relative}"
|
|
1774
|
+
) from error
|
|
1775
|
+
descriptors.append(descriptor)
|
|
1776
|
+
actual = os.fstat(descriptor)
|
|
1777
|
+
if is_link_like(current, actual):
|
|
1778
|
+
raise DetectError(
|
|
1779
|
+
f"link-like {evidence_name} evidence is not allowed: {current}"
|
|
1780
|
+
)
|
|
1781
|
+
if final and not stat.S_ISREG(actual.st_mode):
|
|
1782
|
+
raise DetectError(
|
|
1783
|
+
f"{evidence_name} evidence is not a regular file: {current}"
|
|
1784
|
+
)
|
|
1785
|
+
if not final and not stat.S_ISDIR(actual.st_mode):
|
|
1786
|
+
raise DetectError(
|
|
1787
|
+
f"{evidence_name} evidence parent is not a directory: {current}"
|
|
1788
|
+
)
|
|
1789
|
+
with os.fdopen(descriptors.pop(), "rb") as stream:
|
|
1790
|
+
data = stream.read()
|
|
1791
|
+
except DetectError:
|
|
1792
|
+
raise
|
|
1793
|
+
except OSError as error:
|
|
1794
|
+
raise DetectError(
|
|
1795
|
+
f"cannot read {evidence_name} evidence: {root / relative}"
|
|
1796
|
+
) from error
|
|
1797
|
+
finally:
|
|
1798
|
+
for descriptor in reversed(descriptors):
|
|
1799
|
+
os.close(descriptor)
|
|
1800
|
+
try:
|
|
1801
|
+
return data.decode("utf-8")
|
|
1802
|
+
except UnicodeDecodeError as error:
|
|
1803
|
+
raise DetectError(
|
|
1804
|
+
f"cannot read {evidence_name} evidence: {root / relative}"
|
|
1805
|
+
) from error
|
|
1806
|
+
|
|
1807
|
+
|
|
1808
|
+
def iter_worktree_files_windows_anchored(root: Path) -> Iterable[str]:
|
|
1809
|
+
win = get_windows_handles()
|
|
1810
|
+
try:
|
|
1811
|
+
root_fd = win.open_root(root)
|
|
1812
|
+
except OSError as error:
|
|
1813
|
+
raise DetectError(f"cannot traverse filesystem evidence: {error}") from error
|
|
1814
|
+
try:
|
|
1815
|
+
root_status = os.fstat(root_fd)
|
|
1816
|
+
if not stat.S_ISDIR(root_status.st_mode):
|
|
1817
|
+
raise DetectError(f"repo evidence is not a directory: {root}")
|
|
1818
|
+
yield from iter_from_windows_dir_fd(root_fd, "", root, win)
|
|
1819
|
+
finally:
|
|
1820
|
+
os.close(root_fd)
|
|
1821
|
+
|
|
1822
|
+
|
|
1823
|
+
def iter_from_windows_dir_fd(
|
|
1824
|
+
dir_fd: int, relative_dir: str, root: Path, win: _WindowsHandles
|
|
1825
|
+
) -> Iterable[str]:
|
|
1826
|
+
scan_dir = root if not relative_dir else root.joinpath(*PurePosixPath(relative_dir).parts)
|
|
1827
|
+
try:
|
|
1828
|
+
# Windows CPython cannot listdir(dir_fd); paths come from the pinned walk.
|
|
1829
|
+
names = os.listdir(scan_dir)
|
|
1830
|
+
except OSError as error:
|
|
1831
|
+
raise DetectError(f"cannot traverse filesystem evidence: {error}") from error
|
|
1832
|
+
for name in names:
|
|
1833
|
+
relative = f"{relative_dir}/{name}" if relative_dir else name
|
|
1834
|
+
if is_ignored(relative) or name == ".project":
|
|
1835
|
+
continue
|
|
1836
|
+
path = root.joinpath(*PurePosixPath(relative).parts)
|
|
1837
|
+
try:
|
|
1838
|
+
child_fd = win.open_relative(
|
|
1839
|
+
dir_fd,
|
|
1840
|
+
name,
|
|
1841
|
+
_DIRECTORY_ACCESS,
|
|
1842
|
+
_PIN_SHARE,
|
|
1843
|
+
_FILE_OPEN,
|
|
1844
|
+
_FILE_DIRECTORY_FILE,
|
|
1845
|
+
)
|
|
1846
|
+
except OSError:
|
|
1847
|
+
child_fd = None
|
|
1848
|
+
else:
|
|
1849
|
+
status = os.fstat(child_fd)
|
|
1850
|
+
if is_link_like(path, status):
|
|
1851
|
+
os.close(child_fd)
|
|
1852
|
+
continue
|
|
1853
|
+
if stat.S_ISDIR(status.st_mode):
|
|
1854
|
+
try:
|
|
1855
|
+
if is_verified_skill_bundle_at(relative, child_fd, root):
|
|
1856
|
+
continue
|
|
1857
|
+
yield from iter_from_windows_dir_fd(
|
|
1858
|
+
child_fd, relative, root, win
|
|
1859
|
+
)
|
|
1860
|
+
finally:
|
|
1861
|
+
os.close(child_fd)
|
|
1862
|
+
continue
|
|
1863
|
+
os.close(child_fd)
|
|
1864
|
+
try:
|
|
1865
|
+
file_fd = win.open_relative(
|
|
1866
|
+
dir_fd,
|
|
1867
|
+
name,
|
|
1868
|
+
_FILE_READ_ATTRIBUTES,
|
|
1869
|
+
_PIN_SHARE,
|
|
1870
|
+
_FILE_OPEN,
|
|
1871
|
+
_FILE_NON_DIRECTORY_FILE,
|
|
1872
|
+
)
|
|
1873
|
+
except OSError as error:
|
|
1874
|
+
raise DetectError(
|
|
1875
|
+
f"cannot inspect filesystem evidence: {relative}: {error}"
|
|
1876
|
+
) from error
|
|
1877
|
+
try:
|
|
1878
|
+
status = os.fstat(file_fd)
|
|
1879
|
+
if is_link_like(path, status) or not stat.S_ISREG(status.st_mode):
|
|
1880
|
+
continue
|
|
1881
|
+
if is_fixed_managed_pipeline_artifact(relative):
|
|
1882
|
+
continue
|
|
1883
|
+
yield relative
|
|
1884
|
+
finally:
|
|
1885
|
+
os.close(file_fd)
|
|
1886
|
+
|
|
1887
|
+
|
|
1656
1888
|
def windows_project_entries(project: Path) -> set:
|
|
1657
1889
|
"""project_entries for a .project held open without delete sharing."""
|
|
1658
1890
|
entries = set(os.listdir(project))
|
|
@@ -1805,6 +2037,14 @@ def initialize(
|
|
|
1805
2037
|
)
|
|
1806
2038
|
if git.returncode != 0 or git.stdout.strip() != "true":
|
|
1807
2039
|
return {**payload, "route": "setup-repository", "wrote_state": False}
|
|
2040
|
+
default_branch = _common.origin_default_branch(root)
|
|
2041
|
+
if not _common.valid_default_branch(default_branch):
|
|
2042
|
+
return {**payload, "wrote_state": False, "error": (
|
|
2043
|
+
f"origin default branch {default_branch!r} cannot be recorded in STATE.md: "
|
|
2044
|
+
"it is a GSD Path reserved name or it has a character that STATE frontmatter "
|
|
2045
|
+
"cannot hold. Rename the default branch, then run "
|
|
2046
|
+
"`git remote set-head origin --auto`."
|
|
2047
|
+
)}
|
|
1808
2048
|
expected = "inspect" if payload["verdict"] == "brownfield" else "define"
|
|
1809
2049
|
if phase is None:
|
|
1810
2050
|
phase = expected
|
|
@@ -1818,7 +2058,7 @@ def initialize(
|
|
|
1818
2058
|
return payload
|
|
1819
2059
|
write_state_anchored(
|
|
1820
2060
|
root,
|
|
1821
|
-
filled_state_template(raw, project_slug(root), phase),
|
|
2061
|
+
filled_state_template(raw, project_slug(root), phase, default_branch),
|
|
1822
2062
|
root_status,
|
|
1823
2063
|
project_status,
|
|
1824
2064
|
)
|
|
@@ -7,6 +7,7 @@ import json
|
|
|
7
7
|
import os
|
|
8
8
|
import shutil
|
|
9
9
|
import sys
|
|
10
|
+
import traceback
|
|
10
11
|
|
|
11
12
|
# Runtime helpers must not modify their immutable installation.
|
|
12
13
|
sys.dont_write_bytecode = True
|
|
@@ -33,7 +34,7 @@ def _load_pipeline_modules():
|
|
|
33
34
|
try:
|
|
34
35
|
from scripts import archive_milestone, pipeline_state, _common
|
|
35
36
|
return _common, archive_milestone, pipeline_state
|
|
36
|
-
except
|
|
37
|
+
except ImportError as error: # a foreign `scripts` package
|
|
37
38
|
if error.name not in {
|
|
38
39
|
"scripts",
|
|
39
40
|
"scripts.archive_milestone",
|
|
@@ -41,6 +42,13 @@ def _load_pipeline_modules():
|
|
|
41
42
|
"scripts._common",
|
|
42
43
|
}:
|
|
43
44
|
raise
|
|
45
|
+
# A plain ImportError raised while a `scripts` module loaded is not a
|
|
46
|
+
# foreign package. A missing module falls back, as before.
|
|
47
|
+
if not isinstance(error, ModuleNotFoundError) and any(
|
|
48
|
+
frame.f_globals.get("__name__", "").startswith("scripts.")
|
|
49
|
+
for frame, _ in traceback.walk_tb(error.__traceback__)
|
|
50
|
+
):
|
|
51
|
+
raise
|
|
44
52
|
shared_scripts = Path(__file__).resolve().parents[2] / "gsd-path" / "scripts"
|
|
45
53
|
sys.path.insert(0, str(shared_scripts))
|
|
46
54
|
import archive_milestone
|