@opengsd/gsd-core 1.14.0 → 1.16.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 +1 -1
- package/.opencode/plugins/gsd-core.js +85 -5
- package/README.ja-JP.md +3 -3
- package/README.ko-KR.md +3 -3
- package/README.pt-BR.md +3 -3
- package/README.zh-CN.md +3 -3
- package/agents/gsd-code-fixer.compact.md +7 -6
- package/agents/gsd-code-fixer.md +9 -8
- package/agents/gsd-code-reviewer.compact.md +5 -3
- package/agents/gsd-code-reviewer.md +8 -6
- package/agents/gsd-debug-session-manager.compact.md +17 -2
- package/agents/gsd-debug-session-manager.md +17 -2
- package/agents/gsd-debugger.md +3 -3
- package/agents/gsd-eval-auditor.compact.md +1 -1
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +17 -12
- package/agents/gsd-intel-updater.compact.md +1 -1
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +2 -2
- package/agents/gsd-phase-researcher.md +19 -11
- package/agents/gsd-plan-checker.md +15 -9
- package/agents/gsd-planner.md +15 -11
- package/agents/gsd-project-researcher.compact.md +1 -1
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.compact.md +1 -1
- package/agents/gsd-research-synthesizer.md +1 -1
- package/agents/gsd-ui-auditor.compact.md +21 -30
- package/agents/gsd-ui-auditor.md +166 -37
- package/agents/gsd-ui-researcher.compact.md +1 -1
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-verifier.md +37 -14
- package/bin/install.js +764 -287
- package/commands/gsd/add-tests.md +6 -1
- package/commands/gsd/ai-integration-phase.md +6 -1
- package/commands/gsd/audit-fix.md +5 -0
- package/commands/gsd/audit-milestone.md +6 -1
- package/commands/gsd/autonomous.md +7 -2
- package/commands/gsd/capture.md +9 -5
- package/commands/gsd/code-review.md +7 -2
- package/commands/gsd/complete-milestone.md +4 -0
- package/commands/gsd/config.md +7 -3
- package/commands/gsd/debug.md +11 -7
- package/commands/gsd/discuss-phase.md +7 -3
- package/commands/gsd/docs-update.md +12 -7
- package/commands/gsd/eval-review.md +6 -1
- package/commands/gsd/execute-phase.md +12 -7
- package/commands/gsd/extract-learnings.md +5 -0
- package/commands/gsd/fast.md +4 -0
- package/commands/gsd/forensics.md +5 -1
- package/commands/gsd/graphify.md +10 -6
- package/commands/gsd/health.md +5 -0
- package/commands/gsd/help.md +7 -2
- package/commands/gsd/import.md +7 -3
- package/commands/gsd/inbox.md +5 -0
- package/commands/gsd/ingest-docs.md +5 -1
- package/commands/gsd/manager.md +6 -1
- package/commands/gsd/map-codebase.md +7 -3
- package/commands/gsd/mempalace-capture.md +12 -4
- package/commands/gsd/mempalace-recall.md +5 -1
- package/commands/gsd/milestone-summary.md +5 -1
- package/commands/gsd/mvp-phase.md +8 -3
- package/commands/gsd/new-milestone.md +6 -1
- package/commands/gsd/new-project.md +5 -0
- package/commands/gsd/next.md +6 -1
- package/commands/gsd/ns-context.md +4 -0
- package/commands/gsd/ns-ideate.md +4 -0
- package/commands/gsd/ns-manage.md +4 -0
- package/commands/gsd/ns-project.md +4 -0
- package/commands/gsd/ns-review.md +4 -0
- package/commands/gsd/ns-workflow.md +4 -0
- package/commands/gsd/onboard.md +6 -1
- package/commands/gsd/pause-work.md +5 -1
- package/commands/gsd/phase.md +8 -4
- package/commands/gsd/plan-phase.md +6 -1
- package/commands/gsd/plan-review-convergence.md +11 -7
- package/commands/gsd/pr-branch.md +4 -0
- package/commands/gsd/profile-user.md +5 -1
- package/commands/gsd/progress.md +7 -2
- package/commands/gsd/quick-batch.md +21 -9
- package/commands/gsd/quick.md +12 -7
- package/commands/gsd/review.md +7 -4
- package/commands/gsd/secure-phase.md +6 -1
- package/commands/gsd/ship.md +5 -0
- package/commands/gsd/sketch.md +7 -2
- package/commands/gsd/spec-phase.md +5 -1
- package/commands/gsd/spike.md +8 -3
- package/commands/gsd/surface.md +5 -1
- package/commands/gsd/thread.md +4 -0
- package/commands/gsd/ui-phase.md +6 -1
- package/commands/gsd/ui-review.md +6 -1
- package/commands/gsd/ultraplan-phase.md +5 -1
- package/commands/gsd/undo.md +5 -1
- package/commands/gsd/update.md +6 -2
- package/commands/gsd/validate-phase.md +6 -1
- package/commands/gsd/verify-work.md +6 -1
- package/commands/gsd/workspace.md +7 -3
- package/gsd-core/bin/gsd-tools.cjs +477 -78
- package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
- package/gsd-core/bin/lib/adr-parser.cjs +3 -1
- package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
- package/gsd-core/bin/lib/audit.cjs +144 -42
- package/gsd-core/bin/lib/broken-windows.cjs +13 -13
- package/gsd-core/bin/lib/capability-activation.cjs +9 -4
- package/gsd-core/bin/lib/capability-registry.cjs +197 -222
- package/gsd-core/bin/lib/capability-validator.cjs +16 -1
- package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
- package/gsd-core/bin/lib/check-command-router.cjs +164 -1625
- package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
- package/gsd-core/bin/lib/cli-exit.cjs +12 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +32 -33
- package/gsd-core/bin/lib/command-aliases.cjs +7 -0
- package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
- package/gsd-core/bin/lib/commands.cjs +343 -207
- package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
- package/gsd-core/bin/lib/config-loader.cjs +65 -4
- package/gsd-core/bin/lib/config.cjs +76 -19
- package/gsd-core/bin/lib/core-utils.cjs +6 -1
- package/gsd-core/bin/lib/coverage.cjs +4 -8
- package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
- package/gsd-core/bin/lib/decisions.cjs +30 -14
- package/gsd-core/bin/lib/drift.cjs +177 -42
- package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
- package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
- package/gsd-core/bin/lib/frontmatter.cjs +426 -234
- package/gsd-core/bin/lib/gap-checker.cjs +72 -29
- package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
- package/gsd-core/bin/lib/gate-args.cjs +53 -0
- package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
- package/gsd-core/bin/lib/gate-config.cjs +46 -0
- package/gsd-core/bin/lib/gate-context-drift.cjs +141 -0
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
- package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
- package/gsd-core/bin/lib/gate-exit.cjs +27 -0
- package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
- package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
- package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
- package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
- package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
- package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
- package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
- package/gsd-core/bin/lib/gate-ui-safety.cjs +80 -0
- package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
- package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
- package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
- package/gsd-core/bin/lib/graphify.cjs +10 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
- package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
- package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
- package/gsd-core/bin/lib/init.cjs +364 -132
- package/gsd-core/bin/lib/install-engine.cjs +30 -33
- package/gsd-core/bin/lib/install-profiles.cjs +7 -4
- package/gsd-core/bin/lib/installer-migrations.cjs +8 -1
- package/gsd-core/bin/lib/io.cjs +122 -3
- package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
- package/gsd-core/bin/lib/milestone.cjs +37 -6
- package/gsd-core/bin/lib/model-resolver.cjs +171 -62
- package/gsd-core/bin/lib/observability/event.cjs +1 -1
- package/gsd-core/bin/lib/observability/logger.cjs +46 -1
- package/gsd-core/bin/lib/pattern.cjs +10 -0
- package/gsd-core/bin/lib/phase-command-router.cjs +20 -5
- package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
- package/gsd-core/bin/lib/phase-id-card.cjs +32 -0
- package/gsd-core/bin/lib/phase-id-display.cjs +78 -0
- package/gsd-core/bin/lib/phase-id.cjs +110 -8
- package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
- package/gsd-core/bin/lib/phase-locator.cjs +29 -10
- package/gsd-core/bin/lib/phase-status.cjs +360 -0
- package/gsd-core/bin/lib/phase.cjs +489 -88
- package/gsd-core/bin/lib/plan-document.cjs +142 -20
- package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
- package/gsd-core/bin/lib/planning-document.cjs +692 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +60 -9
- package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +83 -55
- package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
- package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
- package/gsd-core/bin/lib/probe-core.cjs +7 -1
- package/gsd-core/bin/lib/profile-output.cjs +6 -3
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
- package/gsd-core/bin/lib/project-root.cjs +41 -2
- package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +11 -8
- package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
- package/gsd-core/bin/lib/report-parser.cjs +269 -0
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
- package/gsd-core/bin/lib/roadmap-command-router.cjs +25 -19
- package/gsd-core/bin/lib/roadmap-parser.cjs +242 -15
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +1653 -65
- package/gsd-core/bin/lib/roadmap.cjs +405 -88
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +373 -187
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +5 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
- package/gsd-core/bin/lib/runtime-homes.cjs +14 -7
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +522 -624
- package/gsd-core/bin/lib/runtime-name-policy.cjs +246 -21
- package/gsd-core/bin/lib/runtime-slash.cjs +47 -30
- package/gsd-core/bin/lib/shell-command-projection.cjs +47 -8
- package/gsd-core/bin/lib/smart-entry.cjs +19 -3
- package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
- package/gsd-core/bin/lib/state-contract.cjs +15 -18
- package/gsd-core/bin/lib/state-document.cjs +100 -22
- package/gsd-core/bin/lib/state-transition.cjs +39 -2
- package/gsd-core/bin/lib/state.cjs +256 -105
- package/gsd-core/bin/lib/surface.cjs +19 -2
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -79
- package/gsd-core/bin/lib/uat-predicate.cjs +359 -38
- package/gsd-core/bin/lib/uat.cjs +432 -7
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +167 -40
- package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
- package/gsd-core/bin/lib/vendor/README.md +31 -9
- package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
- package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +1378 -274
- package/gsd-core/bin/lib/verify-command-grounding.cjs +46 -2
- package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
- package/gsd-core/bin/lib/verify.cjs +357 -531
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
- package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
- package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
- package/gsd-core/bin/lib/workstream.cjs +11 -2
- package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
- package/gsd-core/bin/lib/worktree-safety.cjs +784 -51
- package/gsd-core/bin/shared/config-defaults.manifest.json +8 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
- package/gsd-core/references/autonomous-smart-discuss.md +2 -1
- package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
- package/gsd-core/references/checkpoints.md +5 -3
- package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +28 -3
- package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +37 -4
- package/gsd-core/references/edge-probe.md +195 -21
- package/gsd-core/references/execute-mvp-tdd.md +5 -10
- package/gsd-core/references/execute-phase-between-wave-reset.md +10 -6
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/execute-phase-wave-guard.md +22 -11
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +7 -1
- package/gsd-core/references/model-profiles.md +1 -1
- package/gsd-core/references/offer-next.md +1 -1
- package/gsd-core/references/phase-argument-parsing.md +9 -7
- package/gsd-core/references/phase-id-convention.md +28 -0
- package/gsd-core/references/planner-gap-closure.md +2 -0
- package/gsd-core/references/planner-load-graph-context.md +24 -13
- package/gsd-core/references/planner-verify-command-grounding.md +14 -0
- package/gsd-core/references/planning-config.md +12 -3
- package/gsd-core/references/spidr-splitting.md +1 -1
- package/gsd-core/references/tdd.md +37 -8
- package/gsd-core/references/ui-consideration-probe.md +10 -5
- package/gsd-core/references/verifier-phase-gates.md +5 -2
- package/gsd-core/references/verify-command-path-resolvability.md +10 -2
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -3
- package/gsd-core/references/worktree-path-safety.md +321 -0
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/UAT.md +17 -1
- package/gsd-core/templates/config.json +2 -11
- package/gsd-core/templates/verification-report.md +1 -1
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +8 -7
- package/gsd-core/workflows/add-tests.md +4 -3
- package/gsd-core/workflows/add-todo.md +6 -5
- package/gsd-core/workflows/ai-integration-phase.md +13 -4
- package/gsd-core/workflows/audit-fix.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +4 -3
- package/gsd-core/workflows/audit-uat.md +1 -1
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +9 -18
- package/gsd-core/workflows/autonomous.md +43 -23
- package/gsd-core/workflows/check-todos.md +7 -6
- package/gsd-core/workflows/cleanup.md +2 -2
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
- package/gsd-core/workflows/code-review-fix.md +112 -25
- package/gsd-core/workflows/code-review.md +146 -135
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
- package/gsd-core/workflows/complete-milestone.md +13 -8
- package/gsd-core/workflows/debug.md +32 -7
- package/gsd-core/workflows/diagnose-issues.md +3 -2
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +4 -3
- package/gsd-core/workflows/do.md +2 -2
- package/gsd-core/workflows/docs-update.md +6 -5
- package/gsd-core/workflows/edit-phase.md +4 -3
- package/gsd-core/workflows/eval-review.md +14 -5
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1019 -0
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +37 -3
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +46 -9
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/ready-wave-gate.md +37 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/threat-id-gate.md +28 -0
- package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
- package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
- package/gsd-core/workflows/execute-phase.md +96 -178
- package/gsd-core/workflows/execute-plan.md +18 -23
- package/gsd-core/workflows/explore.md +4 -4
- package/gsd-core/workflows/extract-learnings.md +4 -2
- package/gsd-core/workflows/fast.md +1 -1
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +3 -2
- package/gsd-core/workflows/help/modes/full.compact.md +3 -3
- package/gsd-core/workflows/help/modes/full.md +5 -5
- package/gsd-core/workflows/help/modes/topic.md +15 -5
- package/gsd-core/workflows/import.md +4 -3
- package/gsd-core/workflows/inbox.md +2 -2
- package/gsd-core/workflows/ingest-docs.md +3 -3
- package/gsd-core/workflows/insert-phase.md +4 -3
- package/gsd-core/workflows/list-seeds.md +1 -1
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +6 -4
- package/gsd-core/workflows/map-codebase.md +5 -4
- package/gsd-core/workflows/milestone-summary.md +3 -2
- package/gsd-core/workflows/mvp-phase.md +14 -14
- package/gsd-core/workflows/new-milestone.md +11 -11
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +3 -3
- package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +1 -1
- package/gsd-core/workflows/new-project.md +7 -7
- package/gsd-core/workflows/new-workspace.md +2 -2
- package/gsd-core/workflows/next.md +1 -1
- package/gsd-core/workflows/note.md +1 -1
- package/gsd-core/workflows/onboard.md +1 -1
- package/gsd-core/workflows/pause-work.md +2 -2
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +17 -5
- package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +23 -5
- package/gsd-core/workflows/plan-phase.md +50 -24
- package/gsd-core/workflows/plan-review-convergence.md +21 -5
- package/gsd-core/workflows/plant-seed.md +62 -20
- package/gsd-core/workflows/pr-branch.md +113 -13
- package/gsd-core/workflows/profile-user.md +2 -2
- package/gsd-core/workflows/progress.md +19 -49
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +27 -0
- package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +9 -3
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
- package/gsd-core/workflows/quick-batch.md +15 -10
- package/gsd-core/workflows/quick.md +62 -39
- package/gsd-core/workflows/reapply-patches.md +9 -3
- package/gsd-core/workflows/remove-phase.md +3 -2
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +3 -2
- package/gsd-core/workflows/review.md +33 -17
- package/gsd-core/workflows/scan.md +3 -2
- package/gsd-core/workflows/secure-phase.md +13 -13
- package/gsd-core/workflows/settings-advanced.md +30 -10
- package/gsd-core/workflows/settings-integrations.md +2 -3
- package/gsd-core/workflows/settings.md +4 -4
- package/gsd-core/workflows/ship.md +14 -13
- package/gsd-core/workflows/sketch-wrap-up.md +1 -1
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/smart-entry.md +2 -2
- package/gsd-core/workflows/spec-phase.md +15 -5
- package/gsd-core/workflows/spike-wrap-up.md +1 -1
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +1 -1
- package/gsd-core/workflows/sync-skills.md +5 -5
- package/gsd-core/workflows/thread.md +2 -2
- package/gsd-core/workflows/transition.md +13 -23
- package/gsd-core/workflows/ui-phase.md +48 -11
- package/gsd-core/workflows/ui-review.md +21 -6
- package/gsd-core/workflows/ultraplan-phase.md +3 -2
- package/gsd-core/workflows/undo.md +339 -20
- package/gsd-core/workflows/update.md +7 -7
- package/gsd-core/workflows/validate-phase.md +12 -13
- package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
- package/gsd-core/workflows/verify-work.md +129 -55
- package/hooks/dist/gsd-agent-isolation-guard.js +32 -0
- package/hooks/dist/gsd-check-update-worker.js +8 -0
- package/hooks/dist/gsd-check-update.js +8 -0
- package/hooks/dist/gsd-context-monitor.js +31 -8
- package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
- package/hooks/dist/gsd-secret-read-guard.js +161 -4
- package/hooks/dist/gsd-statusline.js +85 -20
- package/hooks/dist/gsd-update-banner.js +8 -0
- package/hooks/dist/gsd-validate-commit.sh +63 -4
- package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
- package/hooks/dist/gsd-workflow-guard.js +5 -4
- package/hooks/dist/gsd-worktree-path-guard.js +6 -2
- package/hooks/dist/lib/cli-exit.js +12 -0
- package/hooks/dist/lib/git-probe.js +17 -1
- package/hooks/dist/lib/isolation-sentinel.js +2 -2
- package/hooks/gsd-agent-isolation-guard.js +32 -0
- package/hooks/gsd-check-update-worker.js +8 -0
- package/hooks/gsd-check-update.js +8 -0
- package/hooks/gsd-context-monitor.js +31 -8
- package/hooks/gsd-cursor-subagent-start.js +8 -0
- package/hooks/gsd-secret-read-guard.js +161 -4
- package/hooks/gsd-statusline.js +85 -20
- package/hooks/gsd-update-banner.js +8 -0
- package/hooks/gsd-validate-commit.sh +63 -4
- package/hooks/gsd-windsurf-pre-write.js +11 -2
- package/hooks/gsd-workflow-guard.js +5 -4
- package/hooks/gsd-worktree-path-guard.js +6 -2
- package/hooks/hooks.json +5 -5
- package/hooks/lib/cli-exit.js +12 -0
- package/hooks/lib/git-probe.js +17 -1
- package/hooks/lib/isolation-sentinel.js +2 -2
- package/package.json +22 -4
- package/scripts/build-hooks.js +15 -6
- package/scripts/changeset/parse.cjs +52 -4
- package/scripts/check-contract-drift.cjs +127 -11
- package/scripts/ci-timeout-report.cjs +770 -4
- package/scripts/command-contract-helpers.cjs +15 -8
- package/scripts/docs-guard-registry.cjs +34 -0
- package/scripts/gen-features.cjs +13 -8
- package/scripts/gen-hooks-cli-exit.cjs +12 -28
- package/scripts/gen-loop-host-contract.cjs +79 -1
- package/scripts/gen-platform-conformance-tier.cjs +187 -1
- package/scripts/gen-plugin-skills.cjs +87 -1
- package/scripts/gen-research-agents.cjs +24 -31
- package/scripts/gen-scripts-cli-exit.cjs +30 -3
- package/scripts/gen-test-timings.cjs +32 -7
- package/scripts/lib/cli-exit.cjs +12 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +34 -2
- package/scripts/lib/ndjson-reporter.cjs +31 -5
- package/scripts/lib/platform-conformance-tier.generated.cjs +45 -5
- package/scripts/lib/registration-ledger-preload.cjs +155 -0
- package/scripts/lib/vendor-bundle.cjs +59 -0
- package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-completion-predicate-drift.cjs +18 -19
- package/scripts/lint-descriptions.cjs +7 -3
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +38 -1
- package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
- package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
- package/scripts/lint-phase-arg-assignment.cjs +257 -0
- package/scripts/lint-phase-enumeration-drift.cjs +12 -8
- package/scripts/lint-phase-id-drift.cjs +319 -5
- package/scripts/lint-planning-document-positive-control.cjs +329 -0
- package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
- package/scripts/lint-response-language-coverage.cjs +3 -0
- package/scripts/lint-retired-runtime-name.cjs +619 -0
- package/scripts/lint-skill-deps.cjs +7 -3
- package/scripts/lint-state-write-path-drift.cjs +93 -0
- package/scripts/lint-test-file-count.allowlist.json +38 -9
- package/scripts/lint-test-file-count.cjs +34 -1
- package/scripts/lint-vendored-deps.cjs +41 -5
- package/scripts/lint-workflow-shellcheck-baseline.json +25 -10
- package/scripts/mutation-matrix.cjs +50 -5
- package/scripts/prompt-injection-scan.sh +4 -0
- package/scripts/release-tarball-smoke.cjs +194 -1
- package/scripts/require-issue-link-policy.cjs +6 -2
- package/scripts/sync-runtime-launcher.cjs +184 -2
- package/scripts/verify-npm-publish.cjs +76 -20
- package/skills/gsd-add-tests/SKILL.md +6 -1
- package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
- package/skills/gsd-audit-fix/SKILL.md +5 -0
- package/skills/gsd-audit-milestone/SKILL.md +6 -1
- package/skills/gsd-autonomous/SKILL.md +7 -2
- package/skills/gsd-capture/SKILL.md +9 -5
- package/skills/gsd-code-review/SKILL.md +7 -2
- package/skills/gsd-complete-milestone/SKILL.md +4 -0
- package/skills/gsd-config/SKILL.md +8 -4
- package/skills/gsd-debug/SKILL.md +11 -7
- package/skills/gsd-discuss-phase/SKILL.md +7 -3
- package/skills/gsd-docs-update/SKILL.md +12 -7
- package/skills/gsd-eval-review/SKILL.md +6 -1
- package/skills/gsd-execute-phase/SKILL.md +12 -7
- package/skills/gsd-extract-learnings/SKILL.md +5 -0
- package/skills/gsd-fast/SKILL.md +4 -0
- package/skills/gsd-forensics/SKILL.md +5 -1
- package/skills/gsd-graphify/SKILL.md +10 -6
- package/skills/gsd-health/SKILL.md +5 -0
- package/skills/gsd-help/SKILL.md +7 -2
- package/skills/gsd-import/SKILL.md +7 -3
- package/skills/gsd-inbox/SKILL.md +5 -0
- package/skills/gsd-ingest-docs/SKILL.md +5 -1
- package/skills/gsd-manager/SKILL.md +6 -1
- package/skills/gsd-map-codebase/SKILL.md +7 -3
- package/skills/gsd-mempalace-capture/SKILL.md +12 -4
- package/skills/gsd-mempalace-recall/SKILL.md +5 -1
- package/skills/gsd-milestone-summary/SKILL.md +5 -1
- package/skills/gsd-mvp-phase/SKILL.md +8 -3
- package/skills/gsd-new-milestone/SKILL.md +6 -1
- package/skills/gsd-new-project/SKILL.md +5 -0
- package/skills/gsd-next/SKILL.md +6 -1
- package/skills/gsd-ns-context/SKILL.md +4 -0
- package/skills/gsd-ns-ideate/SKILL.md +4 -0
- package/skills/gsd-ns-manage/SKILL.md +4 -0
- package/skills/gsd-ns-project/SKILL.md +4 -0
- package/skills/gsd-ns-review/SKILL.md +4 -0
- package/skills/gsd-ns-workflow/SKILL.md +4 -0
- package/skills/gsd-onboard/SKILL.md +6 -1
- package/skills/gsd-pause-work/SKILL.md +5 -1
- package/skills/gsd-phase/SKILL.md +8 -4
- package/skills/gsd-plan-phase/SKILL.md +6 -1
- package/skills/gsd-plan-review-convergence/SKILL.md +10 -6
- package/skills/gsd-pr-branch/SKILL.md +4 -0
- package/skills/gsd-profile-user/SKILL.md +5 -1
- package/skills/gsd-progress/SKILL.md +7 -2
- package/skills/gsd-quick/SKILL.md +16 -10
- package/skills/gsd-quick-batch/SKILL.md +21 -9
- package/skills/gsd-review/SKILL.md +7 -4
- package/skills/gsd-review-backlog/SKILL.md +3 -2
- package/skills/gsd-secure-phase/SKILL.md +6 -1
- package/skills/gsd-ship/SKILL.md +5 -0
- package/skills/gsd-sketch/SKILL.md +7 -2
- package/skills/gsd-spec-phase/SKILL.md +5 -1
- package/skills/gsd-spike/SKILL.md +8 -3
- package/skills/gsd-surface/SKILL.md +5 -1
- package/skills/gsd-thread/SKILL.md +4 -0
- package/skills/gsd-ui-phase/SKILL.md +6 -1
- package/skills/gsd-ui-review/SKILL.md +6 -1
- package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
- package/skills/gsd-undo/SKILL.md +5 -1
- package/skills/gsd-update/SKILL.md +6 -2
- package/skills/gsd-validate-phase/SKILL.md +6 -1
- package/skills/gsd-verify-work/SKILL.md +6 -1
- package/skills/gsd-workspace/SKILL.md +7 -3
- package/skills/gsd-workstreams/SKILL.md +6 -6
- package/vscode/package.json +1 -1
|
@@ -55,7 +55,7 @@ const install_scope_cjs_1 = require("./install-scope.cjs");
|
|
|
55
55
|
const { processAttribution } = runtimeArtifactConversion;
|
|
56
56
|
// resolveRuntimeArtifactLayout: accessed via module ref (not destructured) so
|
|
57
57
|
// test stubs that monkeypatch the module's exports are seen at call time.
|
|
58
|
-
const { getDirName } = runtimeNamePolicy;
|
|
58
|
+
const { getDirName, hostBehaviorsFor } = runtimeNamePolicy;
|
|
59
59
|
function withInstallerPackageSource(configDir, fn) {
|
|
60
60
|
// Reuse the existing compatibility-marker contract through the existing fs
|
|
61
61
|
// seam. The marker exists only in this synchronous call tree: no disk state,
|
|
@@ -181,7 +181,7 @@ function provisionRuntimeSurfaceCorpus(layout, configDir, scope) {
|
|
|
181
181
|
const destination = node_path_1.default.join(corpusRoot, 'agents');
|
|
182
182
|
syncRuntimeSurfaceCorpus(source, destination, configDir, 'gsd-core/agents/');
|
|
183
183
|
}
|
|
184
|
-
const markerFile =
|
|
184
|
+
const markerFile = hostBehaviorsFor(layout.runtime).sourceMarkerFile;
|
|
185
185
|
if (typeof markerFile === 'string' && markerFile !== '' && required.has('commands')) {
|
|
186
186
|
try {
|
|
187
187
|
const markerPath = runtimeArtifactInstallPlan.assertDestWithinConfigHome(configDir, markerFile);
|
|
@@ -220,25 +220,6 @@ function executingPackageRoot() { return node_path_1.default.dirname(node_path_1
|
|
|
220
220
|
*/
|
|
221
221
|
const USER_OWNED_ARTIFACTS = ['USER-PROFILE.md'];
|
|
222
222
|
// ---------------------------------------------------------------------------
|
|
223
|
-
// Host-behavior helpers
|
|
224
|
-
// ---------------------------------------------------------------------------
|
|
225
|
-
/**
|
|
226
|
-
* Host-specific install behaviors declared on the runtime descriptor
|
|
227
|
-
* (capabilities/<runtime>/capability.json -> runtime.hostBehaviors).
|
|
228
|
-
* Mirrors bin/install.js's `_hostBehaviors` (ADR-1239 / #2086/#2087). Returns
|
|
229
|
-
* {} for runtimes that declare none or if the registry fails to load, so
|
|
230
|
-
* every behavior branch degrades to the generic path by default.
|
|
231
|
-
*/
|
|
232
|
-
function _hostBehaviors(runtime) {
|
|
233
|
-
try {
|
|
234
|
-
const reg = require('./capability-registry.cjs');
|
|
235
|
-
return (reg && reg.runtimes && reg.runtimes[runtime] && reg.runtimes[runtime].runtime && reg.runtimes[runtime].runtime.hostBehaviors) || {};
|
|
236
|
-
}
|
|
237
|
-
catch {
|
|
238
|
-
return {};
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
// ---------------------------------------------------------------------------
|
|
242
223
|
// Conversion helpers
|
|
243
224
|
// ---------------------------------------------------------------------------
|
|
244
225
|
/**
|
|
@@ -730,6 +711,17 @@ function _copyStaged(stagedDir, destDir, kind, configDir, runtime) {
|
|
|
730
711
|
continue;
|
|
731
712
|
if (!entry.name.endsWith('.md'))
|
|
732
713
|
continue;
|
|
714
|
+
// #4782: compact agent variants are consumed ONLY through the non-claude
|
|
715
|
+
// gate in init.cts's agent-skills persona fallback (`runtime !== 'claude'`
|
|
716
|
+
// — claude's contract is a skills-injection path, never a persona
|
|
717
|
+
// fallback). Staging them into Claude's agents directory shipped 29 dead
|
|
718
|
+
// files whose `name:` frontmatter is identical to their canonical
|
|
719
|
+
// sibling's, leaving the harness resolution unstated. Claude never
|
|
720
|
+
// selects compact, so claude is the one runtime whose agents kind skips
|
|
721
|
+
// them; every other runtime's emission is byte-identical. #5169: the
|
|
722
|
+
// descriptor declares this (`hostBehaviors.skipCompactAgents`), not a name test.
|
|
723
|
+
if (kind.kind === 'agents' && hostBehaviorsFor(runtime).skipCompactAgents && entry.name.endsWith('.compact.md'))
|
|
724
|
+
continue;
|
|
733
725
|
const stem = entry.name.slice(0, -3); // strip .md
|
|
734
726
|
let destName;
|
|
735
727
|
if (kind.kind === 'agents') {
|
|
@@ -738,7 +730,7 @@ function _copyStaged(stagedDir, destDir, kind, configDir, runtime) {
|
|
|
738
730
|
// hardcoded `runtime === 'copilot'`). copilot declares '.agent.md';
|
|
739
731
|
// every other runtime's descriptor leaves this unset, so destName falls
|
|
740
732
|
// back to entry.name unchanged (byte-parity, #1575 origin comment).
|
|
741
|
-
const _agentExt = runtime ?
|
|
733
|
+
const _agentExt = runtime ? hostBehaviorsFor(runtime).agentFileExtension : undefined;
|
|
742
734
|
destName = _agentExt
|
|
743
735
|
? entry.name.replace(/\.md$/, _agentExt)
|
|
744
736
|
: entry.name;
|
|
@@ -877,7 +869,7 @@ function _runLegacyInstallMigrations(runtime, configDir, scope = 'global') {
|
|
|
877
869
|
// that for Hermes the flat skills/gsd-*/ removal (below) does not delete the freshly
|
|
878
870
|
// created skills/gsd-dev-preferences/ skill dir.
|
|
879
871
|
let stagedLegacyArtifacts = null;
|
|
880
|
-
if (
|
|
872
|
+
if (hostBehaviorsFor(runtime).legacyCommandsGsdInstallMigration) {
|
|
881
873
|
if (installFs().existsSync(legacyCommandsGsd)) {
|
|
882
874
|
// #2875: staging root resolved lazily, only when there is actually
|
|
883
875
|
// something to stage — reused below by every other call site sharing
|
|
@@ -901,8 +893,8 @@ function _runLegacyInstallMigrations(runtime, configDir, scope = 'global') {
|
|
|
901
893
|
}
|
|
902
894
|
}
|
|
903
895
|
// Hermes: remove pre-#2841 flat skills/gsd-*/ entries that lived alongside
|
|
904
|
-
// the new skills/gsd/ nested layout.
|
|
905
|
-
if (runtime
|
|
896
|
+
// the new skills/gsd/ nested layout. (#5169: `hostBehaviors.legacyFlatSkillsCleanup`.)
|
|
897
|
+
if (hostBehaviorsFor(runtime).legacyFlatSkillsCleanup) {
|
|
906
898
|
const flatSkillsDir = node_path_1.default.join(configDir, 'skills');
|
|
907
899
|
if (installFs().existsSync(flatSkillsDir)) {
|
|
908
900
|
for (const entry of installFs().readdirSync(flatSkillsDir, { withFileTypes: true })) {
|
|
@@ -1040,7 +1032,7 @@ function _runLegacyUninstallCleanup(runtime, configDir, scope = 'global') {
|
|
|
1040
1032
|
// commands/gsd/ for claude local, preserving dev-preferences.md by restoring it
|
|
1041
1033
|
// to the same location (#1423). Using migrateLegacyDevPreferencesToSkill here
|
|
1042
1034
|
// (which would redirect to skills/) conflicts with the test contract for local installs.
|
|
1043
|
-
const _lu =
|
|
1035
|
+
const _lu = hostBehaviorsFor(runtime).legacyCommandsGsdUninstall;
|
|
1044
1036
|
// #2870: `scope` keeps its exported `string = 'global'` signature (no
|
|
1045
1037
|
// signature change), but every real caller — `uninstallRuntimeArtifacts`'s
|
|
1046
1038
|
// own required `scope` param, always fed a validated 'global' | 'local'
|
|
@@ -1065,8 +1057,8 @@ function _runLegacyUninstallCleanup(runtime, configDir, scope = 'global') {
|
|
|
1065
1057
|
}
|
|
1066
1058
|
}
|
|
1067
1059
|
}
|
|
1068
|
-
// Hermes: pre-#2841 flat skills/gsd-*/ entries
|
|
1069
|
-
if (runtime
|
|
1060
|
+
// Hermes: pre-#2841 flat skills/gsd-*/ entries (#5169: `legacyFlatSkillsCleanup`)
|
|
1061
|
+
if (hostBehaviorsFor(runtime).legacyFlatSkillsCleanup) {
|
|
1070
1062
|
const flatSkillsDir = node_path_1.default.join(configDir, 'skills');
|
|
1071
1063
|
if (node_fs_1.default.existsSync(flatSkillsDir)) {
|
|
1072
1064
|
for (const entry of node_fs_1.default.readdirSync(flatSkillsDir, { withFileTypes: true })) {
|
|
@@ -1075,6 +1067,8 @@ function _runLegacyUninstallCleanup(runtime, configDir, scope = 'global') {
|
|
|
1075
1067
|
}
|
|
1076
1068
|
}
|
|
1077
1069
|
}
|
|
1070
|
+
}
|
|
1071
|
+
if (hostBehaviorsFor(runtime).bareStemSkillsCleanup) {
|
|
1078
1072
|
// Hermes: pre-#947 bare-stem skills/gsd/<stem>/ entries (dirs that do NOT
|
|
1079
1073
|
// start with 'gsd-') — the #3664 layout used prefix='' so GSD-owned skills
|
|
1080
1074
|
// had bare names (e.g. skills/gsd/help/). These are stale on uninstall.
|
|
@@ -1132,7 +1126,7 @@ function installRuntimeArtifacts(runtime, configDir, scope, resolvedProfile, res
|
|
|
1132
1126
|
// the dedicated combined commands+skills+plugin orchestrator instead of the
|
|
1133
1127
|
// generic layout-driven loop below, mirroring the bespoke install path that
|
|
1134
1128
|
// previously lived inline in bin/install.js.
|
|
1135
|
-
const behaviors =
|
|
1129
|
+
const behaviors = hostBehaviorsFor(runtime);
|
|
1136
1130
|
const projectDir = scope === 'global' ? process.cwd() : configDir;
|
|
1137
1131
|
if (behaviors.combinedFamilyInstall) {
|
|
1138
1132
|
// #2329: combined-family runtimes (OpenCode/Kilo) bypass
|
|
@@ -1326,7 +1320,7 @@ function installRuntimeArtifacts(runtime, configDir, scope, resolvedProfile, res
|
|
|
1326
1320
|
// with the same prefix). User-owned bare dirs with no gsd-<stem> counterpart
|
|
1327
1321
|
// are untouched.
|
|
1328
1322
|
let hermesBareStemCleanup = false;
|
|
1329
|
-
if (runtime
|
|
1323
|
+
if (hostBehaviorsFor(runtime).bareStemSkillsCleanup) {
|
|
1330
1324
|
const nestedGsdDirForCleanup = node_path_1.default.join(configDir, 'skills', 'gsd');
|
|
1331
1325
|
_removeHermesBareStemDirs(nestedGsdDirForCleanup);
|
|
1332
1326
|
hermesBareStemCleanup = true;
|
|
@@ -1678,7 +1672,7 @@ function installOpencodeFamilyCommands(runtime, destDir, srcDir, pathPrefix, res
|
|
|
1678
1672
|
// already satisfies the fold-to-descriptor requirement. Only the SKILLS
|
|
1679
1673
|
// converter site above (installOpencodeFamilySkills) has a real
|
|
1680
1674
|
// `converter` string to key on via SKILLS_CONVERTER_REGISTRY.
|
|
1681
|
-
content =
|
|
1675
|
+
content = hostBehaviorsFor(runtime).frontmatterDialect === 'kilo'
|
|
1682
1676
|
? runtimeArtifactConversion.convertClaudeToKiloFrontmatter(content)
|
|
1683
1677
|
: runtimeArtifactConversion.convertClaudeToOpencodeFrontmatter(content);
|
|
1684
1678
|
installFs().writeFileSync(node_path_1.default.join(destDir, destName), content);
|
|
@@ -1881,6 +1875,9 @@ function installOpencodeFamilyArtifacts(runtime, configDir, scope, resolvedProfi
|
|
|
1881
1875
|
isWindowsHost: process.platform === 'win32',
|
|
1882
1876
|
resolvedTarget: (0, shell_command_projection_cjs_1.posixNormalize)(node_path_1.default.resolve(configDir)),
|
|
1883
1877
|
homeDir: (0, shell_command_projection_cjs_1.posixNormalize)(node_os_1.default.homedir()),
|
|
1878
|
+
// #4377: the runtime's own localConfigDir, so an opted-in local install
|
|
1879
|
+
// emits `<dir>/...` instead of this checkout's absolute path.
|
|
1880
|
+
localDirName: runtimeArtifactConversion._localIncludeDirName(runtime),
|
|
1884
1881
|
});
|
|
1885
1882
|
// #2329: destDir is derived from the SAME hostBehaviors.flatCommandDir
|
|
1886
1883
|
// descriptor value read by writeManifest's manifest-key prefix and by
|
|
@@ -1958,7 +1955,8 @@ function uninstallRuntimeArtifacts(runtime, configDir, scope, deps = {}) {
|
|
|
1958
1955
|
// the GSD-managed DESCRIPTION.md and then the category dir itself if it
|
|
1959
1956
|
// contains no user content (#947). _removeGsdEntries removed gsd-* dirs
|
|
1960
1957
|
// but left the category container and DESCRIPTION.md intact.
|
|
1961
|
-
|
|
1958
|
+
// (#5169: `hostBehaviors.categoryContainerCleanup`.)
|
|
1959
|
+
if (hostBehaviorsFor(runtime).categoryContainerCleanup) {
|
|
1962
1960
|
const nestedGsdDir = node_path_1.default.join(configDir, 'skills', 'gsd');
|
|
1963
1961
|
if (node_fs_1.default.existsSync(nestedGsdDir)) {
|
|
1964
1962
|
// Remove GSD-owned DESCRIPTION.md (written by writeHermesCategoryDescription)
|
|
@@ -2016,7 +2014,6 @@ module.exports = {
|
|
|
2016
2014
|
installAgentsKindStandalone,
|
|
2017
2015
|
installOpencodeFamilyArtifacts,
|
|
2018
2016
|
_installNativePluginIfDeclared,
|
|
2019
|
-
_hostBehaviors,
|
|
2020
2017
|
_copyStaged,
|
|
2021
2018
|
hasExistingSymlinkBetween,
|
|
2022
2019
|
isSymlinkedDestOptIn,
|
|
@@ -27,6 +27,7 @@ const node_os_1 = __importDefault(require("node:os"));
|
|
|
27
27
|
const installFsAdapter = require("./install-fs-adapter.cjs");
|
|
28
28
|
const { installFs, mkInstallTempDir } = installFsAdapter;
|
|
29
29
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
30
|
+
const frontmatter_fence_cjs_1 = require("./frontmatter-fence.cjs");
|
|
30
31
|
// #2322: reuse the existing pure path-containment seam (ADR-1239 Phase C-2)
|
|
31
32
|
// instead of hand-rolling a new traversal check for capability skill stems.
|
|
32
33
|
const external_descriptor_trust_cjs_1 = require("./external-descriptor-trust.cjs");
|
|
@@ -95,13 +96,15 @@ const PROFILES = Object.freeze({
|
|
|
95
96
|
* Returns string[] — empty array if no requires: field.
|
|
96
97
|
*
|
|
97
98
|
* No external YAML parser dependency — hand-parse the single line
|
|
98
|
-
* since GSD enforces flow-style arrays for requires:.
|
|
99
|
+
* since GSD enforces flow-style arrays for requires:. The block is the one the
|
|
100
|
+
* one fence owner (`locateFrontmatterFence`) finds — a `---` pair later in the
|
|
101
|
+
* body (a thematic break, a YAML example) is never frontmatter.
|
|
99
102
|
*/
|
|
100
103
|
function parseRequires(content) {
|
|
101
|
-
const
|
|
102
|
-
if (!
|
|
104
|
+
const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(content);
|
|
105
|
+
if (!fence?.closed)
|
|
103
106
|
return [];
|
|
104
|
-
const fm =
|
|
107
|
+
const fm = content.slice(fence.openEnd, fence.bodyEnd);
|
|
105
108
|
const line = fm.match(/^requires:\s*(.+)$/m);
|
|
106
109
|
if (!line)
|
|
107
110
|
return [];
|
|
@@ -280,7 +280,14 @@ function readInstallManifest(configDir) {
|
|
|
280
280
|
version: typeof m.version === 'string' ? m.version : null,
|
|
281
281
|
timestamp: typeof m.timestamp === 'string' ? m.timestamp : null,
|
|
282
282
|
mode: typeof m.mode === 'string' ? m.mode : null,
|
|
283
|
-
|
|
283
|
+
// #4544 (review): `typeof [] === 'object'` — a manifest whose `files` is a
|
|
284
|
+
// JSON array passed the object-shape guard, and Object.keys() then yielded
|
|
285
|
+
// "0","1",... as install-relative file paths. Consumers iterate these keys,
|
|
286
|
+
// so an array shape must degrade to the empty set exactly like a
|
|
287
|
+
// non-object shape does.
|
|
288
|
+
files: m.files && typeof m.files === 'object' && !Array.isArray(m.files)
|
|
289
|
+
? m.files
|
|
290
|
+
: {},
|
|
284
291
|
manifestVersion: normalizeManifestVersion(m.manifestVersion),
|
|
285
292
|
runtime: normalizeReportedRuntime(rawRuntime),
|
|
286
293
|
scope: (0, install_scope_cjs_1.isInstallScopeId)(m.scope) ? m.scope : null,
|
package/gsd-core/bin/lib/io.cjs
CHANGED
|
@@ -121,6 +121,84 @@ function writeAllSync(fd, data) {
|
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* Temporarily patch `fs.writeSync` so everything written to fd 1 (stdout) is
|
|
126
|
+
* captured into a string instead of reaching the real stdout, run `run`, then
|
|
127
|
+
* restore the original `fs.writeSync` and resolve with what was captured.
|
|
128
|
+
*
|
|
129
|
+
* The ONE shared helper (#5105 S9) for "run a nested command and read its own
|
|
130
|
+
* JSON envelope back as data instead of letting it reach the real stdout" —
|
|
131
|
+
* used by gsd-tools.cjs's `--pick`/`@file:` resolution and by `uat.cts`'s
|
|
132
|
+
* `cmdUatCompleteSession` (which needs `cmdCommit`'s result object without
|
|
133
|
+
* emitting cmdCommit's own envelope as a second line of output). A single
|
|
134
|
+
* definition means both callers see the same Buffer/string/encoding handling
|
|
135
|
+
* and the same throw-mid-write flush behavior, rather than two hand-rolled
|
|
136
|
+
* monkeypatches drifting apart.
|
|
137
|
+
*
|
|
138
|
+
* On a throw from `run`, whatever was captured before the throw is flushed to
|
|
139
|
+
* the REAL stdout — the wrapped command may have already written its own
|
|
140
|
+
* JSON envelope and THEN thrown to set a non-zero exit code (e.g. a
|
|
141
|
+
* capability set/disable on an unknown id); without this flush that output
|
|
142
|
+
* would be silently discarded, since the success-path flush at the call site
|
|
143
|
+
* never runs on a throw. The error still propagates so the exit code is
|
|
144
|
+
* preserved.
|
|
145
|
+
*/
|
|
146
|
+
function captureStdoutSyncWrites(run) {
|
|
147
|
+
const originalWriteSync = node_fs_1.default.writeSync;
|
|
148
|
+
let captured = '';
|
|
149
|
+
node_fs_1.default.writeSync = ((fd, data, ...rest) => {
|
|
150
|
+
if (fd === 1) {
|
|
151
|
+
if (Buffer.isBuffer(data)) {
|
|
152
|
+
captured += data.toString('utf-8');
|
|
153
|
+
return data.length;
|
|
154
|
+
}
|
|
155
|
+
const text = String(data);
|
|
156
|
+
captured += text;
|
|
157
|
+
let encoding = 'utf-8';
|
|
158
|
+
if (typeof rest[1] === 'string')
|
|
159
|
+
encoding = rest[1];
|
|
160
|
+
return Buffer.byteLength(text, encoding);
|
|
161
|
+
}
|
|
162
|
+
return originalWriteSync.call(node_fs_1.default, fd, data, ...rest);
|
|
163
|
+
});
|
|
164
|
+
const restore = () => {
|
|
165
|
+
node_fs_1.default.writeSync = originalWriteSync;
|
|
166
|
+
};
|
|
167
|
+
return Promise.resolve()
|
|
168
|
+
.then(() => run())
|
|
169
|
+
.then(() => {
|
|
170
|
+
restore();
|
|
171
|
+
return captured;
|
|
172
|
+
}, (err) => {
|
|
173
|
+
restore();
|
|
174
|
+
if (captured) {
|
|
175
|
+
try {
|
|
176
|
+
originalWriteSync.call(node_fs_1.default, 1, captured);
|
|
177
|
+
}
|
|
178
|
+
catch { /* best-effort flush */ }
|
|
179
|
+
}
|
|
180
|
+
throw err;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Resolve `output()`'s `@file:<path>` redirection (emitted for a >50KB JSON
|
|
185
|
+
* payload) back to the real content, or return `captured` unchanged when it
|
|
186
|
+
* is not that shape.
|
|
187
|
+
*
|
|
188
|
+
* #5105 review finding 7: the ONE definition, shared by gsd-tools.cjs's
|
|
189
|
+
* `--pick`/CLI-passthrough resolution and by `uat.cts`'s
|
|
190
|
+
* `cmdUatCompleteSession` (which reads `cmdCommit`'s captured result back
|
|
191
|
+
* without emitting cmdCommit's own envelope as a second stdout line) — same
|
|
192
|
+
* reasoning as `captureStdoutSyncWrites` just below: one definition means
|
|
193
|
+
* both callers agree on the trailing-newline-free prefix and the read
|
|
194
|
+
* encoding, rather than two hand-rolled `startsWith('@file:')` checks
|
|
195
|
+
* drifting apart.
|
|
196
|
+
*/
|
|
197
|
+
function resolveAtFileOutput(captured) {
|
|
198
|
+
if (!captured.startsWith('@file:'))
|
|
199
|
+
return captured;
|
|
200
|
+
return node_fs_1.default.readFileSync(captured.slice('@file:'.length), 'utf-8');
|
|
201
|
+
}
|
|
124
202
|
/**
|
|
125
203
|
* The wire form of a JSON result: the exact bytes `output()` emits for it.
|
|
126
204
|
*
|
|
@@ -290,6 +368,16 @@ const ERROR_REASON = Object.freeze({
|
|
|
290
368
|
// exit 0. See .gsd/phase/feat-3884-failure-is-a-value/40-design.md.
|
|
291
369
|
PICK_FIELD_ABSENT: 'pick_field_absent',
|
|
292
370
|
PICK_OUTPUT_NOT_JSON: 'pick_output_not_json',
|
|
371
|
+
// summary-extract (#5013): the SUMMARY's frontmatter fence exists but failed
|
|
372
|
+
// to parse (extractFrontmatter's FRONTMATTER_UNPARSEABLE marker) — a
|
|
373
|
+
// distinct failure from "no frontmatter"/"field absent", never a silent
|
|
374
|
+
// demotion to empty fields at exit 0.
|
|
375
|
+
SUMMARY_EXTRACT_UNPARSEABLE: 'summary_extract_unparseable',
|
|
376
|
+
// verification (#5118, ADR-5057 Phase 4): a *-VERIFICATION.md frontmatter
|
|
377
|
+
// `status` outside the closed writer set (`passed | gaps_found |
|
|
378
|
+
// human_needed`) — verification.cts's VerificationStatusError, translated
|
|
379
|
+
// once, centrally, by gsd-tools.cjs. Never read as "no result" at exit 0.
|
|
380
|
+
VERIFICATION_STATUS_INVALID: 'verification_status_invalid',
|
|
293
381
|
// generic
|
|
294
382
|
USAGE: 'usage',
|
|
295
383
|
UNKNOWN: 'unknown',
|
|
@@ -334,14 +422,35 @@ const ERROR_REASON = Object.freeze({
|
|
|
334
422
|
* more than one line or introduce an unescaped `"`. Callers embedding the
|
|
335
423
|
* result MUST NOT add their own surrounding quotes — that would
|
|
336
424
|
* double-quote it.
|
|
425
|
+
*
|
|
426
|
+
* #5118 security review: `JSON.stringify` leaves characters that render
|
|
427
|
+
* invisibly or reorder the text around them untouched — DEL and the C1
|
|
428
|
+
* controls (U+007F–U+009F), the line/paragraph separators (U+2028–U+2029),
|
|
429
|
+
* zero-width and directional marks (U+200B–U+200F), the bidi embeddings and
|
|
430
|
+
* overrides (U+202A–U+202E), the bidi isolates (U+2066–U+2069) and the BOM
|
|
431
|
+
* (U+FEFF). Each is escaped as `\uXXXX` so the token reads exactly as its
|
|
432
|
+
* code points are, whoever renders it.
|
|
337
433
|
*/
|
|
434
|
+
const INVISIBLE_OR_BIDI_RANGES = [
|
|
435
|
+
[0x7f, 0x9f],
|
|
436
|
+
[0x2028, 0x2029],
|
|
437
|
+
[0x200b, 0x200f],
|
|
438
|
+
[0x202a, 0x202e],
|
|
439
|
+
[0x2066, 0x2069],
|
|
440
|
+
[0xfeff, 0xfeff],
|
|
441
|
+
];
|
|
442
|
+
/** Code points as `\uXXXX` escape text (source stays ASCII; no literal invisible characters). */
|
|
443
|
+
function toUnicodeEscape(codePoint) {
|
|
444
|
+
return `\\u${codePoint.toString(16).padStart(4, '0')}`;
|
|
445
|
+
}
|
|
446
|
+
const INVISIBLE_OR_BIDI_RE = new RegExp(`[${INVISIBLE_OR_BIDI_RANGES.map(([lo, hi]) => `${toUnicodeEscape(lo)}-${toUnicodeEscape(hi)}`).join('')}]`, 'g');
|
|
338
447
|
function formatDiagnosticToken(value) {
|
|
339
|
-
return JSON.stringify(value);
|
|
448
|
+
return JSON.stringify(value).replace(INVISIBLE_OR_BIDI_RE, (ch) => toUnicodeEscape(ch.charCodeAt(0)));
|
|
340
449
|
}
|
|
341
450
|
/**
|
|
342
451
|
* Map an ERROR_REASON wire value onto a declared outcome name (#3912,
|
|
343
|
-
* ADR-3889 §4). Closed over the
|
|
344
|
-
* explicit entry below, so a
|
|
452
|
+
* ADR-3889 §4). Closed over the 27-member enum: every reason gets an
|
|
453
|
+
* explicit entry below, so a 28th member added without a mapping falls
|
|
345
454
|
* through to the `?? 'FAIL'` default rather than silently mis-projecting —
|
|
346
455
|
* and tests/A1 iterates `Object.values(ERROR_REASON)`, so that default is
|
|
347
456
|
* exactly what makes an unmapped addition visible instead of invisible.
|
|
@@ -389,6 +498,14 @@ const REASON_TO_OUTCOME = Object.freeze({
|
|
|
389
498
|
// supposed to be there and was not; a prerequisite of the query failed.
|
|
390
499
|
[ERROR_REASON.PICK_FIELD_ABSENT]: 'UNAVAILABLE',
|
|
391
500
|
[ERROR_REASON.PICK_OUTPUT_NOT_JSON]: 'UNAVAILABLE',
|
|
501
|
+
// #5013: the SUMMARY's frontmatter fence exists but failed to parse — the
|
|
502
|
+
// prerequisite of the query (readable frontmatter) is what's broken, same
|
|
503
|
+
// shape as PICK_FIELD_ABSENT/PICK_OUTPUT_NOT_JSON just above.
|
|
504
|
+
[ERROR_REASON.SUMMARY_EXTRACT_UNPARSEABLE]: 'UNAVAILABLE',
|
|
505
|
+
// #5118: the verification report exists but its `status` is not a verdict
|
|
506
|
+
// the reader accepts — a broken prerequisite of the query, the same shape
|
|
507
|
+
// as SUMMARY_EXTRACT_UNPARSEABLE just above.
|
|
508
|
+
[ERROR_REASON.VERIFICATION_STATUS_INVALID]: 'UNAVAILABLE',
|
|
392
509
|
// Self-failure: the run itself broke, not its inputs.
|
|
393
510
|
[ERROR_REASON.SDK_FAIL_FAST]: 'INTERNAL',
|
|
394
511
|
[ERROR_REASON.SECURITY_SCAN_FAILED]: 'INTERNAL',
|
|
@@ -433,4 +550,6 @@ module.exports = {
|
|
|
433
550
|
getJsonErrorMode,
|
|
434
551
|
error,
|
|
435
552
|
formatDiagnosticToken,
|
|
553
|
+
captureStdoutSyncWrites,
|
|
554
|
+
resolveAtFileOutput,
|
|
436
555
|
};
|
|
@@ -28,10 +28,19 @@
|
|
|
28
28
|
* - capability-registry.cjs (byLoopPoint, consumed at call time)
|
|
29
29
|
* - capability-state.cjs (resolveCapabilityRuntimeState — for capabilities list)
|
|
30
30
|
*/
|
|
31
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
32
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
33
|
+
};
|
|
34
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
35
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
31
36
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
32
37
|
const ioMod = require("./io.cjs");
|
|
33
38
|
const { output: coreOutput, error: coreError } = ioMod;
|
|
34
39
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
40
|
+
const verificationMod = require("./verification.cjs");
|
|
41
|
+
const { resolvePhaseArtifactFile } = verificationMod;
|
|
42
|
+
const security_cjs_1 = require("./security.cjs");
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
35
44
|
const configLoaderModule = require("./config-loader.cjs");
|
|
36
45
|
const { loadConfig } = configLoaderModule;
|
|
37
46
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
@@ -528,6 +537,56 @@ function resolveActiveHooksForPoint(cwd, point, options = {}) {
|
|
|
528
537
|
const combinedWarnings = [...(state.warnings || []), ...loadFailWarnings];
|
|
529
538
|
return { point: resolved.point, activeHooks: resolved.activeHooks, warnings: combinedWarnings };
|
|
530
539
|
}
|
|
540
|
+
/**
|
|
541
|
+
* #5105 R2: a `produces` entry `p` "exists" in `phaseDir` when it resolves via
|
|
542
|
+
* the SAME phase-artifact selection core `resolveVerificationFile`/
|
|
543
|
+
* `resolveUatFile` delegate to (`resolvePhaseArtifactFile`, `verification.cts`)
|
|
544
|
+
* — no second derivation of "which file counts as this phase's artifact"
|
|
545
|
+
* (#3473 F2's generative-divergence class). That core is pure and takes an
|
|
546
|
+
* already-read directory listing of REGULAR-file names only, so a directory
|
|
547
|
+
* of the same name, or a suffixed near-miss (`p.bak`, `p.tmp`), never counts,
|
|
548
|
+
* and `phaseDirName` scoping rejects a stray cross-phase file (`02-SECURITY.md`
|
|
549
|
+
* inside a `01-foo` phase dir) exactly as the aggregate scans do.
|
|
550
|
+
*/
|
|
551
|
+
function producesEntryPresent(fileNames, phaseDirName, p) {
|
|
552
|
+
return resolvePhaseArtifactFile([...fileNames], p, { phaseDirName, allowBare: true }) !== null;
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* #5105 R2: partition `activeHooks` by whether every one of a `kind:"step"`
|
|
556
|
+
* hook's declared `produces` artifacts already exists (as a regular file)
|
|
557
|
+
* directly in `phaseDir`. A hook with `produces: []` (e.g. mempalace-capture),
|
|
558
|
+
* and every gate/contribution, passes through unchanged in `activeHooks`.
|
|
559
|
+
*
|
|
560
|
+
* Throws when `phaseDir` cannot be read (fail closed — the caller converts
|
|
561
|
+
* this to a `coreError` exit, never a silent pass-everything-through).
|
|
562
|
+
*/
|
|
563
|
+
function partitionHooksByFingerprint(activeHooks, phaseDir) {
|
|
564
|
+
const entries = node_fs_1.default.readdirSync(phaseDir, { withFileTypes: true });
|
|
565
|
+
const fileNames = entries.filter((e) => e.isFile()).map((e) => e.name);
|
|
566
|
+
const phaseDirName = node_path_1.default.basename(phaseDir);
|
|
567
|
+
const kept = [];
|
|
568
|
+
const skipped = [];
|
|
569
|
+
for (const hook of activeHooks) {
|
|
570
|
+
if (hook.kind !== 'step' || !hook.produces || hook.produces.length === 0) {
|
|
571
|
+
kept.push(hook);
|
|
572
|
+
continue;
|
|
573
|
+
}
|
|
574
|
+
const everyProduced = hook.produces.every((p) => producesEntryPresent(fileNames, phaseDirName, p));
|
|
575
|
+
if (everyProduced) {
|
|
576
|
+
skipped.push({
|
|
577
|
+
capId: hook.capId,
|
|
578
|
+
kind: 'step',
|
|
579
|
+
ref: hook.ref,
|
|
580
|
+
reason: 'produces-present',
|
|
581
|
+
artifacts: [...hook.produces],
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
else {
|
|
585
|
+
kept.push(hook);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
return { activeHooks: kept, skippedHooks: skipped };
|
|
589
|
+
}
|
|
531
590
|
function cmdLoopRenderHooks(cwd, point, raw, options = {}) {
|
|
532
591
|
if (!point) {
|
|
533
592
|
coreError('loop render-hooks requires a <point> argument. Valid points: ' + CANONICAL_POINTS.join(', '));
|
|
@@ -548,6 +607,38 @@ function cmdLoopRenderHooks(cwd, point, raw, options = {}) {
|
|
|
548
607
|
coreError(msg);
|
|
549
608
|
return;
|
|
550
609
|
}
|
|
610
|
+
// #5105 R2: --after-fingerprint <phaseDir> — gate out verify:post steps
|
|
611
|
+
// whose declared artifact(s) already exist in phaseDir (execute-phase
|
|
612
|
+
// already dispatched them before its own fingerprint; a re-dispatch here
|
|
613
|
+
// would write a post-fingerprint covered path for no reason, #4981/#4887).
|
|
614
|
+
const afterFingerprintDir = typeof options['afterFingerprint'] === 'string' ? options['afterFingerprint'] : undefined;
|
|
615
|
+
let skippedHooks;
|
|
616
|
+
if (afterFingerprintDir !== undefined) {
|
|
617
|
+
// #5105 S10: resolve relative to the handler's own cwd (never the
|
|
618
|
+
// process cwd) and fail closed if it escapes the project root — the same
|
|
619
|
+
// `requireSafePath` seam `uat.cts`'s `cmdUatCompleteSession` uses for its
|
|
620
|
+
// own path argument.
|
|
621
|
+
let safePhaseDir;
|
|
622
|
+
try {
|
|
623
|
+
safePhaseDir = (0, security_cjs_1.requireSafePath)(afterFingerprintDir, cwd, '--after-fingerprint directory', security_cjs_1.PathAcceptance.AbsoluteInsideRoot);
|
|
624
|
+
}
|
|
625
|
+
catch (err) {
|
|
626
|
+
const msg = (err instanceof Error) ? err.message : String(err);
|
|
627
|
+
coreError(`--after-fingerprint directory is unsafe: ${msg}`);
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
let partition;
|
|
631
|
+
try {
|
|
632
|
+
partition = partitionHooksByFingerprint(result.activeHooks, safePhaseDir);
|
|
633
|
+
}
|
|
634
|
+
catch (err) {
|
|
635
|
+
const msg = (err instanceof Error) ? err.message : String(err);
|
|
636
|
+
coreError(`--after-fingerprint phase directory not found or unreadable: ${afterFingerprintDir} (${msg})`);
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
result = { point: result.point, activeHooks: partition.activeHooks, warnings: result.warnings };
|
|
640
|
+
skippedHooks = partition.skippedHooks;
|
|
641
|
+
}
|
|
551
642
|
if (activeCapId !== undefined) {
|
|
552
643
|
const isActive = result.activeHooks.some((h) => h.capId === activeCapId);
|
|
553
644
|
process.stdout.write(isActive ? 'true\n' : 'false\n');
|
|
@@ -562,6 +653,9 @@ function cmdLoopRenderHooks(cwd, point, raw, options = {}) {
|
|
|
562
653
|
if (result.warnings.length > 0) {
|
|
563
654
|
envelope.warnings = result.warnings;
|
|
564
655
|
}
|
|
656
|
+
if (skippedHooks !== undefined) {
|
|
657
|
+
envelope.skippedHooks = skippedHooks;
|
|
658
|
+
}
|
|
565
659
|
coreOutput(envelope, raw);
|
|
566
660
|
}
|
|
567
661
|
module.exports = {
|
|
@@ -569,6 +663,7 @@ module.exports = {
|
|
|
569
663
|
renderLoopHooks,
|
|
570
664
|
cmdLoopRenderHooks,
|
|
571
665
|
resolveActiveHooksForPoint,
|
|
666
|
+
partitionHooksByFingerprint,
|
|
572
667
|
// Exported for tests
|
|
573
668
|
_getNestedConfigValue,
|
|
574
669
|
_resolveActivationValue,
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* ADR-457 build-at-publish: compiled by tsc to gsd-core/bin/lib/markdown-sectionizer.cjs.
|
|
12
12
|
*/
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.XML_DECISION_TAG_NAMES = void 0;
|
|
14
15
|
exports.stripFencedCode = stripFencedCode;
|
|
15
16
|
exports.stripInlineCode = stripInlineCode;
|
|
16
17
|
exports.scanInlineCodeSpans = scanInlineCodeSpans;
|
|
@@ -21,11 +22,13 @@ exports.collectSections = collectSections;
|
|
|
21
22
|
exports.collectSection = collectSection;
|
|
22
23
|
exports.iterateBullets = iterateBullets;
|
|
23
24
|
exports.updateBullet = updateBullet;
|
|
25
|
+
exports.updateHeading = updateHeading;
|
|
24
26
|
exports.extractTaggedBlocks = extractTaggedBlocks;
|
|
25
27
|
exports.stripTaggedBlocks = stripTaggedBlocks;
|
|
26
28
|
exports.replaceSection = replaceSection;
|
|
27
29
|
exports.withSection = withSection;
|
|
28
30
|
exports.deleteSection = deleteSection;
|
|
31
|
+
exports.extractXmlTagBodies = extractXmlTagBodies;
|
|
29
32
|
const pattern_cjs_1 = require("./pattern.cjs");
|
|
30
33
|
// ─── stripFencedCode ──────────────────────────────────────────────────────────
|
|
31
34
|
/**
|
|
@@ -722,7 +725,7 @@ function updateBullet(content, match, transform) {
|
|
|
722
725
|
bulletText = nm[2];
|
|
723
726
|
}
|
|
724
727
|
}
|
|
725
|
-
if (bulletText !== null && match(bulletText, rawLine)) {
|
|
728
|
+
if (bulletText !== null && match(bulletText, rawLine, i)) {
|
|
726
729
|
const newLine = transform(rawLine);
|
|
727
730
|
if (typeof newLine !== 'string')
|
|
728
731
|
return content;
|
|
@@ -732,6 +735,40 @@ function updateBullet(content, match, transform) {
|
|
|
732
735
|
}
|
|
733
736
|
return content;
|
|
734
737
|
}
|
|
738
|
+
// ─── updateHeading ────────────────────────────────────────────────────────────
|
|
739
|
+
/**
|
|
740
|
+
* Rewrite the physical line of the FIRST ATX heading (outside fenced code)
|
|
741
|
+
* accepted by `match` — the heading analogue of `updateBullet` (ADR-5057 §6,
|
|
742
|
+
* Phase 13, #5217). Heading discovery is `tokenizeHeadings`' (the one fence
|
|
743
|
+
* state machine for headings); this function adds only the splice.
|
|
744
|
+
*
|
|
745
|
+
* `rawLine` (second argument to `match`, the only argument to `transform`) is
|
|
746
|
+
* the UNMODIFIED physical line between `\n` separators, so on a CRLF document
|
|
747
|
+
* its trailing `\r` is included and every untouched byte — including every
|
|
748
|
+
* other line's own terminator — is copied from `content` verbatim. `lineIndex`
|
|
749
|
+
* is the 0-based physical line index, the same indexing as
|
|
750
|
+
* `content.split('\n')`, so a caller holding a pre-computed line-indexed plan
|
|
751
|
+
* can disambiguate two headings with identical text.
|
|
752
|
+
*
|
|
753
|
+
* Bounded no-op: no accepted heading, or `transform` returning a non-string,
|
|
754
|
+
* returns `content` unchanged.
|
|
755
|
+
*/
|
|
756
|
+
function updateHeading(content, match, transform) {
|
|
757
|
+
if (typeof content !== 'string' || content.length === 0)
|
|
758
|
+
return content;
|
|
759
|
+
for (const heading of tokenizeHeadings(content)) {
|
|
760
|
+
const newlineAt = content.indexOf('\n', heading.offset);
|
|
761
|
+
const lineEnd = newlineAt === -1 ? content.length : newlineAt;
|
|
762
|
+
const rawLine = content.slice(heading.offset, lineEnd);
|
|
763
|
+
if (!match(heading, rawLine, heading.line - 1))
|
|
764
|
+
continue;
|
|
765
|
+
const newLine = transform(rawLine);
|
|
766
|
+
if (typeof newLine !== 'string')
|
|
767
|
+
return content;
|
|
768
|
+
return content.slice(0, heading.offset) + newLine + content.slice(lineEnd);
|
|
769
|
+
}
|
|
770
|
+
return content;
|
|
771
|
+
}
|
|
735
772
|
// ─── extractTaggedBlocks ──────────────────────────────────────────────────────
|
|
736
773
|
/**
|
|
737
774
|
* Return the inner text of every `<tagName>…</tagName>` block in `content`,
|
|
@@ -962,5 +999,42 @@ function deleteSection(content, headingPredicate, opts = {}) {
|
|
|
962
999
|
const collapsedBefore = before.replace(/(?:\r\n|\n){3,}$/, (m) => (m.includes('\r\n') ? '\r\n\r\n' : '\n\n'));
|
|
963
1000
|
return collapsedBefore + after;
|
|
964
1001
|
}
|
|
1002
|
+
// ─── extractXmlTagBodies ──────────────────────────────────────────────────────
|
|
1003
|
+
// #2372: scanned-tag set must match the planner-canonical surfaces where a D-NN citation
|
|
1004
|
+
// is meaningful. `<objective>`/`<tasks>`/`<task>`/`<action>` are the historical core. The
|
|
1005
|
+
// planner is also explicitly told (plan-phase.md) to cite decisions in `<read_first>`,
|
|
1006
|
+
// `<behavior>`, `<verify>`, `<acceptance_criteria>`, and `<done>` — those are scanned too,
|
|
1007
|
+
// so the decision-coverage gate does not report a false gap when a decision is cited in any of them.
|
|
1008
|
+
//
|
|
1009
|
+
// Implementation: per-tag matching, NOT a single wide alternation. A single alternation
|
|
1010
|
+
// like `<(?:a|b|c)>...<\/(?:a|b|c)>` halts the outer tag's body capture at any inner tag
|
|
1011
|
+
// in the set, dropping any citation in the outer tag's prefix prose — e.g.
|
|
1012
|
+
// `<action>per D-05 <verify>npm test</verify></action>` would lose D-05 because `<verify>`
|
|
1013
|
+
// halts the `<action>` body before the citation. Per-tag matching avoids this: each tag's
|
|
1014
|
+
// body terminates only at its OWN closing tag, so `<verify>` inside `<action>` is absorbed
|
|
1015
|
+
// into `<action>`'s body (D-05 caught) AND `<verify>` is matched separately on its own pass.
|
|
1016
|
+
// Each per-tag regex keeps the ReDoS-safe negative-lookahead tempering (#2128).
|
|
1017
|
+
exports.XML_DECISION_TAG_NAMES = ['objective', 'tasks', 'task', 'action', 'read_first', 'behavior', 'verify', 'acceptance_criteria', 'done'];
|
|
1018
|
+
function buildXmlDecisionTagRegex(tagName) {
|
|
1019
|
+
// Per-tag: body tempering stops only at the SAME tag's reopening or closing — other
|
|
1020
|
+
// scanned tags pass through as text into this body. Non-greedy `*?` to first close.
|
|
1021
|
+
return new RegExp(`<${tagName}(?:\\s[^>]{0,1000})?>((?:(?!<${tagName}[\\s>])[\\s\\S])*?)<\\/${tagName}>`, 'gi');
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* The bodies of every planner-canonical XML tag (`XML_DECISION_TAG_NAMES`) in `text`,
|
|
1025
|
+
* joined by `\n`. Each tag's body ends only at its OWN closing tag, so an inner scanned tag
|
|
1026
|
+
* is absorbed into the outer body AND matched on its own pass.
|
|
1027
|
+
*/
|
|
1028
|
+
function extractXmlTagBodies(text) {
|
|
1029
|
+
const parts = [];
|
|
1030
|
+
for (const tagName of exports.XML_DECISION_TAG_NAMES) {
|
|
1031
|
+
const re = buildXmlDecisionTagRegex(tagName);
|
|
1032
|
+
for (const match of text.matchAll(re)) {
|
|
1033
|
+
if (match[1])
|
|
1034
|
+
parts.push(match[1]);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
return parts.join('\n');
|
|
1038
|
+
}
|
|
965
1039
|
// Consumers: require('../gsd-core/bin/lib/markdown-sectionizer.cjs')
|
|
966
1040
|
// Named CJS exports are the canonical surface (ADR-457 .cts → .cjs build-at-publish).
|