@opengsd/gsd-core 1.11.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-debug-session-manager.md +1 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-dom-verifier.md +169 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +17 -9
- package/agents/gsd-framework-selector.md +1 -3
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +0 -1
- package/agents/gsd-pattern-mapper.md +11 -0
- package/agents/gsd-phase-researcher.md +3 -1
- package/agents/gsd-plan-checker.md +15 -55
- package/agents/gsd-planner.md +6 -4
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.md +2 -2
- package/agents/gsd-roadmapper.md +15 -11
- package/agents/gsd-ui-checker.md +63 -4
- package/agents/gsd-ui-researcher.md +41 -3
- package/agents/gsd-verifier.md +1 -1
- package/bin/install.js +609 -134
- package/commands/gsd/discuss-phase.md +1 -1
- package/commands/gsd/import.md +1 -1
- package/commands/gsd/quick.md +8 -4
- package/gsd-core/bin/gsd-tools.cjs +567 -51
- package/gsd-core/bin/lib/active-workstream-store.cjs +8 -0
- package/gsd-core/bin/lib/adr-parser.cjs +13 -7
- package/gsd-core/bin/lib/agent-install-check.cjs +162 -0
- package/gsd-core/bin/lib/api-coverage.cjs +30 -9
- package/gsd-core/bin/lib/artifacts.cjs +2 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +30 -11
- package/gsd-core/bin/lib/audit.cjs +163 -41
- package/gsd-core/bin/lib/broken-windows.cjs +306 -28
- package/gsd-core/bin/lib/capability-lock.cjs +10 -4
- package/gsd-core/bin/lib/capability-registry.cjs +336 -95
- package/gsd-core/bin/lib/capability-state.cjs +18 -3
- package/gsd-core/bin/lib/capability-validator.cjs +205 -18
- package/gsd-core/bin/lib/check-command-router.cjs +145 -5
- package/gsd-core/bin/lib/cli-exit.cjs +496 -10
- package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +410 -4
- package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
- package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
- package/gsd-core/bin/lib/commands.cjs +543 -44
- package/gsd-core/bin/lib/complexity-trigger.cjs +26 -6
- package/gsd-core/bin/lib/config-loader.cjs +118 -29
- package/gsd-core/bin/lib/config.cjs +92 -2
- package/gsd-core/bin/lib/configuration.cjs +129 -37
- package/gsd-core/bin/lib/core-utils.cjs +84 -7
- package/gsd-core/bin/lib/edge-probe.cjs +9 -1
- package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
- package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
- package/gsd-core/bin/lib/frontmatter.cjs +840 -305
- package/gsd-core/bin/lib/gap-checker.cjs +27 -3
- package/gsd-core/bin/lib/git-base-branch.cjs +174 -39
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +7 -3
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +6 -3
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +22 -8
- package/gsd-core/bin/lib/health-diagnostic.cjs +23 -3
- package/gsd-core/bin/lib/host-integration.cjs +39 -6
- package/gsd-core/bin/lib/init-command-router.cjs +118 -21
- package/gsd-core/bin/lib/init.cjs +120 -41
- package/gsd-core/bin/lib/install-engine.cjs +68 -3
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +33 -1
- package/gsd-core/bin/lib/install-profiles.cjs +78 -4
- package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
- package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +10 -7
- package/gsd-core/bin/lib/intel.cjs +101 -26
- package/gsd-core/bin/lib/io.cjs +160 -15
- package/gsd-core/bin/lib/learnings.cjs +85 -14
- package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
- package/gsd-core/bin/lib/markdown-table.cjs +52 -4
- package/gsd-core/bin/lib/milestone.cjs +90 -5
- package/gsd-core/bin/lib/model-catalog.cjs +177 -19
- package/gsd-core/bin/lib/model-resolver.cjs +10 -28
- package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
- package/gsd-core/bin/lib/phase-estimation.cjs +17 -8
- package/gsd-core/bin/lib/phase-id.cjs +70 -4
- package/gsd-core/bin/lib/phase-lifecycle.cjs +24 -16
- package/gsd-core/bin/lib/phase-locator.cjs +138 -17
- package/gsd-core/bin/lib/phase.cjs +405 -84
- package/gsd-core/bin/lib/plan-document.cjs +263 -0
- package/gsd-core/bin/lib/plan-scan.cjs +13 -2
- package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +18 -14
- package/gsd-core/bin/lib/planning-workspace.cjs +56 -0
- package/gsd-core/bin/lib/probe-core.cjs +4 -1
- package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
- package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
- package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +71 -45
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +9 -9
- package/gsd-core/bin/lib/roadmap-command-router.cjs +45 -31
- package/gsd-core/bin/lib/roadmap-parser.cjs +79 -16
- package/gsd-core/bin/lib/roadmap.cjs +74 -19
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +96 -8
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +34 -1
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +287 -55
- package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
- package/gsd-core/bin/lib/runtime-slash.cjs +72 -2
- package/gsd-core/bin/lib/shell-command-projection.cjs +71 -8
- package/gsd-core/bin/lib/smart-entry.cjs +12 -22
- package/gsd-core/bin/lib/spec-section.cjs +12 -7
- package/gsd-core/bin/lib/state-command-router.cjs +47 -18
- package/gsd-core/bin/lib/state-contract.cjs +359 -0
- package/gsd-core/bin/lib/state-document.cjs +186 -0
- package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
- package/gsd-core/bin/lib/state-transition.cjs +517 -101
- package/gsd-core/bin/lib/state.cjs +946 -163
- package/gsd-core/bin/lib/surface.cjs +10 -2
- package/gsd-core/bin/lib/task-command-router.cjs +111 -1
- package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
- package/gsd-core/bin/lib/teams-status.cjs +4 -1
- package/gsd-core/bin/lib/uat-predicate.cjs +58 -20
- package/gsd-core/bin/lib/uat.cjs +1376 -125
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
- package/gsd-core/bin/lib/ui-safety-gate.cjs +37 -7
- package/gsd-core/bin/lib/unusable-input.cjs +13 -0
- package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
- package/gsd-core/bin/lib/vendor/README.md +43 -5
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
- package/gsd-core/bin/lib/verification.cjs +14 -1
- package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
- package/gsd-core/bin/lib/verify.cjs +95 -40
- package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
- package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
- package/gsd-core/bin/lib/worktree-safety.cjs +177 -21
- package/gsd-core/bin/shared/config-defaults.manifest.json +7 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
- package/gsd-core/bin/shared/exit-codes.json +8 -0
- package/gsd-core/bin/shared/exit-codes.sh +20 -0
- package/gsd-core/bin/shared/model-catalog.json +8 -1
- package/gsd-core/references/agent-contracts.md +3 -2
- package/gsd-core/references/api-coverage.md +24 -2
- package/gsd-core/references/autonomous-smart-discuss.md +3 -3
- package/gsd-core/references/checkpoints.md +37 -19
- package/gsd-core/references/decimal-phase-calculation.md +5 -5
- package/gsd-core/references/edge-probe.md +8 -0
- package/gsd-core/references/execute-mvp-tdd.md +1 -3
- package/gsd-core/references/execute-phase-between-wave-reset.md +9 -12
- package/gsd-core/references/execute-phase-wave-guard.md +11 -9
- package/gsd-core/references/failing-direction.md +78 -0
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-integration.md +5 -5
- package/gsd-core/references/git-planning-commit.md +3 -3
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +22 -0
- package/gsd-core/references/model-profiles.md +1 -1
- package/gsd-core/references/nyquist-compliance.md +74 -0
- package/gsd-core/references/offer-next.md +3 -5
- package/gsd-core/references/phase-argument-parsing.md +3 -3
- package/gsd-core/references/planner-failing-direction.md +53 -0
- package/gsd-core/references/planner-human-verify-mode.md +15 -1
- package/gsd-core/references/planner-revision.md +1 -1
- package/gsd-core/references/planner-verify-command-grounding.md +17 -0
- package/gsd-core/references/planning-config.md +37 -8
- package/gsd-core/references/reviewer-instances.md +31 -0
- package/gsd-core/references/runtime-aware-dispatch.md +1 -1
- package/gsd-core/references/tdd.md +1 -3
- package/gsd-core/references/ui-brand.md +65 -21
- package/gsd-core/references/ui-consideration-probe.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +2 -2
- package/gsd-core/references/verify-command-path-resolvability.md +42 -0
- package/gsd-core/references/verify-mvp-mode.md +1 -1
- package/gsd-core/references/workstream-flag.md +11 -11
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/SECURITY.md +3 -3
- package/gsd-core/templates/UI-SPEC.md +25 -3
- package/gsd-core/templates/VALIDATION.md +3 -3
- package/gsd-core/templates/phase-prompt.md +3 -0
- package/gsd-core/templates/state.md +7 -0
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +3 -3
- package/gsd-core/workflows/add-tests.md +3 -8
- package/gsd-core/workflows/add-todo.md +1 -1
- package/gsd-core/workflows/ai-integration-phase.md +4 -9
- package/gsd-core/workflows/audit-fix.md +12 -3
- package/gsd-core/workflows/audit-milestone.md +9 -9
- package/gsd-core/workflows/audit-uat.md +17 -2
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
- package/gsd-core/workflows/autonomous.md +10 -26
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +2 -2
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +1 -1
- package/gsd-core/workflows/code-review-fix.md +1 -1
- package/gsd-core/workflows/code-review.md +121 -40
- package/gsd-core/workflows/complete-milestone.md +15 -10
- package/gsd-core/workflows/debug.md +5 -3
- package/gsd-core/workflows/diagnose-issues.md +12 -6
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +3 -7
- package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
- package/gsd-core/workflows/discuss-phase-assumptions.md +2 -2
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +3 -6
- package/gsd-core/workflows/docs-update.md +5 -4
- package/gsd-core/workflows/edit-phase.md +1 -1
- package/gsd-core/workflows/eval-review.md +4 -9
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +113 -11
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +22 -4
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
- package/gsd-core/workflows/execute-phase.md +38 -54
- package/gsd-core/workflows/execute-plan.md +17 -12
- package/gsd-core/workflows/explore.md +1 -1
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/fast.md +2 -2
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +5 -5
- package/gsd-core/workflows/health.md +3 -6
- package/gsd-core/workflows/import.md +14 -11
- package/gsd-core/workflows/inbox.md +4 -5
- package/gsd-core/workflows/ingest-docs.md +44 -11
- package/gsd-core/workflows/insert-phase.md +5 -5
- package/gsd-core/workflows/list-seeds.md +5 -3
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +12 -23
- package/gsd-core/workflows/map-codebase.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +2 -2
- package/gsd-core/workflows/new-milestone.md +9 -21
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +12 -26
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +2 -2
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
- package/gsd-core/workflows/plan-phase.md +121 -42
- package/gsd-core/workflows/plan-review-convergence.md +46 -9
- package/gsd-core/workflows/plant-seed.md +2 -2
- package/gsd-core/workflows/pr-branch.md +187 -51
- package/gsd-core/workflows/profile-user.md +16 -14
- package/gsd-core/workflows/progress.md +27 -12
- package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +1 -3
- package/gsd-core/workflows/quick/steps/quick-verification.md +2 -4
- package/gsd-core/workflows/quick/steps/research-phase.md +2 -4
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
- package/gsd-core/workflows/quick.md +20 -29
- package/gsd-core/workflows/remove-phase.md +4 -4
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +8 -12
- package/gsd-core/workflows/review.md +193 -15
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +2 -2
- package/gsd-core/workflows/settings-advanced.md +7 -9
- package/gsd-core/workflows/settings-integrations.md +64 -31
- package/gsd-core/workflows/settings.md +3 -5
- package/gsd-core/workflows/ship.md +12 -6
- package/gsd-core/workflows/sketch-wrap-up.md +11 -17
- package/gsd-core/workflows/sketch.md +12 -18
- package/gsd-core/workflows/smart-entry.md +3 -5
- package/gsd-core/workflows/spec-phase.md +23 -1
- package/gsd-core/workflows/spike-wrap-up.md +7 -11
- package/gsd-core/workflows/spike.md +20 -31
- package/gsd-core/workflows/stats.md +2 -2
- package/gsd-core/workflows/sync-skills.md +1 -1
- package/gsd-core/workflows/thread.md +11 -7
- package/gsd-core/workflows/transition.md +5 -5
- package/gsd-core/workflows/ui-phase.md +10 -16
- package/gsd-core/workflows/ui-review.md +6 -10
- package/gsd-core/workflows/ultraplan-phase.md +5 -13
- package/gsd-core/workflows/undo.md +8 -16
- package/gsd-core/workflows/update.md +6 -10
- package/gsd-core/workflows/validate-phase.md +2 -2
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +57 -18
- package/hooks/dist/gsd-agent-isolation-guard.js +77 -38
- package/hooks/dist/gsd-config-reload.js +18 -12
- package/hooks/dist/gsd-context-monitor.js +19 -10
- package/hooks/dist/gsd-cursor-post-tool.js +3 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +3 -1
- package/hooks/dist/gsd-cursor-session-start.js +2 -1
- package/hooks/dist/gsd-cursor-stop.js +2 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +28 -23
- package/hooks/dist/gsd-cursor-subagent-stop.js +3 -1
- package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
- package/hooks/dist/gsd-graphify-update.sh +22 -18
- package/hooks/dist/gsd-node-runner.sh +76 -0
- package/hooks/dist/gsd-phase-boundary.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +16 -7
- package/hooks/dist/gsd-read-guard.js +16 -7
- package/hooks/dist/gsd-read-injection-scanner.js +17 -8
- package/hooks/dist/gsd-session-state.sh +1 -0
- package/hooks/dist/gsd-statusline.js +215 -26
- package/hooks/dist/gsd-validate-commit.sh +80 -6
- package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
- package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
- package/hooks/dist/gsd-workflow-guard.js +34 -16
- package/hooks/dist/gsd-worktree-path-guard.js +36 -21
- package/hooks/dist/gsd-write-guard.js +35 -25
- package/hooks/dist/lib/cli-exit.js +560 -0
- package/hooks/dist/lib/exit-code-registry.js +98 -0
- package/hooks/dist/lib/git-probe.js +84 -0
- package/hooks/dist/lib/hook-exit.js +81 -0
- package/hooks/dist/managed-hooks-registry.cjs +3 -0
- package/hooks/gsd-agent-isolation-guard.js +77 -38
- package/hooks/gsd-config-reload.js +18 -12
- package/hooks/gsd-context-monitor.js +19 -10
- package/hooks/gsd-cursor-post-tool.js +3 -1
- package/hooks/gsd-cursor-pre-tool.js +3 -1
- package/hooks/gsd-cursor-session-start.js +2 -1
- package/hooks/gsd-cursor-stop.js +2 -1
- package/hooks/gsd-cursor-subagent-start.js +28 -23
- package/hooks/gsd-cursor-subagent-stop.js +3 -1
- package/hooks/gsd-ensure-canonical-path.js +2 -1
- package/hooks/gsd-graphify-update.sh +22 -18
- package/hooks/gsd-node-runner.sh +76 -0
- package/hooks/gsd-phase-boundary.sh +1 -0
- package/hooks/gsd-prompt-guard.js +16 -7
- package/hooks/gsd-read-guard.js +16 -7
- package/hooks/gsd-read-injection-scanner.js +17 -8
- package/hooks/gsd-session-state.sh +1 -0
- package/hooks/gsd-statusline.js +215 -26
- package/hooks/gsd-validate-commit.sh +80 -6
- package/hooks/gsd-windsurf-pre-command.js +16 -11
- package/hooks/gsd-windsurf-pre-write.js +22 -13
- package/hooks/gsd-workflow-guard.js +34 -16
- package/hooks/gsd-worktree-path-guard.js +36 -21
- package/hooks/gsd-write-guard.js +35 -25
- package/hooks/lib/cli-exit.js +560 -0
- package/hooks/lib/exit-code-registry.js +98 -0
- package/hooks/lib/git-probe.js +84 -0
- package/hooks/lib/hook-exit.js +81 -0
- package/hooks/managed-hooks-registry.cjs +3 -0
- package/package.json +12 -7
- package/scripts/base64-scan.sh +74 -12
- package/scripts/build-hooks.js +5 -0
- package/scripts/check-glossary-refs.cjs +77 -15
- package/scripts/check-mutation-score-ratchet.cjs +156 -0
- package/scripts/ci-check-job-near-cap.cjs +49 -0
- package/scripts/ci-pr-mergeability.cjs +262 -0
- package/scripts/ci-test-scope.cjs +45 -12
- package/scripts/ci-timeout-report.cjs +230 -0
- package/scripts/docs-guard-registry.cjs +396 -0
- package/scripts/gen-capability-registry.cjs +8 -6
- package/scripts/gen-exit-code-docs.cjs +318 -0
- package/scripts/gen-exit-code-registry.cjs +891 -0
- package/scripts/gen-features.cjs +836 -0
- package/scripts/gen-hooks-cli-exit.cjs +239 -0
- package/scripts/gen-install-tree-fixtures.cjs +2 -2
- package/scripts/gen-loop-host-contract.cjs +134 -1
- package/scripts/gen-scripts-cli-exit.cjs +185 -0
- package/scripts/gen-state-md-docs.cjs +727 -0
- package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
- package/scripts/lib/ci-job-timing.cjs +72 -0
- package/scripts/lib/cli-exit.cjs +546 -44
- package/scripts/lib/drift-scan.cjs +32 -2
- package/scripts/lib/exit-code-registry.cjs +98 -0
- package/scripts/lib/ndjson-reporter.cjs +119 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-docs-guard-registration.cjs +495 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +4 -0
- package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
- package/scripts/lint-health-diagnostic-rule-table.cjs +65 -8
- package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
- package/scripts/lint-phase-enumeration-drift.cjs +21 -8
- package/scripts/lint-planning-prompt-drift.cjs +38 -1
- package/scripts/lint-removed-but-needed.cjs +184 -16
- package/scripts/lint-seam-enforcement.cjs +182 -0
- package/scripts/lint-slug-derivation-drift.cjs +921 -0
- package/scripts/lint-source-test-name-collision.cjs +241 -0
- package/scripts/lint-state-write-path-drift.cjs +337 -432
- package/scripts/lint-test-file-count.allowlist.json +122 -4
- package/scripts/lint-test-file-count.cjs +25 -3
- package/scripts/lint-unreachable-guard-drift.cjs +51 -64
- package/scripts/lint-vendored-deps.cjs +208 -35
- package/scripts/mutation-matrix.cjs +599 -50
- package/scripts/prompt-injection-scan.sh +75 -14
- package/scripts/secret-scan.sh +75 -13
- package/scripts/select-docs-guards.cjs +56 -0
- package/scripts/sync-runtime-launcher.cjs +22 -3
- package/skills/gsd-discuss-phase/SKILL.md +1 -1
- package/skills/gsd-import/SKILL.md +1 -1
- package/skills/gsd-quick/SKILL.md +8 -4
- package/vscode/package.json +1 -1
- package/bin/lib/ui-safety-gate.cjs +0 -109
- package/scripts/lint-emitted-drift-ack.cjs +0 -344
- package/scripts/state-write-path-drift-baseline.json +0 -19
|
@@ -85,6 +85,14 @@ function getControllingTtyToken() {
|
|
|
85
85
|
return probeControllingTtyToken();
|
|
86
86
|
}
|
|
87
87
|
function getWorkstreamSessionKey() {
|
|
88
|
+
// #3883 (ADR-3473 §8.3): DECLARED DIFFERENT from generateSlugInternal
|
|
89
|
+
// (core-utils.cts), the canonical slug formula — deliberately, not a
|
|
90
|
+
// consolidation gap. The text slugified here is never caller-supplied: it
|
|
91
|
+
// is always one of the fixed ASCII WORKSTREAM_SESSION_ENV_KEYS identifier
|
|
92
|
+
// names above (e.g. "GSD_SESSION_KEY"), which already agree with the
|
|
93
|
+
// canonical's output byte-for-byte on this restricted input domain (no
|
|
94
|
+
// unicode, no length anywhere near the 60-char truncation boundary) — so
|
|
95
|
+
// delegating would add a require() edge for zero behavioral change.
|
|
88
96
|
for (const envKey of WORKSTREAM_SESSION_ENV_KEYS) {
|
|
89
97
|
const raw = process.env[envKey];
|
|
90
98
|
const token = sanitizeWorkstreamSessionToken(raw);
|
|
@@ -14,6 +14,9 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
14
14
|
const node_path_1 = __importDefault(require("node:path"));
|
|
15
15
|
const security_cjs_1 = require("./security.cjs");
|
|
16
16
|
const markdown_sectionizer_cjs_1 = require("./markdown-sectionizer.cjs");
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
18
|
+
const cliExitModule = require("./cli-exit.cjs");
|
|
19
|
+
const { ExitError, runMain } = cliExitModule;
|
|
17
20
|
const STATUS_REJECT_SET = new Set(['superseded', 'rejected', 'deprecated']);
|
|
18
21
|
const CANONICAL_HEADERS = {
|
|
19
22
|
status: ['status', 'state', 'lifecycle', 'stage'],
|
|
@@ -405,13 +408,16 @@ function main(argv) {
|
|
|
405
408
|
process.stdout.write(JSON.stringify(parsed, null, 2));
|
|
406
409
|
}
|
|
407
410
|
if (require.main === module) {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
411
|
+
runMain(() => {
|
|
412
|
+
try {
|
|
413
|
+
main(process.argv.slice(2));
|
|
414
|
+
}
|
|
415
|
+
catch (err) {
|
|
416
|
+
// ExitError with a message so runMain's catch writes it verbatim
|
|
417
|
+
// (byte-identical to the prior `Error: ${message}\n` process.exit(1)).
|
|
418
|
+
throw new ExitError(1, `Error: ${err.message}`);
|
|
419
|
+
}
|
|
420
|
+
});
|
|
415
421
|
}
|
|
416
422
|
module.exports = {
|
|
417
423
|
CANONICAL_HEADERS,
|
|
@@ -29,6 +29,20 @@ const model_catalog_cjs_1 = require("./model-catalog.cjs");
|
|
|
29
29
|
// locally. Behavior is unchanged: scanTomlLines/stripBOM here are the exact
|
|
30
30
|
// same lenient functions that used to live in this file — see
|
|
31
31
|
// codex-agent-toml.cts's module header for the reader/writer reconciliation.
|
|
32
|
+
// #3897 CAUSE A fix: `deriveCodexSandboxMode` needs the resolved `tools:`
|
|
33
|
+
// frontmatter VALUE, not raw content — this module used to reach that via
|
|
34
|
+
// `runtime-artifact-conversion.cjs`'s general-purpose
|
|
35
|
+
// `extractFrontmatterAndBody`/`extractFrontmatterField`, but that module's
|
|
36
|
+
// dependency chain (`command-roster.cjs` -> `scripts/fix-slash-commands.cjs`,
|
|
37
|
+
// a dev-only repo script) does not resolve from an installed tree — any test
|
|
38
|
+
// exercising a synthetic install dir blew up at module load. `codex-agent-toml.cjs`
|
|
39
|
+
// is already imported here, is a genuine leaf (node builtins only, zero
|
|
40
|
+
// side effects), and now exports `extractToolsValue` — a single-purpose
|
|
41
|
+
// `tools:`-VALUE reader (inline AND YAML block-list form, #3897 list-form
|
|
42
|
+
// parse fix), not a general frontmatter parser — for exactly this caller,
|
|
43
|
+
// shared with `bin/install.js`'s emitter so the two sandbox-feeding paths
|
|
44
|
+
// can never silently disagree, and no fourth copy of frontmatter parsing is
|
|
45
|
+
// added.
|
|
32
46
|
const codex_agent_toml_cjs_1 = require("./codex-agent-toml.cjs");
|
|
33
47
|
/**
|
|
34
48
|
* Frozen reason enum for {@link checkCodexModelPosture}. Per CONTRIBUTING's
|
|
@@ -305,6 +319,153 @@ function checkCodexModelPosture(runtime, projectRoot) {
|
|
|
305
319
|
agent_runtime: resolvedRuntime,
|
|
306
320
|
};
|
|
307
321
|
}
|
|
322
|
+
// #3897 rung 3 — the canonical bundled `agents/*.md` source directory (the
|
|
323
|
+
// tool-contract source of truth), resolved the same install-relative way
|
|
324
|
+
// getAgentsDir resolves the claude case, WITHOUT that function's npm-global
|
|
325
|
+
// node_modules redirect: that redirect exists so a Codex/claude INSTALL is
|
|
326
|
+
// never validated against itself, but here we deliberately want the bundled
|
|
327
|
+
// copy every time — it is the only place the `tools:` contract a role
|
|
328
|
+
// derives its sandbox_mode from actually lives, in every install shape
|
|
329
|
+
// (repo-dev tree or npm-global package, where the package still ships its
|
|
330
|
+
// own agents/ alongside bin/ and gsd-core/).
|
|
331
|
+
function _canonicalAgentSourceDir() {
|
|
332
|
+
return node_path_1.default.join(__dirname, '..', '..', '..', 'agents');
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Validate installed Codex `.toml` agents' `sandbox_mode` against what each
|
|
336
|
+
* role's own tool contract derives (#3897, ADR-3473 §8.3 criterion 3,
|
|
337
|
+
* HALT.md option 2). Sibling to {@link checkCodexModelPosture} — same shape,
|
|
338
|
+
* same short-circuits — but a different defect class: a TOML whose
|
|
339
|
+
* `sandbox_mode` disagrees with the derived expectation, not a bad `model`.
|
|
340
|
+
*
|
|
341
|
+
* `deriveCodexSandboxMode` (and the `CODEX_SANDBOX_HOLDS` hold list + its own
|
|
342
|
+
* self-invalidation check it embeds) is imported from `codex-agent-toml.cjs`
|
|
343
|
+
* — the shared, side-effect-free leaf both `bin/install.js`'s emitter and
|
|
344
|
+
* this posture check import from (CAUSE A fix, #3897: this function used to
|
|
345
|
+
* lazily `require('bin/install.js')` to reach the same derivation, but
|
|
346
|
+
* requiring `bin/install.js` runs its whole CLI top-level, including an
|
|
347
|
+
* ASCII banner print to stdout, which corrupted every stdout-JSON caller of
|
|
348
|
+
* this posture check, e.g. `gsd-tools validate agents`) — so the emitter and
|
|
349
|
+
* this posture check can never silently diverge on the same tool-contract
|
|
350
|
+
* predicate — the exact generative-fix-divergence shape this epic exists to
|
|
351
|
+
* close. `deriveCodexSandboxMode` itself is total (never throws, #3897
|
|
352
|
+
* CAUSE C fix) — a held role whose supplied content no longer derives
|
|
353
|
+
* broader than its pin simply returns `read-only` rather than failing,
|
|
354
|
+
* because the pin is then a no-op. The staleness invariant (S4/S5) this
|
|
355
|
+
* check's imports still carry is enforced separately, at the real `agents/`
|
|
356
|
+
* roster level, by `validateCodexSandboxHolds` and
|
|
357
|
+
* `tests/codex-config.test.cjs` T24/T25 — not by this per-call derivation.
|
|
358
|
+
*
|
|
359
|
+
* Read-only: detects, never repairs — same posture as {@link checkCodexModelPosture}.
|
|
360
|
+
*
|
|
361
|
+
* @param runtime - the active runtime name; defaults to GSD_RUNTIME env, then 'claude'
|
|
362
|
+
* @param projectRoot - canonical project root for local-install discovery
|
|
363
|
+
*/
|
|
364
|
+
function checkCodexSandboxPosture(runtime, projectRoot) {
|
|
365
|
+
const resolvedRuntime = runtime ?? (process.env['GSD_RUNTIME'] || 'claude');
|
|
366
|
+
if (resolvedRuntime !== 'codex') {
|
|
367
|
+
return {
|
|
368
|
+
ok: true,
|
|
369
|
+
violations: [],
|
|
370
|
+
checked: [],
|
|
371
|
+
agents_dir: '',
|
|
372
|
+
agent_runtime: resolvedRuntime,
|
|
373
|
+
reason: POSTURE_REASON.NOT_CODEX,
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
const agentsDir = getAgentsDir(resolvedRuntime, projectRoot);
|
|
377
|
+
if (!node_fs_1.default.existsSync(agentsDir)) {
|
|
378
|
+
return {
|
|
379
|
+
ok: true,
|
|
380
|
+
violations: [],
|
|
381
|
+
checked: [],
|
|
382
|
+
agents_dir: agentsDir,
|
|
383
|
+
agent_runtime: resolvedRuntime,
|
|
384
|
+
reason: POSTURE_REASON.AGENTS_DIR_MISSING,
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
const canonicalAgentsDir = _canonicalAgentSourceDir();
|
|
388
|
+
// Same symlink guard as checkCodexModelPosture, same reason (never follow
|
|
389
|
+
// an agents-dir symlink into an arbitrary file's content).
|
|
390
|
+
const tomlFiles = node_fs_1.default
|
|
391
|
+
.readdirSync(agentsDir)
|
|
392
|
+
.filter((entry) => {
|
|
393
|
+
if (!entry.endsWith('.toml'))
|
|
394
|
+
return false;
|
|
395
|
+
try {
|
|
396
|
+
return node_fs_1.default.lstatSync(node_path_1.default.join(agentsDir, entry)).isFile();
|
|
397
|
+
}
|
|
398
|
+
catch {
|
|
399
|
+
return false;
|
|
400
|
+
}
|
|
401
|
+
})
|
|
402
|
+
.sort();
|
|
403
|
+
const checked = [];
|
|
404
|
+
const violations = [];
|
|
405
|
+
for (const entry of tomlFiles) {
|
|
406
|
+
const agentName = entry.slice(0, -'.toml'.length);
|
|
407
|
+
const filePath = node_path_1.default.join(agentsDir, entry);
|
|
408
|
+
checked.push(agentName);
|
|
409
|
+
let raw;
|
|
410
|
+
try {
|
|
411
|
+
raw = node_fs_1.default.readFileSync(filePath, 'utf8');
|
|
412
|
+
}
|
|
413
|
+
catch {
|
|
414
|
+
violations.push({ agent: agentName, file: filePath, reason: POSTURE_REASON.UNREADABLE });
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
// #3897 rung 4 (isolated correctness review, MINOR finding 2): route
|
|
418
|
+
// through the same block-aware `scanTomlLines` the sibling
|
|
419
|
+
// `checkCodexModelPosture` already uses, rather than a naive whole-file
|
|
420
|
+
// regex — a `sandbox_mode = "..."`-shaped line inside the
|
|
421
|
+
// `developer_instructions` block (prose) must never be read as a live
|
|
422
|
+
// value. A prior naive `raw.match(/^sandbox_mode.../m)` here produced a
|
|
423
|
+
// FALSE violation whenever an agent's own prompt prose happened to
|
|
424
|
+
// contain that shape.
|
|
425
|
+
const found = (0, codex_agent_toml_cjs_1.scanTomlLines)((0, codex_agent_toml_cjs_1.stripBOM)(raw)).sandboxMode;
|
|
426
|
+
if (found === null) {
|
|
427
|
+
// No sandbox_mode line at all (e.g. sandboxTier "none") is a deliberate,
|
|
428
|
+
// documented state elsewhere — not this check's business.
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
const canonicalFile = node_path_1.default.join(canonicalAgentsDir, `${agentName}.md`);
|
|
432
|
+
let canonicalContent;
|
|
433
|
+
try {
|
|
434
|
+
canonicalContent = node_fs_1.default.readFileSync(canonicalFile, 'utf8');
|
|
435
|
+
}
|
|
436
|
+
catch {
|
|
437
|
+
// No canonical role source (a custom/non-roster agent) — nothing to
|
|
438
|
+
// derive an expectation from, so this is not this check's business.
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
// `canonicalContent` is always a real string here (read via fs.readFileSync
|
|
442
|
+
// above), so extractToolsValue's `undefined` (non-string input) branch is
|
|
443
|
+
// unreachable on this path — the `?? ''` is a type-level formality, not a
|
|
444
|
+
// behavior change (F4, #3897 security review: extractToolsValue is TOTAL).
|
|
445
|
+
const toolsRaw = (0, codex_agent_toml_cjs_1.extractToolsValue)(canonicalContent) ?? '';
|
|
446
|
+
const expected = (0, codex_agent_toml_cjs_1.deriveCodexSandboxMode)(agentName, toolsRaw);
|
|
447
|
+
if (expected !== found) {
|
|
448
|
+
// #3897 rung 4 (isolated correctness review, MINOR finding 3):
|
|
449
|
+
// truncatePostureValue matches the sibling checkCodexModelPosture's
|
|
450
|
+
// convention (see its own `value: truncatePostureValue(model)` above)
|
|
451
|
+
// so an oversized or secret-shaped `sandbox_mode` value can never
|
|
452
|
+
// reach `validate agents --raw` output at full length.
|
|
453
|
+
violations.push({
|
|
454
|
+
agent: agentName,
|
|
455
|
+
file: filePath,
|
|
456
|
+
expected: truncatePostureValue(expected),
|
|
457
|
+
found: truncatePostureValue(found),
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
ok: violations.length === 0,
|
|
463
|
+
violations,
|
|
464
|
+
checked,
|
|
465
|
+
agents_dir: agentsDir,
|
|
466
|
+
agent_runtime: resolvedRuntime,
|
|
467
|
+
};
|
|
468
|
+
}
|
|
308
469
|
/**
|
|
309
470
|
* Probe a single agents dir for `<name>` across runtime filename variants.
|
|
310
471
|
* Mirrors {@link checkAgentsInstalled}'s probe (`.md`, `.agent.md`, `.toml`,
|
|
@@ -368,6 +529,7 @@ module.exports = {
|
|
|
368
529
|
getAgentsDir,
|
|
369
530
|
checkAgentsInstalled,
|
|
370
531
|
checkCodexModelPosture,
|
|
532
|
+
checkCodexSandboxPosture,
|
|
371
533
|
POSTURE_REASON,
|
|
372
534
|
resolveAgentHint,
|
|
373
535
|
};
|
|
@@ -52,9 +52,13 @@
|
|
|
52
52
|
* renderCoverageMatrix(rows) -> string
|
|
53
53
|
* DEFAULT_API_COVERAGE_TERMS
|
|
54
54
|
*
|
|
55
|
-
* CLI:
|
|
55
|
+
* CLI (ADR-3889 Phase 3, #3907):
|
|
56
56
|
* echo "$SCOPE" | node gsd-core/bin/lib/api-coverage.cjs [--json]
|
|
57
|
-
* exit 0 = integration detected, 1 = none,
|
|
57
|
+
* exit 0 = integration detected, 1 = none (real input, examined, no signal),
|
|
58
|
+
* NO_INPUT (registry, src/cli-exit.cts) = stdin empty/whitespace-only,
|
|
59
|
+
* UNAVAILABLE (registry) = stdin read failed
|
|
60
|
+
* --json additionally prints the typed IR on stdout (unchanged for 0/1);
|
|
61
|
+
* NO_INPUT/UNAVAILABLE print {skipped:true, reason:"no_input"|"stdin_error"}
|
|
58
62
|
*/
|
|
59
63
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
60
64
|
exports.DEFAULT_API_COVERAGE_TERMS = void 0;
|
|
@@ -849,11 +853,24 @@ function renderCoverageMatrix(rows) {
|
|
|
849
853
|
// ── CLI entry point ──────────────────────────────────────────────────────────
|
|
850
854
|
// Reads phase-scope text from STDIN (not argv) to avoid OS ARG_MAX limits.
|
|
851
855
|
// Invoked by workflow bash as: echo "$SCOPE" | node .../api-coverage.cjs [--json]
|
|
852
|
-
//
|
|
853
|
-
//
|
|
856
|
+
//
|
|
857
|
+
// Exit codes (ADR-3889 Phase 3, #3907): 0 = integration detected, 1 = none
|
|
858
|
+
// (real input, examined, no signal), NO_INPUT (registry — src/cli-exit.cts) =
|
|
859
|
+
// stdin empty/whitespace-only, UNAVAILABLE (registry) = stdin read failed.
|
|
860
|
+
// The prior single "2 = startup error" arm let empty input flow into the
|
|
861
|
+
// detector and exit 1 — an unexamined input reported as an authoritative
|
|
862
|
+
// negative. Under --json, NO_INPUT/UNAVAILABLE emit `{skipped:true,
|
|
863
|
+
// reason:"no_input"|"stdin_error"}` — no `detected` key, so a stale
|
|
864
|
+
// `detected:false` can never sit beside `skipped:true`; the detected/no-signal
|
|
865
|
+
// `--json` payloads are byte-identical to before. Terminates via terminateNow
|
|
866
|
+
// (write-then-terminate, total by construction), not raw process.exit — these
|
|
867
|
+
// exits fire from inside a stdin event handler. Mirrors assumption-delta.cjs /
|
|
868
|
+
// ui-safety-gate.cjs.
|
|
854
869
|
if (require.main === module) {
|
|
855
870
|
const argv = process.argv.slice(2);
|
|
856
871
|
const wantJson = argv.includes('--json');
|
|
872
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
873
|
+
const cliExit = require('./cli-exit.cjs');
|
|
857
874
|
let termsOverride;
|
|
858
875
|
const verbsIdx = argv.indexOf('--verbs');
|
|
859
876
|
const verbsVal = verbsIdx !== -1 ? argv[verbsIdx + 1] : undefined;
|
|
@@ -877,14 +894,18 @@ if (require.main === module) {
|
|
|
877
894
|
process.stdin.on('data', (chunk) => chunks.push(chunk));
|
|
878
895
|
process.stdin.on('end', () => {
|
|
879
896
|
const input = chunks.join('');
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
897
|
+
// Whitespace-only counts as empty (ADR-3889 §1's NO_INPUT: "zero units
|
|
898
|
+
// were in scope, and that emptiness is known to be genuine"). Real input
|
|
899
|
+
// — including a lone NUL byte, which .trim() does not strip — always
|
|
900
|
+
// falls through to the detector.
|
|
901
|
+
if (input.trim().length === 0) {
|
|
902
|
+
cliExit.terminateNow('NO_INPUT', wantJson ? { skipped: true, reason: 'no_input' } : undefined);
|
|
883
903
|
}
|
|
884
|
-
|
|
904
|
+
const result = detectApiIntegration(input, termsOverride);
|
|
905
|
+
cliExit.terminateNow(result.detected ? 'PASS' : 'FAIL', wantJson ? result : undefined);
|
|
885
906
|
});
|
|
886
907
|
process.stdin.on('error', (err) => {
|
|
887
908
|
process.stderr.write(`ERROR: api-coverage.cjs stdin read failed: ${err.message}\n`);
|
|
888
|
-
|
|
909
|
+
cliExit.terminateNow('UNAVAILABLE', wantJson ? { skipped: true, reason: 'stdin_error' } : undefined);
|
|
889
910
|
});
|
|
890
911
|
}
|
|
@@ -30,6 +30,8 @@ exports.CANONICAL_EXACT = new Set([
|
|
|
30
30
|
'WINDOWS.md', // #3224: broken-windows ledger (src/broken-windows.cts, LEDGER_FILE_NAME)
|
|
31
31
|
'STATE-ARCHIVE.md', // state.cts's cmdStatePrune writes this at the .planning/ root
|
|
32
32
|
'milestone.lock', // #3311: milestone (phase + session) claim (src/milestone-lock.cts); persistent, unlike the transient STATE.md.lock/WAITING.json
|
|
33
|
+
'state.json', // #3227: machine-readable state contract published at step boundaries (src/state-contract.cts)
|
|
34
|
+
'skill-manifest.json', // init.cts routeSkillManifest --write (project-scoped planning root, #3964)
|
|
33
35
|
]);
|
|
34
36
|
// Pattern-match canonical file names (regex tests on the basename)
|
|
35
37
|
// Each pattern includes the name of the workflow that produces it as a comment.
|
|
@@ -21,17 +21,19 @@
|
|
|
21
21
|
* tunable (config + the `terms` parameter) so teams can widen it.
|
|
22
22
|
* - FENCED CODE BLOCKS ARE STRIPPED first (via the markdown-sectionizer seam)
|
|
23
23
|
* so a trigger term that appears only inside a code snippet does not fire.
|
|
24
|
-
* - Mirrors ui-safety-gate.cts: a pure function + a STDIN-reading CLI
|
|
25
|
-
* exit codes mirror grep (0 = signal found, 1 = none, 2 = usage error).
|
|
24
|
+
* - Mirrors ui-safety-gate.cts: a pure function + a STDIN-reading CLI.
|
|
26
25
|
*
|
|
27
26
|
* Public API:
|
|
28
27
|
* detectAssumptionDelta(text, terms?) -> { detected, signals, terms }
|
|
29
28
|
* DEFAULT_ASSUMPTION_DELTA_TERMS
|
|
30
29
|
*
|
|
31
|
-
* CLI:
|
|
30
|
+
* CLI (ADR-3889 Phase 3, #3907):
|
|
32
31
|
* echo "$PHASE_SECTION" | node gsd-core/bin/lib/assumption-delta.cjs [--json]
|
|
33
|
-
* exit 0 = signal detected, 1 = none,
|
|
34
|
-
*
|
|
32
|
+
* exit 0 = signal detected, 1 = none (real input, examined, no signal),
|
|
33
|
+
* NO_INPUT (registry, src/cli-exit.cts) = stdin empty/whitespace-only,
|
|
34
|
+
* UNAVAILABLE (registry) = stdin read failed
|
|
35
|
+
* --json additionally prints the typed IR on stdout (unchanged for 0/1);
|
|
36
|
+
* NO_INPUT/UNAVAILABLE print {skipped:true, reason:"no_input"|"stdin_error"}
|
|
35
37
|
*/
|
|
36
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
39
|
exports.DEFAULT_ASSUMPTION_DELTA_TERMS = void 0;
|
|
@@ -192,10 +194,23 @@ function detectAssumptionDelta(text, terms) {
|
|
|
192
194
|
// ── CLI entry point ──────────────────────────────────────────────────────────
|
|
193
195
|
// Reads phase-section text from STDIN (not argv) to avoid OS ARG_MAX limits.
|
|
194
196
|
// Invoked by workflow bash as: echo "$PHASE_SECTION" | node .../assumption-delta.cjs [--json]
|
|
195
|
-
//
|
|
197
|
+
//
|
|
198
|
+
// Exit codes (ADR-3889 Phase 3, #3907): 0 = signal detected, 1 = none (real
|
|
199
|
+
// input, examined, no signal), NO_INPUT (registry — src/cli-exit.cts) = stdin
|
|
200
|
+
// empty/whitespace-only, UNAVAILABLE (registry) = stdin read failed. The prior
|
|
201
|
+
// single "2 = startup error" arm let empty input flow into the detector and
|
|
202
|
+
// exit 1 — an unexamined input reported as an authoritative negative. Under
|
|
203
|
+
// --json, NO_INPUT/UNAVAILABLE emit `{skipped:true, reason:"no_input"|
|
|
204
|
+
// "stdin_error"}` — no `detected` key, so a stale `detected:false` can never
|
|
205
|
+
// sit beside `skipped:true`; the detected/no-signal `--json` payloads are
|
|
206
|
+
// byte-identical to before. Terminates via terminateNow (write-then-terminate,
|
|
207
|
+
// total by construction), not raw process.exit — these exits fire from inside
|
|
208
|
+
// a stdin event handler. Mirrors ui-safety-gate.cjs / api-coverage.cjs.
|
|
196
209
|
if (require.main === module) {
|
|
197
210
|
const argv = process.argv.slice(2);
|
|
198
211
|
const wantJson = argv.includes('--json');
|
|
212
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
213
|
+
const cliExit = require('./cli-exit.cjs');
|
|
199
214
|
// --terms <csv>: config-tunable vocabulary override. Replaces the
|
|
200
215
|
// pluralization cues (the primary trigger); optional/chosen keep defaults.
|
|
201
216
|
// An EMPTY value ("") or a flag-shaped value restores the curated defaults
|
|
@@ -216,14 +231,18 @@ if (require.main === module) {
|
|
|
216
231
|
process.stdin.on('data', (chunk) => chunks.push(chunk));
|
|
217
232
|
process.stdin.on('end', () => {
|
|
218
233
|
const input = chunks.join('');
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
234
|
+
// Whitespace-only counts as empty (ADR-3889 §1's NO_INPUT: "zero units
|
|
235
|
+
// were in scope, and that emptiness is known to be genuine"). Real input
|
|
236
|
+
// — including a lone NUL byte, which .trim() does not strip — always
|
|
237
|
+
// falls through to the detector.
|
|
238
|
+
if (input.trim().length === 0) {
|
|
239
|
+
cliExit.terminateNow('NO_INPUT', wantJson ? { skipped: true, reason: 'no_input' } : undefined);
|
|
222
240
|
}
|
|
223
|
-
|
|
241
|
+
const result = detectAssumptionDelta(input, termsOverride);
|
|
242
|
+
cliExit.terminateNow(result.detected ? 'PASS' : 'FAIL', wantJson ? result : undefined);
|
|
224
243
|
});
|
|
225
244
|
process.stdin.on('error', (err) => {
|
|
226
245
|
process.stderr.write(`ERROR: assumption-delta.cjs stdin read failed: ${err.message}\n`);
|
|
227
|
-
|
|
246
|
+
cliExit.terminateNow('UNAVAILABLE', wantJson ? { skipped: true, reason: 'stdin_error' } : undefined);
|
|
228
247
|
});
|
|
229
248
|
}
|