@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
|
@@ -52,6 +52,7 @@ const userArtifactStaging = require("./user-artifact-staging.cjs");
|
|
|
52
52
|
// module-level doc comment on `isGlobalScope` for why the projection is
|
|
53
53
|
// centralized rather than eliminated).
|
|
54
54
|
const install_scope_cjs_1 = require("./install-scope.cjs");
|
|
55
|
+
const args_terminator_cjs_1 = require("./args-terminator.cjs");
|
|
55
56
|
const { processAttribution } = runtimeArtifactConversion;
|
|
56
57
|
// resolveRuntimeArtifactLayout: accessed via module ref (not destructured) so
|
|
57
58
|
// test stubs that monkeypatch the module's exports are seen at call time.
|
|
@@ -233,7 +234,8 @@ function applyOpencodeFamilyPathPrefix(content, runtime, pathPrefix) {
|
|
|
233
234
|
content = content.replace(/\.\/\.claude\//g, `./${getDirName(runtime)}/`);
|
|
234
235
|
content = content.replace(/~\/\.opencode\//g, pathPrefix);
|
|
235
236
|
content = content.replace(/~\/\.kilo\//g, pathPrefix);
|
|
236
|
-
|
|
237
|
+
// #5637: the typed-text capture heredoc ends at a terminator the typed text cannot know.
|
|
238
|
+
return (0, args_terminator_cjs_1.stampInstalledContent)(content);
|
|
237
239
|
}
|
|
238
240
|
/**
|
|
239
241
|
* Convert a Claude command (.md) to an OpenCode skill (SKILL.md).
|
|
@@ -755,10 +757,17 @@ function _copyStaged(stagedDir, destDir, kind, configDir, runtime) {
|
|
|
755
757
|
* For the prefix='' case: the destSubpath IS the namespace — remove the entire
|
|
756
758
|
* destDir. (No current runtime uses prefix='' after #947 reversed Hermes; kept
|
|
757
759
|
* as a defensive guard for future runtimes.)
|
|
760
|
+
*
|
|
761
|
+
* `owns` (#5161): when supplied, a prefix match is necessary but NOT
|
|
762
|
+
* sufficient — an entry is removed only when `owns(name)` is true, and every
|
|
763
|
+
* prefix-matching entry it rejects is returned so the caller can name it.
|
|
764
|
+
* Omitted (agents, commands, uninstall), every prefix match is removed as
|
|
765
|
+
* before and the return value is always empty.
|
|
758
766
|
*/
|
|
759
|
-
function _removeGsdEntries(destDir, kind) {
|
|
767
|
+
function _removeGsdEntries(destDir, kind, owns) {
|
|
768
|
+
const preserved = [];
|
|
760
769
|
if (!installFs().existsSync(destDir))
|
|
761
|
-
return;
|
|
770
|
+
return preserved;
|
|
762
771
|
if (kind.kind === 'kimi-agents') {
|
|
763
772
|
for (const fileName of ['gsd.yaml', 'gsd.md']) {
|
|
764
773
|
installFs().rmSync(node_path_1.default.join(destDir, fileName), { force: true });
|
|
@@ -775,19 +784,158 @@ function _removeGsdEntries(destDir, kind) {
|
|
|
775
784
|
installFs().rmSync(node_path_1.default.join(subagentsDir, entry.name), { force: true });
|
|
776
785
|
}
|
|
777
786
|
}
|
|
778
|
-
return;
|
|
787
|
+
return preserved;
|
|
779
788
|
}
|
|
780
789
|
if (kind.prefix === '') {
|
|
781
790
|
// Whole-namespace removal (Hermes nested case — destSubpath is skills/gsd)
|
|
782
791
|
// The directory itself is the GSD namespace, so remove it entirely.
|
|
783
792
|
installFs().rmSync(destDir, { recursive: true, force: true });
|
|
784
|
-
return;
|
|
793
|
+
return preserved;
|
|
785
794
|
}
|
|
786
795
|
for (const entry of installFs().readdirSync(destDir, { withFileTypes: true })) {
|
|
787
796
|
if (!entry.name.startsWith(kind.prefix))
|
|
788
797
|
continue;
|
|
798
|
+
if (owns && !owns(entry.name)) {
|
|
799
|
+
preserved.push(entry.name);
|
|
800
|
+
continue;
|
|
801
|
+
}
|
|
789
802
|
installFs().rmSync(node_path_1.default.join(destDir, entry.name), { recursive: true, force: true });
|
|
790
803
|
}
|
|
804
|
+
return preserved;
|
|
805
|
+
}
|
|
806
|
+
// ---------------------------------------------------------------------------
|
|
807
|
+
// Skill-dir ownership (#5161)
|
|
808
|
+
// ---------------------------------------------------------------------------
|
|
809
|
+
/**
|
|
810
|
+
* GSD-prefixed skill dirs the user owns and GSD never reinstalls from source
|
|
811
|
+
* (#2973). The skills writers snapshot them across the prune and restore them.
|
|
812
|
+
*/
|
|
813
|
+
const USER_OWNED_SKILL_DIRS = ['gsd-dev-preferences'];
|
|
814
|
+
/** The skill dirs each writer wrote, keyed on the resolved skills dir (recordWrittenSkillDirs). */
|
|
815
|
+
const writtenSkillDirs = new Map();
|
|
816
|
+
/**
|
|
817
|
+
* Record the skill dirs a writer just wrote into `skillsDir`, replacing that
|
|
818
|
+
* dir's entry. Called only once the write has returned, so a writer that threw
|
|
819
|
+
* records nothing.
|
|
820
|
+
*/
|
|
821
|
+
function recordWrittenSkillDirs(skillsDir, names) {
|
|
822
|
+
writtenSkillDirs.set(node_path_1.default.resolve(skillsDir), new Set(names));
|
|
823
|
+
}
|
|
824
|
+
/** Start an install's record empty, so no earlier install's writes are read. */
|
|
825
|
+
function clearWrittenSkillDirs() {
|
|
826
|
+
writtenSkillDirs.clear();
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* Build the predicate that decides whether a prefix-matching dir in
|
|
830
|
+
* `skillsDir` is GSD-owned (#5161). A prefix match is necessary but NOT
|
|
831
|
+
* sufficient — the rule surface.cts pruneSkillDirs already applies. A dir is
|
|
832
|
+
* GSD-owned when any of these hold:
|
|
833
|
+
* - it is a first-party skill: `<prefix><stem>` for a commands/gsd/<stem>.md
|
|
834
|
+
* in the install source;
|
|
835
|
+
* - it carries the capability-skill marker (a third-party capability skill
|
|
836
|
+
* GSD staged, install-profiles.cts CAPABILITY_SKILL_MARKER);
|
|
837
|
+
* - `includeManifest` is not false and the previous install's
|
|
838
|
+
* gsd-file-manifest.json records a file under it (a skill GSD installed
|
|
839
|
+
* before that has since been retired or left the active profile).
|
|
840
|
+
* Anything else is user-owned or unknown. The first-time baseline migration
|
|
841
|
+
* may already have resolved it to `keep`, and the prune must honor that.
|
|
842
|
+
*
|
|
843
|
+
* writeManifest builds this with `includeManifest: false`: a preserved user
|
|
844
|
+
* dir recorded into the manifest would read back as GSD-owned on the next
|
|
845
|
+
* install and be deleted then.
|
|
846
|
+
*
|
|
847
|
+
* `manifestIfSourceUnresolved` is writeManifest's answer when the install
|
|
848
|
+
* source cannot be read, which leaves no first-party leg. It turns the manifest
|
|
849
|
+
* leg back on for that case only, so the dirs the previous install recorded
|
|
850
|
+
* stay recorded and the fallback adds no dir the previous manifest does not
|
|
851
|
+
* already record (beyond capability-marked ones). Owning every dir instead
|
|
852
|
+
* would record a user's kept dir, and the next install would read it back as
|
|
853
|
+
* GSD-owned and delete it: the #5161 failure, reached through a fallback. The
|
|
854
|
+
* cost is a skill first shipped by this release going unrecorded until the
|
|
855
|
+
* next install with a readable source. A prune never needs the flag: it keeps
|
|
856
|
+
* every dir it cannot otherwise prove, and its manifest leg is already on.
|
|
857
|
+
*
|
|
858
|
+
* `includeWritten` adds the skill dirs this install wrote into `skillsDir`
|
|
859
|
+
* (recordWrittenSkillDirs). The first-party lookups can miss the corpus a run
|
|
860
|
+
* staged: staging resolves its provider under the layout's requirement and the
|
|
861
|
+
* installed corpus's manifest, so it can take a corpus a `.gsd-source` marker
|
|
862
|
+
* names that neither lookup reaches, and its skills would then go uncounted
|
|
863
|
+
* and unrecorded. Only the skill counts and writeManifest pass the flag, since
|
|
864
|
+
* they must own what the install wrote. Every prune leaves it unset, so the
|
|
865
|
+
* record never widens what is deleted.
|
|
866
|
+
*/
|
|
867
|
+
function createSkillDirOwnership(runtime, configDir, skillsDir, prefix, opts = {}) {
|
|
868
|
+
// First-party stems come from BOTH the configDir-resolved source and the
|
|
869
|
+
// executing package's own source. Staging resolves its provider with the
|
|
870
|
+
// commands+agents requirement while a commands-only lookup can accept a
|
|
871
|
+
// different provider (a commands-only `.gsd-source` marker), so either root
|
|
872
|
+
// alone can miss the corpus the run staged. Both are GSD corpora, so the
|
|
873
|
+
// union only ever widens what GSD owns.
|
|
874
|
+
const firstParty = new Set();
|
|
875
|
+
let sourceResolved = false;
|
|
876
|
+
let lastError = null;
|
|
877
|
+
const roots = [
|
|
878
|
+
() => runtimeArtifactLayout.findInstallSourceRoot(configDir),
|
|
879
|
+
() => runtimeArtifactLayout.findInstallSourceRoot(undefined),
|
|
880
|
+
];
|
|
881
|
+
for (const root of roots) {
|
|
882
|
+
try {
|
|
883
|
+
const commandsGsdDir = root();
|
|
884
|
+
// A regular `.md` file only — the filter every skills writer stages
|
|
885
|
+
// with. A source counts as resolved only once it yields a stem.
|
|
886
|
+
for (const entry of installFs().readdirSync(commandsGsdDir, { withFileTypes: true })) {
|
|
887
|
+
if (!entry.isFile() || !entry.name.endsWith('.md'))
|
|
888
|
+
continue;
|
|
889
|
+
firstParty.add(prefix + entry.name.slice(0, -3));
|
|
890
|
+
sourceResolved = true;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
catch (err) {
|
|
894
|
+
lastError = err;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
if (!sourceResolved) {
|
|
898
|
+
console.warn(` [gsd] could not read the install source to classify ${skillsDir} (${lastError?.message}) — ${opts.manifestIfSourceUnresolved ? 'treating as GSD-owned only the gsd- skill dirs the previous install manifest records or that carry the capability-skill marker' : 'keeping every gsd- skill dir GSD cannot otherwise prove it owns'}.`);
|
|
899
|
+
}
|
|
900
|
+
const manifestNames = new Set();
|
|
901
|
+
if (opts.includeManifest !== false || (!sourceResolved && opts.manifestIfSourceUnresolved === true)) {
|
|
902
|
+
// The prefix must describe the root being pruned: a manifest name under one
|
|
903
|
+
// root says nothing about a same-named dir under another (Hermes' flat
|
|
904
|
+
// pre-#2841 root vs its nested skills/gsd/ root).
|
|
905
|
+
const manifestPrefix = opts.manifestPrefix ?? (hostBehaviorsFor(runtime).skillsManifestPrefix || 'skills/');
|
|
906
|
+
for (const key of Object.keys(installerMigrations.readInstallManifest(configDir).files)) {
|
|
907
|
+
if (!key.startsWith(manifestPrefix))
|
|
908
|
+
continue;
|
|
909
|
+
const rest = key.slice(manifestPrefix.length);
|
|
910
|
+
const slash = rest.indexOf('/');
|
|
911
|
+
if (slash > 0)
|
|
912
|
+
manifestNames.add(rest.slice(0, slash));
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
const written = opts.includeWritten === true ? writtenSkillDirs.get(node_path_1.default.resolve(skillsDir)) : undefined;
|
|
916
|
+
return (name) => firstParty.has(name) ||
|
|
917
|
+
manifestNames.has(name) ||
|
|
918
|
+
written?.has(name) === true ||
|
|
919
|
+
installFs().existsSync(node_path_1.default.join(skillsDir, name, installProfiles.CAPABILITY_SKILL_MARKER));
|
|
920
|
+
}
|
|
921
|
+
/**
|
|
922
|
+
* Report each prefix-matching skill dir the prune preserved as not GSD-owned,
|
|
923
|
+
* by path (#5161). The deletion this replaces was silent.
|
|
924
|
+
*
|
|
925
|
+
* A USER_OWNED_SKILL_DIRS entry is never named: GSD special-cases it (the
|
|
926
|
+
* writers restore it and writeManifest records it), so "GSD does not own it,
|
|
927
|
+
* rename it" would be false. It reaches this list whenever no previous
|
|
928
|
+
* manifest records it yet, e.g. the first update after the user generates it.
|
|
929
|
+
*
|
|
930
|
+
* The message names no manifest: the legacy-location cleanups decide without
|
|
931
|
+
* one, so "not in the previous install manifest" would be false there.
|
|
932
|
+
*/
|
|
933
|
+
function _warnPreservedSkillDirs(skillsDir, names) {
|
|
934
|
+
for (const name of names) {
|
|
935
|
+
if (USER_OWNED_SKILL_DIRS.includes(name))
|
|
936
|
+
continue;
|
|
937
|
+
console.warn(` [gsd] Preserved ${node_path_1.default.join(skillsDir, name)} — it matches the gsd- skill prefix but nothing shows GSD owns it here. Rename it if it should not share GSD's prefix.`);
|
|
938
|
+
}
|
|
791
939
|
}
|
|
792
940
|
// ---------------------------------------------------------------------------
|
|
793
941
|
// _snapshotDir / _restoreDir
|
|
@@ -833,14 +981,17 @@ function _restoreDir(dir, snapshot) {
|
|
|
833
981
|
*
|
|
834
982
|
* @param nestedGsdDir absolute path to skills/gsd/ category dir
|
|
835
983
|
*/
|
|
836
|
-
function _removeHermesBareStemDirs(nestedGsdDir) {
|
|
984
|
+
function _removeHermesBareStemDirs(nestedGsdDir, owns) {
|
|
837
985
|
if (!installFs().existsSync(nestedGsdDir))
|
|
838
986
|
return;
|
|
839
987
|
const entries = installFs().readdirSync(nestedGsdDir, { withFileTypes: true });
|
|
840
988
|
// Collect the set of stems that were installed as gsd-<stem>/ this run.
|
|
989
|
+
// #5161: the prune now keeps gsd-* dirs GSD does not own, so "present" no
|
|
990
|
+
// longer means "installed". With `owns`, only an owned gsd-<stem>/ counts,
|
|
991
|
+
// and a user's own <stem>/ beside their own gsd-<stem>/ is left alone.
|
|
841
992
|
const installedStems = new Set();
|
|
842
993
|
for (const entry of entries) {
|
|
843
|
-
if (entry.isDirectory() && entry.name.startsWith('gsd-')) {
|
|
994
|
+
if (entry.isDirectory() && entry.name.startsWith('gsd-') && (!owns || owns(entry.name))) {
|
|
844
995
|
installedStems.add(entry.name.slice('gsd-'.length)); // e.g. 'quick', 'dev-preferences'
|
|
845
996
|
}
|
|
846
997
|
}
|
|
@@ -893,15 +1044,37 @@ function _runLegacyInstallMigrations(runtime, configDir, scope = 'global') {
|
|
|
893
1044
|
}
|
|
894
1045
|
}
|
|
895
1046
|
// Hermes: remove pre-#2841 flat skills/gsd-*/ entries that lived alongside
|
|
896
|
-
// the new skills/gsd/ nested layout
|
|
1047
|
+
// the new skills/gsd/ nested layout (#5169: `hostBehaviors.legacyFlatSkillsCleanup`).
|
|
1048
|
+
// #5161: skills/ is also Hermes' own skills root, so this runs on every
|
|
1049
|
+
// install against dirs the user may own — remove only what GSD owns, keep
|
|
1050
|
+
// and name the rest.
|
|
897
1051
|
if (hostBehaviorsFor(runtime).legacyFlatSkillsCleanup) {
|
|
898
1052
|
const flatSkillsDir = node_path_1.default.join(configDir, 'skills');
|
|
899
1053
|
if (installFs().existsSync(flatSkillsDir)) {
|
|
1054
|
+
// The flat root's manifest entries were recorded as skills/gsd-<x>/…, not
|
|
1055
|
+
// under Hermes' current nested prefix.
|
|
1056
|
+
const ownsSkillDir = createSkillDirOwnership(runtime, configDir, flatSkillsDir, 'gsd-', { manifestPrefix: 'skills/' });
|
|
1057
|
+
const kept = [];
|
|
900
1058
|
for (const entry of installFs().readdirSync(flatSkillsDir, { withFileTypes: true })) {
|
|
901
|
-
if (entry.
|
|
902
|
-
|
|
1059
|
+
if (!entry.name.startsWith('gsd-'))
|
|
1060
|
+
continue;
|
|
1061
|
+
// A symlink is never removed here (as before); name it when unowned.
|
|
1062
|
+
if (entry.isSymbolicLink()) {
|
|
1063
|
+
if (!ownsSkillDir(entry.name))
|
|
1064
|
+
kept.push(entry.name);
|
|
1065
|
+
continue;
|
|
903
1066
|
}
|
|
1067
|
+
if (!entry.isDirectory())
|
|
1068
|
+
continue;
|
|
1069
|
+
// gsd-dev-preferences is user content even when an old manifest records
|
|
1070
|
+
// it, and nothing here restores it (#2973), so it is never removed.
|
|
1071
|
+
if (!ownsSkillDir(entry.name) || USER_OWNED_SKILL_DIRS.includes(entry.name)) {
|
|
1072
|
+
kept.push(entry.name);
|
|
1073
|
+
continue;
|
|
1074
|
+
}
|
|
1075
|
+
installFs().rmSync(node_path_1.default.join(flatSkillsDir, entry.name), { recursive: true });
|
|
904
1076
|
}
|
|
1077
|
+
_warnPreservedSkillDirs(flatSkillsDir, kept);
|
|
905
1078
|
}
|
|
906
1079
|
// Hermes: bare-stem skills/gsd/<stem>/ cleanup is deferred to AFTER the
|
|
907
1080
|
// layout-driven install loop in installRuntimeArtifacts, where the exact set
|
|
@@ -1117,6 +1290,8 @@ function _runLegacyUninstallCleanup(runtime, configDir, scope = 'global') {
|
|
|
1117
1290
|
*/
|
|
1118
1291
|
function installRuntimeArtifacts(runtime, configDir, scope, resolvedProfile, resolveAttribution = () => undefined, capabilityRegistry, deps = {}) {
|
|
1119
1292
|
return withInstallFs(deps.fs, () => {
|
|
1293
|
+
// #5161: this install's record of the skill dirs it writes starts empty.
|
|
1294
|
+
clearWrittenSkillDirs();
|
|
1120
1295
|
const layout = runtimeArtifactLayout.resolveRuntimeArtifactLayout(runtime, configDir, scope, capabilityRegistry);
|
|
1121
1296
|
// A removed descriptor kind is no longer visited by the layout loop, so it
|
|
1122
1297
|
// cannot prune its own previous output. Clean manifest-proven retired files
|
|
@@ -1253,7 +1428,9 @@ function installRuntimeArtifacts(runtime, configDir, scope, resolvedProfile, res
|
|
|
1253
1428
|
}
|
|
1254
1429
|
installFs().mkdirSync(dest, { recursive: true });
|
|
1255
1430
|
const preserved = [];
|
|
1256
|
-
|
|
1431
|
+
// #5161: keyed on the kind alone, so the non-skills branch below can
|
|
1432
|
+
// never reach a skills dest with the prune that ignores ownership.
|
|
1433
|
+
if (kind.kind === 'skills') {
|
|
1257
1434
|
// Pre-prune: snapshot user-owned content before _removeGsdEntries wipes it,
|
|
1258
1435
|
// then restore after. This preserves user dirs across a wipe-and-replace
|
|
1259
1436
|
// install (#2973 / #3664).
|
|
@@ -1264,24 +1441,37 @@ function installRuntimeArtifacts(runtime, configDir, scope, resolvedProfile, res
|
|
|
1264
1441
|
// gsd-dev-preferences, which GSD does not reinstall from source but must
|
|
1265
1442
|
// survive the prune (#2973).
|
|
1266
1443
|
const toPreserve = new Map(); // dirName -> Map<relPath, Buffer>
|
|
1267
|
-
{
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
continue;
|
|
1275
|
-
const snap = _snapshotDir(skillDir);
|
|
1276
|
-
if (snap.size > 0)
|
|
1277
|
-
toPreserve.set(dirName, snap);
|
|
1278
|
-
}
|
|
1444
|
+
for (const dirName of USER_OWNED_SKILL_DIRS) {
|
|
1445
|
+
const skillDir = node_path_1.default.join(dest, dirName);
|
|
1446
|
+
if (!installFs().existsSync(skillDir))
|
|
1447
|
+
continue;
|
|
1448
|
+
const snap = _snapshotDir(skillDir);
|
|
1449
|
+
if (snap.size > 0)
|
|
1450
|
+
toPreserve.set(dirName, snap);
|
|
1279
1451
|
}
|
|
1280
|
-
|
|
1452
|
+
// #5161: prune only what GSD owns — a dir this run is about to write,
|
|
1453
|
+
// or one createSkillDirOwnership proves GSD's. Any other gsd-* dir is
|
|
1454
|
+
// user-owned or unknown: keep it and name it.
|
|
1455
|
+
const stagedNames = new Set(installFs().existsSync(item.sourceDir) ? installFs().readdirSync(item.sourceDir) : []);
|
|
1456
|
+
const ownsSkillDir = createSkillDirOwnership(runtime, configDir, dest, kind.prefix);
|
|
1457
|
+
// A USER_OWNED_SKILL_DIRS entry is never pruned, even when the manifest
|
|
1458
|
+
// leg owns it: the restore below skips symlinks, so a prune-then-restore
|
|
1459
|
+
// loses a symlinked SKILL.md. The restore remains for prune paths that
|
|
1460
|
+
// do not consult `owns`.
|
|
1461
|
+
const notOwned = _removeGsdEntries(dest, kind, (name) => !USER_OWNED_SKILL_DIRS.includes(name) && (stagedNames.has(name) || ownsSkillDir(name)));
|
|
1462
|
+
_warnPreservedSkillDirs(dest, notOwned);
|
|
1281
1463
|
_copyStaged(item.sourceDir, dest, kind, configDir, runtime);
|
|
1282
|
-
//
|
|
1464
|
+
// The dirs _copyStaged just wrote: each directory child of the stage.
|
|
1465
|
+
recordWrittenSkillDirs(dest, installFs().existsSync(item.sourceDir)
|
|
1466
|
+
? installFs().readdirSync(item.sourceDir, { withFileTypes: true })
|
|
1467
|
+
.filter((e) => e.isDirectory()).map((e) => e.name)
|
|
1468
|
+
: []);
|
|
1469
|
+
// Restore user-owned dirs after the prune+copy — only one a prune
|
|
1470
|
+
// branch that does not consult `owns` actually removed. Writing over
|
|
1471
|
+
// the kept dir would fail on a read-only file the user left there.
|
|
1283
1472
|
for (const [dirName, snap] of toPreserve) {
|
|
1284
|
-
|
|
1473
|
+
if (!installFs().existsSync(node_path_1.default.join(dest, dirName)))
|
|
1474
|
+
_restoreDir(node_path_1.default.join(dest, dirName), snap);
|
|
1285
1475
|
preserved.push(dirName);
|
|
1286
1476
|
}
|
|
1287
1477
|
}
|
|
@@ -1322,7 +1512,10 @@ function installRuntimeArtifacts(runtime, configDir, scope, resolvedProfile, res
|
|
|
1322
1512
|
let hermesBareStemCleanup = false;
|
|
1323
1513
|
if (hostBehaviorsFor(runtime).bareStemSkillsCleanup) {
|
|
1324
1514
|
const nestedGsdDirForCleanup = node_path_1.default.join(configDir, 'skills', 'gsd');
|
|
1325
|
-
|
|
1515
|
+
// gsd-dev-preferences is restored rather than staged, and its legacy bare
|
|
1516
|
+
// dev-preferences/ twin is one this cleanup exists for (#947).
|
|
1517
|
+
const ownsNested = createSkillDirOwnership(runtime, configDir, nestedGsdDirForCleanup, 'gsd-', { includeManifest: false });
|
|
1518
|
+
_removeHermesBareStemDirs(nestedGsdDirForCleanup, (name) => ownsNested(name) || USER_OWNED_SKILL_DIRS.includes(name));
|
|
1326
1519
|
hermesBareStemCleanup = true;
|
|
1327
1520
|
}
|
|
1328
1521
|
// Generic-branch nativePlugin staging (ADR-1239 / #2102 Stage 1): runtimes
|
|
@@ -1427,7 +1620,6 @@ function installOpencodeFamilySkills(runtime, targetDir, rawCommandsDir, pathPre
|
|
|
1427
1620
|
// and lives at <configDir>/skills/gsd-dev-preferences — _removeGsdEntries
|
|
1428
1621
|
// would otherwise wipe it. Mirrors the preservation in installRuntimeArtifacts
|
|
1429
1622
|
// (#2973).
|
|
1430
|
-
const USER_OWNED_SKILL_DIRS = ['gsd-dev-preferences'];
|
|
1431
1623
|
const toPreserve = new Map(); // dirName -> Map<relPath, Buffer>
|
|
1432
1624
|
for (const dirName of USER_OWNED_SKILL_DIRS) {
|
|
1433
1625
|
const skillDir = node_path_1.default.join(dest, dirName);
|
|
@@ -1437,8 +1629,20 @@ function installOpencodeFamilySkills(runtime, targetDir, rawCommandsDir, pathPre
|
|
|
1437
1629
|
if (snap.size > 0)
|
|
1438
1630
|
toPreserve.set(dirName, snap);
|
|
1439
1631
|
}
|
|
1440
|
-
|
|
1632
|
+
// #5161: same ownership gate as installRuntimeArtifacts' skills kind. The
|
|
1633
|
+
// first-party set is rawDir's stems (exactly what this writer is about to
|
|
1634
|
+
// write); third-party capability skills carry the marker.
|
|
1635
|
+
// Same entry filter as the write loop below (a regular `.md` file), so a
|
|
1636
|
+
// name is owned here only if this writer is about to rewrite it.
|
|
1637
|
+
const rawStemNames = new Set(installFs().readdirSync(rawDir, { withFileTypes: true })
|
|
1638
|
+
.filter((e) => e.isFile() && e.name.endsWith('.md'))
|
|
1639
|
+
.map((e) => `${skillsKindEntry.prefix}${e.name.slice(0, -3)}`));
|
|
1640
|
+
const ownsSkillDir = createSkillDirOwnership(runtime, targetDir, dest, skillsKindEntry.prefix);
|
|
1641
|
+
_warnPreservedSkillDirs(dest,
|
|
1642
|
+
// Never pruned, as in installRuntimeArtifacts: the restore skips symlinks.
|
|
1643
|
+
_removeGsdEntries(dest, skillsKindEntry, (name) => !USER_OWNED_SKILL_DIRS.includes(name) && (rawStemNames.has(name) || ownsSkillDir(name))));
|
|
1441
1644
|
let count = 0;
|
|
1645
|
+
const written = new Set();
|
|
1442
1646
|
const firstPartyStems = new Set();
|
|
1443
1647
|
for (const entry of installFs().readdirSync(rawDir, { withFileTypes: true })) {
|
|
1444
1648
|
if (!entry.isFile() || !entry.name.endsWith('.md'))
|
|
@@ -1453,6 +1657,7 @@ function installOpencodeFamilySkills(runtime, targetDir, rawCommandsDir, pathPre
|
|
|
1453
1657
|
const skillDir = node_path_1.default.join(dest, skillName);
|
|
1454
1658
|
installFs().mkdirSync(skillDir, { recursive: true });
|
|
1455
1659
|
installFs().writeFileSync(node_path_1.default.join(skillDir, 'SKILL.md'), content);
|
|
1660
|
+
written.add(skillName);
|
|
1456
1661
|
count++;
|
|
1457
1662
|
}
|
|
1458
1663
|
// #2362: materialize installed THIRD-PARTY capability skills, bound to their
|
|
@@ -1506,13 +1711,17 @@ function installOpencodeFamilySkills(runtime, targetDir, rawCommandsDir, pathPre
|
|
|
1506
1711
|
// capability is uninstalled/unsurfaced and no longer appears in any
|
|
1507
1712
|
// registry view.
|
|
1508
1713
|
installFs().writeFileSync(node_path_1.default.join(skillDir, installProfiles.CAPABILITY_SKILL_MARKER), found.capId + '\n', 'utf8');
|
|
1714
|
+
written.add(skillName);
|
|
1509
1715
|
count++;
|
|
1510
1716
|
}
|
|
1511
1717
|
}
|
|
1512
|
-
// Restore user-owned dirs after the prune+copy
|
|
1718
|
+
// Restore user-owned dirs after the prune+copy, only where a prune removed
|
|
1719
|
+
// one; the kept dir is left untouched (it may hold read-only files).
|
|
1513
1720
|
for (const [dirName, snap] of toPreserve) {
|
|
1514
|
-
|
|
1721
|
+
if (!installFs().existsSync(node_path_1.default.join(dest, dirName)))
|
|
1722
|
+
_restoreDir(node_path_1.default.join(dest, dirName), snap);
|
|
1515
1723
|
}
|
|
1724
|
+
recordWrittenSkillDirs(dest, written);
|
|
1516
1725
|
return count;
|
|
1517
1726
|
}
|
|
1518
1727
|
// ---------------------------------------------------------------------------
|
|
@@ -1544,7 +1753,7 @@ function installOpencodeFamilySkills(runtime, targetDir, rawCommandsDir, pathPre
|
|
|
1544
1753
|
* (`layout.kinds` → `agentsKindEntry.stage(resolvedProfile, agentCtx)` →
|
|
1545
1754
|
* `_copyStaged`), rather than forking a second agent-staging pipeline. A
|
|
1546
1755
|
* runtime/scope whose resolved layout declares no `agents` kind at all
|
|
1547
|
-
* (e.g. pi, whose `artifactLayout` is
|
|
1756
|
+
* (e.g. pi, whose `artifactLayout` is skills-only for both scopes, #5547) is a no-op
|
|
1548
1757
|
* (`null`) — mirrors `installOpencodeFamilySkills`'s own
|
|
1549
1758
|
* `if (!skillsKindEntry) return 0` contract.
|
|
1550
1759
|
*
|
|
@@ -2038,6 +2247,11 @@ module.exports = {
|
|
|
2038
2247
|
_runLegacyInstallMigrations,
|
|
2039
2248
|
_runLegacyUninstallCleanup,
|
|
2040
2249
|
_removeGsdEntries,
|
|
2250
|
+
createSkillDirOwnership,
|
|
2251
|
+
recordWrittenSkillDirs,
|
|
2252
|
+
clearWrittenSkillDirs,
|
|
2253
|
+
_warnPreservedSkillDirs,
|
|
2254
|
+
USER_OWNED_SKILL_DIRS,
|
|
2041
2255
|
_snapshotDir,
|
|
2042
2256
|
_restoreDir,
|
|
2043
2257
|
_removeHermesBareStemDirs,
|
|
@@ -34,6 +34,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
34
34
|
*/
|
|
35
35
|
const node_path_1 = __importDefault(require("node:path"));
|
|
36
36
|
const node_os_1 = __importDefault(require("node:os"));
|
|
37
|
+
const runtime_homes_cjs_1 = require("./runtime-homes.cjs");
|
|
37
38
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- install-fs-adapter.cjs is an export= CommonJS module
|
|
38
39
|
const installFsAdapter = require("./install-fs-adapter.cjs");
|
|
39
40
|
const { installFs } = installFsAdapter;
|
|
@@ -57,7 +58,7 @@ const { resolveTierEntry: gsdResolveTierEntry, resolveModelPolicy: gsdResolveMod
|
|
|
57
58
|
*/
|
|
58
59
|
function readGsdGlobalModelOverrides(options = {}) {
|
|
59
60
|
try {
|
|
60
|
-
const home = options.homedir ? options.homedir() : node_os_1.default.homedir();
|
|
61
|
+
const home = (0, runtime_homes_cjs_1.resolveGsdHome)(options.homedir ? options.homedir() : node_os_1.default.homedir());
|
|
61
62
|
const defaultsPath = node_path_1.default.join(home, '.gsd', 'defaults.json');
|
|
62
63
|
if (!installFs().existsSync(defaultsPath))
|
|
63
64
|
return null;
|
|
@@ -139,7 +140,7 @@ function readGsdAgentTools(config) {
|
|
|
139
140
|
* model override resolver.
|
|
140
141
|
*/
|
|
141
142
|
function readGsdEffectiveAgentTools(targetDir = null, options = {}) {
|
|
142
|
-
const home = options.homedir ? options.homedir() : node_os_1.default.homedir();
|
|
143
|
+
const home = (0, runtime_homes_cjs_1.resolveGsdHome)(options.homedir ? options.homedir() : node_os_1.default.homedir());
|
|
143
144
|
const globalConfig = _readGsdConfigFile(node_path_1.default.join(home, '.gsd', 'defaults.json'), 'global defaults');
|
|
144
145
|
let projectConfig = null;
|
|
145
146
|
if (targetDir) {
|
|
@@ -170,7 +171,7 @@ function readGsdEffectiveAgentTools(targetDir = null, options = {}) {
|
|
|
170
171
|
* baked, letting the runtime's own default/session model govern).
|
|
171
172
|
*/
|
|
172
173
|
function readGsdRuntimeProfileResolver(targetDir = null) {
|
|
173
|
-
const homeDefaults = _readGsdConfigFile(node_path_1.default.join(
|
|
174
|
+
const homeDefaults = _readGsdConfigFile(node_path_1.default.join((0, runtime_homes_cjs_1.resolveGsdHome)(), '.gsd', 'defaults.json'), '~/.gsd/defaults.json');
|
|
174
175
|
// #2875 defect fix (Generative Fix Divergence): same shared walk as
|
|
175
176
|
// readGsdEffectiveModelOverrides above — see that call site's comment.
|
|
176
177
|
let projectConfig = null;
|
|
@@ -31,6 +31,8 @@ const frontmatter_fence_cjs_1 = require("./frontmatter-fence.cjs");
|
|
|
31
31
|
// #2322: reuse the existing pure path-containment seam (ADR-1239 Phase C-2)
|
|
32
32
|
// instead of hand-rolling a new traversal check for capability skill stems.
|
|
33
33
|
const external_descriptor_trust_cjs_1 = require("./external-descriptor-trust.cjs");
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports -- capability-ledger.cjs is an export= CommonJS module
|
|
35
|
+
const capabilityLedger = require("./capability-ledger.cjs");
|
|
34
36
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
35
37
|
const conversionModule = require("./runtime-artifact-conversion.cjs");
|
|
36
38
|
const { applyAgentPathRewrites: _applyAgentPathRewrites, processAttribution: _processAttribution, normalizeAgentBodyForRuntime: _normalizeAgentBodyForRuntime, readGsdCommandNames: _readGsdCommandNames, deriveAgentName: _deriveAgentName, applyAgentFrontmatterExtensions: _applyAgentFrontmatterExtensions, appendAgentTools: _appendAgentTools, } = conversionModule;
|
|
@@ -300,7 +302,7 @@ function _capabilitySkillsForMode(mode, registry) {
|
|
|
300
302
|
/**
|
|
301
303
|
* Resolve a profile (or composed profiles) to a typed result object.
|
|
302
304
|
*/
|
|
303
|
-
function resolveProfile({ modes, manifest, _profilesOverride, registry } = {}) {
|
|
305
|
+
function resolveProfile({ modes, manifest, _profilesOverride, registry, agentManifest } = {}) {
|
|
304
306
|
const profiles = _profilesOverride || PROFILES;
|
|
305
307
|
const activeModes = (modes && modes.length > 0) ? modes : ['full'];
|
|
306
308
|
const normalizedModes = activeModes
|
|
@@ -335,10 +337,13 @@ function resolveProfile({ modes, manifest, _profilesOverride, registry } = {}) {
|
|
|
335
337
|
}
|
|
336
338
|
// Derive agents: union of all agent names referenced in the body text of
|
|
337
339
|
// every skill in unionSkills. Agent names are stored in the manifest under
|
|
338
|
-
// _calls_agents_<stem> keys (populated by loadSkillsManifest).
|
|
340
|
+
// _calls_agents_<stem> keys (populated by loadSkillsManifest). #5503: read from
|
|
341
|
+
// `agentManifest` when given, so a profile that skips the skill closure still
|
|
342
|
+
// stages the agents its own skills spawn.
|
|
343
|
+
const agentMan = agentManifest || man;
|
|
339
344
|
const unionAgents = new Set();
|
|
340
345
|
for (const skillStem of unionSkills) {
|
|
341
|
-
const agentRefs =
|
|
346
|
+
const agentRefs = agentMan.get(`_calls_agents_${skillStem}`) || [];
|
|
342
347
|
for (const agentStem of agentRefs) {
|
|
343
348
|
unionAgents.add(agentStem);
|
|
344
349
|
}
|
|
@@ -748,9 +753,9 @@ function readInstalledCapabilitySkill(stem, registry) {
|
|
|
748
753
|
// installed as a capability skill (epic #4636).
|
|
749
754
|
if (node_fs_1.default.lstatSync(skillPath).isSymbolicLink())
|
|
750
755
|
return null;
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
return { capId, content
|
|
756
|
+
// #5121: the bounded regular-file read — a FIFO/device/oversized SKILL.md is skipped like a missing one.
|
|
757
|
+
const content = capabilityLedger.readSkillFile(skillPath);
|
|
758
|
+
return content === null ? null : { capId, content };
|
|
754
759
|
}
|
|
755
760
|
catch {
|
|
756
761
|
return null; // missing / unreadable / corrupt entry -> skip
|
|
@@ -938,7 +943,7 @@ function stageSkillsForRuntimeAsSkills(srcCommandsDir, resolvedProfile, converte
|
|
|
938
943
|
* @param isGlobal install scope passed through to the converter
|
|
939
944
|
* @param agentCtx optional cross-cutting context (ADR-1235 §1)
|
|
940
945
|
*/
|
|
941
|
-
function stageAgentsForRuntimeWithConverter(srcAgentsDir, resolvedProfile, converter, isGlobal = false, agentCtx) {
|
|
946
|
+
function stageAgentsForRuntimeWithConverter(srcAgentsDir, resolvedProfile, converter, isGlobal = false, agentCtx, excludeSuffixes) {
|
|
942
947
|
if (!installFs().existsSync(srcAgentsDir))
|
|
943
948
|
return srcAgentsDir;
|
|
944
949
|
const stageDir = mkInstallTempDir('gsd-profile-runtime-agents-');
|
|
@@ -974,6 +979,8 @@ function stageAgentsForRuntimeWithConverter(srcAgentsDir, resolvedProfile, conve
|
|
|
974
979
|
continue;
|
|
975
980
|
if (!entry.name.endsWith('.md'))
|
|
976
981
|
continue;
|
|
982
|
+
if (excludeSuffixes && excludeSuffixes.some((s) => entry.name.endsWith(s)))
|
|
983
|
+
continue;
|
|
977
984
|
// For tiered profiles, gate by agent stem (full filename without extension).
|
|
978
985
|
if (resolvedProfile.skills !== '*') {
|
|
979
986
|
const stem = entry.name.slice(0, -3);
|
|
@@ -51,6 +51,8 @@ exports.BUNDLED_GSD_HOOK_FILES = Object.freeze(new Set([
|
|
|
51
51
|
// #3662: portable node resolver staged into hooks/ (not itself a lifecycle
|
|
52
52
|
// hook — managed JS hook commands route through it under --portable-hooks).
|
|
53
53
|
'hooks/gsd-node-runner.sh',
|
|
54
|
+
// #5465: SessionStart PATH persistence through $CLAUDE_ENV_FILE.
|
|
55
|
+
'hooks/gsd-path-export.js',
|
|
54
56
|
'hooks/gsd-phase-boundary.sh',
|
|
55
57
|
'hooks/gsd-prompt-guard.js',
|
|
56
58
|
'hooks/gsd-read-guard.js',
|