@opengsd/gsd-core 1.11.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-debug-session-manager.md +1 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-dom-verifier.md +169 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +17 -9
- package/agents/gsd-framework-selector.md +1 -3
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +0 -1
- package/agents/gsd-pattern-mapper.md +11 -0
- package/agents/gsd-phase-researcher.md +3 -1
- package/agents/gsd-plan-checker.md +15 -55
- package/agents/gsd-planner.md +6 -4
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.md +2 -2
- package/agents/gsd-roadmapper.md +15 -11
- package/agents/gsd-ui-checker.md +63 -4
- package/agents/gsd-ui-researcher.md +41 -3
- package/agents/gsd-verifier.md +1 -1
- package/bin/install.js +609 -134
- package/commands/gsd/discuss-phase.md +1 -1
- package/commands/gsd/import.md +1 -1
- package/commands/gsd/quick.md +8 -4
- package/gsd-core/bin/gsd-tools.cjs +567 -51
- package/gsd-core/bin/lib/active-workstream-store.cjs +8 -0
- package/gsd-core/bin/lib/adr-parser.cjs +13 -7
- package/gsd-core/bin/lib/agent-install-check.cjs +162 -0
- package/gsd-core/bin/lib/api-coverage.cjs +30 -9
- package/gsd-core/bin/lib/artifacts.cjs +2 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +30 -11
- package/gsd-core/bin/lib/audit.cjs +163 -41
- package/gsd-core/bin/lib/broken-windows.cjs +306 -28
- package/gsd-core/bin/lib/capability-lock.cjs +10 -4
- package/gsd-core/bin/lib/capability-registry.cjs +336 -95
- package/gsd-core/bin/lib/capability-state.cjs +18 -3
- package/gsd-core/bin/lib/capability-validator.cjs +205 -18
- package/gsd-core/bin/lib/check-command-router.cjs +145 -5
- package/gsd-core/bin/lib/cli-exit.cjs +496 -10
- package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +410 -4
- package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
- package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
- package/gsd-core/bin/lib/commands.cjs +543 -44
- package/gsd-core/bin/lib/complexity-trigger.cjs +26 -6
- package/gsd-core/bin/lib/config-loader.cjs +118 -29
- package/gsd-core/bin/lib/config.cjs +92 -2
- package/gsd-core/bin/lib/configuration.cjs +129 -37
- package/gsd-core/bin/lib/core-utils.cjs +84 -7
- package/gsd-core/bin/lib/edge-probe.cjs +9 -1
- package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
- package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
- package/gsd-core/bin/lib/frontmatter.cjs +840 -305
- package/gsd-core/bin/lib/gap-checker.cjs +27 -3
- package/gsd-core/bin/lib/git-base-branch.cjs +174 -39
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +7 -3
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +6 -3
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +22 -8
- package/gsd-core/bin/lib/health-diagnostic.cjs +23 -3
- package/gsd-core/bin/lib/host-integration.cjs +39 -6
- package/gsd-core/bin/lib/init-command-router.cjs +118 -21
- package/gsd-core/bin/lib/init.cjs +120 -41
- package/gsd-core/bin/lib/install-engine.cjs +68 -3
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +33 -1
- package/gsd-core/bin/lib/install-profiles.cjs +78 -4
- package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
- package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +10 -7
- package/gsd-core/bin/lib/intel.cjs +101 -26
- package/gsd-core/bin/lib/io.cjs +160 -15
- package/gsd-core/bin/lib/learnings.cjs +85 -14
- package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
- package/gsd-core/bin/lib/markdown-table.cjs +52 -4
- package/gsd-core/bin/lib/milestone.cjs +90 -5
- package/gsd-core/bin/lib/model-catalog.cjs +177 -19
- package/gsd-core/bin/lib/model-resolver.cjs +10 -28
- package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
- package/gsd-core/bin/lib/phase-estimation.cjs +17 -8
- package/gsd-core/bin/lib/phase-id.cjs +70 -4
- package/gsd-core/bin/lib/phase-lifecycle.cjs +24 -16
- package/gsd-core/bin/lib/phase-locator.cjs +138 -17
- package/gsd-core/bin/lib/phase.cjs +405 -84
- package/gsd-core/bin/lib/plan-document.cjs +263 -0
- package/gsd-core/bin/lib/plan-scan.cjs +13 -2
- package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +18 -14
- package/gsd-core/bin/lib/planning-workspace.cjs +56 -0
- package/gsd-core/bin/lib/probe-core.cjs +4 -1
- package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
- package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
- package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +71 -45
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +9 -9
- package/gsd-core/bin/lib/roadmap-command-router.cjs +45 -31
- package/gsd-core/bin/lib/roadmap-parser.cjs +79 -16
- package/gsd-core/bin/lib/roadmap.cjs +74 -19
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +96 -8
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +34 -1
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +287 -55
- package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
- package/gsd-core/bin/lib/runtime-slash.cjs +72 -2
- package/gsd-core/bin/lib/shell-command-projection.cjs +71 -8
- package/gsd-core/bin/lib/smart-entry.cjs +12 -22
- package/gsd-core/bin/lib/spec-section.cjs +12 -7
- package/gsd-core/bin/lib/state-command-router.cjs +47 -18
- package/gsd-core/bin/lib/state-contract.cjs +359 -0
- package/gsd-core/bin/lib/state-document.cjs +186 -0
- package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
- package/gsd-core/bin/lib/state-transition.cjs +517 -101
- package/gsd-core/bin/lib/state.cjs +946 -163
- package/gsd-core/bin/lib/surface.cjs +10 -2
- package/gsd-core/bin/lib/task-command-router.cjs +111 -1
- package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
- package/gsd-core/bin/lib/teams-status.cjs +4 -1
- package/gsd-core/bin/lib/uat-predicate.cjs +58 -20
- package/gsd-core/bin/lib/uat.cjs +1376 -125
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
- package/gsd-core/bin/lib/ui-safety-gate.cjs +37 -7
- package/gsd-core/bin/lib/unusable-input.cjs +13 -0
- package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
- package/gsd-core/bin/lib/vendor/README.md +43 -5
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
- package/gsd-core/bin/lib/verification.cjs +14 -1
- package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
- package/gsd-core/bin/lib/verify.cjs +95 -40
- package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
- package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
- package/gsd-core/bin/lib/worktree-safety.cjs +177 -21
- package/gsd-core/bin/shared/config-defaults.manifest.json +7 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
- package/gsd-core/bin/shared/exit-codes.json +8 -0
- package/gsd-core/bin/shared/exit-codes.sh +20 -0
- package/gsd-core/bin/shared/model-catalog.json +8 -1
- package/gsd-core/references/agent-contracts.md +3 -2
- package/gsd-core/references/api-coverage.md +24 -2
- package/gsd-core/references/autonomous-smart-discuss.md +3 -3
- package/gsd-core/references/checkpoints.md +37 -19
- package/gsd-core/references/decimal-phase-calculation.md +5 -5
- package/gsd-core/references/edge-probe.md +8 -0
- package/gsd-core/references/execute-mvp-tdd.md +1 -3
- package/gsd-core/references/execute-phase-between-wave-reset.md +9 -12
- package/gsd-core/references/execute-phase-wave-guard.md +11 -9
- package/gsd-core/references/failing-direction.md +78 -0
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-integration.md +5 -5
- package/gsd-core/references/git-planning-commit.md +3 -3
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +22 -0
- package/gsd-core/references/model-profiles.md +1 -1
- package/gsd-core/references/nyquist-compliance.md +74 -0
- package/gsd-core/references/offer-next.md +3 -5
- package/gsd-core/references/phase-argument-parsing.md +3 -3
- package/gsd-core/references/planner-failing-direction.md +53 -0
- package/gsd-core/references/planner-human-verify-mode.md +15 -1
- package/gsd-core/references/planner-revision.md +1 -1
- package/gsd-core/references/planner-verify-command-grounding.md +17 -0
- package/gsd-core/references/planning-config.md +37 -8
- package/gsd-core/references/reviewer-instances.md +31 -0
- package/gsd-core/references/runtime-aware-dispatch.md +1 -1
- package/gsd-core/references/tdd.md +1 -3
- package/gsd-core/references/ui-brand.md +65 -21
- package/gsd-core/references/ui-consideration-probe.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +2 -2
- package/gsd-core/references/verify-command-path-resolvability.md +42 -0
- package/gsd-core/references/verify-mvp-mode.md +1 -1
- package/gsd-core/references/workstream-flag.md +11 -11
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/SECURITY.md +3 -3
- package/gsd-core/templates/UI-SPEC.md +25 -3
- package/gsd-core/templates/VALIDATION.md +3 -3
- package/gsd-core/templates/phase-prompt.md +3 -0
- package/gsd-core/templates/state.md +7 -0
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +3 -3
- package/gsd-core/workflows/add-tests.md +3 -8
- package/gsd-core/workflows/add-todo.md +1 -1
- package/gsd-core/workflows/ai-integration-phase.md +4 -9
- package/gsd-core/workflows/audit-fix.md +12 -3
- package/gsd-core/workflows/audit-milestone.md +9 -9
- package/gsd-core/workflows/audit-uat.md +17 -2
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
- package/gsd-core/workflows/autonomous.md +10 -26
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +2 -2
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +1 -1
- package/gsd-core/workflows/code-review-fix.md +1 -1
- package/gsd-core/workflows/code-review.md +121 -40
- package/gsd-core/workflows/complete-milestone.md +15 -10
- package/gsd-core/workflows/debug.md +5 -3
- package/gsd-core/workflows/diagnose-issues.md +12 -6
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +3 -7
- package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
- package/gsd-core/workflows/discuss-phase-assumptions.md +2 -2
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +3 -6
- package/gsd-core/workflows/docs-update.md +5 -4
- package/gsd-core/workflows/edit-phase.md +1 -1
- package/gsd-core/workflows/eval-review.md +4 -9
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +113 -11
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +22 -4
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
- package/gsd-core/workflows/execute-phase.md +38 -54
- package/gsd-core/workflows/execute-plan.md +17 -12
- package/gsd-core/workflows/explore.md +1 -1
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/fast.md +2 -2
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +5 -5
- package/gsd-core/workflows/health.md +3 -6
- package/gsd-core/workflows/import.md +14 -11
- package/gsd-core/workflows/inbox.md +4 -5
- package/gsd-core/workflows/ingest-docs.md +44 -11
- package/gsd-core/workflows/insert-phase.md +5 -5
- package/gsd-core/workflows/list-seeds.md +5 -3
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +12 -23
- package/gsd-core/workflows/map-codebase.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +2 -2
- package/gsd-core/workflows/new-milestone.md +9 -21
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +12 -26
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +2 -2
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
- package/gsd-core/workflows/plan-phase.md +121 -42
- package/gsd-core/workflows/plan-review-convergence.md +46 -9
- package/gsd-core/workflows/plant-seed.md +2 -2
- package/gsd-core/workflows/pr-branch.md +187 -51
- package/gsd-core/workflows/profile-user.md +16 -14
- package/gsd-core/workflows/progress.md +27 -12
- package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +1 -3
- package/gsd-core/workflows/quick/steps/quick-verification.md +2 -4
- package/gsd-core/workflows/quick/steps/research-phase.md +2 -4
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
- package/gsd-core/workflows/quick.md +20 -29
- package/gsd-core/workflows/remove-phase.md +4 -4
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +8 -12
- package/gsd-core/workflows/review.md +193 -15
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +2 -2
- package/gsd-core/workflows/settings-advanced.md +7 -9
- package/gsd-core/workflows/settings-integrations.md +64 -31
- package/gsd-core/workflows/settings.md +3 -5
- package/gsd-core/workflows/ship.md +12 -6
- package/gsd-core/workflows/sketch-wrap-up.md +11 -17
- package/gsd-core/workflows/sketch.md +12 -18
- package/gsd-core/workflows/smart-entry.md +3 -5
- package/gsd-core/workflows/spec-phase.md +23 -1
- package/gsd-core/workflows/spike-wrap-up.md +7 -11
- package/gsd-core/workflows/spike.md +20 -31
- package/gsd-core/workflows/stats.md +2 -2
- package/gsd-core/workflows/sync-skills.md +1 -1
- package/gsd-core/workflows/thread.md +11 -7
- package/gsd-core/workflows/transition.md +5 -5
- package/gsd-core/workflows/ui-phase.md +10 -16
- package/gsd-core/workflows/ui-review.md +6 -10
- package/gsd-core/workflows/ultraplan-phase.md +5 -13
- package/gsd-core/workflows/undo.md +8 -16
- package/gsd-core/workflows/update.md +6 -10
- package/gsd-core/workflows/validate-phase.md +2 -2
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +57 -18
- package/hooks/dist/gsd-agent-isolation-guard.js +77 -38
- package/hooks/dist/gsd-config-reload.js +18 -12
- package/hooks/dist/gsd-context-monitor.js +19 -10
- package/hooks/dist/gsd-cursor-post-tool.js +3 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +3 -1
- package/hooks/dist/gsd-cursor-session-start.js +2 -1
- package/hooks/dist/gsd-cursor-stop.js +2 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +28 -23
- package/hooks/dist/gsd-cursor-subagent-stop.js +3 -1
- package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
- package/hooks/dist/gsd-graphify-update.sh +22 -18
- package/hooks/dist/gsd-node-runner.sh +76 -0
- package/hooks/dist/gsd-phase-boundary.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +16 -7
- package/hooks/dist/gsd-read-guard.js +16 -7
- package/hooks/dist/gsd-read-injection-scanner.js +17 -8
- package/hooks/dist/gsd-session-state.sh +1 -0
- package/hooks/dist/gsd-statusline.js +215 -26
- package/hooks/dist/gsd-validate-commit.sh +80 -6
- package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
- package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
- package/hooks/dist/gsd-workflow-guard.js +34 -16
- package/hooks/dist/gsd-worktree-path-guard.js +36 -21
- package/hooks/dist/gsd-write-guard.js +35 -25
- package/hooks/dist/lib/cli-exit.js +560 -0
- package/hooks/dist/lib/exit-code-registry.js +98 -0
- package/hooks/dist/lib/git-probe.js +84 -0
- package/hooks/dist/lib/hook-exit.js +81 -0
- package/hooks/dist/managed-hooks-registry.cjs +3 -0
- package/hooks/gsd-agent-isolation-guard.js +77 -38
- package/hooks/gsd-config-reload.js +18 -12
- package/hooks/gsd-context-monitor.js +19 -10
- package/hooks/gsd-cursor-post-tool.js +3 -1
- package/hooks/gsd-cursor-pre-tool.js +3 -1
- package/hooks/gsd-cursor-session-start.js +2 -1
- package/hooks/gsd-cursor-stop.js +2 -1
- package/hooks/gsd-cursor-subagent-start.js +28 -23
- package/hooks/gsd-cursor-subagent-stop.js +3 -1
- package/hooks/gsd-ensure-canonical-path.js +2 -1
- package/hooks/gsd-graphify-update.sh +22 -18
- package/hooks/gsd-node-runner.sh +76 -0
- package/hooks/gsd-phase-boundary.sh +1 -0
- package/hooks/gsd-prompt-guard.js +16 -7
- package/hooks/gsd-read-guard.js +16 -7
- package/hooks/gsd-read-injection-scanner.js +17 -8
- package/hooks/gsd-session-state.sh +1 -0
- package/hooks/gsd-statusline.js +215 -26
- package/hooks/gsd-validate-commit.sh +80 -6
- package/hooks/gsd-windsurf-pre-command.js +16 -11
- package/hooks/gsd-windsurf-pre-write.js +22 -13
- package/hooks/gsd-workflow-guard.js +34 -16
- package/hooks/gsd-worktree-path-guard.js +36 -21
- package/hooks/gsd-write-guard.js +35 -25
- package/hooks/lib/cli-exit.js +560 -0
- package/hooks/lib/exit-code-registry.js +98 -0
- package/hooks/lib/git-probe.js +84 -0
- package/hooks/lib/hook-exit.js +81 -0
- package/hooks/managed-hooks-registry.cjs +3 -0
- package/package.json +12 -7
- package/scripts/base64-scan.sh +74 -12
- package/scripts/build-hooks.js +5 -0
- package/scripts/check-glossary-refs.cjs +77 -15
- package/scripts/check-mutation-score-ratchet.cjs +156 -0
- package/scripts/ci-check-job-near-cap.cjs +49 -0
- package/scripts/ci-pr-mergeability.cjs +262 -0
- package/scripts/ci-test-scope.cjs +45 -12
- package/scripts/ci-timeout-report.cjs +230 -0
- package/scripts/docs-guard-registry.cjs +396 -0
- package/scripts/gen-capability-registry.cjs +8 -6
- package/scripts/gen-exit-code-docs.cjs +318 -0
- package/scripts/gen-exit-code-registry.cjs +891 -0
- package/scripts/gen-features.cjs +836 -0
- package/scripts/gen-hooks-cli-exit.cjs +239 -0
- package/scripts/gen-install-tree-fixtures.cjs +2 -2
- package/scripts/gen-loop-host-contract.cjs +134 -1
- package/scripts/gen-scripts-cli-exit.cjs +185 -0
- package/scripts/gen-state-md-docs.cjs +727 -0
- package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
- package/scripts/lib/ci-job-timing.cjs +72 -0
- package/scripts/lib/cli-exit.cjs +546 -44
- package/scripts/lib/drift-scan.cjs +32 -2
- package/scripts/lib/exit-code-registry.cjs +98 -0
- package/scripts/lib/ndjson-reporter.cjs +119 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-docs-guard-registration.cjs +495 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +4 -0
- package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
- package/scripts/lint-health-diagnostic-rule-table.cjs +65 -8
- package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
- package/scripts/lint-phase-enumeration-drift.cjs +21 -8
- package/scripts/lint-planning-prompt-drift.cjs +38 -1
- package/scripts/lint-removed-but-needed.cjs +184 -16
- package/scripts/lint-seam-enforcement.cjs +182 -0
- package/scripts/lint-slug-derivation-drift.cjs +921 -0
- package/scripts/lint-source-test-name-collision.cjs +241 -0
- package/scripts/lint-state-write-path-drift.cjs +337 -432
- package/scripts/lint-test-file-count.allowlist.json +122 -4
- package/scripts/lint-test-file-count.cjs +25 -3
- package/scripts/lint-unreachable-guard-drift.cjs +51 -64
- package/scripts/lint-vendored-deps.cjs +208 -35
- package/scripts/mutation-matrix.cjs +599 -50
- package/scripts/prompt-injection-scan.sh +75 -14
- package/scripts/secret-scan.sh +75 -13
- package/scripts/select-docs-guards.cjs +56 -0
- package/scripts/sync-runtime-launcher.cjs +22 -3
- package/skills/gsd-discuss-phase/SKILL.md +1 -1
- package/skills/gsd-import/SKILL.md +1 -1
- package/skills/gsd-quick/SKILL.md +8 -4
- package/vscode/package.json +1 -1
- package/bin/lib/ui-safety-gate.cjs +0 -109
- package/scripts/lint-emitted-drift-ack.cjs +0 -344
- package/scripts/state-write-path-drift-baseline.json +0 -19
|
@@ -37,7 +37,7 @@ const markdown_sectionizer_cjs_1 = require("./markdown-sectionizer.cjs");
|
|
|
37
37
|
const pattern_cjs_1 = require("./pattern.cjs");
|
|
38
38
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- agent-install-check.cjs is an export= CommonJS module
|
|
39
39
|
const agentInstallCheck = require("./agent-install-check.cjs");
|
|
40
|
-
const { checkAgentsInstalled, checkCodexModelPosture } = agentInstallCheck;
|
|
40
|
+
const { checkAgentsInstalled, checkCodexModelPosture, checkCodexSandboxPosture } = agentInstallCheck;
|
|
41
41
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
42
42
|
const ioMod = require("./io.cjs");
|
|
43
43
|
const { output, error } = ioMod;
|
|
@@ -56,7 +56,7 @@ const { SEVERITY: HEALTH_SEVERITY, REMEDY_ACTION, REMEDY_RISK, evaluateRules, ev
|
|
|
56
56
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- planning-snapshot.cjs is an export= CommonJS module
|
|
57
57
|
const planningSnapshotMod = require("./planning-snapshot.cjs");
|
|
58
58
|
const { buildPlanningSnapshot } = planningSnapshotMod;
|
|
59
|
-
const { planningDir
|
|
59
|
+
const { planningDir } = planningWorkspace;
|
|
60
60
|
const { extractFrontmatter, parseMustHavesBlock } = frontmatterMod;
|
|
61
61
|
const { readStateHeadFreshness } = stateMod;
|
|
62
62
|
/**
|
|
@@ -262,15 +262,78 @@ function cmdVerifySummary(cwd, summaryPath, checkFileCount, raw) {
|
|
|
262
262
|
* verify gate fails on the comment echo rather than a real regression. Conservative:
|
|
263
263
|
* errors only on a confidently-extracted QUOTED literal; ambiguous (bareword) → warning.
|
|
264
264
|
*/
|
|
265
|
+
/**
|
|
266
|
+
* Decode entity-escaped ampersands (& → &) — #3611. Planners emit
|
|
267
|
+
* <automated> bodies with `&&` as the chain operator (66 occurrences
|
|
268
|
+
* vs 0 literal in the reporting repo), and the executing agent reads the
|
|
269
|
+
* decoded (rendered) form. Every downstream scan — segment split,
|
|
270
|
+
* zero-comparison, literal harvest, echo matching — must operate on the same
|
|
271
|
+
* decoded text or a negative clause (`= 0`) poisons the literals of a
|
|
272
|
+
* POSITIVE clause (-ge 3) joined to it. Shared by both plan-discipline
|
|
273
|
+
* scanners so the two gates cannot drift apart again.
|
|
274
|
+
*/
|
|
275
|
+
function decodeEntityAmps(s) {
|
|
276
|
+
return s.replace(/&/g, '&');
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Split one shell line into &&/|| segments, QUOTE-AWARE (#3611 adversarial
|
|
280
|
+
* review): an operator inside a quoted literal (`grep -c 'a&&b'`) is part of
|
|
281
|
+
* the pattern, not a chain operator — a quote-blind split destroys the
|
|
282
|
+
* literal and silently disarms the gate for exactly the plans that spell
|
|
283
|
+
* patterns with ampersands. Backslash escapes count inside double quotes
|
|
284
|
+
* (POSIX single quotes have none, and over-staying a single-quoted span can
|
|
285
|
+
* only miss a split, never invent one).
|
|
286
|
+
*/
|
|
287
|
+
function splitShellSegments(line) {
|
|
288
|
+
const segments = [];
|
|
289
|
+
let current = '';
|
|
290
|
+
let quote = null;
|
|
291
|
+
for (let i = 0; i < line.length; i++) {
|
|
292
|
+
const ch = line[i];
|
|
293
|
+
if (quote === "'") {
|
|
294
|
+
if (ch === "'")
|
|
295
|
+
quote = null;
|
|
296
|
+
current += ch;
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
if (quote === '"') {
|
|
300
|
+
if (ch === '\\') {
|
|
301
|
+
current += ch + (line[i + 1] ?? '');
|
|
302
|
+
i++;
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
if (ch === '"')
|
|
306
|
+
quote = null;
|
|
307
|
+
current += ch;
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
if (ch === "'" || ch === '"') {
|
|
311
|
+
quote = ch;
|
|
312
|
+
current += ch;
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
if ((ch === '&' && line[i + 1] === '&') || (ch === '|' && line[i + 1] === '|')) {
|
|
316
|
+
segments.push(current.trim());
|
|
317
|
+
current = '';
|
|
318
|
+
i++;
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
current += ch;
|
|
322
|
+
}
|
|
323
|
+
segments.push(current.trim());
|
|
324
|
+
return segments.filter((s) => s !== '');
|
|
325
|
+
}
|
|
265
326
|
function scanNegativeGrepCommentEcho(content) {
|
|
266
327
|
const errors = [];
|
|
267
328
|
const warnings = [];
|
|
268
329
|
// Normalize newlines; join backslash line-continuations so a verify command wrapped
|
|
269
330
|
// across lines (grep ... \ <newline> == 0) is still seen as one segment.
|
|
270
|
-
|
|
331
|
+
// #3611: decode entity-escaped ampersands (see decodeEntityAmps) so every
|
|
332
|
+
// downstream scan reads the same decoded text the executing agent reads.
|
|
333
|
+
const text = decodeEntityAmps((content || '')
|
|
271
334
|
.replace(/\r\n/g, '\n')
|
|
272
335
|
.replace(/\r/g, '\n')
|
|
273
|
-
.replace(/\\\n/g, ' ');
|
|
336
|
+
.replace(/\\\n/g, ' '));
|
|
274
337
|
// 1. Allowlisted literals: <!-- planner-discipline-allow: LIT -->
|
|
275
338
|
const allow = new Set();
|
|
276
339
|
const allowRe = /<!--\s*planner-discipline-allow:\s*(.+?)\s*-->/g;
|
|
@@ -313,7 +376,7 @@ function scanNegativeGrepCommentEcho(content) {
|
|
|
313
376
|
// poisoning a negative gate (`== 0`) sharing the same physical line.
|
|
314
377
|
const seenErr = new Set();
|
|
315
378
|
const seenWarn = new Set();
|
|
316
|
-
const segments = text.split('\n').flatMap(
|
|
379
|
+
const segments = text.split('\n').flatMap(splitShellSegments);
|
|
317
380
|
for (const seg of segments) {
|
|
318
381
|
if (!/grep(?:\s+-{1,2}[A-Za-z])/.test(seg) || !zeroCmp(seg))
|
|
319
382
|
continue;
|
|
@@ -362,10 +425,13 @@ function scanNegativeGrepCommentEcho(content) {
|
|
|
362
425
|
function scanFileWideNegativeGateConflict(content) {
|
|
363
426
|
const warnings = [];
|
|
364
427
|
// Normalize newlines; join backslash line-continuations (same as #429).
|
|
365
|
-
|
|
428
|
+
// #3611: the SAME entity decode as the #429 scanner — the two gates share
|
|
429
|
+
// the caller and the input; a decode on one side only let an entity-escaped
|
|
430
|
+
// chain poison this detector's harvest exactly the same way.
|
|
431
|
+
const text = decodeEntityAmps((content || '')
|
|
366
432
|
.replace(/\r\n/g, '\n')
|
|
367
433
|
.replace(/\r/g, '\n')
|
|
368
|
-
.replace(/\\\n/g, ' ');
|
|
434
|
+
.replace(/\\\n/g, ' '));
|
|
369
435
|
// Allowlisted patterns: <!-- planner-region-allow: PAT -->
|
|
370
436
|
const allow = new Set();
|
|
371
437
|
const allowRe = /<!--\s*planner-region-allow:\s*(.+?)\s*-->/g;
|
|
@@ -499,8 +565,8 @@ function scanFileWideNegativeGateConflict(content) {
|
|
|
499
565
|
// For each task A, scan gate text for file-wide negative grep bans.
|
|
500
566
|
for (let ai = 0; ai < tasks.length; ai++) {
|
|
501
567
|
const taskA = tasks[ai];
|
|
502
|
-
// Split gate text into shell segments (
|
|
503
|
-
const segments = taskA.gateText.split('\n').flatMap(
|
|
568
|
+
// Split gate text into shell segments (quote-aware, shared with #429 — #3611).
|
|
569
|
+
const segments = taskA.gateText.split('\n').flatMap(splitShellSegments);
|
|
504
570
|
for (const seg of segments) {
|
|
505
571
|
if (!/grep/.test(seg))
|
|
506
572
|
continue;
|
|
@@ -1242,30 +1308,6 @@ function cmdVerifyKeyLinks(cwd, planFilePath, raw) {
|
|
|
1242
1308
|
links: results,
|
|
1243
1309
|
}, raw, allVerified ? 'valid' : 'invalid');
|
|
1244
1310
|
}
|
|
1245
|
-
function listMilestoneArchiveDirs(planBase) {
|
|
1246
|
-
const milestonesDir = node_path_1.default.join(planBase, 'milestones');
|
|
1247
|
-
try {
|
|
1248
|
-
return node_fs_1.default
|
|
1249
|
-
.readdirSync(milestonesDir, { withFileTypes: true })
|
|
1250
|
-
.filter((e) => e.isDirectory() && validate_cjs_1.MILESTONE_ARCHIVE_DIR_RE.test(e.name))
|
|
1251
|
-
.map((e) => node_path_1.default.join(milestonesDir, e.name))
|
|
1252
|
-
.sort((a, b) => node_path_1.default.basename(a).localeCompare(node_path_1.default.basename(b), undefined, { numeric: true }));
|
|
1253
|
-
}
|
|
1254
|
-
catch (err) {
|
|
1255
|
-
// #1883: distinguish genuine absence from a permission/I-O failure. ENOENT
|
|
1256
|
-
// (no milestones/ dir yet) keeps the long-standing [] contract callers of
|
|
1257
|
-
// this function depend on for "no archives"; every other error (EACCES,
|
|
1258
|
-
// EIO, …) must propagate — otherwise an unreadable milestones/ dir is
|
|
1259
|
-
// silently reported as "no archives" and archived-phase resolution
|
|
1260
|
-
// misbehaves. As of Phase 12 (#3310), `cmdValidateConsistency`'s own
|
|
1261
|
-
// caller of this function (`collectPhaseRoots` -> `getActiveMilestoneArchiveDir`)
|
|
1262
|
-
// was migrated onto `buildPlanningSnapshot` and deleted; this function is
|
|
1263
|
-
// retained solely for its `_listMilestoneArchiveDirs` test seam below.
|
|
1264
|
-
if (err.code === 'ENOENT')
|
|
1265
|
-
return [];
|
|
1266
|
-
throw err;
|
|
1267
|
-
}
|
|
1268
|
-
}
|
|
1269
1311
|
/**
|
|
1270
1312
|
* Wrapper-level fix-text table for `cmdValidateHealth`'s migrated
|
|
1271
1313
|
* `HealthDiagnostic` -> `IssueEntry` mapping (Phase 11, #3309). Rules cannot
|
|
@@ -1397,8 +1439,10 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
1397
1439
|
}, raw);
|
|
1398
1440
|
return;
|
|
1399
1441
|
}
|
|
1400
|
-
// rootBase
|
|
1401
|
-
|
|
1442
|
+
// rootBase resolves to the PROJECT-scoped planning root (`.planning[/<project>]`
|
|
1443
|
+
// — PROJECT.md, config.json live here; #3749). Workstream-free by construction:
|
|
1444
|
+
// planningDir(cwd, null) honors GSD_PROJECT and suppresses GSD_WORKSTREAM.
|
|
1445
|
+
const rootBase = planningDir(cwd, null);
|
|
1402
1446
|
const _slashRuntime = (0, runtime_slash_cjs_1.resolveRuntime)(cwd);
|
|
1403
1447
|
const slash = (name) => (0, runtime_slash_cjs_1.formatGsdSlash)(name, _slashRuntime);
|
|
1404
1448
|
// Second (and last) pre-check that stays OUTSIDE the rule table entirely
|
|
@@ -1523,6 +1567,21 @@ function cmdValidateAgents(cwd, raw) {
|
|
|
1523
1567
|
// model or an orphaned reasoning-effort pin in a Codex agent .toml), not just
|
|
1524
1568
|
// presence. checkAgentsInstalled above is untouched.
|
|
1525
1569
|
const codexPosture = checkCodexModelPosture(runtime, cwd);
|
|
1570
|
+
// #3897 rung 3 (ADR-3473 §8.3 criterion 3) — sibling posture check, additive
|
|
1571
|
+
// alongside codex_posture (never nested inside it, never replacing it): a
|
|
1572
|
+
// TOML's `sandbox_mode` disagreeing with its role's derived expectation is a
|
|
1573
|
+
// different defect class than an Anthropic-flavored model. Same short-circuits,
|
|
1574
|
+
// same read-only posture as checkCodexModelPosture above; checkAgentsInstalled
|
|
1575
|
+
// and codex_posture are both left untouched.
|
|
1576
|
+
//
|
|
1577
|
+
// Failure semantics: matches the checkCodexModelPosture precedent exactly.
|
|
1578
|
+
// Neither posture check makes `validate agents` exit non-zero on its own —
|
|
1579
|
+
// both are report-only fields inspected by the caller (or a human) via the
|
|
1580
|
+
// JSON payload. A `validate` verb whose two posture checks disagreed on
|
|
1581
|
+
// fatality would be its own defect (#3897 dispatch note); this keeps them
|
|
1582
|
+
// consistent rather than inventing new exit-code behavior for only one of
|
|
1583
|
+
// the two siblings.
|
|
1584
|
+
const sandboxPosture = checkCodexSandboxPosture(runtime, cwd);
|
|
1526
1585
|
output({
|
|
1527
1586
|
agents_dir: agentStatus.agents_dir,
|
|
1528
1587
|
agents_found: agentStatus.agents_installed,
|
|
@@ -1531,6 +1590,7 @@ function cmdValidateAgents(cwd, raw) {
|
|
|
1531
1590
|
incomplete: agentStatus.incomplete_agents,
|
|
1532
1591
|
expected,
|
|
1533
1592
|
codex_posture: codexPosture,
|
|
1593
|
+
sandbox_posture: sandboxPosture,
|
|
1534
1594
|
}, raw);
|
|
1535
1595
|
}
|
|
1536
1596
|
function cmdVerifySchemaDrift(cwd, phaseArg, skipFlag, raw) {
|
|
@@ -1765,9 +1825,4 @@ module.exports = {
|
|
|
1765
1825
|
cmdVerifySchemaDrift,
|
|
1766
1826
|
cmdVerifyCodebaseDrift,
|
|
1767
1827
|
STATE_HEAD_ADVISORY_COMMITS,
|
|
1768
|
-
// Test seam (#1883): listMilestoneArchiveDirs is private and exercised through
|
|
1769
|
-
// the validate command, which runs in a subprocess — an fs monkeypatch in the
|
|
1770
|
-
// test process cannot reach it. Exposed under a leading underscore so the
|
|
1771
|
-
// permission-error path can be unit-tested directly (no chmod 0o000).
|
|
1772
|
-
_listMilestoneArchiveDirs: listMilestoneArchiveDirs,
|
|
1773
1828
|
};
|
|
@@ -6,6 +6,24 @@
|
|
|
6
6
|
* byte-for-behaviour from the prior hand-written .cjs; only types are added.
|
|
7
7
|
*
|
|
8
8
|
* Used by active-workstream-store.cjs, planning-workspace.cjs, workstream.cjs.
|
|
9
|
+
*
|
|
10
|
+
* #3883 (ADR-3473 §8.3): toWorkstreamSlug delegates to core-utils.cjs's
|
|
11
|
+
* generateSlugInternal (the canonical slug formula), passing `maxLen: null`
|
|
12
|
+
* to preserve this site's pre-migration untruncated contract — the 60-char
|
|
13
|
+
* default collided distinct >60-char workstream names onto the same slug
|
|
14
|
+
* (verified: `"a".repeat(60)+"alpha"` and `"a".repeat(60)+"beta"` truncated
|
|
15
|
+
* identically). core-utils.cjs already
|
|
16
|
+
* requires (transitively, at module-init time) THIS module:
|
|
17
|
+
* core-utils.cjs -> planning-workspace.cjs -> active-workstream-store.cjs ->
|
|
18
|
+
* workstream-name-policy.cjs. A top-level require of core-utils.cjs here
|
|
19
|
+
* would therefore close that cycle and — per this codebase's compiled-.cjs
|
|
20
|
+
* convention of a single `module.exports = {...}` reassignment at the bottom
|
|
21
|
+
* of core-utils.cjs — capture a stale, still-empty exports object forever
|
|
22
|
+
* (verified live: "generateSlugInternal is not a function" whichever module
|
|
23
|
+
* loads first). The require is deferred (lazy, inside toWorkstreamSlug's
|
|
24
|
+
* body) instead, mirroring the same cycle-break already used by
|
|
25
|
+
* core-utils.cts's own getPhaseFileStats/plan-scan.cjs seam and by
|
|
26
|
+
* phase-id.cts's toDir/getPhaseDirFromPhaseId.
|
|
9
27
|
*/
|
|
10
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
29
|
exports.INVALID_ACTIVE_WORKSTREAM_NAME_MESSAGE = void 0;
|
|
@@ -68,10 +86,13 @@ function validateWorkstreamName(name) {
|
|
|
68
86
|
* Lowercases, collapses non-alphanumeric runs to hyphens, strips leading/trailing hyphens.
|
|
69
87
|
*/
|
|
70
88
|
function toWorkstreamSlug(name) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
89
|
+
// #3883 (ADR-3473 §8.3): delegate to the canonical slug formula
|
|
90
|
+
// (generateSlugInternal, core-utils.cts) rather than re-implementing it —
|
|
91
|
+
// this call site previously diverged from it (no transliteration, no
|
|
92
|
+
// 60-char truncation). Lazy require to break the core-utils.cjs cycle
|
|
93
|
+
// (see the module dependency doc comment above).
|
|
94
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
|
95
|
+
return require('./core-utils.cjs').generateSlugInternal(String(name ?? ''), null) ?? '';
|
|
75
96
|
}
|
|
76
97
|
/**
|
|
77
98
|
* Returns true when `name` is a valid active workstream name:
|
|
@@ -94,10 +94,13 @@ function parseJsonc(text) {
|
|
|
94
94
|
}
|
|
95
95
|
// ─── Message constants (verbatim — downstream docs/tests depend on these) ─────
|
|
96
96
|
function buildMsgDiverged(headSha, forkRef, forkSha) {
|
|
97
|
-
return `⚠ Worktree base mismatch: HEAD (${shortSha(headSha)}) differs from ${forkRef} (${shortSha(forkSha)}). Running this phase sequentially on the main working tree.
|
|
97
|
+
return `⚠ Worktree base mismatch: HEAD (${shortSha(headSha)}) differs from ${forkRef} (${shortSha(forkSha)}). Running this phase sequentially on the main working tree. Parallel worktrees return once HEAD is merged/pushed so ${forkRef} matches it. (worktree.baseRef:"head" applies only where GSD itself creates the worktree — the runtime harness does not read it; #48, #3659.)`;
|
|
98
98
|
}
|
|
99
|
-
const MSG_UNKNOWN = `⚠ Cannot determine the worktree fork base (origin/HEAD unresolved). Running this phase sequentially on the main working tree to avoid a base mismatch.
|
|
100
|
-
|
|
99
|
+
const MSG_UNKNOWN = `⚠ Cannot determine the worktree fork base (origin/HEAD unresolved). Running this phase sequentially on the main working tree to avoid a base mismatch. Parallel worktrees return once origin/HEAD resolves and matches HEAD. See #683, #3659.`;
|
|
100
|
+
function buildMsgBaserefHeadIgnored(headSha, forkRef, forkSha) {
|
|
101
|
+
return `⚠ Worktree base mismatch: worktree.baseRef:"head" is set, but the runtime harness does not honor it for isolated dispatch — the fork base stays ${forkRef} (${shortSha(forkSha)}) while HEAD is ${shortSha(headSha)} (#48; upstream claude-code#44965). Running this phase sequentially on the main working tree. Parallel worktrees return once HEAD is merged/pushed so ${forkRef} matches it, or on runtimes where GSD itself manages worktree creation. See #3659.`;
|
|
102
|
+
}
|
|
103
|
+
const MSG_HEAD_UNRESOLVABLE = `⚠ Cannot determine the worktree base (git rev-parse HEAD did not return a definitive answer). Running this phase sequentially on the main working tree to avoid an unverified base mismatch. Note: worktree.baseRef:"head" silences this check only where GSD itself creates the worktree (orchestrator-managed runtimes) — in harness mode it never applied (#48, #3659). Retry; if it persists, check for a stalled filesystem mount or a stale git index lock (.git/index.lock). See #683, #3050.`;
|
|
101
104
|
/**
|
|
102
105
|
* Returns true when an execGit result indicates the subprocess was killed by
|
|
103
106
|
* a timeout. A timeout means the command genuinely could not complete — it
|
|
@@ -228,7 +231,20 @@ function resolveEffectiveBaseRef(claudeDir, deps, userClaudeDir) {
|
|
|
228
231
|
* deps.userClaudeDir overrides the user/global config directory resolution
|
|
229
232
|
* (default: getGlobalConfigDir('claude'), which honours CLAUDE_CONFIG_DIR).
|
|
230
233
|
*/
|
|
231
|
-
function cmdWorktreeBaseCheck(cwd,
|
|
234
|
+
function cmdWorktreeBaseCheck(cwd, args, deps) {
|
|
235
|
+
// --mode threads the dispatch isolation mode through to the evaluation
|
|
236
|
+
// (#3659): 'harness-worktree' (default) or 'orchestrator-worktree'. Invalid
|
|
237
|
+
// or missing values after --mode fail closed — a silently defaulted typo
|
|
238
|
+
// would re-open the hole the flag exists to close.
|
|
239
|
+
let isolationMode = 'harness-worktree';
|
|
240
|
+
const modeIdx = args.indexOf('--mode');
|
|
241
|
+
if (modeIdx !== -1) {
|
|
242
|
+
const value = args[modeIdx + 1];
|
|
243
|
+
if (value !== 'harness-worktree' && value !== 'orchestrator-worktree') {
|
|
244
|
+
throw new Error(`worktree base-check: --mode must be harness-worktree or orchestrator-worktree, got ${JSON.stringify(value ?? null)}`);
|
|
245
|
+
}
|
|
246
|
+
isolationMode = value;
|
|
247
|
+
}
|
|
232
248
|
const claudeDir = node_path_1.default.join(cwd, '.claude');
|
|
233
249
|
const userClaudeDir = Object.prototype.hasOwnProperty.call(deps ?? {}, 'userClaudeDir')
|
|
234
250
|
? deps.userClaudeDir
|
|
@@ -238,8 +254,22 @@ function cmdWorktreeBaseCheck(cwd, _args, deps) {
|
|
|
238
254
|
cwd,
|
|
239
255
|
effectiveBaseRef,
|
|
240
256
|
execGit: deps?.execGit,
|
|
257
|
+
isolationMode,
|
|
258
|
+
});
|
|
259
|
+
// Default emit goes through fs.writeSync(1, …), NOT process.stdout.write:
|
|
260
|
+
// the CLI's --pick capture intercepts writeSync, and command substitution
|
|
261
|
+
// is a pipe — via process.stdout.write a `$(gsd-tools … --pick x)` capture
|
|
262
|
+
// received the full JSON instead of the picked field, so the workflow
|
|
263
|
+
// auto-degrade guards never matched (#3659 review). Short-count loop per
|
|
264
|
+
// io.cjs writeAllSync's rationale (a non-blocking pipe can accept partial
|
|
265
|
+
// writes).
|
|
266
|
+
const write = deps?.write ?? ((s) => {
|
|
267
|
+
const buf = Buffer.from(s, 'utf8');
|
|
268
|
+
let offset = 0;
|
|
269
|
+
while (offset < buf.length) {
|
|
270
|
+
offset += node_fs_1.default.writeSync(1, buf, offset, buf.length - offset);
|
|
271
|
+
}
|
|
241
272
|
});
|
|
242
|
-
const write = deps?.write ?? ((s) => process.stdout.write(s));
|
|
243
273
|
write(JSON.stringify(result, null, 2) + '\n');
|
|
244
274
|
return result;
|
|
245
275
|
}
|
|
@@ -295,7 +325,20 @@ function cmdWorktreeSetBaseRef(cwd, _args, deps) {
|
|
|
295
325
|
baseRef: 'head',
|
|
296
326
|
file,
|
|
297
327
|
};
|
|
298
|
-
|
|
328
|
+
// Default emit goes through fs.writeSync(1, …), NOT process.stdout.write:
|
|
329
|
+
// the CLI's --pick capture intercepts writeSync, and command substitution
|
|
330
|
+
// is a pipe — via process.stdout.write a `$(gsd-tools … --pick x)` capture
|
|
331
|
+
// received the full JSON instead of the picked field, so the workflow
|
|
332
|
+
// auto-degrade guards never matched (#3659 review). Short-count loop per
|
|
333
|
+
// io.cjs writeAllSync's rationale (a non-blocking pipe can accept partial
|
|
334
|
+
// writes).
|
|
335
|
+
const write = deps?.write ?? ((s) => {
|
|
336
|
+
const buf = Buffer.from(s, 'utf8');
|
|
337
|
+
let offset = 0;
|
|
338
|
+
while (offset < buf.length) {
|
|
339
|
+
offset += node_fs_1.default.writeSync(1, buf, offset, buf.length - offset);
|
|
340
|
+
}
|
|
341
|
+
});
|
|
299
342
|
write(JSON.stringify(output, null, 2) + '\n');
|
|
300
343
|
return output;
|
|
301
344
|
}
|
|
@@ -311,12 +354,19 @@ function evaluateWorktreeBaseDegrade(deps) {
|
|
|
311
354
|
const execGit = deps?.execGit ?? shell_command_projection_cjs_1.execGit;
|
|
312
355
|
const cwd = deps?.cwd;
|
|
313
356
|
const cwdOpts = cwd ? { cwd } : {};
|
|
314
|
-
// a.
|
|
315
|
-
//
|
|
316
|
-
//
|
|
317
|
-
//
|
|
318
|
-
//
|
|
319
|
-
|
|
357
|
+
// a. baseRef 'head' suppresses ONLY where GSD controls the fork start-point
|
|
358
|
+
// (#3659). The former unconditional suppress trusted the harness to honor the
|
|
359
|
+
// setting; #48 verified 5/5 that the Agent-isolation dispatch path never
|
|
360
|
+
// routes through project settings (upstream claude-code#44965), so in
|
|
361
|
+
// harness mode the fork base is always origin/HEAD and 'head' must fall
|
|
362
|
+
// through to the same comparison the fresh path runs. In
|
|
363
|
+
// orchestrator-worktree mode GSD itself runs `git worktree add <path>
|
|
364
|
+
// <start-point>` with the orchestrator HEAD — 'head' is honored by
|
|
365
|
+
// construction there and the suppress is correct. Any non-"head" value
|
|
366
|
+
// (including "fresh" and absent/null) has fresh/origin-HEAD semantics and is
|
|
367
|
+
// evaluated against origin/HEAD as before. (Reference: #683, #48, #3659.)
|
|
368
|
+
const headIgnoredByHarness = deps?.effectiveBaseRef === 'head';
|
|
369
|
+
if (headIgnoredByHarness && (deps?.isolationMode ?? 'harness-worktree') === 'orchestrator-worktree') {
|
|
320
370
|
return { shouldDegrade: false, reason: 'baseref-head', message: null, headSha: null, forkRef: null, forkSha: null, headAbsenceVerified: null };
|
|
321
371
|
}
|
|
322
372
|
// b. Resolve HEAD sha.
|
|
@@ -389,6 +439,10 @@ function evaluateWorktreeBaseDegrade(deps) {
|
|
|
389
439
|
if (forkSha === headSha) {
|
|
390
440
|
return { shouldDegrade: false, reason: 'head-matches-fork', message: null, headSha, forkRef, forkSha, headAbsenceVerified: null };
|
|
391
441
|
}
|
|
442
|
+
if (headIgnoredByHarness) {
|
|
443
|
+
const message = buildMsgBaserefHeadIgnored(headSha, forkRef, forkSha);
|
|
444
|
+
return { shouldDegrade: true, reason: 'baseref-head-ignored-by-harness', message, headSha, forkRef, forkSha, headAbsenceVerified: null };
|
|
445
|
+
}
|
|
392
446
|
const message = buildMsgDiverged(headSha, forkRef, forkSha);
|
|
393
447
|
return { shouldDegrade: true, reason: 'head-diverged-from-fork', message, headSha, forkRef, forkSha, headAbsenceVerified: null };
|
|
394
448
|
}
|