@opengsd/gsd-core 1.9.1 → 1.11.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 -3
- package/.opencode/plugins/gsd-core.js +8 -1
- package/agents/gsd-code-fixer.md +27 -3
- package/agents/gsd-debug-session-manager.md +11 -0
- package/agents/gsd-debugger.md +12 -246
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-executor.md +12 -10
- package/agents/gsd-integration-checker.md +3 -0
- package/agents/gsd-mempalace-curator.md +5 -2
- package/agents/gsd-phase-researcher.md +20 -1
- package/agents/gsd-plan-checker.md +46 -0
- package/agents/gsd-planner.md +49 -54
- package/agents/gsd-roadmapper.md +21 -3
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +26 -73
- package/bin/install.js +1272 -1238
- package/bin/lib/ui-safety-gate.cjs +2 -0
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/mempalace-capture.md +2 -2
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +2 -2
- package/commands/gsd/plan-phase.md +1 -1
- package/commands/gsd/quick.md +1 -1
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +1009 -115
- package/gsd-core/bin/lib/active-workstream-store.cjs +153 -12
- package/gsd-core/bin/lib/agent-install-check.cjs +268 -38
- package/gsd-core/bin/lib/api-coverage.cjs +123 -5
- package/gsd-core/bin/lib/artifacts.cjs +3 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +2 -4
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +926 -202
- package/gsd-core/bin/lib/broken-windows.cjs +36 -6
- package/gsd-core/bin/lib/capability-consent.cjs +149 -15
- package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
- package/gsd-core/bin/lib/capability-registry.cjs +608 -148
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +507 -24
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +114 -38
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/codex-agent-toml.cjs +329 -0
- package/gsd-core/bin/lib/command-aliases.cjs +94 -0
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/commands.cjs +665 -99
- package/gsd-core/bin/lib/commonjs-marker.cjs +142 -0
- package/gsd-core/bin/lib/complexity-trigger.cjs +1172 -0
- package/gsd-core/bin/lib/config-loader.cjs +76 -0
- package/gsd-core/bin/lib/config.cjs +22 -2
- package/gsd-core/bin/lib/context-composer.cjs +278 -0
- package/gsd-core/bin/lib/context-predicates.cjs +506 -0
- package/gsd-core/bin/lib/core-utils.cjs +217 -40
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/docs.cjs +3 -2
- package/gsd-core/bin/lib/external-job.cjs +19 -4
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +239 -32
- package/gsd-core/bin/lib/gap-checker.cjs +68 -7
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +57 -6
- package/gsd-core/bin/lib/git-base-branch.cjs +160 -15
- package/gsd-core/bin/lib/graphify.cjs +142 -27
- package/gsd-core/bin/lib/gsd2-import.cjs +37 -5
- package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +145 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +265 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +173 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +431 -0
- package/gsd-core/bin/lib/host-integration.cjs +13 -1
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init-command-router.cjs +83 -8
- package/gsd-core/bin/lib/init.cjs +1325 -169
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +805 -264
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +203 -0
- package/gsd-core/bin/lib/install-profiles.cjs +160 -57
- package/gsd-core/bin/lib/install-scope.cjs +270 -0
- package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
- package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
- package/gsd-core/bin/lib/installer-migration-authoring.cjs +3 -1
- package/gsd-core/bin/lib/installer-migration-report.cjs +4 -0
- package/gsd-core/bin/lib/installer-migrations/007-retire-config-root-commonjs-marker.cjs +149 -0
- package/gsd-core/bin/lib/installer-migrations/008-cursor-retire-commands-surface.cjs +55 -0
- package/gsd-core/bin/lib/installer-migrations/009-pi-retire-reserved-hooks-dir.cjs +199 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +206 -13
- package/gsd-core/bin/lib/io.cjs +38 -3
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +8 -1
- package/gsd-core/bin/lib/markdown-table.cjs +133 -20
- package/gsd-core/bin/lib/mcp-catalog.cjs +518 -0
- package/gsd-core/bin/lib/mcp-server.cjs +135 -3
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +821 -109
- package/gsd-core/bin/lib/model-catalog.cjs +59 -1
- package/gsd-core/bin/lib/model-resolver.cjs +183 -40
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +1 -1
- package/gsd-core/bin/lib/phase-id.cjs +507 -36
- package/gsd-core/bin/lib/phase-lifecycle.cjs +28 -3
- package/gsd-core/bin/lib/phase-locator.cjs +258 -58
- package/gsd-core/bin/lib/phase.cjs +891 -156
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +303 -0
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +86 -2
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +890 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +60 -6
- package/gsd-core/bin/lib/probe-core.cjs +1 -1
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/prompt-budget.cjs +128 -165
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +740 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +85 -0
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +108 -0
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +447 -68
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +76 -9
- package/gsd-core/bin/lib/roadmap-parser.cjs +1035 -194
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +405 -84
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +795 -100
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +440 -57
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +220 -41
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +220 -44
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +27 -9
- package/gsd-core/bin/lib/section-manifest.cjs +209 -0
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +388 -30
- package/gsd-core/bin/lib/smart-entry.cjs +154 -22
- package/gsd-core/bin/lib/state-command-router.cjs +5 -1
- package/gsd-core/bin/lib/state-document.cjs +152 -8
- package/gsd-core/bin/lib/state-transition.cjs +424 -105
- package/gsd-core/bin/lib/state.cjs +1927 -401
- package/gsd-core/bin/lib/surface.cjs +35 -10
- package/gsd-core/bin/lib/text-lines.cjs +80 -0
- package/gsd-core/bin/lib/token-scanner.cjs +76 -0
- package/gsd-core/bin/lib/uat-predicate.cjs +20 -4
- package/gsd-core/bin/lib/uat.cjs +706 -64
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +14 -5
- package/gsd-core/bin/lib/unusable-input.cjs +33 -0
- package/gsd-core/bin/lib/update-context.cjs +8 -2
- package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
- package/gsd-core/bin/lib/validate.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +37 -0
- package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
- package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +287 -20
- package/gsd-core/bin/lib/verify.cjs +368 -880
- package/gsd-core/bin/lib/workflow-fragments.cjs +557 -0
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +203 -19
- package/gsd-core/bin/lib/workstream-inventory.cjs +576 -31
- package/gsd-core/bin/lib/workstream.cjs +8 -2
- package/gsd-core/bin/lib/worktree-base-ref.cjs +50 -6
- package/gsd-core/bin/lib/worktree-safety.cjs +450 -125
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +9 -1
- package/gsd-core/references/agent-contracts.md +43 -26
- package/gsd-core/references/artifact-types.md +10 -3
- package/gsd-core/references/autonomous-ui-design-contract.md +42 -0
- package/gsd-core/references/checkpoints.md +2 -2
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/debugger-techniques.md +255 -0
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/execute-mvp-tdd.md +3 -3
- package/gsd-core/references/execute-phase-between-wave-reset.md +6 -2
- package/gsd-core/references/execute-phase-context-guard.md +1 -1
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/execute-phase-wave-guard.md +6 -2
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-planning-commit.md +2 -1
- package/gsd-core/references/loop-hook-dispatch.md +39 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planning-config.md +8 -6
- package/gsd-core/references/research-documentation-lookup.md +5 -3
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +8 -7
- package/gsd-core/references/universal-anti-patterns.md +3 -3
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verifier-wiring-patterns.md +100 -0
- package/gsd-core/references/verify-mvp-mode.md +1 -1
- package/gsd-core/references/workstream-flag.md +22 -6
- package/gsd-core/references/worktree-branch-check.md +2 -2
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +2 -4
- package/gsd-core/templates/state.md +4 -4
- package/gsd-core/templates/summary-complex.md +2 -0
- package/gsd-core/templates/summary-minimal.md +2 -0
- package/gsd-core/templates/summary-standard.md +2 -0
- package/gsd-core/templates/summary.md +2 -0
- package/gsd-core/templates/verification-report.md +9 -1
- package/gsd-core/workflows/ai-integration-phase.md +9 -11
- package/gsd-core/workflows/audit-milestone.md +3 -0
- package/gsd-core/workflows/autonomous/steps/converge-banner.md +1 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-bg.md +11 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-inline.md +7 -0
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +21 -0
- package/gsd-core/workflows/autonomous/steps/converge-loop.md +7 -0
- package/gsd-core/workflows/autonomous.md +33 -70
- package/gsd-core/workflows/cleanup.md +62 -3
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +39 -0
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +93 -0
- package/gsd-core/workflows/code-review-fix.md +37 -10
- package/gsd-core/workflows/code-review.md +74 -166
- package/gsd-core/workflows/complete-milestone/steps/git-tag.md +29 -0
- package/gsd-core/workflows/complete-milestone.md +160 -95
- package/gsd-core/workflows/debug.md +16 -17
- package/gsd-core/workflows/diagnose-issues.md +56 -8
- package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -1
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +15 -0
- package/gsd-core/workflows/discuss-phase-assumptions.md +7 -17
- package/gsd-core/workflows/docs-update/steps/dispatch-monorepo-packages.md +51 -0
- package/gsd-core/workflows/docs-update.md +8 -51
- package/gsd-core/workflows/edit-phase.md +26 -1
- package/gsd-core/workflows/eval-review.md +3 -5
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +64 -7
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +50 -0
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +31 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +42 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +43 -37
- package/gsd-core/workflows/execute-phase.md +103 -187
- package/gsd-core/workflows/execute-plan.md +36 -4
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/health.md +73 -4
- package/gsd-core/workflows/help/modes/full.md +6 -1
- package/gsd-core/workflows/import.md +4 -4
- package/gsd-core/workflows/ingest-docs.md +7 -6
- package/gsd-core/workflows/mvp-phase.md +6 -3
- package/gsd-core/workflows/new-milestone/steps/project-md-milestone-write.md +16 -0
- package/gsd-core/workflows/new-milestone/steps/reset-phase-safety.md +19 -0
- package/gsd-core/workflows/new-milestone.md +35 -47
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +176 -0
- package/gsd-core/workflows/new-project/steps/auto-mode-detection.md +32 -0
- package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +18 -0
- package/gsd-core/workflows/new-project.md +27 -240
- package/gsd-core/workflows/next.md +12 -0
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +15 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +110 -0
- package/gsd-core/workflows/plan-phase/steps/prd-express-gate.md +8 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-early-exit.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-modifiers.md +16 -0
- package/gsd-core/workflows/plan-phase/steps/reviews-prerequisite.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +149 -0
- package/gsd-core/workflows/plan-phase.md +89 -209
- package/gsd-core/workflows/plan-review-convergence.md +50 -2
- package/gsd-core/workflows/progress/steps/forensic-audit.md +125 -0
- package/gsd-core/workflows/progress/steps/mvp-display.md +18 -0
- package/gsd-core/workflows/progress.md +45 -159
- package/gsd-core/workflows/quick/steps/discussion-phase.md +124 -0
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +111 -0
- package/gsd-core/workflows/quick/steps/quick-verification.md +67 -0
- package/gsd-core/workflows/quick/steps/research-phase.md +72 -0
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +37 -0
- package/gsd-core/workflows/quick.md +55 -405
- package/gsd-core/workflows/resume-project.md +3 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-1.md +4 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-2.md +3 -0
- package/gsd-core/workflows/review.md +41 -13
- package/gsd-core/workflows/section-manifest.json +219 -0
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings.md +66 -2
- package/gsd-core/workflows/ship.md +104 -44
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/spec-phase.md +41 -20
- package/gsd-core/workflows/spike-wrap-up.md +20 -5
- package/gsd-core/workflows/spike.md +50 -16
- package/gsd-core/workflows/sync-skills.md +106 -13
- package/gsd-core/workflows/transition/steps/workstream-collision-check.md +17 -0
- package/gsd-core/workflows/transition.md +53 -31
- package/gsd-core/workflows/ui-phase.md +13 -12
- package/gsd-core/workflows/ui-review.md +2 -2
- package/gsd-core/workflows/update/steps/channel-banner.md +7 -0
- package/gsd-core/workflows/update.md +19 -8
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +36 -0
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +21 -0
- package/gsd-core/workflows/verify-work.md +17 -65
- package/hooks/dist/gsd-agent-isolation-guard.js +517 -0
- package/hooks/dist/gsd-check-update-worker.js +64 -12
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +0 -3
- package/hooks/dist/gsd-cursor-subagent-start.js +607 -26
- package/hooks/dist/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/dist/gsd-prompt-guard.js +21 -20
- package/hooks/dist/gsd-read-injection-scanner.js +45 -24
- package/hooks/dist/gsd-statusline.js +90 -6
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-workflow-guard.js +134 -36
- package/hooks/dist/gsd-worktree-path-guard.js +2 -1
- package/hooks/dist/gsd-write-guard.js +359 -0
- package/hooks/dist/lib/git-cmd.js +92 -59
- package/hooks/dist/lib/injection-patterns.js +45 -0
- package/hooks/dist/lib/isolation-deny-reason.js +39 -0
- package/hooks/dist/lib/isolation-sentinel.js +277 -0
- package/hooks/dist/managed-hooks-registry.cjs +2 -0
- package/hooks/gsd-agent-isolation-guard.js +517 -0
- package/hooks/gsd-check-update-worker.js +64 -12
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-cursor-pre-tool.js +0 -3
- package/hooks/gsd-cursor-subagent-start.js +607 -26
- package/hooks/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/gsd-prompt-guard.js +21 -20
- package/hooks/gsd-read-injection-scanner.js +45 -24
- package/hooks/gsd-statusline.js +90 -6
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-workflow-guard.js +134 -36
- package/hooks/gsd-worktree-path-guard.js +2 -1
- package/hooks/gsd-write-guard.js +359 -0
- package/hooks/hooks.json +12 -0
- package/hooks/lib/git-cmd.js +92 -59
- package/hooks/lib/injection-patterns.js +45 -0
- package/hooks/lib/isolation-deny-reason.js +39 -0
- package/hooks/lib/isolation-sentinel.js +277 -0
- package/hooks/managed-hooks-registry.cjs +2 -0
- package/package.json +31 -10
- package/pi/gsd.cjs +71 -12
- package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
- package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
- package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
- package/scripts/build-hooks.js +9 -0
- package/scripts/changeset/lint.cjs +68 -6
- package/scripts/changeset/serialize.cjs +5 -1
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/ci-test-scope.cjs +19 -2
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-matrix.cjs +1 -1
- package/scripts/gen-capability-registry.cjs +3 -15
- package/scripts/gen-context-index.cjs +439 -0
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-inventory-manifest.cjs +150 -4
- package/scripts/gen-loop-host-contract.cjs +4 -24
- package/scripts/gen-prompt-budget-parity-corpus.cjs +645 -0
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/gen-section-manifest.cjs +638 -0
- package/scripts/generate-package-identity.cjs +4 -2
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/drift-scan.cjs +278 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +15 -54
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
- package/scripts/lint-canary-version-leak.cjs +73 -0
- package/scripts/lint-command-contract.cjs +96 -13
- package/scripts/lint-compiled-artifact-sync.cjs +6 -1
- package/scripts/lint-completion-predicate-drift.cjs +933 -0
- package/scripts/lint-completion-ratio-drift.cjs +214 -0
- package/scripts/lint-default-flip-documentation.cjs +193 -0
- package/scripts/lint-docs-command-form.cjs +195 -0
- package/scripts/lint-docs-required.cjs +9 -1
- package/scripts/lint-emitted-drift-ack.cjs +215 -20
- package/scripts/lint-eslint-glob-coverage.allowlist.json +34 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/lint-example-parser-parity.cjs +395 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +404 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-phase-enumeration-drift.cjs +479 -0
- package/scripts/lint-plan-count-drift.cjs +318 -0
- package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
- package/scripts/lint-planning-prompt-drift.cjs +434 -0
- package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
- package/scripts/lint-regression-test-names.cjs +15 -13
- package/scripts/lint-removed-but-needed.cjs +320 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +1045 -0
- package/scripts/lint-test-file-count.allowlist.json +40 -3
- package/scripts/lint-unreachable-guard-drift.cjs +843 -0
- package/scripts/lint-vendored-deps.cjs +124 -0
- package/scripts/mutation-matrix.cjs +13 -0
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +52 -6
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/state-write-path-drift-baseline.json +19 -0
- package/scripts/sync-runtime-launcher.cjs +2 -4
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +2 -2
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +2 -2
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +1 -2
- package/skills/gsd-progress/SKILL.md +0 -1
- package/skills/gsd-quick/SKILL.md +1 -1
- package/skills/gsd-review-backlog/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +0 -1
- package/skills/gsd-verify-work/SKILL.md +1 -1
- package/vscode/package.json +1 -1
- package/gsd-core/workflows/discovery-phase.md +0 -298
- package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
- package/gsd-core/workflows/verify-phase.md +0 -577
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/gen-emitted-baseline.cjs +0 -145
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1050
|
@@ -13,13 +13,33 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
14
14
|
const node_path_1 = __importDefault(require("node:path"));
|
|
15
15
|
const node_os_1 = __importDefault(require("node:os"));
|
|
16
|
+
// #2874 (ADR-58 cleanup phase): route the staging functions' fs calls
|
|
17
|
+
// through the installRuntimeArtifacts call tree's injectable seam — see
|
|
18
|
+
// install-fs-adapter.cts's module doc. Resolves to real `node:fs` unless the
|
|
19
|
+
// top-level installRuntimeArtifacts call injected a `deps.fs`. Only the
|
|
20
|
+
// staging functions reachable FROM that call tree are routed
|
|
21
|
+
// (stageSkillsForProfile / stageAgentsForProfile /
|
|
22
|
+
// stageAgentsForRuntimeWithConverter / stageSkillsForRuntimeAsSkills /
|
|
23
|
+
// stageCommandsForRuntimeFlat / buildNamespaceBundleMap) — the profile-marker
|
|
24
|
+
// and manifest-loading helpers below are not on that call tree and keep
|
|
25
|
+
// using real `fs` directly.
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
27
|
+
const installFsAdapter = require("./install-fs-adapter.cjs");
|
|
28
|
+
const { installFs, mkInstallTempDir } = installFsAdapter;
|
|
16
29
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
17
30
|
// #2322: reuse the existing pure path-containment seam (ADR-1239 Phase C-2)
|
|
18
31
|
// instead of hand-rolling a new traversal check for capability skill stems.
|
|
19
32
|
const external_descriptor_trust_cjs_1 = require("./external-descriptor-trust.cjs");
|
|
20
33
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
21
34
|
const conversionModule = require("./runtime-artifact-conversion.cjs");
|
|
22
|
-
const { applyAgentPathRewrites: _applyAgentPathRewrites, processAttribution: _processAttribution, normalizeAgentBodyForRuntime: _normalizeAgentBodyForRuntime, readGsdCommandNames: _readGsdCommandNames, } = conversionModule;
|
|
35
|
+
const { applyAgentPathRewrites: _applyAgentPathRewrites, processAttribution: _processAttribution, normalizeAgentBodyForRuntime: _normalizeAgentBodyForRuntime, readGsdCommandNames: _readGsdCommandNames, deriveAgentName: _deriveAgentName, applyAgentFrontmatterExtensions: _applyAgentFrontmatterExtensions, } = conversionModule;
|
|
36
|
+
// #2995 (epic #1671 Phase 6.4): agent bodies join the fragment model. Markers are
|
|
37
|
+
// stripped at emit BEFORE any path rewrite or converter runs, so a `.claude/` ->
|
|
38
|
+
// `.windsurf/` regex can never reach inside a marker attribute and corrupt it —
|
|
39
|
+
// the same ordering #2930 established for workflows.
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
41
|
+
const workflowFragmentsModule = require("./workflow-fragments.cjs");
|
|
42
|
+
const { composeWorkflow: _composeWorkflow } = workflowFragmentsModule;
|
|
23
43
|
// ---------------------------------------------------------------------------
|
|
24
44
|
// Profile definitions
|
|
25
45
|
// ---------------------------------------------------------------------------
|
|
@@ -257,10 +277,41 @@ function resolveProfile({ modes, manifest, _profilesOverride, registry } = {}) {
|
|
|
257
277
|
// site to track its own cleanup handle.
|
|
258
278
|
const STAGED_DIRS = new Set();
|
|
259
279
|
let exitHandlerRegistered = false;
|
|
280
|
+
// #2874 leak-fix: `cleanupStagedSkills` runs at process exit — AFTER
|
|
281
|
+
// `withInstallFs` has already restored `current` back to the real adapter
|
|
282
|
+
// (install-fs-adapter.cts's module doc, "SYNCHRONOUS-ONLY / RE-ENTRANCY
|
|
283
|
+
// ASSUMPTION" — extended there to reference this map). A dir staged during a
|
|
284
|
+
// fake-adapter call must be cleaned up with THAT SAME fake adapter, not with
|
|
285
|
+
// whatever is ambiently active later, or an exit handler would perform real
|
|
286
|
+
// filesystem IO on a path that only ever existed in the fake's in-memory
|
|
287
|
+
// store. Capturing the adapter OBJECT `installFs()` returns at registration
|
|
288
|
+
// time (not the ambient `current` variable, which changes) means cleanup
|
|
289
|
+
// always replays the exact adapter that created the path. Dirs added to
|
|
290
|
+
// STAGED_DIRS without going through `registerStagedDir` (the deprecated
|
|
291
|
+
// `stageSkillsForMode`, which creates its stage dir via raw `fs.mkdtempSync`
|
|
292
|
+
// and was never on the injectable seam) have no entry here and fall back to
|
|
293
|
+
// real `fs.rmSync` below — the same real fs it always used to create them.
|
|
294
|
+
const STAGED_DIR_ADAPTERS = new Map();
|
|
295
|
+
/**
|
|
296
|
+
* Register a dir just staged through the injectable seam (`installFs()`) for
|
|
297
|
+
* exit-time cleanup, capturing the adapter that staged it alongside the path.
|
|
298
|
+
* See `STAGED_DIR_ADAPTERS`'s comment for why the capture matters.
|
|
299
|
+
*/
|
|
300
|
+
function registerStagedDir(dir) {
|
|
301
|
+
STAGED_DIRS.add(dir);
|
|
302
|
+
STAGED_DIR_ADAPTERS.set(dir, installFs());
|
|
303
|
+
ensureExitCleanup();
|
|
304
|
+
}
|
|
260
305
|
function cleanupStagedSkills() {
|
|
261
306
|
for (const dir of STAGED_DIRS) {
|
|
307
|
+
const adapter = STAGED_DIR_ADAPTERS.get(dir);
|
|
262
308
|
try {
|
|
263
|
-
|
|
309
|
+
if (adapter) {
|
|
310
|
+
adapter.rmSync(dir, { recursive: true, force: true });
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
node_fs_1.default.rmSync(dir, { recursive: true, force: true });
|
|
314
|
+
}
|
|
264
315
|
}
|
|
265
316
|
catch {
|
|
266
317
|
// Best-effort: missing dir or permission error shouldn't crash a
|
|
@@ -268,6 +319,7 @@ function cleanupStagedSkills() {
|
|
|
268
319
|
}
|
|
269
320
|
}
|
|
270
321
|
STAGED_DIRS.clear();
|
|
322
|
+
STAGED_DIR_ADAPTERS.clear();
|
|
271
323
|
}
|
|
272
324
|
// Signals we register a cleanup handler for in addition to the natural
|
|
273
325
|
// 'exit' event. `process.on('exit')` does NOT fire on these — an installer
|
|
@@ -296,11 +348,11 @@ function ensureExitCleanup() {
|
|
|
296
348
|
function stageSkillsForProfile(srcDir, resolvedProfile) {
|
|
297
349
|
if (resolvedProfile.skills === '*')
|
|
298
350
|
return srcDir;
|
|
299
|
-
if (!
|
|
351
|
+
if (!installFs().existsSync(srcDir))
|
|
300
352
|
return srcDir;
|
|
301
|
-
const stageDir =
|
|
353
|
+
const stageDir = mkInstallTempDir('gsd-profile-skills-');
|
|
302
354
|
try {
|
|
303
|
-
const entries =
|
|
355
|
+
const entries = installFs().readdirSync(srcDir, { withFileTypes: true });
|
|
304
356
|
for (const entry of entries) {
|
|
305
357
|
if (!entry.isFile())
|
|
306
358
|
continue;
|
|
@@ -309,18 +361,17 @@ function stageSkillsForProfile(srcDir, resolvedProfile) {
|
|
|
309
361
|
const stem = entry.name.slice(0, -3);
|
|
310
362
|
if (!(resolvedProfile.skills).has(stem))
|
|
311
363
|
continue;
|
|
312
|
-
|
|
364
|
+
installFs().copyFileSync(node_path_1.default.join(srcDir, entry.name), node_path_1.default.join(stageDir, entry.name));
|
|
313
365
|
}
|
|
314
366
|
}
|
|
315
367
|
catch (err) {
|
|
316
368
|
try {
|
|
317
|
-
|
|
369
|
+
installFs().rmSync(stageDir, { recursive: true, force: true });
|
|
318
370
|
}
|
|
319
371
|
catch { /* best-effort */ }
|
|
320
372
|
throw err;
|
|
321
373
|
}
|
|
322
|
-
|
|
323
|
-
ensureExitCleanup();
|
|
374
|
+
registerStagedDir(stageDir);
|
|
324
375
|
return stageDir;
|
|
325
376
|
}
|
|
326
377
|
/**
|
|
@@ -329,16 +380,29 @@ function stageSkillsForProfile(srcDir, resolvedProfile) {
|
|
|
329
380
|
* For tiered profiles, copies only agents whose full stem (e.g. 'gsd-planner')
|
|
330
381
|
* is in resolvedProfile.agents — which is populated by resolveProfile() from
|
|
331
382
|
* the _calls_agents_* entries in the manifest.
|
|
383
|
+
*
|
|
384
|
+
* ⚠️ RAW STAGER — ITS OUTPUT IS NOT EMISSION-READY (#2995). This stager performs a
|
|
385
|
+
* plain `fs.copyFileSync` and — under the default `full` profile — short-circuits
|
|
386
|
+
* and returns the real source directory unstaged. It does NOT strip `gsd:section`
|
|
387
|
+
* markers. It is still called, by `bin/install.js`'s `_stageAgents`, whose output
|
|
388
|
+
* feeds the inline agent loop and `installCodexConfig`; both of those compose the
|
|
389
|
+
* content themselves before writing, so the raw output never reaches disk. What
|
|
390
|
+
* changed in #2995 is that `agentsKind` and `kimiAgentsKind` no longer use it —
|
|
391
|
+
* they route through `stageAgentsForRuntimeWithConverter`, which composes.
|
|
392
|
+
*
|
|
393
|
+
* The invariant to preserve: anything that takes this function's output and WRITES
|
|
394
|
+
* it as a runtime artifact must call `composeWorkflow` on each file first, or it
|
|
395
|
+
* ships markers verbatim.
|
|
332
396
|
*/
|
|
333
397
|
function stageAgentsForProfile(srcAgentsDir, resolvedProfile) {
|
|
334
398
|
if (resolvedProfile.skills === '*')
|
|
335
399
|
return srcAgentsDir;
|
|
336
|
-
if (!
|
|
400
|
+
if (!installFs().existsSync(srcAgentsDir))
|
|
337
401
|
return srcAgentsDir;
|
|
338
|
-
const stageDir =
|
|
402
|
+
const stageDir = mkInstallTempDir('gsd-profile-agents-');
|
|
339
403
|
try {
|
|
340
404
|
if (resolvedProfile.agents instanceof Set && resolvedProfile.agents.size > 0) {
|
|
341
|
-
const entries =
|
|
405
|
+
const entries = installFs().readdirSync(srcAgentsDir, { withFileTypes: true });
|
|
342
406
|
for (const entry of entries) {
|
|
343
407
|
if (!entry.isFile())
|
|
344
408
|
continue;
|
|
@@ -348,20 +412,19 @@ function stageAgentsForProfile(srcAgentsDir, resolvedProfile) {
|
|
|
348
412
|
const stem = entry.name.slice(0, -3);
|
|
349
413
|
if (!resolvedProfile.agents.has(stem))
|
|
350
414
|
continue;
|
|
351
|
-
|
|
415
|
+
installFs().copyFileSync(node_path_1.default.join(srcAgentsDir, entry.name), node_path_1.default.join(stageDir, entry.name));
|
|
352
416
|
}
|
|
353
417
|
}
|
|
354
418
|
// If agents is empty Set, we produce an empty stageDir (no agents for this profile)
|
|
355
419
|
}
|
|
356
420
|
catch (err) {
|
|
357
421
|
try {
|
|
358
|
-
|
|
422
|
+
installFs().rmSync(stageDir, { recursive: true, force: true });
|
|
359
423
|
}
|
|
360
424
|
catch { /* best-effort */ }
|
|
361
425
|
throw err;
|
|
362
426
|
}
|
|
363
|
-
|
|
364
|
-
ensureExitCleanup();
|
|
427
|
+
registerStagedDir(stageDir);
|
|
365
428
|
return stageDir;
|
|
366
429
|
}
|
|
367
430
|
/**
|
|
@@ -375,10 +438,10 @@ function buildNamespaceBundleMap(srcCommandsDir) {
|
|
|
375
438
|
const routerStems = new Set();
|
|
376
439
|
const routerChildren = new Map();
|
|
377
440
|
const childToRouters = new Map();
|
|
378
|
-
if (!
|
|
441
|
+
if (!installFs().existsSync(srcCommandsDir)) {
|
|
379
442
|
return { routerStems, routerChildren, childToRouters };
|
|
380
443
|
}
|
|
381
|
-
for (const entry of
|
|
444
|
+
for (const entry of installFs().readdirSync(srcCommandsDir, { withFileTypes: true })) {
|
|
382
445
|
if (!entry.isFile() || !entry.name.endsWith('.md'))
|
|
383
446
|
continue;
|
|
384
447
|
if (!entry.name.startsWith('ns-'))
|
|
@@ -386,7 +449,7 @@ function buildNamespaceBundleMap(srcCommandsDir) {
|
|
|
386
449
|
const stem = entry.name.slice(0, -3);
|
|
387
450
|
let children = [];
|
|
388
451
|
try {
|
|
389
|
-
children = parseRequires(
|
|
452
|
+
children = parseRequires(installFs().readFileSync(node_path_1.default.join(srcCommandsDir, entry.name), 'utf8'));
|
|
390
453
|
}
|
|
391
454
|
catch {
|
|
392
455
|
children = [];
|
|
@@ -617,7 +680,7 @@ function readInstalledCapabilitySkill(stem, registry) {
|
|
|
617
680
|
* When absent, NOTHING third-party is staged (fail closed).
|
|
618
681
|
*/
|
|
619
682
|
function stageSkillsForRuntimeAsSkills(srcCommandsDir, resolvedProfile, converter, prefix, nested = false, registry) {
|
|
620
|
-
if (!
|
|
683
|
+
if (!installFs().existsSync(srcCommandsDir))
|
|
621
684
|
return srcCommandsDir;
|
|
622
685
|
// Nesting applies to the `full` install AND to any surface whose skill set
|
|
623
686
|
// still contains every namespace router (a full/reset surface). It must NOT
|
|
@@ -640,9 +703,9 @@ function stageSkillsForRuntimeAsSkills(srcCommandsDir, resolvedProfile, converte
|
|
|
640
703
|
// this call, so the third-party fill-in pass below can enforce "first-party
|
|
641
704
|
// ALWAYS wins on collision" without re-deriving membership.
|
|
642
705
|
const firstPartyStems = new Set();
|
|
643
|
-
const stageDir =
|
|
706
|
+
const stageDir = mkInstallTempDir('gsd-profile-runtime-skills-');
|
|
644
707
|
try {
|
|
645
|
-
const entries =
|
|
708
|
+
const entries = installFs().readdirSync(srcCommandsDir, { withFileTypes: true });
|
|
646
709
|
for (const entry of entries) {
|
|
647
710
|
if (!entry.isFile())
|
|
648
711
|
continue;
|
|
@@ -652,15 +715,15 @@ function stageSkillsForRuntimeAsSkills(srcCommandsDir, resolvedProfile, converte
|
|
|
652
715
|
if (resolvedProfile.skills !== '*' && !(resolvedProfile.skills).has(stem))
|
|
653
716
|
continue;
|
|
654
717
|
firstPartyStems.add(stem);
|
|
655
|
-
const content =
|
|
718
|
+
const content = installFs().readFileSync(node_path_1.default.join(srcCommandsDir, entry.name), 'utf8');
|
|
656
719
|
const skillName = `${prefix}${stem}`;
|
|
657
720
|
const converted = converter(content, skillName);
|
|
658
721
|
if (doNest && bundles.routerStems.has(stem)) {
|
|
659
722
|
// Router skill: rewrite its routing table to the nested Read pattern and
|
|
660
723
|
// emit it as the single top-level bundle entry.
|
|
661
724
|
const destDir = node_path_1.default.join(stageDir, skillName);
|
|
662
|
-
|
|
663
|
-
|
|
725
|
+
installFs().mkdirSync(destDir, { recursive: true });
|
|
726
|
+
installFs().writeFileSync(node_path_1.default.join(destDir, 'SKILL.md'), transformRouterBodyToNested(converted));
|
|
664
727
|
continue;
|
|
665
728
|
}
|
|
666
729
|
if (doNest && bundles.childToRouters.has(stem)) {
|
|
@@ -669,16 +732,16 @@ function stageSkillsForRuntimeAsSkills(srcCommandsDir, resolvedProfile, converte
|
|
|
669
732
|
// top-level eager listing while staying readable by file path (#69).
|
|
670
733
|
for (const routerStem of bundles.childToRouters.get(stem)) {
|
|
671
734
|
const destDir = node_path_1.default.join(stageDir, `${prefix}${routerStem}`, 'skills', stem);
|
|
672
|
-
|
|
673
|
-
|
|
735
|
+
installFs().mkdirSync(destDir, { recursive: true });
|
|
736
|
+
installFs().writeFileSync(node_path_1.default.join(destDir, 'SKILL.md'), converted);
|
|
674
737
|
}
|
|
675
738
|
continue;
|
|
676
739
|
}
|
|
677
740
|
// Flat top-level skill (default behaviour; also the unrouted fallback when
|
|
678
741
|
// nesting is active).
|
|
679
742
|
const destDir = node_path_1.default.join(stageDir, skillName);
|
|
680
|
-
|
|
681
|
-
|
|
743
|
+
installFs().mkdirSync(destDir, { recursive: true });
|
|
744
|
+
installFs().writeFileSync(node_path_1.default.join(destDir, 'SKILL.md'), converted);
|
|
682
745
|
}
|
|
683
746
|
// #2322: materialize installed THIRD-PARTY capability skills, bound to
|
|
684
747
|
// their DECLARING capability via the registry's capabilityClusters view
|
|
@@ -720,25 +783,24 @@ function stageSkillsForRuntimeAsSkills(srcCommandsDir, resolvedProfile, converte
|
|
|
720
783
|
if (!(0, external_descriptor_trust_cjs_1.isPathConfined)(skillName, stageDir))
|
|
721
784
|
continue; // defense-in-depth
|
|
722
785
|
const destDir = node_path_1.default.join(stageDir, skillName);
|
|
723
|
-
|
|
724
|
-
|
|
786
|
+
installFs().mkdirSync(destDir, { recursive: true });
|
|
787
|
+
installFs().writeFileSync(node_path_1.default.join(destDir, 'SKILL.md'), found.content);
|
|
725
788
|
// #2322 HIGH-3: persist the capability-owned marker so a later prune
|
|
726
789
|
// pass (surface.cts pruneSkillDirs) can identify — and remove — this
|
|
727
790
|
// directory even once the owning capability is uninstalled/unsurfaced
|
|
728
791
|
// and no longer appears in any registry view.
|
|
729
|
-
|
|
792
|
+
installFs().writeFileSync(node_path_1.default.join(destDir, CAPABILITY_SKILL_MARKER), found.capId + '\n', 'utf8');
|
|
730
793
|
}
|
|
731
794
|
}
|
|
732
795
|
}
|
|
733
796
|
catch (err) {
|
|
734
797
|
try {
|
|
735
|
-
|
|
798
|
+
installFs().rmSync(stageDir, { recursive: true, force: true });
|
|
736
799
|
}
|
|
737
800
|
catch { /* best-effort */ }
|
|
738
801
|
throw err;
|
|
739
802
|
}
|
|
740
|
-
|
|
741
|
-
ensureExitCleanup();
|
|
803
|
+
registerStagedDir(stageDir);
|
|
742
804
|
return stageDir;
|
|
743
805
|
}
|
|
744
806
|
/**
|
|
@@ -762,26 +824,57 @@ function stageSkillsForRuntimeAsSkills(srcCommandsDir, resolvedProfile, converte
|
|
|
762
824
|
* 1. applyAgentPathRewrites (4 base ~/.claude/ regexes; skipped for copilot/antigravity)
|
|
763
825
|
* 2. processAttribution (Co-Authored-By policy)
|
|
764
826
|
* 3. converter (runtime-specific frontmatter/body transform)
|
|
765
|
-
* 4.
|
|
827
|
+
* 4. applyAgentFrontmatterExtensions (#2875 Part 2: effort/disallowedTools,
|
|
828
|
+
* gated by hostBehaviors.agentFrontmatterExtensions — no-op for a runtime
|
|
829
|
+
* that declares nothing, e.g. every non-Claude runtime today)
|
|
830
|
+
* 5. normalizeAgentBodyForRuntime (colon→hyphen refs; no-op for trivial group)
|
|
766
831
|
* When `agentCtx` is absent, only the converter is applied (backward-compat for
|
|
767
832
|
* the feat-1173 synthetic-descriptor tests and the copilot/antigravity paths
|
|
768
833
|
* that handle cross-cutting inside their converters).
|
|
769
834
|
*
|
|
770
835
|
* @param srcAgentsDir source agents directory (e.g. agents/)
|
|
771
836
|
* @param resolvedProfile profile filter from resolveProfile()
|
|
772
|
-
* @param converter (content: string, isGlobal?: boolean) → string
|
|
773
|
-
* converter; scope-aware converters (copilot/antigravity)
|
|
774
|
-
* read isGlobal, single-arg converters ignore
|
|
837
|
+
* @param converter (content: string, isGlobal?: boolean, meta?: {agentName: string}) → string
|
|
838
|
+
* per-file converter; scope-aware converters (copilot/antigravity)
|
|
839
|
+
* read isGlobal, single-arg converters ignore both extra args (#1173).
|
|
840
|
+
* `meta.agentName` (#2875 Part 2) is passed ONLY when `agentCtx` is
|
|
841
|
+
* present, letting a converter close over per-agent config
|
|
842
|
+
* (e.g. kilo/opencode model-override resolution in
|
|
843
|
+
* runtime-artifact-layout.cts's convertedAgentsKind) without widening
|
|
844
|
+
* every OTHER converter's contract — converters that don't declare a
|
|
845
|
+
* 3rd parameter simply never read it.
|
|
775
846
|
* @param isGlobal install scope passed through to the converter
|
|
776
847
|
* @param agentCtx optional cross-cutting context (ADR-1235 §1); when absent,
|
|
777
848
|
* only the converter is applied (backward compat)
|
|
778
849
|
*/
|
|
779
850
|
function stageAgentsForRuntimeWithConverter(srcAgentsDir, resolvedProfile, converter, isGlobal = false, agentCtx) {
|
|
780
|
-
if (!
|
|
851
|
+
if (!installFs().existsSync(srcAgentsDir))
|
|
781
852
|
return srcAgentsDir;
|
|
782
|
-
const stageDir =
|
|
853
|
+
const stageDir = mkInstallTempDir('gsd-profile-runtime-agents-');
|
|
854
|
+
let entries;
|
|
855
|
+
try {
|
|
856
|
+
// #2284/#2875: readdirSync-ing the shipped agents/ source is isolated in
|
|
857
|
+
// its own try/catch so an unreadable source directory (permissions, a
|
|
858
|
+
// corrupted install, or — as the #2284 test suite demonstrates — the
|
|
859
|
+
// fail-closed injection harness) produces the SAME "refusing to install"
|
|
860
|
+
// fail-closed wording every other agents-dir-unreadable path in this
|
|
861
|
+
// codebase uses (bin/install.js's `_resolveAvailableGsdRoles` /
|
|
862
|
+
// `_assertRoleResolvable`), instead of an unrelated raw fs error message
|
|
863
|
+
// escaping uncaught. Hermes's role-dispatch validation depends on the
|
|
864
|
+
// SAME shipped agents/ directory being readable; before this runtime also
|
|
865
|
+
// declared an `agents` kind, this function was never reached on a Hermes
|
|
866
|
+
// install, so an unreadable source here silently surfaced as a raw error
|
|
867
|
+
// rather than the deliberate fail-closed contract #2284 established.
|
|
868
|
+
entries = installFs().readdirSync(srcAgentsDir, { withFileTypes: true });
|
|
869
|
+
}
|
|
870
|
+
catch (err) {
|
|
871
|
+
try {
|
|
872
|
+
installFs().rmSync(stageDir, { recursive: true, force: true });
|
|
873
|
+
}
|
|
874
|
+
catch { /* best-effort */ }
|
|
875
|
+
throw new Error(`stageAgentsForRuntimeWithConverter: could not resolve the shipped agents/ directory "${srcAgentsDir}" to stage — refusing to install (fail-closed, #2284/#2875): ${err.message}`);
|
|
876
|
+
}
|
|
783
877
|
try {
|
|
784
|
-
const entries = node_fs_1.default.readdirSync(srcAgentsDir, { withFileTypes: true });
|
|
785
878
|
// Resolve cmdNames once per staging call (not per file) for performance.
|
|
786
879
|
const cmdNames = agentCtx ? _readGsdCommandNames() : [];
|
|
787
880
|
for (const entry of entries) {
|
|
@@ -796,34 +889,45 @@ function stageAgentsForRuntimeWithConverter(srcAgentsDir, resolvedProfile, conve
|
|
|
796
889
|
continue;
|
|
797
890
|
}
|
|
798
891
|
}
|
|
799
|
-
|
|
892
|
+
const agentSourcePath = node_path_1.default.join(srcAgentsDir, entry.name);
|
|
893
|
+
let content = installFs().readFileSync(agentSourcePath, 'utf8');
|
|
894
|
+
// #2995: strip gsd:section markers FIRST — before path rewrites, attribution,
|
|
895
|
+
// and the per-runtime converter. Byte-identical (no-op) for an unmarked agent;
|
|
896
|
+
// throws loudly naming the file for a malformed marker, never emitting a
|
|
897
|
+
// half-composed agent.
|
|
898
|
+
content = _composeWorkflow(content, { sourcePath: agentSourcePath });
|
|
800
899
|
if (agentCtx) {
|
|
900
|
+
// #2875 Part 2 / row I3: derived exactly as the inline loop does —
|
|
901
|
+
// single-sourced via deriveAgentName (runtime-artifact-conversion.cts).
|
|
902
|
+
const agentName = _deriveAgentName(entry.name);
|
|
801
903
|
// ADR-1235 §1: pre-converter cross-cutting (matches inline loop order exactly)
|
|
802
904
|
// Step 1: path rewrites (4 base ~/.claude/ regexes; skipped for copilot/antigravity)
|
|
803
905
|
content = _applyAgentPathRewrites(content, agentCtx.runtime, agentCtx.pathPrefix);
|
|
804
906
|
// Step 2: attribution
|
|
805
907
|
content = _processAttribution(content, agentCtx.attribution);
|
|
806
908
|
// Step 3: converter (runtime-specific frontmatter/body transform)
|
|
807
|
-
content = converter(content, isGlobal);
|
|
808
|
-
// Step 4:
|
|
909
|
+
content = converter(content, isGlobal, { agentName });
|
|
910
|
+
// Step 4: frontmatter extensions (effort/disallowedTools; no-op unless
|
|
911
|
+
// the runtime declares hostBehaviors.agentFrontmatterExtensions)
|
|
912
|
+
content = _applyAgentFrontmatterExtensions(content, { runtime: agentCtx.runtime, agentName, targetDir: agentCtx.targetDir });
|
|
913
|
+
// Step 5: normalize colon→hyphen refs (no-op for trivial group)
|
|
809
914
|
content = _normalizeAgentBodyForRuntime(content, agentCtx.runtime, cmdNames);
|
|
810
915
|
}
|
|
811
916
|
else {
|
|
812
917
|
// Backward-compat: only apply the converter (no cross-cutting)
|
|
813
918
|
content = converter(content, isGlobal);
|
|
814
919
|
}
|
|
815
|
-
|
|
920
|
+
installFs().writeFileSync(node_path_1.default.join(stageDir, entry.name), content, 'utf8');
|
|
816
921
|
}
|
|
817
922
|
}
|
|
818
923
|
catch (err) {
|
|
819
924
|
try {
|
|
820
|
-
|
|
925
|
+
installFs().rmSync(stageDir, { recursive: true, force: true });
|
|
821
926
|
}
|
|
822
927
|
catch { /* best-effort */ }
|
|
823
928
|
throw err;
|
|
824
929
|
}
|
|
825
|
-
|
|
826
|
-
ensureExitCleanup();
|
|
930
|
+
registerStagedDir(stageDir);
|
|
827
931
|
return stageDir;
|
|
828
932
|
}
|
|
829
933
|
/**
|
|
@@ -850,11 +954,11 @@ function stageAgentsForRuntimeWithConverter(srcAgentsDir, resolvedProfile, conve
|
|
|
850
954
|
* @param prefix command name prefix (for converter arg), e.g. 'gsd-'
|
|
851
955
|
*/
|
|
852
956
|
function stageCommandsForRuntimeFlat(srcCommandsDir, resolvedProfile, converter, prefix) {
|
|
853
|
-
if (!
|
|
957
|
+
if (!installFs().existsSync(srcCommandsDir))
|
|
854
958
|
return srcCommandsDir;
|
|
855
|
-
const stageDir =
|
|
959
|
+
const stageDir = mkInstallTempDir('gsd-profile-runtime-commands-');
|
|
856
960
|
try {
|
|
857
|
-
const entries =
|
|
961
|
+
const entries = installFs().readdirSync(srcCommandsDir, { withFileTypes: true });
|
|
858
962
|
for (const entry of entries) {
|
|
859
963
|
if (!entry.isFile())
|
|
860
964
|
continue;
|
|
@@ -863,24 +967,23 @@ function stageCommandsForRuntimeFlat(srcCommandsDir, resolvedProfile, converter,
|
|
|
863
967
|
const stem = entry.name.slice(0, -3);
|
|
864
968
|
if (resolvedProfile.skills !== '*' && !(resolvedProfile.skills).has(stem))
|
|
865
969
|
continue;
|
|
866
|
-
const content =
|
|
970
|
+
const content = installFs().readFileSync(node_path_1.default.join(srcCommandsDir, entry.name), 'utf8');
|
|
867
971
|
// Pass the full command name (with prefix) to the converter so it can
|
|
868
972
|
// reference the installed command name in the body (e.g. for descriptions).
|
|
869
973
|
// The staged file itself is named without the prefix; _copyStaged adds it.
|
|
870
974
|
const commandName = `${prefix}${stem}`;
|
|
871
975
|
const converted = converter(content, commandName);
|
|
872
|
-
|
|
976
|
+
installFs().writeFileSync(node_path_1.default.join(stageDir, `${stem}.md`), converted);
|
|
873
977
|
}
|
|
874
978
|
}
|
|
875
979
|
catch (err) {
|
|
876
980
|
try {
|
|
877
|
-
|
|
981
|
+
installFs().rmSync(stageDir, { recursive: true, force: true });
|
|
878
982
|
}
|
|
879
983
|
catch { /* best-effort */ }
|
|
880
984
|
throw err;
|
|
881
985
|
}
|
|
882
|
-
|
|
883
|
-
ensureExitCleanup();
|
|
986
|
+
registerStagedDir(stageDir);
|
|
884
987
|
return stageDir;
|
|
885
988
|
}
|
|
886
989
|
// ---------------------------------------------------------------------------
|