@opengsd/gsd-core 1.11.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.opencode/plugins/gsd-core.js +12 -0
- 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 +78 -42
- 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 +91 -112
- package/agents/gsd-planner.md +20 -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 +82 -7
- package/agents/gsd-ui-researcher.md +70 -3
- package/agents/gsd-verifier.md +24 -2
- package/bin/install.js +847 -200
- 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/ns-workflow.md +2 -1
- package/commands/gsd/phase.md +1 -1
- package/commands/gsd/quick-batch.md +105 -0
- package/commands/gsd/quick.md +8 -4
- package/commands/gsd/surface.md +18 -8
- package/gsd-core/bin/gsd-tools.cjs +761 -100
- 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-activation.cjs +27 -0
- package/gsd-core/bin/lib/capability-lock.cjs +10 -4
- package/gsd-core/bin/lib/capability-registry.cjs +785 -144
- package/gsd-core/bin/lib/capability-state.cjs +25 -4
- package/gsd-core/bin/lib/capability-validator.cjs +321 -18
- package/gsd-core/bin/lib/capability-writer.cjs +14 -4
- package/gsd-core/bin/lib/check-command-router.cjs +229 -6
- package/gsd-core/bin/lib/claude-orchestration.cjs +10 -25
- package/gsd-core/bin/lib/cli-exit.cjs +496 -10
- package/gsd-core/bin/lib/clusters.cjs +1 -0
- 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-aliases.cjs +16 -0
- 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 +877 -54
- package/gsd-core/bin/lib/complexity-trigger.cjs +26 -6
- package/gsd-core/bin/lib/config-loader.cjs +121 -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 +118 -14
- package/gsd-core/bin/lib/decisions.cjs +213 -1
- package/gsd-core/bin/lib/edge-probe.cjs +23 -2
- 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/file-overlap-partitioner.cjs +74 -0
- package/gsd-core/bin/lib/frontmatter.cjs +975 -326
- package/gsd-core/bin/lib/gap-checker.cjs +41 -8
- package/gsd-core/bin/lib/git-base-branch.cjs +182 -39
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +7 -3
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +8 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +60 -14
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +75 -22
- 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 +96 -11
- package/gsd-core/bin/lib/init-command-router.cjs +132 -21
- package/gsd-core/bin/lib/init.cjs +252 -56
- package/gsd-core/bin/lib/install-engine.cjs +252 -15
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +78 -1
- package/gsd-core/bin/lib/install-profiles.cjs +100 -18
- package/gsd-core/bin/lib/installer-migration-report.cjs +4 -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 +195 -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/loop-resolver.cjs +14 -8
- package/gsd-core/bin/lib/markdown-table.cjs +175 -4
- package/gsd-core/bin/lib/milestone.cjs +112 -7
- 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-command-router.cjs +13 -6
- package/gsd-core/bin/lib/phase-estimation.cjs +17 -8
- package/gsd-core/bin/lib/phase-id.cjs +321 -13
- 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 +1175 -115
- package/gsd-core/bin/lib/plan-document.cjs +273 -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 +165 -34
- package/gsd-core/bin/lib/planning-workspace.cjs +159 -28
- 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/quick-batch-command-router.cjs +285 -0
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +250 -0
- package/gsd-core/bin/lib/quick-batch.cjs +840 -0
- 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 +62 -14
- package/gsd-core/bin/lib/review-lane-invocation.cjs +73 -1
- package/gsd-core/bin/lib/review-lane-runner.cjs +136 -10
- package/gsd-core/bin/lib/roadmap-command-router.cjs +45 -31
- package/gsd-core/bin/lib/roadmap-parser.cjs +577 -41
- package/gsd-core/bin/lib/roadmap.cjs +248 -64
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +329 -41
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +16 -17
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +320 -109
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +487 -83
- 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 +75 -8
- package/gsd-core/bin/lib/smart-entry.cjs +19 -31
- 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 +216 -5
- package/gsd-core/bin/lib/state-md-schema.cjs +231 -0
- package/gsd-core/bin/lib/state-transition.cjs +850 -145
- package/gsd-core/bin/lib/state.cjs +1629 -287
- package/gsd-core/bin/lib/surface.cjs +33 -10
- 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/tdd-red-evidence.cjs +133 -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 +2542 -387
- 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/update-context.cjs +6 -2
- package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
- package/gsd-core/bin/lib/validate.cjs +230 -12
- 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-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +287 -13
- package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
- package/gsd-core/bin/lib/verify-command-router.cjs +1 -0
- package/gsd-core/bin/lib/verify.cjs +441 -56
- package/gsd-core/bin/lib/workstream-inventory.cjs +20 -2
- 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 +185 -21
- package/gsd-core/bin/shared/config-defaults.manifest.json +7 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +13 -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/bin/verify-reapply-patches.cjs +70 -3
- package/gsd-core/references/agent-contracts.md +6 -5
- 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 +17 -5
- package/gsd-core/references/execute-mvp-tdd.md +18 -18
- package/gsd-core/references/execute-phase-between-wave-reset.md +9 -12
- package/gsd-core/references/execute-phase-response-language.md +6 -0
- package/gsd-core/references/execute-phase-wave-guard.md +11 -9
- package/gsd-core/references/executor-examples.md +42 -0
- package/gsd-core/references/failing-direction.md +78 -0
- package/gsd-core/references/few-shot-examples/plan-checker.md +15 -15
- 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/mvp-concepts.md +2 -2
- 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/plan-checker-examples.md +41 -0
- package/gsd-core/references/planner-antipatterns.md +25 -0
- package/gsd-core/references/planner-chunked.md +5 -1
- package/gsd-core/references/planner-coupling.md +42 -0
- 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-quick-batch.md +71 -0
- package/gsd-core/references/planner-reviews.md +47 -0
- package/gsd-core/references/planner-revision.md +76 -3
- package/gsd-core/references/planner-verify-command-grounding.md +17 -0
- package/gsd-core/references/planning-config.md +39 -9
- package/gsd-core/references/response-language-directive.md +9 -0
- package/gsd-core/references/reviewer-instances.md +31 -0
- package/gsd-core/references/revision-loop.md +118 -11
- package/gsd-core/references/runtime-aware-dispatch.md +1 -1
- package/gsd-core/references/tdd.md +15 -12
- 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/verifier-evidence-gate.md +160 -0
- 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 +7 -0
- package/gsd-core/templates/state.md +7 -0
- package/gsd-core/templates/verification-report.md +5 -0
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +3 -1
- package/gsd-core/workflows/add-phase.md +5 -3
- package/gsd-core/workflows/add-tests.md +4 -9
- package/gsd-core/workflows/add-todo.md +2 -2
- package/gsd-core/workflows/ai-integration-phase.md +5 -10
- package/gsd-core/workflows/analyze-dependencies.md +2 -0
- package/gsd-core/workflows/audit-fix.md +14 -3
- package/gsd-core/workflows/audit-milestone.md +11 -9
- package/gsd-core/workflows/audit-uat.md +19 -2
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
- package/gsd-core/workflows/autonomous.md +12 -26
- package/gsd-core/workflows/check-todos.md +2 -2
- package/gsd-core/workflows/cleanup.md +3 -3
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +16 -14
- package/gsd-core/workflows/code-review-fix.md +3 -1
- package/gsd-core/workflows/code-review.md +192 -69
- package/gsd-core/workflows/complete-milestone.md +28 -14
- package/gsd-core/workflows/debug.md +6 -4
- package/gsd-core/workflows/diagnose-issues.md +17 -7
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +3 -1
- package/gsd-core/workflows/discuss-phase/modes/all.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/analyze.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/auto.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/batch.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -7
- package/gsd-core/workflows/discuss-phase/modes/default.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/power.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/text.md +3 -1
- package/gsd-core/workflows/discuss-phase/templates/context.md +2 -0
- package/gsd-core/workflows/discuss-phase/templates/discussion-log.md +2 -0
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
- package/gsd-core/workflows/discuss-phase-assumptions.md +3 -3
- package/gsd-core/workflows/discuss-phase-power.md +2 -0
- package/gsd-core/workflows/discuss-phase.md +2 -2
- package/gsd-core/workflows/do.md +46 -19
- package/gsd-core/workflows/docs-update.md +6 -5
- package/gsd-core/workflows/edit-phase.md +3 -1
- package/gsd-core/workflows/eval-review.md +5 -10
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +3 -1
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +129 -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 +29 -5
- 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 +4 -2
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +25 -0
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
- package/gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md +2 -0
- package/gsd-core/workflows/execute-phase.md +68 -66
- package/gsd-core/workflows/execute-plan.md +25 -20
- package/gsd-core/workflows/explore.md +3 -1
- package/gsd-core/workflows/extract-learnings.md +3 -1
- package/gsd-core/workflows/fast.md +8 -2
- package/gsd-core/workflows/forensics.md +3 -1
- package/gsd-core/workflows/graduation.md +6 -6
- package/gsd-core/workflows/health.md +4 -7
- package/gsd-core/workflows/help/modes/brief.md +2 -0
- package/gsd-core/workflows/help/modes/default.md +2 -0
- package/gsd-core/workflows/help/modes/full.md +12 -0
- package/gsd-core/workflows/help/modes/topic.md +2 -0
- package/gsd-core/workflows/help.md +2 -0
- package/gsd-core/workflows/import.md +17 -14
- package/gsd-core/workflows/inbox.md +5 -6
- package/gsd-core/workflows/ingest-docs.md +45 -12
- package/gsd-core/workflows/insert-phase.md +7 -5
- package/gsd-core/workflows/list-phase-assumptions.md +2 -0
- package/gsd-core/workflows/list-seeds.md +7 -3
- package/gsd-core/workflows/list-workspaces.md +3 -1
- package/gsd-core/workflows/manager.md +15 -26
- package/gsd-core/workflows/map-codebase.md +3 -1
- package/gsd-core/workflows/milestone-summary.md +3 -1
- package/gsd-core/workflows/mvp-phase.md +3 -3
- package/gsd-core/workflows/new-milestone.md +10 -22
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +17 -29
- package/gsd-core/workflows/new-workspace.md +2 -2
- package/gsd-core/workflows/next.md +4 -2
- package/gsd-core/workflows/node-repair.md +2 -0
- package/gsd-core/workflows/note.md +2 -0
- package/gsd-core/workflows/onboard.md +1 -1
- package/gsd-core/workflows/pause-work.md +20 -5
- 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 +100 -18
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +4 -4
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +12 -3
- package/gsd-core/workflows/plan-phase.md +251 -54
- package/gsd-core/workflows/plan-review-convergence.md +148 -19
- package/gsd-core/workflows/plant-seed.md +3 -3
- package/gsd-core/workflows/pr-branch.md +195 -51
- package/gsd-core/workflows/profile-user.md +17 -15
- package/gsd-core/workflows/progress/steps/forensic-audit.md +1 -1
- package/gsd-core/workflows/progress.md +52 -15
- package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +38 -5
- package/gsd-core/workflows/quick/steps/quick-verification.md +2 -4
- package/gsd-core/workflows/quick/steps/research-phase.md +5 -7
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +55 -0
- package/gsd-core/workflows/quick-batch/steps/completion.md +65 -0
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +100 -0
- package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +147 -0
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +158 -0
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +95 -0
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +49 -0
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +73 -0
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +169 -0
- package/gsd-core/workflows/quick-batch.md +203 -0
- package/gsd-core/workflows/quick.md +33 -32
- package/gsd-core/workflows/reapply-patches.md +2 -0
- package/gsd-core/workflows/remove-phase.md +6 -4
- package/gsd-core/workflows/remove-workspace.md +3 -3
- package/gsd-core/workflows/resume-project.md +14 -14
- package/gsd-core/workflows/review.md +404 -21
- package/gsd-core/workflows/scan.md +3 -1
- package/gsd-core/workflows/section-manifest.json +12 -0
- package/gsd-core/workflows/secure-phase.md +3 -3
- package/gsd-core/workflows/session-report.md +2 -0
- package/gsd-core/workflows/settings-advanced.md +9 -9
- package/gsd-core/workflows/settings-integrations.md +66 -32
- package/gsd-core/workflows/settings.md +4 -6
- package/gsd-core/workflows/ship.md +22 -16
- package/gsd-core/workflows/sketch-wrap-up.md +13 -17
- package/gsd-core/workflows/sketch.md +13 -19
- package/gsd-core/workflows/smart-entry.md +4 -6
- package/gsd-core/workflows/spec-phase.md +31 -4
- package/gsd-core/workflows/spike-wrap-up.md +9 -11
- package/gsd-core/workflows/spike.md +21 -32
- package/gsd-core/workflows/stats.md +4 -2
- package/gsd-core/workflows/sync-skills.md +13 -5
- package/gsd-core/workflows/thread.md +13 -7
- package/gsd-core/workflows/transition.md +7 -5
- package/gsd-core/workflows/ui-phase.md +36 -21
- package/gsd-core/workflows/ui-review.md +7 -11
- package/gsd-core/workflows/ultraplan-phase.md +7 -13
- package/gsd-core/workflows/undo.md +9 -17
- package/gsd-core/workflows/update.md +47 -48
- 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 +106 -21
- package/hooks/dist/gsd-agent-isolation-guard.js +77 -38
- package/hooks/dist/gsd-check-update-worker.js +19 -2
- package/hooks/dist/gsd-config-reload.js +18 -12
- package/hooks/dist/gsd-context-monitor.js +302 -22
- 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 +77 -0
- package/hooks/dist/gsd-phase-boundary.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +46 -12
- package/hooks/dist/gsd-read-guard.js +18 -7
- package/hooks/dist/gsd-read-injection-scanner.js +22 -13
- package/hooks/dist/gsd-secret-read-guard.js +1079 -0
- package/hooks/dist/gsd-session-state.sh +1 -0
- package/hooks/dist/gsd-statusline.js +222 -29
- package/hooks/dist/gsd-validate-commit.sh +523 -12
- 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 +36 -17
- 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 +210 -1
- 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 +36 -6
- package/hooks/dist/managed-hooks-registry.cjs +4 -0
- package/hooks/gsd-agent-isolation-guard.js +77 -38
- package/hooks/gsd-check-update-worker.js +19 -2
- package/hooks/gsd-config-reload.js +18 -12
- package/hooks/gsd-context-monitor.js +302 -22
- 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 +77 -0
- package/hooks/gsd-phase-boundary.sh +1 -0
- package/hooks/gsd-prompt-guard.js +46 -12
- package/hooks/gsd-read-guard.js +18 -7
- package/hooks/gsd-read-injection-scanner.js +22 -13
- package/hooks/gsd-secret-read-guard.js +1079 -0
- package/hooks/gsd-session-state.sh +1 -0
- package/hooks/gsd-statusline.js +222 -29
- package/hooks/gsd-validate-commit.sh +523 -12
- package/hooks/gsd-windsurf-pre-command.js +16 -11
- package/hooks/gsd-windsurf-pre-write.js +22 -13
- package/hooks/gsd-workflow-guard.js +36 -17
- package/hooks/gsd-worktree-path-guard.js +36 -21
- package/hooks/gsd-write-guard.js +35 -25
- package/hooks/hooks.json +6 -0
- package/hooks/lib/cli-exit.js +560 -0
- package/hooks/lib/exit-code-registry.js +98 -0
- package/hooks/lib/git-cmd.js +210 -1
- package/hooks/lib/git-probe.js +84 -0
- package/hooks/lib/hook-exit.js +81 -0
- package/hooks/lib/injection-patterns.js +36 -6
- package/hooks/managed-hooks-registry.cjs +4 -0
- package/package.json +14 -9
- package/scripts/base64-scan.sh +74 -12
- package/scripts/build-hooks.js +12 -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 +52 -12
- package/scripts/ci-timeout-report.cjs +230 -0
- package/scripts/docs-guard-registry.cjs +406 -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 +189 -4
- 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/lib/shellcheck-fetch.cjs +247 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -6
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-docs-guard-registration.cjs +495 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +198 -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 +45 -14
- package/scripts/lint-phase-id-drift.cjs +133 -8
- package/scripts/lint-planning-prompt-drift.cjs +38 -1
- package/scripts/lint-portable-grep.cjs +176 -0
- package/scripts/lint-removed-but-needed.cjs +184 -16
- package/scripts/lint-response-language-coverage.cjs +524 -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-write-path-drift.cjs +337 -432
- package/scripts/lint-test-file-count.allowlist.json +124 -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/lint-workflow-shellcheck-baseline.json +1027 -0
- package/scripts/lint-workflow-shellcheck.cjs +614 -0
- package/scripts/mutation-matrix.cjs +599 -50
- package/scripts/npm-audit-baseline.cjs +376 -0
- package/scripts/prompt-injection-scan.sh +83 -14
- package/scripts/require-issue-link-policy.cjs +16 -1
- 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-execute-phase/SKILL.md +1 -1
- package/skills/gsd-import/SKILL.md +1 -1
- package/skills/gsd-ns-workflow/SKILL.md +1 -0
- package/skills/gsd-phase/SKILL.md +1 -1
- package/skills/gsd-quick/SKILL.md +8 -4
- package/skills/gsd-quick-batch/SKILL.md +105 -0
- package/skills/gsd-surface/SKILL.md +18 -8
- 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
|
@@ -37,7 +37,7 @@ No Pass/Fail buttons. No severity questions. Just: "Here's what should happen. D
|
|
|
37
37
|
If $ARGUMENTS contains a phase number, load context:
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
|
-
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$
|
|
40
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif _gsd_at "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd_run is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; case "$(gsd_run runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') GSD_IDENTITY_STATUS=ok;; esac; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
41
41
|
GSD_WS=""
|
|
42
42
|
echo "$ARGUMENTS" | grep -qE -- '--ws[[:space:]]+[A-Za-z0-9._-]+' && GSD_WS=$(echo "$ARGUMENTS" | grep -oE -- '--ws[[:space:]]+[A-Za-z0-9._-]+')
|
|
43
43
|
PHASE_ARG=$(echo "$ARGUMENTS" | sed -E 's/--ws[[:space:]]+[A-Za-z0-9._-]+//g' | xargs)
|
|
@@ -50,7 +50,7 @@ AGENT_SKILLS_CHECKER=$(gsd_run query agent-skills gsd-plan-checker)
|
|
|
50
50
|
|
|
51
51
|
Parse JSON for: `planner_model`, `checker_model`, `commit_docs`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `has_verification`, `uat_path`, `state_path`, `roadmap_path`, `response_language`.
|
|
52
52
|
|
|
53
|
-
**If `response_language` is set:** All user-facing questions, prompts, and explanations
|
|
53
|
+
**If `response_language` is set:** All user-facing output of this workflow — narration between tool calls, status updates, progress notes, findings, questions, prompts, and explanations — MUST be presented in `{response_language}`. Technical terms, code, file paths, and subagent prompts stay in English — only user-facing output is translated.
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
56
|
# MVP mode detection via the centralized phase.mvp-mode resolver.
|
|
@@ -61,15 +61,26 @@ MVP_MODE=$(gsd_run query phase.mvp-mode "${phase_number}" ${GSD_WS} --pick activ
|
|
|
61
61
|
</step>
|
|
62
62
|
|
|
63
63
|
<step name="verify_pre_hooks">
|
|
64
|
-
**Verify:pre
|
|
65
|
-
|
|
66
|
-
data-driven — resolved from the capability
|
|
64
|
+
**Verify:pre capability dispatch.** Before verification begins, dispatch every
|
|
65
|
+
active hook registered at the `verify:pre` loop extension point — of **every**
|
|
66
|
+
kind, not gates alone. Each hook is data-driven — resolved from the capability
|
|
67
|
+
registry, not hardcoded here.
|
|
67
68
|
|
|
68
69
|
```bash
|
|
69
70
|
VERIFY_PRE_HOOKS_JSON=$(gsd_run loop render-hooks verify:pre --raw)
|
|
70
71
|
PHASE_DIR=$(printf '%s' "$INIT" | jq -r '.phase_dir // empty')
|
|
71
72
|
```
|
|
72
73
|
|
|
74
|
+
Read the `activeHooks` array from `VERIFY_PRE_HOOKS_JSON` in-context (do NOT pipe through a shell parser).
|
|
75
|
+
|
|
76
|
+
**If `activeHooks` is empty or absent:** skip silently to `check_active_session`.
|
|
77
|
+
|
|
78
|
+
**Contribution dispatch:** inject every `kind == "contribution"` fragment per @gsd-core/references/loop-hook-dispatch.md (skip when none), before the steps and gates below.
|
|
79
|
+
|
|
80
|
+
**Step dispatch:** dispatch every `kind == "step"` hook per @gsd-core/references/loop-hook-dispatch.md (skip when none) — not one shape of one. A step here is advisory: it never blocks the start of UAT, and a step that errors is routed by its own `onError` without failing verification. ⚠ **Validate `ref.command` in-context before any shell use** (third-party manifest input) — loop-hook-dispatch.md § `step`.
|
|
81
|
+
|
|
82
|
+
Record the union of `produces` artefact names declared by the active step entries as `VERIFY_PRE_PRODUCED` — `extract_tests` consumes it below. An entry declaring `produces: []` contributes nothing, which is the normal case.
|
|
83
|
+
|
|
73
84
|
⚠ **Validate `check` before shell use** (third-party manifest input) — `loop-hook-dispatch.md` § `gate`.
|
|
74
85
|
|
|
75
86
|
Resolve active gate hooks from `VERIFY_PRE_HOOKS_JSON` where `kind == "gate"`.
|
|
@@ -161,6 +172,27 @@ ls "$phase_dir"/*-SUMMARY.md 2>/dev/null || true
|
|
|
161
172
|
```
|
|
162
173
|
|
|
163
174
|
Read each SUMMARY.md to extract testable deliverables.
|
|
175
|
+
|
|
176
|
+
**Commit-claim reconciliation (#3968).** A SUMMARY's `commits:` frontmatter is a MEASURED
|
|
177
|
+
number (the executor derives it from its on-disk plan commit ledger and records the base as
|
|
178
|
+
`plan_head_before:`), and this is where that claim is checked against reality with the SAME
|
|
179
|
+
instrument — the executor's own narration is never the last word. For each `*-SUMMARY.md`:
|
|
180
|
+
```bash
|
|
181
|
+
BASE=$(grep -oE '^plan_head_before: [0-9a-f]{7,40}' "$SUMMARY_FILE" | awk '{print $2}')
|
|
182
|
+
CLAIMED=$(grep -oE '^commits: [0-9]+' "$SUMMARY_FILE" | grep -oE '[0-9]+' || echo absent)
|
|
183
|
+
ACTUAL=$(git rev-list --count "${BASE}"..HEAD)
|
|
184
|
+
```
|
|
185
|
+
- A `commits: absent` or `plan_head_before: absent` SUMMARY (pre-#3968 legacy) is reported as
|
|
186
|
+
a WARNING with the measured git state, not a mismatch.
|
|
187
|
+
- `ACTUAL == CLAIMED` is consistent. `ACTUAL == CLAIMED + 1` is ALSO consistent: the
|
|
188
|
+
SUMMARY/metadata commit itself lands after the executor measured, so exactly one
|
|
189
|
+
post-measurement commit is expected.
|
|
190
|
+
- Anything else is a **BLOCKER** — the phase must not read as done: real project evidence
|
|
191
|
+
(#3968) showed 14 plans declaring `commits: 1` with zero git activity, their code sitting
|
|
192
|
+
uncommitted and one `git reset --hard` from loss. Record it as `commit_claim_mismatch`
|
|
193
|
+
with both numbers and the SUMMARY path; a mismatch means either the executor narrated
|
|
194
|
+
instead of measuring or commits were lost after the fact — both require reconciliation
|
|
195
|
+
before the phase can pass.
|
|
164
196
|
</step>
|
|
165
197
|
|
|
166
198
|
<step name="extract_tests">
|
|
@@ -187,6 +219,35 @@ Read the JSON result (`mode`, `total`, `all_auto_covered`, `auto_passed[]`, `pre
|
|
|
187
219
|
|
|
188
220
|
The cold-start smoke test injection below still applies in `coverage` mode.
|
|
189
221
|
|
|
222
|
+
**Verify:pre produced-artefact seam (#3866).** If `VERIFY_PRE_PRODUCED` (recorded in
|
|
223
|
+
`verify_pre_hooks`) is empty or absent, skip this paragraph entirely — derivation is unchanged.
|
|
224
|
+
Otherwise, for each artefact name in it, locate the artefact the producing step wrote under
|
|
225
|
+
`$PHASE_DIR` and merge its checkpoints into the test list **additively**.
|
|
226
|
+
|
|
227
|
+
**The artefact contract.** A consumable artefact is a Markdown file holding a list of checkpoint
|
|
228
|
+
entries in the **same shape `extract_tests` already emits and `create_uat_file` already consumes** —
|
|
229
|
+
each entry a `name` (brief test name) and an `expected` (specific, user-observable outcome).
|
|
230
|
+
Nothing else is read: extra fields are ignored, not an error. There is no new schema and no new
|
|
231
|
+
parser — a producing step writes what a checkpoint already looks like. An artefact that yields zero
|
|
232
|
+
parseable entries is treated exactly like an absent one (see below).
|
|
233
|
+
|
|
234
|
+
Merge rules:
|
|
235
|
+
|
|
236
|
+
- ⚠ **Validate the artefact name in-context before resolving it** (third-party manifest input).
|
|
237
|
+
An artefact name is a registry-declared name, **not** a path: check the value you read from
|
|
238
|
+
`produces` against `^[A-Za-z0-9][A-Za-z0-9._-]*$` yourself — **never** by pasting it into a
|
|
239
|
+
shell command to be tested there. A name carrying `/`, `..`, a leading `-`, a leading path
|
|
240
|
+
separator, or any shell metacharacter is a malformed manifest: record a warning, skip that
|
|
241
|
+
name, continue. Only a validated name is resolved, and only against what the step wrote inside
|
|
242
|
+
`$PHASE_DIR` — never above it, and never through a symlink that leaves it.
|
|
243
|
+
- A name with no artefact on disk means that step was inactive, skipped, or failed. Note it to the
|
|
244
|
+
user and derive normally — **never drop a deliverable and never block UAT over it.**
|
|
245
|
+
- Merged entries are added to, never subtracted from, what `coverage:` classification and the
|
|
246
|
+
prose fallback produce. An `auto_passed[]` entry stays un-presented; a `present[]` entry stays a
|
|
247
|
+
human checkpoint. This seam can deepen UAT, not suppress it.
|
|
248
|
+
- Deduplicate against already-derived checkpoints by `name`, keeping the earlier entry's
|
|
249
|
+
`expected` text so a produced artefact cannot silently rewrite a criterion.
|
|
250
|
+
|
|
190
251
|
**Extract testable deliverables from SUMMARY.md (legacy fallback — used when `mode: legacy`):**
|
|
191
252
|
|
|
192
253
|
Parse for:
|
|
@@ -534,6 +595,8 @@ VERIFY_POST_HOOKS_JSON=$(gsd_run loop render-hooks verify:post --raw)
|
|
|
534
595
|
SECURITY_FILE=$(ls "${PHASE_DIR}"/*-SECURITY.md 2>/dev/null | head -1)
|
|
535
596
|
```
|
|
536
597
|
|
|
598
|
+
**Generic step dispatch:** dispatch every `kind == "step"` hook from `VERIFY_POST_HOOKS_JSON` per @gsd-core/references/loop-hook-dispatch.md (skip silently when none). Each step is advisory and best-effort — honor `onError` and continue. The secure-phase handling below is an additional specialization of one such hook, not a replacement for the generic dispatch.
|
|
599
|
+
|
|
537
600
|
Resolve active step hooks from `VERIFY_POST_HOOKS_JSON` where `kind == "step"` and `ref.skill == "secure-phase"`.
|
|
538
601
|
|
|
539
602
|
If an active secure-phase step hook exists AND `SECURITY_FILE` is empty, dispatch the registry-provided skill stem:
|
|
@@ -633,7 +696,7 @@ All tests passed. Phase {phase} marked complete.
|
|
|
633
696
|
<step name="scan_phase_artifacts">
|
|
634
697
|
Run phase artifact scan to surface any open items before marking phase verified:
|
|
635
698
|
|
|
636
|
-
`audit-open` is CJS-only until registered on `
|
|
699
|
+
`audit-open` is CJS-only until registered on `gsd_run query`:
|
|
637
700
|
|
|
638
701
|
```bash
|
|
639
702
|
gsd_run query audit-open --json
|
|
@@ -647,9 +710,12 @@ Parse the JSON output. For the CURRENT PHASE ONLY, surface:
|
|
|
647
710
|
If any are found, display:
|
|
648
711
|
```
|
|
649
712
|
Phase {N} Artifact Check
|
|
650
|
-
|
|
713
|
+
|
|
714
|
+
---
|
|
715
|
+
|
|
651
716
|
{list each item with status and file path}
|
|
652
|
-
|
|
717
|
+
|
|
718
|
+
---
|
|
653
719
|
These items are open. Proceed anyway? [Y/n]
|
|
654
720
|
```
|
|
655
721
|
|
|
@@ -685,9 +751,7 @@ Diagnosis runs automatically - no user prompt. Parallel agents investigate simul
|
|
|
685
751
|
|
|
686
752
|
Display:
|
|
687
753
|
```
|
|
688
|
-
|
|
689
|
-
GSD ► PLANNING FIXES
|
|
690
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
754
|
+
### GSD ► PLANNING FIXES
|
|
691
755
|
|
|
692
756
|
◆ Spawning planner for gap closure... (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)
|
|
693
757
|
```
|
|
@@ -752,9 +816,7 @@ On return:
|
|
|
752
816
|
|
|
753
817
|
Display:
|
|
754
818
|
```
|
|
755
|
-
|
|
756
|
-
GSD ► VERIFYING FIX PLANS
|
|
757
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
819
|
+
### GSD ► VERIFYING FIX PLANS
|
|
758
820
|
|
|
759
821
|
◆ Spawning plan checker... (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)
|
|
760
822
|
```
|
|
@@ -795,7 +857,7 @@ Return one of:
|
|
|
795
857
|
|
|
796
858
|
On return:
|
|
797
859
|
- **VERIFICATION PASSED:** Proceed to `present_ready`
|
|
798
|
-
- **ISSUES FOUND:**
|
|
860
|
+
- **ISSUES FOUND:** Count BLOCKER + WARNING entries in the YAML issues block; an entry whose severity is missing or unrecognized counts as a BLOCKER (fail closed). If zero — every entry is explicitly INFO — display `ℹ advisory — {dimension}: {description}` per entry and proceed to `present_ready`; INFO is advisory and never enters the loop (#3724). Otherwise proceed to `revision_loop`
|
|
799
861
|
</step>
|
|
800
862
|
|
|
801
863
|
<step name="revision_loop">
|
|
@@ -828,6 +890,15 @@ ${AGENT_SKILLS_PLANNER}
|
|
|
828
890
|
|
|
829
891
|
<instructions>
|
|
830
892
|
Read existing PLAN.md files. Make targeted updates to address checker issues.
|
|
893
|
+
|
|
894
|
+
`required_property` + evidence + severity BIND. `fix_hint` is ONE non-binding example route: a
|
|
895
|
+
smaller or different mechanism reaching the same property addresses the issue in full — say which
|
|
896
|
+
you used. Re-check locked decisions, capability guidance (CLAUDE.md, project skills) and the
|
|
897
|
+
constraints these plans already encode BEFORE editing; if a hint would contradict one, or the
|
|
898
|
+
property is unreachable without breaking one, return `## REVISION_CONFLICT` with the conflict and
|
|
899
|
+
the alternatives rather than applying or working around it. Full contract:
|
|
900
|
+
`gsd-core/references/planner-revision.md`, which you load in revision mode.
|
|
901
|
+
|
|
831
902
|
Do NOT replan from scratch unless issues are fundamental.
|
|
832
903
|
</instructions>
|
|
833
904
|
""",
|
|
@@ -839,7 +910,23 @@ Do NOT replan from scratch unless issues are fundamental.
|
|
|
839
910
|
|
|
840
911
|
> **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
|
|
841
912
|
|
|
842
|
-
|
|
913
|
+
**If the planner returns `## REVISION_CONFLICT`:** do NOT increment `iteration_count` and do NOT
|
|
914
|
+
re-spawn the checker — a conflict is not resolvable by re-running the same loop, so it must not
|
|
915
|
+
consume retry budget. Present the conflict table and its alternatives to the user and ask which
|
|
916
|
+
to take: adopt a named alternative / override the named constraint and apply the hint / amend the
|
|
917
|
+
constraint itself. Every option resolves the conflict; accepting the plans with the blocker still
|
|
918
|
+
open is NOT offered here — that choice belongs to the max-iteration escalation below. Re-spawn
|
|
919
|
+
the planner with the chosen resolution and then **re-evaluate its return from the top of this
|
|
920
|
+
handler** — never fall through to the checker spawn below, because a second conflict is still a
|
|
921
|
+
conflict, not a revised plan, and only a NON-conflict return may reach the checker or increment
|
|
922
|
+
`iteration_count`.
|
|
923
|
+
|
|
924
|
+
**Bounded:** a conflict naming the SAME `required_property` twice in a row (no successful revision in between) is a stall, and so is
|
|
925
|
+
the THIRD conflict return of this loop whatever property it names — alternating property names
|
|
926
|
+
would otherwise never trip the repeat rule. Stop re-spawning and route it to the same
|
|
927
|
+
max-iteration escalation below.
|
|
928
|
+
|
|
929
|
+
**On any other return** → spawn checker again (verify_gap_plans logic)
|
|
843
930
|
Increment iteration_count
|
|
844
931
|
|
|
845
932
|
**If iteration_count >= 3:**
|
|
@@ -858,9 +945,7 @@ Wait for user response.
|
|
|
858
945
|
**Present completion and next steps:**
|
|
859
946
|
|
|
860
947
|
```
|
|
861
|
-
|
|
862
|
-
GSD ► FIXES READY ✓
|
|
863
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
948
|
+
### GSD ► FIXES READY ✓
|
|
864
949
|
|
|
865
950
|
**Phase {X}: {Name}** — {N} gap(s) diagnosed, {M} fix plan(s) created
|
|
866
951
|
|
|
@@ -871,7 +956,7 @@ Wait for user response.
|
|
|
871
956
|
|
|
872
957
|
Plans verified and ready for execution.
|
|
873
958
|
|
|
874
|
-
|
|
959
|
+
---
|
|
875
960
|
|
|
876
961
|
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
|
|
877
962
|
|
|
@@ -879,7 +964,7 @@ Plans verified and ready for execution.
|
|
|
879
964
|
|
|
880
965
|
`/clear` then `/gsd:execute-phase {phase} --gaps-only`
|
|
881
966
|
|
|
882
|
-
|
|
967
|
+
---
|
|
883
968
|
```
|
|
884
969
|
</step>
|
|
885
970
|
|
|
@@ -65,6 +65,23 @@ const path = require('path');
|
|
|
65
65
|
const os = require('os');
|
|
66
66
|
const { readSentinel, VALID_ISOLATION, extractDispatchIdentifiers, sentinelAppliesToDispatch } = require('./lib/isolation-sentinel.js');
|
|
67
67
|
const { REASON_CODE } = require('./lib/isolation-deny-reason.js');
|
|
68
|
+
const { HOOK_ON_CRASH, allow, deny, crash } = require('./lib/hook-exit.js');
|
|
69
|
+
|
|
70
|
+
// Required at module top, alongside the other ./lib requires — NOT behind
|
|
71
|
+
// ensureRuntimeBuild() below. Terminating on a parse/timeout failure must
|
|
72
|
+
// never depend on the gitignored build artifacts this hook self-heals for
|
|
73
|
+
// its own registry lookups (#3911).
|
|
74
|
+
//
|
|
75
|
+
// This guard's outer catch (main(), below) has always exited 0 (fail open):
|
|
76
|
+
// that outer catch only covers payload PARSING failing before applicability
|
|
77
|
+
// could even be determined (malformed stdin JSON, etc.) — the guard's real
|
|
78
|
+
// fail-closed logic (a GSD project whose dispatch-isolation configuration
|
|
79
|
+
// cannot be verified) is handled separately, inside evaluateDispatch/
|
|
80
|
+
// resolveIsolationState, and already returns a 'block' decision through the
|
|
81
|
+
// normal exit-2 path rather than through this catch. So an unparseable
|
|
82
|
+
// payload has nothing to enforce; allowing it preserves today's behavior
|
|
83
|
+
// exactly.
|
|
84
|
+
const ON_CRASH = HOOK_ON_CRASH.ALLOW;
|
|
68
85
|
// #3582: gsd-core/bin/lib/*.cjs (runtime-name-policy.cjs, capability-registry.cjs
|
|
69
86
|
// below) are tsc build artifacts (ADR-457), gitignored and absent on a raw
|
|
70
87
|
// plugin-marketplace / git-clone install that never ran `npm run build:lib`.
|
|
@@ -95,40 +112,40 @@ function parseHarnessFlag(flag) {
|
|
|
95
112
|
return { param: m[1], value: m[2] };
|
|
96
113
|
}
|
|
97
114
|
|
|
98
|
-
// ─── #
|
|
115
|
+
// ─── #3897 rung 2: per-install runtime marker, single canonical owner ────────
|
|
99
116
|
// bin/install.js writes `<install>/gsd-core/.gsd-runtime` for EVERY runtime
|
|
100
117
|
// install (#2297), co-located with VERSION. Unlike `~/.gsd/defaults.json` —
|
|
101
118
|
// which is host-wide and names whichever runtime's install ran LAST, the exact
|
|
102
119
|
// leakage #2840's config.cjs change exists to prevent — the marker describes
|
|
103
120
|
// THIS install, which is the property runtime identity needs on a machine
|
|
104
|
-
// with 2+ runtimes.
|
|
105
|
-
// (
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
//
|
|
109
|
-
// consolidating every marker reader into one shared seam.
|
|
110
|
-
let _installMarkerCache; // undefined = unread; null = known absent; string = value
|
|
111
|
-
|
|
121
|
+
// with 2+ runtimes. Previously this hook held its own private reader/cache
|
|
122
|
+
// (one of four #3897 found); it now delegates to the single canonical owner,
|
|
123
|
+
// `src/runtime-slash.cts` (compiled to gsd-core/bin/lib/runtime-slash.cjs),
|
|
124
|
+
// reached through `ensureRuntimeBuild()` like every other compiled-lib require
|
|
125
|
+
// in this file (`scripts/lint-hooks-runtime-build-seam.cjs`).
|
|
112
126
|
function readInstallRuntimeMarker() {
|
|
113
|
-
if (_installMarkerCache !== undefined) return _installMarkerCache;
|
|
114
127
|
try {
|
|
115
|
-
|
|
116
|
-
const
|
|
117
|
-
|
|
128
|
+
ensureRuntimeBuild();
|
|
129
|
+
const runtimeSlash = require('../gsd-core/bin/lib/runtime-slash.cjs');
|
|
130
|
+
return runtimeSlash.readInstallRuntimeMarker();
|
|
118
131
|
} catch {
|
|
119
|
-
//
|
|
120
|
-
// from this rung", never a resolution failure.
|
|
121
|
-
|
|
122
|
-
_installMarkerCache = null;
|
|
132
|
+
// Unbuilt runtime library, or any other failure reaching the canonical
|
|
133
|
+
// owner — "no signal from this rung" (N4), never a resolution failure.
|
|
134
|
+
return null;
|
|
123
135
|
}
|
|
124
|
-
return _installMarkerCache;
|
|
125
136
|
}
|
|
126
137
|
|
|
127
|
-
// Test seam for the marker rung
|
|
128
|
-
//
|
|
129
|
-
// model-resolver.cts's _setInstallRuntimeMarkerForTests, #2297).
|
|
138
|
+
// Test seam for the marker rung — forwards to the canonical owner's seam so
|
|
139
|
+
// this hook and runtime-slash.cjs always share one cache (#3897 rung 2).
|
|
130
140
|
function _setInstallRuntimeMarkerForTests(value) {
|
|
131
|
-
|
|
141
|
+
try {
|
|
142
|
+
ensureRuntimeBuild();
|
|
143
|
+
const runtimeSlash = require('../gsd-core/bin/lib/runtime-slash.cjs');
|
|
144
|
+
runtimeSlash._setInstallRuntimeMarkerForTests(value);
|
|
145
|
+
} catch {
|
|
146
|
+
// Test-only seam; an unbuilt library here means the test itself will fail
|
|
147
|
+
// downstream, which is a louder and more actionable signal than throwing here.
|
|
148
|
+
}
|
|
132
149
|
}
|
|
133
150
|
|
|
134
151
|
/**
|
|
@@ -282,18 +299,40 @@ function resolveRegistryIsolation(cwd, configPath) {
|
|
|
282
299
|
|
|
283
300
|
if (isolation === 'harness-worktree') {
|
|
284
301
|
let useWorktrees = true;
|
|
302
|
+
// #3972: the opt-out read shares the ONE owner every other
|
|
303
|
+
// isolation-deciding surface uses — planning-workspace's
|
|
304
|
+
// worktreesOptedOut ladder (scoped own-key wins; root inherited under
|
|
305
|
+
// the GSD_WORKSTREAM gate; strict === false). A flat single-file read
|
|
306
|
+
// here made a workstream-LOCAL opt-out invisible, so the sentinel-absent
|
|
307
|
+
// fallback denied a sequential dispatch the config explicitly allowed.
|
|
308
|
+
// Reached through ensureRuntimeBuild() like every other compiled-lib
|
|
309
|
+
// require in this file (scripts/lint-hooks-runtime-build-seam.cjs); if
|
|
310
|
+
// the library is unreachable the flat-root read below remains as the
|
|
311
|
+
// degraded fallback — today's behavior, never worse.
|
|
312
|
+
let ladderAnswered = false;
|
|
285
313
|
try {
|
|
286
|
-
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
useWorktrees = false;
|
|
291
|
-
}
|
|
314
|
+
ensureRuntimeBuild();
|
|
315
|
+
const { worktreesOptedOut } = require('../gsd-core/bin/lib/planning-workspace.cjs');
|
|
316
|
+
useWorktrees = !worktreesOptedOut(cwd);
|
|
317
|
+
ladderAnswered = true;
|
|
292
318
|
} catch {
|
|
293
|
-
//
|
|
294
|
-
//
|
|
295
|
-
|
|
296
|
-
|
|
319
|
+
// Unbuilt runtime library or a ladder failure — fall through to the
|
|
320
|
+
// legacy flat-root read (conservative: keep enforcing).
|
|
321
|
+
}
|
|
322
|
+
if (!ladderAnswered) {
|
|
323
|
+
try {
|
|
324
|
+
const raw = fs.readFileSync(configPath, 'utf-8');
|
|
325
|
+
const parsedCfg = JSON.parse(raw);
|
|
326
|
+
if (parsedCfg && typeof parsedCfg === 'object' && parsedCfg.workflow &&
|
|
327
|
+
typeof parsedCfg.workflow === 'object' && parsedCfg.workflow.use_worktrees === false) {
|
|
328
|
+
useWorktrees = false;
|
|
329
|
+
}
|
|
330
|
+
} catch {
|
|
331
|
+
// Unreadable config already propagated to the outer caller's catch
|
|
332
|
+
// before this point in practice (resolveRuntimeIdentity reads it
|
|
333
|
+
// first); tolerate defensively and keep the conservative (enforce)
|
|
334
|
+
// default rather than silently disabling the guard.
|
|
335
|
+
}
|
|
297
336
|
}
|
|
298
337
|
if (!useWorktrees) isolation = 'none';
|
|
299
338
|
}
|
|
@@ -476,7 +515,7 @@ function evaluateDispatch(data, { clock = Date } = {}) {
|
|
|
476
515
|
/* istanbul ignore next -- stdin adapter, exercised via spawnSync in tests */
|
|
477
516
|
function main() {
|
|
478
517
|
let input = '';
|
|
479
|
-
const stdinTimeout = setTimeout(() =>
|
|
518
|
+
const stdinTimeout = setTimeout(() => allow(undefined), 3000);
|
|
480
519
|
process.stdin.setEncoding('utf8');
|
|
481
520
|
process.stdin.on('data', (chunk) => { input += chunk; });
|
|
482
521
|
process.stdin.on('end', () => {
|
|
@@ -486,18 +525,18 @@ function main() {
|
|
|
486
525
|
const decision = evaluateDispatch(data);
|
|
487
526
|
if (decision.action === 'block') {
|
|
488
527
|
const out = { decision: 'block', reason: decision.reason, reason_code: decision.reasonCode };
|
|
489
|
-
process.stdout.write(JSON.stringify(out));
|
|
490
528
|
// Kimi feeds stderr (not stdout) back to the model on exit 2.
|
|
491
|
-
|
|
492
|
-
process.exit(2);
|
|
529
|
+
deny(out, decision.reason);
|
|
493
530
|
}
|
|
494
|
-
|
|
531
|
+
allow(undefined);
|
|
495
532
|
} catch {
|
|
496
533
|
// Silent fail — never block valid tool calls due to hook errors
|
|
497
534
|
// (malformed payload, etc.). This is distinct from resolveIsolationState's
|
|
498
535
|
// internal error handling, which DOES deny — this outer catch only
|
|
499
536
|
// covers payload parsing before applicability could even be determined.
|
|
500
|
-
|
|
537
|
+
// ON_CRASH is declared ALLOW at module top: this preserves today's
|
|
538
|
+
// exit(0) fail-open behavior exactly (#3911).
|
|
539
|
+
crash(ON_CRASH, undefined);
|
|
501
540
|
}
|
|
502
541
|
});
|
|
503
542
|
}
|
|
@@ -156,5 +156,22 @@ const result = {
|
|
|
156
156
|
};
|
|
157
157
|
|
|
158
158
|
if (cacheFile) {
|
|
159
|
-
|
|
160
|
-
|
|
159
|
+
// #4091: the cache file is shared per-PACKAGE across every runtime's worker
|
|
160
|
+
// (#607/#1421), so concurrent statusline/banner readers parse it while this
|
|
161
|
+
// worker writes it. A direct writeFileSync truncates before writing — a
|
|
162
|
+
// reader landing mid-write sees a torn/empty record (its JSON.parse catch
|
|
163
|
+
// swallows it, so the symptom is an intermittently blank update segment).
|
|
164
|
+
// Publish atomically instead: stage under a unique same-directory temp
|
|
165
|
+
// (same filesystem, so rename(2) is atomic — readers see the old or the new
|
|
166
|
+
// record, never a partial one), then renameSync into place. Failure policy
|
|
167
|
+
// is unchanged (#3582 degrade): any error is swallowed and the temp, if
|
|
168
|
+
// left behind, is best-effort removed.
|
|
169
|
+
const tmp = cacheFile + '.tmp-' + process.pid;
|
|
170
|
+
try {
|
|
171
|
+
fs.writeFileSync(tmp, JSON.stringify(result));
|
|
172
|
+
fs.renameSync(tmp, cacheFile);
|
|
173
|
+
} catch (e) {
|
|
174
|
+
try {
|
|
175
|
+
fs.rmSync(tmp, { force: true });
|
|
176
|
+
} catch (e2) {}
|
|
177
|
+
}}
|
|
@@ -20,11 +20,17 @@
|
|
|
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 hook only injects an advisory config-reload summary; a crash mid-parse
|
|
26
|
+
// must not block the session or the FileChanged event that triggered it — the
|
|
27
|
+
// agent simply keeps using the config context it already had (#3911).
|
|
28
|
+
const ON_CRASH = HOOK_ON_CRASH.ALLOW;
|
|
23
29
|
|
|
24
30
|
let input = '';
|
|
25
31
|
// Timeout guard: if stdin does not close within 8s exit silently rather than
|
|
26
32
|
// hanging until Claude Code kills the process and reports "hook error".
|
|
27
|
-
const stdinTimeout = setTimeout(() =>
|
|
33
|
+
const stdinTimeout = setTimeout(() => allow(undefined), 8000);
|
|
28
34
|
process.stdin.setEncoding('utf8');
|
|
29
35
|
process.stdin.on('data', chunk => (input += chunk));
|
|
30
36
|
process.stdin.on('end', () => {
|
|
@@ -42,24 +48,23 @@ process.stdin.on('end', () => {
|
|
|
42
48
|
// inject spurious additionalContext.
|
|
43
49
|
const basename = path.basename(filePath);
|
|
44
50
|
if (basename !== 'config.json') {
|
|
45
|
-
|
|
51
|
+
allow(undefined);
|
|
46
52
|
}
|
|
47
53
|
const expectedPath = path.resolve(cwd, '.planning', 'config.json');
|
|
48
54
|
if (path.resolve(filePath) !== expectedPath) {
|
|
49
|
-
|
|
55
|
+
allow(undefined);
|
|
50
56
|
}
|
|
51
57
|
|
|
52
58
|
// On unlink (deletion) emit a brief notice and exit
|
|
53
59
|
if (event === 'unlink') {
|
|
54
|
-
|
|
60
|
+
allow({
|
|
55
61
|
hookSpecificOutput: {
|
|
56
62
|
hookEventName: 'FileChanged',
|
|
57
63
|
additionalContext:
|
|
58
64
|
'GSD config (.planning/config.json) was deleted. ' +
|
|
59
65
|
'Falling back to built-in defaults for this session.',
|
|
60
66
|
},
|
|
61
|
-
})
|
|
62
|
-
process.exit(0);
|
|
67
|
+
});
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
// Read the updated config file
|
|
@@ -68,17 +73,16 @@ process.stdin.on('end', () => {
|
|
|
68
73
|
const raw = fs.readFileSync(filePath, 'utf8');
|
|
69
74
|
config = JSON.parse(raw);
|
|
70
75
|
} catch (e) {
|
|
71
|
-
if (e && e.code === 'ENOENT')
|
|
76
|
+
if (e && e.code === 'ENOENT') allow(undefined);
|
|
72
77
|
// Malformed JSON — inform the agent without crashing
|
|
73
|
-
|
|
78
|
+
allow({
|
|
74
79
|
hookSpecificOutput: {
|
|
75
80
|
hookEventName: 'FileChanged',
|
|
76
81
|
additionalContext:
|
|
77
82
|
'GSD config (.planning/config.json) was modified but could not be parsed. ' +
|
|
78
83
|
'Check the file for JSON syntax errors.',
|
|
79
84
|
},
|
|
80
|
-
})
|
|
81
|
-
process.exit(0);
|
|
85
|
+
});
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
// Build a concise summary of key config fields the agent cares about
|
|
@@ -127,7 +131,9 @@ process.stdin.on('end', () => {
|
|
|
127
131
|
},
|
|
128
132
|
}));
|
|
129
133
|
} catch (e) {
|
|
130
|
-
// Silent fail — never block the session on a config reload error
|
|
131
|
-
|
|
134
|
+
// Silent fail — never block the session on a config reload error.
|
|
135
|
+
// ON_CRASH is declared ALLOW at module top: this preserves today's
|
|
136
|
+
// exit(0) fail-open behavior exactly (#3911).
|
|
137
|
+
crash(ON_CRASH, undefined);
|
|
132
138
|
}
|
|
133
139
|
});
|