@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
|
@@ -366,13 +366,32 @@ function normalizeCleanupManifestEntry(entry) {
|
|
|
366
366
|
return null;
|
|
367
367
|
const rawAllowedBases = Array.isArray(e.allowed_bases) ? e.allowed_bases : [];
|
|
368
368
|
const allowedBases = Array.from(new Set([expectedBase, ...rawAllowedBases.filter((base) => typeof base === 'string' && base.length > 0)]));
|
|
369
|
-
|
|
369
|
+
// #2596: liberal in what we accept — non-array, or non-string / empty
|
|
370
|
+
// elements, are dropped rather than coerced. An EMPTY result omits the field
|
|
371
|
+
// entirely, so "declared nothing" is indistinguishable from "not recorded":
|
|
372
|
+
// that ambiguity is already resolved as *unknown* by the per-plan submodule
|
|
373
|
+
// gate's own `[ -z "$PLAN_FILES" ]` rule, and inventing a second rule here
|
|
374
|
+
// would make an unrecorded plan look 100% out of scope.
|
|
375
|
+
const filesModified = (Array.isArray(e.files_modified) ? e.files_modified : [])
|
|
376
|
+
.filter((f) => typeof f === 'string' && f.trim().length > 0);
|
|
377
|
+
// #3003: same liberal-in-what-we-accept rule as `files_modified` above — non-array,
|
|
378
|
+
// or non-string / empty elements, are dropped rather than coerced, and an EMPTY
|
|
379
|
+
// result omits the field entirely so "declares nothing" stays indistinguishable
|
|
380
|
+
// from "not recorded" (the guard's own absence-check already treats both as unknown).
|
|
381
|
+
const declaredDeletions = (Array.isArray(e.declared_deletions) ? e.declared_deletions : [])
|
|
382
|
+
.filter((f) => typeof f === 'string' && f.trim().length > 0);
|
|
383
|
+
const normalized = {
|
|
370
384
|
agent_id: typeof e.agent_id === 'string' ? e.agent_id : null,
|
|
371
385
|
worktree_path: worktreePath,
|
|
372
386
|
branch,
|
|
373
387
|
expected_base: expectedBase,
|
|
374
388
|
allowed_bases: allowedBases,
|
|
375
389
|
};
|
|
390
|
+
if (filesModified.length > 0)
|
|
391
|
+
normalized.files_modified = filesModified;
|
|
392
|
+
if (declaredDeletions.length > 0)
|
|
393
|
+
normalized.declared_deletions = declaredDeletions;
|
|
394
|
+
return normalized;
|
|
376
395
|
}
|
|
377
396
|
function normalizeCleanupManifest(manifest) {
|
|
378
397
|
let parsed = manifest;
|
|
@@ -461,6 +480,102 @@ function repoRootStillMidMerge(execGit, repoRoot) {
|
|
|
461
480
|
return false; // ref not found — repoRoot is not mid-merge
|
|
462
481
|
return true; // any other exit code (e.g. a fatal git error) — fail closed
|
|
463
482
|
}
|
|
483
|
+
// #2596: the single definition of "this file is an executor-written SUMMARY
|
|
484
|
+
// artifact". Shared by `defaultFindSummaryFiles` (which walks for them to
|
|
485
|
+
// rescue) and the scope advisory below (which must never flag them) — a plan's
|
|
486
|
+
// declared `files_modified` never lists a SUMMARY, because the executor writes
|
|
487
|
+
// it by orchestration contract, so a second copy of this rule would make the
|
|
488
|
+
// advisory fire on essentially every wave.
|
|
489
|
+
const SUMMARY_ARTIFACT_DIR = '.planning';
|
|
490
|
+
const SUMMARY_ARTIFACT_SUFFIX = 'SUMMARY.md';
|
|
491
|
+
/**
|
|
492
|
+
* Decode a git-quoted path. With `core.quotepath` left at its default (`true`)
|
|
493
|
+
* git wraps any path containing non-ASCII or special bytes in double quotes
|
|
494
|
+
* and C-escapes it — e.g. `tests/é.ts` is emitted as the literal
|
|
495
|
+
* `"tests/\303\251.ts"`. Both sides of the deletion/scope comparison
|
|
496
|
+
* (a declared path and a git-reported path) must agree on the same decoded
|
|
497
|
+
* shape, and decoding it here — rather than passing `-c core.quotepath=false`
|
|
498
|
+
* on the `execGit` call — keeps the git argv, and therefore every existing
|
|
499
|
+
* test fixture that asserts on exact argv, unchanged. It also works
|
|
500
|
+
* regardless of the user's own `core.quotepath` config.
|
|
501
|
+
*
|
|
502
|
+
* A value that is not wrapped in a leading and trailing `"` is returned
|
|
503
|
+
* completely untouched — this is the overwhelmingly common (plain ASCII)
|
|
504
|
+
* case and must not be altered in any way.
|
|
505
|
+
*
|
|
506
|
+
* Escapes decode to BYTES, collected into a Buffer and decoded as UTF-8 only
|
|
507
|
+
* at the end: `\303\251` is two bytes that together form one character (é),
|
|
508
|
+
* so decoding them one at a time would produce mojibake. Malformed input
|
|
509
|
+
* (a trailing lone backslash, or an octal escape with fewer than three
|
|
510
|
+
* digits) never throws — it degrades to treating the character literally, so
|
|
511
|
+
* a single bad path can never take down the whole cleanup wave.
|
|
512
|
+
*/
|
|
513
|
+
function decodeGitQuotedPath(raw) {
|
|
514
|
+
if (raw.length < 2 || !raw.startsWith('"') || !raw.endsWith('"'))
|
|
515
|
+
return raw;
|
|
516
|
+
const body = raw.slice(1, -1);
|
|
517
|
+
const bytes = [];
|
|
518
|
+
for (let i = 0; i < body.length; i++) {
|
|
519
|
+
const ch = body[i];
|
|
520
|
+
if (ch !== '\\' || i === body.length - 1) {
|
|
521
|
+
// UTF-8 bytes, not the code unit: a DECLARED path may be quoted while
|
|
522
|
+
// still holding a literal `é`, and pushing 0xE9 alone is invalid UTF-8.
|
|
523
|
+
// codePointAt keeps a surrogate pair together.
|
|
524
|
+
const codePoint = body.codePointAt(i);
|
|
525
|
+
const char = codePoint === undefined ? ch : String.fromCodePoint(codePoint);
|
|
526
|
+
bytes.push(...Buffer.from(char, 'utf8'));
|
|
527
|
+
i += char.length - 1;
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
530
|
+
const rest = body.slice(i + 1);
|
|
531
|
+
const octalMatch = /^([0-3][0-7][0-7])/.exec(rest);
|
|
532
|
+
if (octalMatch) {
|
|
533
|
+
bytes.push(parseInt(octalMatch[1], 8));
|
|
534
|
+
i += 3;
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
const next = body[i + 1];
|
|
538
|
+
const CONTROL_ESCAPES = {
|
|
539
|
+
a: 0x07, b: 0x08, f: 0x0c, n: 0x0a, r: 0x0d, t: 0x09, v: 0x0b,
|
|
540
|
+
'\\': 0x5c, '"': 0x22,
|
|
541
|
+
};
|
|
542
|
+
if (Object.prototype.hasOwnProperty.call(CONTROL_ESCAPES, next)) {
|
|
543
|
+
bytes.push(CONTROL_ESCAPES[next]);
|
|
544
|
+
}
|
|
545
|
+
else {
|
|
546
|
+
bytes.push(next.charCodeAt(0));
|
|
547
|
+
}
|
|
548
|
+
i += 1;
|
|
549
|
+
}
|
|
550
|
+
return Buffer.from(bytes).toString('utf8');
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Normalize one path for scope comparison. Applied to BOTH sides so a declared
|
|
554
|
+
* path and a git-reported path meet in the same shape: any git C-quoting is
|
|
555
|
+
* decoded first (order matters — the backslash-to-slash conversion below
|
|
556
|
+
* would destroy the escape sequences if it ran first), then backslashes
|
|
557
|
+
* become slashes unconditionally (a backslash path is not a Windows-only
|
|
558
|
+
* input), and a leading `./` and any trailing `/` are stripped. This is the
|
|
559
|
+
* single normalizer shared by the SUMMARY-artifact predicate and the scope
|
|
560
|
+
* advisory, so the two can never disagree about what `./a\b/` means.
|
|
561
|
+
*/
|
|
562
|
+
function normalizeScopePath(raw) {
|
|
563
|
+
return decodeGitQuotedPath(String(raw || '').trim())
|
|
564
|
+
.replace(/\\/g, '/')
|
|
565
|
+
.trim()
|
|
566
|
+
.replace(/^\.\//, '')
|
|
567
|
+
.replace(/\/+$/, '');
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* True when a worktree-relative path is a SUMMARY artifact. Input may use
|
|
571
|
+
* either separator; normalization to POSIX is unconditional (backslash paths
|
|
572
|
+
* reach Linux too).
|
|
573
|
+
*/
|
|
574
|
+
function isSummaryArtifactRelPath(relPath) {
|
|
575
|
+
const normalized = normalizeScopePath(relPath);
|
|
576
|
+
return normalized.startsWith(`${SUMMARY_ARTIFACT_DIR}/`)
|
|
577
|
+
&& normalized.endsWith(SUMMARY_ARTIFACT_SUFFIX);
|
|
578
|
+
}
|
|
464
579
|
/**
|
|
465
580
|
* Walk <worktreePath>/.planning/ recursively and collect absolute paths of
|
|
466
581
|
* all files whose names match *SUMMARY.md. Returns [] when the directory
|
|
@@ -470,7 +585,7 @@ function repoRootStillMidMerge(execGit, repoRoot) {
|
|
|
470
585
|
* find "$WT/.planning" -name "*SUMMARY.md"
|
|
471
586
|
*/
|
|
472
587
|
function defaultFindSummaryFiles(worktreePath) {
|
|
473
|
-
const planningDir = node_path_1.default.join(worktreePath,
|
|
588
|
+
const planningDir = node_path_1.default.join(worktreePath, SUMMARY_ARTIFACT_DIR);
|
|
474
589
|
const results = [];
|
|
475
590
|
function walk(dir) {
|
|
476
591
|
let entries;
|
|
@@ -485,7 +600,7 @@ function defaultFindSummaryFiles(worktreePath) {
|
|
|
485
600
|
if (entry.isDirectory()) {
|
|
486
601
|
walk(full);
|
|
487
602
|
}
|
|
488
|
-
else if (entry.isFile() && entry.name.endsWith(
|
|
603
|
+
else if (entry.isFile() && entry.name.endsWith(SUMMARY_ARTIFACT_SUFFIX)) {
|
|
489
604
|
results.push(full);
|
|
490
605
|
}
|
|
491
606
|
}
|
|
@@ -588,6 +703,113 @@ function rescueSummaryArtifacts(worktreePath, repoRoot, deps) {
|
|
|
588
703
|
}
|
|
589
704
|
return { rescuedRelPaths, failures };
|
|
590
705
|
}
|
|
706
|
+
/**
|
|
707
|
+
* #2596: advisory codes emitted by the wave-cleanup gauntlet. Frozen and
|
|
708
|
+
* exported so tests assert on a code rather than on rendered prose (this repo
|
|
709
|
+
* forbids raw-text matching on test output).
|
|
710
|
+
*/
|
|
711
|
+
const WAVE_CLEANUP_WARNING = Object.freeze({
|
|
712
|
+
/** A committed path fell outside the plan's declared `files_modified`. */
|
|
713
|
+
SCOPE_OUT_OF_DECLARED: 'scope_out_of_declared',
|
|
714
|
+
/** The scope diff could not be computed, so conformance is unknown. */
|
|
715
|
+
SCOPE_CHECK_UNAVAILABLE: 'scope_check_unavailable',
|
|
716
|
+
});
|
|
717
|
+
/**
|
|
718
|
+
* The literal directory prefix a declared path covers, or `null` when the
|
|
719
|
+
* pattern begins with a glob metacharacter and therefore has no usable prefix.
|
|
720
|
+
*
|
|
721
|
+
* Deliberately literal-prefix only — NOT a glob engine. A hand-rolled
|
|
722
|
+
* `**`/`*`/`?` matcher inside a worktree-lifecycle module is an informal,
|
|
723
|
+
* undocumented pattern language living where no language belongs, and this
|
|
724
|
+
* repo forbids external deps in core. The submodule-intersection gate
|
|
725
|
+
* (`workflows/execute-phase/steps/per-plan-worktree-gate.md`) already ships
|
|
726
|
+
* exactly this glob-prefix rule; reusing it beats inventing a second one.
|
|
727
|
+
*
|
|
728
|
+
* `null` (no literal prefix, e.g. `*.md`) means "matches everything": for an
|
|
729
|
+
* ADVISORY, a false alarm costs more than a miss, so the ambiguous case
|
|
730
|
+
* suppresses rather than shouts.
|
|
731
|
+
*/
|
|
732
|
+
function declaredScopePrefix(declared) {
|
|
733
|
+
const globAt = declared.search(/[*?[]/);
|
|
734
|
+
if (globAt < 0)
|
|
735
|
+
return declared;
|
|
736
|
+
const literal = declared.slice(0, globAt).replace(/\/+$/, '');
|
|
737
|
+
return literal.length > 0 ? literal : null;
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* #2596: compare a branch's actual committed paths against the plan's declared
|
|
741
|
+
* scope. Pure — no git, no IO. Returns one warning per out-of-scope path, in
|
|
742
|
+
* the order the paths were given. Returns [] when nothing usable was declared:
|
|
743
|
+
* absence of data is not evidence of over-reach.
|
|
744
|
+
*/
|
|
745
|
+
function planWaveScopeConformance(changedPaths, declaredFiles, branch) {
|
|
746
|
+
if (!Array.isArray(declaredFiles))
|
|
747
|
+
return [];
|
|
748
|
+
const prefixes = [];
|
|
749
|
+
for (const declared of declaredFiles) {
|
|
750
|
+
if (typeof declared !== 'string')
|
|
751
|
+
continue;
|
|
752
|
+
const normalized = normalizeScopePath(declared);
|
|
753
|
+
if (!normalized)
|
|
754
|
+
continue;
|
|
755
|
+
prefixes.push(declaredScopePrefix(normalized));
|
|
756
|
+
}
|
|
757
|
+
if (prefixes.length === 0)
|
|
758
|
+
return [];
|
|
759
|
+
const warnings = [];
|
|
760
|
+
const seen = new Set();
|
|
761
|
+
for (const raw of Array.isArray(changedPaths) ? changedPaths : []) {
|
|
762
|
+
if (typeof raw !== 'string')
|
|
763
|
+
continue;
|
|
764
|
+
const changed = normalizeScopePath(raw);
|
|
765
|
+
if (!changed || seen.has(changed))
|
|
766
|
+
continue;
|
|
767
|
+
seen.add(changed);
|
|
768
|
+
if (isSummaryArtifactRelPath(changed))
|
|
769
|
+
continue;
|
|
770
|
+
const covered = prefixes.some((prefix) => (prefix === null || changed === prefix || changed.startsWith(`${prefix}/`)));
|
|
771
|
+
if (covered)
|
|
772
|
+
continue;
|
|
773
|
+
warnings.push({ code: WAVE_CLEANUP_WARNING.SCOPE_OUT_OF_DECLARED, branch, path: changed });
|
|
774
|
+
}
|
|
775
|
+
return warnings;
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* #3003: split git's reported deletions into declared and undeclared.
|
|
779
|
+
*
|
|
780
|
+
* EXACT match after `normalizeScopePath` — the same normalizer both other path
|
|
781
|
+
* comparisons in this file use, so a declared path and a git-reported path meet in the
|
|
782
|
+
* same shape (`a\b` and `./a/b/` both become `a/b`).
|
|
783
|
+
*
|
|
784
|
+
* Deliberately NOT `declaredScopePrefix`. That helper returns `null` for a glob-leading
|
|
785
|
+
* pattern meaning "matches everything", which is right for the ADVISORY it serves — a
|
|
786
|
+
* false alarm there costs more than a miss — and exactly wrong for a GATE, where it would
|
|
787
|
+
* let `["*.ts"]` disarm the guard. A glob here is simply a literal path that matches
|
|
788
|
+
* nothing. Prefix matching is likewise refused: `["tests"]` must not authorize deleting
|
|
789
|
+
* everything under tests/.
|
|
790
|
+
*
|
|
791
|
+
* Pure — no git, no IO. Returns the undeclared residue in the order git reported it.
|
|
792
|
+
*/
|
|
793
|
+
function partitionDeclaredDeletions(deletedPaths, declared) {
|
|
794
|
+
const allowed = new Set((Array.isArray(declared) ? declared : [])
|
|
795
|
+
.filter((p) => typeof p === 'string')
|
|
796
|
+
.map((p) => normalizeScopePath(p))
|
|
797
|
+
.filter((p) => p.length > 0));
|
|
798
|
+
const undeclared = [];
|
|
799
|
+
const seen = new Set();
|
|
800
|
+
for (const raw of Array.isArray(deletedPaths) ? deletedPaths : []) {
|
|
801
|
+
if (typeof raw !== 'string')
|
|
802
|
+
continue;
|
|
803
|
+
const normalized = normalizeScopePath(raw);
|
|
804
|
+
if (!normalized || seen.has(normalized))
|
|
805
|
+
continue;
|
|
806
|
+
seen.add(normalized);
|
|
807
|
+
if (allowed.has(normalized))
|
|
808
|
+
continue;
|
|
809
|
+
undeclared.push(normalized);
|
|
810
|
+
}
|
|
811
|
+
return undeclared;
|
|
812
|
+
}
|
|
591
813
|
function executeWorktreeWaveCleanupPlan(plan, deps = {}) {
|
|
592
814
|
const execGit = deps.execGit || execGitDefault;
|
|
593
815
|
const entries = Array.isArray(plan?.entries) ? plan.entries : [];
|
|
@@ -598,10 +820,12 @@ function executeWorktreeWaveCleanupPlan(plan, deps = {}) {
|
|
|
598
820
|
reason: plan ? (plan.reason || 'missing_entries') : 'missing_plan',
|
|
599
821
|
entries: [],
|
|
600
822
|
pending: entries,
|
|
823
|
+
warnings: [],
|
|
601
824
|
};
|
|
602
825
|
}
|
|
603
826
|
const results = [];
|
|
604
827
|
const pending = [];
|
|
828
|
+
const allWarnings = [];
|
|
605
829
|
let ok = true;
|
|
606
830
|
// #2852: every per-entry failure site marks the SAME shape — status='blocked',
|
|
607
831
|
// a reason code, the captured stderr, push to results, flip the overall `ok`
|
|
@@ -622,6 +846,7 @@ function executeWorktreeWaveCleanupPlan(plan, deps = {}) {
|
|
|
622
846
|
status: 'pending',
|
|
623
847
|
reason: null,
|
|
624
848
|
stderr: '',
|
|
849
|
+
warnings: [],
|
|
625
850
|
};
|
|
626
851
|
const branchCheck = execGit(['-C', entry.worktree_path, 'rev-parse', '--abbrev-ref', 'HEAD'], { cwd: plan.repoRoot });
|
|
627
852
|
if (!gitResultOk(branchCheck) || branchCheck.stdout.trim() !== entry.branch) {
|
|
@@ -644,13 +869,57 @@ function executeWorktreeWaveCleanupPlan(plan, deps = {}) {
|
|
|
644
869
|
continue; // #2852: isolate
|
|
645
870
|
}
|
|
646
871
|
if (deletions.stdout) {
|
|
647
|
-
//
|
|
648
|
-
//
|
|
649
|
-
//
|
|
650
|
-
//
|
|
651
|
-
//
|
|
652
|
-
|
|
653
|
-
|
|
872
|
+
// #3003: a deletion the PLAN declared is authorized; anything else still blocks.
|
|
873
|
+
// Only a SUCCESSFUL check reaches here — a failed one blocked above on its own
|
|
874
|
+
// reason, so a broken check can never be filtered into a pass.
|
|
875
|
+
//
|
|
876
|
+
// The block detail carries ONLY the undeclared residue. Listing declared paths
|
|
877
|
+
// there would misdirect the operator toward paths that were fine.
|
|
878
|
+
const undeclaredDeletions = partitionDeclaredDeletions(deletions.stdout.split('\n'), entry.declared_deletions);
|
|
879
|
+
if (undeclaredDeletions.length > 0) {
|
|
880
|
+
blockEntry(result, 'branch_contains_deletions', undeclaredDeletions.join('\n'));
|
|
881
|
+
continue; // #2852: isolate
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
// #2596: advisory scope conformance — does the branch's ACTUAL committed
|
|
885
|
+
// diff stay inside the scope the plan declared? Gated on a declared scope
|
|
886
|
+
// being present: with nothing declared there is nothing to compare, so no
|
|
887
|
+
// git subprocess is spent at all (and every pre-#2596 fixture, none of
|
|
888
|
+
// which declares one, issues exactly the git calls it always did).
|
|
889
|
+
//
|
|
890
|
+
// ADVISORY ONLY. Unlike the deletions check above, a finding here does NOT
|
|
891
|
+
// call blockEntry and does NOT touch `ok` — the merge proceeds. Promotion
|
|
892
|
+
// to a hard gate is a separate, disclosed change.
|
|
893
|
+
// #3003: a declared deletion is in scope by construction — `git diff --name-only`
|
|
894
|
+
// includes deleted paths, so without accounting for the declaration, authorizing a
|
|
895
|
+
// deletion would immediately warn that the same path is out of declared scope.
|
|
896
|
+
//
|
|
897
|
+
// It is SUBTRACTED from the findings rather than UNIONED into the declared scope,
|
|
898
|
+
// and the difference is not cosmetic. `planWaveScopeConformance` reads its scope
|
|
899
|
+
// list with prefix-and-glob semantics, so unioning would silently hand
|
|
900
|
+
// `declared_deletions` a second, WIDER matching rule than the gate gives it:
|
|
901
|
+
// `["*.md"]` (inert at the gate) would yield a null prefix meaning "matches
|
|
902
|
+
// everything" and mute the advisory entirely, and `["src"]` would mute all of
|
|
903
|
+
// `src/`. One field with two matching rules is a trap. Subtracting keeps the
|
|
904
|
+
// field exact-match-only on every surface it touches.
|
|
905
|
+
//
|
|
906
|
+
// Gating stays on `files_modified` alone for the same reason: a plan that declares
|
|
907
|
+
// only deletions has still declared no modification scope, so the advisory stays
|
|
908
|
+
// exactly as silent as it was before this change instead of warning on every
|
|
909
|
+
// modified path.
|
|
910
|
+
const declaredFiles = Array.isArray(entry.files_modified) ? entry.files_modified : [];
|
|
911
|
+
if (declaredFiles.length > 0) {
|
|
912
|
+
const scopeDiff = execGit(['diff', '--name-only', `HEAD...${entry.branch}`], { cwd: plan.repoRoot });
|
|
913
|
+
const scopeWarnings = !gitResultOk(scopeDiff)
|
|
914
|
+
// A broken advisory must never become a gate: record that conformance
|
|
915
|
+
// is unknown rather than blocking (or, worse, silently passing).
|
|
916
|
+
? [{ code: WAVE_CLEANUP_WARNING.SCOPE_CHECK_UNAVAILABLE, branch: entry.branch, path: null }]
|
|
917
|
+
: planWaveScopeConformance((scopeDiff.stdout || '').split('\n'), declaredFiles, entry.branch)
|
|
918
|
+
// A path-less warning (SCOPE_CHECK_UNAVAILABLE) is never subtracted.
|
|
919
|
+
.filter((w) => w.path === null
|
|
920
|
+
|| partitionDeclaredDeletions([w.path], entry.declared_deletions).length > 0);
|
|
921
|
+
result.warnings.push(...scopeWarnings);
|
|
922
|
+
allWarnings.push(...scopeWarnings);
|
|
654
923
|
}
|
|
655
924
|
// Safety net: rescue uncommitted SUMMARY.md artifacts before the dirty check.
|
|
656
925
|
// The executor leaves <quick_id>-SUMMARY.md uncommitted by contract — the
|
|
@@ -737,6 +1006,7 @@ function executeWorktreeWaveCleanupPlan(plan, deps = {}) {
|
|
|
737
1006
|
reason: ok ? 'ok' : 'cleanup_blocked',
|
|
738
1007
|
entries: results,
|
|
739
1008
|
pending,
|
|
1009
|
+
warnings: allWarnings,
|
|
740
1010
|
};
|
|
741
1011
|
}
|
|
742
1012
|
function cmdWorktreeCleanupWave(cwd, args = []) {
|
|
@@ -777,6 +1047,15 @@ function cmdWorktreeCleanupWave(cwd, args = []) {
|
|
|
777
1047
|
process.exitCode = 1;
|
|
778
1048
|
}
|
|
779
1049
|
}
|
|
1050
|
+
/**
|
|
1051
|
+
* #2596: split a `--files` value into declared paths. Whitespace-separated,
|
|
1052
|
+
* matching the `PLAN_FILES` shape the per-plan worktree gate already builds
|
|
1053
|
+
* with `jq -r '.files_modified // [] | join(" ")'`. Values are DATA compared
|
|
1054
|
+
* against a diff — never opened, never passed to a shell.
|
|
1055
|
+
*/
|
|
1056
|
+
function parseDeclaredScopeFlag(raw) {
|
|
1057
|
+
return String(raw || '').split(/\s+/).filter((token) => token.length > 0);
|
|
1058
|
+
}
|
|
780
1059
|
/**
|
|
781
1060
|
* Pure planner for the per-agent wave-manifest append.
|
|
782
1061
|
*
|
|
@@ -793,8 +1072,9 @@ function cmdWorktreeCleanupWave(cwd, args = []) {
|
|
|
793
1072
|
* rejected loudly — the reader dedups on that key, so a re-record would be
|
|
794
1073
|
* silently dropped (the failure mode this verb exists to eliminate). The
|
|
795
1074
|
* on-disk shape stays the existing 4-field entry (`agent_id`, `worktree_path`,
|
|
796
|
-
* `branch`, `expected_base`)
|
|
797
|
-
* `
|
|
1075
|
+
* `branch`, `expected_base`) unless `--files` declares a scope, in which case
|
|
1076
|
+
* an optional `files_modified` is appended (#2596); the reader still
|
|
1077
|
+
* re-derives `allowed_bases`.
|
|
798
1078
|
*/
|
|
799
1079
|
function planWorktreeRecordAgent(manifestRaw, fields) {
|
|
800
1080
|
// 1. Write-strict required-field check (loud, with which flag is missing).
|
|
@@ -824,11 +1104,17 @@ function planWorktreeRecordAgent(manifestRaw, fields) {
|
|
|
824
1104
|
}
|
|
825
1105
|
// 2. Shared validation: run the candidate through the reader's normalizer.
|
|
826
1106
|
// If it returns null the reader would drop this entry on read — reject now.
|
|
1107
|
+
const declaredScope = parseDeclaredScopeFlag(fields.files);
|
|
1108
|
+
// #3003: reuse parseDeclaredScopeFlag — a blank/absent --deletions leaves the
|
|
1109
|
+
// entry shape untouched, mirroring the --files rule directly above.
|
|
1110
|
+
const declaredDeletions = parseDeclaredScopeFlag(fields.deletions);
|
|
827
1111
|
const candidate = {
|
|
828
1112
|
agent_id: agentId,
|
|
829
1113
|
worktree_path: worktreePath,
|
|
830
1114
|
branch,
|
|
831
1115
|
expected_base: base,
|
|
1116
|
+
...(declaredScope.length > 0 ? { files_modified: declaredScope } : {}),
|
|
1117
|
+
...(declaredDeletions.length > 0 ? { declared_deletions: declaredDeletions } : {}),
|
|
832
1118
|
};
|
|
833
1119
|
const entry = normalizeCleanupManifestEntry(candidate);
|
|
834
1120
|
if (!entry) {
|
|
@@ -917,6 +1203,16 @@ function planWorktreeRecordAgent(manifestRaw, fields) {
|
|
|
917
1203
|
branch: entry.branch,
|
|
918
1204
|
expected_base: entry.expected_base,
|
|
919
1205
|
};
|
|
1206
|
+
// #2596: only written when a scope was actually declared — conservative in
|
|
1207
|
+
// what we send, so a blank --files leaves the 4-field shape untouched.
|
|
1208
|
+
if (entry.files_modified && entry.files_modified.length > 0) {
|
|
1209
|
+
recorded.files_modified = entry.files_modified;
|
|
1210
|
+
}
|
|
1211
|
+
// #3003: same conservative rule as --files above — a blank --deletions
|
|
1212
|
+
// leaves the entry shape untouched.
|
|
1213
|
+
if (entry.declared_deletions && entry.declared_deletions.length > 0) {
|
|
1214
|
+
recorded.declared_deletions = entry.declared_deletions;
|
|
1215
|
+
}
|
|
920
1216
|
worktrees.push(recorded);
|
|
921
1217
|
return {
|
|
922
1218
|
ok: true,
|
|
@@ -928,7 +1224,7 @@ function planWorktreeRecordAgent(manifestRaw, fields) {
|
|
|
928
1224
|
/**
|
|
929
1225
|
* CLI command: append a validated per-agent entry to a wave cleanup manifest.
|
|
930
1226
|
*
|
|
931
|
-
* Usage: worktree record-agent --manifest <path> --agent-id <id> --path <worktree> --branch <branch> --base <sha>
|
|
1227
|
+
* Usage: worktree record-agent --manifest <path> --agent-id <id> --path <worktree> --branch <branch> --base <sha> [--files "<space-separated paths>"] [--deletions "<space-separated paths>"]
|
|
932
1228
|
*
|
|
933
1229
|
* Fails loudly (non-zero exit + recovery hint on stderr) when a field is
|
|
934
1230
|
* missing/garbled or the manifest is absent/malformed, rather than appending an
|
|
@@ -937,13 +1233,15 @@ function planWorktreeRecordAgent(manifestRaw, fields) {
|
|
|
937
1233
|
function cmdWorktreeRecordAgent(cwd, args = [], deps = {}) {
|
|
938
1234
|
const flag = (name) => {
|
|
939
1235
|
const i = args.indexOf(name);
|
|
940
|
-
|
|
1236
|
+
if (i < 0 || i + 1 >= args.length)
|
|
1237
|
+
return '';
|
|
1238
|
+
return args[i + 1];
|
|
941
1239
|
};
|
|
942
1240
|
const write = deps.write || ((s) => process.stdout.write(s));
|
|
943
1241
|
const writeErr = deps.writeErr || ((s) => process.stderr.write(s));
|
|
944
1242
|
const manifestPath = flag('--manifest');
|
|
945
1243
|
if (!manifestPath) {
|
|
946
|
-
writeErr('Usage: worktree record-agent --manifest <path> --agent-id <id> --path <worktree> --branch <branch> --base <sha
|
|
1244
|
+
writeErr('Usage: worktree record-agent --manifest <path> --agent-id <id> --path <worktree> --branch <branch> --base <sha> [--files "<space-separated paths>"] [--deletions "<space-separated paths>"]\n');
|
|
947
1245
|
process.exitCode = 2;
|
|
948
1246
|
return { ok: false, reason: 'usage', entry: null };
|
|
949
1247
|
}
|
|
@@ -965,6 +1263,8 @@ function cmdWorktreeRecordAgent(cwd, args = [], deps = {}) {
|
|
|
965
1263
|
worktreePath: flag('--path'),
|
|
966
1264
|
branch: flag('--branch'),
|
|
967
1265
|
base: flag('--base'),
|
|
1266
|
+
files: flag('--files'),
|
|
1267
|
+
deletions: flag('--deletions'),
|
|
968
1268
|
});
|
|
969
1269
|
if (!plan.ok || plan.manifest === null) {
|
|
970
1270
|
writeErr(`[gsd] worktree.record-agent: ${plan.reason} — ${plan.hint || ''}\n`);
|
|
@@ -1008,11 +1308,17 @@ function planWorktreeCreate(fields) {
|
|
|
1008
1308
|
entry: null,
|
|
1009
1309
|
};
|
|
1010
1310
|
}
|
|
1311
|
+
const declaredScope = parseDeclaredScopeFlag(fields.files);
|
|
1312
|
+
// #3003: reuse parseDeclaredScopeFlag — a blank/absent --deletions leaves the
|
|
1313
|
+
// entry shape untouched, mirroring the --files rule directly above.
|
|
1314
|
+
const declaredDeletions = parseDeclaredScopeFlag(fields.deletions);
|
|
1011
1315
|
const candidate = {
|
|
1012
1316
|
agent_id: agentId,
|
|
1013
1317
|
worktree_path: worktreePath,
|
|
1014
1318
|
branch,
|
|
1015
1319
|
expected_base: base,
|
|
1320
|
+
...(declaredScope.length > 0 ? { files_modified: declaredScope } : {}),
|
|
1321
|
+
...(declaredDeletions.length > 0 ? { declared_deletions: declaredDeletions } : {}),
|
|
1016
1322
|
};
|
|
1017
1323
|
const entry = normalizeCleanupManifestEntry(candidate);
|
|
1018
1324
|
if (!entry) {
|
|
@@ -1140,7 +1446,7 @@ function executeWorktreeCreatePlan(plan, repoRoot, deps = {}) {
|
|
|
1140
1446
|
* validated manifest entry so the worktree is immediately manageable by
|
|
1141
1447
|
* `worktree cleanup-wave` / `worktree reap-orphans`.
|
|
1142
1448
|
*
|
|
1143
|
-
* Usage: worktree create --manifest <path> --agent-id <id> --path <worktree> --branch <branch> --base <sha> --root <dir>
|
|
1449
|
+
* Usage: worktree create --manifest <path> --agent-id <id> --path <worktree> --branch <branch> --base <sha> --root <dir> [--files "<space-separated paths>"] [--deletions "<space-separated paths>"]
|
|
1144
1450
|
*
|
|
1145
1451
|
* #2584 FIX 1 — ORDERING CONTRACT: every manifest read/parse/shape-validate/
|
|
1146
1452
|
* plan step runs BEFORE the git side effect (step 5). The ONLY manifest
|
|
@@ -1154,13 +1460,15 @@ function executeWorktreeCreatePlan(plan, repoRoot, deps = {}) {
|
|
|
1154
1460
|
function cmdWorktreeCreate(cwd, args = [], deps = {}) {
|
|
1155
1461
|
const flag = (name) => {
|
|
1156
1462
|
const i = args.indexOf(name);
|
|
1157
|
-
|
|
1463
|
+
if (i < 0 || i + 1 >= args.length)
|
|
1464
|
+
return '';
|
|
1465
|
+
return args[i + 1];
|
|
1158
1466
|
};
|
|
1159
1467
|
const write = deps.write || ((s) => process.stdout.write(s));
|
|
1160
1468
|
const writeErr = deps.writeErr || ((s) => process.stderr.write(s));
|
|
1161
1469
|
const manifestPath = flag('--manifest');
|
|
1162
1470
|
if (!manifestPath) {
|
|
1163
|
-
writeErr('Usage: worktree create --manifest <path> --agent-id <id> --path <worktree> --branch <branch> --base <sha> --root <dir
|
|
1471
|
+
writeErr('Usage: worktree create --manifest <path> --agent-id <id> --path <worktree> --branch <branch> --base <sha> --root <dir> [--files "<space-separated paths>"] [--deletions "<space-separated paths>"]\n');
|
|
1164
1472
|
process.exitCode = 2;
|
|
1165
1473
|
return { ok: false, reason: 'usage' };
|
|
1166
1474
|
}
|
|
@@ -1225,6 +1533,8 @@ function cmdWorktreeCreate(cwd, args = [], deps = {}) {
|
|
|
1225
1533
|
worktreePath: flag('--path'),
|
|
1226
1534
|
branch: flag('--branch'),
|
|
1227
1535
|
base: flag('--base'),
|
|
1536
|
+
files: flag('--files'),
|
|
1537
|
+
deletions: flag('--deletions'),
|
|
1228
1538
|
});
|
|
1229
1539
|
if (!plan.ok || !plan.entry) {
|
|
1230
1540
|
writeErr(`[gsd] worktree.create: ${plan.reason} — ${plan.hint || ''}\n`);
|
|
@@ -1291,6 +1601,16 @@ function cmdWorktreeCreate(cwd, args = [], deps = {}) {
|
|
|
1291
1601
|
branch: plan.entry.branch,
|
|
1292
1602
|
expected_base: plan.entry.expected_base,
|
|
1293
1603
|
};
|
|
1604
|
+
// #2596: only written when a scope was actually declared — conservative in
|
|
1605
|
+
// what we send, so a blank --files leaves the 4-field shape untouched.
|
|
1606
|
+
if (Array.isArray(plan.entry.files_modified) && plan.entry.files_modified.length > 0) {
|
|
1607
|
+
recorded.files_modified = plan.entry.files_modified;
|
|
1608
|
+
}
|
|
1609
|
+
// #3003: same conservative rule as --files above — a blank --deletions
|
|
1610
|
+
// leaves the entry shape untouched.
|
|
1611
|
+
if (Array.isArray(plan.entry.declared_deletions) && plan.entry.declared_deletions.length > 0) {
|
|
1612
|
+
recorded.declared_deletions = plan.entry.declared_deletions;
|
|
1613
|
+
}
|
|
1294
1614
|
const dedupeKey = `${recorded.worktree_path}\0${recorded.branch}`;
|
|
1295
1615
|
const alreadyPresent = worktrees.some((existing) => {
|
|
1296
1616
|
const normalized = normalizeCleanupManifestEntry(existing);
|
|
@@ -1677,6 +1997,9 @@ module.exports = {
|
|
|
1677
1997
|
normalizeCleanupManifest,
|
|
1678
1998
|
planWorktreeWaveCleanup,
|
|
1679
1999
|
executeWorktreeWaveCleanupPlan,
|
|
2000
|
+
WAVE_CLEANUP_WARNING,
|
|
2001
|
+
planWaveScopeConformance,
|
|
2002
|
+
isSummaryArtifactRelPath,
|
|
1680
2003
|
cmdWorktreeCleanupWave,
|
|
1681
2004
|
planWorktreeRecordAgent,
|
|
1682
2005
|
cmdWorktreeRecordAgent,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_comment": "Canonical CONFIG_DEFAULTS for the Configuration Module. Nested shape is canonical. CJS flat projection (branching_strategy, sub_repos, etc.) is handled by consumers at the boundary. Security keys (security_enforcement, security_asvs_level, security_block_on) and post_planning_gaps live in workflow.* as their canonical location. resolve_model_ids, context_window, phase_naming are CJS-originated top-level keys included here. brave_search, firecrawl, exa_search default to false in the manifest; at runtime buildNewProjectConfig detects API keys. The plan_checker (CJS flat)
|
|
2
|
+
"_comment": "Canonical CONFIG_DEFAULTS for the Configuration Module. Nested shape is canonical. CJS flat projection (branching_strategy, sub_repos, etc.) is handled by consumers at the boundary. Security keys (security_enforcement, security_asvs_level, security_block_on) and post_planning_gaps live in workflow.* as their canonical location. resolve_model_ids, context_window, phase_naming are CJS-originated top-level keys included here. brave_search, firecrawl, exa_search default to false in the manifest; at runtime buildNewProjectConfig detects API keys. The plan_checker (CJS flat) \u2192 workflow.plan_check (canonical nested) divergence is resolved: canonical name is workflow.plan_check. _auto_chain_active is a runtime-state field included for completeness.",
|
|
3
3
|
"model_profile": "balanced",
|
|
4
4
|
"commit_docs": true,
|
|
5
5
|
"parallelization": true,
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"verifier": true,
|
|
29
29
|
"nyquist_validation": true,
|
|
30
30
|
"ai_integration_phase": true,
|
|
31
|
+
"agent_hint_routing": true,
|
|
31
32
|
"human_verify_mode": "end-of-phase",
|
|
32
33
|
"auto_advance": false,
|
|
33
34
|
"_auto_chain_active": false,
|
|
@@ -45,11 +46,13 @@
|
|
|
45
46
|
"context_coverage_gate": true,
|
|
46
47
|
"code_review": true,
|
|
47
48
|
"code_review_depth": "standard",
|
|
49
|
+
"code_review_depth_overrides": [],
|
|
48
50
|
"code_review_command": null,
|
|
49
51
|
"pattern_mapper": true,
|
|
50
52
|
"plan_bounce": false,
|
|
51
53
|
"plan_bounce_script": null,
|
|
52
54
|
"plan_bounce_passes": 2,
|
|
55
|
+
"inline_plan_threshold": 2,
|
|
53
56
|
"auto_prune_state": false,
|
|
54
57
|
"post_planning_gaps": true,
|
|
55
58
|
"security_enforcement": true,
|
|
@@ -59,6 +62,7 @@
|
|
|
59
62
|
},
|
|
60
63
|
"planning": {
|
|
61
64
|
"commit_docs": true,
|
|
65
|
+
"pr_strict": false,
|
|
62
66
|
"search_gitignored": false,
|
|
63
67
|
"sub_repos": [],
|
|
64
68
|
"granularity": "standard"
|
|
@@ -96,6 +100,9 @@
|
|
|
96
100
|
"source_grounding": true,
|
|
97
101
|
"source_grounding_authority": "grep"
|
|
98
102
|
},
|
|
103
|
+
"review": {
|
|
104
|
+
"max_prompt_tokens": null
|
|
105
|
+
},
|
|
99
106
|
"capabilities": {
|
|
100
107
|
"strict_known_registries": null,
|
|
101
108
|
"auto_update": false
|
|
@@ -29,12 +29,14 @@
|
|
|
29
29
|
"workflow.use_worktrees",
|
|
30
30
|
"workflow.worktree_skip_hooks",
|
|
31
31
|
"workflow.code_review_command",
|
|
32
|
+
"workflow.code_review_depth_overrides",
|
|
32
33
|
"workflow.plan_bounce",
|
|
33
34
|
"workflow.plan_bounce_script",
|
|
34
35
|
"workflow.plan_bounce_passes",
|
|
35
36
|
"workflow.plan_chunked",
|
|
36
37
|
"workflow.specless_probe_fallback",
|
|
37
38
|
"workflow.plan_review_convergence",
|
|
39
|
+
"workflow.agent_hint_routing",
|
|
38
40
|
"code_quality.fallow.enabled",
|
|
39
41
|
"code_quality.fallow.scope",
|
|
40
42
|
"code_quality.fallow.profile",
|
|
@@ -42,16 +44,19 @@
|
|
|
42
44
|
"ship.pr_body_sections",
|
|
43
45
|
"git.branching_strategy",
|
|
44
46
|
"git.base_branch",
|
|
47
|
+
"git.protected_branches",
|
|
45
48
|
"git.create_tag",
|
|
46
49
|
"git.phase_branch_template",
|
|
47
50
|
"git.milestone_branch_template",
|
|
48
51
|
"git.quick_branch_template",
|
|
49
52
|
"planning.commit_docs",
|
|
53
|
+
"planning.pr_strict",
|
|
50
54
|
"planning.search_gitignored",
|
|
51
55
|
"planning.sub_repos",
|
|
52
56
|
"review.default_reviewers",
|
|
53
57
|
"review.max_prompt_tokens",
|
|
54
58
|
"review.max_prompt_tokens_per_reviewer",
|
|
59
|
+
"review.parallel_lanes",
|
|
55
60
|
"workflow.cross_ai_execution",
|
|
56
61
|
"workflow.cross_ai_command",
|
|
57
62
|
"workflow.cross_ai_timeout",
|
|
@@ -74,6 +79,7 @@
|
|
|
74
79
|
"statusline.show_context_tokens",
|
|
75
80
|
"statusline.state_format",
|
|
76
81
|
"statusline.show_git",
|
|
82
|
+
"statusline.show_state_freshness",
|
|
77
83
|
"workflow.max_discuss_passes",
|
|
78
84
|
"features.thinking_partner",
|
|
79
85
|
"context",
|
|
@@ -180,7 +186,12 @@
|
|
|
180
186
|
{
|
|
181
187
|
"topLevel": "model_policy",
|
|
182
188
|
"source": "^model_policy\\.runtime_tiers\\.[a-zA-Z0-9_-]+\\.(opus|sonnet|haiku)$",
|
|
183
|
-
"description": "model_policy.runtime_tiers.<runtime>.<opus|sonnet|haiku>"
|
|
189
|
+
"description": "model_policy.runtime_tiers.<runtime>.<opus|sonnet|haiku> (#3587)"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"topLevel": "phase_commit_docs",
|
|
193
|
+
"source": "^phase_commit_docs\\.\\d+[A-Z]?(?:\\.\\d+)*$",
|
|
194
|
+
"description": "phase_commit_docs.<phase-id> — per-phase commit_docs override (#3587). The <phase-id> segment is a hand-copy of the canonical PHASE_NUMBER_TOKEN_SOURCE grammar owned by src/phase-id.cts (#2128); this manifest is hand-maintained JSON so it cannot import that constant. Pinned against drift by the behavioral parity test in tests/commit-docs-bypass.test.cjs (folded 'phase-commit-docs' block, describe block 'E', #3587) — do not hand-edit this pattern without updating that test."
|
|
184
195
|
}
|
|
185
196
|
]
|
|
186
197
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
[
|
|
2
|
+
{ "code": 2, "name": "HOOK_DENY", "meaning": "Hook protocol deny — the harness blocks the tool call", "owner": "hook-adapter", "authorizedBy": "ADR-3889" },
|
|
3
|
+
{ "code": 64, "name": "USAGE", "meaning": "Caller error — bad argv, unknown subcommand, missing argument", "owner": "generic", "authorizedBy": "ADR-3889" },
|
|
4
|
+
{ "code": 66, "name": "NO_INPUT", "meaning": "Ran; zero units were in scope, and that emptiness is known to be genuine", "owner": "generic", "authorizedBy": "ADR-3889" },
|
|
5
|
+
{ "code": 69, "name": "UNAVAILABLE", "meaning": "Could not run — prerequisite absent, input unreadable, scope unestablished", "owner": "generic", "authorizedBy": "ADR-3889" },
|
|
6
|
+
{ "code": 70, "name": "INTERNAL", "meaning": "Self-failure — crash, timeout, killed subprocess", "owner": "generic", "authorizedBy": "ADR-3889" },
|
|
7
|
+
{ "code": 80, "name": "DEGRADED", "meaning": "Ran to completion and is reporting a condition through its result payload rather than as a process failure", "owner": "gsd-tools", "authorizedBy": "ADR-3889 + ADR-2980" }
|
|
8
|
+
]
|