@opengsd/gsd-core 1.10.0 → 1.12.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/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-debug-session-manager.md +12 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-dom-verifier.md +169 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +22 -14
- package/agents/gsd-framework-selector.md +1 -3
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +5 -3
- package/agents/gsd-pattern-mapper.md +11 -0
- package/agents/gsd-phase-researcher.md +23 -2
- package/agents/gsd-plan-checker.md +50 -53
- package/agents/gsd-planner.md +50 -50
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.md +2 -2
- package/agents/gsd-roadmapper.md +15 -11
- package/agents/gsd-ui-checker.md +63 -4
- package/agents/gsd-ui-researcher.md +41 -3
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +13 -4
- package/bin/install.js +1448 -1103
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/discuss-phase.md +1 -1
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/import.md +1 -1
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/quick.md +9 -5
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +1035 -138
- package/gsd-core/bin/lib/active-workstream-store.cjs +146 -22
- package/gsd-core/bin/lib/adr-parser.cjs +13 -7
- package/gsd-core/bin/lib/agent-install-check.cjs +392 -32
- package/gsd-core/bin/lib/api-coverage.cjs +33 -14
- package/gsd-core/bin/lib/artifacts.cjs +5 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +32 -15
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +1026 -268
- package/gsd-core/bin/lib/broken-windows.cjs +306 -28
- 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-lock.cjs +10 -4
- package/gsd-core/bin/lib/capability-registry.cjs +845 -130
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-state.cjs +18 -3
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +700 -40
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +216 -42
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/cli-exit.cjs +496 -10
- package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +735 -0
- package/gsd-core/bin/lib/command-aliases.cjs +22 -0
- package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
- package/gsd-core/bin/lib/commands.cjs +1172 -108
- package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
- package/gsd-core/bin/lib/complexity-trigger.cjs +1192 -0
- package/gsd-core/bin/lib/config-loader.cjs +187 -23
- package/gsd-core/bin/lib/config.cjs +102 -3
- package/gsd-core/bin/lib/configuration.cjs +129 -37
- package/gsd-core/bin/lib/core-utils.cjs +208 -33
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/edge-probe.cjs +9 -1
- package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
- package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +899 -229
- package/gsd-core/bin/lib/gap-checker.cjs +95 -10
- package/gsd-core/bin/lib/git-base-branch.cjs +276 -39
- package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
- 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 +149 -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 +268 -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 +187 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +451 -0
- package/gsd-core/bin/lib/host-integration.cjs +39 -6
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init-command-router.cjs +118 -21
- package/gsd-core/bin/lib/init.cjs +439 -168
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +811 -259
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +235 -0
- package/gsd-core/bin/lib/install-profiles.cjs +212 -61
- 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-report.cjs +3 -0
- package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +148 -38
- package/gsd-core/bin/lib/intel.cjs +101 -26
- package/gsd-core/bin/lib/io.cjs +170 -15
- package/gsd-core/bin/lib/learnings.cjs +85 -14
- package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
- package/gsd-core/bin/lib/markdown-table.cjs +183 -22
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +842 -73
- package/gsd-core/bin/lib/model-catalog.cjs +232 -16
- package/gsd-core/bin/lib/model-resolver.cjs +193 -68
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +18 -9
- package/gsd-core/bin/lib/phase-id.cjs +514 -40
- package/gsd-core/bin/lib/phase-lifecycle.cjs +52 -19
- package/gsd-core/bin/lib/phase-locator.cjs +262 -34
- package/gsd-core/bin/lib/phase.cjs +1038 -214
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
- package/gsd-core/bin/lib/plan-document.cjs +263 -0
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +98 -3
- package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +894 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +112 -6
- package/gsd-core/bin/lib/probe-core.cjs +5 -2
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
- package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
- package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +766 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +22 -13
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +59 -11
- package/gsd-core/bin/lib/roadmap-parser.cjs +1006 -184
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +442 -96
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +702 -52
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +459 -55
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +402 -58
- package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +96 -8
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +342 -7
- package/gsd-core/bin/lib/smart-entry.cjs +133 -23
- package/gsd-core/bin/lib/spec-section.cjs +12 -7
- package/gsd-core/bin/lib/state-command-router.cjs +52 -19
- package/gsd-core/bin/lib/state-contract.cjs +359 -0
- package/gsd-core/bin/lib/state-document.cjs +338 -8
- package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
- package/gsd-core/bin/lib/state-transition.cjs +846 -176
- package/gsd-core/bin/lib/state.cjs +2589 -369
- package/gsd-core/bin/lib/surface.cjs +33 -11
- package/gsd-core/bin/lib/task-command-router.cjs +111 -1
- package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
- package/gsd-core/bin/lib/teams-status.cjs +4 -1
- 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 +67 -23
- package/gsd-core/bin/lib/uat.cjs +1761 -167
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +51 -12
- package/gsd-core/bin/lib/unusable-input.cjs +37 -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-command-router.cjs +2 -2
- package/gsd-core/bin/lib/validate.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +75 -0
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -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 +272 -9
- package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
- package/gsd-core/bin/lib/verify.cjs +453 -918
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
- package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
- package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
- package/gsd-core/bin/lib/workstream.cjs +2 -2
- package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
- package/gsd-core/bin/lib/worktree-safety.cjs +341 -18
- package/gsd-core/bin/shared/config-defaults.manifest.json +8 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +12 -1
- package/gsd-core/bin/shared/exit-codes.json +8 -0
- package/gsd-core/bin/shared/exit-codes.sh +20 -0
- package/gsd-core/bin/shared/model-catalog.json +8 -1
- package/gsd-core/references/agent-contracts.md +44 -26
- package/gsd-core/references/api-coverage.md +24 -2
- package/gsd-core/references/autonomous-smart-discuss.md +3 -3
- package/gsd-core/references/checkpoints.md +39 -21
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/decimal-phase-calculation.md +5 -5
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/edge-probe.md +8 -0
- package/gsd-core/references/execute-mvp-tdd.md +4 -6
- package/gsd-core/references/execute-phase-between-wave-reset.md +15 -14
- 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 +17 -11
- package/gsd-core/references/failing-direction.md +78 -0
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-integration.md +5 -5
- package/gsd-core/references/git-planning-commit.md +5 -4
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +61 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/nyquist-compliance.md +74 -0
- package/gsd-core/references/offer-next.md +3 -5
- package/gsd-core/references/phase-argument-parsing.md +3 -3
- package/gsd-core/references/planner-failing-direction.md +53 -0
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-human-verify-mode.md +15 -1
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planner-revision.md +1 -1
- package/gsd-core/references/planner-verify-command-grounding.md +17 -0
- package/gsd-core/references/planning-config.md +44 -13
- package/gsd-core/references/reviewer-instances.md +31 -0
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/runtime-aware-dispatch.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +1 -1
- package/gsd-core/references/tdd.md +1 -3
- package/gsd-core/references/ui-brand.md +65 -21
- package/gsd-core/references/ui-consideration-probe.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +5 -5
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verify-command-path-resolvability.md +42 -0
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -17
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/SECURITY.md +3 -3
- package/gsd-core/templates/UI-SPEC.md +25 -3
- package/gsd-core/templates/VALIDATION.md +3 -3
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +5 -4
- package/gsd-core/templates/state.md +11 -4
- package/gsd-core/templates/verification-report.md +9 -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 +3 -3
- package/gsd-core/workflows/add-tests.md +3 -8
- package/gsd-core/workflows/add-todo.md +1 -1
- package/gsd-core/workflows/ai-integration-phase.md +13 -20
- package/gsd-core/workflows/audit-fix.md +12 -3
- package/gsd-core/workflows/audit-milestone.md +9 -9
- package/gsd-core/workflows/audit-uat.md +17 -2
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
- package/gsd-core/workflows/autonomous.md +11 -27
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +64 -5
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +14 -4
- package/gsd-core/workflows/code-review-fix.md +38 -11
- package/gsd-core/workflows/code-review.md +159 -52
- package/gsd-core/workflows/complete-milestone.md +151 -23
- package/gsd-core/workflows/debug.md +12 -8
- package/gsd-core/workflows/diagnose-issues.md +47 -15
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -8
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +3 -6
- package/gsd-core/workflows/docs-update.md +5 -4
- package/gsd-core/workflows/edit-phase.md +27 -2
- package/gsd-core/workflows/eval-review.md +7 -14
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +142 -15
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
- 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 +24 -4
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
- package/gsd-core/workflows/execute-phase.md +72 -100
- package/gsd-core/workflows/execute-plan.md +52 -15
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +5 -5
- package/gsd-core/workflows/health.md +76 -10
- package/gsd-core/workflows/import.md +18 -15
- package/gsd-core/workflows/inbox.md +4 -5
- package/gsd-core/workflows/ingest-docs.md +49 -16
- package/gsd-core/workflows/insert-phase.md +5 -5
- package/gsd-core/workflows/list-seeds.md +5 -3
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +12 -23
- package/gsd-core/workflows/map-codebase.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +8 -5
- package/gsd-core/workflows/new-milestone.md +22 -29
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +26 -40
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +14 -2
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
- package/gsd-core/workflows/plan-phase.md +162 -59
- package/gsd-core/workflows/plan-review-convergence.md +96 -11
- package/gsd-core/workflows/plant-seed.md +2 -2
- package/gsd-core/workflows/pr-branch.md +187 -51
- package/gsd-core/workflows/profile-user.md +16 -14
- package/gsd-core/workflows/progress.md +61 -18
- package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +5 -7
- package/gsd-core/workflows/quick/steps/quick-verification.md +28 -9
- package/gsd-core/workflows/quick/steps/research-phase.md +4 -6
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
- package/gsd-core/workflows/quick.md +55 -44
- package/gsd-core/workflows/remove-phase.md +4 -4
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +8 -12
- package/gsd-core/workflows/review.md +219 -20
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +3 -3
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings-advanced.md +7 -9
- package/gsd-core/workflows/settings-integrations.md +64 -31
- package/gsd-core/workflows/settings.md +69 -7
- package/gsd-core/workflows/ship.md +116 -50
- package/gsd-core/workflows/sketch-wrap-up.md +11 -17
- package/gsd-core/workflows/sketch.md +12 -18
- package/gsd-core/workflows/smart-entry.md +3 -5
- package/gsd-core/workflows/spec-phase.md +53 -13
- package/gsd-core/workflows/spike-wrap-up.md +7 -11
- package/gsd-core/workflows/spike.md +20 -31
- package/gsd-core/workflows/stats.md +2 -2
- package/gsd-core/workflows/sync-skills.md +64 -9
- package/gsd-core/workflows/thread.md +11 -7
- package/gsd-core/workflows/transition.md +49 -14
- package/gsd-core/workflows/ui-phase.md +15 -21
- package/gsd-core/workflows/ui-review.md +8 -12
- package/gsd-core/workflows/ultraplan-phase.md +5 -13
- package/gsd-core/workflows/undo.md +8 -16
- package/gsd-core/workflows/update.md +7 -11
- package/gsd-core/workflows/validate-phase.md +3 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +66 -25
- package/hooks/dist/gsd-agent-isolation-guard.js +158 -30
- package/hooks/dist/gsd-check-update-worker.js +56 -13
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-config-reload.js +18 -12
- package/hooks/dist/gsd-context-monitor.js +19 -10
- package/hooks/dist/gsd-cursor-post-tool.js +3 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +2 -3
- package/hooks/dist/gsd-cursor-session-start.js +2 -1
- package/hooks/dist/gsd-cursor-stop.js +2 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +83 -3
- package/hooks/dist/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
- package/hooks/dist/gsd-graphify-update.sh +22 -18
- package/hooks/dist/gsd-node-runner.sh +76 -0
- package/hooks/dist/gsd-phase-boundary.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +37 -27
- package/hooks/dist/gsd-read-guard.js +16 -7
- package/hooks/dist/gsd-read-injection-scanner.js +55 -32
- package/hooks/dist/gsd-session-state.sh +1 -0
- package/hooks/dist/gsd-statusline.js +231 -24
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-validate-commit.sh +80 -6
- package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
- package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
- package/hooks/dist/gsd-workflow-guard.js +162 -46
- package/hooks/dist/gsd-worktree-path-guard.js +36 -21
- package/hooks/dist/gsd-write-guard.js +35 -25
- package/hooks/dist/lib/cli-exit.js +560 -0
- package/hooks/dist/lib/exit-code-registry.js +98 -0
- package/hooks/dist/lib/git-cmd.js +92 -59
- package/hooks/dist/lib/git-probe.js +84 -0
- package/hooks/dist/lib/hook-exit.js +81 -0
- 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 +9 -0
- package/hooks/dist/managed-hooks-registry.cjs +3 -0
- package/hooks/gsd-agent-isolation-guard.js +158 -30
- package/hooks/gsd-check-update-worker.js +56 -13
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-config-reload.js +18 -12
- package/hooks/gsd-context-monitor.js +19 -10
- package/hooks/gsd-cursor-post-tool.js +3 -1
- package/hooks/gsd-cursor-pre-tool.js +2 -3
- package/hooks/gsd-cursor-session-start.js +2 -1
- package/hooks/gsd-cursor-stop.js +2 -1
- package/hooks/gsd-cursor-subagent-start.js +83 -3
- package/hooks/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/gsd-ensure-canonical-path.js +2 -1
- package/hooks/gsd-graphify-update.sh +22 -18
- package/hooks/gsd-node-runner.sh +76 -0
- package/hooks/gsd-phase-boundary.sh +1 -0
- package/hooks/gsd-prompt-guard.js +37 -27
- package/hooks/gsd-read-guard.js +16 -7
- package/hooks/gsd-read-injection-scanner.js +55 -32
- package/hooks/gsd-session-state.sh +1 -0
- package/hooks/gsd-statusline.js +231 -24
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-validate-commit.sh +80 -6
- package/hooks/gsd-windsurf-pre-command.js +16 -11
- package/hooks/gsd-windsurf-pre-write.js +22 -13
- package/hooks/gsd-workflow-guard.js +162 -46
- package/hooks/gsd-worktree-path-guard.js +36 -21
- package/hooks/gsd-write-guard.js +35 -25
- package/hooks/lib/cli-exit.js +560 -0
- package/hooks/lib/exit-code-registry.js +98 -0
- package/hooks/lib/git-cmd.js +92 -59
- package/hooks/lib/git-probe.js +84 -0
- package/hooks/lib/hook-exit.js +81 -0
- package/hooks/lib/injection-patterns.js +45 -0
- package/hooks/lib/isolation-deny-reason.js +39 -0
- package/hooks/lib/isolation-sentinel.js +9 -0
- package/hooks/managed-hooks-registry.cjs +3 -0
- package/package.json +28 -11
- package/pi/gsd.cjs +19 -5
- package/scripts/base64-scan.sh +74 -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 +5 -0
- package/scripts/changeset/lint.cjs +60 -5
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/check-glossary-refs.cjs +77 -15
- package/scripts/check-mutation-score-ratchet.cjs +156 -0
- package/scripts/ci-check-job-near-cap.cjs +49 -0
- package/scripts/ci-pr-mergeability.cjs +262 -0
- package/scripts/ci-test-scope.cjs +64 -14
- package/scripts/ci-timeout-report.cjs +230 -0
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/docs-guard-registry.cjs +396 -0
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-registry.cjs +11 -21
- package/scripts/gen-context-index.cjs +2 -11
- package/scripts/gen-exit-code-docs.cjs +318 -0
- package/scripts/gen-exit-code-registry.cjs +891 -0
- package/scripts/gen-features.cjs +836 -0
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-hooks-cli-exit.cjs +239 -0
- package/scripts/gen-install-tree-fixtures.cjs +2 -2
- package/scripts/gen-inventory-manifest.cjs +50 -4
- package/scripts/gen-loop-host-contract.cjs +138 -25
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/gen-scripts-cli-exit.cjs +185 -0
- package/scripts/gen-state-md-docs.cjs +727 -0
- package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/ci-job-timing.cjs +72 -0
- package/scripts/lib/cli-exit.cjs +546 -44
- package/scripts/lib/drift-scan.cjs +308 -0
- package/scripts/lib/exit-code-registry.cjs +98 -0
- package/scripts/lib/ndjson-reporter.cjs +119 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
- 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-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-guard-registration.cjs +495 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +38 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +461 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
- package/scripts/lint-phase-enumeration-drift.cjs +492 -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 +471 -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 +488 -0
- package/scripts/lint-seam-enforcement.cjs +182 -0
- package/scripts/lint-slug-derivation-drift.cjs +921 -0
- package/scripts/lint-source-test-name-collision.cjs +241 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +950 -0
- package/scripts/lint-test-file-count.allowlist.json +137 -8
- package/scripts/lint-test-file-count.cjs +25 -3
- package/scripts/lint-unreachable-guard-drift.cjs +830 -0
- package/scripts/lint-vendored-deps.cjs +297 -0
- package/scripts/mutation-matrix.cjs +599 -50
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +100 -14
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/secret-scan.sh +75 -13
- package/scripts/select-docs-guards.cjs +56 -0
- package/scripts/sync-runtime-launcher.cjs +24 -7
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-discuss-phase/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- package/skills/gsd-import/SKILL.md +1 -1
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +0 -1
- package/skills/gsd-progress/SKILL.md +0 -1
- package/skills/gsd-quick/SKILL.md +9 -5
- 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/bin/lib/ui-safety-gate.cjs +0 -107
- 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 -574
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/lint-emitted-drift-ack.cjs +0 -344
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1051
|
@@ -56,12 +56,22 @@
|
|
|
56
56
|
const fs = require('fs');
|
|
57
57
|
const path = require('path');
|
|
58
58
|
const os = require('os');
|
|
59
|
+
const { allow } = require('./lib/hook-exit.js');
|
|
59
60
|
|
|
60
61
|
// Workspace resolution is shared across the Cursor hooks (#2587) — see
|
|
61
62
|
// hooks/lib/cursor-workspace.js. Staged next to these scripts by
|
|
62
63
|
// writeCursorHooksJson so the require always resolves post-install.
|
|
63
64
|
const { resolveStatePath } = require('./lib/cursor-workspace.js');
|
|
64
65
|
const { readSentinel, VALID_ISOLATION, extractDispatchIdentifiers, sentinelAppliesToDispatch } = require('./lib/isolation-sentinel.js');
|
|
66
|
+
const { REASON_CODE } = require('./lib/isolation-deny-reason.js');
|
|
67
|
+
// #3582: gsd-core/bin/lib/*.cjs (runtime-homes.cjs, worktree-safety.cjs,
|
|
68
|
+
// runtime-name-policy.cjs, capability-registry.cjs — required below, inside
|
|
69
|
+
// resolveIsolationEvidence and resolveFallbackIsolation) are tsc build
|
|
70
|
+
// artifacts (ADR-457), gitignored and absent on a raw plugin-marketplace /
|
|
71
|
+
// git-clone install that never ran `npm run build:lib`. Self-heal once, in
|
|
72
|
+
// evaluateRootIsolation, before any of those four requires run — see the
|
|
73
|
+
// call site below. This module itself depends on nothing under ./lib.
|
|
74
|
+
const { ensureRuntimeBuild, RuntimeBuildError } = require('../gsd-core/bin/ensure-runtime-build.cjs');
|
|
65
75
|
|
|
66
76
|
const MSG_PRESENT =
|
|
67
77
|
'GSD: Subagent session started — review .planning/STATE.md for the current phase and any blockers before acting.';
|
|
@@ -333,6 +343,41 @@ function resolveIsolationDecision(data, { clock = Date, realpath = fs.realpathSy
|
|
|
333
343
|
return { action: 'allow' };
|
|
334
344
|
}
|
|
335
345
|
|
|
346
|
+
// ─── #3897 rung 2: per-install runtime marker, single canonical owner ────────
|
|
347
|
+
// bin/install.js writes `<install>/gsd-core/.gsd-runtime` beside VERSION for
|
|
348
|
+
// every runtime install (#2297); this hook ships at `<install>/hooks/`, so the
|
|
349
|
+
// marker is the `gsd-core` sibling of this file's own directory. Previously
|
|
350
|
+
// this hook held its own private reader/cache (one of four #3897 found); it
|
|
351
|
+
// now delegates to the single canonical owner, `src/runtime-slash.cts`
|
|
352
|
+
// (compiled to gsd-core/bin/lib/runtime-slash.cjs), reached through
|
|
353
|
+
// `ensureRuntimeBuild()` like the other compiled-lib requires in this file
|
|
354
|
+
// (`scripts/lint-hooks-runtime-build-seam.cjs`).
|
|
355
|
+
function readInstallRuntimeMarker() {
|
|
356
|
+
try {
|
|
357
|
+
ensureRuntimeBuild();
|
|
358
|
+
const runtimeSlash = require('../gsd-core/bin/lib/runtime-slash.cjs');
|
|
359
|
+
return runtimeSlash.readInstallRuntimeMarker();
|
|
360
|
+
} catch {
|
|
361
|
+
// Unbuilt runtime library, or any other failure reaching the canonical
|
|
362
|
+
// owner — "no signal from this rung", never a resolution failure.
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Test seam — forwards to the canonical owner's seam so this hook and
|
|
368
|
+
// runtime-slash.cjs always share one cache (#3897 rung 2). Spawned-hook tests
|
|
369
|
+
// (fresh process, no marker) are unaffected.
|
|
370
|
+
function _setInstallRuntimeMarkerForTests(value) {
|
|
371
|
+
try {
|
|
372
|
+
ensureRuntimeBuild();
|
|
373
|
+
const runtimeSlash = require('../gsd-core/bin/lib/runtime-slash.cjs');
|
|
374
|
+
runtimeSlash._setInstallRuntimeMarkerForTests(value);
|
|
375
|
+
} catch {
|
|
376
|
+
// Test-only seam; an unbuilt library here means the test itself will fail
|
|
377
|
+
// downstream, which is a louder and more actionable signal than throwing here.
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
336
381
|
/**
|
|
337
382
|
* Conservative fallback resolution used when the #3045 sentinel is absent or
|
|
338
383
|
* stale for `root`: re-derive isolation from the registry CAPABILITY, gated
|
|
@@ -355,7 +400,8 @@ function resolveIsolationDecision(data, { clock = Date, realpath = fs.realpathSy
|
|
|
355
400
|
* otherwise legitimate dispatches, unlike `hooks/gsd-agent-isolation-guard.js`,
|
|
356
401
|
* which degrades an undeterminable runtime to inert (#3045 MAJOR 2). Aligned
|
|
357
402
|
* here: an explicit signal is now required — `GSD_RUNTIME` > config.json
|
|
358
|
-
* `runtime` key >
|
|
403
|
+
* `runtime` key > the per-install `.gsd-runtime` marker (#3566) >
|
|
404
|
+
* `~/.gsd/defaults.json` `runtime` (mirrors the Claude hook's
|
|
359
405
|
* `resolveRuntimeIdentity`; `bin/install.js`'s `writeNonClaudeDefaults`
|
|
360
406
|
* persists the installed runtime there for every non-Claude install,
|
|
361
407
|
* including Cursor, so a REAL Cursor+GSD install still resolves confidently
|
|
@@ -372,6 +418,13 @@ function resolveFallbackIsolation(root, configPath) {
|
|
|
372
418
|
if (!runtimeId && parsedConfig && typeof parsedConfig === 'object' && 'runtime' in parsedConfig) {
|
|
373
419
|
runtimeId = resolveRuntimeNameFromCandidates(parsedConfig.runtime) || null;
|
|
374
420
|
}
|
|
421
|
+
if (!runtimeId) {
|
|
422
|
+
// #3566: the per-install marker, above the host-wide defaults — same fix as
|
|
423
|
+
// hooks/gsd-agent-isolation-guard.js's resolveRuntimeIdentity. defaults.json
|
|
424
|
+
// is host-wide and names whichever runtime installed LAST (#2840's poison);
|
|
425
|
+
// the marker describes THIS install (written for every runtime since #2297).
|
|
426
|
+
runtimeId = resolveRuntimeNameFromCandidates(readInstallRuntimeMarker()) || null;
|
|
427
|
+
}
|
|
375
428
|
if (!runtimeId) {
|
|
376
429
|
try {
|
|
377
430
|
const defaultsPath = path.join(os.homedir(), '.gsd', 'defaults.json');
|
|
@@ -419,6 +472,28 @@ function evaluateRootIsolation(root, subagentType, { clock = Date, dispatchIds =
|
|
|
419
472
|
}
|
|
420
473
|
if (!isGsdProject) return { action: 'allow' };
|
|
421
474
|
|
|
475
|
+
// #3582: self-heal the compiled runtime library BEFORE any of its four
|
|
476
|
+
// downstream requires (resolveFallbackIsolation's two, resolveIsolationEvidence's
|
|
477
|
+
// two — reached only below this point). Checked separately from the
|
|
478
|
+
// sentinel/fallback try block below so a build failure surfaces its own
|
|
479
|
+
// actionable RuntimeBuildError message rather than being folded into the
|
|
480
|
+
// generic "could not read or resolve ... configuration" deny reason (the
|
|
481
|
+
// #3050 misreport this issue exists to fix). Still fails closed either way.
|
|
482
|
+
try {
|
|
483
|
+
ensureRuntimeBuild();
|
|
484
|
+
} catch (err) {
|
|
485
|
+
return {
|
|
486
|
+
action: 'deny',
|
|
487
|
+
reason:
|
|
488
|
+
`GSD subagent isolation guard: cannot resolve this project's dispatch-isolation ` +
|
|
489
|
+
`configuration because the GSD runtime library failed to self-build. ` +
|
|
490
|
+
`${err instanceof RuntimeBuildError ? err.message : String(err && err.message || err)} ` +
|
|
491
|
+
`Refusing to allow this subagent to spawn until the runtime library is built — a guard ` +
|
|
492
|
+
`that cannot verify must not answer "safe" (#3050).`,
|
|
493
|
+
reasonCode: REASON_CODE.RUNTIME_BUILD_FAILED,
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
|
|
422
497
|
let declaredIsolation;
|
|
423
498
|
try {
|
|
424
499
|
// #3045 BLOCKER fix: a fresh sentinel is authoritative for THIS
|
|
@@ -439,6 +514,7 @@ function evaluateRootIsolation(root, subagentType, { clock = Date, dispatchIds =
|
|
|
439
514
|
`Refusing to allow this subagent to spawn without being able to verify whether ` +
|
|
440
515
|
`isolation is required — a guard that cannot verify must not answer "safe" (#3050). ` +
|
|
441
516
|
`Retry once the project configuration is readable.`,
|
|
517
|
+
reasonCode: REASON_CODE.CONFIG_UNREADABLE,
|
|
442
518
|
};
|
|
443
519
|
}
|
|
444
520
|
|
|
@@ -455,6 +531,7 @@ function evaluateRootIsolation(root, subagentType, { clock = Date, dispatchIds =
|
|
|
455
531
|
`"harness-worktree", but the subagentStart payload for this dispatch carries no usable ` +
|
|
456
532
|
`subagent_type. Refusing to allow it to spawn without being able to confirm whether it ` +
|
|
457
533
|
`is a GSD executor — a guard that cannot verify must not answer "safe" (#3050).`,
|
|
534
|
+
reasonCode: REASON_CODE.NO_SUBAGENT_TYPE,
|
|
458
535
|
};
|
|
459
536
|
}
|
|
460
537
|
|
|
@@ -471,6 +548,7 @@ function evaluateRootIsolation(root, subagentType, { clock = Date, dispatchIds =
|
|
|
471
548
|
`could not be determined (git did not respond). Refusing to allow subagent_type=` +
|
|
472
549
|
`"${subagentType}" to spawn without being able to verify isolation — a guard that ` +
|
|
473
550
|
`cannot verify must not answer "safe" (#3050). Retry once git is responsive.`,
|
|
551
|
+
reasonCode: REASON_CODE.CANNOT_DETERMINE_ISOLATION,
|
|
474
552
|
};
|
|
475
553
|
}
|
|
476
554
|
|
|
@@ -483,6 +561,7 @@ function evaluateRootIsolation(root, subagentType, { clock = Date, dispatchIds =
|
|
|
483
561
|
`directly, with no consent and no warning. Start an isolated session first (the ` +
|
|
484
562
|
`"--worktree" CLI flag or the "/worktree" chat command; Cursor manages these worktrees ` +
|
|
485
563
|
`under "~/.cursor/worktrees/") and retry.`,
|
|
564
|
+
reasonCode: REASON_CODE.NOT_ISOLATED_WORKTREE,
|
|
486
565
|
};
|
|
487
566
|
}
|
|
488
567
|
|
|
@@ -490,7 +569,7 @@ function evaluateRootIsolation(root, subagentType, { clock = Date, dispatchIds =
|
|
|
490
569
|
function main() {
|
|
491
570
|
let raw = '';
|
|
492
571
|
const stdinTimeout = setTimeout(() => {
|
|
493
|
-
|
|
572
|
+
allow(undefined);
|
|
494
573
|
}, 10000);
|
|
495
574
|
|
|
496
575
|
process.stdin.setEncoding('utf8');
|
|
@@ -532,7 +611,7 @@ function main() {
|
|
|
532
611
|
decision = { action: 'allow' };
|
|
533
612
|
}
|
|
534
613
|
if (decision.action === 'deny') {
|
|
535
|
-
const out = { permission: 'deny', user_message: decision.reason };
|
|
614
|
+
const out = { permission: 'deny', user_message: decision.reason, reason_code: decision.reasonCode };
|
|
536
615
|
if (additionalContext !== null) out.additional_context = additionalContext;
|
|
537
616
|
process.stdout.write(JSON.stringify(out));
|
|
538
617
|
return;
|
|
@@ -557,4 +636,5 @@ module.exports = {
|
|
|
557
636
|
resolveFallbackIsolation,
|
|
558
637
|
resolveIsolationEvidence,
|
|
559
638
|
getWorkspaceRoots,
|
|
639
|
+
_setInstallRuntimeMarkerForTests,
|
|
560
640
|
};
|
|
@@ -20,13 +20,16 @@
|
|
|
20
20
|
|
|
21
21
|
'use strict';
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
const { allow } = require('./lib/hook-exit.js');
|
|
24
|
+
|
|
24
25
|
const stdinTimeout = setTimeout(() => {
|
|
25
|
-
|
|
26
|
+
allow(undefined);
|
|
26
27
|
}, 10000);
|
|
27
28
|
|
|
28
29
|
process.stdin.setEncoding('utf8');
|
|
29
|
-
|
|
30
|
+
// Drain stdin (puts the stream into flowing mode so 'end' fires); the
|
|
31
|
+
// payload itself is unused — this hook responds unconditionally.
|
|
32
|
+
process.stdin.on('data', () => {});
|
|
30
33
|
process.stdin.on('end', () => {
|
|
31
34
|
clearTimeout(stdinTimeout);
|
|
32
35
|
try {
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
const fs = require('fs');
|
|
35
35
|
const path = require('path');
|
|
36
36
|
const os = require('os');
|
|
37
|
+
const { allow } = require('./lib/hook-exit.js');
|
|
37
38
|
|
|
38
39
|
// Immutable, bundled subdirectories that the canonical path must expose. These
|
|
39
40
|
// are the directories `@~/.claude/gsd-core/<subdir>/...` includes point into.
|
|
@@ -301,5 +302,5 @@ if (require.main === module) {
|
|
|
301
302
|
} catch (_) {
|
|
302
303
|
// Best-effort: a canonical-path failure must never abort a session.
|
|
303
304
|
}
|
|
304
|
-
|
|
305
|
+
allow(undefined);
|
|
305
306
|
}
|
|
@@ -9,17 +9,20 @@
|
|
|
9
9
|
# graphify.auto_update defaults to false so existing users see no behavior change.
|
|
10
10
|
#
|
|
11
11
|
# Gates (in fast-fail order — each shaves work off the common non-dispatch path):
|
|
12
|
+
# 0. .planning/config.json exists AND $CI unset/empty (#3729 — both are
|
|
13
|
+
# parse-free shell tests; running them before the Gate 1 node spawn keeps
|
|
14
|
+
# non-GSD repositories and CI off the spawn path entirely, which on
|
|
15
|
+
# Windows otherwise flashes a console window per Bash call)
|
|
12
16
|
# 1. Stdin payload present and tool_name == "Bash"
|
|
13
17
|
# 2. tool_input.command matches a HEAD-advancing git op (shell-direct or
|
|
14
18
|
# the exact `gsd-tools query commit` command shape; the SDK command invokes
|
|
15
19
|
# git internally, so the literal "git commit" substring never appears —
|
|
16
20
|
# see #3653)
|
|
17
|
-
# 3.
|
|
18
|
-
# 4.
|
|
19
|
-
# 5.
|
|
20
|
-
# 6.
|
|
21
|
-
# 7.
|
|
22
|
-
# 8. No rebuild already in flight (PID lock — kill -0 check, stale-tolerant)
|
|
21
|
+
# 3. Inside a git repo
|
|
22
|
+
# 4. Current branch == default branch (git.base_branch override, else main/master/trunk)
|
|
23
|
+
# 5. .planning/config.json sets graphify.enabled=true AND graphify.auto_update=true
|
|
24
|
+
# 6. graphify binary on PATH
|
|
25
|
+
# 7. No rebuild already in flight (PID lock — kill -0 check, stale-tolerant)
|
|
23
26
|
#
|
|
24
27
|
# When all gates pass:
|
|
25
28
|
# - Writes .planning/graphs/.last-build-status.json with status="running"
|
|
@@ -30,6 +33,13 @@
|
|
|
30
33
|
|
|
31
34
|
set -uo pipefail
|
|
32
35
|
|
|
36
|
+
# Gate 0 — GSD project at all, and not CI (#3729). Both are pure shell tests;
|
|
37
|
+
# they must precede the Gate 1 node spawn so the common non-GSD/CI path pays
|
|
38
|
+
# for zero child processes. Hoisting is behavior-preserving: old Gates 3 and 6
|
|
39
|
+
# made the same decisions, just later.
|
|
40
|
+
[ -f .planning/config.json ] || exit 0
|
|
41
|
+
[ -z "${CI:-}" ] || exit 0
|
|
42
|
+
|
|
33
43
|
# Gate 1 — tool_name == Bash; extract command
|
|
34
44
|
INPUT=$(cat 2>/dev/null || true)
|
|
35
45
|
[ -n "$INPUT" ] || exit 0
|
|
@@ -71,22 +81,17 @@ case "$COMMAND" in
|
|
|
71
81
|
*) exit 0 ;;
|
|
72
82
|
esac
|
|
73
83
|
|
|
74
|
-
# Gate 3 —
|
|
75
|
-
[ -z "${CI:-}" ] || exit 0
|
|
76
|
-
|
|
77
|
-
# Gate 4 — inside git repo
|
|
84
|
+
# Gate 3 — inside git repo
|
|
78
85
|
git rev-parse --git-dir >/dev/null 2>&1 || exit 0
|
|
79
86
|
|
|
80
|
-
# Gate
|
|
87
|
+
# Gate 4 — current branch == default branch (config guaranteed by Gate 0)
|
|
81
88
|
DEFAULT_BRANCH=""
|
|
82
|
-
|
|
83
|
-
DEFAULT_BRANCH=$(node -e '
|
|
89
|
+
DEFAULT_BRANCH=$(node -e '
|
|
84
90
|
try {
|
|
85
91
|
const c = require("./.planning/config.json");
|
|
86
92
|
process.stdout.write(c.git?.base_branch || "");
|
|
87
93
|
} catch { process.stdout.write(""); }
|
|
88
94
|
' 2>/dev/null || echo "")
|
|
89
|
-
fi
|
|
90
95
|
if [ -z "$DEFAULT_BRANCH" ]; then
|
|
91
96
|
for cand in main master trunk; do
|
|
92
97
|
if git rev-parse --verify "$cand" >/dev/null 2>&1; then
|
|
@@ -100,8 +105,7 @@ fi
|
|
|
100
105
|
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
|
|
101
106
|
[ "$CURRENT_BRANCH" = "$DEFAULT_BRANCH" ] || exit 0
|
|
102
107
|
|
|
103
|
-
# Gate
|
|
104
|
-
[ -f .planning/config.json ] || exit 0
|
|
108
|
+
# Gate 5 — both graphify gates true in config (file existence checked at Gate 0)
|
|
105
109
|
GATES=$(node -e '
|
|
106
110
|
try {
|
|
107
111
|
const c = require("./.planning/config.json");
|
|
@@ -111,11 +115,11 @@ try {
|
|
|
111
115
|
' 2>/dev/null || echo "0")
|
|
112
116
|
[ "$GATES" = "1" ] || exit 0
|
|
113
117
|
|
|
114
|
-
# Gate
|
|
118
|
+
# Gate 6 — graphify on PATH
|
|
115
119
|
GRAPHIFY_BIN=$(command -v graphify 2>/dev/null || true)
|
|
116
120
|
[ -n "$GRAPHIFY_BIN" ] || exit 0
|
|
117
121
|
|
|
118
|
-
# Gate
|
|
122
|
+
# Gate 7 — no live rebuild in flight
|
|
119
123
|
mkdir -p .planning/graphs
|
|
120
124
|
LOCK_FILE=".planning/graphs/.rebuild.lock"
|
|
121
125
|
if [ -f "$LOCK_FILE" ]; then
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# gsd-node-runner.sh — GSD portable node resolver (#3662).
|
|
3
|
+
#
|
|
4
|
+
# Managed JS hook commands under --portable-hooks route through this script:
|
|
5
|
+
#
|
|
6
|
+
# bash "<hooks>/gsd-node-runner.sh" "<baked-node-path>" "<script.js>" [args...]
|
|
7
|
+
#
|
|
8
|
+
# so a config root shared across environments (mounted ~/.claude, shared
|
|
9
|
+
# containers) resolves node at hook-fire time instead of depending on the
|
|
10
|
+
# absolute path of whichever environment ran the installer. Candidates, in
|
|
11
|
+
# order — the first executable one wins:
|
|
12
|
+
#
|
|
13
|
+
# 1. the first argument — the install-time node path, tried FIRST and by
|
|
14
|
+
# absolute path so the #2979/#3002/#3017/#3022 minimal-PATH guarantee
|
|
15
|
+
# holds (GUI launches with a stripped PATH still resolve where the
|
|
16
|
+
# baked path exists);
|
|
17
|
+
# 2. `command -v node`, accepted only when it yields an absolute path;
|
|
18
|
+
# 3. the well-known stable layouts: $HOME-derived mise/volta shims, the
|
|
19
|
+
# Homebrew prefixes, /usr/local/bin/node, /usr/bin/node.
|
|
20
|
+
#
|
|
21
|
+
# No bare `node` lookup is ever depended on: a candidate is used only after
|
|
22
|
+
# an explicit executable check, and when nothing resolves this script fails
|
|
23
|
+
# visibly (stderr diagnostic + exit 127) rather than emitting a half-resolved
|
|
24
|
+
# invocation.
|
|
25
|
+
#
|
|
26
|
+
# The candidate list below is a SUPERSET of the inline chain token emitted by
|
|
27
|
+
# buildNodeRunnerChainToken (src/runtime-hooks-surface.cts, #3662) — keep the
|
|
28
|
+
# two lists consistent.
|
|
29
|
+
#
|
|
30
|
+
# Diagnostic escape: GSD_NODE_RUNNER_NO_FALLBACKS=1 disables candidates 2-3
|
|
31
|
+
# (first-argument-only resolution) — used by the test suite and useful to
|
|
32
|
+
# pin down which node a given environment picks.
|
|
33
|
+
set -u
|
|
34
|
+
|
|
35
|
+
preferred=${1:-}
|
|
36
|
+
script=${2:-}
|
|
37
|
+
if [ -n "$script" ]; then
|
|
38
|
+
shift 2
|
|
39
|
+
elif [ -n "$preferred" ]; then
|
|
40
|
+
shift 1
|
|
41
|
+
preferred=
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
found=''
|
|
45
|
+
|
|
46
|
+
# check <path> — record <path> if it is an absolute, executable file.
|
|
47
|
+
# Absolute = POSIX root (/*) or a win32 drive-letter path (C:/…), which is
|
|
48
|
+
# what the installer bakes on Windows; anything else (a relative `command -v`
|
|
49
|
+
# hit under a relative PATH entry, a bare name) is rejected so repo-cwd
|
|
50
|
+
# content can never reach the runner slot.
|
|
51
|
+
check() {
|
|
52
|
+
case "$1" in
|
|
53
|
+
/*|[A-Za-z]:/*) if [ -x "$1" ]; then found=$1; fi ;;
|
|
54
|
+
esac
|
|
55
|
+
[ -n "$found" ]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
check "$preferred" || {
|
|
59
|
+
if [ "${GSD_NODE_RUNNER_NO_FALLBACKS:-0}" != "1" ]; then
|
|
60
|
+
path_node=$(command -v node 2>/dev/null || true)
|
|
61
|
+
check "$path_node" ||
|
|
62
|
+
check "${HOME:-}/.local/share/mise/shims/node" ||
|
|
63
|
+
check "${HOME:-}/.volta/bin/node" ||
|
|
64
|
+
check /opt/homebrew/bin/node ||
|
|
65
|
+
check /usr/local/bin/node ||
|
|
66
|
+
check /usr/bin/node ||
|
|
67
|
+
true
|
|
68
|
+
fi
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if [ -z "$found" ]; then
|
|
72
|
+
echo "gsd-node-runner: no usable node found (preferred: ${preferred:-<none>})" >&2
|
|
73
|
+
exit 127
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
exec "$found" "$script" "$@"
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#
|
|
7
7
|
# OPT-IN: This hook is a no-op unless config.json has hooks.community: true.
|
|
8
8
|
# Enable with: "hooks": { "community": true } in .planning/config.json
|
|
9
|
+
set -euo pipefail
|
|
9
10
|
|
|
10
11
|
# Check opt-in config — exit silently if not enabled
|
|
11
12
|
if [ -f .planning/config.json ]; then
|
|
@@ -11,26 +11,21 @@
|
|
|
11
11
|
// The goal is to surface suspicious content so the orchestrator can inspect it,
|
|
12
12
|
// not to create false-positive deadlocks.
|
|
13
13
|
|
|
14
|
-
const fs = require('fs');
|
|
15
14
|
const path = require('path');
|
|
15
|
+
const { HOOK_ON_CRASH, allow, crash } = require('./lib/hook-exit.js');
|
|
16
16
|
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
/<\/?(?:system|assistant|human)>/i,
|
|
30
|
-
/\[SYSTEM\]/i,
|
|
31
|
-
/\[INST\]/i,
|
|
32
|
-
/<<\s*SYS\s*>>/i,
|
|
33
|
-
];
|
|
17
|
+
// This guard is advisory-only by design (see header) — it never blocks the
|
|
18
|
+
// Write/Edit it scans, only adds context about it. A crash here must not
|
|
19
|
+
// start blocking now, which is strictly worse than the advisory it exists
|
|
20
|
+
// to add on top of an already-permitted operation (#3911).
|
|
21
|
+
const ON_CRASH = HOOK_ON_CRASH.ALLOW;
|
|
22
|
+
|
|
23
|
+
// Prompt injection patterns — shared with gsd-read-injection-scanner.js via
|
|
24
|
+
// hooks/lib/injection-patterns.js so the two surfaces cannot drift (#3504).
|
|
25
|
+
// Deliberately a subset of security.cjs's set: hooks stay loadable without the
|
|
26
|
+
// compiled lib tree. Staging of the lib helper is allowlisted in
|
|
27
|
+
// GSD_HOOK_LIB_FILES (bin/install.js).
|
|
28
|
+
const { INJECTION_PATTERNS } = require('./lib/injection-patterns.js');
|
|
34
29
|
|
|
35
30
|
// #2304: Kimi's native hook bus delivers Kimi's tool vocabulary in the payload
|
|
36
31
|
// (Write → WriteFile, Edit/MultiEdit → StrReplaceFile) while the [[hooks]]
|
|
@@ -127,7 +122,7 @@ function normalizeKimiPayload(data) {
|
|
|
127
122
|
}
|
|
128
123
|
|
|
129
124
|
let input = '';
|
|
130
|
-
const stdinTimeout = setTimeout(() =>
|
|
125
|
+
const stdinTimeout = setTimeout(() => allow(undefined), 3000);
|
|
131
126
|
process.stdin.setEncoding('utf8');
|
|
132
127
|
process.stdin.on('data', chunk => input += chunk);
|
|
133
128
|
process.stdin.on('end', () => {
|
|
@@ -138,7 +133,7 @@ process.stdin.on('end', () => {
|
|
|
138
133
|
|
|
139
134
|
// Only scan Write and Edit operations
|
|
140
135
|
if (toolName !== 'Write' && toolName !== 'Edit') {
|
|
141
|
-
|
|
136
|
+
allow(undefined);
|
|
142
137
|
}
|
|
143
138
|
|
|
144
139
|
// #2595 (review Major 3, sibling sweep): typed read. A non-string
|
|
@@ -150,13 +145,26 @@ process.stdin.on('end', () => {
|
|
|
150
145
|
|
|
151
146
|
// Only scan files going into .planning/ (agent context files)
|
|
152
147
|
if (!filePath.includes('.planning/') && !filePath.includes('.planning\\')) {
|
|
153
|
-
|
|
148
|
+
allow(undefined);
|
|
154
149
|
}
|
|
155
150
|
|
|
156
|
-
// Get the content being written
|
|
157
|
-
|
|
151
|
+
// Get the content being written. #3504 (isolated review finding 3): the
|
|
152
|
+
// bare `||` chain handed a NON-STRING truthy `content` straight to
|
|
153
|
+
// pattern.test(), where ToString can throw ("Cannot convert object to a
|
|
154
|
+
// primitive value" for `{"toString": null}`) into the outer catch — the
|
|
155
|
+
// exact crash-to-allow class #2547/#2595 hardened inside
|
|
156
|
+
// normalizeKimiPayload, unreached on this read. Guarded selection: take
|
|
157
|
+
// the first field that is a string, or String-coerces without throwing,
|
|
158
|
+
// so a poisoned `content` no longer shadows a real `new_string`.
|
|
159
|
+
let content = '';
|
|
160
|
+
for (const candidate of [data.tool_input?.content, data.tool_input?.new_string]) {
|
|
161
|
+
if (typeof candidate === 'string' && candidate) { content = candidate; break; }
|
|
162
|
+
if (candidate && typeof candidate !== 'string') {
|
|
163
|
+
try { const s = String(candidate); if (s) { content = s; break; } } catch { /* keep looking */ }
|
|
164
|
+
}
|
|
165
|
+
}
|
|
158
166
|
if (!content) {
|
|
159
|
-
|
|
167
|
+
allow(undefined);
|
|
160
168
|
}
|
|
161
169
|
|
|
162
170
|
// Scan for injection patterns
|
|
@@ -173,7 +181,7 @@ process.stdin.on('end', () => {
|
|
|
173
181
|
}
|
|
174
182
|
|
|
175
183
|
if (findings.length === 0) {
|
|
176
|
-
|
|
184
|
+
allow(undefined);
|
|
177
185
|
}
|
|
178
186
|
|
|
179
187
|
// Advisory warning — does not block the operation
|
|
@@ -190,7 +198,9 @@ process.stdin.on('end', () => {
|
|
|
190
198
|
|
|
191
199
|
process.stdout.write(JSON.stringify(output));
|
|
192
200
|
} catch {
|
|
193
|
-
// Silent fail — never block tool execution
|
|
194
|
-
|
|
201
|
+
// Silent fail — never block tool execution.
|
|
202
|
+
// ON_CRASH is declared ALLOW at module top: this preserves today's
|
|
203
|
+
// exit(0) fail-open behavior exactly (#3911).
|
|
204
|
+
crash(ON_CRASH, undefined);
|
|
195
205
|
}
|
|
196
206
|
});
|
package/hooks/gsd-read-guard.js
CHANGED
|
@@ -20,6 +20,13 @@
|
|
|
20
20
|
|
|
21
21
|
const fs = require('fs');
|
|
22
22
|
const path = require('path');
|
|
23
|
+
const { HOOK_ON_CRASH, allow, crash } = require('./lib/hook-exit.js');
|
|
24
|
+
|
|
25
|
+
// This guard is pure advisory UX — a reminder to Read before Write/Edit on
|
|
26
|
+
// non-Claude-Code runtimes. A crash here must not block a legitimate Write/
|
|
27
|
+
// Edit; the worst outcome of failing open is the model hitting the runtime's
|
|
28
|
+
// own read-before-edit rejection it was trying to help avoid (#3911).
|
|
29
|
+
const ON_CRASH = HOOK_ON_CRASH.ALLOW;
|
|
23
30
|
|
|
24
31
|
// #2304: Kimi's native hook bus delivers Kimi's tool vocabulary in the payload
|
|
25
32
|
// (Write → WriteFile, Edit/MultiEdit → StrReplaceFile) while the [[hooks]]
|
|
@@ -116,7 +123,7 @@ function normalizeKimiPayload(data) {
|
|
|
116
123
|
}
|
|
117
124
|
|
|
118
125
|
let input = '';
|
|
119
|
-
const stdinTimeout = setTimeout(() =>
|
|
126
|
+
const stdinTimeout = setTimeout(() => allow(undefined), 3000);
|
|
120
127
|
process.stdin.setEncoding('utf8');
|
|
121
128
|
process.stdin.on('data', chunk => input += chunk);
|
|
122
129
|
process.stdin.on('end', () => {
|
|
@@ -127,7 +134,7 @@ process.stdin.on('end', () => {
|
|
|
127
134
|
|
|
128
135
|
// Only intercept Write and Edit tool calls
|
|
129
136
|
if (toolName !== 'Write' && toolName !== 'Edit') {
|
|
130
|
-
|
|
137
|
+
allow(undefined);
|
|
131
138
|
}
|
|
132
139
|
|
|
133
140
|
// Claude Code natively enforces read-before-edit — skip the advisory (#1984, #2344, #2520).
|
|
@@ -151,7 +158,7 @@ process.stdin.on('end', () => {
|
|
|
151
158
|
process.env.CLAUDE_SESSION_ID ||
|
|
152
159
|
process.env.CLAUDECODE;
|
|
153
160
|
if (isClaudeCode) {
|
|
154
|
-
|
|
161
|
+
allow(undefined);
|
|
155
162
|
}
|
|
156
163
|
|
|
157
164
|
// #2595 (review Major 3, sibling sweep): typed read — same class as the
|
|
@@ -160,7 +167,7 @@ process.stdin.on('end', () => {
|
|
|
160
167
|
? data.tool_input.file_path
|
|
161
168
|
: '';
|
|
162
169
|
if (!filePath) {
|
|
163
|
-
|
|
170
|
+
allow(undefined);
|
|
164
171
|
}
|
|
165
172
|
|
|
166
173
|
// Only inject guidance when the file already exists.
|
|
@@ -174,7 +181,7 @@ process.stdin.on('end', () => {
|
|
|
174
181
|
}
|
|
175
182
|
|
|
176
183
|
if (!fileExists) {
|
|
177
|
-
|
|
184
|
+
allow(undefined);
|
|
178
185
|
}
|
|
179
186
|
|
|
180
187
|
const fileName = path.basename(filePath);
|
|
@@ -193,7 +200,9 @@ process.stdin.on('end', () => {
|
|
|
193
200
|
|
|
194
201
|
process.stdout.write(JSON.stringify(output));
|
|
195
202
|
} catch {
|
|
196
|
-
// Silent fail — never block tool execution
|
|
197
|
-
|
|
203
|
+
// Silent fail — never block tool execution.
|
|
204
|
+
// ON_CRASH is declared ALLOW at module top: this preserves today's
|
|
205
|
+
// exit(0) fail-open behavior exactly (#3911).
|
|
206
|
+
crash(ON_CRASH, undefined);
|
|
198
207
|
}
|
|
199
208
|
});
|