@opengsd/gsd-core 1.18.0 → 1.20.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 +2 -1
- package/.opencode/plugins/gsd-core.js +2 -3
- package/agents/gsd-code-fixer.compact.md +7 -7
- package/agents/gsd-code-fixer.md +13 -7
- package/agents/gsd-code-reviewer.compact.md +49 -8
- package/agents/gsd-code-reviewer.md +53 -14
- package/agents/gsd-executor.md +8 -4
- package/agents/gsd-verifier.md +1 -1
- package/bin/install.js +422 -103
- package/commands/gsd/update.md +5 -2
- package/gsd-core/bin/gsd-tools.cjs +179 -30
- package/gsd-core/bin/lib/agent-install-check.cjs +29 -3
- package/gsd-core/bin/lib/args-terminator.cjs +114 -0
- package/gsd-core/bin/lib/broken-windows.cjs +59 -1
- package/gsd-core/bin/lib/capability-lifecycle.cjs +1 -12
- package/gsd-core/bin/lib/capability-lock.cjs +13 -2
- package/gsd-core/bin/lib/capability-registry.cjs +376 -103
- package/gsd-core/bin/lib/capability-state.cjs +14 -8
- package/gsd-core/bin/lib/capability-validator.cjs +32 -0
- package/gsd-core/bin/lib/commands.cjs +27 -17
- package/gsd-core/bin/lib/config-loader.cjs +13 -3
- package/gsd-core/bin/lib/config.cjs +256 -58
- package/gsd-core/bin/lib/core-utils.cjs +45 -0
- package/gsd-core/bin/lib/decision-coverage-support.cjs +74 -0
- package/gsd-core/bin/lib/frontmatter.cjs +21 -3
- package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +2 -2
- package/gsd-core/bin/lib/gate-context-drift.cjs +9 -4
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +6 -1
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +6 -1
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +134 -13
- package/gsd-core/bin/lib/gate-phase-context.cjs +7 -8
- package/gsd-core/bin/lib/gate-schema-drift.cjs +1 -1
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +63 -22
- package/gsd-core/bin/lib/gate-ui-safety.cjs +23 -5
- package/gsd-core/bin/lib/git-info-exclude.cjs +52 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +31 -12
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +9 -7
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +3 -3
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +4 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +52 -1
- package/gsd-core/bin/lib/host-integration.cjs +13 -6
- package/gsd-core/bin/lib/init.cjs +245 -68
- package/gsd-core/bin/lib/install-engine.cjs +246 -32
- package/gsd-core/bin/lib/install-profiles.cjs +9 -4
- package/gsd-core/bin/lib/installer-migration-report.cjs +2 -0
- package/gsd-core/bin/lib/io.cjs +6 -0
- package/gsd-core/bin/lib/markdown-line-diff.cjs +147 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +147 -1
- package/gsd-core/bin/lib/markdown-table.cjs +23 -0
- package/gsd-core/bin/lib/mcp-server.cjs +8 -5
- package/gsd-core/bin/lib/milestone-lock.cjs +8 -1
- package/gsd-core/bin/lib/milestone-release-map.cjs +244 -0
- package/gsd-core/bin/lib/milestone-release-tags.cjs +440 -0
- package/gsd-core/bin/lib/milestone.cjs +61 -51
- package/gsd-core/bin/lib/model-catalog.cjs +8 -0
- package/gsd-core/bin/lib/normalize-test-command.cjs +67 -0
- package/gsd-core/bin/lib/phase-entry-grammar.cjs +119 -0
- package/gsd-core/bin/lib/phase-id-display.cjs +2 -0
- package/gsd-core/bin/lib/phase-id.cjs +629 -38
- package/gsd-core/bin/lib/phase-lifecycle.cjs +12 -44
- package/gsd-core/bin/lib/phase-locator.cjs +328 -19
- package/gsd-core/bin/lib/phase.cjs +3066 -653
- package/gsd-core/bin/lib/planning-document.cjs +26 -5
- package/gsd-core/bin/lib/planning-inspect.cjs +27 -35
- package/gsd-core/bin/lib/planning-snapshot.cjs +15 -8
- package/gsd-core/bin/lib/planning-workspace.cjs +21 -3
- package/gsd-core/bin/lib/pristine-baseline.cjs +11 -3
- package/gsd-core/bin/lib/read-only-git-env.cjs +79 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +2 -2
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +57 -2
- package/gsd-core/bin/lib/review-lane-invocation.cjs +125 -18
- package/gsd-core/bin/lib/review-lane-runner.cjs +33 -4
- package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +11 -9
- package/gsd-core/bin/lib/roadmap-parser.cjs +735 -137
- package/gsd-core/bin/lib/roadmap-progress.cjs +136 -0
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +47 -7
- package/gsd-core/bin/lib/roadmap.cjs +383 -123
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +381 -14
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +8 -4
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +60 -16
- package/gsd-core/bin/lib/shell-command-projection.cjs +151 -19
- package/gsd-core/bin/lib/smart-entry.cjs +35 -11
- package/gsd-core/bin/lib/state-contract.cjs +39 -15
- package/gsd-core/bin/lib/state-document.cjs +344 -27
- package/gsd-core/bin/lib/state-transition.cjs +156 -32
- package/gsd-core/bin/lib/state.cjs +527 -186
- package/gsd-core/bin/lib/surface.cjs +9 -0
- package/gsd-core/bin/lib/task-command-router.cjs +5 -25
- package/gsd-core/bin/lib/task-content-resolution.cjs +46 -1
- package/gsd-core/bin/lib/template.cjs +2 -2
- package/gsd-core/bin/lib/validate.cjs +3 -2
- package/gsd-core/bin/lib/vendor/re2js.cjs +863 -577
- package/gsd-core/bin/lib/vendor/re2js.d.cts +284 -219
- package/gsd-core/bin/lib/verification.cjs +96 -9
- package/gsd-core/bin/lib/verify.cjs +4 -2
- package/gsd-core/bin/lib/workstream-inventory.cjs +26 -20
- package/gsd-core/bin/lib/worktree-safety.cjs +22 -1
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
- package/gsd-core/bin/verify-reapply-patches.cjs +411 -10
- package/gsd-core/references/cicd-review-patterns.md +45 -0
- package/gsd-core/references/git-integration.md +11 -0
- package/gsd-core/references/loop-hook-dispatch.md +13 -6
- package/gsd-core/references/necessity-review.md +48 -0
- package/gsd-core/references/planning-config.md +2 -0
- package/gsd-core/references/tdd.md +2 -2
- package/gsd-core/templates/DEBUG.md +16 -0
- package/gsd-core/templates/config.json +2 -1
- package/gsd-core/templates/verification-report.md +1 -1
- package/gsd-core/workflows/audit-fix.md +2 -1
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +10 -1
- package/gsd-core/workflows/code-review-fix.md +46 -5
- package/gsd-core/workflows/code-review.md +64 -7
- package/gsd-core/workflows/complete-milestone/steps/project-md-evolution-review.md +145 -0
- package/gsd-core/workflows/complete-milestone/steps/release-map.md +80 -0
- package/gsd-core/workflows/complete-milestone.md +37 -150
- package/gsd-core/workflows/diagnose-issues.md +29 -5
- package/gsd-core/workflows/discuss-phase/modes/power.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +33 -2
- package/gsd-core/workflows/discuss-phase-power.md +19 -2
- package/gsd-core/workflows/discuss-phase.md +6 -10
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +13 -7
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +7 -2
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -1
- package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +11 -2
- package/gsd-core/workflows/execute-phase.md +10 -6
- package/gsd-core/workflows/execute-plan.md +1 -1
- package/gsd-core/workflows/health.md +2 -1
- package/gsd-core/workflows/import.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +2 -2
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +13 -9
- package/gsd-core/workflows/plan-phase.md +14 -14
- package/gsd-core/workflows/pr-branch.md +2 -0
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +1 -1
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +8 -1
- package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +2 -1
- package/gsd-core/workflows/quick.md +1 -1
- package/gsd-core/workflows/reapply-patches.md +104 -0
- package/gsd-core/workflows/review.md +70 -154
- package/gsd-core/workflows/section-manifest.json +5 -0
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/settings-advanced.md +57 -9
- package/gsd-core/workflows/settings.md +1 -0
- package/gsd-core/workflows/ship.md +15 -4
- package/gsd-core/workflows/spec-phase.md +3 -6
- package/gsd-core/workflows/verify-work.md +4 -3
- package/hooks/dist/gsd-agent-isolation-guard.js +11 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +6 -2
- package/hooks/dist/gsd-graphify-update.sh +6 -0
- package/hooks/dist/gsd-path-export.js +95 -0
- package/hooks/dist/gsd-secret-read-guard.js +172 -39
- package/hooks/dist/gsd-statusline.js +37 -3
- package/hooks/dist/gsd-windsurf-pre-write.js +29 -2
- package/hooks/dist/gsd-workflow-guard.js +3 -2
- package/hooks/dist/gsd-worktree-path-guard.js +29 -2
- package/hooks/dist/lib/git-probe.js +16 -0
- package/hooks/dist/lib/isolation-sentinel.js +44 -0
- package/hooks/dist/managed-hooks-registry.cjs +1 -0
- package/hooks/gsd-agent-isolation-guard.js +11 -1
- package/hooks/gsd-cursor-subagent-start.js +6 -2
- package/hooks/gsd-graphify-update.sh +6 -0
- package/hooks/gsd-path-export.js +95 -0
- package/hooks/gsd-secret-read-guard.js +172 -39
- package/hooks/gsd-statusline.js +37 -3
- package/hooks/gsd-windsurf-pre-write.js +29 -2
- package/hooks/gsd-workflow-guard.js +3 -2
- package/hooks/gsd-worktree-path-guard.js +29 -2
- package/hooks/hooks.json +1 -0
- package/hooks/lib/git-probe.js +16 -0
- package/hooks/lib/isolation-sentinel.js +44 -0
- package/hooks/managed-hooks-registry.cjs +1 -0
- package/package.json +15 -8
- package/pi/gsd.cjs +1047 -10
- package/pi/package-agents/gsd-advisor-researcher.md +113 -0
- package/pi/package-agents/gsd-ai-researcher.md +111 -0
- package/pi/package-agents/gsd-assumptions-analyzer.md +110 -0
- package/pi/package-agents/gsd-code-fixer.md +774 -0
- package/pi/package-agents/gsd-code-reviewer.md +441 -0
- package/pi/package-agents/gsd-codebase-mapper.md +850 -0
- package/pi/package-agents/gsd-debug-session-manager.md +416 -0
- package/pi/package-agents/gsd-debugger.md +1274 -0
- package/pi/package-agents/gsd-doc-classifier.md +269 -0
- package/pi/package-agents/gsd-doc-synthesizer.md +259 -0
- package/pi/package-agents/gsd-doc-verifier.md +212 -0
- package/pi/package-agents/gsd-doc-writer.md +626 -0
- package/pi/package-agents/gsd-dom-verifier.md +164 -0
- package/pi/package-agents/gsd-domain-researcher.md +144 -0
- package/pi/package-agents/gsd-eval-auditor.md +185 -0
- package/pi/package-agents/gsd-eval-planner.md +149 -0
- package/pi/package-agents/gsd-executor.md +898 -0
- package/pi/package-agents/gsd-framework-selector.md +159 -0
- package/pi/package-agents/gsd-integration-checker.md +476 -0
- package/pi/package-agents/gsd-intel-updater.md +338 -0
- package/pi/package-agents/gsd-mempalace-curator.md +49 -0
- package/pi/package-agents/gsd-nyquist-auditor.md +200 -0
- package/pi/package-agents/gsd-pattern-mapper.md +340 -0
- package/pi/package-agents/gsd-phase-researcher.md +897 -0
- package/pi/package-agents/gsd-plan-checker.md +1077 -0
- package/pi/package-agents/gsd-planner.md +1003 -0
- package/pi/package-agents/gsd-project-researcher.md +611 -0
- package/pi/package-agents/gsd-research-synthesizer.md +259 -0
- package/pi/package-agents/gsd-roadmapper.md +779 -0
- package/pi/package-agents/gsd-security-auditor.md +171 -0
- package/pi/package-agents/gsd-ui-auditor.md +581 -0
- package/pi/package-agents/gsd-ui-checker.md +417 -0
- package/pi/package-agents/gsd-ui-researcher.md +469 -0
- package/pi/package-agents/gsd-user-profiler.md +174 -0
- package/pi/package-agents/gsd-verifier.md +963 -0
- package/pi/package-agents/manifest.json +39 -0
- package/pi/package-skills/gsd-add-tests/SKILL.md +39 -0
- package/pi/package-skills/gsd-ai-integration-phase/SKILL.md +36 -0
- package/pi/package-skills/gsd-audit-fix/SKILL.md +34 -0
- package/pi/package-skills/gsd-audit-milestone/SKILL.md +40 -0
- package/pi/package-skills/gsd-audit-uat/SKILL.md +26 -0
- package/pi/package-skills/gsd-autonomous/SKILL.md +52 -0
- package/pi/package-skills/gsd-capture/SKILL.md +68 -0
- package/pi/package-skills/gsd-cleanup/SKILL.md +25 -0
- package/pi/package-skills/gsd-code-review/SKILL.md +71 -0
- package/pi/package-skills/gsd-complete-milestone/SKILL.md +147 -0
- package/pi/package-skills/gsd-config/SKILL.md +60 -0
- package/pi/package-skills/gsd-debug/SKILL.md +64 -0
- package/pi/package-skills/gsd-discuss-phase/SKILL.md +74 -0
- package/pi/package-skills/gsd-docs-update/SKILL.md +50 -0
- package/pi/package-skills/gsd-eval-review/SKILL.md +35 -0
- package/pi/package-skills/gsd-execute-phase/SKILL.md +62 -0
- package/pi/package-skills/gsd-explore/SKILL.md +26 -0
- package/pi/package-skills/gsd-extract-learnings/SKILL.md +25 -0
- package/pi/package-skills/gsd-fast/SKILL.md +33 -0
- package/pi/package-skills/gsd-forensics/SKILL.md +59 -0
- package/pi/package-skills/gsd-graphify/SKILL.md +210 -0
- package/pi/package-skills/gsd-health/SKILL.md +36 -0
- package/pi/package-skills/gsd-help/SKILL.md +37 -0
- package/pi/package-skills/gsd-import/SKILL.md +46 -0
- package/pi/package-skills/gsd-inbox/SKILL.md +42 -0
- package/pi/package-skills/gsd-ingest-docs/SKILL.md +43 -0
- package/pi/package-skills/gsd-manager/SKILL.md +46 -0
- package/pi/package-skills/gsd-map-codebase/SKILL.md +85 -0
- package/pi/package-skills/gsd-mempalace-capture/SKILL.md +111 -0
- package/pi/package-skills/gsd-mempalace-recall/SKILL.md +111 -0
- package/pi/package-skills/gsd-milestone-summary/SKILL.md +54 -0
- package/pi/package-skills/gsd-mvp-phase/SKILL.md +45 -0
- package/pi/package-skills/gsd-new-milestone/SKILL.md +49 -0
- package/pi/package-skills/gsd-new-project/SKILL.md +49 -0
- package/pi/package-skills/gsd-next/SKILL.md +34 -0
- package/pi/package-skills/gsd-ns-context/SKILL.md +31 -0
- package/pi/package-skills/gsd-ns-ideate/SKILL.md +30 -0
- package/pi/package-skills/gsd-ns-manage/SKILL.md +42 -0
- package/pi/package-skills/gsd-ns-project/SKILL.md +34 -0
- package/pi/package-skills/gsd-ns-review/SKILL.md +35 -0
- package/pi/package-skills/gsd-ns-workflow/SKILL.md +44 -0
- package/pi/package-skills/gsd-onboard/SKILL.md +46 -0
- package/pi/package-skills/gsd-pause-work/SKILL.md +48 -0
- package/pi/package-skills/gsd-phase/SKILL.md +61 -0
- package/pi/package-skills/gsd-plan-phase/SKILL.md +62 -0
- package/pi/package-skills/gsd-plan-review-convergence/SKILL.md +63 -0
- package/pi/package-skills/gsd-pr-branch/SKILL.md +31 -0
- package/pi/package-skills/gsd-profile-user/SKILL.md +48 -0
- package/pi/package-skills/gsd-progress/SKILL.md +51 -0
- package/pi/package-skills/gsd-quick/SKILL.md +179 -0
- package/pi/package-skills/gsd-quick-batch/SKILL.md +114 -0
- package/pi/package-skills/gsd-resume-work/SKILL.md +31 -0
- package/pi/package-skills/gsd-review/SKILL.md +50 -0
- package/pi/package-skills/gsd-review-backlog/SKILL.md +65 -0
- package/pi/package-skills/gsd-secure-phase/SKILL.md +37 -0
- package/pi/package-skills/gsd-settings/SKILL.md +30 -0
- package/pi/package-skills/gsd-ship/SKILL.md +27 -0
- package/pi/package-skills/gsd-sketch/SKILL.md +56 -0
- package/pi/package-skills/gsd-spec-phase/SKILL.md +63 -0
- package/pi/package-skills/gsd-spike/SKILL.md +53 -0
- package/pi/package-skills/gsd-stats/SKILL.md +22 -0
- package/pi/package-skills/gsd-surface/SKILL.md +177 -0
- package/pi/package-skills/gsd-thread/SKILL.md +29 -0
- package/pi/package-skills/gsd-ui-phase/SKILL.md +35 -0
- package/pi/package-skills/gsd-ui-review/SKILL.md +35 -0
- package/pi/package-skills/gsd-ultraplan-phase/SKILL.md +38 -0
- package/pi/package-skills/gsd-undo/SKILL.md +38 -0
- package/pi/package-skills/gsd-update/SKILL.md +54 -0
- package/pi/package-skills/gsd-validate-phase/SKILL.md +37 -0
- package/pi/package-skills/gsd-verify-work/SKILL.md +41 -0
- package/pi/package-skills/gsd-workspace/SKILL.md +57 -0
- package/pi/package-skills/gsd-workstreams/SKILL.md +73 -0
- package/scripts/build-hooks.js +4 -0
- package/scripts/ci-next-health.cjs +246 -23
- package/scripts/command-contract-helpers.cjs +1 -1
- package/scripts/docs-guard-registry.cjs +22 -7
- package/scripts/gen-features.cjs +14 -2
- package/scripts/gen-health-docs.cjs +13 -1
- package/scripts/gen-pi-package-skills.cjs +217 -0
- package/scripts/lib/drift-scan.cjs +27 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +17 -1
- package/scripts/lib/platform-conformance-tier.generated.cjs +37 -1
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +3 -3
- package/scripts/lint-phase-enumeration-drift.cjs +8 -4
- package/scripts/lint-retired-runtime-name.cjs +5 -0
- package/scripts/lint-roadmap-progress-drift.cjs +421 -0
- package/scripts/mutation-matrix.cjs +23 -1
- package/scripts/npm-audit-baseline.cjs +41 -7
- package/scripts/reviewed-or-maintainer-policy.cjs +181 -0
- package/scripts/select-docs-guards.cjs +1 -1
- package/scripts/self-test-report-policy.cjs +350 -0
- package/scripts/sync-next-version.cjs +38 -6
- package/skills/gsd-update/SKILL.md +5 -2
- package/vscode/package.json +1 -1
- package/scripts/diagnose-validate-commit-in-tier.cjs +0 -270
- package/scripts/diagnose-validate-commit-phases.cjs +0 -348
- package/scripts/xtrace-phase-timing.cjs +0 -205
|
@@ -58,6 +58,7 @@ exports.DOCS_PARITY_VIOLATION = exports.LANE_SLUG_RE = exports.PARITY_VIOLATION
|
|
|
58
58
|
exports.mergeReviewerLanes = mergeReviewerLanes;
|
|
59
59
|
exports.checkReviewerLaneParity = checkReviewerLaneParity;
|
|
60
60
|
exports.checkReviewerDocsParity = checkReviewerDocsParity;
|
|
61
|
+
const text_lines_cjs_1 = require("./text-lines.cjs");
|
|
61
62
|
/**
|
|
62
63
|
* Argv placeholders (Phase 5b, #2799).
|
|
63
64
|
*
|
|
@@ -134,6 +135,8 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
134
135
|
evidenceClass: 'source-grounded',
|
|
135
136
|
requiresBinaries: [],
|
|
136
137
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.claude',
|
|
138
|
+
contextWindowTokens: 200000,
|
|
139
|
+
contextWindowConfigKey: 'review.context_window_tokens.claude',
|
|
137
140
|
modelConfigKey: 'review.models.claude',
|
|
138
141
|
effortConfigKey: 'review.effort.claude',
|
|
139
142
|
defaultEffort: 'high',
|
|
@@ -165,6 +168,8 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
165
168
|
evidenceClass: 'source-grounded',
|
|
166
169
|
requiresBinaries: [],
|
|
167
170
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.codex',
|
|
171
|
+
contextWindowTokens: 272000,
|
|
172
|
+
contextWindowConfigKey: 'review.context_window_tokens.codex',
|
|
168
173
|
modelConfigKey: 'review.models.codex',
|
|
169
174
|
effortConfigKey: 'review.effort.codex',
|
|
170
175
|
defaultEffort: 'high',
|
|
@@ -193,6 +198,8 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
193
198
|
evidenceClass: 'diff-only',
|
|
194
199
|
requiresBinaries: [],
|
|
195
200
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.coderabbit',
|
|
201
|
+
contextWindowTokens: null,
|
|
202
|
+
contextWindowConfigKey: null,
|
|
196
203
|
// Accepts no model flag at all (review.md:367) — not merely "none configured".
|
|
197
204
|
modelConfigKey: null,
|
|
198
205
|
effortConfigKey: null,
|
|
@@ -223,6 +230,8 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
223
230
|
// stock Windows/Git-Bash (#2589) — is no longer a prerequisite for this lane.
|
|
224
231
|
requiresBinaries: [],
|
|
225
232
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.opencode',
|
|
233
|
+
contextWindowTokens: null,
|
|
234
|
+
contextWindowConfigKey: 'review.context_window_tokens.opencode',
|
|
226
235
|
modelConfigKey: 'review.models.opencode',
|
|
227
236
|
effortConfigKey: 'review.effort.opencode',
|
|
228
237
|
defaultEffort: 'high',
|
|
@@ -249,6 +258,8 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
249
258
|
evidenceClass: 'source-grounded',
|
|
250
259
|
requiresBinaries: [],
|
|
251
260
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.qwen',
|
|
261
|
+
contextWindowTokens: 131072,
|
|
262
|
+
contextWindowConfigKey: 'review.context_window_tokens.qwen',
|
|
252
263
|
modelConfigKey: null,
|
|
253
264
|
effortConfigKey: null,
|
|
254
265
|
defaultEffort: null,
|
|
@@ -277,6 +288,8 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
277
288
|
evidenceClass: 'source-grounded',
|
|
278
289
|
requiresBinaries: [],
|
|
279
290
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.cursor',
|
|
291
|
+
contextWindowTokens: null,
|
|
292
|
+
contextWindowConfigKey: 'review.context_window_tokens.cursor',
|
|
280
293
|
// #3653: cursor-agent exposes --model (204 selectable models); wired the same as codex.
|
|
281
294
|
modelConfigKey: 'review.models.cursor',
|
|
282
295
|
effortConfigKey: null,
|
|
@@ -313,6 +326,8 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
313
326
|
// Phase 5b: the handler reads the transcript with JSON.parse per line, not `jq`.
|
|
314
327
|
requiresBinaries: [],
|
|
315
328
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.antigravity',
|
|
329
|
+
contextWindowTokens: null,
|
|
330
|
+
contextWindowConfigKey: 'review.context_window_tokens.antigravity',
|
|
316
331
|
// NOT `review.models.antigravity` — the shipped key is `review.models.agy` (review.md:291) and
|
|
317
332
|
// Phase 4 federated it under that name. This lane is why the key is declared, not derived.
|
|
318
333
|
modelConfigKey: 'review.models.agy',
|
|
@@ -347,6 +362,8 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
347
362
|
// neither `jq` nor `curl` is a prerequisite any more (#2589's stated Windows hazard).
|
|
348
363
|
requiresBinaries: [],
|
|
349
364
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.ollama',
|
|
365
|
+
contextWindowTokens: null,
|
|
366
|
+
contextWindowConfigKey: 'review.context_window_tokens.ollama',
|
|
350
367
|
modelConfigKey: 'review.models.ollama',
|
|
351
368
|
effortConfigKey: null,
|
|
352
369
|
defaultEffort: null,
|
|
@@ -377,6 +394,8 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
377
394
|
evidenceClass: 'source-grounded',
|
|
378
395
|
requiresBinaries: [],
|
|
379
396
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.lm_studio',
|
|
397
|
+
contextWindowTokens: null,
|
|
398
|
+
contextWindowConfigKey: 'review.context_window_tokens.lm_studio',
|
|
380
399
|
modelConfigKey: 'review.models.lm_studio',
|
|
381
400
|
effortConfigKey: null,
|
|
382
401
|
defaultEffort: null,
|
|
@@ -407,6 +426,8 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
407
426
|
evidenceClass: 'source-grounded',
|
|
408
427
|
requiresBinaries: [],
|
|
409
428
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.llama_cpp',
|
|
429
|
+
contextWindowTokens: null,
|
|
430
|
+
contextWindowConfigKey: 'review.context_window_tokens.llama_cpp',
|
|
410
431
|
modelConfigKey: 'review.models.llama_cpp',
|
|
411
432
|
effortConfigKey: null,
|
|
412
433
|
defaultEffort: null,
|
|
@@ -455,6 +476,8 @@ exports.REVIEWER_LANES = Object.freeze([
|
|
|
455
476
|
evidenceClass: 'source-grounded',
|
|
456
477
|
requiresBinaries: [],
|
|
457
478
|
promptBudgetKey: 'review.max_prompt_tokens_per_reviewer.kimi-code',
|
|
479
|
+
contextWindowTokens: 262144,
|
|
480
|
+
contextWindowConfigKey: 'review.context_window_tokens.kimi-code',
|
|
458
481
|
modelConfigKey: 'review.models.kimi-code',
|
|
459
482
|
effortConfigKey: null,
|
|
460
483
|
defaultEffort: null,
|
|
@@ -576,6 +599,7 @@ exports.PARITY_VIOLATION = Object.freeze({
|
|
|
576
599
|
REGISTRY_LANE_UNDECLARED: 'registry_lane_undeclared',
|
|
577
600
|
DESCRIPTOR_LANE_NOT_IN_REGISTRY: 'descriptor_lane_not_in_registry',
|
|
578
601
|
BESPOKE_LEG_PRESENT: 'bespoke_leg_present',
|
|
602
|
+
AVAILABILITY_FALLBACK_MISMATCH: 'availability_fallback_mismatch',
|
|
579
603
|
DUPLICATE_SLUG: 'duplicate_slug',
|
|
580
604
|
DUPLICATE_FLAG: 'duplicate_flag',
|
|
581
605
|
DUPLICATE_SECTION: 'duplicate_section',
|
|
@@ -607,6 +631,10 @@ const LEG_MARKER_RE = /<!--\s*reviewer-lane:\s*([a-z0-9_-]+)\s*-->/g;
|
|
|
607
631
|
* design principle of this module.
|
|
608
632
|
*/
|
|
609
633
|
exports.LANE_SLUG_RE = /^[a-z0-9][a-z0-9_-]*$/;
|
|
634
|
+
/** The workflow's availability call: `gsd_run review-lane availability ...` at command position. */
|
|
635
|
+
const AVAILABILITY_CALL_RE = /^\s*gsd_run review-lane availability(?:\s|$)/;
|
|
636
|
+
/** One `<slug>:missing` row in the printf fallback; slug is LANE_SLUG_RE's grammar capped at 32 chars. */
|
|
637
|
+
const AVAILABILITY_FALLBACK_ROW_RE = /(?:'|\\n)([a-z0-9][a-z0-9_-]{0,31}):missing/g;
|
|
610
638
|
/** Bounds of the step a bespoke leg marker could appear inside. */
|
|
611
639
|
const INVOKE_STEP_RE = /<step name="invoke_reviewers">([\s\S]*?)<\/step>/;
|
|
612
640
|
function sliceStep(workflowText, re) {
|
|
@@ -627,8 +655,10 @@ function countOccurrences(haystack, re) {
|
|
|
627
655
|
}
|
|
628
656
|
/**
|
|
629
657
|
* Bidirectional parity across three surfaces: the descriptor, the roster
|
|
630
|
-
* (`KNOWN_REVIEWER_SLUGS`), and the generated capability **registry** — plus
|
|
631
|
-
*
|
|
658
|
+
* (`KNOWN_REVIEWER_SLUGS`), and the generated capability **registry** — plus two assertions
|
|
659
|
+
* against the workflow: the anti-parity check, and the availability-fallback check (the workflow
|
|
660
|
+
* makes the availability call, has a fallback row per lane, and the fallback slug set equals the
|
|
661
|
+
* openai-http lanes).
|
|
632
662
|
*
|
|
633
663
|
* **Re-pointed by Phase 5b (#2799).** Through Phase 5a this function also required a literal
|
|
634
664
|
* `<!-- reviewer-lane: <slug> -->` per lane inside `invoke_reviewers` and a literal
|
|
@@ -671,6 +701,7 @@ function checkReviewerLaneParity(input) {
|
|
|
671
701
|
const seenSlug = new Set();
|
|
672
702
|
const seenFlag = new Set();
|
|
673
703
|
const seenSection = new Set();
|
|
704
|
+
const httpSlugs = new Set();
|
|
674
705
|
// The declared parameter type says `ReviewerLane[]`, but this function is a
|
|
675
706
|
// trust boundary — narrow from `unknown` rather than believing the annotation.
|
|
676
707
|
const rawLanes = Array.isArray(descriptor) ? descriptor : [];
|
|
@@ -689,6 +720,8 @@ function checkReviewerLaneParity(input) {
|
|
|
689
720
|
if (seenSlug.has(slug))
|
|
690
721
|
add(exports.PARITY_VIOLATION.DUPLICATE_SLUG, slug);
|
|
691
722
|
seenSlug.add(slug);
|
|
723
|
+
if (lane.transport === 'openai-http')
|
|
724
|
+
httpSlugs.add(slug);
|
|
692
725
|
const flags = Array.isArray(lane.flags) ? lane.flags : [];
|
|
693
726
|
for (const flag of flags) {
|
|
694
727
|
if (typeof flag !== 'string')
|
|
@@ -740,6 +773,28 @@ function checkReviewerLaneParity(input) {
|
|
|
740
773
|
for (const slug of markerSlugs.keys()) {
|
|
741
774
|
add(exports.PARITY_VIOLATION.BESPOKE_LEG_PRESENT, slug);
|
|
742
775
|
}
|
|
776
|
+
// --- the availability call's `||` fallback must name exactly the openai-http lanes ---
|
|
777
|
+
//
|
|
778
|
+
// review.md prints these rows only when an older gsd-tools lacks `review-lane availability`, so
|
|
779
|
+
// they are a second hand-kept copy of the roster. Checked only when the call is present.
|
|
780
|
+
// Anchored to the command position so a comment or prose mention cannot shadow the real call;
|
|
781
|
+
// a missing call is itself a violation (otherwise deleting it would silently skip this check).
|
|
782
|
+
const availabilityLine = (0, text_lines_cjs_1.splitLines)(workflowText).find((line) => AVAILABILITY_CALL_RE.test(line));
|
|
783
|
+
if (availabilityLine === undefined) {
|
|
784
|
+
add(exports.PARITY_VIOLATION.AVAILABILITY_FALLBACK_MISMATCH, 'no-call');
|
|
785
|
+
}
|
|
786
|
+
else {
|
|
787
|
+
if (!availabilityLine.includes('review-lane availability ||')) {
|
|
788
|
+
add(exports.PARITY_VIOLATION.AVAILABILITY_FALLBACK_MISMATCH, 'no-fallback');
|
|
789
|
+
}
|
|
790
|
+
const fallback = new Set(Array.from(availabilityLine.matchAll(AVAILABILITY_FALLBACK_ROW_RE), (m) => m[1]));
|
|
791
|
+
for (const slug of fallback)
|
|
792
|
+
if (!httpSlugs.has(slug))
|
|
793
|
+
add(exports.PARITY_VIOLATION.AVAILABILITY_FALLBACK_MISMATCH, slug);
|
|
794
|
+
for (const slug of httpSlugs)
|
|
795
|
+
if (!fallback.has(slug))
|
|
796
|
+
add(exports.PARITY_VIOLATION.AVAILABILITY_FALLBACK_MISMATCH, slug);
|
|
797
|
+
}
|
|
743
798
|
return { ok: violations.length === 0, violations };
|
|
744
799
|
}
|
|
745
800
|
/* ------------------------------------------------------------------ *
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* third-party overlay manifests (ADR-2782 D4).
|
|
24
24
|
*/
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.LANE_UNAVAILABLE = void 0;
|
|
26
|
+
exports.CONTEXT_WINDOW_HEADROOM = exports.LANE_UNAVAILABLE = void 0;
|
|
27
27
|
exports.configString = configString;
|
|
28
28
|
exports.normalizeHost = normalizeHost;
|
|
29
29
|
exports.resolveLaneEffort = resolveLaneEffort;
|
|
@@ -33,7 +33,10 @@ exports.isEmptyReview = isEmptyReview;
|
|
|
33
33
|
exports.fileRefPrompt = fileRefPrompt;
|
|
34
34
|
exports.applyPromptOverride = applyPromptOverride;
|
|
35
35
|
exports.artifactPaths = artifactPaths;
|
|
36
|
-
exports.
|
|
36
|
+
exports.resolveLaneCap = resolveLaneCap;
|
|
37
|
+
exports.checkPromptAgainstCap = checkPromptAgainstCap;
|
|
38
|
+
exports.refuseIfOverCap = refuseIfOverCap;
|
|
39
|
+
exports.renderPromptRefusalStub = renderPromptRefusalStub;
|
|
37
40
|
exports.resolveLanePlan = resolveLanePlan;
|
|
38
41
|
const review_lane_descriptor_cjs_1 = require("./review-lane-descriptor.cjs");
|
|
39
42
|
/* ------------------------------------------------------------------ *
|
|
@@ -60,8 +63,12 @@ exports.LANE_UNAVAILABLE = Object.freeze({
|
|
|
60
63
|
PROBE_TIMEOUT: 'probe_timeout',
|
|
61
64
|
HOST_UNREACHABLE: 'host_unreachable',
|
|
62
65
|
EGRESS_HOST_CHANGED: 'egress_host_changed',
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
/**
|
|
67
|
+
* #4559: the prompt a lane would receive is larger than its prompt cap (an explicit cap, or the
|
|
68
|
+
* default derived from the lane's context window). The lane is REFUSED — never trimmed, because a
|
|
69
|
+
* silently truncated plan set is a review of something other than the plans.
|
|
70
|
+
*/
|
|
71
|
+
PROMPT_EXCEEDS_CONTEXT: 'prompt_exceeds_context',
|
|
65
72
|
});
|
|
66
73
|
/** Every handler name the runner can dispatch. Mirrors `LaneHandler` (D6's closed enum). */
|
|
67
74
|
const KNOWN_HANDLERS = new Set(['antigravity', 'openai-compatible', 'opencode']);
|
|
@@ -233,7 +240,8 @@ function fileRefPrompt(promptPath, repoRoot) {
|
|
|
233
240
|
/**
|
|
234
241
|
* Re-point a resolved plan at a different prompt file (`review-lane invoke --prompt-file`, #5049).
|
|
235
242
|
*
|
|
236
|
-
* The override carries a
|
|
243
|
+
* The override carries a caller-substituted prompt (a section subset, say; nothing trims a prompt
|
|
244
|
+
* to fit a lane since #4559), so it has to land wherever THIS lane actually
|
|
237
245
|
* reads its prompt, and that differs by channel:
|
|
238
246
|
* - `stdin`: the runner streams the file `plan.stdin` names.
|
|
239
247
|
* - `argv-file-ref`: the prompt PATH is embedded in a sentence in argv (`fileRefPrompt`), already
|
|
@@ -279,25 +287,124 @@ function artifactPaths(runDir, slug) {
|
|
|
279
287
|
};
|
|
280
288
|
}
|
|
281
289
|
/**
|
|
282
|
-
*
|
|
290
|
+
* Fraction of a lane's declared context window a prompt may occupy (#4559). The remaining 35%
|
|
291
|
+
* absorbs the system prompt, the reply, and `estimateTokens` being a chars/4 estimate rather than
|
|
292
|
+
* a tokenizer (code tokenizes denser than prose).
|
|
293
|
+
*/
|
|
294
|
+
exports.CONTEXT_WINDOW_HEADROOM = 0.65;
|
|
295
|
+
/**
|
|
296
|
+
* Per-lane prompt cap (#2797 semantics, extended by #4559).
|
|
283
297
|
*
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
298
|
+
* Precedence: per-lane `promptBudgetKey` → global `review.max_prompt_tokens` → the default derived
|
|
299
|
+
* from the lane's context window (`floor(window * CONTEXT_WINDOW_HEADROOM)`). `-1` is the UNSET
|
|
300
|
+
* sentinel for the per-lane key, because `0` is a legitimate value meaning "no cap for this lane".
|
|
301
|
+
* An explicit `0` at either explicit level also turns the derived default off.
|
|
302
|
+
*
|
|
303
|
+
* The window is the operator's `contextWindowConfigKey` value when that is a positive finite number
|
|
304
|
+
* (`0` disables the derived cap), else the lane's declared `contextWindowTokens`. Both are narrowed
|
|
305
|
+
* from `unknown` — overlay lanes and config values cross a trust boundary — and anything that is not
|
|
306
|
+
* a positive finite number narrows to "unset".
|
|
287
307
|
*
|
|
288
308
|
* Single source of truth: `gsd-core/bin/gsd-tools.cjs`'s `review-lane plan`/`invoke` and
|
|
289
|
-
* `src/reviewer-step-dispatch.cts`'s `dispatchReviewerLanes` both resolve a lane's
|
|
309
|
+
* `src/reviewer-step-dispatch.cts`'s `dispatchReviewerLanes` both resolve a lane's cap through
|
|
290
310
|
* this function rather than each carrying their own copy (#4209 R3 — two verbatim copies drift).
|
|
291
311
|
*/
|
|
292
|
-
function
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const
|
|
312
|
+
function resolveLaneCap(lane, configGet) {
|
|
313
|
+
// A spawn lane whose prompt channel is `none` (coderabbit) is fed no prompt, so there is nothing
|
|
314
|
+
// to cap: no key — explicit, global or derived — may ever refuse it (#4559, design row 18).
|
|
315
|
+
const laneRaw = lane;
|
|
316
|
+
if (laneRaw?.transport === 'spawn' && laneRaw.invoke?.promptChannel === 'none') {
|
|
317
|
+
return { cap: null, source: 'none', contextWindowTokens: null };
|
|
318
|
+
}
|
|
296
319
|
const isNum = (v) => typeof v === 'number' && Number.isFinite(v);
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
const
|
|
300
|
-
|
|
320
|
+
const isPositive = (v) => isNum(v) && v > 0;
|
|
321
|
+
const raw = lane;
|
|
322
|
+
const budgetKey = typeof raw?.promptBudgetKey === 'string' && raw.promptBudgetKey ? raw.promptBudgetKey : null;
|
|
323
|
+
if (budgetKey) {
|
|
324
|
+
const per = configGet(budgetKey);
|
|
325
|
+
if (isNum(per) && per !== -1)
|
|
326
|
+
return { cap: per, source: 'lane', contextWindowTokens: null };
|
|
327
|
+
const global = configGet('review.max_prompt_tokens');
|
|
328
|
+
if (isNum(global))
|
|
329
|
+
return { cap: global, source: 'global', contextWindowTokens: null };
|
|
330
|
+
}
|
|
331
|
+
const windowKey = typeof raw?.contextWindowConfigKey === 'string' && raw.contextWindowConfigKey ? raw.contextWindowConfigKey : null;
|
|
332
|
+
const override = windowKey ? configGet(windowKey) : undefined;
|
|
333
|
+
if (override === 0)
|
|
334
|
+
return { cap: null, source: 'none', contextWindowTokens: null };
|
|
335
|
+
const windowTokens = isPositive(override)
|
|
336
|
+
? override
|
|
337
|
+
: isPositive(raw?.contextWindowTokens)
|
|
338
|
+
? raw.contextWindowTokens
|
|
339
|
+
: null;
|
|
340
|
+
if (windowTokens === null)
|
|
341
|
+
return { cap: null, source: 'none', contextWindowTokens: null };
|
|
342
|
+
return {
|
|
343
|
+
cap: Math.floor(windowTokens * exports.CONTEXT_WINDOW_HEADROOM),
|
|
344
|
+
source: 'context-window',
|
|
345
|
+
contextWindowTokens: windowTokens,
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* The ONE refuse-or-run decision (#4559), shared by `review-lane invoke` and `dispatchReviewerLanes`.
|
|
350
|
+
* Refuses only when a positive cap is STRICTLY exceeded: a prompt exactly at the cap runs, and a
|
|
351
|
+
* cap of `0` or `null` never refuses. `detail` names the estimate, the cap, where the cap came from
|
|
352
|
+
* and the key to change, so the refusal is actionable rather than a bare "too big".
|
|
353
|
+
*/
|
|
354
|
+
function checkPromptAgainstCap(estimatedTokens, capInfo, lane) {
|
|
355
|
+
const { cap, source, contextWindowTokens } = capInfo;
|
|
356
|
+
if (cap === null || !(cap > 0) || !(estimatedTokens > cap))
|
|
357
|
+
return { ok: true };
|
|
358
|
+
const raw = lane;
|
|
359
|
+
const slug = typeof raw?.slug === 'string' ? raw.slug : '';
|
|
360
|
+
const budgetKey = typeof raw?.promptBudgetKey === 'string' && raw.promptBudgetKey ? raw.promptBudgetKey : null;
|
|
361
|
+
const windowKey = typeof raw?.contextWindowConfigKey === 'string' && raw.contextWindowConfigKey ? raw.contextWindowConfigKey : null;
|
|
362
|
+
// Remedy keys are the lane's DECLARED keys (an overlay lane's differ from the slug convention).
|
|
363
|
+
const remedy = source === 'lane'
|
|
364
|
+
? `raise ${budgetKey ?? 'the lane prompt cap'} or set it to 0 to remove the cap`
|
|
365
|
+
: source === 'global'
|
|
366
|
+
? `raise review.max_prompt_tokens${budgetKey ? ` or set ${budgetKey}` : ''}`
|
|
367
|
+
: windowKey
|
|
368
|
+
? `raise ${windowKey} if this lane's model has a larger window, or set it to 0 to remove the cap`
|
|
369
|
+
: budgetKey
|
|
370
|
+
? `this lane's context window is fixed by its declaration; set review.max_prompt_tokens or ${budgetKey} to override`
|
|
371
|
+
: `this lane's cap comes from its declared contextWindowTokens and the lane declares no key to override it`;
|
|
372
|
+
const windowNote = contextWindowTokens !== null ? `, ${contextWindowTokens}-token context window` : '';
|
|
373
|
+
return {
|
|
374
|
+
ok: false,
|
|
375
|
+
reason: exports.LANE_UNAVAILABLE.PROMPT_EXCEEDS_CONTEXT,
|
|
376
|
+
detail: `estimated ${estimatedTokens} tokens exceeds the ${cap}-token cap for lane '${slug}' ` +
|
|
377
|
+
`(source: ${source}${windowNote}); ${remedy}`,
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Resolve the lane's cap and decide refuse-or-run in one pure step (#4559): `null` = run, otherwise
|
|
382
|
+
* the structured refusal. `review-lane invoke` and `dispatchReviewerLanes` both call this, so the
|
|
383
|
+
* two surfaces cannot disagree about whether, or how, a lane is refused.
|
|
384
|
+
*/
|
|
385
|
+
function refuseIfOverCap(input) {
|
|
386
|
+
const capInfo = resolveLaneCap(input.lane, input.configGet);
|
|
387
|
+
const verdict = checkPromptAgainstCap(input.estimatedTokens, capInfo, input.lane);
|
|
388
|
+
if (verdict.ok)
|
|
389
|
+
return null;
|
|
390
|
+
return {
|
|
391
|
+
ok: false,
|
|
392
|
+
reason: verdict.reason,
|
|
393
|
+
detail: verdict.detail,
|
|
394
|
+
refusal: {
|
|
395
|
+
estimatedTokens: input.estimatedTokens,
|
|
396
|
+
cap: capInfo.cap,
|
|
397
|
+
capSource: capInfo.source,
|
|
398
|
+
contextWindowTokens: capInfo.contextWindowTokens,
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* The text written to a refused lane's review file (#4559). The marker
|
|
404
|
+
* `review did not run: prompt exceeds` is stable: `review.md`'s skip gate and coverage loop key on it.
|
|
405
|
+
*/
|
|
406
|
+
function renderPromptRefusalStub(slug, detail) {
|
|
407
|
+
return `${slug} review did not run: prompt exceeds this lane's context cap (${detail})\n`;
|
|
301
408
|
}
|
|
302
409
|
/* ------------------------------------------------------------------ *
|
|
303
410
|
* Resolution
|
|
@@ -32,6 +32,7 @@ exports.parseModelBanner = parseModelBanner;
|
|
|
32
32
|
exports.parseTranscriptModel = parseTranscriptModel;
|
|
33
33
|
exports.checkEgressHost = checkEgressHost;
|
|
34
34
|
exports.probeLane = probeLane;
|
|
35
|
+
exports.probeHttpLanes = probeHttpLanes;
|
|
35
36
|
exports.writeReviewOrStub = writeReviewOrStub;
|
|
36
37
|
exports.emptyOutputDiagnosis = emptyOutputDiagnosis;
|
|
37
38
|
exports.handleOpencodeOutput = handleOpencodeOutput;
|
|
@@ -318,14 +319,18 @@ async function probeLane(plan, deps) {
|
|
|
318
319
|
// Only a STRING config value names a host. `String(unknown)` would turn an object into the
|
|
319
320
|
// literal '[object Object]' and probe that as a URL — a nonsense destination reported as
|
|
320
321
|
// "unreachable" rather than as the misconfiguration it is.
|
|
322
|
+
// For openai-http, `plan.host` is already resolved by `resolveLanePlan` (config → default,
|
|
323
|
+
// unset sentinels like "null" handled) — probe the destination the run would use.
|
|
321
324
|
const configured = deps.configGet(probe.hostConfigKey);
|
|
322
|
-
const base = (0, review_lane_invocation_cjs_1.normalizeHost)((typeof configured === 'string' ? configured : '')
|
|
323
|
-
(plan.transport === 'openai-http' ? plan.host : ''));
|
|
325
|
+
const base = (0, review_lane_invocation_cjs_1.normalizeHost)((plan.transport === 'openai-http' ? plan.host : '') || (typeof configured === 'string' ? configured : ''));
|
|
324
326
|
if (!base) {
|
|
325
327
|
return { available: false, reason: review_lane_invocation_cjs_1.LANE_UNAVAILABLE.HOST_UNREACHABLE, detail: 'no host resolved' };
|
|
326
328
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
+
// D7: reachable ⇒ available. Any HTTP answer (401 behind an auth proxy, 404, 3xx) proves a
|
|
330
|
+
// server is there; only a transport failure (status 0) does not. Redirects are not followed:
|
|
331
|
+
// a probe must not issue a request to a host the descriptor never named.
|
|
332
|
+
const r = await deps.httpJson(`${base}${probe.path}`, { method: 'GET', timeoutMs: probe.timeoutMs, probe: true });
|
|
333
|
+
return r.status > 0
|
|
329
334
|
? { available: true }
|
|
330
335
|
: {
|
|
331
336
|
available: false,
|
|
@@ -341,6 +346,25 @@ async function probeLane(plan, deps) {
|
|
|
341
346
|
};
|
|
342
347
|
}
|
|
343
348
|
}
|
|
349
|
+
/**
|
|
350
|
+
* `<slug>:available|missing` rows for the openai-http lanes in `lanes` (all, or those in `selected`).
|
|
351
|
+
* Prerequisite binaries are not folded in: the caller reports `jq` separately. An unresolvable lane
|
|
352
|
+
* reads `missing` and its reason is returned in `warnings` rather than swallowed.
|
|
353
|
+
*/
|
|
354
|
+
async function probeHttpLanes(lanes, selected, resolve, deps) {
|
|
355
|
+
// Probes run concurrently (each has its own timeout); Promise.all keeps descriptor order, and
|
|
356
|
+
// warnings are collected from the results afterwards so their order never depends on resolve timing.
|
|
357
|
+
const results = await Promise.all(lanes
|
|
358
|
+
.filter((l) => l.transport === 'openai-http' && (selected.length === 0 || selected.includes(l.slug)))
|
|
359
|
+
.map(async (lane) => {
|
|
360
|
+
const r = resolve(lane);
|
|
361
|
+
const up = r.ok && (await probeLane({ ...r.plan, requiresBinaries: [] }, deps)).available;
|
|
362
|
+
return { row: `${lane.slug}:${up ? 'available' : 'missing'}`, warning: r.ok ? null : `${lane.slug}: ${r.detail}` };
|
|
363
|
+
}));
|
|
364
|
+
const rows = results.map((x) => x.row);
|
|
365
|
+
const warnings = results.flatMap((x) => (x.warning === null ? [] : [x.warning]));
|
|
366
|
+
return { rows, warnings };
|
|
367
|
+
}
|
|
344
368
|
/* ------------------------------------------------------------------ *
|
|
345
369
|
* Empty-output policy (#2494 / #2605 / #2794)
|
|
346
370
|
* ------------------------------------------------------------------ */
|
|
@@ -940,6 +964,11 @@ async function runOpenAiCompatible(plan, promptText, deps) {
|
|
|
940
964
|
let model = plan.model;
|
|
941
965
|
if (!model && plan.modelsUrl) {
|
|
942
966
|
const listed = await deps.httpJson(plan.modelsUrl, { method: 'GET', timeoutMs: 2_000 });
|
|
967
|
+
// A redirect is a lane failure, not "discovery found nothing" (#5433): the host answered with
|
|
968
|
+
// somewhere else to go, so the configured URL is wrong and the completions request would be too.
|
|
969
|
+
if (listed.status >= 300 && listed.status < 400 && listed.error) {
|
|
970
|
+
return { review: '', rawBody: listed.error, model: recordedModel(plan.fallbackModel, exports.MODEL_SOURCE.REQUESTED) };
|
|
971
|
+
}
|
|
943
972
|
if (listed.ok) {
|
|
944
973
|
try {
|
|
945
974
|
const parsed = JSON.parse(listed.body);
|
|
@@ -29,8 +29,9 @@
|
|
|
29
29
|
*
|
|
30
30
|
* The bounded source-review prompt built here is METADATA ONLY — repository root, canonical
|
|
31
31
|
* file paths, review depth, base SHA, and four fixed prohibitions. It never embeds file
|
|
32
|
-
* contents. If the assembled prompt exceeds a lane's resolved
|
|
33
|
-
*
|
|
32
|
+
* contents. If the assembled prompt exceeds a lane's resolved prompt cap (an explicit cap or the
|
|
33
|
+
* default derived from its context window, #4559), that lane's dispatch hard-fails with reason
|
|
34
|
+
* `prompt_exceeds_context` before `invoke` runs for it — no silent truncation of the file list.
|
|
34
35
|
*/
|
|
35
36
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
37
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -125,9 +126,8 @@ function validatePaths(repoRoot, paths) {
|
|
|
125
126
|
}
|
|
126
127
|
return { ok: true };
|
|
127
128
|
}
|
|
128
|
-
// `
|
|
129
|
-
//
|
|
130
|
-
// `!== 0`. See the call site below.
|
|
129
|
+
// `resolveLaneCap` (review-lane-invocation.cjs) resolves the cap; `null` and a resolved `0` both
|
|
130
|
+
// mean unbounded (#2797), and `checkPromptAgainstCap` owns that test. See the call site below.
|
|
131
131
|
/**
|
|
132
132
|
* One-line depth definition for an external reviewer lane, condensed from `<depth_levels>` in
|
|
133
133
|
* `agents/gsd-code-reviewer.md` (#4209 review: a bare `quick`/`standard`/`deep` label means
|
|
@@ -296,13 +296,15 @@ async function dispatchReviewerLanes(input, deps) {
|
|
|
296
296
|
anyFailed = true;
|
|
297
297
|
continue;
|
|
298
298
|
}
|
|
299
|
-
|
|
300
|
-
|
|
299
|
+
// #4559: refuse-not-trim, through the same check `review-lane invoke` uses.
|
|
300
|
+
const refused = (0, review_lane_invocation_cjs_1.refuseIfOverCap)({ lane, estimatedTokens, configGet });
|
|
301
|
+
if (refused) {
|
|
301
302
|
results.push({
|
|
302
303
|
slug,
|
|
303
304
|
ok: false,
|
|
304
|
-
reason:
|
|
305
|
-
detail:
|
|
305
|
+
reason: refused.reason,
|
|
306
|
+
detail: refused.detail,
|
|
307
|
+
refusal: refused.refusal,
|
|
306
308
|
});
|
|
307
309
|
anyFailed = true;
|
|
308
310
|
continue;
|