@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
|
@@ -19,9 +19,19 @@
|
|
|
19
19
|
* hook's own __dirname:
|
|
20
20
|
*
|
|
21
21
|
* const { isGitSubcommand } = require(path.join(__dirname, 'lib', 'git-cmd.js'));
|
|
22
|
+
*
|
|
23
|
+
* `tokenize()` delegates to the shared `src/token-scanner.cts` seam (ADR-3212
|
|
24
|
+
* §4, epic #3212 Phase 3, #3414) — the built `gsd-core/bin/lib/token-scanner.cjs`
|
|
25
|
+
* artifact, not a sibling hooks/-tree file, because hook scripts are staged as
|
|
26
|
+
* standalone files at install time and a sibling require is a staging
|
|
27
|
+
* dependency that can fail silently (see gsd-workflow-guard.js's own
|
|
28
|
+
* KIMI_TOOL_NAMES comment for the precedent this follows). Re-exported here
|
|
29
|
+
* unchanged — every existing caller's behavior is identical (parity-asserted
|
|
30
|
+
* in tests/token-scanner.test.cjs row 5).
|
|
22
31
|
*/
|
|
23
32
|
|
|
24
33
|
const path = require('path');
|
|
34
|
+
const { tokenizeShellLike } = require(path.join(__dirname, '..', '..', 'gsd-core', 'bin', 'lib', 'token-scanner.cjs'));
|
|
25
35
|
|
|
26
36
|
/**
|
|
27
37
|
* Git global options that take a following argument.
|
|
@@ -29,6 +39,7 @@ const path = require('path');
|
|
|
29
39
|
*/
|
|
30
40
|
const ARGUMENT_TAKING_FLAGS = new Set([
|
|
31
41
|
'-C', // working directory
|
|
42
|
+
'-c', // config override (separate-arg form: `git -c k=v …`; #3504)
|
|
32
43
|
'--git-dir', // path to git repository
|
|
33
44
|
'--work-tree', // path to working tree
|
|
34
45
|
'--namespace', // git namespace
|
|
@@ -57,94 +68,116 @@ const BOOLEAN_FLAGS = new Set([
|
|
|
57
68
|
* Handles single-quoted strings, double-quoted strings, and unquoted tokens.
|
|
58
69
|
* Does NOT perform variable expansion or brace expansion.
|
|
59
70
|
*
|
|
71
|
+
* Delegates to the shared `src/token-scanner.cts` seam — see the module
|
|
72
|
+
* header comment for why the built artifact, not a sibling require, is used.
|
|
73
|
+
*
|
|
60
74
|
* @param {string} cmd
|
|
61
75
|
* @returns {string[]}
|
|
62
76
|
*/
|
|
63
77
|
function tokenize(cmd) {
|
|
64
|
-
|
|
65
|
-
let i = 0;
|
|
66
|
-
const len = cmd.length;
|
|
67
|
-
|
|
68
|
-
while (i < len) {
|
|
69
|
-
// Skip whitespace
|
|
70
|
-
while (i < len && /\s/.test(cmd[i])) i++;
|
|
71
|
-
if (i >= len) break;
|
|
72
|
-
|
|
73
|
-
let token = '';
|
|
74
|
-
while (i < len && !/\s/.test(cmd[i])) {
|
|
75
|
-
if (cmd[i] === "'") {
|
|
76
|
-
// Single-quoted string: take everything until closing '
|
|
77
|
-
i++;
|
|
78
|
-
while (i < len && cmd[i] !== "'") token += cmd[i++];
|
|
79
|
-
if (i < len) i++; // consume closing '
|
|
80
|
-
} else if (cmd[i] === '"') {
|
|
81
|
-
// Double-quoted string: take everything until closing " (no escape handling)
|
|
82
|
-
i++;
|
|
83
|
-
while (i < len && cmd[i] !== '"') token += cmd[i++];
|
|
84
|
-
if (i < len) i++; // consume closing "
|
|
85
|
-
} else {
|
|
86
|
-
token += cmd[i++];
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (token) tokens.push(token);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return tokens;
|
|
78
|
+
return tokenizeShellLike(cmd);
|
|
93
79
|
}
|
|
94
80
|
|
|
95
81
|
/**
|
|
96
|
-
*
|
|
82
|
+
* Walk past leading env-prefix assignments and global git options, same as
|
|
83
|
+
* `isGitSubcommand`'s phases 1-3. Returns the index of the subcommand token,
|
|
84
|
+
* or -1 if the command does not resolve to a git invocation at all.
|
|
97
85
|
*
|
|
98
|
-
* @param {string}
|
|
99
|
-
* @
|
|
100
|
-
* @returns {boolean}
|
|
86
|
+
* @param {string[]} tokens
|
|
87
|
+
* @returns {number}
|
|
101
88
|
*/
|
|
102
|
-
function
|
|
103
|
-
if (!cmd || !sub) return false;
|
|
104
|
-
|
|
105
|
-
const tokens = tokenize(cmd);
|
|
89
|
+
function skipToSubcommand(tokens) {
|
|
106
90
|
let i = 0;
|
|
107
|
-
|
|
108
|
-
// Phase 1: skip leading VAR=VALUE environment assignments
|
|
109
91
|
while (i < tokens.length && /^[A-Za-z_][A-Za-z0-9_]*=/.test(tokens[i])) {
|
|
110
92
|
i++;
|
|
111
93
|
}
|
|
112
|
-
|
|
113
|
-
// Phase 2: the next token must be the git executable
|
|
114
|
-
if (i >= tokens.length) return false;
|
|
94
|
+
if (i >= tokens.length) return -1;
|
|
115
95
|
const gitToken = tokens[i++];
|
|
116
|
-
if (path.basename(gitToken) !== 'git') return
|
|
96
|
+
if (path.basename(gitToken) !== 'git') return -1;
|
|
117
97
|
|
|
118
|
-
// Phase 3: consume git global options
|
|
119
98
|
while (i < tokens.length) {
|
|
120
99
|
const t = tokens[i];
|
|
121
|
-
|
|
122
|
-
// --flag=value form for argument-taking flags
|
|
123
100
|
const eqIdx = t.indexOf('=');
|
|
124
101
|
const flagName = eqIdx !== -1 ? t.slice(0, eqIdx) : t;
|
|
125
102
|
if (ARGUMENT_TAKING_FLAGS.has(flagName)) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
103
|
+
i += eqIdx !== -1 ? 1 : 2;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
// #3504: glued `-ckey=value` form — git accepts the config override with
|
|
107
|
+
// its argument attached (`git -cfoo.bar=1 …`). The eq-slice above yields
|
|
108
|
+
// flagName `-cfoo`, which no set contains, so without this arm the walk
|
|
109
|
+
// stops and the whole invocation is misclassified as not-git.
|
|
110
|
+
if (/^-c\S*=/.test(t)) {
|
|
111
|
+
i++;
|
|
133
112
|
continue;
|
|
134
113
|
}
|
|
135
|
-
|
|
136
114
|
if (BOOLEAN_FLAGS.has(t)) {
|
|
137
115
|
i++;
|
|
138
116
|
continue;
|
|
139
117
|
}
|
|
140
|
-
|
|
141
|
-
// Not a global option — this is the subcommand
|
|
142
118
|
break;
|
|
143
119
|
}
|
|
120
|
+
return i;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Extract the branch-name argument from a git command line that creates or
|
|
125
|
+
* references one — `git checkout -b <name>` or `git branch <name>`. Returns
|
|
126
|
+
* null for any other command, including plain `git checkout <ref>` (switches
|
|
127
|
+
* branches, does not create one) and commands where a checkout/branch-shaped
|
|
128
|
+
* substring appears only inside a quoted argument (e.g. a commit message).
|
|
129
|
+
*
|
|
130
|
+
* New capability (ADR-3212 §4, epic #3212 Phase 3, #3414) exercising the
|
|
131
|
+
* shared scanner on the domain the ADR names ("a branch name... [is] not
|
|
132
|
+
* regular") — not a migration of existing duplicated logic; no prior
|
|
133
|
+
* implementation of this existed in the repo (design doc §1.2).
|
|
134
|
+
*
|
|
135
|
+
* @param {string} cmd
|
|
136
|
+
* @returns {string | null}
|
|
137
|
+
*/
|
|
138
|
+
function extractBranchArgument(cmd) {
|
|
139
|
+
if (!cmd) return null;
|
|
140
|
+
const tokens = tokenizeShellLike(cmd);
|
|
141
|
+
const subIdx = skipToSubcommand(tokens);
|
|
142
|
+
if (subIdx === -1 || subIdx >= tokens.length) return null;
|
|
143
|
+
const sub = tokens[subIdx];
|
|
144
|
+
|
|
145
|
+
if (sub === 'checkout') {
|
|
146
|
+
for (let j = subIdx + 1; j < tokens.length; j++) {
|
|
147
|
+
if (tokens[j] === '-b' && j + 1 < tokens.length) return tokens[j + 1];
|
|
148
|
+
}
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (sub === 'branch') {
|
|
153
|
+
for (let j = subIdx + 1; j < tokens.length; j++) {
|
|
154
|
+
if (!tokens[j].startsWith('-')) return tokens[j];
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Return true if `cmd` invokes the git subcommand `sub`.
|
|
164
|
+
*
|
|
165
|
+
* @param {string} cmd - Full shell command string (may include env vars, full paths)
|
|
166
|
+
* @param {string} sub - Subcommand to test for, e.g. 'commit'
|
|
167
|
+
* @returns {boolean}
|
|
168
|
+
*/
|
|
169
|
+
function isGitSubcommand(cmd, sub) {
|
|
170
|
+
if (!cmd || !sub) return false;
|
|
171
|
+
|
|
172
|
+
// Phases 1-3 (env-prefix skip, git-executable check, global-option consume)
|
|
173
|
+
// extracted verbatim into skipToSubcommand — byte-identical logic, shared
|
|
174
|
+
// with extractBranchArgument rather than a second copy (#3212 Phase 3).
|
|
175
|
+
const tokens = tokenizeShellLike(cmd);
|
|
176
|
+
const subIdx = skipToSubcommand(tokens);
|
|
144
177
|
|
|
145
178
|
// Phase 4: check the subcommand
|
|
146
|
-
if (
|
|
147
|
-
return tokens[
|
|
179
|
+
if (subIdx === -1 || subIdx >= tokens.length) return false;
|
|
180
|
+
return tokens[subIdx] === sub;
|
|
148
181
|
}
|
|
149
182
|
|
|
150
|
-
module.exports = { isGitSubcommand, tokenize };
|
|
183
|
+
module.exports = { isGitSubcommand, tokenize, extractBranchArgument, skipToSubcommand };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// hooks/lib/git-probe.js — classify a bounded spawnSync(git, ...) result,
|
|
3
|
+
// distinguishing a GENUINE negative answer (git ran and said "no") from
|
|
4
|
+
// "could not determine" (timeout / spawn failure / signal kill) — #3911.
|
|
5
|
+
//
|
|
6
|
+
// Proven defect: hooks/gsd-worktree-path-guard.js, hooks/gsd-workflow-guard.js,
|
|
7
|
+
// and hooks/gsd-windsurf-pre-write.js each treat spawnSync(git, ..., {timeout})
|
|
8
|
+
// returning a non-zero/empty result as "not applicable" and allow silently.
|
|
9
|
+
// A macOS CI run showed three deny cases land at 2084ms/2112ms/2177ms — just
|
|
10
|
+
// past the 2000ms budget — each returning exit 0 with EMPTY stdout AND EMPTY
|
|
11
|
+
// stderr: a timeout is INDISTINGUISHABLE, at the call site, from git cleanly
|
|
12
|
+
// answering "not a repo" / "not this worktree" unless the spawnSync() result
|
|
13
|
+
// itself is inspected for `error`/`signal`, not just `status`/`stdout`.
|
|
14
|
+
//
|
|
15
|
+
// This module does not change any hook's decision or exit code — it only
|
|
16
|
+
// answers "was this probe's answer real?" so a caller can emit a diagnostic
|
|
17
|
+
// on the undetermined branch while keeping the existing fail-open behavior.
|
|
18
|
+
//
|
|
19
|
+
// Classification mirrors tests/helpers/process-seam.cjs's OUTCOME vocabulary
|
|
20
|
+
// (EXITED vs TIMED_OUT/SPAWN_FAILED/KILLED) — same evidence-over-classification
|
|
21
|
+
// ordering (a populated `status` outranks an attached `error`, since Node can
|
|
22
|
+
// report `error.code === 'ETIMEDOUT'` on a result that also carried a real
|
|
23
|
+
// exit that beat the timer) — so a probe here and a subprocess outcome in the
|
|
24
|
+
// test suite never disagree on the same raw spawnSync() shape.
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {{error?: (Error & {code?: string})|null, status: number|null, signal: string|null}} result
|
|
28
|
+
* the raw return value of `spawnSync('git', ...)`.
|
|
29
|
+
* @returns {{determined: true} | {determined: false, reason: string}}
|
|
30
|
+
*/
|
|
31
|
+
function classifyGitProbe(result) {
|
|
32
|
+
const error = result && result.error;
|
|
33
|
+
const status = result ? result.status : null;
|
|
34
|
+
const signal = result ? result.signal : null;
|
|
35
|
+
|
|
36
|
+
if (!error && signal === null) {
|
|
37
|
+
// A real exit — status 0 or non-zero is a genuine, trustworthy answer.
|
|
38
|
+
return { determined: true };
|
|
39
|
+
}
|
|
40
|
+
if (status !== null) {
|
|
41
|
+
// `status` is only ever populated by a real exit; it outranks an attached
|
|
42
|
+
// `error` even at the exact timeout boundary (process-seam.cjs's own
|
|
43
|
+
// "evidence over classification" rule).
|
|
44
|
+
return { determined: true };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const code = error ? (error.code ?? null) : null;
|
|
48
|
+
let reason;
|
|
49
|
+
if (code === 'ETIMEDOUT' || signal !== null) {
|
|
50
|
+
reason = signal ? `timed out (signal ${signal})` : 'timed out';
|
|
51
|
+
} else if (code) {
|
|
52
|
+
reason = `spawn failed (${code})`;
|
|
53
|
+
} else {
|
|
54
|
+
reason = 'could not run (unknown reason)';
|
|
55
|
+
}
|
|
56
|
+
return { determined: false, reason };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* If `result` could not be determined (timeout / spawn failure / signal
|
|
61
|
+
* kill), write a stderr diagnostic naming the probe and why — never changes
|
|
62
|
+
* any exit code, never throws. A no-op when the probe genuinely ran and
|
|
63
|
+
* answered (status 0 or non-zero with no error/signal).
|
|
64
|
+
*
|
|
65
|
+
* @param {string} hookName - e.g. 'gsd-worktree-path-guard'
|
|
66
|
+
* @param {string} probeLabel - e.g. "git rev-parse --show-toplevel"
|
|
67
|
+
* @param {*} result - the raw spawnSync() return value
|
|
68
|
+
*/
|
|
69
|
+
function reportIfUndetermined(hookName, probeLabel, result) {
|
|
70
|
+
const classification = classifyGitProbe(result);
|
|
71
|
+
if (classification.determined) return;
|
|
72
|
+
try {
|
|
73
|
+
process.stderr.write(
|
|
74
|
+
`${hookName}: git probe '${probeLabel}' ${classification.reason} — ` +
|
|
75
|
+
`allowing this call because the probe's answer is unknown, not because ` +
|
|
76
|
+
`git answered "no" (#3911).\n`
|
|
77
|
+
);
|
|
78
|
+
} catch {
|
|
79
|
+
// A stderr write failing (EPIPE, closed fd) must never itself change the
|
|
80
|
+
// hook's fail-open outcome.
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
module.exports = { classifyGitProbe, reportIfUndetermined };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// hooks/lib/hook-exit.js — hand-written, NOT generated. A tiny hook-facing
|
|
3
|
+
// vocabulary layered over hooks/lib/cli-exit.js's terminateNow (ADR-3889 §3),
|
|
4
|
+
// for the 19 enforcement hooks P7/#3911 is migrating off raw process.exit().
|
|
5
|
+
//
|
|
6
|
+
// WHY onCrash is a REQUIRED argument, with no default (this is the entire
|
|
7
|
+
// point of this module): every hook audited for #3911 ended its outer
|
|
8
|
+
// try/catch in ONE of two ways — some `process.exit(0)` (fail open: a hook
|
|
9
|
+
// error must never block a legitimate tool call), others `process.exit(2)`
|
|
10
|
+
// (fail closed: a hook whose whole job is a security/safety denial must not
|
|
11
|
+
// let its own bug wave the denial through). Both are legitimate policies for
|
|
12
|
+
// DIFFERENT hooks — but neither is the "obviously correct" one, and a shared
|
|
13
|
+
// helper that silently defaulted to either would let a future hook inherit
|
|
14
|
+
// the wrong policy by omission, which is exactly the "nothing fails with
|
|
15
|
+
// success" defect ADR-3889 exists to close. Requiring the caller to name its
|
|
16
|
+
// policy at every call site — not just once at module load — makes "I forgot
|
|
17
|
+
// to decide" a load-time/call-time crash instead of a silent behavior. A
|
|
18
|
+
// caller that truly wants "allow on crash" must still write ALLOW; there is
|
|
19
|
+
// no path that reaches terminateNow without a declared choice.
|
|
20
|
+
//
|
|
21
|
+
// crash() itself is total: it does not throw on a bad `onCrash`, because
|
|
22
|
+
// throwing would unwind into the CALLER's own outer catch — the exact
|
|
23
|
+
// fail-open-by-accident hazard this module removes. Instead an unrecognized
|
|
24
|
+
// policy terminates via terminateNow('INTERNAL', ...) with a diagnostic
|
|
25
|
+
// payload naming the offending value, so a typo'd/misspelled policy is
|
|
26
|
+
// debuggable on stderr rather than silently reinterpreted as ALLOW or DENY.
|
|
27
|
+
const { terminateNow } = require('./cli-exit.js');
|
|
28
|
+
|
|
29
|
+
/** Frozen enum of the two declarable crash policies. No third option. */
|
|
30
|
+
const HOOK_ON_CRASH = Object.freeze({
|
|
31
|
+
ALLOW: 'allow',
|
|
32
|
+
DENY: 'deny',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
/** Terminate with the hook-protocol PASS outcome (exit 0). */
|
|
36
|
+
function allow(payload) {
|
|
37
|
+
terminateNow('PASS', payload);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Terminate with the hook-protocol deny outcome (exit 2, stdout+stderr).
|
|
42
|
+
*
|
|
43
|
+
* @param {*} payload - JSON-serializable value written to fd 1 (and, when
|
|
44
|
+
* `stderrPayload` is omitted, fd 2 too).
|
|
45
|
+
* @param {*} [stderrPayload] - optional distinct value for fd 2, forwarded
|
|
46
|
+
* verbatim to terminateNow's own `stderrPayload` param — a string is
|
|
47
|
+
* written raw, anything else is JSON-stringified.
|
|
48
|
+
*/
|
|
49
|
+
function deny(payload, stderrPayload) {
|
|
50
|
+
terminateNow('HOOK_DENY', payload, stderrPayload);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Dispatch to allow()/deny() per a DECLARED crash policy. `onCrash` is
|
|
55
|
+
* required — see the module header for why there is no default.
|
|
56
|
+
*
|
|
57
|
+
* @param {'allow'|'deny'} onCrash - one of HOOK_ON_CRASH's two values.
|
|
58
|
+
* @param {*} payload - JSON-serializable value forwarded to terminateNow.
|
|
59
|
+
*/
|
|
60
|
+
function crash(onCrash, payload) {
|
|
61
|
+
if (onCrash === HOOK_ON_CRASH.ALLOW) {
|
|
62
|
+
allow(payload);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (onCrash === HOOK_ON_CRASH.DENY) {
|
|
66
|
+
deny(payload);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// Never guess a policy and never throw (a throw would unwind into the
|
|
70
|
+
// caller's own outer catch — the fail-open-by-accident defect this module
|
|
71
|
+
// exists to remove). Terminate deterministically with INTERNAL, naming the
|
|
72
|
+
// offending value so a misspelled/omitted policy is diagnosable.
|
|
73
|
+
terminateNow('INTERNAL', {
|
|
74
|
+
error: 'hook-exit: crash() called with an unrecognized onCrash policy',
|
|
75
|
+
receivedOnCrash: onCrash,
|
|
76
|
+
expectedOneOf: [HOOK_ON_CRASH.ALLOW, HOOK_ON_CRASH.DENY],
|
|
77
|
+
originalPayload: payload,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = { HOOK_ON_CRASH, allow, deny, crash };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* injection-patterns.js — the shared prompt-injection pattern list (#3504, epic #1900).
|
|
5
|
+
*
|
|
6
|
+
* Single source of truth for the standard injection signatures used by BOTH
|
|
7
|
+
* gsd-prompt-guard.js (PreToolUse scan of writes into .planning/) and
|
|
8
|
+
* gsd-read-injection-scanner.js (PostToolUse scan of Read/WebFetch/WebSearch
|
|
9
|
+
* content). Previously each hook carried a byte-identical copy ("inlined for
|
|
10
|
+
* hook independence") that could silently drift — a pattern tightened in one
|
|
11
|
+
* would stop protecting the other surface.
|
|
12
|
+
*
|
|
13
|
+
* Why a shared lib require is safe here (the old inlining rationale, retired):
|
|
14
|
+
* the installer stages hooks/lib/ from the GSD_HOOK_LIB_FILES allowlist for the
|
|
15
|
+
* shared-bundle surfaces (Claude-family settings.json runtimes and Kimi), the
|
|
16
|
+
* Cursor stager auto-discovers require('./lib/...') in staged scripts and fails
|
|
17
|
+
* the install loudly when a helper is missing (#2587), and the plugin path
|
|
18
|
+
* ships this directory wholesale.
|
|
19
|
+
*
|
|
20
|
+
* Deliberately NOT unified with src/security.cts's scanForInjection set: that
|
|
21
|
+
* set runs inside the compiled lib tree; hooks must stay loadable standalone
|
|
22
|
+
* without it. The two lists are different surfaces by design, not drift.
|
|
23
|
+
*
|
|
24
|
+
* Keep this file free of literal 'gsd:' text — the stager rewrites that marker
|
|
25
|
+
* in staged hook content.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
const INJECTION_PATTERNS = Object.freeze([
|
|
29
|
+
/ignore\s+(all\s+)?previous\s+instructions/i,
|
|
30
|
+
/ignore\s+(all\s+)?above\s+instructions/i,
|
|
31
|
+
/disregard\s+(all\s+)?previous/i,
|
|
32
|
+
/forget\s+(all\s+)?(your\s+)?instructions/i,
|
|
33
|
+
/override\s+(system|previous)\s+(prompt|instructions)/i,
|
|
34
|
+
/you\s+are\s+now\s+(?:a|an|the)\s+/i,
|
|
35
|
+
/act\s+as\s+(?:a|an|the)\s+(?!plan|phase|wave)/i,
|
|
36
|
+
/pretend\s+(?:you(?:'re| are)\s+|to\s+be\s+)/i,
|
|
37
|
+
/from\s+now\s+on,?\s+you\s+(?:are|will|should|must)/i,
|
|
38
|
+
/(?:print|output|reveal|show|display|repeat)\s+(?:your\s+)?(?:system\s+)?(?:prompt|instructions)/i,
|
|
39
|
+
/<\/?(?:system|assistant|human)>/i,
|
|
40
|
+
/\[SYSTEM\]/i,
|
|
41
|
+
/\[INST\]/i,
|
|
42
|
+
/<<\s*SYS\s*>>/i,
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
module.exports = { INJECTION_PATTERNS };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// hooks/lib/isolation-deny-reason.js — shared, frozen reason-code enum for
|
|
3
|
+
// the #3045 dispatch-isolation guards' block/deny decisions
|
|
4
|
+
// (hooks/gsd-agent-isolation-guard.js, hooks/gsd-cursor-subagent-start.js).
|
|
5
|
+
//
|
|
6
|
+
// CONTRIBUTING.md ("Prohibited: Raw Text Matching on Test Outputs") bans
|
|
7
|
+
// asserting on a hook's free-form, human-readable reason/user_message prose
|
|
8
|
+
// — that text is for the operator/model reading the denial and may change
|
|
9
|
+
// wording without notice. Every block/deny decision therefore ALSO carries
|
|
10
|
+
// one of these STABLE codes (surfaced on the hook's stdout JSON as
|
|
11
|
+
// `reason_code`), so tests assert `out.reason_code === REASON_CODE.X`
|
|
12
|
+
// instead of regexing the message (mirrors the REASON enum convention in
|
|
13
|
+
// gsd-core/bin/verify-reapply-patches.cjs).
|
|
14
|
+
//
|
|
15
|
+
// Adding a new code requires updating this enum AND any test that locks the
|
|
16
|
+
// documented set.
|
|
17
|
+
const REASON_CODE = Object.freeze({
|
|
18
|
+
// The compiled runtime library (gsd-core/bin/lib/*.cjs) is missing and
|
|
19
|
+
// could not be self-built (ensure-runtime-build.cjs's RuntimeBuildError).
|
|
20
|
+
RUNTIME_BUILD_FAILED: 'runtime_build_failed',
|
|
21
|
+
// The project's dispatch-isolation configuration ('.planning/config.json')
|
|
22
|
+
// could not be read or resolved for a reason OTHER than a runtime-build
|
|
23
|
+
// failure (unreadable/malformed config, unexpected resolver error).
|
|
24
|
+
CONFIG_UNREADABLE: 'config_unreadable',
|
|
25
|
+
// Isolation resolves to "harness-worktree" but the Agent()/Task() dispatch
|
|
26
|
+
// is missing the harness's isolation flag/kwarg.
|
|
27
|
+
HARNESS_FLAG_MISSING: 'harness_flag_missing',
|
|
28
|
+
// Isolation resolves to "harness-worktree" but the dispatch payload carries
|
|
29
|
+
// no usable subagent_type, so the guard cannot confirm it is a GSD executor.
|
|
30
|
+
NO_SUBAGENT_TYPE: 'no_subagent_type',
|
|
31
|
+
// Isolation resolves to "harness-worktree" but whether the workspace root
|
|
32
|
+
// is an isolated worktree could not be determined (e.g. git unresponsive).
|
|
33
|
+
CANNOT_DETERMINE_ISOLATION: 'cannot_determine_isolation',
|
|
34
|
+
// Isolation resolves to "harness-worktree" and the workspace root is
|
|
35
|
+
// confirmed NOT an isolated worktree.
|
|
36
|
+
NOT_ISOLATED_WORKTREE: 'not_isolated_worktree',
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
module.exports = { REASON_CODE };
|
|
@@ -130,6 +130,15 @@ function resolveSentinelRoot(cwd) {
|
|
|
130
130
|
if (fs.existsSync(path.join(cwd, '.planning'))) {
|
|
131
131
|
return cwd;
|
|
132
132
|
}
|
|
133
|
+
// #3582: worktree-safety.cjs / project-root.cjs are tsc build artifacts
|
|
134
|
+
// (ADR-457), gitignored and absent on a raw plugin-marketplace / git-clone
|
|
135
|
+
// install that never ran `npm run build:lib`. Self-heal before either
|
|
136
|
+
// require below; a RuntimeBuildError (or any other failure) falls through
|
|
137
|
+
// to the existing catch's degrade-to-raw-`cwd` — unchanged behavior, just
|
|
138
|
+
// now attempted-healed-first rather than silently degrading on the first
|
|
139
|
+
// cold-tree encounter.
|
|
140
|
+
const { ensureRuntimeBuild } = require('../../gsd-core/bin/ensure-runtime-build.cjs');
|
|
141
|
+
ensureRuntimeBuild();
|
|
133
142
|
const { resolveWorktreeRoot } = require('../../gsd-core/bin/lib/worktree-safety.cjs');
|
|
134
143
|
const { root } = resolveWorktreeRoot(cwd);
|
|
135
144
|
const { findProjectRoot } = require('../../gsd-core/bin/lib/project-root.cjs');
|
|
@@ -29,6 +29,9 @@ const MANAGED_HOOKS = [
|
|
|
29
29
|
'gsd-cursor-subagent-stop.js',
|
|
30
30
|
'gsd-ensure-canonical-path.js',
|
|
31
31
|
'gsd-graphify-update.sh',
|
|
32
|
+
// #3662: portable node resolver (helper staged in hooks/; managed JS hook
|
|
33
|
+
// commands route through it under --portable-hooks).
|
|
34
|
+
'gsd-node-runner.sh',
|
|
32
35
|
'gsd-phase-boundary.sh',
|
|
33
36
|
'gsd-prompt-guard.js',
|
|
34
37
|
'gsd-read-guard.js',
|