@opengsd/gsd-core 1.11.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 +1 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-dom-verifier.md +169 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +17 -9
- package/agents/gsd-framework-selector.md +1 -3
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +0 -1
- package/agents/gsd-pattern-mapper.md +11 -0
- package/agents/gsd-phase-researcher.md +3 -1
- package/agents/gsd-plan-checker.md +15 -55
- package/agents/gsd-planner.md +6 -4
- 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-verifier.md +1 -1
- package/bin/install.js +609 -134
- package/commands/gsd/discuss-phase.md +1 -1
- package/commands/gsd/import.md +1 -1
- package/commands/gsd/quick.md +8 -4
- package/gsd-core/bin/gsd-tools.cjs +567 -51
- package/gsd-core/bin/lib/active-workstream-store.cjs +8 -0
- package/gsd-core/bin/lib/adr-parser.cjs +13 -7
- package/gsd-core/bin/lib/agent-install-check.cjs +162 -0
- package/gsd-core/bin/lib/api-coverage.cjs +30 -9
- package/gsd-core/bin/lib/artifacts.cjs +2 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +30 -11
- package/gsd-core/bin/lib/audit.cjs +163 -41
- package/gsd-core/bin/lib/broken-windows.cjs +306 -28
- package/gsd-core/bin/lib/capability-lock.cjs +10 -4
- package/gsd-core/bin/lib/capability-registry.cjs +336 -95
- package/gsd-core/bin/lib/capability-state.cjs +18 -3
- package/gsd-core/bin/lib/capability-validator.cjs +205 -18
- package/gsd-core/bin/lib/check-command-router.cjs +145 -5
- 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 +410 -4
- package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
- package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
- package/gsd-core/bin/lib/commands.cjs +543 -44
- package/gsd-core/bin/lib/complexity-trigger.cjs +26 -6
- package/gsd-core/bin/lib/config-loader.cjs +118 -29
- package/gsd-core/bin/lib/config.cjs +92 -2
- package/gsd-core/bin/lib/configuration.cjs +129 -37
- package/gsd-core/bin/lib/core-utils.cjs +84 -7
- 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/frontmatter.cjs +840 -305
- package/gsd-core/bin/lib/gap-checker.cjs +27 -3
- package/gsd-core/bin/lib/git-base-branch.cjs +174 -39
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +7 -3
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +6 -3
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +22 -8
- package/gsd-core/bin/lib/health-diagnostic.cjs +23 -3
- package/gsd-core/bin/lib/host-integration.cjs +39 -6
- package/gsd-core/bin/lib/init-command-router.cjs +118 -21
- package/gsd-core/bin/lib/init.cjs +120 -41
- package/gsd-core/bin/lib/install-engine.cjs +68 -3
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +33 -1
- package/gsd-core/bin/lib/install-profiles.cjs +78 -4
- 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 +10 -7
- package/gsd-core/bin/lib/intel.cjs +101 -26
- package/gsd-core/bin/lib/io.cjs +160 -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-table.cjs +52 -4
- package/gsd-core/bin/lib/milestone.cjs +90 -5
- package/gsd-core/bin/lib/model-catalog.cjs +177 -19
- package/gsd-core/bin/lib/model-resolver.cjs +10 -28
- package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
- package/gsd-core/bin/lib/phase-estimation.cjs +17 -8
- package/gsd-core/bin/lib/phase-id.cjs +70 -4
- package/gsd-core/bin/lib/phase-lifecycle.cjs +24 -16
- package/gsd-core/bin/lib/phase-locator.cjs +138 -17
- package/gsd-core/bin/lib/phase.cjs +405 -84
- package/gsd-core/bin/lib/plan-document.cjs +263 -0
- package/gsd-core/bin/lib/plan-scan.cjs +13 -2
- 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-snapshot.cjs +18 -14
- package/gsd-core/bin/lib/planning-workspace.cjs +56 -0
- package/gsd-core/bin/lib/probe-core.cjs +4 -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 +71 -45
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +9 -9
- package/gsd-core/bin/lib/roadmap-command-router.cjs +45 -31
- package/gsd-core/bin/lib/roadmap-parser.cjs +79 -16
- package/gsd-core/bin/lib/roadmap.cjs +74 -19
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +96 -8
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +34 -1
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +287 -55
- package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
- package/gsd-core/bin/lib/runtime-slash.cjs +72 -2
- package/gsd-core/bin/lib/shell-command-projection.cjs +71 -8
- package/gsd-core/bin/lib/smart-entry.cjs +12 -22
- package/gsd-core/bin/lib/spec-section.cjs +12 -7
- package/gsd-core/bin/lib/state-command-router.cjs +47 -18
- package/gsd-core/bin/lib/state-contract.cjs +359 -0
- package/gsd-core/bin/lib/state-document.cjs +186 -0
- package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
- package/gsd-core/bin/lib/state-transition.cjs +517 -101
- package/gsd-core/bin/lib/state.cjs +946 -163
- package/gsd-core/bin/lib/surface.cjs +10 -2
- 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/uat-predicate.cjs +58 -20
- package/gsd-core/bin/lib/uat.cjs +1376 -125
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
- package/gsd-core/bin/lib/ui-safety-gate.cjs +37 -7
- package/gsd-core/bin/lib/unusable-input.cjs +13 -0
- package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
- package/gsd-core/bin/lib/vendor/README.md +43 -5
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
- package/gsd-core/bin/lib/verification.cjs +14 -1
- package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
- package/gsd-core/bin/lib/verify.cjs +95 -40
- package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
- package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
- package/gsd-core/bin/lib/worktree-safety.cjs +177 -21
- package/gsd-core/bin/shared/config-defaults.manifest.json +7 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
- 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 +3 -2
- 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 +37 -19
- package/gsd-core/references/decimal-phase-calculation.md +5 -5
- package/gsd-core/references/edge-probe.md +8 -0
- package/gsd-core/references/execute-mvp-tdd.md +1 -3
- package/gsd-core/references/execute-phase-between-wave-reset.md +9 -12
- package/gsd-core/references/execute-phase-wave-guard.md +11 -9
- 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 +3 -3
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +22 -0
- package/gsd-core/references/model-profiles.md +1 -1
- 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-human-verify-mode.md +15 -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 +37 -8
- package/gsd-core/references/reviewer-instances.md +31 -0
- package/gsd-core/references/runtime-aware-dispatch.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 +2 -2
- package/gsd-core/references/verify-command-path-resolvability.md +42 -0
- package/gsd-core/references/verify-mvp-mode.md +1 -1
- package/gsd-core/references/workstream-flag.md +11 -11
- 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/phase-prompt.md +3 -0
- package/gsd-core/templates/state.md +7 -0
- 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 +4 -9
- 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 +10 -26
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +2 -2
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +1 -1
- package/gsd-core/workflows/code-review-fix.md +1 -1
- package/gsd-core/workflows/code-review.md +121 -40
- package/gsd-core/workflows/complete-milestone.md +15 -10
- package/gsd-core/workflows/debug.md +5 -3
- package/gsd-core/workflows/diagnose-issues.md +12 -6
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +3 -7
- 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 +2 -2
- 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 +1 -1
- package/gsd-core/workflows/eval-review.md +4 -9
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +113 -11
- 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 +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +22 -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 +38 -54
- package/gsd-core/workflows/execute-plan.md +17 -12
- package/gsd-core/workflows/explore.md +1 -1
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/fast.md +2 -2
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +5 -5
- package/gsd-core/workflows/health.md +3 -6
- package/gsd-core/workflows/import.md +14 -11
- package/gsd-core/workflows/inbox.md +4 -5
- package/gsd-core/workflows/ingest-docs.md +44 -11
- 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 +2 -2
- package/gsd-core/workflows/new-milestone.md +9 -21
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +12 -26
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +2 -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 +121 -42
- package/gsd-core/workflows/plan-review-convergence.md +46 -9
- 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 +27 -12
- package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +1 -3
- package/gsd-core/workflows/quick/steps/quick-verification.md +2 -4
- package/gsd-core/workflows/quick/steps/research-phase.md +2 -4
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
- package/gsd-core/workflows/quick.md +20 -29
- 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 +193 -15
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +2 -2
- package/gsd-core/workflows/settings-advanced.md +7 -9
- package/gsd-core/workflows/settings-integrations.md +64 -31
- package/gsd-core/workflows/settings.md +3 -5
- package/gsd-core/workflows/ship.md +12 -6
- 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 +23 -1
- 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 +1 -1
- package/gsd-core/workflows/thread.md +11 -7
- package/gsd-core/workflows/transition.md +5 -5
- package/gsd-core/workflows/ui-phase.md +10 -16
- package/gsd-core/workflows/ui-review.md +6 -10
- package/gsd-core/workflows/ultraplan-phase.md +5 -13
- package/gsd-core/workflows/undo.md +8 -16
- package/gsd-core/workflows/update.md +6 -10
- package/gsd-core/workflows/validate-phase.md +2 -2
- 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 +57 -18
- package/hooks/dist/gsd-agent-isolation-guard.js +77 -38
- 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 +3 -1
- 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 +28 -23
- package/hooks/dist/gsd-cursor-subagent-stop.js +3 -1
- 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 +16 -7
- package/hooks/dist/gsd-read-guard.js +16 -7
- package/hooks/dist/gsd-read-injection-scanner.js +17 -8
- package/hooks/dist/gsd-session-state.sh +1 -0
- package/hooks/dist/gsd-statusline.js +215 -26
- 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 +34 -16
- 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-probe.js +84 -0
- package/hooks/dist/lib/hook-exit.js +81 -0
- package/hooks/dist/managed-hooks-registry.cjs +3 -0
- package/hooks/gsd-agent-isolation-guard.js +77 -38
- 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 +3 -1
- package/hooks/gsd-cursor-session-start.js +2 -1
- package/hooks/gsd-cursor-stop.js +2 -1
- package/hooks/gsd-cursor-subagent-start.js +28 -23
- package/hooks/gsd-cursor-subagent-stop.js +3 -1
- 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 +16 -7
- package/hooks/gsd-read-guard.js +16 -7
- package/hooks/gsd-read-injection-scanner.js +17 -8
- package/hooks/gsd-session-state.sh +1 -0
- package/hooks/gsd-statusline.js +215 -26
- 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 +34 -16
- 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-probe.js +84 -0
- package/hooks/lib/hook-exit.js +81 -0
- package/hooks/managed-hooks-registry.cjs +3 -0
- package/package.json +12 -7
- package/scripts/base64-scan.sh +74 -12
- package/scripts/build-hooks.js +5 -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 +45 -12
- package/scripts/ci-timeout-report.cjs +230 -0
- package/scripts/docs-guard-registry.cjs +396 -0
- package/scripts/gen-capability-registry.cjs +8 -6
- 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-hooks-cli-exit.cjs +239 -0
- package/scripts/gen-install-tree-fixtures.cjs +2 -2
- package/scripts/gen-loop-host-contract.cjs +134 -1
- 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/ci-job-timing.cjs +72 -0
- package/scripts/lib/cli-exit.cjs +546 -44
- package/scripts/lib/drift-scan.cjs +32 -2
- package/scripts/lib/exit-code-registry.cjs +98 -0
- package/scripts/lib/ndjson-reporter.cjs +119 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- 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 +4 -0
- package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
- package/scripts/lint-health-diagnostic-rule-table.cjs +65 -8
- package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
- package/scripts/lint-phase-enumeration-drift.cjs +21 -8
- package/scripts/lint-planning-prompt-drift.cjs +38 -1
- package/scripts/lint-removed-but-needed.cjs +184 -16
- 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-write-path-drift.cjs +337 -432
- package/scripts/lint-test-file-count.allowlist.json +122 -4
- package/scripts/lint-test-file-count.cjs +25 -3
- package/scripts/lint-unreachable-guard-drift.cjs +51 -64
- package/scripts/lint-vendored-deps.cjs +208 -35
- package/scripts/mutation-matrix.cjs +599 -50
- package/scripts/prompt-injection-scan.sh +75 -14
- package/scripts/secret-scan.sh +75 -13
- package/scripts/select-docs-guards.cjs +56 -0
- package/scripts/sync-runtime-launcher.cjs +22 -3
- package/skills/gsd-discuss-phase/SKILL.md +1 -1
- package/skills/gsd-import/SKILL.md +1 -1
- package/skills/gsd-quick/SKILL.md +8 -4
- package/vscode/package.json +1 -1
- package/bin/lib/ui-safety-gate.cjs +0 -109
- package/scripts/lint-emitted-drift-ack.cjs +0 -344
- package/scripts/state-write-path-drift-baseline.json +0 -19
|
@@ -56,6 +56,7 @@
|
|
|
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
|
|
@@ -342,35 +343,39 @@ function resolveIsolationDecision(data, { clock = Date, realpath = fs.realpathSy
|
|
|
342
343
|
return { action: 'allow' };
|
|
343
344
|
}
|
|
344
345
|
|
|
345
|
-
// ─── #
|
|
346
|
-
//
|
|
347
|
-
//
|
|
348
|
-
//
|
|
349
|
-
// this hook
|
|
350
|
-
//
|
|
351
|
-
//
|
|
352
|
-
//
|
|
353
|
-
|
|
354
|
-
|
|
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
355
|
function readInstallRuntimeMarker() {
|
|
356
|
-
if (_installMarkerCache !== undefined) return _installMarkerCache;
|
|
357
356
|
try {
|
|
358
|
-
|
|
359
|
-
const
|
|
360
|
-
|
|
357
|
+
ensureRuntimeBuild();
|
|
358
|
+
const runtimeSlash = require('../gsd-core/bin/lib/runtime-slash.cjs');
|
|
359
|
+
return runtimeSlash.readInstallRuntimeMarker();
|
|
361
360
|
} catch {
|
|
362
|
-
//
|
|
363
|
-
// from this rung", never a resolution failure.
|
|
364
|
-
|
|
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;
|
|
365
364
|
}
|
|
366
|
-
return _installMarkerCache;
|
|
367
365
|
}
|
|
368
366
|
|
|
369
|
-
// Test seam —
|
|
370
|
-
//
|
|
371
|
-
// are unaffected.
|
|
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.
|
|
372
370
|
function _setInstallRuntimeMarkerForTests(value) {
|
|
373
|
-
|
|
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
|
+
}
|
|
374
379
|
}
|
|
375
380
|
|
|
376
381
|
/**
|
|
@@ -564,7 +569,7 @@ function evaluateRootIsolation(root, subagentType, { clock = Date, dispatchIds =
|
|
|
564
569
|
function main() {
|
|
565
570
|
let raw = '';
|
|
566
571
|
const stdinTimeout = setTimeout(() => {
|
|
567
|
-
|
|
572
|
+
allow(undefined);
|
|
568
573
|
}, 10000);
|
|
569
574
|
|
|
570
575
|
process.stdin.setEncoding('utf8');
|
|
@@ -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
|
|
@@ -12,6 +12,13 @@
|
|
|
12
12
|
// not to create false-positive deadlocks.
|
|
13
13
|
|
|
14
14
|
const path = require('path');
|
|
15
|
+
const { HOOK_ON_CRASH, allow, crash } = require('./lib/hook-exit.js');
|
|
16
|
+
|
|
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;
|
|
15
22
|
|
|
16
23
|
// Prompt injection patterns — shared with gsd-read-injection-scanner.js via
|
|
17
24
|
// hooks/lib/injection-patterns.js so the two surfaces cannot drift (#3504).
|
|
@@ -115,7 +122,7 @@ function normalizeKimiPayload(data) {
|
|
|
115
122
|
}
|
|
116
123
|
|
|
117
124
|
let input = '';
|
|
118
|
-
const stdinTimeout = setTimeout(() =>
|
|
125
|
+
const stdinTimeout = setTimeout(() => allow(undefined), 3000);
|
|
119
126
|
process.stdin.setEncoding('utf8');
|
|
120
127
|
process.stdin.on('data', chunk => input += chunk);
|
|
121
128
|
process.stdin.on('end', () => {
|
|
@@ -126,7 +133,7 @@ process.stdin.on('end', () => {
|
|
|
126
133
|
|
|
127
134
|
// Only scan Write and Edit operations
|
|
128
135
|
if (toolName !== 'Write' && toolName !== 'Edit') {
|
|
129
|
-
|
|
136
|
+
allow(undefined);
|
|
130
137
|
}
|
|
131
138
|
|
|
132
139
|
// #2595 (review Major 3, sibling sweep): typed read. A non-string
|
|
@@ -138,7 +145,7 @@ process.stdin.on('end', () => {
|
|
|
138
145
|
|
|
139
146
|
// Only scan files going into .planning/ (agent context files)
|
|
140
147
|
if (!filePath.includes('.planning/') && !filePath.includes('.planning\\')) {
|
|
141
|
-
|
|
148
|
+
allow(undefined);
|
|
142
149
|
}
|
|
143
150
|
|
|
144
151
|
// Get the content being written. #3504 (isolated review finding 3): the
|
|
@@ -157,7 +164,7 @@ process.stdin.on('end', () => {
|
|
|
157
164
|
}
|
|
158
165
|
}
|
|
159
166
|
if (!content) {
|
|
160
|
-
|
|
167
|
+
allow(undefined);
|
|
161
168
|
}
|
|
162
169
|
|
|
163
170
|
// Scan for injection patterns
|
|
@@ -174,7 +181,7 @@ process.stdin.on('end', () => {
|
|
|
174
181
|
}
|
|
175
182
|
|
|
176
183
|
if (findings.length === 0) {
|
|
177
|
-
|
|
184
|
+
allow(undefined);
|
|
178
185
|
}
|
|
179
186
|
|
|
180
187
|
// Advisory warning — does not block the operation
|
|
@@ -191,7 +198,9 @@ process.stdin.on('end', () => {
|
|
|
191
198
|
|
|
192
199
|
process.stdout.write(JSON.stringify(output));
|
|
193
200
|
} catch {
|
|
194
|
-
// Silent fail — never block tool execution
|
|
195
|
-
|
|
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);
|
|
196
205
|
}
|
|
197
206
|
});
|
|
@@ -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
|
});
|
|
@@ -23,6 +23,13 @@
|
|
|
23
23
|
|
|
24
24
|
const path = require('path');
|
|
25
25
|
const fs = require('fs');
|
|
26
|
+
const { HOOK_ON_CRASH, allow, crash } = require('./lib/hook-exit.js');
|
|
27
|
+
|
|
28
|
+
// This is a PostToolUse advisory scanner over content the tool call already
|
|
29
|
+
// returned; a crash while scanning must not retroactively block that Read/
|
|
30
|
+
// WebFetch/WebSearch result from reaching the agent — losing the injection
|
|
31
|
+
// check is safer than failing the tool call it is only observing (#3911).
|
|
32
|
+
const ON_CRASH = HOOK_ON_CRASH.ALLOW;
|
|
26
33
|
|
|
27
34
|
// Summarisation-specific patterns (novel — not in gsd-prompt-guard.js).
|
|
28
35
|
// These target instructions specifically designed to survive context compression.
|
|
@@ -213,7 +220,7 @@ function normalizeKimiPayload(data) {
|
|
|
213
220
|
}
|
|
214
221
|
|
|
215
222
|
let inputBuf = '';
|
|
216
|
-
const stdinTimeout = setTimeout(() =>
|
|
223
|
+
const stdinTimeout = setTimeout(() => allow(undefined), 5000);
|
|
217
224
|
process.stdin.setEncoding('utf8');
|
|
218
225
|
process.stdin.on('data', chunk => { inputBuf += chunk; });
|
|
219
226
|
process.stdin.on('end', () => {
|
|
@@ -224,7 +231,7 @@ process.stdin.on('end', () => {
|
|
|
224
231
|
const toolName = data.tool_name;
|
|
225
232
|
const SCANNED_TOOLS = new Set(['Read', 'WebFetch', 'WebSearch']);
|
|
226
233
|
if (!SCANNED_TOOLS.has(toolName)) {
|
|
227
|
-
|
|
234
|
+
allow(undefined);
|
|
228
235
|
}
|
|
229
236
|
|
|
230
237
|
// Source label + path-exclusion (path-exclusion applies to file reads only)
|
|
@@ -235,8 +242,8 @@ process.stdin.on('end', () => {
|
|
|
235
242
|
source = typeof data.tool_input?.file_path === 'string'
|
|
236
243
|
? data.tool_input.file_path
|
|
237
244
|
: '';
|
|
238
|
-
if (!source)
|
|
239
|
-
if (isExcludedPath(source))
|
|
245
|
+
if (!source) allow(undefined);
|
|
246
|
+
if (isExcludedPath(source)) allow(undefined);
|
|
240
247
|
} else if (toolName === 'WebFetch') {
|
|
241
248
|
source = data.tool_input?.url || 'web';
|
|
242
249
|
} else { // WebSearch
|
|
@@ -261,7 +268,7 @@ process.stdin.on('end', () => {
|
|
|
261
268
|
}
|
|
262
269
|
|
|
263
270
|
if (!content || content.length < 20) {
|
|
264
|
-
|
|
271
|
+
allow(undefined);
|
|
265
272
|
}
|
|
266
273
|
|
|
267
274
|
// Typed findings IR — single source of truth for both the machine-readable
|
|
@@ -307,7 +314,7 @@ process.stdin.on('end', () => {
|
|
|
307
314
|
}
|
|
308
315
|
|
|
309
316
|
if (findings.length === 0) {
|
|
310
|
-
|
|
317
|
+
allow(undefined);
|
|
311
318
|
}
|
|
312
319
|
|
|
313
320
|
// Renders one finding back into the exact prose fragment the advisory has
|
|
@@ -349,7 +356,9 @@ process.stdin.on('end', () => {
|
|
|
349
356
|
|
|
350
357
|
process.stdout.write(JSON.stringify(output));
|
|
351
358
|
} catch {
|
|
352
|
-
// Silent fail — never block tool execution
|
|
353
|
-
|
|
359
|
+
// Silent fail — never block tool execution.
|
|
360
|
+
// ON_CRASH is declared ALLOW at module top: this preserves today's
|
|
361
|
+
// exit(0) fail-open behavior exactly (#3911).
|
|
362
|
+
crash(ON_CRASH, undefined);
|
|
354
363
|
}
|
|
355
364
|
});
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#
|
|
6
6
|
# OPT-IN: This hook is a no-op unless config.json has hooks.community: true.
|
|
7
7
|
# Enable with: "hooks": { "community": true } in .planning/config.json
|
|
8
|
+
set -euo pipefail
|
|
8
9
|
|
|
9
10
|
# Check opt-in config — exit silently if not enabled
|
|
10
11
|
if [ -f .planning/config.json ]; then
|