@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
|
@@ -117,6 +117,47 @@ function statOrNull(p) {
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Collect `<dir>/<subdir>/<file>` entries as `<subdir>/<file>` keys — ONE level of
|
|
122
|
+
* subdirectory beneath `dir` itself, where the subdirectory's NAME is the thing being
|
|
123
|
+
* collected (unlike `collectNested`, there is no fixed subdir name to look for; every
|
|
124
|
+
* child directory of `dir` is scanned). This is what makes `gsd-core/bin/lib/<subdir>/*.cjs`
|
|
125
|
+
* (e.g. `health-diagnostic-rules/`, `installer-migrations/`, `host-integration-adapters/`,
|
|
126
|
+
* `observability/`) visible to the `cli_modules` family, mirroring the shape
|
|
127
|
+
* `docs/INVENTORY.md`'s CLI Modules table already uses for these files.
|
|
128
|
+
*
|
|
129
|
+
* Same defensive `statOrNull`-based style as `collectNested`: a stat/readdir failure on
|
|
130
|
+
* one entry is swallowed rather than thrown, so one unreadable subdirectory cannot take
|
|
131
|
+
* down `--check` for the whole repo.
|
|
132
|
+
*/
|
|
133
|
+
function collectOneLevelSubdirs({ dir, filter }) {
|
|
134
|
+
if (!fs.existsSync(dir)) return [];
|
|
135
|
+
const out = [];
|
|
136
|
+
let children;
|
|
137
|
+
try {
|
|
138
|
+
children = fs.readdirSync(dir);
|
|
139
|
+
} catch {
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
142
|
+
for (const child of children) {
|
|
143
|
+
const childStat = statOrNull(path.join(dir, child));
|
|
144
|
+
if (!childStat || !childStat.isDirectory()) continue;
|
|
145
|
+
const subdirPath = path.join(dir, child);
|
|
146
|
+
let files;
|
|
147
|
+
try {
|
|
148
|
+
files = fs.readdirSync(subdirPath);
|
|
149
|
+
} catch {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
for (const file of files) {
|
|
153
|
+
const fileStat = statOrNull(path.join(subdirPath, file));
|
|
154
|
+
if (!fileStat || !fileStat.isFile() || !filter(file)) continue;
|
|
155
|
+
out.push([child, file].join('/'));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return out.sort();
|
|
159
|
+
}
|
|
160
|
+
|
|
120
161
|
function collectNested({ root, subdir, filter }) {
|
|
121
162
|
if (!fs.existsSync(root)) return [];
|
|
122
163
|
const out = [];
|
|
@@ -150,11 +191,16 @@ function collectNested({ root, subdir, filter }) {
|
|
|
150
191
|
function buildManifest() {
|
|
151
192
|
const manifest = { families: {} };
|
|
152
193
|
for (const { name, dir, filter, toName } of FAMILIES) {
|
|
153
|
-
|
|
194
|
+
const flat = fs
|
|
154
195
|
.readdirSync(dir)
|
|
155
196
|
.filter((f) => fs.statSync(path.join(dir, f)).isFile() && filter(f))
|
|
156
|
-
.map(toName)
|
|
157
|
-
|
|
197
|
+
.map(toName);
|
|
198
|
+
// `cli_modules` also ships subdirectory modules (`health-diagnostic-rules/`,
|
|
199
|
+
// `installer-migrations/`, `host-integration-adapters/`, `observability/`) invisible to
|
|
200
|
+
// the flat readdirSync above; merge them into the SAME sorted array, matching the single
|
|
201
|
+
// "CLI Modules" table shape docs/INVENTORY.md already uses (#3309).
|
|
202
|
+
const nested = name === 'cli_modules' ? collectOneLevelSubdirs({ dir, filter }) : [];
|
|
203
|
+
manifest.families[name] = [...flat, ...nested].sort();
|
|
158
204
|
}
|
|
159
205
|
for (const family of NESTED_FAMILIES) {
|
|
160
206
|
manifest.families[family.name] = collectNested(family);
|
|
@@ -209,4 +255,4 @@ if (require.main === module) {
|
|
|
209
255
|
// `DEFECT.GENERATIVE-FIX` divergence class: adding a family here while the test kept
|
|
210
256
|
// its own list meant the test silently verified fewer families than shipped, and still
|
|
211
257
|
// passed. The test now imports these, so the two surfaces cannot drift.
|
|
212
|
-
module.exports = { FAMILIES, NESTED_FAMILIES, collectNested, buildManifest };
|
|
258
|
+
module.exports = { FAMILIES, NESTED_FAMILIES, collectNested, collectOneLevelSubdirs, buildManifest };
|
|
@@ -20,6 +20,8 @@ const fs = require('node:fs');
|
|
|
20
20
|
const path = require('node:path');
|
|
21
21
|
|
|
22
22
|
const { ExitError, runMain } = require('./lib/cli-exit.cjs');
|
|
23
|
+
const { escapeRegex: escapeRegExp } = require('../gsd-core/bin/lib/pattern.cjs');
|
|
24
|
+
const { normalizeEol } = require('../gsd-core/bin/lib/text-lines.cjs');
|
|
23
25
|
|
|
24
26
|
const ROOT = path.resolve(__dirname, '..');
|
|
25
27
|
const WORKFLOWS_DIR = path.join(ROOT, 'gsd-core', 'workflows');
|
|
@@ -191,13 +193,6 @@ function parseLoopHostBlock(content, fileName) {
|
|
|
191
193
|
* @param {string} fileName For error messages
|
|
192
194
|
* @returns {string[]} Array of error strings; empty = OK
|
|
193
195
|
*/
|
|
194
|
-
/**
|
|
195
|
-
* Escape a string for literal use in a RegExp.
|
|
196
|
-
*/
|
|
197
|
-
function escapeRegExp(s) {
|
|
198
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
199
|
-
}
|
|
200
|
-
|
|
201
196
|
function crossCheckRoles(content, agentRoles, fileName) {
|
|
202
197
|
const errors = [];
|
|
203
198
|
for (const role of agentRoles) {
|
|
@@ -375,21 +370,6 @@ function serializeContract(contract) {
|
|
|
375
370
|
return lines.join('\n');
|
|
376
371
|
}
|
|
377
372
|
|
|
378
|
-
// ─── --check diff helper ──────────────────────────────────────────────────────
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Normalize line endings to LF for CRLF-agnostic comparison.
|
|
382
|
-
* FIX 4: The serializer has no nondeterministic content (no timestamp), so
|
|
383
|
-
* the generated-by-line stripping that was here has been removed — full content
|
|
384
|
-
* comparison is now used so header drift is caught by --check.
|
|
385
|
-
*
|
|
386
|
-
* @param {string} content
|
|
387
|
-
* @returns {string}
|
|
388
|
-
*/
|
|
389
|
-
function normalizeLineEndings(content) {
|
|
390
|
-
return content.replace(/\r/g, '');
|
|
391
|
-
}
|
|
392
|
-
|
|
393
373
|
// ─── Main ─────────────────────────────────────────────────────────────────────
|
|
394
374
|
|
|
395
375
|
function main() {
|
|
@@ -415,7 +395,7 @@ function main() {
|
|
|
415
395
|
|
|
416
396
|
const committed = fs.readFileSync(CONTRACT_PATH, 'utf8');
|
|
417
397
|
// FIX 4: Compare full content (no generated-by stripping) so header drift is caught.
|
|
418
|
-
if (
|
|
398
|
+
if (normalizeEol(committed) !== normalizeEol(live)) {
|
|
419
399
|
process.stderr.write(
|
|
420
400
|
'gsd-core/bin/lib/loop-host-contract.cjs is stale. Run:\n' +
|
|
421
401
|
' node scripts/gen-loop-host-contract.cjs --write\n',
|
|
@@ -466,8 +446,11 @@ const HOST_LOOP_FILES = STEP_WORKFLOWS.map((w) => 'gsd-core/workflows/' + w.file
|
|
|
466
446
|
* @param {string} text Content of a workflow file (or any text).
|
|
467
447
|
* @returns {Set<string>}
|
|
468
448
|
*/
|
|
449
|
+
/** The call-site shape both scanners key on — one regex, two consumers (#3606). */
|
|
450
|
+
const CALL_SITE_RE = /loop render-hooks\s+([a-z:]+)/g;
|
|
451
|
+
|
|
469
452
|
function scanWiredPoints(text) {
|
|
470
|
-
const re =
|
|
453
|
+
const re = CALL_SITE_RE;
|
|
471
454
|
const result = new Set();
|
|
472
455
|
let m;
|
|
473
456
|
while ((m = re.exec(text)) !== null) {
|
|
@@ -476,6 +459,132 @@ function scanWiredPoints(text) {
|
|
|
476
459
|
return result;
|
|
477
460
|
}
|
|
478
461
|
|
|
462
|
+
// ─── Hook-kind coverage (#3606) ──────────────────────────────────────────────
|
|
463
|
+
|
|
464
|
+
const HOOK_KINDS = ['contribution', 'step', 'gate'];
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* The kinds one call site's dispatch text actually covers (#3606).
|
|
468
|
+
*
|
|
469
|
+
* A point having a `loop render-hooks <point>` call site proves the hooks are
|
|
470
|
+
* RENDERED, not that they are DISPATCHED — a consumer that iterates only
|
|
471
|
+
* `kind == "gate"` (or narrows `kind == "step"` to one `ref.skill`) silently
|
|
472
|
+
* drops every other registered kind. Coverage rules for the text following a
|
|
473
|
+
* call site, up to the next call site or the region cap, judged LINE by line:
|
|
474
|
+
*
|
|
475
|
+
* - A deferral line (one carrying an `@`-included path to the generic
|
|
476
|
+
* contract, e.g. `@gsd-core/references/loop-hook-dispatch.md`) that names a
|
|
477
|
+
* kind (`kind == "step"`) covers that kind; a deferral line with no kind
|
|
478
|
+
* discriminator ("apply each entry") covers every kind. A bare §-citation
|
|
479
|
+
* of the reference (validation guidance only, no `@`) covers nothing —
|
|
480
|
+
* plan-phase cites the gate-validation section while dispatching only gates.
|
|
481
|
+
* - Otherwise a kind is covered when some LINE dispatches it unconditionally:
|
|
482
|
+
* a `kind == "<kind>"` discriminator with NO same-line narrowing to one
|
|
483
|
+
* hook (`ref.skill ==`, `ref.agent ==`, `ref.command ==`). A narrowed line
|
|
484
|
+
* special-cases ONE hook and proves nothing about the kind generally — the
|
|
485
|
+
* exact hand-rolled-consumer shape the reference warns about.
|
|
486
|
+
*
|
|
487
|
+
* Quote style and spacing vary across the corpus (`kind == "step"`,
|
|
488
|
+
* `kind === 'gate'`), so the matcher is tolerant of both quote characters and
|
|
489
|
+
* of `==`/`===`.
|
|
490
|
+
*
|
|
491
|
+
* Pure: same input, same output; CRLF-safe (line splitting tolerates \r).
|
|
492
|
+
*
|
|
493
|
+
* @param {string} region Dispatch text following one call site.
|
|
494
|
+
* @returns {Set<string>}
|
|
495
|
+
*/
|
|
496
|
+
function coveredKindsInRegion(region) {
|
|
497
|
+
const covered = new Set();
|
|
498
|
+
// Same-SEGMENT narrowing to ONE hook voids credit: `ref.skill ==`, `capId ==`,
|
|
499
|
+
// and `into ==` each special-case a subset, not the kind generally
|
|
500
|
+
// (plan-phase's `kind == "contribution" and capId == "security"` is the
|
|
501
|
+
// hand-rolled shape; `into == "planner"` covers only planner-targeted
|
|
502
|
+
// contributions). Segments, not lines: execute-phase legitimately writes
|
|
503
|
+
// "dispatch `kind == "step"` hooks per … . `ref.skill == "code-review"`:" —
|
|
504
|
+
// the deferral is one sentence, the specialization the next; narrowing in a
|
|
505
|
+
// DIFFERENT segment must not void the deferral's credit.
|
|
506
|
+
const narrowingRe = /(?:ref\.(?:skill|agent|command)|capId|into)\s*={2,3}/;
|
|
507
|
+
// Negated mentions describe an absence, not a dispatch ("Branch 1 — no active
|
|
508
|
+
// step hooks (`activeHooks` has no entry with `kind == "step"`)" — ship.md).
|
|
509
|
+
const negationRe = /\b(?:no|without|absent|lacks?|missing)\b[^.|]*kind\s*={2,3}/;
|
|
510
|
+
const deferralRe = /@\S*loop-hook-dispatch\.md/;
|
|
511
|
+
for (const line of region.split(/\r?\n/)) {
|
|
512
|
+
// Sentence segments: a `.`/`;` followed by whitespace ends a segment. A
|
|
513
|
+
// period NOT followed by whitespace (the `.md` inside a deferral path,
|
|
514
|
+
// `ref.skill`) is not a boundary.
|
|
515
|
+
for (const segment of line.split(/(?<=[.;])\s+/)) {
|
|
516
|
+
const kindDiscriminators = [];
|
|
517
|
+
for (const kind of HOOK_KINDS) {
|
|
518
|
+
if (new RegExp(`kind\\s*={2,3}\\s*["']${kind}["']`).test(segment)) kindDiscriminators.push(kind);
|
|
519
|
+
}
|
|
520
|
+
if (kindDiscriminators.length === 0) {
|
|
521
|
+
// A deferral with no kind discriminator ("apply each entry per …")
|
|
522
|
+
// still covers every kind.
|
|
523
|
+
if (deferralRe.test(segment)) for (const kind of HOOK_KINDS) covered.add(kind);
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
if (negationRe.test(segment)) continue;
|
|
527
|
+
if (deferralRe.test(segment)) {
|
|
528
|
+
// Deferral naming kinds ("dispatch `kind == "step"` hooks per …").
|
|
529
|
+
if (!narrowingRe.test(segment)) for (const kind of kindDiscriminators) covered.add(kind);
|
|
530
|
+
continue;
|
|
531
|
+
}
|
|
532
|
+
if (!narrowingRe.test(segment)) for (const kind of kindDiscriminators) covered.add(kind);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
return covered;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Scan every `loop render-hooks <point>` call site in `text` and accumulate,
|
|
540
|
+
* per point, the union of hook kinds its dispatch regions cover (#3606).
|
|
541
|
+
*
|
|
542
|
+
* @param {string} text Content of a workflow file (or any text).
|
|
543
|
+
* @returns {Map<string, Set<string>>} point → covered kinds.
|
|
544
|
+
*/
|
|
545
|
+
function scanWiredKinds(text) {
|
|
546
|
+
const result = new Map();
|
|
547
|
+
const siteRe = CALL_SITE_RE;
|
|
548
|
+
const sites = [];
|
|
549
|
+
let m;
|
|
550
|
+
while ((m = siteRe.exec(text)) !== null) sites.push({ point: m[1], start: m.index });
|
|
551
|
+
const REGION_CAP = 6000;
|
|
552
|
+
for (let i = 0; i < sites.length; i++) {
|
|
553
|
+
const regionEnd = i + 1 < sites.length ? sites[i + 1].start : Math.min(text.length, sites[i].start + REGION_CAP);
|
|
554
|
+
const region = text.slice(sites[i].start, regionEnd);
|
|
555
|
+
const covered = coveredKindsInRegion(region);
|
|
556
|
+
if (!result.has(sites[i].point)) result.set(sites[i].point, new Set());
|
|
557
|
+
for (const kind of covered) result.get(sites[i].point).add(kind);
|
|
558
|
+
}
|
|
559
|
+
return result;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Read every host-loop workflow file and return, per point, the union of hook
|
|
564
|
+
* kinds its call sites' dispatch text covers (#3606).
|
|
565
|
+
*
|
|
566
|
+
* @param {string} [repoRoot] Path to the repository root. Defaults to ROOT.
|
|
567
|
+
* @returns {Map<string, Set<string>>}
|
|
568
|
+
*/
|
|
569
|
+
function getWiredKinds(repoRoot) {
|
|
570
|
+
const resolvedRoot = repoRoot !== undefined ? repoRoot : ROOT;
|
|
571
|
+
const result = new Map();
|
|
572
|
+
for (const relPath of HOST_LOOP_FILES) {
|
|
573
|
+
const absPath = path.join(resolvedRoot, relPath);
|
|
574
|
+
let content;
|
|
575
|
+
try {
|
|
576
|
+
content = fs.readFileSync(absPath, 'utf8');
|
|
577
|
+
} catch (err) {
|
|
578
|
+
throw new Error('getWiredKinds: cannot read host-loop file ' + absPath + ': ' + err.message);
|
|
579
|
+
}
|
|
580
|
+
for (const [point, kinds] of scanWiredKinds(content)) {
|
|
581
|
+
if (!result.has(point)) result.set(point, new Set());
|
|
582
|
+
for (const kind of kinds) result.get(point).add(kind);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
return result;
|
|
586
|
+
}
|
|
587
|
+
|
|
479
588
|
/**
|
|
480
589
|
* Read every host-loop workflow file and return the union of all wired loop points
|
|
481
590
|
* (i.e. points that have a `loop render-hooks <point>` call site).
|
|
@@ -509,7 +618,7 @@ module.exports = {
|
|
|
509
618
|
assertPointsCoverage,
|
|
510
619
|
buildContract,
|
|
511
620
|
serializeContract,
|
|
512
|
-
normalizeLineEndings,
|
|
621
|
+
normalizeLineEndings: normalizeEol,
|
|
513
622
|
STEP_WORKFLOWS,
|
|
514
623
|
HOST_LOOP_FILES,
|
|
515
624
|
CANONICAL_POINTS,
|
|
@@ -517,6 +626,10 @@ module.exports = {
|
|
|
517
626
|
ROLE_TO_AGENT,
|
|
518
627
|
scanWiredPoints,
|
|
519
628
|
getWiredLoopPoints,
|
|
629
|
+
coveredKindsInRegion,
|
|
630
|
+
scanWiredKinds,
|
|
631
|
+
getWiredKinds,
|
|
632
|
+
HOOK_KINDS,
|
|
520
633
|
};
|
|
521
634
|
|
|
522
635
|
// ─── CLI entry point ──────────────────────────────────────────────────────────
|
package/scripts/gen-registry.cjs
CHANGED
|
@@ -35,6 +35,7 @@ const path = require('node:path');
|
|
|
35
35
|
|
|
36
36
|
const { ExitError, runMain } = require('./lib/cli-exit.cjs');
|
|
37
37
|
const { renderMarkdown } = require('./registry-schema.cjs');
|
|
38
|
+
const { normalizeEol } = require('../gsd-core/bin/lib/text-lines.cjs');
|
|
38
39
|
|
|
39
40
|
const SOURCES = [
|
|
40
41
|
{ type: 'capability', jsonFile: 'capabilities.json', mdFile: 'capability-registry.md' },
|
|
@@ -42,18 +43,6 @@ const SOURCES = [
|
|
|
42
43
|
{ type: 'reviewer', jsonFile: 'reviewers.json', mdFile: 'reviewer-registry.md', optional: true },
|
|
43
44
|
];
|
|
44
45
|
|
|
45
|
-
/**
|
|
46
|
-
* The generator always writes LF; a Windows checkout (autocrlf) may present
|
|
47
|
-
* committed files with CRLF. Normalize before comparing so `--check` only
|
|
48
|
-
* fails on real content drift, not checkout-introduced line-ending noise.
|
|
49
|
-
*
|
|
50
|
-
* @param {string} content
|
|
51
|
-
* @returns {string}
|
|
52
|
-
*/
|
|
53
|
-
function normalizeLineEndings(content) {
|
|
54
|
-
return content.replace(/\r/g, '');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
46
|
function getRegistriesDir() {
|
|
58
47
|
return path.join(process.cwd(), 'docs', 'registries');
|
|
59
48
|
}
|
|
@@ -126,7 +115,7 @@ function main() {
|
|
|
126
115
|
continue;
|
|
127
116
|
}
|
|
128
117
|
const committed = fs.readFileSync(mdPath, 'utf8');
|
|
129
|
-
if (
|
|
118
|
+
if (normalizeEol(committed) !== normalizeEol(rendered)) {
|
|
130
119
|
process.stderr.write(`${mdFile} is stale. Run:\n node scripts/gen-registry.cjs --write\n`);
|
|
131
120
|
anyDrift = true;
|
|
132
121
|
}
|
|
@@ -149,4 +138,4 @@ function main() {
|
|
|
149
138
|
|
|
150
139
|
if (require.main === module) runMain(main);
|
|
151
140
|
|
|
152
|
-
module.exports = { main, renderFor, SOURCES, normalizeLineEndings };
|
|
141
|
+
module.exports = { main, renderFor, SOURCES, normalizeLineEndings: normalizeEol };
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* gen-scripts-cli-exit.cjs — generates scripts/lib/cli-exit.cjs from a fresh
|
|
4
|
+
* compile of src/cli-exit.cts.
|
|
5
|
+
*
|
|
6
|
+
* ADR-3889 Phase 0 (#3904): scripts/lib/cli-exit.cjs used to be a hand-written
|
|
7
|
+
* fork of gsd-core/bin/lib/cli-exit.cjs (the compiled artifact of
|
|
8
|
+
* src/cli-exit.cts). The two drifted — only the .cts copy routed a
|
|
9
|
+
* non-ExitError throw through getJsonErrorMode() to emit a structured
|
|
10
|
+
* { ok:false, reason, message } envelope. This script makes scripts/lib/cli-exit.cjs
|
|
11
|
+
* a generated artifact of the SAME source, so the two surfaces cannot diverge
|
|
12
|
+
* again.
|
|
13
|
+
*
|
|
14
|
+
* scripts/ runs straight from the repo checkout and must work on an unbuilt
|
|
15
|
+
* clone (scripts/check-env.cjs requires this file before any build runs), so
|
|
16
|
+
* the generated file is compiled to a THROWAWAY outDir rather than read from
|
|
17
|
+
* gsd-core/bin/lib/ — reading the tracked build output would let a stale build
|
|
18
|
+
* produce a false green.
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* node scripts/gen-scripts-cli-exit.cjs # same as --write
|
|
22
|
+
* node scripts/gen-scripts-cli-exit.cjs --write # write scripts/lib/cli-exit.cjs
|
|
23
|
+
* node scripts/gen-scripts-cli-exit.cjs --check # exit 1 if committed file is stale
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
'use strict';
|
|
27
|
+
|
|
28
|
+
const { execFileSync } = require('node:child_process');
|
|
29
|
+
const fs = require('node:fs');
|
|
30
|
+
const os = require('node:os');
|
|
31
|
+
const path = require('node:path');
|
|
32
|
+
|
|
33
|
+
const REPO_ROOT = path.resolve(__dirname, '..');
|
|
34
|
+
const OUTPUT_PATH = path.join(REPO_ROOT, 'scripts', 'lib', 'cli-exit.cjs');
|
|
35
|
+
const COMPILE_TIMEOUT_MS = 60_000;
|
|
36
|
+
|
|
37
|
+
/** Frozen reason codes so tests assert on structure, not prose. */
|
|
38
|
+
const REASON = Object.freeze({
|
|
39
|
+
OK: 'ok_generated_sync',
|
|
40
|
+
DRIFTED: 'fail_generated_drifted',
|
|
41
|
+
BUILD_FAILED: 'fail_build_failed',
|
|
42
|
+
MISSING_EMIT: 'fail_missing_emit',
|
|
43
|
+
USAGE: 'fail_usage',
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const USAGE_MESSAGE = [
|
|
47
|
+
'Usage: node scripts/gen-scripts-cli-exit.cjs [--write|--check]',
|
|
48
|
+
' (no flag) same as --write',
|
|
49
|
+
' --write write scripts/lib/cli-exit.cjs',
|
|
50
|
+
' --check exit 1 if the committed file is stale',
|
|
51
|
+
].join('\n');
|
|
52
|
+
|
|
53
|
+
const BANNER = [
|
|
54
|
+
'// GENERATED FILE — DO NOT EDIT BY HAND.',
|
|
55
|
+
'// Source of truth: src/cli-exit.cts. Regenerate with:',
|
|
56
|
+
'// node scripts/gen-scripts-cli-exit.cjs --write',
|
|
57
|
+
'// Byte-compared by `npm run lint:generated-sync` (#3904, ADR-3889 Phase 0).',
|
|
58
|
+
'//',
|
|
59
|
+
'// Why this copy exists: scripts/ runs straight from the repo checkout and must',
|
|
60
|
+
'// work on an unbuilt clone — 64+ scripts require this file, including',
|
|
61
|
+
'// check-env.cjs, which runs before any build. gsd-core/bin/lib/cli-exit.cjs is',
|
|
62
|
+
'// gitignored tsc output and doubles as the build sentinel, so it cannot be',
|
|
63
|
+
'// required from here. Hence one source, two emitted locations.',
|
|
64
|
+
'',
|
|
65
|
+
'',
|
|
66
|
+
].join('\n');
|
|
67
|
+
|
|
68
|
+
/** Compile the whole project to a throwaway outDir so the work tree is untouched. */
|
|
69
|
+
function compileToTemp() {
|
|
70
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-scripts-cli-exit-'));
|
|
71
|
+
try {
|
|
72
|
+
execFileSync(
|
|
73
|
+
process.execPath,
|
|
74
|
+
[
|
|
75
|
+
path.join(REPO_ROOT, 'node_modules', 'typescript', 'bin', 'tsc'),
|
|
76
|
+
'-p', path.join(REPO_ROOT, 'tsconfig.build.json'),
|
|
77
|
+
'--outDir', tmp,
|
|
78
|
+
// A throwaway outDir must not reuse the in-tree incremental state, or
|
|
79
|
+
// tsc skips emit for files it believes are already current.
|
|
80
|
+
'--incremental', 'false',
|
|
81
|
+
'--tsBuildInfoFile', 'null',
|
|
82
|
+
],
|
|
83
|
+
{ cwd: REPO_ROOT, encoding: 'utf8', stdio: 'pipe', timeout: COMPILE_TIMEOUT_MS },
|
|
84
|
+
);
|
|
85
|
+
return { ok: true, dir: tmp };
|
|
86
|
+
} catch (err) {
|
|
87
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
88
|
+
const detail = [err.stdout, err.stderr].filter(Boolean).join('\n').trim();
|
|
89
|
+
return { ok: false, detail };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Compile src/cli-exit.cts to a throwaway outDir and return the expected
|
|
95
|
+
* generated content (banner + compiled bytes), or a failure descriptor.
|
|
96
|
+
*
|
|
97
|
+
* @returns {{ ok: true, content: string } | { ok: false, reason: string, detail?: string }}
|
|
98
|
+
*/
|
|
99
|
+
function buildExpectedContent() {
|
|
100
|
+
const build = compileToTemp();
|
|
101
|
+
if (!build.ok) {
|
|
102
|
+
return { ok: false, reason: REASON.BUILD_FAILED, detail: build.detail };
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
const emitted = path.join(build.dir, 'cli-exit.cjs');
|
|
106
|
+
if (!fs.existsSync(emitted)) {
|
|
107
|
+
return { ok: false, reason: REASON.MISSING_EMIT, detail: `no emit produced at ${emitted} from src/cli-exit.cts` };
|
|
108
|
+
}
|
|
109
|
+
const compiled = fs.readFileSync(emitted, 'utf8');
|
|
110
|
+
return { ok: true, content: BANNER + compiled };
|
|
111
|
+
} finally {
|
|
112
|
+
fs.rmSync(build.dir, { recursive: true, force: true });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function doWrite() {
|
|
117
|
+
const result = buildExpectedContent();
|
|
118
|
+
if (!result.ok) {
|
|
119
|
+
console.error(`FAIL gen-scripts-cli-exit: ${result.reason}`);
|
|
120
|
+
if (result.detail) console.error(result.detail);
|
|
121
|
+
return 1;
|
|
122
|
+
}
|
|
123
|
+
fs.mkdirSync(path.dirname(OUTPUT_PATH), { recursive: true });
|
|
124
|
+
fs.writeFileSync(OUTPUT_PATH, result.content, 'utf8');
|
|
125
|
+
console.log(`ok gen-scripts-cli-exit: wrote ${path.relative(REPO_ROOT, OUTPUT_PATH)}`);
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function doCheck() {
|
|
130
|
+
const result = buildExpectedContent();
|
|
131
|
+
if (!result.ok) {
|
|
132
|
+
console.error(`FAIL gen-scripts-cli-exit: ${result.reason}`);
|
|
133
|
+
if (result.detail) console.error(result.detail);
|
|
134
|
+
return 1;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!fs.existsSync(OUTPUT_PATH)) {
|
|
138
|
+
console.error(`FAIL gen-scripts-cli-exit: ${REASON.MISSING_EMIT}`);
|
|
139
|
+
console.error(` ${path.relative(REPO_ROOT, OUTPUT_PATH)} does not exist. Run:`);
|
|
140
|
+
console.error(' node scripts/gen-scripts-cli-exit.cjs --write');
|
|
141
|
+
return 1;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const committed = fs.readFileSync(OUTPUT_PATH, 'utf8');
|
|
145
|
+
if (committed !== result.content) {
|
|
146
|
+
console.error(`FAIL gen-scripts-cli-exit: ${REASON.DRIFTED}`);
|
|
147
|
+
console.error(
|
|
148
|
+
` ${path.relative(REPO_ROOT, OUTPUT_PATH)} (${committed.length} bytes) != ` +
|
|
149
|
+
`compile of src/cli-exit.cts (${result.content.length} bytes)`,
|
|
150
|
+
);
|
|
151
|
+
console.error('');
|
|
152
|
+
console.error('Regenerate with:');
|
|
153
|
+
console.error(' node scripts/gen-scripts-cli-exit.cjs --write');
|
|
154
|
+
return 1;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
console.log(`ok gen-scripts-cli-exit: ${path.relative(REPO_ROOT, OUTPUT_PATH)} matches src/cli-exit.cts`);
|
|
158
|
+
return 0;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function main() {
|
|
162
|
+
const flag = process.argv[2];
|
|
163
|
+
const extra = process.argv[3];
|
|
164
|
+
|
|
165
|
+
if (flag !== undefined && flag !== '--write' && flag !== '--check') {
|
|
166
|
+
console.error(`FAIL gen-scripts-cli-exit: ${REASON.USAGE}`);
|
|
167
|
+
console.error(` unrecognized argument: ${flag}`);
|
|
168
|
+
console.error(USAGE_MESSAGE);
|
|
169
|
+
return 1;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (extra !== undefined) {
|
|
173
|
+
console.error(`FAIL gen-scripts-cli-exit: ${REASON.USAGE}`);
|
|
174
|
+
console.error(` unexpected extra argument: ${extra}`);
|
|
175
|
+
console.error(USAGE_MESSAGE);
|
|
176
|
+
return 1;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (flag === '--check') return doCheck();
|
|
180
|
+
return doWrite();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (require.main === module) process.exitCode = main();
|
|
184
|
+
|
|
185
|
+
module.exports = { REASON, buildExpectedContent, OUTPUT_PATH, BANNER };
|