@opengsd/gsd-core 1.12.0 → 1.14.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/.opencode/plugins/gsd-core.js +12 -0
- package/agents/gsd-advisor-researcher.compact.md +85 -0
- package/agents/gsd-ai-researcher.compact.md +96 -0
- package/agents/gsd-assumptions-analyzer.compact.md +81 -0
- package/agents/gsd-code-fixer.compact.md +458 -0
- package/agents/gsd-code-fixer.md +5 -5
- package/agents/gsd-code-reviewer.compact.md +269 -0
- package/agents/gsd-code-reviewer.md +15 -3
- package/agents/gsd-codebase-mapper.compact.md +760 -0
- package/agents/gsd-debug-session-manager.compact.md +345 -0
- package/agents/gsd-doc-classifier.compact.md +192 -0
- package/agents/gsd-doc-synthesizer.compact.md +200 -0
- package/agents/gsd-doc-verifier.compact.md +143 -0
- package/agents/gsd-doc-writer.compact.md +440 -0
- package/agents/gsd-dom-verifier.compact.md +138 -0
- package/agents/gsd-domain-researcher.compact.md +141 -0
- package/agents/gsd-eval-auditor.compact.md +160 -0
- package/agents/gsd-eval-planner.compact.md +137 -0
- package/agents/gsd-executor.md +63 -35
- package/agents/gsd-framework-selector.compact.md +82 -0
- package/agents/gsd-integration-checker.compact.md +245 -0
- package/agents/gsd-intel-updater.compact.md +226 -0
- package/agents/gsd-mempalace-curator.compact.md +45 -0
- package/agents/gsd-nyquist-auditor.compact.md +179 -0
- package/agents/gsd-pattern-mapper.compact.md +275 -0
- package/agents/gsd-plan-checker.md +76 -57
- package/agents/gsd-planner.md +14 -0
- package/agents/gsd-project-researcher.compact.md +587 -0
- package/agents/gsd-research-synthesizer.compact.md +212 -0
- package/agents/gsd-roadmapper.compact.md +454 -0
- package/agents/gsd-roadmapper.md +13 -0
- package/agents/gsd-security-auditor.compact.md +162 -0
- package/agents/gsd-ui-auditor.compact.md +404 -0
- package/agents/gsd-ui-checker.compact.md +277 -0
- package/agents/gsd-ui-checker.md +19 -3
- package/agents/gsd-ui-researcher.compact.md +282 -0
- package/agents/gsd-ui-researcher.md +29 -0
- package/agents/gsd-user-profiler.compact.md +108 -0
- package/agents/gsd-verifier.md +23 -1
- package/bin/install.js +444 -134
- package/commands/gsd/cleanup.md +1 -0
- package/commands/gsd/code-review.md +2 -1
- package/commands/gsd/complete-milestone.md +1 -0
- package/commands/gsd/config.md +1 -0
- package/commands/gsd/debug.md +1 -0
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/graphify.md +1 -0
- package/commands/gsd/health.md +1 -0
- package/commands/gsd/mempalace-capture.md +1 -0
- package/commands/gsd/mempalace-recall.md +1 -0
- package/commands/gsd/new-milestone.md +1 -0
- package/commands/gsd/new-project.md +1 -0
- package/commands/gsd/next.md +1 -0
- package/commands/gsd/ns-workflow.md +2 -1
- package/commands/gsd/pause-work.md +1 -0
- package/commands/gsd/phase.md +2 -1
- package/commands/gsd/pr-branch.md +1 -0
- package/commands/gsd/quick-batch.md +105 -0
- package/commands/gsd/resume-work.md +1 -0
- package/commands/gsd/review-backlog.md +1 -0
- package/commands/gsd/settings.md +2 -1
- package/commands/gsd/stats.md +1 -0
- package/commands/gsd/surface.md +18 -8
- package/commands/gsd/thread.md +1 -0
- package/commands/gsd/workspace.md +1 -0
- package/commands/gsd/workstreams.md +1 -0
- package/gsd-core/bin/check-latest-version.cjs +8 -3
- package/gsd-core/bin/gsd-tools.cjs +532 -174
- package/gsd-core/bin/lib/adr-parser.cjs +1 -1
- package/gsd-core/bin/lib/artifacts.cjs +2 -1
- package/gsd-core/bin/lib/audit.cjs +39 -22
- package/gsd-core/bin/lib/broken-windows.cjs +168 -49
- package/gsd-core/bin/lib/capability-activation.cjs +27 -0
- package/gsd-core/bin/lib/capability-lifecycle.cjs +10 -6
- package/gsd-core/bin/lib/capability-loader.cjs +135 -1
- package/gsd-core/bin/lib/capability-registry.cjs +528 -116
- package/gsd-core/bin/lib/capability-source.cjs +19 -2
- package/gsd-core/bin/lib/capability-state.cjs +7 -1
- package/gsd-core/bin/lib/capability-validator.cjs +134 -5
- package/gsd-core/bin/lib/capability-writer.cjs +14 -4
- package/gsd-core/bin/lib/check-command-router.cjs +198 -38
- package/gsd-core/bin/lib/claude-orchestration.cjs +10 -25
- package/gsd-core/bin/lib/clusters.cjs +1 -0
- package/gsd-core/bin/lib/code-review-depth.cjs +2 -2
- package/gsd-core/bin/lib/command-aliases.cjs +16 -0
- package/gsd-core/bin/lib/commands.cjs +981 -79
- package/gsd-core/bin/lib/config-loader.cjs +4 -0
- package/gsd-core/bin/lib/config.cjs +153 -38
- package/gsd-core/bin/lib/core-utils.cjs +34 -7
- package/gsd-core/bin/lib/coverage.cjs +1 -1
- package/gsd-core/bin/lib/decisions.cjs +343 -28
- package/gsd-core/bin/lib/edge-probe.cjs +14 -1
- package/gsd-core/bin/lib/external-descriptor-trust.cjs +29 -14
- package/gsd-core/bin/lib/file-overlap-partitioner.cjs +74 -0
- package/gsd-core/bin/lib/frontmatter.cjs +137 -23
- package/gsd-core/bin/lib/gap-checker.cjs +22 -13
- package/gsd-core/bin/lib/git-base-branch.cjs +10 -2
- package/gsd-core/bin/lib/gsd2-import.cjs +1 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +8 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +54 -11
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +87 -23
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +1 -1
- package/gsd-core/bin/lib/host-integration.cjs +57 -5
- package/gsd-core/bin/lib/init-command-router.cjs +14 -0
- package/gsd-core/bin/lib/init.cjs +539 -60
- package/gsd-core/bin/lib/install-engine.cjs +199 -14
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +45 -0
- package/gsd-core/bin/lib/install-profiles.cjs +36 -14
- package/gsd-core/bin/lib/installer-migration-report.cjs +1 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +33 -4
- package/gsd-core/bin/lib/io.cjs +35 -0
- package/gsd-core/bin/lib/loop-resolver.cjs +64 -39
- package/gsd-core/bin/lib/markdown-table.cjs +123 -0
- package/gsd-core/bin/lib/mcp-catalog.cjs +2 -2
- package/gsd-core/bin/lib/milestone.cjs +41 -10
- package/gsd-core/bin/lib/model-resolver.cjs +101 -10
- package/gsd-core/bin/lib/phase-command-router.cjs +20 -7
- package/gsd-core/bin/lib/phase-id.cjs +412 -31
- package/gsd-core/bin/lib/phase-lifecycle.cjs +61 -0
- package/gsd-core/bin/lib/phase.cjs +941 -98
- package/gsd-core/bin/lib/plan-document.cjs +10 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +34 -18
- package/gsd-core/bin/lib/planning-snapshot.cjs +206 -30
- package/gsd-core/bin/lib/planning-workspace.cjs +153 -29
- package/gsd-core/bin/lib/pristine-baseline.cjs +182 -0
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +91 -4
- package/gsd-core/bin/lib/quick-batch-command-router.cjs +285 -0
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +250 -0
- package/gsd-core/bin/lib/quick-batch.cjs +840 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +61 -2
- package/gsd-core/bin/lib/research-store.cjs +11 -12
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +53 -5
- package/gsd-core/bin/lib/review-lane-invocation.cjs +96 -1
- package/gsd-core/bin/lib/review-lane-runner.cjs +136 -10
- package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +337 -0
- package/gsd-core/bin/lib/roadmap-parser.cjs +555 -41
- package/gsd-core/bin/lib/roadmap.cjs +292 -69
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +260 -43
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +28 -20
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +294 -108
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +408 -47
- package/gsd-core/bin/lib/security.cjs +126 -7
- package/gsd-core/bin/lib/shell-command-projection.cjs +4 -0
- package/gsd-core/bin/lib/smart-entry.cjs +7 -9
- package/gsd-core/bin/lib/state-document.cjs +159 -32
- package/gsd-core/bin/lib/state-md-schema.cjs +44 -27
- package/gsd-core/bin/lib/state-transition.cjs +465 -62
- package/gsd-core/bin/lib/state.cjs +906 -151
- package/gsd-core/bin/lib/surface.cjs +83 -10
- package/gsd-core/bin/lib/task-command-router.cjs +12 -6
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +133 -0
- package/gsd-core/bin/lib/uat.cjs +1420 -516
- package/gsd-core/bin/lib/update-context.cjs +36 -26
- package/gsd-core/bin/lib/validate.cjs +230 -12
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +11 -3
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +316 -23
- package/gsd-core/bin/lib/verify-command-grounding.cjs +1 -1
- package/gsd-core/bin/lib/verify-command-router.cjs +1 -0
- package/gsd-core/bin/lib/verify.cjs +531 -36
- package/gsd-core/bin/lib/workstream-inventory.cjs +21 -2
- package/gsd-core/bin/lib/worktree-safety.cjs +21 -7
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +13 -0
- package/gsd-core/bin/verify-reapply-patches.cjs +507 -81
- package/gsd-core/references/agent-contracts.md +3 -3
- package/gsd-core/references/compact-content-gate.md +66 -0
- package/gsd-core/references/edge-probe.md +17 -13
- package/gsd-core/references/execute-mvp-tdd.md +18 -16
- package/gsd-core/references/execute-phase-response-language.md +6 -0
- package/gsd-core/references/executor-examples.md +42 -0
- package/gsd-core/references/few-shot-examples/plan-checker.md +15 -15
- package/gsd-core/references/loop-hook-dispatch.md +18 -0
- package/gsd-core/references/model-profiles.md +12 -3
- package/gsd-core/references/mvp-concepts.md +2 -2
- package/gsd-core/references/plan-checker-examples.md +41 -0
- package/gsd-core/references/planner-antipatterns.md +25 -0
- package/gsd-core/references/planner-chunked.md +5 -1
- package/gsd-core/references/planner-coupling.md +42 -0
- package/gsd-core/references/planner-quick-batch.md +71 -0
- package/gsd-core/references/planner-reviews.md +47 -0
- package/gsd-core/references/planner-revision.md +75 -2
- package/gsd-core/references/planning-config.md +5 -1
- package/gsd-core/references/response-language-directive.md +9 -0
- package/gsd-core/references/revision-loop.md +118 -11
- package/gsd-core/references/tdd.md +17 -9
- package/gsd-core/references/thinking-models-planning.md +18 -2
- package/gsd-core/references/verification-patterns.md +17 -4
- package/gsd-core/references/verifier-evidence-gate.md +160 -0
- package/gsd-core/references/worktree-path-safety.md +112 -2
- package/gsd-core/templates/README.md +7 -1
- package/gsd-core/templates/phase-prompt.md +4 -0
- package/gsd-core/templates/state.md +6 -3
- package/gsd-core/templates/summary.compact.md +212 -0
- package/gsd-core/templates/user-setup.compact.md +199 -0
- package/gsd-core/templates/user-setup.md +0 -9
- package/gsd-core/templates/verification-report.md +5 -0
- package/gsd-core/workflows/add-backlog.md +2 -0
- package/gsd-core/workflows/add-phase.md +2 -0
- package/gsd-core/workflows/add-tests.md +1 -1
- package/gsd-core/workflows/add-todo.md +4 -3
- package/gsd-core/workflows/ai-integration-phase.md +1 -1
- package/gsd-core/workflows/analyze-dependencies.md +2 -0
- package/gsd-core/workflows/audit-fix.md +2 -0
- package/gsd-core/workflows/audit-milestone.md +2 -0
- package/gsd-core/workflows/audit-uat.md +2 -0
- package/gsd-core/workflows/autonomous.md +15 -10
- package/gsd-core/workflows/check-todos.md +5 -3
- package/gsd-core/workflows/cleanup.md +4 -2
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +22 -13
- package/gsd-core/workflows/code-review-fix.md +5 -3
- package/gsd-core/workflows/code-review.md +211 -43
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +274 -0
- package/gsd-core/workflows/complete-milestone.md +40 -254
- package/gsd-core/workflows/debug.md +1 -1
- package/gsd-core/workflows/diagnose-issues.md +5 -1
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/all.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/analyze.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/auto.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/batch.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/default.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/power.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/text.md +2 -0
- package/gsd-core/workflows/discuss-phase/templates/context.md +2 -0
- package/gsd-core/workflows/discuss-phase/templates/discussion-log.md +2 -0
- package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
- package/gsd-core/workflows/discuss-phase-power.md +2 -0
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +43 -13
- package/gsd-core/workflows/docs-update/detail/elaboration.md +179 -0
- package/gsd-core/workflows/docs-update.md +15 -156
- package/gsd-core/workflows/edit-phase.md +2 -0
- package/gsd-core/workflows/eval-review.md +1 -1
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +124 -0
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +20 -3
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +56 -0
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +24 -3
- package/gsd-core/workflows/execute-phase/steps/executor-progress-policy.md +43 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +8 -2
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -0
- package/gsd-core/workflows/execute-phase/steps/sequential-root-pin.md +35 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +25 -0
- package/gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md +2 -0
- package/gsd-core/workflows/execute-phase.md +78 -159
- package/gsd-core/workflows/execute-plan.md +28 -15
- package/gsd-core/workflows/explore.md +2 -0
- package/gsd-core/workflows/extract-learnings.md +2 -0
- package/gsd-core/workflows/fast.md +6 -0
- package/gsd-core/workflows/forensics.md +2 -0
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +1 -1
- package/gsd-core/workflows/help/modes/brief.md +2 -0
- package/gsd-core/workflows/help/modes/default.md +2 -0
- package/gsd-core/workflows/help/modes/full.compact.md +398 -0
- package/gsd-core/workflows/help/modes/full.md +12 -0
- package/gsd-core/workflows/help/modes/topic.md +2 -0
- package/gsd-core/workflows/help.md +3 -1
- package/gsd-core/workflows/import.md +3 -3
- package/gsd-core/workflows/inbox.md +1 -1
- package/gsd-core/workflows/ingest-docs.md +1 -1
- package/gsd-core/workflows/insert-phase.md +2 -0
- package/gsd-core/workflows/list-phase-assumptions.md +2 -0
- package/gsd-core/workflows/list-seeds.md +2 -0
- package/gsd-core/workflows/list-workspaces.md +2 -0
- package/gsd-core/workflows/manager.md +3 -3
- package/gsd-core/workflows/map-codebase.md +52 -3
- package/gsd-core/workflows/milestone-summary.md +2 -0
- package/gsd-core/workflows/mvp-phase.md +1 -1
- package/gsd-core/workflows/new-milestone.md +55 -13
- package/gsd-core/workflows/new-project/detail/elaboration.md +216 -0
- package/gsd-core/workflows/new-project.md +37 -205
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +2 -0
- package/gsd-core/workflows/node-repair.md +2 -0
- package/gsd-core/workflows/note.md +2 -0
- package/gsd-core/workflows/onboard.md +1 -1
- package/gsd-core/workflows/pause-work.md +19 -4
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +209 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +100 -18
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -0
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +9 -0
- package/gsd-core/workflows/plan-phase.md +144 -185
- package/gsd-core/workflows/plan-review-convergence.md +102 -10
- package/gsd-core/workflows/plant-seed.md +1 -1
- package/gsd-core/workflows/pr-branch.md +30 -10
- package/gsd-core/workflows/profile-user.md +1 -1
- package/gsd-core/workflows/progress/steps/forensic-audit.md +1 -1
- package/gsd-core/workflows/progress.md +25 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +37 -2
- package/gsd-core/workflows/quick/steps/research-phase.md +3 -3
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +55 -0
- package/gsd-core/workflows/quick-batch/steps/completion.md +65 -0
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +100 -0
- package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +147 -0
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +158 -0
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +95 -0
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +49 -0
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +73 -0
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +169 -0
- package/gsd-core/workflows/quick-batch.md +203 -0
- package/gsd-core/workflows/quick.md +21 -4
- package/gsd-core/workflows/reapply-patches.md +79 -3
- package/gsd-core/workflows/remove-phase.md +2 -0
- package/gsd-core/workflows/remove-workspace.md +1 -1
- package/gsd-core/workflows/resume-project.md +6 -2
- package/gsd-core/workflows/review.md +215 -10
- package/gsd-core/workflows/scan.md +2 -0
- package/gsd-core/workflows/section-manifest.json +12 -0
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/session-report.md +2 -0
- package/gsd-core/workflows/settings-advanced.md +2 -0
- package/gsd-core/workflows/settings-integrations.md +9 -8
- package/gsd-core/workflows/settings.md +19 -6
- package/gsd-core/workflows/ship.md +10 -10
- package/gsd-core/workflows/sketch-wrap-up.md +2 -0
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/smart-entry.md +1 -1
- package/gsd-core/workflows/spec-phase.md +24 -19
- package/gsd-core/workflows/spike-wrap-up.md +2 -0
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +2 -0
- package/gsd-core/workflows/sync-skills.md +12 -4
- package/gsd-core/workflows/thread.md +2 -0
- package/gsd-core/workflows/transition.md +2 -0
- package/gsd-core/workflows/ui-phase.md +26 -5
- package/gsd-core/workflows/ui-review.md +1 -1
- package/gsd-core/workflows/ultraplan-phase.md +2 -0
- package/gsd-core/workflows/undo.md +1 -1
- package/gsd-core/workflows/update.md +48 -43
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-work/detail/elaboration.md +230 -0
- package/gsd-core/workflows/verify-work.md +68 -182
- package/hooks/dist/gsd-agent-isolation-guard.js +42 -16
- package/hooks/dist/gsd-check-update-worker.js +19 -2
- package/hooks/dist/gsd-context-monitor.js +371 -27
- package/hooks/dist/gsd-cursor-subagent-start.js +34 -14
- package/hooks/dist/gsd-node-runner.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +30 -5
- package/hooks/dist/gsd-read-guard.js +2 -0
- package/hooks/dist/gsd-read-injection-scanner.js +5 -5
- package/hooks/dist/gsd-secret-read-guard.js +1105 -0
- package/hooks/dist/gsd-statusline.js +18 -10
- package/hooks/dist/gsd-validate-commit.sh +474 -7
- package/hooks/dist/gsd-workflow-guard.js +2 -1
- package/hooks/dist/gsd-worktree-path-guard.js +25 -14
- package/hooks/dist/gsd-write-guard.js +46 -1
- package/hooks/dist/lib/dispatch-identity.js +187 -0
- package/hooks/dist/lib/filename-classification.js +64 -0
- package/hooks/dist/lib/git-cmd.js +210 -1
- package/hooks/dist/lib/injection-patterns.js +36 -6
- package/hooks/dist/lib/isolation-deny-reason.js +53 -1
- package/hooks/dist/lib/isolation-sentinel.js +58 -19
- package/hooks/dist/managed-hooks-registry.cjs +1 -0
- package/hooks/gsd-agent-isolation-guard.js +42 -16
- package/hooks/gsd-check-update-worker.js +19 -2
- package/hooks/gsd-context-monitor.js +371 -27
- package/hooks/gsd-cursor-subagent-start.js +34 -14
- package/hooks/gsd-node-runner.sh +1 -0
- package/hooks/gsd-prompt-guard.js +30 -5
- package/hooks/gsd-read-guard.js +2 -0
- package/hooks/gsd-read-injection-scanner.js +5 -5
- package/hooks/gsd-secret-read-guard.js +1105 -0
- package/hooks/gsd-statusline.js +18 -10
- package/hooks/gsd-validate-commit.sh +474 -7
- package/hooks/gsd-workflow-guard.js +2 -1
- package/hooks/gsd-worktree-path-guard.js +25 -14
- package/hooks/gsd-write-guard.js +46 -1
- package/hooks/hooks.json +6 -0
- package/hooks/lib/dispatch-identity.js +187 -0
- package/hooks/lib/filename-classification.js +64 -0
- package/hooks/lib/git-cmd.js +210 -1
- package/hooks/lib/injection-patterns.js +36 -6
- package/hooks/lib/isolation-deny-reason.js +53 -1
- package/hooks/lib/isolation-sentinel.js +58 -19
- package/hooks/managed-hooks-registry.cjs +1 -0
- package/package.json +13 -9
- package/scripts/benchmark-compact-content-variants.cjs +298 -0
- package/scripts/benchmark-compact-content.cjs +368 -0
- package/scripts/build-hooks.js +11 -4
- package/scripts/check-contract-drift.cjs +4 -1
- package/scripts/check-env.cjs +36 -8
- package/scripts/check-glossary-refs.cjs +25 -21
- package/scripts/ci-next-health.cjs +271 -0
- package/scripts/ci-prepare-test-scope.cjs +7 -7
- package/scripts/ci-test-scope.cjs +133 -20
- package/scripts/ci-timeout-report.cjs +1 -1
- package/scripts/diff-touches-shipped-paths.cjs +1 -1
- package/scripts/docs-guard-registry.cjs +17 -2
- package/scripts/gen-adr-index.cjs +8 -2
- package/scripts/gen-inventory-manifest.cjs +12 -0
- package/scripts/gen-loop-host-contract.cjs +67 -15
- package/scripts/gen-platform-conformance-tier.cjs +557 -0
- package/scripts/lib/drift-scan.cjs +1 -1
- package/scripts/lib/macos-conformance-tier.generated.cjs +210 -0
- package/scripts/lib/npm-version-check-diagnosis.cjs +59 -0
- package/scripts/lib/platform-conformance-tier.generated.cjs +276 -0
- package/scripts/lib/shellcheck-fetch.cjs +247 -0
- package/scripts/lib/suite-detection.cjs +32 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -6
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-allowed-tools-parity.cjs +221 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +24 -2
- package/scripts/lint-phase-enumeration-drift.cjs +24 -6
- package/scripts/lint-phase-id-drift.cjs +465 -15
- package/scripts/lint-portable-grep.cjs +176 -0
- package/scripts/lint-response-language-coverage.cjs +530 -0
- package/scripts/lint-source-test-name-collision.cjs +1 -1
- package/scripts/lint-test-file-count.allowlist.json +4 -1
- package/scripts/lint-vendored-deps.cjs +128 -17
- package/scripts/lint-workflow-shellcheck-baseline.json +1112 -0
- package/scripts/lint-workflow-shellcheck.cjs +614 -0
- package/scripts/npm-audit-baseline.cjs +376 -0
- package/scripts/prompt-injection-scan.sh +22 -0
- package/scripts/require-issue-link-policy.cjs +16 -1
- package/scripts/workflow-size.cjs +139 -0
- package/skills/gsd-cleanup/SKILL.md +1 -0
- package/skills/gsd-code-review/SKILL.md +2 -1
- package/skills/gsd-complete-milestone/SKILL.md +1 -0
- package/skills/gsd-config/SKILL.md +1 -0
- package/skills/gsd-debug/SKILL.md +1 -0
- package/skills/gsd-execute-phase/SKILL.md +1 -1
- package/skills/gsd-graphify/SKILL.md +1 -0
- package/skills/gsd-health/SKILL.md +1 -0
- package/skills/gsd-mempalace-capture/SKILL.md +1 -0
- package/skills/gsd-mempalace-recall/SKILL.md +1 -0
- package/skills/gsd-new-milestone/SKILL.md +1 -0
- package/skills/gsd-new-project/SKILL.md +1 -0
- package/skills/gsd-next/SKILL.md +1 -0
- package/skills/gsd-ns-workflow/SKILL.md +1 -0
- package/skills/gsd-pause-work/SKILL.md +1 -0
- package/skills/gsd-phase/SKILL.md +2 -1
- package/skills/gsd-pr-branch/SKILL.md +1 -0
- package/skills/gsd-quick-batch/SKILL.md +105 -0
- package/skills/gsd-resume-work/SKILL.md +1 -0
- package/skills/gsd-review-backlog/SKILL.md +1 -0
- package/skills/gsd-settings/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +1 -0
- package/skills/gsd-surface/SKILL.md +18 -8
- package/skills/gsd-thread/SKILL.md +1 -0
- package/skills/gsd-workspace/SKILL.md +1 -0
- package/skills/gsd-workstreams/SKILL.md +1 -0
- package/vscode/package.json +1 -1
- package/gsd-core/templates/claude-md.md +0 -145
- package/gsd-core/templates/codebase/concerns.md +0 -310
- package/gsd-core/templates/codebase/conventions.md +0 -307
- package/gsd-core/templates/codebase/integrations.md +0 -280
- package/gsd-core/templates/codebase/structure.md +0 -285
- package/gsd-core/templates/codebase/testing.md +0 -480
- package/gsd-core/templates/debug-subagent-prompt.md +0 -91
- package/gsd-core/templates/discovery.md +0 -146
|
@@ -35,6 +35,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
const node_path_1 = __importDefault(require("node:path"));
|
|
36
36
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
37
37
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
38
|
+
const security_cjs_1 = require("./security.cjs");
|
|
38
39
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
39
40
|
const io = require("./io.cjs");
|
|
40
41
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
@@ -174,8 +175,11 @@ function resolvePhaseDirForArg(cwd, phaseArg) {
|
|
|
174
175
|
*/
|
|
175
176
|
function resolveConfinedPath(cwd, relFile) {
|
|
176
177
|
const root = node_path_1.default.resolve(cwd);
|
|
177
|
-
|
|
178
|
-
|
|
178
|
+
// ADR-4650 decision 6: lexical family — resolving the symlink here would
|
|
179
|
+
// undo the refuse-don't-resolve posture documented above; `lstatSync` below
|
|
180
|
+
// is the gate that actually refuses a symlink.
|
|
181
|
+
const resolved = (0, security_cjs_1.tryWithinRootLexical)(relFile, root);
|
|
182
|
+
if (resolved === null)
|
|
179
183
|
return null;
|
|
180
184
|
try {
|
|
181
185
|
if (!node_fs_1.default.lstatSync(resolved).isFile())
|
|
@@ -321,6 +325,32 @@ function loadWindowsOrDegrade(cwd, windowsOverride) {
|
|
|
321
325
|
}
|
|
322
326
|
return { ok: true, windows, ledger };
|
|
323
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* #3780: lazy (module-load cost, see file header) require of the ledger's
|
|
330
|
+
* serialization seam — the same `.planning/.WINDOWS.lock` the windows cmd*
|
|
331
|
+
* writers hold, so this router's own read-compute-write cycles on
|
|
332
|
+
* WINDOWS.md cannot lose updates against them. Required from the REAL
|
|
333
|
+
* compiled module, never through the injectable `windowsOverride` seam:
|
|
334
|
+
* the lock is infrastructure, not a parser stand-in.
|
|
335
|
+
*/
|
|
336
|
+
function withLedgerLock(cwd, fn) {
|
|
337
|
+
let lockMod;
|
|
338
|
+
try {
|
|
339
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
340
|
+
lockMod = require('./broken-windows.cjs');
|
|
341
|
+
/* eslint-enable @typescript-eslint/no-require-imports */
|
|
342
|
+
}
|
|
343
|
+
catch {
|
|
344
|
+
// Ledger module unavailable (the #1953 degrade world — see the row-86
|
|
345
|
+
// notesLedgerUnavailableWithoutBrokenWindows contract): no lock-holding
|
|
346
|
+
// writer can exist either, because every WINDOWS.md writer requires this
|
|
347
|
+
// same module. Run the body unlocked and let loadWindowsOrDegrade
|
|
348
|
+
// produce the canonical degrade note — wrapping that world in lock
|
|
349
|
+
// ceremony would only rewrite the note the degrade contract pins.
|
|
350
|
+
return fn();
|
|
351
|
+
}
|
|
352
|
+
return lockMod.withLedgerLock(cwd, fn);
|
|
353
|
+
}
|
|
324
354
|
/**
|
|
325
355
|
* Strict-mode window append (step 9 of `evaluate`). Degrades to
|
|
326
356
|
* `{ recorded: false, note }` per `loadWindowsOrDegrade` — never an error,
|
|
@@ -329,6 +359,23 @@ function loadWindowsOrDegrade(cwd, windowsOverride) {
|
|
|
329
359
|
* file/line) and does not append a second one.
|
|
330
360
|
*/
|
|
331
361
|
function recordStrictWindow(cwd, padded, target, windowsOverride) {
|
|
362
|
+
// #3780: hold the same cross-process ledger lock the windows cmd* writers
|
|
363
|
+
// hold — this site's read-compute-write on WINDOWS.md is otherwise the
|
|
364
|
+
// same lost-update race: a concurrent `gsd_run windows append` (or another
|
|
365
|
+
// evaluator) could silently overwrite this entry, or be overwritten by
|
|
366
|
+
// it. The lock comes from the real ledger module, not the injectable
|
|
367
|
+
// `windowsOverride` seam — it is infrastructure, not a parser stand-in.
|
|
368
|
+
// The wrapper keeps the #1953-defect-2 degrade contract: the lock's typed
|
|
369
|
+
// refusal degrades to `{ recorded: false, note }` like every other
|
|
370
|
+
// failure, it never throws out of this function.
|
|
371
|
+
try {
|
|
372
|
+
return withLedgerLock(cwd, () => recordStrictWindowLocked(cwd, padded, target, windowsOverride));
|
|
373
|
+
}
|
|
374
|
+
catch (e) {
|
|
375
|
+
return { recorded: false, note: `failed to record broken-windows entry: ${e instanceof Error ? e.message : String(e)}` };
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
function recordStrictWindowLocked(cwd, padded, target, windowsOverride) {
|
|
332
379
|
const loaded = loadWindowsOrDegrade(cwd, windowsOverride);
|
|
333
380
|
if (!loaded.ok)
|
|
334
381
|
return { recorded: false, note: loaded.note };
|
|
@@ -357,6 +404,18 @@ function recordStrictWindow(cwd, padded, target, windowsOverride) {
|
|
|
357
404
|
* `accept`/`decline` never tell a user "it failed" without saying why.
|
|
358
405
|
*/
|
|
359
406
|
function resolveLedgerWindow(cwd, padded, file, line, kind, reasonText, windowsOverride) {
|
|
407
|
+
// #3780: same serialization as recordStrictWindow — a concurrent ledger
|
|
408
|
+
// writer holding a stale snapshot would silently revert this resolve (or
|
|
409
|
+
// lose its own write to this one). Same degrade contract: the lock's
|
|
410
|
+
// typed refusal degrades, never throws.
|
|
411
|
+
try {
|
|
412
|
+
return withLedgerLock(cwd, () => resolveLedgerWindowLocked(cwd, padded, file, line, kind, reasonText, windowsOverride));
|
|
413
|
+
}
|
|
414
|
+
catch (e) {
|
|
415
|
+
return { resolved: false, note: `failed to resolve broken-windows entry: ${e instanceof Error ? e.message : String(e)}` };
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
function resolveLedgerWindowLocked(cwd, padded, file, line, kind, reasonText, windowsOverride) {
|
|
360
419
|
const loaded = loadWindowsOrDegrade(cwd, windowsOverride);
|
|
361
420
|
if (!loaded.ok)
|
|
362
421
|
return { resolved: false, note: loaded.note };
|
|
@@ -15,6 +15,10 @@ const node_os_1 = __importDefault(require("node:os"));
|
|
|
15
15
|
const node_path_1 = __importDefault(require("node:path"));
|
|
16
16
|
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
17
17
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
18
|
+
// ADR-4650 decision 6: lexical family — the key is validated before
|
|
19
|
+
// `fs.mkdirSync` creates the store dir, so the candidate legitimately does
|
|
20
|
+
// not exist yet at check time.
|
|
21
|
+
const security_cjs_1 = require("./security.cjs");
|
|
18
22
|
// ---------------------------------------------------------------------------
|
|
19
23
|
// Constants
|
|
20
24
|
// ---------------------------------------------------------------------------
|
|
@@ -94,15 +98,12 @@ function putResearch(cwd, key, payload, { clock = Date, homeDir = node_os_1.defa
|
|
|
94
98
|
const fetched_at = new Date(clock.now()).toISOString();
|
|
95
99
|
const entry = { content, source, provider, confidence, fetched_at, ttl, kind };
|
|
96
100
|
const dir = resolveStorePath(cwd, source, { homeDir });
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const filePath = node_path_1.default.join(dir, `${key}.json`);
|
|
100
|
-
const resolvedFile = node_path_1.default.resolve(filePath);
|
|
101
|
-
if (!resolvedFile.startsWith(resolvedDir + node_path_1.default.sep)) {
|
|
101
|
+
const containedFile = (0, security_cjs_1.tryWithinRootLexical)(`${key}.json`, dir);
|
|
102
|
+
if (containedFile === null || containedFile === node_path_1.default.resolve(dir)) {
|
|
102
103
|
throw new Error('invalid research key');
|
|
103
104
|
}
|
|
104
105
|
node_fs_1.default.mkdirSync(dir, { recursive: true });
|
|
105
|
-
(0, shell_command_projection_cjs_1.platformWriteSync)(
|
|
106
|
+
(0, shell_command_projection_cjs_1.platformWriteSync)(containedFile, JSON.stringify(entry));
|
|
106
107
|
return entry;
|
|
107
108
|
}
|
|
108
109
|
// ---------------------------------------------------------------------------
|
|
@@ -120,16 +121,14 @@ function getResearch(cwd, key, { clock = Date, homeDir = node_os_1.default.homed
|
|
|
120
121
|
const tierDirs = [userDir, projectDir];
|
|
121
122
|
const candidates = [];
|
|
122
123
|
for (const dir of tierDirs) {
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
// Belt-and-suspenders: ensure path stays inside tier dir
|
|
126
|
-
if (!node_path_1.default.resolve(filePath).startsWith(resolvedDir + node_path_1.default.sep))
|
|
124
|
+
const containedFile = (0, security_cjs_1.tryWithinRootLexical)(`${key}.json`, dir);
|
|
125
|
+
if (containedFile === null || containedFile === node_path_1.default.resolve(dir))
|
|
127
126
|
continue;
|
|
128
|
-
if (!node_fs_1.default.existsSync(
|
|
127
|
+
if (!node_fs_1.default.existsSync(containedFile))
|
|
129
128
|
continue;
|
|
130
129
|
let entry;
|
|
131
130
|
try {
|
|
132
|
-
entry = JSON.parse(node_fs_1.default.readFileSync(
|
|
131
|
+
entry = JSON.parse(node_fs_1.default.readFileSync(containedFile, 'utf8'));
|
|
133
132
|
}
|
|
134
133
|
catch {
|
|
135
134
|
// Corrupt file in this tier — skip it
|
|
@@ -45,6 +45,9 @@
|
|
|
45
45
|
* 4. `flags: string[]` — Antigravity is selected by BOTH `--antigravity` and
|
|
46
46
|
* `--agy`, which a single-valued field cannot express. This also flattens
|
|
47
47
|
* D8's uniqueness invariant across every lane's flags.
|
|
48
|
+
* 5. `NATIVE_TIMEOUT` — a lane whose CLI takes its own native inner timeout flag (today only
|
|
49
|
+
* antigravity's `--print-timeout`) declares where the resolved value goes; `resolveLanePlan`
|
|
50
|
+
* computes what it is from the same resolved outer `timeoutMs` (#3274).
|
|
48
51
|
*
|
|
49
52
|
* Phase 2 (#2795) implements the manifest validator against the amended
|
|
50
53
|
* vocabulary, which is the point of amending rather than leaving it to be
|
|
@@ -69,7 +72,7 @@ exports.checkReviewerDocsParity = checkReviewerDocsParity;
|
|
|
69
72
|
* and vanishes when it has nothing to contribute (no model configured, no effort channel, prompt on
|
|
70
73
|
* stdin), which is what lets one template serve the configured and unconfigured cases.
|
|
71
74
|
*
|
|
72
|
-
* This is a closed
|
|
75
|
+
* This is a closed five-member vocabulary with no expressions, no nesting and no conditionals — a
|
|
73
76
|
* placeholder set, deliberately not a template language. The moment it needs a conditional, the
|
|
74
77
|
* lane wants a `handler` instead (D6).
|
|
75
78
|
*/
|
|
@@ -82,6 +85,9 @@ exports.ARGV_PLACEHOLDER = Object.freeze({
|
|
|
82
85
|
OUTPUT: '{{output}}',
|
|
83
86
|
/** The argv-borne prompt, or nothing unless `promptChannel` is `argv`/`argv-file-ref`. */
|
|
84
87
|
PROMPT: '{{prompt}}',
|
|
88
|
+
/** A lane's own CLI-native inner timeout duration, derived from the resolved outer `timeoutMs`
|
|
89
|
+
* (never independently configured) — see `resolveLanePlan`'s expansion of this token. */
|
|
90
|
+
NATIVE_TIMEOUT: '{{nativeTimeout}}',
|
|
85
91
|
});
|
|
86
92
|
const SPAWN_STDIN_STDOUT = {
|
|
87
93
|
promptChannel: 'stdin',
|
|
@@ -107,12 +113,15 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
107
113
|
effortChannel: 'none',
|
|
108
114
|
},
|
|
109
115
|
timeoutFloorMs: 900_000,
|
|
116
|
+
timeoutConfigKey: 'review.timeouts.gemini',
|
|
110
117
|
emptyOutput: 'stub-with-stderr',
|
|
111
118
|
reviewsSection: 'Gemini',
|
|
112
119
|
evidenceClass: 'source-grounded',
|
|
113
120
|
requiresBinaries: [],
|
|
114
121
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.gemini',
|
|
115
122
|
modelConfigKey: 'review.models.gemini',
|
|
123
|
+
effortConfigKey: null,
|
|
124
|
+
defaultEffort: null,
|
|
116
125
|
handler: null,
|
|
117
126
|
},
|
|
118
127
|
{
|
|
@@ -139,12 +148,15 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
139
148
|
env: { CLAUDE_CODE_DISABLE_CLAUDE_MDS: '1', CLAUDE_CODE_DISABLE_AUTO_MEMORY: '1' },
|
|
140
149
|
},
|
|
141
150
|
timeoutFloorMs: 1_200_000,
|
|
151
|
+
timeoutConfigKey: 'review.timeouts.claude',
|
|
142
152
|
emptyOutput: 'stub-with-stderr',
|
|
143
153
|
reviewsSection: 'Claude',
|
|
144
154
|
evidenceClass: 'source-grounded',
|
|
145
155
|
requiresBinaries: [],
|
|
146
156
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.claude',
|
|
147
157
|
modelConfigKey: 'review.models.claude',
|
|
158
|
+
effortConfigKey: 'review.effort.claude',
|
|
159
|
+
defaultEffort: 'high',
|
|
148
160
|
handler: null,
|
|
149
161
|
},
|
|
150
162
|
{
|
|
@@ -167,12 +179,15 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
167
179
|
effortChannel: 'argv',
|
|
168
180
|
},
|
|
169
181
|
timeoutFloorMs: 1_200_000,
|
|
182
|
+
timeoutConfigKey: 'review.timeouts.codex',
|
|
170
183
|
emptyOutput: 'stub-with-stderr',
|
|
171
184
|
reviewsSection: 'Codex',
|
|
172
185
|
evidenceClass: 'source-grounded',
|
|
173
186
|
requiresBinaries: [],
|
|
174
187
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.codex',
|
|
175
188
|
modelConfigKey: 'review.models.codex',
|
|
189
|
+
effortConfigKey: 'review.effort.codex',
|
|
190
|
+
defaultEffort: 'high',
|
|
176
191
|
handler: null,
|
|
177
192
|
},
|
|
178
193
|
{
|
|
@@ -192,6 +207,7 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
192
207
|
effortChannel: 'none',
|
|
193
208
|
},
|
|
194
209
|
timeoutFloorMs: 360_000,
|
|
210
|
+
timeoutConfigKey: null,
|
|
195
211
|
emptyOutput: 'stub-with-stderr',
|
|
196
212
|
reviewsSection: 'CodeRabbit',
|
|
197
213
|
evidenceClass: 'diff-only',
|
|
@@ -199,6 +215,8 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
199
215
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.coderabbit',
|
|
200
216
|
// Accepts no model flag at all (review.md:367) — not merely "none configured".
|
|
201
217
|
modelConfigKey: null,
|
|
218
|
+
effortConfigKey: null,
|
|
219
|
+
defaultEffort: null,
|
|
202
220
|
handler: null,
|
|
203
221
|
},
|
|
204
222
|
{
|
|
@@ -217,6 +235,7 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
217
235
|
effortChannel: 'argv',
|
|
218
236
|
},
|
|
219
237
|
timeoutFloorMs: 660_000,
|
|
238
|
+
timeoutConfigKey: 'review.timeouts.opencode',
|
|
220
239
|
emptyOutput: 'stub-with-stderr',
|
|
221
240
|
reviewsSection: 'OpenCode',
|
|
222
241
|
evidenceClass: 'source-grounded',
|
|
@@ -225,6 +244,8 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
225
244
|
requiresBinaries: [],
|
|
226
245
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.opencode',
|
|
227
246
|
modelConfigKey: 'review.models.opencode',
|
|
247
|
+
effortConfigKey: 'review.effort.opencode',
|
|
248
|
+
defaultEffort: 'high',
|
|
228
249
|
// Phase 5b (#2799): was `null`. The review is REBUILT from assistant `text` parts; a plain
|
|
229
250
|
// stdout copy would write the raw JSON envelope as the review (#1936). See LaneHandler.
|
|
230
251
|
handler: 'opencode',
|
|
@@ -242,12 +263,15 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
242
263
|
effortChannel: 'none',
|
|
243
264
|
},
|
|
244
265
|
timeoutFloorMs: 900_000,
|
|
266
|
+
timeoutConfigKey: null,
|
|
245
267
|
emptyOutput: 'stub-with-stderr',
|
|
246
268
|
reviewsSection: 'Qwen',
|
|
247
269
|
evidenceClass: 'source-grounded',
|
|
248
270
|
requiresBinaries: [],
|
|
249
271
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.qwen',
|
|
250
272
|
modelConfigKey: null,
|
|
273
|
+
effortConfigKey: null,
|
|
274
|
+
defaultEffort: null,
|
|
251
275
|
handler: null,
|
|
252
276
|
},
|
|
253
277
|
{
|
|
@@ -260,19 +284,23 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
260
284
|
probe: { kind: 'command-exists', binary: 'cursor-agent' },
|
|
261
285
|
invoke: {
|
|
262
286
|
binary: 'cursor-agent',
|
|
263
|
-
args: ['-p', '--mode', 'ask', '--trust', '--output-format', 'text', '{{prompt}}'],
|
|
287
|
+
args: ['-p', '{{model}}', '--mode', 'ask', '--trust', '--output-format', 'text', '{{prompt}}'],
|
|
264
288
|
promptChannel: 'argv-file-ref',
|
|
265
289
|
outputChannel: 'stdout',
|
|
266
|
-
modelArg:
|
|
290
|
+
modelArg: '--model',
|
|
267
291
|
effortChannel: 'none',
|
|
268
292
|
},
|
|
269
293
|
timeoutFloorMs: 900_000,
|
|
294
|
+
timeoutConfigKey: null,
|
|
270
295
|
emptyOutput: 'stub-with-stderr',
|
|
271
296
|
reviewsSection: 'Cursor',
|
|
272
297
|
evidenceClass: 'source-grounded',
|
|
273
298
|
requiresBinaries: [],
|
|
274
299
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.cursor',
|
|
275
|
-
|
|
300
|
+
// #3653: cursor-agent exposes --model (204 selectable models); wired the same as codex.
|
|
301
|
+
modelConfigKey: 'review.models.cursor',
|
|
302
|
+
effortConfigKey: null,
|
|
303
|
+
defaultEffort: null,
|
|
276
304
|
handler: null,
|
|
277
305
|
},
|
|
278
306
|
{
|
|
@@ -286,13 +314,19 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
286
314
|
probe: { kind: 'command-exists', binary: 'agy' },
|
|
287
315
|
invoke: {
|
|
288
316
|
binary: 'agy',
|
|
289
|
-
|
|
317
|
+
// `{{nativeTimeout}}` is the fifth ARGV_PLACEHOLDER member (#3274) — `resolveLanePlan`
|
|
318
|
+
// (review-lane-invocation.cts) expands it to a value DERIVED from this same lane's resolved
|
|
319
|
+
// outer `timeoutMs`, so the native `--print-timeout` and the outer wall-clock cap can never
|
|
320
|
+
// drift apart. No other shipped lane's `args` template contains this token, so the expansion
|
|
321
|
+
// is inert everywhere else.
|
|
322
|
+
args: ['--print-timeout', '{{nativeTimeout}}', '{{model}}', '-p', '{{prompt}}'],
|
|
290
323
|
promptChannel: 'argv-file-ref',
|
|
291
324
|
outputChannel: 'stdout',
|
|
292
325
|
modelArg: '--model',
|
|
293
326
|
effortChannel: 'none',
|
|
294
327
|
},
|
|
295
328
|
timeoutFloorMs: 600_000,
|
|
329
|
+
timeoutConfigKey: 'review.timeouts.antigravity',
|
|
296
330
|
emptyOutput: 'handler-owned',
|
|
297
331
|
reviewsSection: 'Antigravity',
|
|
298
332
|
evidenceClass: 'source-grounded',
|
|
@@ -302,6 +336,8 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
302
336
|
// NOT `review.models.antigravity` — the shipped key is `review.models.agy` (review.md:291) and
|
|
303
337
|
// Phase 4 federated it under that name. This lane is why the key is declared, not derived.
|
|
304
338
|
modelConfigKey: 'review.models.agy',
|
|
339
|
+
effortConfigKey: null,
|
|
340
|
+
defaultEffort: null,
|
|
305
341
|
handler: 'antigravity',
|
|
306
342
|
},
|
|
307
343
|
{
|
|
@@ -323,6 +359,7 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
323
359
|
effortChannel: 'none',
|
|
324
360
|
},
|
|
325
361
|
timeoutFloorMs: 120_000,
|
|
362
|
+
timeoutConfigKey: 'review.timeouts.ollama',
|
|
326
363
|
emptyOutput: 'stub-with-stderr',
|
|
327
364
|
reviewsSection: 'Ollama',
|
|
328
365
|
evidenceClass: 'source-grounded',
|
|
@@ -331,6 +368,8 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
331
368
|
requiresBinaries: [],
|
|
332
369
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.ollama',
|
|
333
370
|
modelConfigKey: 'review.models.ollama',
|
|
371
|
+
effortConfigKey: null,
|
|
372
|
+
defaultEffort: null,
|
|
334
373
|
handler: 'openai-compatible',
|
|
335
374
|
},
|
|
336
375
|
{
|
|
@@ -352,12 +391,15 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
352
391
|
effortChannel: 'none',
|
|
353
392
|
},
|
|
354
393
|
timeoutFloorMs: 120_000,
|
|
394
|
+
timeoutConfigKey: 'review.timeouts.lm_studio',
|
|
355
395
|
emptyOutput: 'stub-with-stderr',
|
|
356
396
|
reviewsSection: 'LM Studio',
|
|
357
397
|
evidenceClass: 'source-grounded',
|
|
358
398
|
requiresBinaries: [],
|
|
359
399
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.lm_studio',
|
|
360
400
|
modelConfigKey: 'review.models.lm_studio',
|
|
401
|
+
effortConfigKey: null,
|
|
402
|
+
defaultEffort: null,
|
|
361
403
|
handler: 'openai-compatible',
|
|
362
404
|
},
|
|
363
405
|
{
|
|
@@ -379,12 +421,15 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
379
421
|
effortChannel: 'none',
|
|
380
422
|
},
|
|
381
423
|
timeoutFloorMs: 120_000,
|
|
424
|
+
timeoutConfigKey: 'review.timeouts.llama_cpp',
|
|
382
425
|
emptyOutput: 'stub-with-stderr',
|
|
383
426
|
reviewsSection: 'llama.cpp',
|
|
384
427
|
evidenceClass: 'source-grounded',
|
|
385
428
|
requiresBinaries: [],
|
|
386
429
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.llama_cpp',
|
|
387
430
|
modelConfigKey: 'review.models.llama_cpp',
|
|
431
|
+
effortConfigKey: null,
|
|
432
|
+
defaultEffort: null,
|
|
388
433
|
handler: 'openai-compatible',
|
|
389
434
|
},
|
|
390
435
|
{
|
|
@@ -424,12 +469,15 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
424
469
|
effortChannel: 'none',
|
|
425
470
|
},
|
|
426
471
|
timeoutFloorMs: 900_000,
|
|
472
|
+
timeoutConfigKey: 'review.timeouts.kimi-code',
|
|
427
473
|
emptyOutput: 'stub-with-stderr',
|
|
428
474
|
reviewsSection: 'Kimi Code',
|
|
429
475
|
evidenceClass: 'source-grounded',
|
|
430
476
|
requiresBinaries: [],
|
|
431
477
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.kimi-code',
|
|
432
478
|
modelConfigKey: 'review.models.kimi-code',
|
|
479
|
+
effortConfigKey: null,
|
|
480
|
+
defaultEffort: null,
|
|
433
481
|
handler: null,
|
|
434
482
|
},
|
|
435
483
|
].map((lane) => Object.freeze(lane)));
|
|
@@ -26,8 +26,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
26
26
|
exports.LANE_UNAVAILABLE = void 0;
|
|
27
27
|
exports.configString = configString;
|
|
28
28
|
exports.normalizeHost = normalizeHost;
|
|
29
|
+
exports.resolveLaneEffort = resolveLaneEffort;
|
|
30
|
+
exports.resolveTimeoutMs = resolveTimeoutMs;
|
|
31
|
+
exports.nativeTimeoutToken = nativeTimeoutToken;
|
|
29
32
|
exports.isEmptyReview = isEmptyReview;
|
|
30
33
|
exports.fileRefPrompt = fileRefPrompt;
|
|
34
|
+
exports.artifactPaths = artifactPaths;
|
|
35
|
+
exports.resolveLaneBudget = resolveLaneBudget;
|
|
31
36
|
exports.resolveLanePlan = resolveLanePlan;
|
|
32
37
|
const review_lane_descriptor_cjs_1 = require("./review-lane-descriptor.cjs");
|
|
33
38
|
/* ------------------------------------------------------------------ *
|
|
@@ -122,6 +127,73 @@ function normalizeHost(raw) {
|
|
|
122
127
|
const pathPart = u.pathname.replace(/\/+$/, '');
|
|
123
128
|
return `${scheme}//${host}${port ? `:${port}` : ''}${pathPart}`;
|
|
124
129
|
}
|
|
130
|
+
/** Levels GSD's effort axis accepts (#3533). `inherit` selects the no-argument path. */
|
|
131
|
+
const EFFORT_LEVELS = new Set([
|
|
132
|
+
'minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'inherit',
|
|
133
|
+
]);
|
|
134
|
+
/**
|
|
135
|
+
* Resolve one lane's reasoning effort from REVIEW configuration (#4255).
|
|
136
|
+
*
|
|
137
|
+
* Resolution order, highest first:
|
|
138
|
+
* 1. `lane.effortConfigKey` — the per-lane review effort the operator set
|
|
139
|
+
* 2. `lane.defaultEffort` — the lane's declared review default (`high` for prompt-fed,
|
|
140
|
+
* source-grounded lanes)
|
|
141
|
+
* 3. nothing — no effort argument is emitted and the reviewer CLI's own configuration decides
|
|
142
|
+
*
|
|
143
|
+
* A configured `'inherit'` selects (3) explicitly. An unrecognized level is REFUSED rather than
|
|
144
|
+
* passed to the host: it falls back to the lane default, because forwarding a typo would render an
|
|
145
|
+
* argument the CLI rejects and kill the lane outright.
|
|
146
|
+
*
|
|
147
|
+
* What this function deliberately does NOT do is consult any agent's execution settings. Before
|
|
148
|
+
* #4255 the level came from `gsd-plan-checker`'s installed frontmatter through a hardcoded agent
|
|
149
|
+
* id, so every lane ran at a fast structural verifier's `low` — and, because the rendered argument
|
|
150
|
+
* is a CLI config override, it silently beat the effort the operator had configured for that CLI
|
|
151
|
+
* itself. A value inherited from an unrelated agent is worse than no value at all, which is why
|
|
152
|
+
* (3) emits nothing rather than falling back to some other agent's number.
|
|
153
|
+
*
|
|
154
|
+
* `renderArgv` is injected (the host table and the ADR-2481 surface negotiation live in
|
|
155
|
+
* `model-catalog` / `commands`, above this module's layer) so this stays a pure function of its
|
|
156
|
+
* inputs and the golden lane table can assert it without a spawn.
|
|
157
|
+
*/
|
|
158
|
+
function resolveLaneEffort(lane, configGet, renderArgv) {
|
|
159
|
+
const none = { argv: [], value: null, source: 'none' };
|
|
160
|
+
if (!lane || typeof lane !== 'object')
|
|
161
|
+
return none;
|
|
162
|
+
const configured = lane.effortConfigKey ? configString(configGet(lane.effortConfigKey)) : null;
|
|
163
|
+
const valid = configured !== null && EFFORT_LEVELS.has(configured) ? configured : null;
|
|
164
|
+
const level = valid ?? configString(lane.defaultEffort);
|
|
165
|
+
if (level === null || level === 'inherit')
|
|
166
|
+
return none;
|
|
167
|
+
const rendered = renderArgv(lane.slug, level);
|
|
168
|
+
const argv = (rendered.argv ?? []).filter((a) => typeof a === 'string' && a !== '');
|
|
169
|
+
if (argv.length === 0)
|
|
170
|
+
return none;
|
|
171
|
+
return {
|
|
172
|
+
argv,
|
|
173
|
+
value: configString(rendered.value) ?? level,
|
|
174
|
+
source: valid !== null ? 'config' : 'lane-default',
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function resolveTimeoutMs(timeoutConfigKey, floorMs, configGet) {
|
|
178
|
+
const configuredSeconds = typeof timeoutConfigKey === 'string' ? configGet(timeoutConfigKey) : undefined;
|
|
179
|
+
return typeof configuredSeconds === 'number' && Number.isFinite(configuredSeconds) && configuredSeconds > 0
|
|
180
|
+
? configuredSeconds * 1000
|
|
181
|
+
: floorMs;
|
|
182
|
+
}
|
|
183
|
+
/** Buffer (seconds) a lane's native inner timeout sits under its resolved outer wall-clock cap
|
|
184
|
+
* (#3274). Matches the shipped 600s outer / 540s native relationship exactly when unconfigured:
|
|
185
|
+
* floor(600000/1000) - 60 = 540. */
|
|
186
|
+
const NATIVE_TIMEOUT_BUFFER_SECONDS = 60;
|
|
187
|
+
/**
|
|
188
|
+
* Render the `{{nativeTimeout}}` argv placeholder from a lane's resolved outer timeout (#3274).
|
|
189
|
+
*
|
|
190
|
+
* Clamped to a 1-second floor so a very small configured (or, today, only-ever-default) outer
|
|
191
|
+
* timeout never produces a zero or negative duration string a CLI would reject or misinterpret.
|
|
192
|
+
*/
|
|
193
|
+
function nativeTimeoutToken(timeoutMs) {
|
|
194
|
+
const seconds = Math.max(1, Math.floor(timeoutMs / 1000) - NATIVE_TIMEOUT_BUFFER_SECONDS);
|
|
195
|
+
return `${seconds}s`;
|
|
196
|
+
}
|
|
125
197
|
/**
|
|
126
198
|
* Classify a lane's output as a review or as empty.
|
|
127
199
|
*
|
|
@@ -166,6 +238,27 @@ function artifactPaths(runDir, slug) {
|
|
|
166
238
|
errPath: `${base}/gsd-review-${slug}.err`,
|
|
167
239
|
};
|
|
168
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* Per-lane prompt budget (#2797 semantics, preserved exactly).
|
|
243
|
+
*
|
|
244
|
+
* `-1` is the UNSET sentinel and falls back to the central `review.max_prompt_tokens`, because
|
|
245
|
+
* `0` is a legitimate value meaning "do not trim this lane". Treating 0 as unset would silently
|
|
246
|
+
* switch a user who deliberately disabled trimming onto the global budget.
|
|
247
|
+
*
|
|
248
|
+
* Single source of truth: `gsd-core/bin/gsd-tools.cjs`'s `review-lane plan`/`invoke` and
|
|
249
|
+
* `src/reviewer-step-dispatch.cts`'s `dispatchReviewerLanes` both resolve a lane's budget through
|
|
250
|
+
* this function rather than each carrying their own copy (#4209 R3 — two verbatim copies drift).
|
|
251
|
+
*/
|
|
252
|
+
function resolveLaneBudget(lane, configGet) {
|
|
253
|
+
if (!lane.promptBudgetKey)
|
|
254
|
+
return null;
|
|
255
|
+
const per = configGet(lane.promptBudgetKey);
|
|
256
|
+
const isNum = (v) => typeof v === 'number' && Number.isFinite(v);
|
|
257
|
+
if (isNum(per) && per !== -1)
|
|
258
|
+
return per;
|
|
259
|
+
const global = configGet('review.max_prompt_tokens');
|
|
260
|
+
return isNum(global) ? global : null;
|
|
261
|
+
}
|
|
169
262
|
/* ------------------------------------------------------------------ *
|
|
170
263
|
* Resolution
|
|
171
264
|
* ------------------------------------------------------------------ */
|
|
@@ -212,9 +305,10 @@ function resolveLanePlan(input) {
|
|
|
212
305
|
return fail(exports.LANE_UNAVAILABLE.UNKNOWN_HANDLER, `lane '${slug}' names handler '${String(handler)}', which this GSD version does not provide`);
|
|
213
306
|
}
|
|
214
307
|
const { promptPath, reviewPath, errPath } = artifactPaths(input.runDir, slug);
|
|
215
|
-
const
|
|
308
|
+
const floorMs = typeof lane.timeoutFloorMs === 'number' && Number.isFinite(lane.timeoutFloorMs) && lane.timeoutFloorMs > 0
|
|
216
309
|
? lane.timeoutFloorMs
|
|
217
310
|
: 900_000;
|
|
311
|
+
const timeoutMs = resolveTimeoutMs(lane.timeoutConfigKey, floorMs, input.configGet);
|
|
218
312
|
const emptyOutput = lane.emptyOutput === 'handler-owned' ? 'handler-owned' : 'stub-with-stderr';
|
|
219
313
|
// #3194: only an EXACT 'diff-only' declaration exempts a lane from evidence verification.
|
|
220
314
|
// Anything else — including a missing or garbage value on a third-party overlay body —
|
|
@@ -319,6 +413,7 @@ function resolveLanePlan(input) {
|
|
|
319
413
|
'{{effort}}': effortExpansion,
|
|
320
414
|
'{{output}}': outputExpansion,
|
|
321
415
|
'{{prompt}}': promptExpansion,
|
|
416
|
+
'{{nativeTimeout}}': [nativeTimeoutToken(timeoutMs)],
|
|
322
417
|
};
|
|
323
418
|
const template = Array.isArray(inv.args)
|
|
324
419
|
? inv.args.filter((a) => typeof a === 'string')
|