@opengsd/gsd-core 1.17.0 → 1.19.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +2 -1
- package/.opencode/plugins/gsd-core.js +2 -3
- package/agents/gsd-advisor-researcher.compact.md +1 -1
- package/agents/gsd-advisor-researcher.md +1 -1
- package/agents/gsd-assumptions-analyzer.compact.md +1 -1
- package/agents/gsd-assumptions-analyzer.md +1 -1
- package/agents/gsd-code-fixer.compact.md +3 -3
- package/agents/gsd-code-fixer.md +5 -4
- package/agents/gsd-code-reviewer.compact.md +1 -1
- package/agents/gsd-code-reviewer.md +1 -1
- package/agents/gsd-codebase-mapper.compact.md +1 -1
- package/agents/gsd-codebase-mapper.md +1 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-doc-verifier.compact.md +4 -4
- package/agents/gsd-doc-verifier.md +4 -3
- package/agents/gsd-doc-writer.compact.md +23 -5
- package/agents/gsd-doc-writer.md +19 -6
- package/agents/gsd-eval-auditor.compact.md +1 -1
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +7 -3
- package/agents/gsd-integration-checker.compact.md +1 -1
- package/agents/gsd-integration-checker.md +1 -1
- package/agents/gsd-nyquist-auditor.compact.md +1 -1
- package/agents/gsd-nyquist-auditor.md +1 -1
- package/agents/gsd-phase-researcher.md +1 -1
- package/agents/gsd-plan-checker.md +2 -1
- package/agents/gsd-planner.md +5 -4
- package/agents/gsd-project-researcher.compact.md +1 -1
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.compact.md +5 -5
- package/agents/gsd-research-synthesizer.md +5 -5
- package/agents/gsd-roadmapper.compact.md +1 -1
- package/agents/gsd-roadmapper.md +1 -1
- package/agents/gsd-security-auditor.compact.md +1 -1
- package/agents/gsd-security-auditor.md +1 -1
- package/agents/gsd-ui-auditor.compact.md +1 -1
- package/agents/gsd-ui-auditor.md +1 -1
- package/agents/gsd-ui-checker.compact.md +1 -1
- package/agents/gsd-ui-checker.md +1 -1
- package/agents/gsd-ui-researcher.compact.md +13 -1
- package/agents/gsd-ui-researcher.md +28 -1
- package/agents/gsd-verifier.md +2 -2
- package/bin/install.js +460 -105
- package/commands/gsd/code-review.md +8 -0
- package/commands/gsd/pause-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +124 -18
- package/gsd-core/bin/lib/agent-install-check.cjs +29 -3
- package/gsd-core/bin/lib/args-terminator.cjs +114 -0
- package/gsd-core/bin/lib/broken-windows.cjs +59 -1
- package/gsd-core/bin/lib/capability-ledger.cjs +25 -0
- package/gsd-core/bin/lib/capability-lock.cjs +41 -8
- package/gsd-core/bin/lib/capability-registry.cjs +162 -74
- package/gsd-core/bin/lib/capability-source.cjs +3 -1
- package/gsd-core/bin/lib/capability-state.cjs +20 -11
- package/gsd-core/bin/lib/capability-validator.cjs +23 -4
- package/gsd-core/bin/lib/commands.cjs +5 -1
- package/gsd-core/bin/lib/config-loader.cjs +13 -3
- package/gsd-core/bin/lib/config.cjs +256 -58
- package/gsd-core/bin/lib/core-utils.cjs +34 -0
- package/gsd-core/bin/lib/decision-coverage-support.cjs +93 -0
- package/gsd-core/bin/lib/gate-context-drift.cjs +8 -3
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +21 -1
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +19 -1
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +134 -13
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +23 -3
- package/gsd-core/bin/lib/gate-predicate.cjs +8 -12
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +114 -18
- package/gsd-core/bin/lib/gate-ui-safety.cjs +23 -5
- package/gsd-core/bin/lib/git-info-exclude.cjs +57 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +18 -3
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +4 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +52 -1
- package/gsd-core/bin/lib/host-integration.cjs +13 -6
- package/gsd-core/bin/lib/init.cjs +76 -5
- package/gsd-core/bin/lib/install-effort-resolver.cjs +2 -2
- package/gsd-core/bin/lib/install-engine.cjs +246 -32
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +4 -3
- package/gsd-core/bin/lib/install-profiles.cjs +14 -7
- package/gsd-core/bin/lib/installer-migration-report.cjs +2 -0
- package/gsd-core/bin/lib/markdown-line-diff.cjs +147 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +113 -0
- package/gsd-core/bin/lib/milestone-lock.cjs +8 -1
- package/gsd-core/bin/lib/milestone-release-map.cjs +244 -0
- package/gsd-core/bin/lib/milestone-release-tags.cjs +440 -0
- package/gsd-core/bin/lib/milestone.cjs +43 -1
- package/gsd-core/bin/lib/model-catalog.cjs +8 -0
- package/gsd-core/bin/lib/normalize-test-command.cjs +67 -0
- package/gsd-core/bin/lib/phase-id.cjs +21 -4
- package/gsd-core/bin/lib/phase-lifecycle.cjs +37 -4
- package/gsd-core/bin/lib/phase.cjs +235 -37
- package/gsd-core/bin/lib/planning-snapshot.cjs +3 -1
- package/gsd-core/bin/lib/planning-workspace.cjs +18 -0
- package/gsd-core/bin/lib/pristine-baseline.cjs +11 -3
- package/gsd-core/bin/lib/read-only-git-env.cjs +58 -0
- package/gsd-core/bin/lib/report-parser.cjs +57 -1
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +35 -2
- package/gsd-core/bin/lib/review-lane-invocation.cjs +40 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +33 -4
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +20 -1
- package/gsd-core/bin/lib/roadmap-parser.cjs +12 -0
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +39 -2
- package/gsd-core/bin/lib/roadmap.cjs +89 -30
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +428 -16
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +8 -4
- package/gsd-core/bin/lib/runtime-homes.cjs +18 -0
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +60 -16
- package/gsd-core/bin/lib/shell-command-projection.cjs +123 -16
- package/gsd-core/bin/lib/smart-entry.cjs +37 -16
- package/gsd-core/bin/lib/state-contract.cjs +29 -9
- package/gsd-core/bin/lib/state-document.cjs +47 -5
- package/gsd-core/bin/lib/state-transition.cjs +150 -34
- package/gsd-core/bin/lib/state.cjs +140 -88
- package/gsd-core/bin/lib/surface.cjs +9 -0
- package/gsd-core/bin/lib/task-command-router.cjs +7 -28
- package/gsd-core/bin/lib/task-content-resolution.cjs +46 -1
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +5 -0
- package/gsd-core/bin/lib/tdd-test-files.cjs +42 -0
- package/gsd-core/bin/lib/verification.cjs +96 -9
- package/gsd-core/bin/lib/verify.cjs +38 -1
- package/gsd-core/bin/lib/worktree-safety.cjs +22 -1
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
- package/gsd-core/references/agent-contracts.md +1 -1
- package/gsd-core/references/agent-skills-bootstrap.md +26 -7
- package/gsd-core/references/git-integration.md +14 -3
- package/gsd-core/references/loop-hook-dispatch.md +13 -6
- package/gsd-core/references/planner-reversibility.md +18 -4
- package/gsd-core/references/planner-verify-command-grounding.md +18 -0
- package/gsd-core/references/planning-config.md +2 -0
- package/gsd-core/references/tdd.md +5 -4
- package/gsd-core/references/verifier-phase-gates.md +8 -1
- package/gsd-core/templates/DEBUG.md +16 -0
- package/gsd-core/templates/config.json +2 -1
- package/gsd-core/templates/verification-report.md +1 -1
- package/gsd-core/workflows/add-backlog.md +10 -2
- package/gsd-core/workflows/add-phase.md +5 -1
- package/gsd-core/workflows/add-tests.md +5 -1
- package/gsd-core/workflows/add-todo.md +5 -1
- package/gsd-core/workflows/ai-integration-phase.md +5 -1
- package/gsd-core/workflows/audit-fix.md +2 -1
- package/gsd-core/workflows/audit-milestone.md +21 -9
- package/gsd-core/workflows/autonomous/templates/minimal-context.md +41 -0
- package/gsd-core/workflows/autonomous.md +52 -64
- package/gsd-core/workflows/check-todos.md +5 -1
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +10 -1
- package/gsd-core/workflows/code-review-fix.md +5 -1
- package/gsd-core/workflows/code-review.md +66 -8
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +5 -1
- package/gsd-core/workflows/complete-milestone/steps/project-md-evolution-review.md +145 -0
- package/gsd-core/workflows/complete-milestone/steps/release-map.md +80 -0
- package/gsd-core/workflows/complete-milestone.md +64 -157
- package/gsd-core/workflows/debug.md +5 -1
- package/gsd-core/workflows/diagnose-issues.md +34 -6
- package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -1
- package/gsd-core/workflows/discuss-phase/modes/power.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +44 -5
- package/gsd-core/workflows/discuss-phase-power.md +19 -2
- package/gsd-core/workflows/discuss-phase.md +11 -11
- package/gsd-core/workflows/docs-update/detail/elaboration.md +7 -6
- package/gsd-core/workflows/docs-update.md +27 -5
- package/gsd-core/workflows/edit-phase.md +5 -1
- package/gsd-core/workflows/eval-review.md +11 -3
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +5 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +13 -7
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +19 -8
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +21 -3
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +18 -1
- package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +7 -3
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +11 -2
- package/gsd-core/workflows/execute-phase.md +46 -11
- package/gsd-core/workflows/execute-plan.md +8 -4
- package/gsd-core/workflows/extract-learnings.md +6 -2
- package/gsd-core/workflows/forensics.md +5 -1
- package/gsd-core/workflows/health.md +2 -1
- package/gsd-core/workflows/import.md +6 -2
- package/gsd-core/workflows/insert-phase.md +5 -1
- package/gsd-core/workflows/manager.md +10 -2
- package/gsd-core/workflows/map-codebase.md +5 -1
- package/gsd-core/workflows/milestone-summary.md +10 -2
- package/gsd-core/workflows/new-milestone.md +13 -5
- package/gsd-core/workflows/new-project.md +9 -5
- package/gsd-core/workflows/next.md +8 -4
- package/gsd-core/workflows/pause-work.md +3 -3
- package/gsd-core/workflows/plan-phase/steps/auto-advance-check.md +70 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +7 -3
- package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +6 -2
- package/gsd-core/workflows/plan-phase.md +54 -86
- package/gsd-core/workflows/plan-review-convergence.md +17 -5
- package/gsd-core/workflows/plant-seed.md +8 -4
- package/gsd-core/workflows/progress.md +6 -2
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +1 -1
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +8 -1
- package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +2 -1
- package/gsd-core/workflows/quick-batch.md +5 -1
- package/gsd-core/workflows/quick.md +23 -8
- package/gsd-core/workflows/remove-phase.md +5 -1
- package/gsd-core/workflows/resume-project.md +5 -1
- package/gsd-core/workflows/review.md +22 -15
- package/gsd-core/workflows/scan.md +5 -1
- package/gsd-core/workflows/section-manifest.json +5 -0
- package/gsd-core/workflows/secure-phase.md +6 -2
- package/gsd-core/workflows/settings.md +4 -3
- package/gsd-core/workflows/ship.md +16 -14
- package/gsd-core/workflows/spec-phase.md +3 -6
- package/gsd-core/workflows/thread.md +10 -2
- package/gsd-core/workflows/transition.md +5 -1
- package/gsd-core/workflows/ui-phase.md +5 -1
- package/gsd-core/workflows/ui-review.md +6 -2
- package/gsd-core/workflows/ultraplan-phase.md +5 -1
- package/gsd-core/workflows/update.md +5 -1
- package/gsd-core/workflows/validate-phase.md +6 -2
- package/gsd-core/workflows/verify-work/detail/elaboration.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -1
- package/gsd-core/workflows/verify-work.md +15 -6
- package/hooks/dist/gsd-agent-isolation-guard.js +14 -2
- package/hooks/dist/gsd-cursor-subagent-start.js +8 -3
- package/hooks/dist/gsd-path-export.js +95 -0
- package/hooks/dist/gsd-secret-read-guard.js +244 -53
- package/hooks/dist/gsd-statusline.js +35 -2
- package/hooks/dist/gsd-validate-commit.sh +27 -5
- package/hooks/dist/gsd-windsurf-pre-write.js +28 -1
- package/hooks/dist/gsd-workflow-guard.js +1 -1
- package/hooks/dist/gsd-worktree-path-guard.js +28 -1
- package/hooks/dist/lib/isolation-sentinel.js +44 -0
- package/hooks/dist/managed-hooks-registry.cjs +1 -0
- package/hooks/gsd-agent-isolation-guard.js +14 -2
- package/hooks/gsd-cursor-subagent-start.js +8 -3
- package/hooks/gsd-path-export.js +95 -0
- package/hooks/gsd-secret-read-guard.js +244 -53
- package/hooks/gsd-statusline.js +35 -2
- package/hooks/gsd-validate-commit.sh +27 -5
- package/hooks/gsd-windsurf-pre-write.js +28 -1
- package/hooks/gsd-workflow-guard.js +1 -1
- package/hooks/gsd-worktree-path-guard.js +28 -1
- package/hooks/hooks.json +1 -0
- package/hooks/lib/isolation-sentinel.js +44 -0
- package/hooks/managed-hooks-registry.cjs +1 -0
- package/package.json +13 -6
- package/pi/gsd.cjs +1047 -10
- package/pi/package-agents/gsd-advisor-researcher.md +113 -0
- package/pi/package-agents/gsd-ai-researcher.md +111 -0
- package/pi/package-agents/gsd-assumptions-analyzer.md +110 -0
- package/pi/package-agents/gsd-code-fixer.md +769 -0
- package/pi/package-agents/gsd-code-reviewer.md +402 -0
- package/pi/package-agents/gsd-codebase-mapper.md +850 -0
- package/pi/package-agents/gsd-debug-session-manager.md +416 -0
- package/pi/package-agents/gsd-debugger.md +1274 -0
- package/pi/package-agents/gsd-doc-classifier.md +269 -0
- package/pi/package-agents/gsd-doc-synthesizer.md +259 -0
- package/pi/package-agents/gsd-doc-verifier.md +212 -0
- package/pi/package-agents/gsd-doc-writer.md +626 -0
- package/pi/package-agents/gsd-dom-verifier.md +164 -0
- package/pi/package-agents/gsd-domain-researcher.md +144 -0
- package/pi/package-agents/gsd-eval-auditor.md +185 -0
- package/pi/package-agents/gsd-eval-planner.md +149 -0
- package/pi/package-agents/gsd-executor.md +894 -0
- package/pi/package-agents/gsd-framework-selector.md +159 -0
- package/pi/package-agents/gsd-integration-checker.md +476 -0
- package/pi/package-agents/gsd-intel-updater.md +338 -0
- package/pi/package-agents/gsd-mempalace-curator.md +49 -0
- package/pi/package-agents/gsd-nyquist-auditor.md +200 -0
- package/pi/package-agents/gsd-pattern-mapper.md +340 -0
- package/pi/package-agents/gsd-phase-researcher.md +897 -0
- package/pi/package-agents/gsd-plan-checker.md +1077 -0
- package/pi/package-agents/gsd-planner.md +1003 -0
- package/pi/package-agents/gsd-project-researcher.md +611 -0
- package/pi/package-agents/gsd-research-synthesizer.md +259 -0
- package/pi/package-agents/gsd-roadmapper.md +779 -0
- package/pi/package-agents/gsd-security-auditor.md +171 -0
- package/pi/package-agents/gsd-ui-auditor.md +581 -0
- package/pi/package-agents/gsd-ui-checker.md +417 -0
- package/pi/package-agents/gsd-ui-researcher.md +469 -0
- package/pi/package-agents/gsd-user-profiler.md +174 -0
- package/pi/package-agents/gsd-verifier.md +963 -0
- package/pi/package-agents/manifest.json +39 -0
- package/pi/package-skills/gsd-add-tests/SKILL.md +39 -0
- package/pi/package-skills/gsd-ai-integration-phase/SKILL.md +36 -0
- package/pi/package-skills/gsd-audit-fix/SKILL.md +34 -0
- package/pi/package-skills/gsd-audit-milestone/SKILL.md +40 -0
- package/pi/package-skills/gsd-audit-uat/SKILL.md +26 -0
- package/pi/package-skills/gsd-autonomous/SKILL.md +52 -0
- package/pi/package-skills/gsd-capture/SKILL.md +68 -0
- package/pi/package-skills/gsd-cleanup/SKILL.md +25 -0
- package/pi/package-skills/gsd-code-review/SKILL.md +71 -0
- package/pi/package-skills/gsd-complete-milestone/SKILL.md +147 -0
- package/pi/package-skills/gsd-config/SKILL.md +60 -0
- package/pi/package-skills/gsd-debug/SKILL.md +64 -0
- package/pi/package-skills/gsd-discuss-phase/SKILL.md +74 -0
- package/pi/package-skills/gsd-docs-update/SKILL.md +50 -0
- package/pi/package-skills/gsd-eval-review/SKILL.md +35 -0
- package/pi/package-skills/gsd-execute-phase/SKILL.md +62 -0
- package/pi/package-skills/gsd-explore/SKILL.md +26 -0
- package/pi/package-skills/gsd-extract-learnings/SKILL.md +25 -0
- package/pi/package-skills/gsd-fast/SKILL.md +33 -0
- package/pi/package-skills/gsd-forensics/SKILL.md +59 -0
- package/pi/package-skills/gsd-graphify/SKILL.md +210 -0
- package/pi/package-skills/gsd-health/SKILL.md +36 -0
- package/pi/package-skills/gsd-help/SKILL.md +37 -0
- package/pi/package-skills/gsd-import/SKILL.md +46 -0
- package/pi/package-skills/gsd-inbox/SKILL.md +42 -0
- package/pi/package-skills/gsd-ingest-docs/SKILL.md +43 -0
- package/pi/package-skills/gsd-manager/SKILL.md +46 -0
- package/pi/package-skills/gsd-map-codebase/SKILL.md +85 -0
- package/pi/package-skills/gsd-mempalace-capture/SKILL.md +111 -0
- package/pi/package-skills/gsd-mempalace-recall/SKILL.md +111 -0
- package/pi/package-skills/gsd-milestone-summary/SKILL.md +54 -0
- package/pi/package-skills/gsd-mvp-phase/SKILL.md +45 -0
- package/pi/package-skills/gsd-new-milestone/SKILL.md +49 -0
- package/pi/package-skills/gsd-new-project/SKILL.md +49 -0
- package/pi/package-skills/gsd-next/SKILL.md +34 -0
- package/pi/package-skills/gsd-ns-context/SKILL.md +31 -0
- package/pi/package-skills/gsd-ns-ideate/SKILL.md +30 -0
- package/pi/package-skills/gsd-ns-manage/SKILL.md +42 -0
- package/pi/package-skills/gsd-ns-project/SKILL.md +34 -0
- package/pi/package-skills/gsd-ns-review/SKILL.md +35 -0
- package/pi/package-skills/gsd-ns-workflow/SKILL.md +44 -0
- package/pi/package-skills/gsd-onboard/SKILL.md +46 -0
- package/pi/package-skills/gsd-pause-work/SKILL.md +48 -0
- package/pi/package-skills/gsd-phase/SKILL.md +61 -0
- package/pi/package-skills/gsd-plan-phase/SKILL.md +62 -0
- package/pi/package-skills/gsd-plan-review-convergence/SKILL.md +63 -0
- package/pi/package-skills/gsd-pr-branch/SKILL.md +31 -0
- package/pi/package-skills/gsd-profile-user/SKILL.md +48 -0
- package/pi/package-skills/gsd-progress/SKILL.md +51 -0
- package/pi/package-skills/gsd-quick/SKILL.md +179 -0
- package/pi/package-skills/gsd-quick-batch/SKILL.md +114 -0
- package/pi/package-skills/gsd-resume-work/SKILL.md +31 -0
- package/pi/package-skills/gsd-review/SKILL.md +50 -0
- package/pi/package-skills/gsd-review-backlog/SKILL.md +65 -0
- package/pi/package-skills/gsd-secure-phase/SKILL.md +37 -0
- package/pi/package-skills/gsd-settings/SKILL.md +30 -0
- package/pi/package-skills/gsd-ship/SKILL.md +27 -0
- package/pi/package-skills/gsd-sketch/SKILL.md +56 -0
- package/pi/package-skills/gsd-spec-phase/SKILL.md +63 -0
- package/pi/package-skills/gsd-spike/SKILL.md +53 -0
- package/pi/package-skills/gsd-stats/SKILL.md +22 -0
- package/pi/package-skills/gsd-surface/SKILL.md +177 -0
- package/pi/package-skills/gsd-thread/SKILL.md +29 -0
- package/pi/package-skills/gsd-ui-phase/SKILL.md +35 -0
- package/pi/package-skills/gsd-ui-review/SKILL.md +35 -0
- package/pi/package-skills/gsd-ultraplan-phase/SKILL.md +38 -0
- package/pi/package-skills/gsd-undo/SKILL.md +38 -0
- package/pi/package-skills/gsd-update/SKILL.md +51 -0
- package/pi/package-skills/gsd-validate-phase/SKILL.md +37 -0
- package/pi/package-skills/gsd-verify-work/SKILL.md +41 -0
- package/pi/package-skills/gsd-workspace/SKILL.md +57 -0
- package/pi/package-skills/gsd-workstreams/SKILL.md +73 -0
- package/scripts/audit-workflow-script-paths.cjs +1 -1
- package/scripts/build-hooks.js +4 -0
- package/scripts/command-contract-helpers.cjs +1 -1
- package/scripts/diagnose-windows-spawn-watcher.cjs +317 -0
- package/scripts/docs-guard-registry.cjs +22 -7
- package/scripts/gen-health-docs.cjs +13 -1
- package/scripts/gen-pi-package-skills.cjs +217 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +19 -0
- package/scripts/lib/platform-conformance-tier.generated.cjs +41 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +3 -3
- package/scripts/lint-phase-arg-assignment.cjs +2 -2
- package/scripts/lint-retired-runtime-name.cjs +5 -0
- package/scripts/lint-workflow-shellcheck-baseline.json +16 -16
- package/scripts/npm-audit-baseline.cjs +41 -7
- package/scripts/release-tarball-smoke.cjs +1 -0
- package/scripts/reviewed-or-maintainer-policy.cjs +181 -0
- package/scripts/select-docs-guards.cjs +1 -1
- package/scripts/self-test-report-policy.cjs +350 -0
- package/skills/gsd-code-review/SKILL.md +8 -0
- package/skills/gsd-pause-work/SKILL.md +1 -1
- package/vscode/package.json +1 -1
|
@@ -21,6 +21,8 @@ const gate_phase_context_cjs_1 = require("./gate-phase-context.cjs");
|
|
|
21
21
|
const gate_evaluation_scope_cjs_1 = require("./gate-evaluation-scope.cjs");
|
|
22
22
|
const runtime_slash_cjs_1 = require("./runtime-slash.cjs");
|
|
23
23
|
const ui_safety_gate_cjs_1 = require("./ui-safety-gate.cjs");
|
|
24
|
+
const ui_frontend_evidence_cjs_1 = require("./ui-frontend-evidence.cjs");
|
|
25
|
+
const gate_evidence_cjs_1 = require("./gate-evidence.cjs");
|
|
24
26
|
const UI_FILE_EXTENSIONS_RE = /\.(tsx|jsx|css|scss|sass|less|vue|svelte|html)$/i;
|
|
25
27
|
const UI_PATH_PATTERNS_RE = /\/(components|pages|views|screens|layouts|ui|frontend)\//i;
|
|
26
28
|
/**
|
|
@@ -32,7 +34,10 @@ const UI_PATH_PATTERNS_RE = /\/(components|pages|views|screens|layouts|ui|fronte
|
|
|
32
34
|
* git call is bounded by the resolver's seam; an unreadable scope is reported, not "clean").
|
|
33
35
|
* (d) Phase directory → `*-UI-SPEC.md`.
|
|
34
36
|
*
|
|
35
|
-
*
|
|
37
|
+
* (c') Static frontend evidence (`readStaticFrontendEvidence`, the definition `computeUiPlanGate` uses),
|
|
38
|
+
* probed only for a frontend phase that changed UI files (#5646).
|
|
39
|
+
*
|
|
40
|
+
* `block = frontend && hasUiFiles && hasFrontendEvidence && !hasUiSpec`.
|
|
36
41
|
*/
|
|
37
42
|
function computeUiSafetyGate(projectDir, phase) {
|
|
38
43
|
// (a) phase section text (same two-pass lookup as computeUiPlanGate)
|
|
@@ -43,14 +48,27 @@ function computeUiSafetyGate(projectDir, phase) {
|
|
|
43
48
|
// (c) any UI files in the phase's own commits? (deleted paths count: a removed component is a UI change)
|
|
44
49
|
const scope = (0, gate_evaluation_scope_cjs_1.resolveEvaluationScope)(projectDir, { kind: 'phase', phase });
|
|
45
50
|
const hasUiFiles = scope.changedFiles.some((f) => f.trim() && (UI_FILE_EXTENSIONS_RE.test(f) || UI_PATH_PATTERNS_RE.test(f)));
|
|
51
|
+
// (c') #5646 — static structural corroboration, the same evidence `computeUiPlanGate` requires (#3312):
|
|
52
|
+
// `hasUiFiles` is a weak signal (an `.html` fixture, or any file under a `ui/` directory in any
|
|
53
|
+
// language), so on its own it halted projects with no frontend that the plan gate had cleared. Only
|
|
54
|
+
// probed when it could change the answer. `unreadable` (#5170) is a manifest or tree the probe could
|
|
55
|
+
// not look at: absence of evidence is then not established, and the verdict says so (below).
|
|
56
|
+
const frontendEvidence = frontend && hasUiFiles ? (0, ui_frontend_evidence_cjs_1.readStaticFrontendEvidence)(projectDir) : (0, gate_evidence_cjs_1.evidenceNone)();
|
|
57
|
+
const hasFrontendEvidence = frontendEvidence.kind === 'found';
|
|
46
58
|
// (d) phase directory and *-UI-SPEC.md
|
|
47
59
|
// `none` is "no spec"; `unreadable` is "could not look" (#5170) and is carried to the verdict.
|
|
48
60
|
const uiSpec = (0, gate_phase_context_cjs_1.locateUiSpec)(projectDir, phase);
|
|
49
61
|
const hasUiSpec = uiSpec.kind === 'found';
|
|
50
|
-
|
|
51
|
-
//
|
|
52
|
-
const
|
|
53
|
-
|
|
62
|
+
// Unreadable frontend evidence only matters when it could flip the verdict: with a UI-SPEC present the
|
|
63
|
+
// gate does not block whatever the tree holds.
|
|
64
|
+
const frontendReadError = frontendEvidence.kind === 'unreadable' && !hasUiSpec
|
|
65
|
+
? `static frontend evidence could not be read (${frontendEvidence.reason})`
|
|
66
|
+
: undefined;
|
|
67
|
+
const readError = roadmapReadError ?? (uiSpec.kind === 'unreadable' ? uiSpec.reason : undefined) ?? frontendReadError;
|
|
68
|
+
// block only when: this is a frontend phase AND UI files were changed AND the project has static
|
|
69
|
+
// frontend evidence AND no UI-SPEC exists
|
|
70
|
+
const block = frontend && hasUiFiles && hasFrontendEvidence && !hasUiSpec;
|
|
71
|
+
const result = { frontend, hasUiFiles, hasFrontendEvidence, hasUiSpec, block };
|
|
54
72
|
if (block) {
|
|
55
73
|
result.message = `UI files changed in this wave but no UI-SPEC.md exists for Phase ${phase}. ` +
|
|
56
74
|
`Run ${(0, runtime_slash_cjs_1.runtimeCommand)(projectDir, `ui-phase ${phase}`)} to generate the design contract before continuing.`;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Keep a machine-local file out of `git status` without touching any tracked
|
|
4
|
+
* file: append an anchored entry to the enclosing repo's `info/exclude` (#5551).
|
|
5
|
+
*
|
|
6
|
+
* Used for files GSD writes under `.planning/` that are per-machine state, not
|
|
7
|
+
* project content (the milestone claim). A copy that is already tracked is left
|
|
8
|
+
* alone — an exclude entry never untracks, and migrating it is the user's call.
|
|
9
|
+
*
|
|
10
|
+
* Best-effort by contract: never throws. Ignoring is optional, so no failure
|
|
11
|
+
* here (no git, read-only `.git`, odd path) may perturb the caller.
|
|
12
|
+
*/
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.excludeFromGit = excludeFromGit;
|
|
18
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
19
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
20
|
+
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
21
|
+
const text_lines_cjs_1 = require("./text-lines.cjs");
|
|
22
|
+
/** Escape gitignore metacharacters so a directory or file name matches literally. */
|
|
23
|
+
function escapeGitignore(s) {
|
|
24
|
+
return s.replace(/[\\*?[]/g, '\\$&');
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Exclude `<dir>/<filename>` from git via the repo-local `info/exclude`.
|
|
28
|
+
* `dir` must already exist (it is the spawn cwd).
|
|
29
|
+
*/
|
|
30
|
+
function excludeFromGit(dir, filename) {
|
|
31
|
+
try {
|
|
32
|
+
// gitignore cannot express a newline in a pattern, and git's line output could not be split.
|
|
33
|
+
if (/[\r\n]/.test(dir))
|
|
34
|
+
return;
|
|
35
|
+
// cwd must pick the repo: drop inherited repository-location variables (e.g. inside a git hook).
|
|
36
|
+
const env = { GIT_DIR: undefined, GIT_WORK_TREE: undefined, GIT_INDEX_FILE: undefined, GIT_COMMON_DIR: undefined };
|
|
37
|
+
// The prefix goes last: stdout is trimmed, and a non-empty prefix ends in `/`, so only an
|
|
38
|
+
// empty prefix (dir is the git root) loses its line; a leading space survives.
|
|
39
|
+
const revParse = (0, shell_command_projection_cjs_1.execGit)(['rev-parse', '--git-path', 'info/exclude', '--show-prefix'], {
|
|
40
|
+
cwd: dir,
|
|
41
|
+
env: env,
|
|
42
|
+
});
|
|
43
|
+
const [excludeRel, prefix = ''] = (0, text_lines_cjs_1.splitLines)(String(revParse.stdout));
|
|
44
|
+
if (revParse.exitCode !== 0 || !excludeRel)
|
|
45
|
+
return;
|
|
46
|
+
const exclude = node_path_1.default.resolve(dir, excludeRel);
|
|
47
|
+
const entry = `/${escapeGitignore(prefix)}${escapeGitignore(filename)}`;
|
|
48
|
+
const existing = node_fs_1.default.existsSync(exclude) ? node_fs_1.default.readFileSync(exclude, 'utf8') : '';
|
|
49
|
+
if ((0, text_lines_cjs_1.splitLines)(existing).includes(entry))
|
|
50
|
+
return;
|
|
51
|
+
node_fs_1.default.mkdirSync(node_path_1.default.dirname(exclude), { recursive: true });
|
|
52
|
+
node_fs_1.default.appendFileSync(exclude, (existing && !existing.endsWith('\n') ? '\n' : '') + entry + '\n');
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// advisory: see the module header.
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
*/
|
|
43
43
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
44
44
|
const healthDiagnosticMod = require("../health-diagnostic-types.cjs");
|
|
45
|
-
const { SEVERITY, adviseRemedy } = healthDiagnosticMod;
|
|
45
|
+
const { SEVERITY, REMEDY_ACTION, REMEDY_RISK, adviseRemedy } = healthDiagnosticMod;
|
|
46
46
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
47
47
|
const validateMod = require("../validate.cjs");
|
|
48
48
|
// #612: `isPhaseDirName` is the convention-SELECTED shape test wrapping
|
|
@@ -57,6 +57,9 @@ const phaseIdMod = require("../phase-id.cjs");
|
|
|
57
57
|
const { extractPhaseToken, normalizePhaseName, comparePhaseNum } = phaseIdMod;
|
|
58
58
|
// #5060: the Phase Status Module owns the status-label ladder.
|
|
59
59
|
const phase_status_cjs_1 = require("../phase-status.cjs");
|
|
60
|
+
// #5291: W030 asks whether a raw report status has a known repair. The lookup is
|
|
61
|
+
// a pure read of a frozen table, so `check` stays free of ambient I/O (§8.1 rule 1).
|
|
62
|
+
const verification_cjs_1 = require("../verification.cjs");
|
|
60
63
|
// ─── W005 — phase directory doesn't follow NN-name format (verify.cts:1893-1902) ─
|
|
61
64
|
function checkW005(snapshot) {
|
|
62
65
|
const diagnostics = [];
|
|
@@ -174,11 +177,21 @@ function checkW030(snapshot) {
|
|
|
174
177
|
const invalid = phase.verificationStatusError;
|
|
175
178
|
if (!invalid)
|
|
176
179
|
continue;
|
|
180
|
+
// #5291: a KNOWN legacy status is repairable (rewritten to its closed-set
|
|
181
|
+
// equivalent, original kept in `legacy_status`); any other value has no
|
|
182
|
+
// mapping and keeps the advise-only remedy — it stays refused.
|
|
183
|
+
const target = (0, verification_cjs_1.legacyStatusRepairTarget)(invalid.rawStatus);
|
|
177
184
|
diagnostics.push({
|
|
178
185
|
code: 'W030',
|
|
179
186
|
severity: SEVERITY.WARNING,
|
|
180
187
|
message: `Phase ${phase.dir}: ${invalid.message}`,
|
|
181
|
-
remedy:
|
|
188
|
+
remedy: target === null
|
|
189
|
+
? adviseRemedy('Set the report frontmatter `status` to one of passed | gaps_found | human_needed, or delete the report and re-run the phase verification')
|
|
190
|
+
: {
|
|
191
|
+
action: REMEDY_ACTION.REPAIR_VERIFICATION_STATUS,
|
|
192
|
+
risk: REMEDY_RISK.NONE,
|
|
193
|
+
args: { file: invalid.file, from: invalid.rawStatus, to: target },
|
|
194
|
+
},
|
|
182
195
|
});
|
|
183
196
|
}
|
|
184
197
|
return diagnostics;
|
|
@@ -217,7 +230,9 @@ const RULES = [
|
|
|
217
230
|
code: 'W030',
|
|
218
231
|
severity: SEVERITY.WARNING,
|
|
219
232
|
description: 'Phase verification report status is outside the closed set',
|
|
220
|
-
|
|
233
|
+
// #5291: repairable per finding — a KNOWN legacy status (`pass_with_caveats`)
|
|
234
|
+
// is rewritten by `--repair`; any other value stays advise-only.
|
|
235
|
+
repairable: true,
|
|
221
236
|
check: checkW030,
|
|
222
237
|
},
|
|
223
238
|
];
|
|
@@ -38,6 +38,10 @@ const REMEDY_ACTION = Object.freeze({
|
|
|
38
38
|
ADD_NYQUIST_KEY: 'addNyquistKey',
|
|
39
39
|
ADD_AI_INTEGRATION_PHASE_KEY: 'addAiIntegrationPhaseKey',
|
|
40
40
|
BACKFILL_MILESTONES: 'backfillMilestones',
|
|
41
|
+
// #5291: rewrite a KNOWN legacy verification `status` (W030) to its closed-set
|
|
42
|
+
// equivalent, keeping the original in `legacy_status`. Per-finding: only
|
|
43
|
+
// emitted when the raw value has a mapping; every other W030 stays ADVISE.
|
|
44
|
+
REPAIR_VERIFICATION_STATUS: 'repairVerificationStatus',
|
|
41
45
|
// §8.3 rule 5 — every non-repairable finding's `fix` string becomes an
|
|
42
46
|
// ADVISE payload; ADVISE never acts, only describes.
|
|
43
47
|
ADVISE: 'advise',
|
|
@@ -118,6 +118,9 @@ const { getMilestoneInfo } = roadmapParserMod;
|
|
|
118
118
|
const stateMod = require("./state.cjs");
|
|
119
119
|
const { writeStateMd, assertVerificationReportsReadable } = stateMod;
|
|
120
120
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
121
|
+
const verificationMod = require("./verification.cjs");
|
|
122
|
+
const { repairLegacyVerificationStatus } = verificationMod;
|
|
123
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
121
124
|
const frontmatter = require("./frontmatter.cjs");
|
|
122
125
|
const { extractFrontmatter } = frontmatter;
|
|
123
126
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
@@ -252,9 +255,27 @@ function computeMissingMilestoneVersions(milestonesArchiveDir, milestonesPath) {
|
|
|
252
255
|
* shape, collapsed to one seam here since every case now shares one
|
|
253
256
|
* caller).
|
|
254
257
|
*/
|
|
255
|
-
function runRepairAction(cwd, action, paths) {
|
|
258
|
+
function runRepairAction(cwd, action, paths, args = {}) {
|
|
256
259
|
const { rootBase, configPath, statePath, milestonesPath, milestonesArchiveDir } = paths;
|
|
257
260
|
switch (action) {
|
|
261
|
+
case REMEDY_ACTION.REPAIR_VERIFICATION_STATUS: {
|
|
262
|
+
// #5291: the report path comes from the finding's own remedy args, not
|
|
263
|
+
// from user input; `repairLegacyVerificationStatus` re-verifies that it is
|
|
264
|
+
// a report contained in its phase directory before it writes a byte.
|
|
265
|
+
const file = typeof args['file'] === 'string' ? args['file'] : '';
|
|
266
|
+
if (file === '')
|
|
267
|
+
return { success: false, error: 'no report path on the finding' };
|
|
268
|
+
const repaired = repairLegacyVerificationStatus(file);
|
|
269
|
+
if (!repaired.ok)
|
|
270
|
+
return { success: false, error: repaired.reason };
|
|
271
|
+
return {
|
|
272
|
+
success: true,
|
|
273
|
+
path: node_path_1.default.relative(cwd, file).split(node_path_1.default.sep).join('/'),
|
|
274
|
+
detail: repaired.legacyStatusKept
|
|
275
|
+
? `status ${repaired.from} -> ${repaired.to}; the report's existing legacy_status was left as it was`
|
|
276
|
+
: `status ${repaired.from} -> ${repaired.to}; original kept as legacy_status`,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
258
279
|
case REMEDY_ACTION.CREATE_CONFIG:
|
|
259
280
|
case REMEDY_ACTION.RESET_CONFIG: {
|
|
260
281
|
(0, shell_command_projection_cjs_1.platformWriteSync)(configPath, JSON.stringify(defaultConfigPayload(), null, 2));
|
|
@@ -390,6 +411,34 @@ function applyRepairs(cwd, diagnostics, repair, backfill) {
|
|
|
390
411
|
const refused = [];
|
|
391
412
|
const details = [];
|
|
392
413
|
const paths = repairPaths(cwd);
|
|
414
|
+
// #5291: a legacy-status repair is the CURE for the refusal the pre-check
|
|
415
|
+
// below enforces, so it runs first (a report edit is its only write and it
|
|
416
|
+
// validates its own target); the pre-check then sees the repaired reports.
|
|
417
|
+
const statusRepairs = new Set();
|
|
418
|
+
if (repair) {
|
|
419
|
+
for (const diagnostic of diagnostics) {
|
|
420
|
+
const { remedy, code } = diagnostic;
|
|
421
|
+
if (remedy.action !== REMEDY_ACTION.REPAIR_VERIFICATION_STATUS || remedy.risk === REMEDY_RISK.DESTRUCTIVE)
|
|
422
|
+
continue;
|
|
423
|
+
statusRepairs.add(diagnostic);
|
|
424
|
+
try {
|
|
425
|
+
const outcome = runRepairAction(cwd, remedy.action, paths, remedy.args);
|
|
426
|
+
details.push({
|
|
427
|
+
code,
|
|
428
|
+
action: remedy.action,
|
|
429
|
+
success: outcome.success,
|
|
430
|
+
...(outcome.path ? { path: outcome.path } : {}),
|
|
431
|
+
...(outcome.detail ? { detail: outcome.detail } : {}),
|
|
432
|
+
...(outcome.error ? { error: outcome.error } : {}),
|
|
433
|
+
});
|
|
434
|
+
if (outcome.success)
|
|
435
|
+
applied.push(code);
|
|
436
|
+
}
|
|
437
|
+
catch (err) {
|
|
438
|
+
details.push({ code, action: remedy.action, success: false, error: err instanceof Error ? err.message : String(err) });
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
393
442
|
// #5118 (no write before the error): a requested REGENERATE_STATE rewrites
|
|
394
443
|
// STATE.md from every phase's report and throws on one whose `status` is
|
|
395
444
|
// outside the closed set — but other repairs in the SAME run (config,
|
|
@@ -411,6 +460,8 @@ function applyRepairs(cwd, diagnostics, repair, backfill) {
|
|
|
411
460
|
const { remedy, code } = diagnostic;
|
|
412
461
|
if (remedy.action === REMEDY_ACTION.ADVISE)
|
|
413
462
|
continue;
|
|
463
|
+
if (statusRepairs.has(diagnostic))
|
|
464
|
+
continue;
|
|
414
465
|
const requested = remedy.action === REMEDY_ACTION.BACKFILL_MILESTONES ? repair || backfill : repair;
|
|
415
466
|
if (!requested)
|
|
416
467
|
continue;
|
|
@@ -620,7 +620,7 @@ function hookEventSurfaceFor(hookEvents) {
|
|
|
620
620
|
// event subset (imperative hosts' extension API). They are not the same thing.
|
|
621
621
|
//
|
|
622
622
|
// Values are documentation-sourced (ADR-1239 §research): OpenCode ~25 plugin
|
|
623
|
-
// events (session/tool/file/permission); pi
|
|
623
|
+
// events (session/tool/file/permission); pi 41 fine-grained extension events (pi 1.3.0);
|
|
624
624
|
// 'none' = the host exposes no extension surface and the engine owns the bus
|
|
625
625
|
// (VS Code). Declarative hosts (no plugin API) do not set `extensionEvents`.
|
|
626
626
|
// OpenCode's plugin event surface (ADR-1239 §research; ~25 documented events,
|
|
@@ -655,11 +655,13 @@ const EXTENSION_EVENT_SURFACES = Object.freeze({
|
|
|
655
655
|
'pre_gateway_dispatch', 'pre_approval_request',
|
|
656
656
|
'transform_tool_result',
|
|
657
657
|
]),
|
|
658
|
-
//
|
|
659
|
-
//
|
|
660
|
-
//
|
|
661
|
-
//
|
|
662
|
-
//
|
|
658
|
+
// pi's real ExtensionAPI event vocabulary: the 41 `on(event: "...")` overloads
|
|
659
|
+
// declared by pi 1.3.0 (@earendil-works/pi-coding-agent
|
|
660
|
+
// dist/core/extensions/types.d.ts, sourceCommit 71023aec15, #5557). #2102
|
|
661
|
+
// Stage 2 declared the first 30 from pi.dev prose; the last 11 on the final
|
|
662
|
+
// row group were added when the host's own declarations were read. The
|
|
663
|
+
// pi.dev extensions page lists a lossy subset (it omits session_before_compact,
|
|
664
|
+
// which pi/gsd.cjs binds), so the type declarations are the source of truth.
|
|
663
665
|
pi: Object.freeze([
|
|
664
666
|
'session_start', 'project_trust', 'resources_discover', 'input',
|
|
665
667
|
'before_agent_start', 'agent_start', 'message_start', 'message_update',
|
|
@@ -669,6 +671,11 @@ const EXTENSION_EVENT_SURFACES = Object.freeze({
|
|
|
669
671
|
'session_before_switch', 'session_shutdown', 'session_before_fork',
|
|
670
672
|
'session_info_changed', 'session_before_compact', 'session_compact',
|
|
671
673
|
'session_before_tree', 'session_tree', 'thinking_level_select', 'model_select',
|
|
674
|
+
// Added in pi 1.3.0 (#5557):
|
|
675
|
+
'agent_before_settle', 'agent_settled', 'before_provider_headers',
|
|
676
|
+
'cache_warming_decision', 'context_with_system', 'mcp_servers_change',
|
|
677
|
+
'provider_stream_event', 'session_compact_failed', 'ui_prompt_end',
|
|
678
|
+
'ui_prompt_start', 'user_bash',
|
|
672
679
|
]),
|
|
673
680
|
none: Object.freeze([]),
|
|
674
681
|
});
|
|
@@ -20,6 +20,8 @@ const markdown_sectionizer_cjs_1 = require("./markdown-sectionizer.cjs");
|
|
|
20
20
|
const io = require("./io.cjs");
|
|
21
21
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- config-loader.cjs is an export= CommonJS module
|
|
22
22
|
const configLoader = require("./config-loader.cjs");
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports -- capability-ledger.cjs is an export= CommonJS module
|
|
24
|
+
const capabilityLedger = require("./capability-ledger.cjs");
|
|
23
25
|
const project_root_cjs_1 = require("./project-root.cjs");
|
|
24
26
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- model-resolver.cjs is an export= CommonJS module
|
|
25
27
|
const modelResolver = require("./model-resolver.cjs");
|
|
@@ -96,7 +98,7 @@ const { getRoadmapPhaseInternal, getMilestoneInfo, stripShippedMilestones, extra
|
|
|
96
98
|
const { pathExistsInternal, generateSlugInternal, toPosixPath } = coreUtils;
|
|
97
99
|
const { comparePhaseNum, normalizePhaseName, stripProjectCodePrefix, PHASE_NUMBER_TOKEN_SOURCE, PHASE_DEP_REF_SOURCE, isForeignPrefixedPhaseQuery, isSentinelPhaseId, extractPhaseToken, scopeToPhase, renderPhaseBranchName, parsePhaseId, renderPhaseId, phaseHeadingPrefixSrcFor, PHASE_HEADING_BASELINE, buildPhaseHeadingScanRegex, } = phaseId;
|
|
98
100
|
const { pruneOrphanedWorktrees } = worktreeSafety;
|
|
99
|
-
const { planningPaths, planningDir, planningRoot, todosDir, listAvailableWorkstreams, peekActiveWorkstream, resolveEnvWorkstream, diagnoseUnresolvedActiveWorkstream, describeUnresolvedWorkstreamReason, findContextMdIn, resolvePhaseIdConvention, worktreesOptedOut, } = planningWorkspace;
|
|
101
|
+
const { planningPaths, planningDir, planningRoot, todosDir, listAvailableWorkstreams, peekActiveWorkstream, resolveEnvWorkstream, diagnoseUnresolvedActiveWorkstream, describeUnresolvedWorkstreamReason, findContextMdIn, findPhaseSpecIn, resolvePhaseIdConvention, worktreesOptedOut, } = planningWorkspace;
|
|
100
102
|
const { extractFrontmatter, frontmatterBlock } = frontmatterMod;
|
|
101
103
|
const { isPhaseComplete, resolveVerificationFile, resolveUatFile, VERIFICATION_STATUS, VerificationStatusError } = verificationMod;
|
|
102
104
|
const { evaluateUatPassed } = uatPredicateMod;
|
|
@@ -175,6 +177,28 @@ function resolvePhaseDisplayName(phaseInfo, roadmapPhase) {
|
|
|
175
177
|
|| phaseInfo?.['phase_name']
|
|
176
178
|
|| null;
|
|
177
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* #5629: the phase SPEC as init facts, for every init payload a SPEC-consuming workflow parses
|
|
182
|
+
* (discuss-phase via `phase-op`, discuss-phase-assumptions, plan-phase). `has_spec` is always present;
|
|
183
|
+
* `spec_path` (absolute, posix) only when a plain `NN-SPEC.md` exists. One predicate (`findPhaseSpecIn`, shared
|
|
184
|
+
* with the context-drift gate) decides, so a UI-SPEC or AI-SPEC is never mistaken for the requirements lock and
|
|
185
|
+
* no workflow globs for it. A phase with no directory yet, or one that cannot be read, has no SPEC.
|
|
186
|
+
*/
|
|
187
|
+
function phaseSpecFacts(phaseDirAbs) {
|
|
188
|
+
if (!phaseDirAbs)
|
|
189
|
+
return { has_spec: false };
|
|
190
|
+
let files;
|
|
191
|
+
try {
|
|
192
|
+
files = node_fs_1.default.readdirSync(phaseDirAbs);
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return { has_spec: false };
|
|
196
|
+
}
|
|
197
|
+
// Scoped to THIS phase's own artifacts first (#3511), like the sibling artifact lookups: a misfiled
|
|
198
|
+
// `02-SPEC.md` in phase 03's directory must not win (the context-drift gate scopes the same way).
|
|
199
|
+
const spec = findPhaseSpecIn(scopeToPhase(files, node_path_1.default.basename(phaseDirAbs)));
|
|
200
|
+
return spec ? { has_spec: true, spec_path: toPosixPath(node_path_1.default.join(phaseDirAbs, spec)) } : { has_spec: false };
|
|
201
|
+
}
|
|
178
202
|
/**
|
|
179
203
|
* #2994 (review finding, DEFECT.GENERATIVE-FIX): shared archived/not-found
|
|
180
204
|
* fallback applied identically by `cmdInitExecutePhase`, `cmdInitPlanPhase`,
|
|
@@ -598,6 +622,28 @@ function detectFallowConfig(cwd) {
|
|
|
598
622
|
function detectGitCreateTag(cwd) {
|
|
599
623
|
return readConfigJsonValue(cwd, ['git', 'create_tag']) !== false;
|
|
600
624
|
}
|
|
625
|
+
/**
|
|
626
|
+
* `git.repo_tagging` ground truth (#5706, epic #3628): the milestone tagging
|
|
627
|
+
* mode exposed to `complete-milestone.md`. Only the documented `per_repo`
|
|
628
|
+
* opts in; an absent key or any other stored value reads as the default
|
|
629
|
+
* `single` (today's behavior), matching `loadConfig`'s resolution.
|
|
630
|
+
*/
|
|
631
|
+
function detectRepoTagging(cwd) {
|
|
632
|
+
return readConfigJsonValue(cwd, ['git', 'repo_tagging']) === 'per_repo' ? 'per_repo' : 'single';
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* The configured `planning.sub_repos` (#5706): an array of non-empty repo
|
|
636
|
+
* names, possibly empty. A legacy top-level `sub_repos` is honored when the
|
|
637
|
+
* nested key is absent, the same flat-then-nested order `loadConfig` applies.
|
|
638
|
+
* Non-string members are dropped; any degraded read yields `[]`.
|
|
639
|
+
*/
|
|
640
|
+
function detectSubRepos(cwd) {
|
|
641
|
+
const nested = readConfigJsonValue(cwd, ['planning', 'sub_repos']);
|
|
642
|
+
const raw = nested !== undefined ? nested : readConfigJsonValue(cwd, ['sub_repos']);
|
|
643
|
+
if (!Array.isArray(raw))
|
|
644
|
+
return [];
|
|
645
|
+
return raw.filter((name) => typeof name === 'string' && name.trim() !== '');
|
|
646
|
+
}
|
|
601
647
|
/**
|
|
602
648
|
* `state:phase-mvp-mode` ground truth (design doc §Behavior table: ROADMAP.md
|
|
603
649
|
* `**Mode:** mvp` for the CURRENT phase). Bounded, non-throwing — an absent
|
|
@@ -1137,6 +1183,8 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
|
|
|
1137
1183
|
state_path: node_fs_1.default.existsSync(statePath) ? toPosixPath(statePath) : null,
|
|
1138
1184
|
roadmap_path: node_fs_1.default.existsSync(roadmapPath) ? toPosixPath(roadmapPath) : null,
|
|
1139
1185
|
requirements_path: node_fs_1.default.existsSync(requirementsPath) ? toPosixPath(requirementsPath) : null,
|
|
1186
|
+
// #5629: the phase SPEC (plan-phase lifts its Edge Coverage from it; no workflow globs for it).
|
|
1187
|
+
...phaseSpecFacts(phaseInfo?.['directory'] ? node_path_1.default.join(cwd, phaseInfo['directory']) : null),
|
|
1140
1188
|
patterns_path: null,
|
|
1141
1189
|
};
|
|
1142
1190
|
if (phaseInfo?.['directory']) {
|
|
@@ -1932,6 +1980,8 @@ function cmdInitDiscussPhaseAssumptions(cwd, phase, raw, options = {}) {
|
|
|
1932
1980
|
plan_count: phaseInfo?.['plans']?.length || 0,
|
|
1933
1981
|
roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
1934
1982
|
planning_exists: node_fs_1.default.existsSync(planningDir(cwd)),
|
|
1983
|
+
// #5629: the phase SPEC, so assumptions mode honours it like the default flow does.
|
|
1984
|
+
...phaseSpecFacts(phaseDir ? node_path_1.default.join(cwd, phaseDir) : null),
|
|
1935
1985
|
};
|
|
1936
1986
|
// #2994 (Phase 6.3): additive, optional field — degrades to null, never throws.
|
|
1937
1987
|
const sectionManifestOptions = {
|
|
@@ -2063,6 +2113,8 @@ function cmdInitPhaseOp(cwd, phase, raw) {
|
|
|
2063
2113
|
state_path: node_fs_1.default.existsSync(statePath) ? toPosixPath(statePath) : null,
|
|
2064
2114
|
roadmap_path: node_fs_1.default.existsSync(roadmapPath) ? toPosixPath(roadmapPath) : null,
|
|
2065
2115
|
requirements_path: node_fs_1.default.existsSync(requirementsPath) ? toPosixPath(requirementsPath) : null,
|
|
2116
|
+
// #5629: the phase SPEC (discuss-phase reads it from here; no workflow globs for it).
|
|
2117
|
+
...phaseSpecFacts(phaseDir ? node_path_1.default.join(cwd, phaseDir) : null),
|
|
2066
2118
|
};
|
|
2067
2119
|
if (phaseInfo?.['directory']) {
|
|
2068
2120
|
const phaseDirFull = node_path_1.default.join(cwd, phaseInfo['directory']);
|
|
@@ -3014,9 +3066,23 @@ function cmdInitCompleteMilestone(cwd, raw, options = {}) {
|
|
|
3014
3066
|
milestones_path: node_fs_1.default.existsSync(milestonesPath) ? toPosixPath(milestonesPath) : null,
|
|
3015
3067
|
project_path: node_fs_1.default.existsSync(projectPath) ? toPosixPath(projectPath) : null,
|
|
3016
3068
|
requirements_path: node_fs_1.default.existsSync(requirementsPath) ? toPosixPath(requirementsPath) : null,
|
|
3069
|
+
// #5706 (epic #3628): the repositories configured for this project and the
|
|
3070
|
+
// milestone tagging mode, so the workflow reads both from one init call.
|
|
3071
|
+
sub_repos: detectSubRepos(cwd),
|
|
3072
|
+
repo_tagging: detectRepoTagging(cwd),
|
|
3017
3073
|
};
|
|
3074
|
+
// #5195: `state:flat-mode` gates the PROJECT.md evolution review. PROJECT.md
|
|
3075
|
+
// is shared across workstreams (the `projectPath` comment above), so a
|
|
3076
|
+
// workstream's milestone close must not rewrite or stage it — the same
|
|
3077
|
+
// decision `cmdInitNewMilestone` applies to its Part A (#2308), resolved from
|
|
3078
|
+
// the same authority (`GSD_WORKSTREAM` env, else the stored pointer) so the
|
|
3079
|
+
// gate cannot disagree with the workstream-scoped paths returned above.
|
|
3080
|
+
// Read-only peek: no self-heal side effect from building a report field (#3579).
|
|
3081
|
+
const workstreamActive = !!(resolveEnvWorkstream() ?? peekActiveWorkstream(cwd));
|
|
3018
3082
|
result['section_manifest'] = buildSectionManifestField(cwd, null, options, 'complete-milestone', {
|
|
3019
3083
|
gitCreateTag,
|
|
3084
|
+
workstreamActive,
|
|
3085
|
+
flatMode: !workstreamActive,
|
|
3020
3086
|
});
|
|
3021
3087
|
output(withProjectRoot(cwd, result), raw);
|
|
3022
3088
|
}
|
|
@@ -3773,7 +3839,7 @@ function buildAgentSkillsBlock(config, agentType, projectRoot, diagnostics) {
|
|
|
3773
3839
|
}).join('\n');
|
|
3774
3840
|
return `<agent_skills>\nRead these user-configured skills:\n${lines}\n</agent_skills>`;
|
|
3775
3841
|
}
|
|
3776
|
-
function cmdAgentSkills(cwd, agentType, raw, jsonMode) {
|
|
3842
|
+
function cmdAgentSkills(cwd, agentType, raw, jsonMode, skillsOnly = false) {
|
|
3777
3843
|
if (!agentType) {
|
|
3778
3844
|
output('', raw, '');
|
|
3779
3845
|
return;
|
|
@@ -3804,8 +3870,13 @@ function cmdAgentSkills(cwd, agentType, raw, jsonMode) {
|
|
|
3804
3870
|
// (a real exit code) instead of a prose config-get gate. Compact is tried
|
|
3805
3871
|
// first when requested; a missing compact sibling falls back to canonical
|
|
3806
3872
|
// with the fallback disclosed in the payload itself, never a silent switch.
|
|
3873
|
+
//
|
|
3874
|
+
// #5122: `skillsOnly` (the CLI's `--skills-only`) is the agent's own
|
|
3875
|
+
// self-load. It wants configured skills and nothing else, so it skips the
|
|
3876
|
+
// fallback on every runtime — otherwise a non-Claude agent reads its own
|
|
3877
|
+
// persona back into itself as if it were a skills block.
|
|
3807
3878
|
let agentPayloadVariant = null;
|
|
3808
|
-
if (!block) {
|
|
3879
|
+
if (!block && !skillsOnly) {
|
|
3809
3880
|
const runtime = (config && config['runtime']) || process.env['GSD_RUNTIME'] || 'claude';
|
|
3810
3881
|
if (runtime !== 'claude') {
|
|
3811
3882
|
const agentCheck = checkAgentsInstalled(runtime, projectRoot);
|
|
@@ -4071,7 +4142,7 @@ function buildSkillManifest(cwd, skillsDir = null) {
|
|
|
4071
4142
|
if (!entry.isDirectory())
|
|
4072
4143
|
continue;
|
|
4073
4144
|
const skillMdPath = node_path_1.default.join(rootPath, entry.name, 'SKILL.md');
|
|
4074
|
-
const content =
|
|
4145
|
+
const content = capabilityLedger.readSkillFile(skillMdPath);
|
|
4075
4146
|
if (content !== null) {
|
|
4076
4147
|
if (pushSkillEntry(`${entry.name}/SKILL.md`, content, skillMdPath))
|
|
4077
4148
|
skillCount++;
|
|
@@ -4096,7 +4167,7 @@ function buildSkillManifest(cwd, skillsDir = null) {
|
|
|
4096
4167
|
if (!nested.isDirectory())
|
|
4097
4168
|
continue;
|
|
4098
4169
|
const nestedSkillMd = node_path_1.default.join(nestedSkillsDir, nested.name, 'SKILL.md');
|
|
4099
|
-
const nestedContent =
|
|
4170
|
+
const nestedContent = capabilityLedger.readSkillFile(nestedSkillMd);
|
|
4100
4171
|
if (nestedContent === null)
|
|
4101
4172
|
continue;
|
|
4102
4173
|
// Use forward-slash separator explicitly so manifest paths are posix-style
|
|
@@ -35,7 +35,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
*/
|
|
36
36
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
37
37
|
const node_path_1 = __importDefault(require("node:path"));
|
|
38
|
-
const
|
|
38
|
+
const runtime_homes_cjs_1 = require("./runtime-homes.cjs");
|
|
39
39
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- install-fs-adapter.cjs is an export= CommonJS module
|
|
40
40
|
const installFsAdapter = require("./install-fs-adapter.cjs");
|
|
41
41
|
const { installFs } = installFsAdapter;
|
|
@@ -154,7 +154,7 @@ function _findAncestorGsdConfigPath(targetDir) {
|
|
|
154
154
|
* @param targetDir Runtime install root (walks up to find .planning/).
|
|
155
155
|
*/
|
|
156
156
|
function readGsdEffectiveEffortConfig(targetDir = null) {
|
|
157
|
-
const homeDefaults = _readGsdConfigFile(node_path_1.default.join(
|
|
157
|
+
const homeDefaults = _readGsdConfigFile(node_path_1.default.join((0, runtime_homes_cjs_1.resolveGsdHome)(), '.gsd', 'defaults.json'), '~/.gsd/defaults.json');
|
|
158
158
|
let projectConfig = null;
|
|
159
159
|
if (targetDir) {
|
|
160
160
|
const candidate = _findAncestorGsdConfigPath(targetDir);
|