@opengsd/gsd-core 1.10.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-debug-session-manager.md +12 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-dom-verifier.md +169 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +22 -14
- package/agents/gsd-framework-selector.md +1 -3
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +5 -3
- package/agents/gsd-pattern-mapper.md +11 -0
- package/agents/gsd-phase-researcher.md +23 -2
- package/agents/gsd-plan-checker.md +50 -53
- package/agents/gsd-planner.md +50 -50
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.md +2 -2
- package/agents/gsd-roadmapper.md +15 -11
- package/agents/gsd-ui-checker.md +63 -4
- package/agents/gsd-ui-researcher.md +41 -3
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +13 -4
- package/bin/install.js +1448 -1103
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/discuss-phase.md +1 -1
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/import.md +1 -1
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/quick.md +9 -5
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +1035 -138
- package/gsd-core/bin/lib/active-workstream-store.cjs +146 -22
- package/gsd-core/bin/lib/adr-parser.cjs +13 -7
- package/gsd-core/bin/lib/agent-install-check.cjs +392 -32
- package/gsd-core/bin/lib/api-coverage.cjs +33 -14
- package/gsd-core/bin/lib/artifacts.cjs +5 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +32 -15
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +1026 -268
- package/gsd-core/bin/lib/broken-windows.cjs +306 -28
- package/gsd-core/bin/lib/capability-consent.cjs +149 -15
- package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
- package/gsd-core/bin/lib/capability-lock.cjs +10 -4
- package/gsd-core/bin/lib/capability-registry.cjs +845 -130
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-state.cjs +18 -3
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +700 -40
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +216 -42
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/cli-exit.cjs +496 -10
- package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +735 -0
- package/gsd-core/bin/lib/command-aliases.cjs +22 -0
- package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
- package/gsd-core/bin/lib/commands.cjs +1172 -108
- package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
- package/gsd-core/bin/lib/complexity-trigger.cjs +1192 -0
- package/gsd-core/bin/lib/config-loader.cjs +187 -23
- package/gsd-core/bin/lib/config.cjs +102 -3
- package/gsd-core/bin/lib/configuration.cjs +129 -37
- package/gsd-core/bin/lib/core-utils.cjs +208 -33
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/edge-probe.cjs +9 -1
- package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
- package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +899 -229
- package/gsd-core/bin/lib/gap-checker.cjs +95 -10
- package/gsd-core/bin/lib/git-base-branch.cjs +276 -39
- package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
- package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +149 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +268 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +187 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +451 -0
- package/gsd-core/bin/lib/host-integration.cjs +39 -6
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init-command-router.cjs +118 -21
- package/gsd-core/bin/lib/init.cjs +439 -168
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +811 -259
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +235 -0
- package/gsd-core/bin/lib/install-profiles.cjs +212 -61
- package/gsd-core/bin/lib/install-scope.cjs +270 -0
- package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
- package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
- package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
- package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +148 -38
- package/gsd-core/bin/lib/intel.cjs +101 -26
- package/gsd-core/bin/lib/io.cjs +170 -15
- package/gsd-core/bin/lib/learnings.cjs +85 -14
- package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
- package/gsd-core/bin/lib/markdown-table.cjs +183 -22
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +842 -73
- package/gsd-core/bin/lib/model-catalog.cjs +232 -16
- package/gsd-core/bin/lib/model-resolver.cjs +193 -68
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +18 -9
- package/gsd-core/bin/lib/phase-id.cjs +514 -40
- package/gsd-core/bin/lib/phase-lifecycle.cjs +52 -19
- package/gsd-core/bin/lib/phase-locator.cjs +262 -34
- package/gsd-core/bin/lib/phase.cjs +1038 -214
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
- package/gsd-core/bin/lib/plan-document.cjs +263 -0
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +98 -3
- package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +894 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +112 -6
- package/gsd-core/bin/lib/probe-core.cjs +5 -2
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
- package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
- package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +766 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +22 -13
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +59 -11
- package/gsd-core/bin/lib/roadmap-parser.cjs +1006 -184
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +442 -96
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +702 -52
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +459 -55
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +402 -58
- package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +96 -8
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +342 -7
- package/gsd-core/bin/lib/smart-entry.cjs +133 -23
- package/gsd-core/bin/lib/spec-section.cjs +12 -7
- package/gsd-core/bin/lib/state-command-router.cjs +52 -19
- package/gsd-core/bin/lib/state-contract.cjs +359 -0
- package/gsd-core/bin/lib/state-document.cjs +338 -8
- package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
- package/gsd-core/bin/lib/state-transition.cjs +846 -176
- package/gsd-core/bin/lib/state.cjs +2589 -369
- package/gsd-core/bin/lib/surface.cjs +33 -11
- package/gsd-core/bin/lib/task-command-router.cjs +111 -1
- package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
- package/gsd-core/bin/lib/teams-status.cjs +4 -1
- package/gsd-core/bin/lib/text-lines.cjs +80 -0
- package/gsd-core/bin/lib/token-scanner.cjs +76 -0
- package/gsd-core/bin/lib/uat-predicate.cjs +67 -23
- package/gsd-core/bin/lib/uat.cjs +1761 -167
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +51 -12
- package/gsd-core/bin/lib/unusable-input.cjs +37 -0
- package/gsd-core/bin/lib/update-context.cjs +8 -2
- package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
- package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
- package/gsd-core/bin/lib/validate.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +75 -0
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
- package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
- package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +272 -9
- package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
- package/gsd-core/bin/lib/verify.cjs +453 -918
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
- package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
- package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
- package/gsd-core/bin/lib/workstream.cjs +2 -2
- package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
- package/gsd-core/bin/lib/worktree-safety.cjs +341 -18
- package/gsd-core/bin/shared/config-defaults.manifest.json +8 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +12 -1
- package/gsd-core/bin/shared/exit-codes.json +8 -0
- package/gsd-core/bin/shared/exit-codes.sh +20 -0
- package/gsd-core/bin/shared/model-catalog.json +8 -1
- package/gsd-core/references/agent-contracts.md +44 -26
- package/gsd-core/references/api-coverage.md +24 -2
- package/gsd-core/references/autonomous-smart-discuss.md +3 -3
- package/gsd-core/references/checkpoints.md +39 -21
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/decimal-phase-calculation.md +5 -5
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/edge-probe.md +8 -0
- package/gsd-core/references/execute-mvp-tdd.md +4 -6
- package/gsd-core/references/execute-phase-between-wave-reset.md +15 -14
- package/gsd-core/references/execute-phase-context-guard.md +1 -1
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/execute-phase-wave-guard.md +17 -11
- package/gsd-core/references/failing-direction.md +78 -0
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-integration.md +5 -5
- package/gsd-core/references/git-planning-commit.md +5 -4
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +61 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/nyquist-compliance.md +74 -0
- package/gsd-core/references/offer-next.md +3 -5
- package/gsd-core/references/phase-argument-parsing.md +3 -3
- package/gsd-core/references/planner-failing-direction.md +53 -0
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-human-verify-mode.md +15 -1
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planner-revision.md +1 -1
- package/gsd-core/references/planner-verify-command-grounding.md +17 -0
- package/gsd-core/references/planning-config.md +44 -13
- package/gsd-core/references/reviewer-instances.md +31 -0
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/runtime-aware-dispatch.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +1 -1
- package/gsd-core/references/tdd.md +1 -3
- package/gsd-core/references/ui-brand.md +65 -21
- package/gsd-core/references/ui-consideration-probe.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +5 -5
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verify-command-path-resolvability.md +42 -0
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -17
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/SECURITY.md +3 -3
- package/gsd-core/templates/UI-SPEC.md +25 -3
- package/gsd-core/templates/VALIDATION.md +3 -3
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +5 -4
- package/gsd-core/templates/state.md +11 -4
- package/gsd-core/templates/verification-report.md +9 -1
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +3 -3
- package/gsd-core/workflows/add-tests.md +3 -8
- package/gsd-core/workflows/add-todo.md +1 -1
- package/gsd-core/workflows/ai-integration-phase.md +13 -20
- package/gsd-core/workflows/audit-fix.md +12 -3
- package/gsd-core/workflows/audit-milestone.md +9 -9
- package/gsd-core/workflows/audit-uat.md +17 -2
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
- package/gsd-core/workflows/autonomous.md +11 -27
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +64 -5
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +14 -4
- package/gsd-core/workflows/code-review-fix.md +38 -11
- package/gsd-core/workflows/code-review.md +159 -52
- package/gsd-core/workflows/complete-milestone.md +151 -23
- package/gsd-core/workflows/debug.md +12 -8
- package/gsd-core/workflows/diagnose-issues.md +47 -15
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -8
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +3 -6
- package/gsd-core/workflows/docs-update.md +5 -4
- package/gsd-core/workflows/edit-phase.md +27 -2
- package/gsd-core/workflows/eval-review.md +7 -14
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +142 -15
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +24 -4
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
- package/gsd-core/workflows/execute-phase.md +72 -100
- package/gsd-core/workflows/execute-plan.md +52 -15
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +5 -5
- package/gsd-core/workflows/health.md +76 -10
- package/gsd-core/workflows/import.md +18 -15
- package/gsd-core/workflows/inbox.md +4 -5
- package/gsd-core/workflows/ingest-docs.md +49 -16
- package/gsd-core/workflows/insert-phase.md +5 -5
- package/gsd-core/workflows/list-seeds.md +5 -3
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +12 -23
- package/gsd-core/workflows/map-codebase.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +8 -5
- package/gsd-core/workflows/new-milestone.md +22 -29
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +26 -40
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +14 -2
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
- package/gsd-core/workflows/plan-phase.md +162 -59
- package/gsd-core/workflows/plan-review-convergence.md +96 -11
- package/gsd-core/workflows/plant-seed.md +2 -2
- package/gsd-core/workflows/pr-branch.md +187 -51
- package/gsd-core/workflows/profile-user.md +16 -14
- package/gsd-core/workflows/progress.md +61 -18
- package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +5 -7
- package/gsd-core/workflows/quick/steps/quick-verification.md +28 -9
- package/gsd-core/workflows/quick/steps/research-phase.md +4 -6
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
- package/gsd-core/workflows/quick.md +55 -44
- package/gsd-core/workflows/remove-phase.md +4 -4
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +8 -12
- package/gsd-core/workflows/review.md +219 -20
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +3 -3
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings-advanced.md +7 -9
- package/gsd-core/workflows/settings-integrations.md +64 -31
- package/gsd-core/workflows/settings.md +69 -7
- package/gsd-core/workflows/ship.md +116 -50
- package/gsd-core/workflows/sketch-wrap-up.md +11 -17
- package/gsd-core/workflows/sketch.md +12 -18
- package/gsd-core/workflows/smart-entry.md +3 -5
- package/gsd-core/workflows/spec-phase.md +53 -13
- package/gsd-core/workflows/spike-wrap-up.md +7 -11
- package/gsd-core/workflows/spike.md +20 -31
- package/gsd-core/workflows/stats.md +2 -2
- package/gsd-core/workflows/sync-skills.md +64 -9
- package/gsd-core/workflows/thread.md +11 -7
- package/gsd-core/workflows/transition.md +49 -14
- package/gsd-core/workflows/ui-phase.md +15 -21
- package/gsd-core/workflows/ui-review.md +8 -12
- package/gsd-core/workflows/ultraplan-phase.md +5 -13
- package/gsd-core/workflows/undo.md +8 -16
- package/gsd-core/workflows/update.md +7 -11
- package/gsd-core/workflows/validate-phase.md +3 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +66 -25
- package/hooks/dist/gsd-agent-isolation-guard.js +158 -30
- package/hooks/dist/gsd-check-update-worker.js +56 -13
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-config-reload.js +18 -12
- package/hooks/dist/gsd-context-monitor.js +19 -10
- package/hooks/dist/gsd-cursor-post-tool.js +3 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +2 -3
- package/hooks/dist/gsd-cursor-session-start.js +2 -1
- package/hooks/dist/gsd-cursor-stop.js +2 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +83 -3
- package/hooks/dist/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
- package/hooks/dist/gsd-graphify-update.sh +22 -18
- package/hooks/dist/gsd-node-runner.sh +76 -0
- package/hooks/dist/gsd-phase-boundary.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +37 -27
- package/hooks/dist/gsd-read-guard.js +16 -7
- package/hooks/dist/gsd-read-injection-scanner.js +55 -32
- package/hooks/dist/gsd-session-state.sh +1 -0
- package/hooks/dist/gsd-statusline.js +231 -24
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-validate-commit.sh +80 -6
- package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
- package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
- package/hooks/dist/gsd-workflow-guard.js +162 -46
- package/hooks/dist/gsd-worktree-path-guard.js +36 -21
- package/hooks/dist/gsd-write-guard.js +35 -25
- package/hooks/dist/lib/cli-exit.js +560 -0
- package/hooks/dist/lib/exit-code-registry.js +98 -0
- package/hooks/dist/lib/git-cmd.js +92 -59
- package/hooks/dist/lib/git-probe.js +84 -0
- package/hooks/dist/lib/hook-exit.js +81 -0
- package/hooks/dist/lib/injection-patterns.js +45 -0
- package/hooks/dist/lib/isolation-deny-reason.js +39 -0
- package/hooks/dist/lib/isolation-sentinel.js +9 -0
- package/hooks/dist/managed-hooks-registry.cjs +3 -0
- package/hooks/gsd-agent-isolation-guard.js +158 -30
- package/hooks/gsd-check-update-worker.js +56 -13
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-config-reload.js +18 -12
- package/hooks/gsd-context-monitor.js +19 -10
- package/hooks/gsd-cursor-post-tool.js +3 -1
- package/hooks/gsd-cursor-pre-tool.js +2 -3
- package/hooks/gsd-cursor-session-start.js +2 -1
- package/hooks/gsd-cursor-stop.js +2 -1
- package/hooks/gsd-cursor-subagent-start.js +83 -3
- package/hooks/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/gsd-ensure-canonical-path.js +2 -1
- package/hooks/gsd-graphify-update.sh +22 -18
- package/hooks/gsd-node-runner.sh +76 -0
- package/hooks/gsd-phase-boundary.sh +1 -0
- package/hooks/gsd-prompt-guard.js +37 -27
- package/hooks/gsd-read-guard.js +16 -7
- package/hooks/gsd-read-injection-scanner.js +55 -32
- package/hooks/gsd-session-state.sh +1 -0
- package/hooks/gsd-statusline.js +231 -24
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-validate-commit.sh +80 -6
- package/hooks/gsd-windsurf-pre-command.js +16 -11
- package/hooks/gsd-windsurf-pre-write.js +22 -13
- package/hooks/gsd-workflow-guard.js +162 -46
- package/hooks/gsd-worktree-path-guard.js +36 -21
- package/hooks/gsd-write-guard.js +35 -25
- package/hooks/lib/cli-exit.js +560 -0
- package/hooks/lib/exit-code-registry.js +98 -0
- package/hooks/lib/git-cmd.js +92 -59
- package/hooks/lib/git-probe.js +84 -0
- package/hooks/lib/hook-exit.js +81 -0
- package/hooks/lib/injection-patterns.js +45 -0
- package/hooks/lib/isolation-deny-reason.js +39 -0
- package/hooks/lib/isolation-sentinel.js +9 -0
- package/hooks/managed-hooks-registry.cjs +3 -0
- package/package.json +28 -11
- package/pi/gsd.cjs +19 -5
- package/scripts/base64-scan.sh +74 -12
- package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
- package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
- package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
- package/scripts/build-hooks.js +5 -0
- package/scripts/changeset/lint.cjs +60 -5
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/check-glossary-refs.cjs +77 -15
- package/scripts/check-mutation-score-ratchet.cjs +156 -0
- package/scripts/ci-check-job-near-cap.cjs +49 -0
- package/scripts/ci-pr-mergeability.cjs +262 -0
- package/scripts/ci-test-scope.cjs +64 -14
- package/scripts/ci-timeout-report.cjs +230 -0
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/docs-guard-registry.cjs +396 -0
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-registry.cjs +11 -21
- package/scripts/gen-context-index.cjs +2 -11
- package/scripts/gen-exit-code-docs.cjs +318 -0
- package/scripts/gen-exit-code-registry.cjs +891 -0
- package/scripts/gen-features.cjs +836 -0
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-hooks-cli-exit.cjs +239 -0
- package/scripts/gen-install-tree-fixtures.cjs +2 -2
- package/scripts/gen-inventory-manifest.cjs +50 -4
- package/scripts/gen-loop-host-contract.cjs +138 -25
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/gen-scripts-cli-exit.cjs +185 -0
- package/scripts/gen-state-md-docs.cjs +727 -0
- package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/ci-job-timing.cjs +72 -0
- package/scripts/lib/cli-exit.cjs +546 -44
- package/scripts/lib/drift-scan.cjs +308 -0
- package/scripts/lib/exit-code-registry.cjs +98 -0
- package/scripts/lib/ndjson-reporter.cjs +119 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
- package/scripts/lint-canary-version-leak.cjs +73 -0
- package/scripts/lint-command-contract.cjs +96 -13
- package/scripts/lint-completion-predicate-drift.cjs +933 -0
- package/scripts/lint-completion-ratio-drift.cjs +214 -0
- package/scripts/lint-default-flip-documentation.cjs +193 -0
- package/scripts/lint-docs-guard-registration.cjs +495 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +38 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +461 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
- package/scripts/lint-phase-enumeration-drift.cjs +492 -0
- package/scripts/lint-plan-count-drift.cjs +318 -0
- package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
- package/scripts/lint-planning-prompt-drift.cjs +471 -0
- package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
- package/scripts/lint-regression-test-names.cjs +15 -13
- package/scripts/lint-removed-but-needed.cjs +488 -0
- package/scripts/lint-seam-enforcement.cjs +182 -0
- package/scripts/lint-slug-derivation-drift.cjs +921 -0
- package/scripts/lint-source-test-name-collision.cjs +241 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +950 -0
- package/scripts/lint-test-file-count.allowlist.json +137 -8
- package/scripts/lint-test-file-count.cjs +25 -3
- package/scripts/lint-unreachable-guard-drift.cjs +830 -0
- package/scripts/lint-vendored-deps.cjs +297 -0
- package/scripts/mutation-matrix.cjs +599 -50
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +100 -14
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/secret-scan.sh +75 -13
- package/scripts/select-docs-guards.cjs +56 -0
- package/scripts/sync-runtime-launcher.cjs +24 -7
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-discuss-phase/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- package/skills/gsd-import/SKILL.md +1 -1
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +0 -1
- package/skills/gsd-progress/SKILL.md +0 -1
- package/skills/gsd-quick/SKILL.md +9 -5
- package/skills/gsd-review-backlog/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +0 -1
- package/skills/gsd-verify-work/SKILL.md +1 -1
- package/vscode/package.json +1 -1
- package/bin/lib/ui-safety-gate.cjs +0 -107
- package/gsd-core/workflows/discovery-phase.md +0 -298
- package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
- package/gsd-core/workflows/verify-phase.md +0 -574
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/lint-emitted-drift-ack.cjs +0 -344
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1051
|
@@ -19,14 +19,66 @@ const modelProfiles = require("./model-profiles.cjs");
|
|
|
19
19
|
const { MODEL_PROFILES } = modelProfiles;
|
|
20
20
|
const runtime_homes_cjs_1 = require("./runtime-homes.cjs");
|
|
21
21
|
const runtime_name_policy_cjs_1 = require("./runtime-name-policy.cjs");
|
|
22
|
+
// #3242 — model-catalog is a genuine leaf (only node:path + its own JSON), which is
|
|
23
|
+
// exactly why Phase 1 (#3241) moved isAnthropicFlavoredModel there: this module can
|
|
24
|
+
// consume it without dragging model-resolver's config-loader chain into a
|
|
25
|
+
// pure read/verify surface.
|
|
26
|
+
const model_catalog_cjs_1 = require("./model-catalog.cjs");
|
|
27
|
+
// #3243 — the Codex `.toml` block-range/BOM/scan primitives moved into the typed
|
|
28
|
+
// IR module (Phase 3), which this reader now imports rather than defining
|
|
29
|
+
// locally. Behavior is unchanged: scanTomlLines/stripBOM here are the exact
|
|
30
|
+
// same lenient functions that used to live in this file — see
|
|
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.
|
|
46
|
+
const codex_agent_toml_cjs_1 = require("./codex-agent-toml.cjs");
|
|
47
|
+
/**
|
|
48
|
+
* Frozen reason enum for {@link checkCodexModelPosture}. Per CONTRIBUTING's
|
|
49
|
+
* typed-IR rule ("Error / status / reason → a frozen enum"): callers and tests
|
|
50
|
+
* assert on these wire values, never on prose. Adding a member is a deliberate
|
|
51
|
+
* three-way coordinated change — enum, emitting site, and the enum-lock test.
|
|
52
|
+
*/
|
|
53
|
+
const POSTURE_REASON = Object.freeze({
|
|
54
|
+
ANTHROPIC_FLAVORED_MODEL: 'anthropic_flavored_model',
|
|
55
|
+
ORPHANED_REASONING_EFFORT: 'orphaned_reasoning_effort',
|
|
56
|
+
UNREADABLE: 'unreadable',
|
|
57
|
+
NOT_CODEX: 'not_codex',
|
|
58
|
+
AGENTS_DIR_MISSING: 'agents_dir_missing',
|
|
59
|
+
});
|
|
60
|
+
// Matches the value-truncation convention in bin/install.js's
|
|
61
|
+
// _warnCodexModelOverrideDropped: values over 64 chars are capped so an
|
|
62
|
+
// oversized or secret-shaped config value can never reach a report in full.
|
|
63
|
+
function truncatePostureValue(value) {
|
|
64
|
+
return value.length > 64 ? `${value.slice(0, 64)}…` : value;
|
|
65
|
+
}
|
|
22
66
|
/**
|
|
23
67
|
* Resolve the agents directory for the given runtime.
|
|
24
68
|
*
|
|
25
69
|
* Priority:
|
|
26
70
|
* 1. GSD_AGENTS_DIR env var (explicit override, any runtime)
|
|
27
|
-
* 2. For claude runtime: __dirname-relative path (agents/ sibling of
|
|
28
|
-
*
|
|
29
|
-
* agents/
|
|
71
|
+
* 2. For claude runtime: __dirname-relative path (agents/ sibling of
|
|
72
|
+
* gsd-core/) — correct for repo runs and runtime-config-dir installs,
|
|
73
|
+
* where the sibling agents/ IS the user's agents dir — UNLESS that path
|
|
74
|
+
* carries an exact node_modules segment. gsd-tools.cjs lives inside
|
|
75
|
+
* gsd-core/bin/ in every install shape, but on an npm-global install
|
|
76
|
+
* gsd-core/ sits inside the package (not the runtime config dir) and the
|
|
77
|
+
* package ships its own agents/, so the install-relative path resolves
|
|
78
|
+
* to the bundled copy and the check validates the package against
|
|
79
|
+
* itself — agents_installed can never be false. In that case resolve
|
|
80
|
+
* getGlobalConfigDir('claude')/agents (honours CLAUDE_CONFIG_DIR) like
|
|
81
|
+
* every other runtime (#3203).
|
|
30
82
|
* 3. For non-claude runtimes with a manifest-backed project-local install:
|
|
31
83
|
* <projectRoot>/<localConfigDir>/agents (or <projectRoot>/agents when
|
|
32
84
|
* the runtime's local install targets the project root). Requiring the
|
|
@@ -43,7 +95,16 @@ function getAgentsDir(runtime, projectRoot) {
|
|
|
43
95
|
}
|
|
44
96
|
const resolved = runtime ?? (process.env['GSD_RUNTIME'] || 'claude');
|
|
45
97
|
if (resolved === 'claude') {
|
|
46
|
-
|
|
98
|
+
const installRelative = node_path_1.default.join(__dirname, '..', '..', '..', 'agents');
|
|
99
|
+
// #3203: a lexical guard, not an install-shape test. It targets the
|
|
100
|
+
// layouts where the sibling agents/ is the package's own bundled copy and
|
|
101
|
+
// the check would otherwise validate the package against itself; a path
|
|
102
|
+
// merely carrying a directory of that name resolves the same way, and a
|
|
103
|
+
// non-empty GSD_AGENTS_DIR overrides both.
|
|
104
|
+
if (installRelative.split(node_path_1.default.sep).includes('node_modules')) {
|
|
105
|
+
return node_path_1.default.join((0, runtime_homes_cjs_1.getGlobalConfigDir)('claude'), 'agents');
|
|
106
|
+
}
|
|
107
|
+
return installRelative;
|
|
47
108
|
}
|
|
48
109
|
if (projectRoot) {
|
|
49
110
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
@@ -94,18 +155,7 @@ function checkAgentsInstalled(runtime, projectRoot) {
|
|
|
94
155
|
};
|
|
95
156
|
}
|
|
96
157
|
for (const agent of expectedAgents) {
|
|
97
|
-
|
|
98
|
-
const agentFileCopilot = node_path_1.default.join(agentsDir, `${agent}.agent.md`);
|
|
99
|
-
const agentFileCodex = node_path_1.default.join(agentsDir, `${agent}.toml`);
|
|
100
|
-
const agentFileKimiYaml = node_path_1.default.join(agentsDir, 'subagents', `${agent}.yaml`);
|
|
101
|
-
const agentFileKimiPrompt = node_path_1.default.join(agentsDir, 'subagents', `${agent}.md`);
|
|
102
|
-
const kimiAgentInstalled = resolvedRuntime === 'kimi' &&
|
|
103
|
-
node_fs_1.default.existsSync(agentFileKimiYaml) &&
|
|
104
|
-
node_fs_1.default.existsSync(agentFileKimiPrompt);
|
|
105
|
-
if (node_fs_1.default.existsSync(agentFile) ||
|
|
106
|
-
node_fs_1.default.existsSync(agentFileCopilot) ||
|
|
107
|
-
node_fs_1.default.existsSync(agentFileCodex) ||
|
|
108
|
-
kimiAgentInstalled) {
|
|
158
|
+
if (agentFileExists(agentsDir, agent, resolvedRuntime)) {
|
|
109
159
|
installed.push(agent);
|
|
110
160
|
}
|
|
111
161
|
else {
|
|
@@ -119,22 +169,13 @@ function checkAgentsInstalled(runtime, projectRoot) {
|
|
|
119
169
|
// when the plain presence check above passed (e.g. .md present, .toml absent).
|
|
120
170
|
// If no manifest is found the check is a no-op (graceful for claude/bundled).
|
|
121
171
|
const incomplete = [];
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
'files' in parsed &&
|
|
130
|
-
typeof parsed['files'] === 'object' &&
|
|
131
|
-
parsed['files'] !== null) {
|
|
132
|
-
manifestFiles = parsed['files'];
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
catch {
|
|
136
|
-
// No manifest or unreadable — completeness check is skipped
|
|
137
|
-
}
|
|
172
|
+
// #2872: the manifest read is the Installer Migration Module's, not a
|
|
173
|
+
// fourth private copy of it. Lazily required — matching this file's own
|
|
174
|
+
// capability-registry idiom — so a pure read/verify surface on the
|
|
175
|
+
// init/verify hot path takes no new static dependency.
|
|
176
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
177
|
+
const { readInstallManifest } = require('./installer-migrations.cjs');
|
|
178
|
+
const manifestFiles = readInstallManifest(node_path_1.default.dirname(agentsDir)).files;
|
|
138
179
|
if (Object.keys(manifestFiles).length > 0) {
|
|
139
180
|
for (const agent of expectedAgents) {
|
|
140
181
|
// Find all manifest keys that belong to this agent:
|
|
@@ -169,7 +210,326 @@ function checkAgentsInstalled(runtime, projectRoot) {
|
|
|
169
210
|
agent_runtime: resolvedRuntime,
|
|
170
211
|
};
|
|
171
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* Validate Codex `.toml` agent files for Anthropic-flavored `model` pins and
|
|
215
|
+
* orphaned `model_reasoning_effort` values (ADR-2313 D6, #3242).
|
|
216
|
+
*
|
|
217
|
+
* A new sibling export to {@link checkAgentsInstalled}, deliberately — that
|
|
218
|
+
* function carries 33 upstream dependents and cyclomatic complexity 25, so this
|
|
219
|
+
* posture check gets zero new branches there (see 40-design.md "Rejected" #1).
|
|
220
|
+
* Presence is `checkAgentsInstalled`'s job; this function's job starts only once
|
|
221
|
+
* the runtime is confirmed `codex` and only inspects posture, never presence.
|
|
222
|
+
*
|
|
223
|
+
* Read-only: detects, never repairs (repair is Phase 3, #3243).
|
|
224
|
+
*
|
|
225
|
+
* @param runtime - the active runtime name; defaults to GSD_RUNTIME env, then 'claude'
|
|
226
|
+
* @param projectRoot - canonical project root for local-install discovery
|
|
227
|
+
*/
|
|
228
|
+
function checkCodexModelPosture(runtime, projectRoot) {
|
|
229
|
+
// Short-circuit BEFORE any filesystem access: a non-codex runtime must never
|
|
230
|
+
// have its agents directory resolved or a stray .toml inspected, however
|
|
231
|
+
// violating that file's contents would be if it were ever read (#3242 row 25).
|
|
232
|
+
const resolvedRuntime = runtime ?? (process.env['GSD_RUNTIME'] || 'claude');
|
|
233
|
+
if (resolvedRuntime !== 'codex') {
|
|
234
|
+
return {
|
|
235
|
+
ok: true,
|
|
236
|
+
violations: [],
|
|
237
|
+
checked: [],
|
|
238
|
+
agents_dir: '',
|
|
239
|
+
agent_runtime: resolvedRuntime,
|
|
240
|
+
reason: POSTURE_REASON.NOT_CODEX,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
const agentsDir = getAgentsDir(resolvedRuntime, projectRoot);
|
|
244
|
+
if (!node_fs_1.default.existsSync(agentsDir)) {
|
|
245
|
+
// Presence is checkAgentsInstalled's job — an absent agents dir here is a
|
|
246
|
+
// distinct, non-violating outcome, not a failure of this check.
|
|
247
|
+
return {
|
|
248
|
+
ok: true,
|
|
249
|
+
violations: [],
|
|
250
|
+
checked: [],
|
|
251
|
+
agents_dir: agentsDir,
|
|
252
|
+
agent_runtime: resolvedRuntime,
|
|
253
|
+
reason: POSTURE_REASON.AGENTS_DIR_MISSING,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
// Skip symlinks — matches cmdEffortSync's existing idiom in commands.cts
|
|
257
|
+
// ("Skip symlinks — only write regular files..."). Here the risk is reading
|
|
258
|
+
// (not writing) through a symlink: readFileSync follows symlinks, so an
|
|
259
|
+
// agents-dir symlink pointing at an arbitrary file would let that target's
|
|
260
|
+
// contents be echoed into this function's `value` field. A symlinked agent
|
|
261
|
+
// file is a structural install choice (checkAgentsInstalled's territory),
|
|
262
|
+
// not a model-content posture defect, so it is silently excluded from
|
|
263
|
+
// `checked` rather than reported as a distinct violation — same shape as
|
|
264
|
+
// cmdEffortSync, which silently drops symlinks from its file list rather
|
|
265
|
+
// than inventing a new skip/violation reason.
|
|
266
|
+
const tomlFiles = node_fs_1.default
|
|
267
|
+
.readdirSync(agentsDir)
|
|
268
|
+
.filter((entry) => {
|
|
269
|
+
if (!entry.endsWith('.toml'))
|
|
270
|
+
return false;
|
|
271
|
+
try {
|
|
272
|
+
return node_fs_1.default.lstatSync(node_path_1.default.join(agentsDir, entry)).isFile();
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
})
|
|
278
|
+
.sort();
|
|
279
|
+
const checked = [];
|
|
280
|
+
const violations = [];
|
|
281
|
+
for (const entry of tomlFiles) {
|
|
282
|
+
const agentName = entry.slice(0, -'.toml'.length);
|
|
283
|
+
const filePath = node_path_1.default.join(agentsDir, entry);
|
|
284
|
+
checked.push(agentName);
|
|
285
|
+
let raw;
|
|
286
|
+
try {
|
|
287
|
+
raw = node_fs_1.default.readFileSync(filePath, 'utf8');
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
// Never throws, never silently skips — an unreadable file is reported and
|
|
291
|
+
// the loop continues checking the rest (40-design.md "Rejected" #5).
|
|
292
|
+
violations.push({ agent: agentName, file: filePath, reason: POSTURE_REASON.UNREADABLE });
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
const { model, hasReasoningEffort } = (0, codex_agent_toml_cjs_1.scanTomlLines)((0, codex_agent_toml_cjs_1.stripBOM)(raw));
|
|
296
|
+
if (model !== null && (0, model_catalog_cjs_1.isAnthropicFlavoredModel)(model)) {
|
|
297
|
+
violations.push({
|
|
298
|
+
agent: agentName,
|
|
299
|
+
file: filePath,
|
|
300
|
+
reason: POSTURE_REASON.ANTHROPIC_FLAVORED_MODEL,
|
|
301
|
+
value: truncatePostureValue(model),
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
else if (model === null && hasReasoningEffort) {
|
|
305
|
+
// #838 coupling: a reasoning-effort pin with no model pin means Codex
|
|
306
|
+
// inherits the session model while the effort pin silently disagrees.
|
|
307
|
+
violations.push({
|
|
308
|
+
agent: agentName,
|
|
309
|
+
file: filePath,
|
|
310
|
+
reason: POSTURE_REASON.ORPHANED_REASONING_EFFORT,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
ok: violations.length === 0,
|
|
316
|
+
violations,
|
|
317
|
+
checked,
|
|
318
|
+
agents_dir: agentsDir,
|
|
319
|
+
agent_runtime: resolvedRuntime,
|
|
320
|
+
};
|
|
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
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Probe a single agents dir for `<name>` across runtime filename variants.
|
|
471
|
+
* Mirrors {@link checkAgentsInstalled}'s probe (`.md`, `.agent.md`, `.toml`,
|
|
472
|
+
* and the kimi `subagents/<name>.{yaml,md}` pair) so the two can never disagree
|
|
473
|
+
* about which on-disk shapes count as "installed". Not exported — internal to
|
|
474
|
+
* {@link resolveAgentHint}.
|
|
475
|
+
*/
|
|
476
|
+
function agentFileExists(agentsDir, name, runtime) {
|
|
477
|
+
const base = node_path_1.default.join(agentsDir, `${name}.md`);
|
|
478
|
+
const copilot = node_path_1.default.join(agentsDir, `${name}.agent.md`);
|
|
479
|
+
const codex = node_path_1.default.join(agentsDir, `${name}.toml`);
|
|
480
|
+
if (node_fs_1.default.existsSync(base) || node_fs_1.default.existsSync(copilot) || node_fs_1.default.existsSync(codex)) {
|
|
481
|
+
return true;
|
|
482
|
+
}
|
|
483
|
+
// kimi requires BOTH the persona yaml and the prompt md (same as checkAgentsInstalled).
|
|
484
|
+
const kimiYaml = node_path_1.default.join(agentsDir, 'subagents', `${name}.yaml`);
|
|
485
|
+
const kimiPrompt = node_path_1.default.join(agentsDir, 'subagents', `${name}.md`);
|
|
486
|
+
return runtime === 'kimi' && node_fs_1.default.existsSync(kimiYaml) && node_fs_1.default.existsSync(kimiPrompt);
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Resolve a per-plan `agent_hint` specialist name to a dispatchable subagent
|
|
490
|
+
* type on the active runtime (#1689). Unlike {@link checkAgentsInstalled},
|
|
491
|
+
* which validates the fixed GSD roster, this answers "does an agent file for
|
|
492
|
+
* this ARBITRARY name exist in the active runtime's agent dir(s)?" — so a plan
|
|
493
|
+
* can opt into a domain specialist (e.g. a Flutter engineer) that shares the
|
|
494
|
+
* gsd-executor contract without being part of the built-in roster.
|
|
495
|
+
*
|
|
496
|
+
* Probes BOTH the runtime-canonical agents dir ({@link getAgentsDir}, which
|
|
497
|
+
* honors `GSD_AGENTS_DIR`, project-local manifest-backed installs, and the
|
|
498
|
+
* claude install-relative path) AND the runtime's global config agents dir, so
|
|
499
|
+
* a specialist installed at either level is recognized. The decision in #1689
|
|
500
|
+
* explicitly requires consulting the active runtime's agent dir rather than
|
|
501
|
+
* only the Claude runtime's user-global and project-local agent dirs.
|
|
502
|
+
*
|
|
503
|
+
* @returns the name when a matching agent file exists; `null` when it does not
|
|
504
|
+
* (the caller falls back to `gsd-executor`). An empty/whitespace name always
|
|
505
|
+
* returns `null`.
|
|
506
|
+
*/
|
|
507
|
+
function resolveAgentHint(name, runtime, projectRoot) {
|
|
508
|
+
const trimmed = String(name ?? '').trim();
|
|
509
|
+
if (trimmed === '')
|
|
510
|
+
return null;
|
|
511
|
+
// A hint is a bare agent name. Reject path separators and `..` so a value
|
|
512
|
+
// like `../../README` cannot path-traverse out of the agents dir via
|
|
513
|
+
// path.join and match an unrelated file — that would echo an invalid
|
|
514
|
+
// subagent_type and block the wave, defeating fail-closed resolution.
|
|
515
|
+
if (trimmed.includes('/') || trimmed.includes('\\') || trimmed.includes('..'))
|
|
516
|
+
return null;
|
|
517
|
+
const resolvedRuntime = runtime ?? (process.env['GSD_RUNTIME'] || 'claude');
|
|
518
|
+
const candidateDirs = new Set();
|
|
519
|
+
candidateDirs.add(getAgentsDir(resolvedRuntime, projectRoot));
|
|
520
|
+
candidateDirs.add(node_path_1.default.join((0, runtime_homes_cjs_1.getGlobalConfigDir)(resolvedRuntime), 'agents'));
|
|
521
|
+
for (const dir of candidateDirs) {
|
|
522
|
+
if (agentFileExists(dir, trimmed, resolvedRuntime)) {
|
|
523
|
+
return trimmed;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
return null;
|
|
527
|
+
}
|
|
172
528
|
module.exports = {
|
|
173
529
|
getAgentsDir,
|
|
174
530
|
checkAgentsInstalled,
|
|
531
|
+
checkCodexModelPosture,
|
|
532
|
+
checkCodexSandboxPosture,
|
|
533
|
+
POSTURE_REASON,
|
|
534
|
+
resolveAgentHint,
|
|
175
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;
|
|
@@ -63,6 +67,7 @@ exports.parseCoverageMatrix = parseCoverageMatrix;
|
|
|
63
67
|
exports.validateCoverageMatrix = validateCoverageMatrix;
|
|
64
68
|
exports.renderCoverageMatrix = renderCoverageMatrix;
|
|
65
69
|
const markdown_sectionizer_cjs_1 = require("./markdown-sectionizer.cjs");
|
|
70
|
+
const pattern_cjs_1 = require("./pattern.cjs");
|
|
66
71
|
/**
|
|
67
72
|
* Curated default trigger vocabulary. ADDITIVE-ONLY (Hyrum's Law). Tunable via
|
|
68
73
|
* the `terms` parameter.
|
|
@@ -156,9 +161,6 @@ function resolveTerms(terms) {
|
|
|
156
161
|
};
|
|
157
162
|
return { verbs: merge('verbs'), nouns: merge('nouns') };
|
|
158
163
|
}
|
|
159
|
-
function escapeRegex(s) {
|
|
160
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
161
|
-
}
|
|
162
164
|
function makeSnippet(line, anchor) {
|
|
163
165
|
const cleaned = line.replace(/\s+/g, ' ').trim();
|
|
164
166
|
if (cleaned.length <= 120)
|
|
@@ -402,10 +404,10 @@ function detectApiIntegration(text, terms) {
|
|
|
402
404
|
// Trailing boundary is a LOOKAHEAD (not consumed) so back-to-back terms
|
|
403
405
|
// separated by one boundary char are both found.
|
|
404
406
|
const verbRe = hasCompoundTerms
|
|
405
|
-
? new RegExp('(^|[^a-zA-Z0-9])(' + effective.verbs.map(escapeRegex).join('|') + ')(?=[^a-zA-Z0-9]|$)', 'gi')
|
|
407
|
+
? new RegExp('(^|[^a-zA-Z0-9])(' + effective.verbs.map(pattern_cjs_1.escapeRegex).join('|') + ')(?=[^a-zA-Z0-9]|$)', 'gi')
|
|
406
408
|
: null;
|
|
407
409
|
const nounRe = hasCompoundTerms
|
|
408
|
-
? new RegExp('(^|[^a-zA-Z0-9])(' + effective.nouns.map(escapeRegex).join('|') + ')(?=[^a-zA-Z0-9]|$)', 'gi')
|
|
410
|
+
? new RegExp('(^|[^a-zA-Z0-9])(' + effective.nouns.map(pattern_cjs_1.escapeRegex).join('|') + ')(?=[^a-zA-Z0-9]|$)', 'gi')
|
|
409
411
|
: null;
|
|
410
412
|
const surfaceRe = new RegExp(SERVICE_SURFACE_API_RE.source, 'g');
|
|
411
413
|
const nounSet = new Set(effective.nouns);
|
|
@@ -851,11 +853,24 @@ function renderCoverageMatrix(rows) {
|
|
|
851
853
|
// ── CLI entry point ──────────────────────────────────────────────────────────
|
|
852
854
|
// Reads phase-scope text from STDIN (not argv) to avoid OS ARG_MAX limits.
|
|
853
855
|
// Invoked by workflow bash as: echo "$SCOPE" | node .../api-coverage.cjs [--json]
|
|
854
|
-
//
|
|
855
|
-
//
|
|
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.
|
|
856
869
|
if (require.main === module) {
|
|
857
870
|
const argv = process.argv.slice(2);
|
|
858
871
|
const wantJson = argv.includes('--json');
|
|
872
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
873
|
+
const cliExit = require('./cli-exit.cjs');
|
|
859
874
|
let termsOverride;
|
|
860
875
|
const verbsIdx = argv.indexOf('--verbs');
|
|
861
876
|
const verbsVal = verbsIdx !== -1 ? argv[verbsIdx + 1] : undefined;
|
|
@@ -879,14 +894,18 @@ if (require.main === module) {
|
|
|
879
894
|
process.stdin.on('data', (chunk) => chunks.push(chunk));
|
|
880
895
|
process.stdin.on('end', () => {
|
|
881
896
|
const input = chunks.join('');
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
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);
|
|
885
903
|
}
|
|
886
|
-
|
|
904
|
+
const result = detectApiIntegration(input, termsOverride);
|
|
905
|
+
cliExit.terminateNow(result.detected ? 'PASS' : 'FAIL', wantJson ? result : undefined);
|
|
887
906
|
});
|
|
888
907
|
process.stdin.on('error', (err) => {
|
|
889
908
|
process.stderr.write(`ERROR: api-coverage.cjs stdin read failed: ${err.message}\n`);
|
|
890
|
-
|
|
909
|
+
cliExit.terminateNow('UNAVAILABLE', wantJson ? { skipped: true, reason: 'stdin_error' } : undefined);
|
|
891
910
|
});
|
|
892
911
|
}
|
|
@@ -27,6 +27,11 @@ exports.CANONICAL_EXACT = new Set([
|
|
|
27
27
|
'config.json',
|
|
28
28
|
'CLAUDE.md',
|
|
29
29
|
'RETROSPECTIVE.md',
|
|
30
|
+
'WINDOWS.md', // #3224: broken-windows ledger (src/broken-windows.cts, LEDGER_FILE_NAME)
|
|
31
|
+
'STATE-ARCHIVE.md', // state.cts's cmdStatePrune writes this at the .planning/ root
|
|
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)
|
|
30
35
|
]);
|
|
31
36
|
// Pattern-match canonical file names (regex tests on the basename)
|
|
32
37
|
// Each pattern includes the name of the workflow that produces it as a comment.
|