@opengsd/gsd-core 1.15.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.opencode/plugins/gsd-core.js +85 -5
- package/agents/gsd-code-fixer.compact.md +1 -1
- package/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-code-reviewer.compact.md +5 -3
- package/agents/gsd-code-reviewer.md +8 -6
- package/agents/gsd-debug-session-manager.compact.md +1 -1
- package/agents/gsd-debug-session-manager.md +1 -1
- package/agents/gsd-debugger.md +2 -2
- package/agents/gsd-eval-auditor.compact.md +1 -1
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +4 -4
- package/agents/gsd-intel-updater.compact.md +1 -1
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +2 -2
- package/agents/gsd-phase-researcher.md +1 -1
- package/agents/gsd-plan-checker.md +7 -2
- package/agents/gsd-planner.md +3 -3
- package/agents/gsd-project-researcher.compact.md +1 -1
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.compact.md +1 -1
- package/agents/gsd-research-synthesizer.md +1 -1
- package/agents/gsd-ui-auditor.compact.md +21 -30
- package/agents/gsd-ui-auditor.md +42 -51
- package/agents/gsd-ui-researcher.compact.md +1 -1
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-verifier.md +31 -9
- package/bin/install.js +126 -196
- package/commands/gsd/add-tests.md +6 -1
- package/commands/gsd/ai-integration-phase.md +6 -1
- package/commands/gsd/audit-fix.md +5 -0
- package/commands/gsd/audit-milestone.md +6 -1
- package/commands/gsd/autonomous.md +5 -0
- package/commands/gsd/capture.md +8 -4
- package/commands/gsd/code-review.md +7 -2
- package/commands/gsd/complete-milestone.md +4 -0
- package/commands/gsd/config.md +7 -3
- package/commands/gsd/debug.md +11 -7
- package/commands/gsd/discuss-phase.md +7 -3
- package/commands/gsd/docs-update.md +12 -7
- package/commands/gsd/eval-review.md +6 -1
- package/commands/gsd/execute-phase.md +12 -7
- package/commands/gsd/extract-learnings.md +5 -0
- package/commands/gsd/fast.md +4 -0
- package/commands/gsd/forensics.md +5 -1
- package/commands/gsd/graphify.md +10 -6
- package/commands/gsd/health.md +5 -0
- package/commands/gsd/help.md +7 -2
- package/commands/gsd/import.md +7 -3
- package/commands/gsd/inbox.md +5 -0
- package/commands/gsd/ingest-docs.md +5 -1
- package/commands/gsd/manager.md +6 -1
- package/commands/gsd/map-codebase.md +7 -3
- package/commands/gsd/mempalace-capture.md +5 -1
- package/commands/gsd/mempalace-recall.md +5 -1
- package/commands/gsd/milestone-summary.md +5 -1
- package/commands/gsd/mvp-phase.md +8 -3
- package/commands/gsd/new-milestone.md +6 -1
- package/commands/gsd/new-project.md +5 -0
- package/commands/gsd/next.md +6 -1
- package/commands/gsd/ns-context.md +4 -0
- package/commands/gsd/ns-ideate.md +4 -0
- package/commands/gsd/ns-manage.md +4 -0
- package/commands/gsd/ns-project.md +4 -0
- package/commands/gsd/ns-review.md +4 -0
- package/commands/gsd/ns-workflow.md +4 -0
- package/commands/gsd/onboard.md +6 -1
- package/commands/gsd/pause-work.md +5 -1
- package/commands/gsd/phase.md +8 -4
- package/commands/gsd/plan-phase.md +6 -1
- package/commands/gsd/plan-review-convergence.md +5 -1
- package/commands/gsd/pr-branch.md +4 -0
- package/commands/gsd/profile-user.md +5 -1
- package/commands/gsd/progress.md +6 -1
- package/commands/gsd/quick-batch.md +20 -8
- package/commands/gsd/quick.md +12 -7
- package/commands/gsd/review.md +5 -1
- package/commands/gsd/secure-phase.md +6 -1
- package/commands/gsd/ship.md +5 -0
- package/commands/gsd/sketch.md +7 -2
- package/commands/gsd/spec-phase.md +5 -1
- package/commands/gsd/spike.md +8 -3
- package/commands/gsd/surface.md +5 -1
- package/commands/gsd/thread.md +4 -0
- package/commands/gsd/ui-phase.md +6 -1
- package/commands/gsd/ui-review.md +6 -1
- package/commands/gsd/ultraplan-phase.md +5 -1
- package/commands/gsd/undo.md +5 -1
- package/commands/gsd/update.md +6 -2
- package/commands/gsd/validate-phase.md +6 -1
- package/commands/gsd/verify-work.md +6 -1
- package/commands/gsd/workspace.md +7 -3
- package/gsd-core/bin/gsd-tools.cjs +142 -56
- package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
- package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
- package/gsd-core/bin/lib/audit.cjs +78 -44
- package/gsd-core/bin/lib/broken-windows.cjs +13 -13
- package/gsd-core/bin/lib/capability-activation.cjs +9 -4
- package/gsd-core/bin/lib/capability-registry.cjs +183 -103
- package/gsd-core/bin/lib/capability-validator.cjs +16 -0
- package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
- package/gsd-core/bin/lib/check-command-router.cjs +164 -1712
- package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
- package/gsd-core/bin/lib/cli-exit.cjs +12 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +11 -8
- package/gsd-core/bin/lib/command-aliases.cjs +7 -0
- package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
- package/gsd-core/bin/lib/commands.cjs +173 -170
- package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
- package/gsd-core/bin/lib/config.cjs +43 -12
- package/gsd-core/bin/lib/core-utils.cjs +6 -1
- package/gsd-core/bin/lib/coverage.cjs +4 -8
- package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
- package/gsd-core/bin/lib/drift.cjs +177 -42
- package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
- package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
- package/gsd-core/bin/lib/frontmatter.cjs +413 -234
- package/gsd-core/bin/lib/gap-checker.cjs +72 -29
- package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
- package/gsd-core/bin/lib/gate-args.cjs +53 -0
- package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
- package/gsd-core/bin/lib/gate-config.cjs +46 -0
- package/gsd-core/bin/lib/gate-context-drift.cjs +141 -0
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
- package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
- package/gsd-core/bin/lib/gate-exit.cjs +27 -0
- package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
- package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
- package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
- package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
- package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
- package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
- package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
- package/gsd-core/bin/lib/gate-ui-safety.cjs +80 -0
- package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
- package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
- package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
- package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
- package/gsd-core/bin/lib/init.cjs +162 -96
- package/gsd-core/bin/lib/install-engine.cjs +19 -35
- package/gsd-core/bin/lib/install-profiles.cjs +7 -4
- package/gsd-core/bin/lib/io.cjs +122 -3
- package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
- package/gsd-core/bin/lib/milestone.cjs +19 -1
- package/gsd-core/bin/lib/model-resolver.cjs +18 -18
- package/gsd-core/bin/lib/observability/event.cjs +1 -1
- package/gsd-core/bin/lib/observability/logger.cjs +46 -1
- package/gsd-core/bin/lib/pattern.cjs +10 -0
- package/gsd-core/bin/lib/phase-command-router.cjs +11 -4
- package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
- package/gsd-core/bin/lib/phase-id.cjs +1 -1
- package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
- package/gsd-core/bin/lib/phase-status.cjs +360 -0
- package/gsd-core/bin/lib/phase.cjs +280 -80
- package/gsd-core/bin/lib/plan-document.cjs +93 -19
- package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
- package/gsd-core/bin/lib/planning-document.cjs +273 -40
- package/gsd-core/bin/lib/planning-inspect.cjs +42 -8
- package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +76 -53
- package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
- package/gsd-core/bin/lib/profile-output.cjs +6 -3
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
- package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +11 -8
- package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
- package/gsd-core/bin/lib/report-parser.cjs +269 -0
- package/gsd-core/bin/lib/roadmap-command-router.cjs +13 -15
- package/gsd-core/bin/lib/roadmap-parser.cjs +82 -15
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +127 -65
- package/gsd-core/bin/lib/roadmap.cjs +169 -72
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +91 -157
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +2 -1
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
- package/gsd-core/bin/lib/runtime-homes.cjs +13 -10
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +307 -591
- package/gsd-core/bin/lib/runtime-name-policy.cjs +142 -27
- package/gsd-core/bin/lib/runtime-slash.cjs +47 -30
- package/gsd-core/bin/lib/shell-command-projection.cjs +37 -2
- package/gsd-core/bin/lib/smart-entry.cjs +19 -3
- package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
- package/gsd-core/bin/lib/state-contract.cjs +15 -18
- package/gsd-core/bin/lib/state-document.cjs +100 -22
- package/gsd-core/bin/lib/state.cjs +214 -105
- package/gsd-core/bin/lib/surface.cjs +2 -1
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -152
- package/gsd-core/bin/lib/uat-predicate.cjs +313 -35
- package/gsd-core/bin/lib/uat.cjs +424 -7
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +94 -58
- package/gsd-core/bin/lib/vendor/README.md +31 -9
- package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
- package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +1165 -314
- package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
- package/gsd-core/bin/lib/verify.cjs +286 -567
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
- package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
- package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
- package/gsd-core/bin/lib/workstream.cjs +11 -2
- package/gsd-core/bin/shared/config-defaults.manifest.json +5 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +4 -0
- package/gsd-core/references/autonomous-smart-discuss.md +2 -1
- package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
- package/gsd-core/references/execute-mvp-tdd.md +5 -10
- package/gsd-core/references/execute-phase-between-wave-reset.md +3 -0
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +7 -1
- package/gsd-core/references/offer-next.md +1 -1
- package/gsd-core/references/planning-config.md +1 -1
- package/gsd-core/references/spidr-splitting.md +1 -1
- package/gsd-core/references/tdd.md +10 -4
- package/gsd-core/references/verifier-phase-gates.md +5 -2
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -3
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/UAT.md +17 -1
- package/gsd-core/templates/config.json +2 -11
- package/gsd-core/templates/verification-report.md +1 -1
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +8 -7
- package/gsd-core/workflows/add-tests.md +3 -2
- package/gsd-core/workflows/add-todo.md +4 -3
- package/gsd-core/workflows/ai-integration-phase.md +3 -2
- package/gsd-core/workflows/audit-fix.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +4 -3
- package/gsd-core/workflows/audit-uat.md +1 -1
- package/gsd-core/workflows/autonomous.md +28 -18
- package/gsd-core/workflows/check-todos.md +6 -5
- package/gsd-core/workflows/cleanup.md +1 -1
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
- package/gsd-core/workflows/code-review-fix.md +5 -4
- package/gsd-core/workflows/code-review.md +84 -90
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
- package/gsd-core/workflows/complete-milestone.md +12 -7
- package/gsd-core/workflows/debug.md +30 -5
- package/gsd-core/workflows/diagnose-issues.md +3 -2
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +4 -3
- package/gsd-core/workflows/do.md +1 -1
- package/gsd-core/workflows/docs-update.md +4 -3
- package/gsd-core/workflows/edit-phase.md +4 -3
- package/gsd-core/workflows/eval-review.md +5 -3
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +4 -2
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
- package/gsd-core/workflows/execute-phase.md +78 -170
- package/gsd-core/workflows/execute-plan.md +13 -19
- package/gsd-core/workflows/explore.md +2 -2
- package/gsd-core/workflows/extract-learnings.md +3 -2
- package/gsd-core/workflows/fast.md +1 -1
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +2 -1
- package/gsd-core/workflows/import.md +3 -2
- package/gsd-core/workflows/inbox.md +1 -1
- package/gsd-core/workflows/ingest-docs.md +1 -1
- package/gsd-core/workflows/insert-phase.md +4 -3
- package/gsd-core/workflows/list-seeds.md +1 -1
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +5 -3
- package/gsd-core/workflows/map-codebase.md +4 -3
- package/gsd-core/workflows/milestone-summary.md +3 -2
- package/gsd-core/workflows/mvp-phase.md +14 -14
- package/gsd-core/workflows/new-milestone.md +10 -10
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +1 -1
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +1 -1
- package/gsd-core/workflows/pause-work.md +2 -2
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +1 -1
- package/gsd-core/workflows/plan-phase.md +27 -18
- package/gsd-core/workflows/plan-review-convergence.md +1 -1
- package/gsd-core/workflows/plant-seed.md +1 -1
- package/gsd-core/workflows/pr-branch.md +1 -1
- package/gsd-core/workflows/profile-user.md +1 -1
- package/gsd-core/workflows/progress.md +19 -49
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +4 -2
- package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +9 -3
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
- package/gsd-core/workflows/quick-batch.md +15 -10
- package/gsd-core/workflows/quick.md +42 -31
- package/gsd-core/workflows/remove-phase.md +3 -2
- package/gsd-core/workflows/remove-workspace.md +1 -1
- package/gsd-core/workflows/resume-project.md +3 -2
- package/gsd-core/workflows/review.md +3 -2
- package/gsd-core/workflows/scan.md +3 -2
- package/gsd-core/workflows/secure-phase.md +11 -12
- package/gsd-core/workflows/settings-advanced.md +1 -1
- package/gsd-core/workflows/settings-integrations.md +1 -1
- package/gsd-core/workflows/settings.md +1 -1
- package/gsd-core/workflows/ship.md +12 -12
- package/gsd-core/workflows/sketch-wrap-up.md +1 -1
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/smart-entry.md +1 -1
- package/gsd-core/workflows/spec-phase.md +1 -1
- package/gsd-core/workflows/spike-wrap-up.md +1 -1
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +1 -1
- package/gsd-core/workflows/sync-skills.md +1 -1
- package/gsd-core/workflows/thread.md +2 -2
- package/gsd-core/workflows/transition.md +13 -23
- package/gsd-core/workflows/ui-phase.md +5 -4
- package/gsd-core/workflows/ui-review.md +4 -3
- package/gsd-core/workflows/ultraplan-phase.md +3 -2
- package/gsd-core/workflows/undo.md +1 -1
- package/gsd-core/workflows/validate-phase.md +10 -12
- package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
- package/gsd-core/workflows/verify-work.md +68 -59
- package/hooks/dist/gsd-agent-isolation-guard.js +8 -0
- package/hooks/dist/gsd-check-update-worker.js +8 -0
- package/hooks/dist/gsd-check-update.js +8 -0
- package/hooks/dist/gsd-context-monitor.js +31 -8
- package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
- package/hooks/dist/gsd-secret-read-guard.js +147 -16
- package/hooks/dist/gsd-statusline.js +15 -7
- package/hooks/dist/gsd-update-banner.js +8 -0
- package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
- package/hooks/dist/gsd-workflow-guard.js +5 -4
- package/hooks/dist/gsd-worktree-path-guard.js +6 -2
- package/hooks/dist/lib/cli-exit.js +12 -0
- package/hooks/dist/lib/git-probe.js +17 -1
- package/hooks/dist/lib/isolation-sentinel.js +2 -2
- package/hooks/gsd-agent-isolation-guard.js +8 -0
- package/hooks/gsd-check-update-worker.js +8 -0
- package/hooks/gsd-check-update.js +8 -0
- package/hooks/gsd-context-monitor.js +31 -8
- package/hooks/gsd-cursor-subagent-start.js +8 -0
- package/hooks/gsd-secret-read-guard.js +147 -16
- package/hooks/gsd-statusline.js +15 -7
- package/hooks/gsd-update-banner.js +8 -0
- package/hooks/gsd-windsurf-pre-write.js +11 -2
- package/hooks/gsd-workflow-guard.js +5 -4
- package/hooks/gsd-worktree-path-guard.js +6 -2
- package/hooks/hooks.json +5 -5
- package/hooks/lib/cli-exit.js +12 -0
- package/hooks/lib/git-probe.js +17 -1
- package/hooks/lib/isolation-sentinel.js +2 -2
- package/package.json +21 -4
- package/scripts/changeset/parse.cjs +52 -4
- package/scripts/ci-timeout-report.cjs +770 -4
- package/scripts/command-contract-helpers.cjs +12 -8
- package/scripts/docs-guard-registry.cjs +6 -0
- package/scripts/gen-features.cjs +13 -8
- package/scripts/gen-hooks-cli-exit.cjs +12 -28
- package/scripts/gen-loop-host-contract.cjs +10 -1
- package/scripts/gen-platform-conformance-tier.cjs +187 -1
- package/scripts/gen-plugin-skills.cjs +87 -1
- package/scripts/gen-research-agents.cjs +24 -31
- package/scripts/gen-scripts-cli-exit.cjs +30 -3
- package/scripts/gen-test-timings.cjs +32 -7
- package/scripts/lib/cli-exit.cjs +12 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +20 -2
- package/scripts/lib/ndjson-reporter.cjs +28 -3
- package/scripts/lib/platform-conformance-tier.generated.cjs +34 -5
- package/scripts/lib/registration-ledger-preload.cjs +155 -0
- package/scripts/lib/vendor-bundle.cjs +59 -0
- package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-completion-predicate-drift.cjs +18 -19
- package/scripts/lint-descriptions.cjs +7 -3
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +10 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
- package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
- package/scripts/lint-phase-enumeration-drift.cjs +12 -8
- package/scripts/lint-phase-id-drift.cjs +29 -0
- package/scripts/lint-planning-document-positive-control.cjs +329 -0
- package/scripts/lint-response-language-coverage.cjs +3 -0
- package/scripts/lint-skill-deps.cjs +7 -3
- package/scripts/lint-test-file-count.allowlist.json +11 -1
- package/scripts/lint-test-file-count.cjs +34 -1
- package/scripts/lint-vendored-deps.cjs +41 -5
- package/scripts/lint-workflow-shellcheck-baseline.json +10 -10
- package/scripts/mutation-matrix.cjs +50 -5
- package/scripts/require-issue-link-policy.cjs +6 -2
- package/scripts/sync-runtime-launcher.cjs +184 -2
- package/scripts/verify-npm-publish.cjs +76 -20
- package/skills/gsd-add-tests/SKILL.md +6 -1
- package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
- package/skills/gsd-audit-fix/SKILL.md +5 -0
- package/skills/gsd-audit-milestone/SKILL.md +6 -1
- package/skills/gsd-autonomous/SKILL.md +5 -0
- package/skills/gsd-capture/SKILL.md +8 -4
- package/skills/gsd-code-review/SKILL.md +7 -2
- package/skills/gsd-complete-milestone/SKILL.md +4 -0
- package/skills/gsd-config/SKILL.md +8 -4
- package/skills/gsd-debug/SKILL.md +11 -7
- package/skills/gsd-discuss-phase/SKILL.md +7 -3
- package/skills/gsd-docs-update/SKILL.md +12 -7
- package/skills/gsd-eval-review/SKILL.md +6 -1
- package/skills/gsd-execute-phase/SKILL.md +12 -7
- package/skills/gsd-extract-learnings/SKILL.md +5 -0
- package/skills/gsd-fast/SKILL.md +4 -0
- package/skills/gsd-forensics/SKILL.md +5 -1
- package/skills/gsd-graphify/SKILL.md +10 -6
- package/skills/gsd-health/SKILL.md +5 -0
- package/skills/gsd-help/SKILL.md +7 -2
- package/skills/gsd-import/SKILL.md +7 -3
- package/skills/gsd-inbox/SKILL.md +5 -0
- package/skills/gsd-ingest-docs/SKILL.md +5 -1
- package/skills/gsd-manager/SKILL.md +6 -1
- package/skills/gsd-map-codebase/SKILL.md +7 -3
- package/skills/gsd-mempalace-capture/SKILL.md +5 -1
- package/skills/gsd-mempalace-recall/SKILL.md +5 -1
- package/skills/gsd-milestone-summary/SKILL.md +5 -1
- package/skills/gsd-mvp-phase/SKILL.md +8 -3
- package/skills/gsd-new-milestone/SKILL.md +6 -1
- package/skills/gsd-new-project/SKILL.md +5 -0
- package/skills/gsd-next/SKILL.md +6 -1
- package/skills/gsd-ns-context/SKILL.md +4 -0
- package/skills/gsd-ns-ideate/SKILL.md +4 -0
- package/skills/gsd-ns-manage/SKILL.md +4 -0
- package/skills/gsd-ns-project/SKILL.md +4 -0
- package/skills/gsd-ns-review/SKILL.md +4 -0
- package/skills/gsd-ns-workflow/SKILL.md +4 -0
- package/skills/gsd-onboard/SKILL.md +6 -1
- package/skills/gsd-pause-work/SKILL.md +5 -1
- package/skills/gsd-phase/SKILL.md +8 -4
- package/skills/gsd-plan-phase/SKILL.md +6 -1
- package/skills/gsd-plan-review-convergence/SKILL.md +5 -1
- package/skills/gsd-pr-branch/SKILL.md +4 -0
- package/skills/gsd-profile-user/SKILL.md +5 -1
- package/skills/gsd-progress/SKILL.md +6 -1
- package/skills/gsd-quick/SKILL.md +16 -10
- package/skills/gsd-quick-batch/SKILL.md +20 -8
- package/skills/gsd-review/SKILL.md +5 -1
- package/skills/gsd-review-backlog/SKILL.md +3 -2
- package/skills/gsd-secure-phase/SKILL.md +6 -1
- package/skills/gsd-ship/SKILL.md +5 -0
- package/skills/gsd-sketch/SKILL.md +7 -2
- package/skills/gsd-spec-phase/SKILL.md +5 -1
- package/skills/gsd-spike/SKILL.md +8 -3
- package/skills/gsd-surface/SKILL.md +5 -1
- package/skills/gsd-thread/SKILL.md +4 -0
- package/skills/gsd-ui-phase/SKILL.md +6 -1
- package/skills/gsd-ui-review/SKILL.md +6 -1
- package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
- package/skills/gsd-undo/SKILL.md +5 -1
- package/skills/gsd-update/SKILL.md +6 -2
- package/skills/gsd-validate-phase/SKILL.md +6 -1
- package/skills/gsd-verify-work/SKILL.md +6 -1
- package/skills/gsd-workspace/SKILL.md +7 -3
- package/skills/gsd-workstreams/SKILL.md +6 -6
- package/vscode/package.json +1 -1
- package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +0 -24
|
@@ -61,7 +61,13 @@
|
|
|
61
61
|
// segment's operands — `[ -f .env ]` and `ls .env*` are existence checks
|
|
62
62
|
// GSD's own agents run — while `cp`/`mv`/`ln`/`git` are deliberately NOT
|
|
63
63
|
// exempt (`cp .env x && cat x` launders the name; `git show HEAD:.env`
|
|
64
|
-
// reads).
|
|
64
|
+
// reads). Narrower carve-outs exempt single operand POSITIONS that are
|
|
65
|
+
// names, never contents, and keep checking the rest of the segment: the
|
|
66
|
+
// `--env-file` value under a container runtime (#4639), the pathspecs of
|
|
67
|
+
// `git check-ignore` / `git ls-files` / `git rm --cached`, and the
|
|
68
|
+
// destination of a one-source `cp`/`mv` (#4856). The #4856 carve-outs
|
|
69
|
+
// fail closed: an option they do not list withdraws them from the segment.
|
|
70
|
+
// A shell interpreter (bash/sh/zsh/dash/ksh/su) has its script scanned
|
|
65
71
|
// whether it arrives via `-c '…'`, a `<( )` file operand, a heredoc /
|
|
66
72
|
// here-string, or a pipe from a knowable `echo`/`printf` source
|
|
67
73
|
// (`echo cat .env | bash`); `eval` scans its joined operands; `source`/`.`
|
|
@@ -91,7 +97,11 @@
|
|
|
91
97
|
// container's own command can print the interpolated environment
|
|
92
98
|
// (`alpine printenv`, `docker compose config`) — the same exposure class
|
|
93
99
|
// as the pre-existing volume-mount gap (`-v .env:/s`); the flag's value
|
|
94
|
-
// itself is a name, never contents.
|
|
100
|
+
// itself is a name, never contents. #4856 adds another: the `cp`/`mv`
|
|
101
|
+
// destination exemption can move a link prepared under a non-secret name
|
|
102
|
+
// onto a secret name (`ln -s .env.example l && mv l .env`), so a later
|
|
103
|
+
// edit of `.env` lands in the link target — a write redirection, the
|
|
104
|
+
// out-of-scope write class, not a read.)
|
|
95
105
|
//
|
|
96
106
|
// Triggers on: Read, Grep, Bash tool calls (Kimi: ReadFile, Grep, Shell)
|
|
97
107
|
// Action: BLOCK (decision: 'block', exit 2) — codes secret-read |
|
|
@@ -141,6 +151,57 @@ const NON_READING_COMMANDS = new Set([
|
|
|
141
151
|
const CONTAINER_RUNTIMES = new Set(['docker', 'docker-compose', 'podman', 'nerdctl']);
|
|
142
152
|
const ENV_FILE_FLAG_RE = /^--env-file(=|$)/;
|
|
143
153
|
|
|
154
|
+
// #4856: git subcommands that report or drop a path's ignore / tracking
|
|
155
|
+
// status and never print the file, so their pathspec operands are names —
|
|
156
|
+
// the category NON_READING_COMMANDS encodes. Each carries the closed set of
|
|
157
|
+
// its NO-VALUE options (from `git <subcommand> -h`, git 2.49). Any other
|
|
158
|
+
// option withdraws the exemption from the whole segment, so an option value
|
|
159
|
+
// is never mistaken for a pathspec: `-X <file>` reads the file, and
|
|
160
|
+
// `--pathspec-from-file=<file>` echoes its lines in the "did not match"
|
|
161
|
+
// error. `requires` names the option without which the subcommand stays
|
|
162
|
+
// checked (#4856 scopes `git rm` to `--cached`).
|
|
163
|
+
const GIT_PATHSPEC_SUBCOMMANDS = new Map([
|
|
164
|
+
['check-ignore', {
|
|
165
|
+
flags: new Set(['-q', '--quiet', '-v', '--verbose', '--stdin', '-z', '-n', '--non-matching', '--no-index', '--index']),
|
|
166
|
+
}],
|
|
167
|
+
['ls-files', {
|
|
168
|
+
flags: new Set([
|
|
169
|
+
'-z', '-t', '-v', '-f', '-c', '--cached', '-d', '--deleted', '-m', '--modified', '-o', '--others',
|
|
170
|
+
'-i', '--ignored', '-s', '--stage', '-k', '--killed', '-u', '--unmerged', '--directory', '--eol',
|
|
171
|
+
'--no-empty-directory', '--resolve-undo', '--exclude-standard', '--full-name',
|
|
172
|
+
'--recurse-submodules', '--error-unmatch', '--abbrev', '--debug', '--deduplicate', '--sparse',
|
|
173
|
+
]),
|
|
174
|
+
}],
|
|
175
|
+
['rm', {
|
|
176
|
+
flags: new Set(['--cached', '-f', '--force', '-n', '--dry-run', '-q', '--quiet', '-r', '--ignore-unmatch', '--sparse']),
|
|
177
|
+
requires: '--cached',
|
|
178
|
+
}],
|
|
179
|
+
]);
|
|
180
|
+
|
|
181
|
+
// git's global options (its own usage line, git 2.49), needed to locate the
|
|
182
|
+
// subcommand. A value option consumes the next word unless written
|
|
183
|
+
// `--opt=value`; an option in neither set fails closed, so a value is never
|
|
184
|
+
// read as the subcommand (`git -C ls-files show HEAD:.env` runs `show`).
|
|
185
|
+
const GIT_GLOBAL_VALUE_OPTIONS = new Set(['-C', '-c', '--git-dir', '--work-tree', '--namespace', '--config-env']);
|
|
186
|
+
const GIT_GLOBAL_FLAGS = new Set([
|
|
187
|
+
'-p', '--paginate', '-P', '--no-pager', '--no-replace-objects', '--no-lazy-fetch',
|
|
188
|
+
'--no-optional-locks', '--no-advice', '--bare',
|
|
189
|
+
]);
|
|
190
|
+
|
|
191
|
+
// #4856: `cp`/`mv` write their destination and never print it, so a secret
|
|
192
|
+
// name that is ONLY the destination of a one-source copy or move is a name
|
|
193
|
+
// (`cp .env.example .env`). The exemption holds for exactly two operands
|
|
194
|
+
// behind options from this closed set; anything else keeps the whole segment
|
|
195
|
+
// checked — `-t`/`--target-directory` (every operand becomes a source), a
|
|
196
|
+
// backup (`-b`, `--backup`, `-S`: the old secret survives as `.env~`, a name
|
|
197
|
+
// the predicate does not classify), a link (`-l`, `-s`) or `--exchange`
|
|
198
|
+
// (the destination shares or swaps the secret). Options must precede the
|
|
199
|
+
// operands: a trailing one is an option under GNU getopt's permutation but
|
|
200
|
+
// an operand under POSIXLY_CORRECT (`cp a .env -f` then copies `.env` INTO
|
|
201
|
+
// `-f/`), so which word is the destination would hang on an environment
|
|
202
|
+
// the hook cannot see.
|
|
203
|
+
const COPY_NAME_ONLY_FLAGS = new Set(['-f', '--force', '-i', '--interactive', '-n', '--no-clobber', '-v', '--verbose']);
|
|
204
|
+
|
|
144
205
|
// Shell interpreters that run a script from `-c`, a file operand, or stdin
|
|
145
206
|
// (heredoc / here-string / piped `echo`|`printf`). `su` is here for its `-c`
|
|
146
207
|
// form (`su [user] -c 'cmd'`); a bare `su user` resolves to file mode, which
|
|
@@ -714,6 +775,86 @@ function resolveCommand(words) {
|
|
|
714
775
|
return { base: lastSegment(words[idx].text).toLowerCase(), operands: words.slice(idx + 1) };
|
|
715
776
|
}
|
|
716
777
|
|
|
778
|
+
// Operand indices the segment's command consumes as a NAME, never as
|
|
779
|
+
// CONTENTS (#4639, #4856). Only these positions skip the operand check;
|
|
780
|
+
// every other operand is still checked, so a carve-out cannot launder a read
|
|
781
|
+
// elsewhere in the segment.
|
|
782
|
+
function nameOnlyOperandIndices(base, operands) {
|
|
783
|
+
if (CONTAINER_RUNTIMES.has(base)) return envFileValueIndices(operands);
|
|
784
|
+
if (base === 'git') return gitPathspecIndices(operands);
|
|
785
|
+
if (base === 'cp' || base === 'mv') return copyDestinationIndices(operands);
|
|
786
|
+
return new Set();
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// #4639: the `--env-file` word, plus the next operand for the bare flag
|
|
790
|
+
// (`--env-file=<value>` is a single word).
|
|
791
|
+
function envFileValueIndices(operands) {
|
|
792
|
+
const exempt = new Set();
|
|
793
|
+
for (let k = 0; k < operands.length; k++) {
|
|
794
|
+
if (!ENV_FILE_FLAG_RE.test(operands[k].text)) continue;
|
|
795
|
+
exempt.add(k);
|
|
796
|
+
if (!operands[k].text.includes('=')) exempt.add(++k);
|
|
797
|
+
}
|
|
798
|
+
return exempt;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// True when `text` is a listed long option, or a short cluster (`-co`) whose
|
|
802
|
+
// every letter is listed. `--opt=value`, an abbreviation, or a cluster
|
|
803
|
+
// holding a value option (`-ciX`) is not.
|
|
804
|
+
function isListedFlag(text, flags) {
|
|
805
|
+
if (text.startsWith('--')) return flags.has(text);
|
|
806
|
+
return /^-[A-Za-z]+$/.test(text) && [...text.slice(1)].every((ch) => flags.has(`-${ch}`));
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// Index of git's subcommand past its global options, or -1 when an option
|
|
810
|
+
// outside GIT_GLOBAL_VALUE_OPTIONS / GIT_GLOBAL_FLAGS precedes it.
|
|
811
|
+
function gitSubcommandIndex(operands) {
|
|
812
|
+
for (let k = 0; k < operands.length; k++) {
|
|
813
|
+
const t = operands[k].text;
|
|
814
|
+
if (!t.startsWith('-')) return k;
|
|
815
|
+
if (GIT_GLOBAL_VALUE_OPTIONS.has(t)) { k++; continue; }
|
|
816
|
+
if (GIT_GLOBAL_FLAGS.has(t)) continue;
|
|
817
|
+
const eq = t.indexOf('=');
|
|
818
|
+
const isLongValueForm = t.startsWith('--') && eq !== -1 && GIT_GLOBAL_VALUE_OPTIONS.has(t.slice(0, eq));
|
|
819
|
+
if (!isLongValueForm) return -1;
|
|
820
|
+
}
|
|
821
|
+
return -1;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// #4856: the pathspec operands of a GIT_PATHSPEC_SUBCOMMANDS invocation. git
|
|
825
|
+
// permutes options, so one may follow a pathspec; after `--` every word is a
|
|
826
|
+
// pathspec. The subcommand is matched case-sensitively, as git looks it up.
|
|
827
|
+
function gitPathspecIndices(operands) {
|
|
828
|
+
const sub = gitSubcommandIndex(operands);
|
|
829
|
+
const spec = sub === -1 ? undefined : GIT_PATHSPEC_SUBCOMMANDS.get(operands[sub].text);
|
|
830
|
+
if (!spec) return new Set();
|
|
831
|
+
const pathspecs = new Set();
|
|
832
|
+
let required = spec.requires === undefined;
|
|
833
|
+
let endOfOptions = false;
|
|
834
|
+
for (let k = sub + 1; k < operands.length; k++) {
|
|
835
|
+
const t = operands[k].text;
|
|
836
|
+
if (endOfOptions || !t.startsWith('-') || t === '-') pathspecs.add(k);
|
|
837
|
+
else if (t === '--') endOfOptions = true;
|
|
838
|
+
else if (!isListedFlag(t, spec.flags)) return new Set();
|
|
839
|
+
else if (t === spec.requires) required = true;
|
|
840
|
+
}
|
|
841
|
+
return required ? pathspecs : new Set();
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// #4856: the destination of a one-source `cp`/`mv` (see COPY_NAME_ONLY_FLAGS).
|
|
845
|
+
function copyDestinationIndices(operands) {
|
|
846
|
+
const positional = [];
|
|
847
|
+
let endOfOptions = false;
|
|
848
|
+
for (let k = 0; k < operands.length; k++) {
|
|
849
|
+
const t = operands[k].text;
|
|
850
|
+
if (endOfOptions || !t.startsWith('-') || t === '-') positional.push(k);
|
|
851
|
+
else if (positional.length) return new Set(); // an option or `--` after an operand
|
|
852
|
+
else if (t === '--') endOfOptions = true;
|
|
853
|
+
else if (!isListedFlag(t, COPY_NAME_ONLY_FLAGS)) return new Set();
|
|
854
|
+
}
|
|
855
|
+
return positional.length === 2 ? new Set([positional[1]]) : new Set();
|
|
856
|
+
}
|
|
857
|
+
|
|
717
858
|
// The statically-knowable stdin a segment writes: `echo`/`printf` operands
|
|
718
859
|
// joined by a space (for `echo`, leading `-neE` flags dropped). Any other
|
|
719
860
|
// source (`cat gen.sh | bash`, `curl … | sh`) is not knowable → null.
|
|
@@ -854,20 +995,10 @@ function findSecretRead(command, depth) {
|
|
|
854
995
|
|
|
855
996
|
if (NON_READING_COMMANDS.has(base)) continue;
|
|
856
997
|
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
let skipNext = false;
|
|
862
|
-
for (const w of operands) {
|
|
863
|
-
if (envFileExempt) {
|
|
864
|
-
if (skipNext) { skipNext = false; continue; }
|
|
865
|
-
if (ENV_FILE_FLAG_RE.test(w.text)) {
|
|
866
|
-
if (!w.text.includes('=')) skipNext = true; // bare flag consumes the next operand
|
|
867
|
-
continue;
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
if (namesSecret(normalizeOperand(w.text))) return w.text;
|
|
998
|
+
const nameOnly = nameOnlyOperandIndices(base, operands);
|
|
999
|
+
for (let k = 0; k < operands.length; k++) {
|
|
1000
|
+
if (nameOnly.has(k)) continue;
|
|
1001
|
+
if (namesSecret(normalizeOperand(operands[k].text))) return operands[k].text;
|
|
871
1002
|
}
|
|
872
1003
|
}
|
|
873
1004
|
return null;
|
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
// Claude Code Statusline - GSD Edition
|
|
4
4
|
// Shows: model | current task (or GSD state) | directory | context usage
|
|
5
5
|
|
|
6
|
+
// #5183: Node's on-disk compile cache, so later runs reuse V8's compiled code
|
|
7
|
+
// for unchanged modules. Only as the entry (a test require() is unaffected),
|
|
8
|
+
// skipped under V8 coverage, optional (Bun stubs it), and never fatal.
|
|
9
|
+
// NODE_DISABLE_COMPILE_CACHE (any value) turns it off.
|
|
10
|
+
if (require.main === module && !process.env.NODE_V8_COVERAGE) {
|
|
11
|
+
try { require('node:module').enableCompileCache?.(); } catch { /* optimization only */ }
|
|
12
|
+
}
|
|
13
|
+
|
|
6
14
|
const fs = require('fs');
|
|
7
15
|
const path = require('path');
|
|
8
16
|
const os = require('os');
|
|
@@ -42,6 +50,7 @@ if (require.main === module) {
|
|
|
42
50
|
const { isSemverNewer } = require('../gsd-core/bin/lib/semver-compare.cjs');
|
|
43
51
|
const { PACKAGE_NAME, updateCacheFileName } = require('../gsd-core/bin/lib/package-identity.cjs');
|
|
44
52
|
const { normalizeStateStatus } = require('../gsd-core/bin/lib/state-document.cjs');
|
|
53
|
+
const { locateFrontmatterFence } = require('../gsd-core/bin/lib/frontmatter-fence.cjs');
|
|
45
54
|
const {
|
|
46
55
|
renderBracketPhaseDisplay,
|
|
47
56
|
renderBracketMilestoneDisplay,
|
|
@@ -250,13 +259,12 @@ function readGsdState(dir, opts = {}) {
|
|
|
250
259
|
function parseStateMd(content) {
|
|
251
260
|
const state = {};
|
|
252
261
|
|
|
253
|
-
// YAML frontmatter
|
|
254
|
-
// #2754
|
|
255
|
-
//
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const fm = fmMatch[1];
|
|
262
|
+
// YAML frontmatter: the block the one fence owner finds (`locateFrontmatterFence`), so a
|
|
263
|
+
// CRLF STATE.md (#2754), a BOM, and a `---` inside a value read exactly as every other
|
|
264
|
+
// STATE.md reader reads them (found while implementing #5105).
|
|
265
|
+
const fence = locateFrontmatterFence(content);
|
|
266
|
+
if (fence && fence.closed) {
|
|
267
|
+
const fm = content.slice(fence.openEnd, fence.bodyEnd);
|
|
260
268
|
// Top-level scalar key: value
|
|
261
269
|
for (const line of fm.split(/\r?\n/)) {
|
|
262
270
|
const m = line.match(/^(\w+):\s*(.+)/);
|
|
@@ -12,6 +12,14 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
+
// #5183: Node's on-disk compile cache, so later runs reuse V8's compiled code
|
|
16
|
+
// for unchanged modules. Only as the entry (a test require() is unaffected),
|
|
17
|
+
// skipped under V8 coverage, optional (Bun stubs it), and never fatal.
|
|
18
|
+
// NODE_DISABLE_COMPILE_CACHE (any value) turns it off.
|
|
19
|
+
if (require.main === module && !process.env.NODE_V8_COVERAGE) {
|
|
20
|
+
try { require('node:module').enableCompileCache?.(); } catch { /* optimization only */ }
|
|
21
|
+
}
|
|
22
|
+
|
|
15
23
|
const fs = require('fs');
|
|
16
24
|
const path = require('path');
|
|
17
25
|
const os = require('os');
|
|
@@ -31,14 +31,23 @@ const fs = require('fs');
|
|
|
31
31
|
const path = require('path');
|
|
32
32
|
const { spawnSync } = require('child_process');
|
|
33
33
|
const { allow, deny } = require('./lib/hook-exit.js');
|
|
34
|
-
const { reportIfUndetermined } = require('./lib/git-probe.js');
|
|
34
|
+
const { reportIfUndetermined, BLOCKING_GUARD_PROBE_TIMEOUT_MS } = require('./lib/git-probe.js');
|
|
35
35
|
|
|
36
36
|
// #3911 (ADR-3889 Phase 7): the exit(2) call site (block(), below) is
|
|
37
37
|
// migrated to hook-exit.js's deny(undefined, reason) — see
|
|
38
38
|
// gsd-windsurf-pre-command.js's identical note for the fixed defect
|
|
39
39
|
// (terminateNow's fd 1/fd 2 writes now run in independent try/catch blocks).
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
// Shared blocking-guard probe budget (hooks/lib/git-probe.js, #5180): a timed-out
|
|
42
|
+
// probe fails open, so it is sized for a starved host. Windsurf documents NO
|
|
43
|
+
// hook timeout (docs.devin.ai/desktop/cascade/hooks lists only an aspirational
|
|
44
|
+
// "sub-100ms" target) and this surface's registration entry
|
|
45
|
+
// (buildWindsurfHookEntry in src/runtime-hooks-surface.cts) carries none, so the
|
|
46
|
+
// host budget is UNKNOWN. This guard runs at most 3 sequential probes (15 s
|
|
47
|
+
// worst case); that worst case is NOT claimed to fit any host budget — if
|
|
48
|
+
// Windsurf kills the hook sooner, the host kill fails open exactly as a probe
|
|
49
|
+
// timeout does. The guard keeps its fail-open posture either way.
|
|
50
|
+
const SPAWNOPT = { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], timeout: BLOCKING_GUARD_PROBE_TIMEOUT_MS, windowsHide: true };
|
|
42
51
|
|
|
43
52
|
function git(args, cwd) {
|
|
44
53
|
return spawnSync('git', args, { ...SPAWNOPT, cwd });
|
|
@@ -22,7 +22,7 @@ const path = require('path');
|
|
|
22
22
|
const { spawnSync } = require('child_process');
|
|
23
23
|
const { tokenize, skipToSubcommand } = require('./lib/git-cmd.js');
|
|
24
24
|
const { HOOK_ON_CRASH, allow, deny, crash } = require('./lib/hook-exit.js');
|
|
25
|
-
const { reportIfUndetermined } = require('./lib/git-probe.js');
|
|
25
|
+
const { reportIfUndetermined, BLOCKING_GUARD_PROBE_TIMEOUT_MS } = require('./lib/git-probe.js');
|
|
26
26
|
|
|
27
27
|
// This guard is almost entirely advisory (fail open — a broken advisory must
|
|
28
28
|
// never wedge every tool call), with ONE hard block (#3504 force-add-on-
|
|
@@ -87,11 +87,12 @@ function currentBranch(cwd) {
|
|
|
87
87
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
88
88
|
windowsHide: true,
|
|
89
89
|
// #3504: bounded — this ran unbounded before, an indefinite hang under a
|
|
90
|
-
// wedged git would hang every PreToolUse call.
|
|
91
|
-
// budget
|
|
90
|
+
// wedged git would hang every PreToolUse call. The probe gets the shared
|
|
91
|
+
// blocking-guard budget (hooks/lib/git-probe.js, #5180), well inside the
|
|
92
|
+
// 120s host budget this guard is registered with (#3981); a timeout
|
|
92
93
|
// returns '' (branch unknown), which both the block decision and the
|
|
93
94
|
// fail-closed re-check treat as "cannot establish agent branch".
|
|
94
|
-
timeout:
|
|
95
|
+
timeout: BLOCKING_GUARD_PROBE_TIMEOUT_MS,
|
|
95
96
|
killSignal: 'SIGTERM',
|
|
96
97
|
});
|
|
97
98
|
// #3911: a timeout/spawn-failure here previously degraded to '' exactly
|
|
@@ -18,7 +18,7 @@ const fs = require('fs');
|
|
|
18
18
|
const path = require('path');
|
|
19
19
|
const { spawnSync } = require('child_process');
|
|
20
20
|
const { HOOK_ON_CRASH, allow, deny, crash } = require('./lib/hook-exit.js');
|
|
21
|
-
const { reportIfUndetermined } = require('./lib/git-probe.js');
|
|
21
|
+
const { reportIfUndetermined, BLOCKING_GUARD_PROBE_TIMEOUT_MS } = require('./lib/git-probe.js');
|
|
22
22
|
|
|
23
23
|
// This guard's outer catch has always exited 0 (fail open): a path guard that
|
|
24
24
|
// cannot resolve the worktree must not block the user's edit — its whole job
|
|
@@ -28,7 +28,11 @@ const { reportIfUndetermined } = require('./lib/git-probe.js');
|
|
|
28
28
|
// rather than inheriting a default (#3911).
|
|
29
29
|
const ON_CRASH = HOOK_ON_CRASH.ALLOW;
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
// A timed-out git probe fails OPEN (see ON_CRASH above), so the per-probe
|
|
32
|
+
// budget is the shared blocking-guard value, sized for a starved host rather
|
|
33
|
+
// than git's ~0.1s typical run (rationale and arithmetic in
|
|
34
|
+
// hooks/lib/git-probe.js, #5180). This guard runs at most 3 sequential probes.
|
|
35
|
+
const SPAWNOPT = { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], timeout: BLOCKING_GUARD_PROBE_TIMEOUT_MS, windowsHide: true };
|
|
32
36
|
|
|
33
37
|
function git(args, cwd) {
|
|
34
38
|
return spawnSync('git', args, { ...SPAWNOPT, cwd });
|
|
@@ -185,6 +185,17 @@ function setPendingOutcome(v) {
|
|
|
185
185
|
function getPendingOutcome() {
|
|
186
186
|
return globalThis[PENDING_OUTCOME_KEY];
|
|
187
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Declare the outcome a void-returning `main()` ends with (#5170, ADR-5057 §4): writes the
|
|
190
|
+
* pending-outcome cell that `runMain` projects. Validates `name` is an outcome
|
|
191
|
+
* `projectOutcome` accepts (PASS, FAIL or a registered name) and THROWS otherwise, so a typo'd
|
|
192
|
+
* name fails at the declaration rather than at process exit. Call it AFTER `output()`, which
|
|
193
|
+
* rewrites the cell on every call. `output()` and this are the only writers of the cell.
|
|
194
|
+
*/
|
|
195
|
+
function declareOutcome(name) {
|
|
196
|
+
projectOutcome(name, 'v1');
|
|
197
|
+
setPendingOutcome(name);
|
|
198
|
+
}
|
|
188
199
|
const EXIT_CONTRACT_FLAG_PREFIX = '--exit-contract=';
|
|
189
200
|
/** Scan argv for the FIRST `--exit-contract=<value>` token; undefined if absent. */
|
|
190
201
|
function findExitContractFlag(argv) {
|
|
@@ -557,4 +568,5 @@ module.exports = {
|
|
|
557
568
|
terminateNow,
|
|
558
569
|
setPendingOutcome,
|
|
559
570
|
getPendingOutcome,
|
|
571
|
+
declareOutcome,
|
|
560
572
|
};
|
|
@@ -81,4 +81,20 @@ function reportIfUndetermined(hookName, probeLabel, result) {
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
// Per-probe budget for the git probes of BLOCKING guards. A probe that times
|
|
85
|
+
// out fails OPEN (see reportIfUndetermined above), which is the same outcome
|
|
86
|
+
// as the host killing the hook — so a budget sized to git's ~0.1s typical run
|
|
87
|
+
// silently disables the gate on a starved host (a 2000ms budget was exceeded
|
|
88
|
+
// on a loaded Windows runner, #5180). Worst case for a guard that runs up to
|
|
89
|
+
// BLOCKING_GUARD_MAX_SEQUENTIAL_PROBES sequential probes:
|
|
90
|
+
// 3 x 5000ms + ~500ms node start/kill/reap = ~15.5s,
|
|
91
|
+
// inside the 120s host budget blocking guards are registered with (#3981).
|
|
92
|
+
const BLOCKING_GUARD_PROBE_TIMEOUT_MS = 5000;
|
|
93
|
+
const BLOCKING_GUARD_MAX_SEQUENTIAL_PROBES = 3;
|
|
94
|
+
|
|
95
|
+
module.exports = {
|
|
96
|
+
classifyGitProbe,
|
|
97
|
+
reportIfUndetermined,
|
|
98
|
+
BLOCKING_GUARD_PROBE_TIMEOUT_MS,
|
|
99
|
+
BLOCKING_GUARD_MAX_SEQUENTIAL_PROBES,
|
|
100
|
+
};
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
// explicit fallback for the per-plan submodule-degrade override and shares
|
|
24
24
|
// the exact same atomic-write implementation.
|
|
25
25
|
//
|
|
26
|
-
// Sentinel path: `<cwd>/.gsd/dispatch-isolation-sentinel.json`.
|
|
27
|
-
//
|
|
26
|
+
// Sentinel path: `<cwd>/.gsd/dispatch-isolation-sentinel.json`. The writer
|
|
27
|
+
// seeds `.gsd/.gitignore` so this stays ignored in user projects too,
|
|
28
28
|
// and lives inside the checkout that ran the workflow — concurrent worktrees
|
|
29
29
|
// of the same repo are separate directories on disk, so each gets its own
|
|
30
30
|
// sentinel with no cross-worktree collision, no lock file needed.
|
|
@@ -60,6 +60,14 @@
|
|
|
60
60
|
|
|
61
61
|
'use strict';
|
|
62
62
|
|
|
63
|
+
// #5183: Node's on-disk compile cache, so later runs reuse V8's compiled code
|
|
64
|
+
// for unchanged modules. Only as the entry (a test require() is unaffected),
|
|
65
|
+
// skipped under V8 coverage, optional (Bun stubs it), and never fatal.
|
|
66
|
+
// NODE_DISABLE_COMPILE_CACHE (any value) turns it off.
|
|
67
|
+
if (require.main === module && !process.env.NODE_V8_COVERAGE) {
|
|
68
|
+
try { require('node:module').enableCompileCache?.(); } catch { /* optimization only */ }
|
|
69
|
+
}
|
|
70
|
+
|
|
63
71
|
const fs = require('fs');
|
|
64
72
|
const path = require('path');
|
|
65
73
|
const os = require('os');
|
|
@@ -9,6 +9,14 @@
|
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
11
11
|
|
|
12
|
+
// #5183: Node's on-disk compile cache, so later runs reuse V8's compiled code
|
|
13
|
+
// for unchanged modules. Only as the entry (a test require() is unaffected),
|
|
14
|
+
// skipped under V8 coverage, optional (Bun stubs it), and never fatal.
|
|
15
|
+
// NODE_DISABLE_COMPILE_CACHE (any value) turns it off.
|
|
16
|
+
if (require.main === module && !process.env.NODE_V8_COVERAGE) {
|
|
17
|
+
try { require('node:module').enableCompileCache?.(); } catch { /* optimization only */ }
|
|
18
|
+
}
|
|
19
|
+
|
|
12
20
|
const fs = require('fs');
|
|
13
21
|
const path = require('path');
|
|
14
22
|
|
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
// Check for GSD updates in background, write result to cache
|
|
4
4
|
// Called by SessionStart hook - runs once per session
|
|
5
5
|
|
|
6
|
+
// #5183: Node's on-disk compile cache, so later runs reuse V8's compiled code
|
|
7
|
+
// for unchanged modules. Only as the entry (a test require() is unaffected),
|
|
8
|
+
// skipped under V8 coverage, optional (Bun stubs it), and never fatal.
|
|
9
|
+
// NODE_DISABLE_COMPILE_CACHE (any value) turns it off.
|
|
10
|
+
if (require.main === module && !process.env.NODE_V8_COVERAGE) {
|
|
11
|
+
try { require('node:module').enableCompileCache?.(); } catch { /* optimization only */ }
|
|
12
|
+
}
|
|
13
|
+
|
|
6
14
|
const fs = require('fs');
|
|
7
15
|
const path = require('path');
|
|
8
16
|
const os = require('os');
|
|
@@ -201,6 +201,29 @@ function writeSentinel(target, payload) {
|
|
|
201
201
|
} catch (e) { /* best effort — see above */ }
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
+
// The calendar day the CRITICAL auto-record writes into STATE.md (#4905): the
|
|
205
|
+
// operator's LOCAL day through the clock seam, which honors GSD_NOW_MS under
|
|
206
|
+
// GSD_TEST_MODE, like every other date GSD stamps into planning files. The
|
|
207
|
+
// clock is compiled into gsd-core/bin/lib/, so it is reached through the
|
|
208
|
+
// self-healing build seam (#3582). If the library is missing and cannot
|
|
209
|
+
// self-build, the host's local day stands in — still never the UTC day.
|
|
210
|
+
function localDayStamp() {
|
|
211
|
+
try {
|
|
212
|
+
const { ensureRuntimeBuild } = require('../gsd-core/bin/ensure-runtime-build.cjs');
|
|
213
|
+
ensureRuntimeBuild();
|
|
214
|
+
return require('../gsd-core/bin/lib/clock.cjs').realClock.localToday();
|
|
215
|
+
} catch {
|
|
216
|
+
const now = new Date();
|
|
217
|
+
return [now.getFullYear(), String(now.getMonth() + 1).padStart(2, '0'), String(now.getDate()).padStart(2, '0')].join('-');
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// The Stopped At breadcrumb for /gsd:resume-work (#1974). usedPct is coerced to
|
|
222
|
+
// a safe number in case the bridge file is malformed.
|
|
223
|
+
function criticalStoppedAt(usedPct) {
|
|
224
|
+
return `context exhaustion at ${Number(usedPct) || 0}% (${localDayStamp()})`;
|
|
225
|
+
}
|
|
226
|
+
|
|
204
227
|
let input = '';
|
|
205
228
|
// Assigned by main(); the handler below clears it. Declared out here rather
|
|
206
229
|
// than inside main() because the handler closes over it.
|
|
@@ -464,9 +487,7 @@ const handleStdinEnd = () => {
|
|
|
464
487
|
// Using __dirname makes this work on Claude Code, OpenCode, Gemini,
|
|
465
488
|
// Kilo, etc. without hardcoding ~/.claude/.
|
|
466
489
|
const gsdTools = path.join(__dirname, '..', 'gsd-core', 'bin', 'gsd-tools.cjs');
|
|
467
|
-
|
|
468
|
-
const safeUsedPct = Number(usedPct) || 0;
|
|
469
|
-
const stoppedAt = `context exhaustion at ${safeUsedPct}% (${new Date().toISOString().split('T')[0]})`;
|
|
490
|
+
const stoppedAt = criticalStoppedAt(usedPct);
|
|
470
491
|
spawn(
|
|
471
492
|
process.execPath,
|
|
472
493
|
[gsdTools, 'state', 'record-session', '--stopped-at', stoppedAt],
|
|
@@ -560,8 +581,10 @@ if (require.main === module) {
|
|
|
560
581
|
main();
|
|
561
582
|
}
|
|
562
583
|
|
|
563
|
-
// Exported for
|
|
564
|
-
// test
|
|
565
|
-
// re-hardcoding 35/25 — a test
|
|
566
|
-
// green if the constants were
|
|
567
|
-
|
|
584
|
+
// Exported for tests only. resolveThresholds and the two constants serve the
|
|
585
|
+
// #4285 property test; the constants ride along so a test asserts the fallback
|
|
586
|
+
// pair against the SOURCE of truth rather than re-hardcoding 35/25 — a test
|
|
587
|
+
// carrying its own copy of the defaults would stay green if the constants were
|
|
588
|
+
// edited. criticalStoppedAt lets the #4905 test pin the breadcrumb's day
|
|
589
|
+
// without waiting on the detached record-session writer (#3726).
|
|
590
|
+
module.exports = { resolveThresholds, WARNING_THRESHOLD, CRITICAL_THRESHOLD, criticalStoppedAt };
|
|
@@ -53,6 +53,14 @@
|
|
|
53
53
|
|
|
54
54
|
'use strict';
|
|
55
55
|
|
|
56
|
+
// #5183: Node's on-disk compile cache, so later runs reuse V8's compiled code
|
|
57
|
+
// for unchanged modules. Only as the entry (a test require() is unaffected),
|
|
58
|
+
// skipped under V8 coverage, optional (Bun stubs it), and never fatal.
|
|
59
|
+
// NODE_DISABLE_COMPILE_CACHE (any value) turns it off.
|
|
60
|
+
if (require.main === module && !process.env.NODE_V8_COVERAGE) {
|
|
61
|
+
try { require('node:module').enableCompileCache?.(); } catch { /* optimization only */ }
|
|
62
|
+
}
|
|
63
|
+
|
|
56
64
|
const fs = require('fs');
|
|
57
65
|
const path = require('path');
|
|
58
66
|
const os = require('os');
|