@opengsd/gsd-core 1.17.0 → 1.19.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-advisor-researcher.compact.md +1 -1
- package/agents/gsd-advisor-researcher.md +1 -1
- package/agents/gsd-assumptions-analyzer.compact.md +1 -1
- package/agents/gsd-assumptions-analyzer.md +1 -1
- package/agents/gsd-code-fixer.compact.md +3 -3
- package/agents/gsd-code-fixer.md +5 -4
- package/agents/gsd-code-reviewer.compact.md +1 -1
- package/agents/gsd-code-reviewer.md +1 -1
- package/agents/gsd-codebase-mapper.compact.md +1 -1
- package/agents/gsd-codebase-mapper.md +1 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-doc-verifier.compact.md +4 -4
- package/agents/gsd-doc-verifier.md +4 -3
- package/agents/gsd-doc-writer.compact.md +23 -5
- package/agents/gsd-doc-writer.md +19 -6
- package/agents/gsd-eval-auditor.compact.md +1 -1
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +7 -3
- package/agents/gsd-integration-checker.compact.md +1 -1
- package/agents/gsd-integration-checker.md +1 -1
- package/agents/gsd-nyquist-auditor.compact.md +1 -1
- package/agents/gsd-nyquist-auditor.md +1 -1
- package/agents/gsd-phase-researcher.md +1 -1
- package/agents/gsd-plan-checker.md +2 -1
- package/agents/gsd-planner.md +5 -4
- package/agents/gsd-project-researcher.compact.md +1 -1
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.compact.md +5 -5
- package/agents/gsd-research-synthesizer.md +5 -5
- package/agents/gsd-roadmapper.compact.md +1 -1
- package/agents/gsd-roadmapper.md +1 -1
- package/agents/gsd-security-auditor.compact.md +1 -1
- package/agents/gsd-security-auditor.md +1 -1
- package/agents/gsd-ui-auditor.compact.md +1 -1
- package/agents/gsd-ui-auditor.md +1 -1
- package/agents/gsd-ui-checker.compact.md +1 -1
- package/agents/gsd-ui-checker.md +1 -1
- package/agents/gsd-ui-researcher.compact.md +13 -1
- package/agents/gsd-ui-researcher.md +28 -1
- package/agents/gsd-verifier.md +2 -2
- package/bin/install.js +460 -105
- package/commands/gsd/code-review.md +8 -0
- package/commands/gsd/pause-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +124 -18
- 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-ledger.cjs +25 -0
- package/gsd-core/bin/lib/capability-lock.cjs +41 -8
- package/gsd-core/bin/lib/capability-registry.cjs +162 -74
- package/gsd-core/bin/lib/capability-source.cjs +3 -1
- package/gsd-core/bin/lib/capability-state.cjs +20 -11
- package/gsd-core/bin/lib/capability-validator.cjs +23 -4
- package/gsd-core/bin/lib/commands.cjs +5 -1
- 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 +34 -0
- package/gsd-core/bin/lib/decision-coverage-support.cjs +93 -0
- package/gsd-core/bin/lib/gate-context-drift.cjs +8 -3
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +21 -1
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +19 -1
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +134 -13
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +23 -3
- package/gsd-core/bin/lib/gate-predicate.cjs +8 -12
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +114 -18
- package/gsd-core/bin/lib/gate-ui-safety.cjs +23 -5
- package/gsd-core/bin/lib/git-info-exclude.cjs +57 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +18 -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 +76 -5
- package/gsd-core/bin/lib/install-effort-resolver.cjs +2 -2
- package/gsd-core/bin/lib/install-engine.cjs +246 -32
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +4 -3
- package/gsd-core/bin/lib/install-profiles.cjs +14 -7
- package/gsd-core/bin/lib/installer-migration-report.cjs +2 -0
- package/gsd-core/bin/lib/markdown-line-diff.cjs +147 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +113 -0
- 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 +43 -1
- 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-id.cjs +21 -4
- package/gsd-core/bin/lib/phase-lifecycle.cjs +37 -4
- package/gsd-core/bin/lib/phase.cjs +235 -37
- package/gsd-core/bin/lib/planning-snapshot.cjs +3 -1
- package/gsd-core/bin/lib/planning-workspace.cjs +18 -0
- package/gsd-core/bin/lib/pristine-baseline.cjs +11 -3
- package/gsd-core/bin/lib/read-only-git-env.cjs +58 -0
- package/gsd-core/bin/lib/report-parser.cjs +57 -1
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +35 -2
- package/gsd-core/bin/lib/review-lane-invocation.cjs +40 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +33 -4
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +20 -1
- package/gsd-core/bin/lib/roadmap-parser.cjs +12 -0
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +39 -2
- package/gsd-core/bin/lib/roadmap.cjs +89 -30
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +428 -16
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +8 -4
- package/gsd-core/bin/lib/runtime-homes.cjs +18 -0
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +60 -16
- package/gsd-core/bin/lib/shell-command-projection.cjs +123 -16
- package/gsd-core/bin/lib/smart-entry.cjs +37 -16
- package/gsd-core/bin/lib/state-contract.cjs +29 -9
- package/gsd-core/bin/lib/state-document.cjs +47 -5
- package/gsd-core/bin/lib/state-transition.cjs +150 -34
- package/gsd-core/bin/lib/state.cjs +140 -88
- package/gsd-core/bin/lib/surface.cjs +9 -0
- package/gsd-core/bin/lib/task-command-router.cjs +7 -28
- package/gsd-core/bin/lib/task-content-resolution.cjs +46 -1
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +5 -0
- package/gsd-core/bin/lib/tdd-test-files.cjs +42 -0
- package/gsd-core/bin/lib/verification.cjs +96 -9
- package/gsd-core/bin/lib/verify.cjs +38 -1
- 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/references/agent-contracts.md +1 -1
- package/gsd-core/references/agent-skills-bootstrap.md +26 -7
- package/gsd-core/references/git-integration.md +14 -3
- package/gsd-core/references/loop-hook-dispatch.md +13 -6
- package/gsd-core/references/planner-reversibility.md +18 -4
- package/gsd-core/references/planner-verify-command-grounding.md +18 -0
- package/gsd-core/references/planning-config.md +2 -0
- package/gsd-core/references/tdd.md +5 -4
- package/gsd-core/references/verifier-phase-gates.md +8 -1
- 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/add-backlog.md +10 -2
- package/gsd-core/workflows/add-phase.md +5 -1
- package/gsd-core/workflows/add-tests.md +5 -1
- package/gsd-core/workflows/add-todo.md +5 -1
- package/gsd-core/workflows/ai-integration-phase.md +5 -1
- package/gsd-core/workflows/audit-fix.md +2 -1
- package/gsd-core/workflows/audit-milestone.md +21 -9
- package/gsd-core/workflows/autonomous/templates/minimal-context.md +41 -0
- package/gsd-core/workflows/autonomous.md +52 -64
- package/gsd-core/workflows/check-todos.md +5 -1
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +10 -1
- package/gsd-core/workflows/code-review-fix.md +5 -1
- package/gsd-core/workflows/code-review.md +66 -8
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +5 -1
- 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 +64 -157
- package/gsd-core/workflows/debug.md +5 -1
- package/gsd-core/workflows/diagnose-issues.md +34 -6
- package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -1
- package/gsd-core/workflows/discuss-phase/modes/power.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +44 -5
- package/gsd-core/workflows/discuss-phase-power.md +19 -2
- package/gsd-core/workflows/discuss-phase.md +11 -11
- package/gsd-core/workflows/docs-update/detail/elaboration.md +7 -6
- package/gsd-core/workflows/docs-update.md +27 -5
- package/gsd-core/workflows/edit-phase.md +5 -1
- package/gsd-core/workflows/eval-review.md +11 -3
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +5 -1
- 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 +19 -8
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +21 -3
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +18 -1
- package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +7 -3
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +11 -2
- package/gsd-core/workflows/execute-phase.md +46 -11
- package/gsd-core/workflows/execute-plan.md +8 -4
- package/gsd-core/workflows/extract-learnings.md +6 -2
- package/gsd-core/workflows/forensics.md +5 -1
- package/gsd-core/workflows/health.md +2 -1
- package/gsd-core/workflows/import.md +6 -2
- package/gsd-core/workflows/insert-phase.md +5 -1
- package/gsd-core/workflows/manager.md +10 -2
- package/gsd-core/workflows/map-codebase.md +5 -1
- package/gsd-core/workflows/milestone-summary.md +10 -2
- package/gsd-core/workflows/new-milestone.md +13 -5
- package/gsd-core/workflows/new-project.md +9 -5
- package/gsd-core/workflows/next.md +8 -4
- package/gsd-core/workflows/pause-work.md +3 -3
- package/gsd-core/workflows/plan-phase/steps/auto-advance-check.md +70 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +7 -3
- package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +6 -2
- package/gsd-core/workflows/plan-phase.md +54 -86
- package/gsd-core/workflows/plan-review-convergence.md +17 -5
- package/gsd-core/workflows/plant-seed.md +8 -4
- package/gsd-core/workflows/progress.md +6 -2
- 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-batch.md +5 -1
- package/gsd-core/workflows/quick.md +23 -8
- package/gsd-core/workflows/remove-phase.md +5 -1
- package/gsd-core/workflows/resume-project.md +5 -1
- package/gsd-core/workflows/review.md +22 -15
- package/gsd-core/workflows/scan.md +5 -1
- package/gsd-core/workflows/section-manifest.json +5 -0
- package/gsd-core/workflows/secure-phase.md +6 -2
- package/gsd-core/workflows/settings.md +4 -3
- package/gsd-core/workflows/ship.md +16 -14
- package/gsd-core/workflows/spec-phase.md +3 -6
- package/gsd-core/workflows/thread.md +10 -2
- package/gsd-core/workflows/transition.md +5 -1
- package/gsd-core/workflows/ui-phase.md +5 -1
- package/gsd-core/workflows/ui-review.md +6 -2
- package/gsd-core/workflows/ultraplan-phase.md +5 -1
- package/gsd-core/workflows/update.md +5 -1
- package/gsd-core/workflows/validate-phase.md +6 -2
- package/gsd-core/workflows/verify-work/detail/elaboration.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -1
- package/gsd-core/workflows/verify-work.md +15 -6
- package/hooks/dist/gsd-agent-isolation-guard.js +14 -2
- package/hooks/dist/gsd-cursor-subagent-start.js +8 -3
- package/hooks/dist/gsd-path-export.js +95 -0
- package/hooks/dist/gsd-secret-read-guard.js +244 -53
- package/hooks/dist/gsd-statusline.js +35 -2
- package/hooks/dist/gsd-validate-commit.sh +27 -5
- package/hooks/dist/gsd-windsurf-pre-write.js +28 -1
- package/hooks/dist/gsd-workflow-guard.js +1 -1
- package/hooks/dist/gsd-worktree-path-guard.js +28 -1
- 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 +14 -2
- package/hooks/gsd-cursor-subagent-start.js +8 -3
- package/hooks/gsd-path-export.js +95 -0
- package/hooks/gsd-secret-read-guard.js +244 -53
- package/hooks/gsd-statusline.js +35 -2
- package/hooks/gsd-validate-commit.sh +27 -5
- package/hooks/gsd-windsurf-pre-write.js +28 -1
- package/hooks/gsd-workflow-guard.js +1 -1
- package/hooks/gsd-worktree-path-guard.js +28 -1
- package/hooks/hooks.json +1 -0
- package/hooks/lib/isolation-sentinel.js +44 -0
- package/hooks/managed-hooks-registry.cjs +1 -0
- package/package.json +13 -6
- 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 +769 -0
- package/pi/package-agents/gsd-code-reviewer.md +402 -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 +894 -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 +51 -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/audit-workflow-script-paths.cjs +1 -1
- package/scripts/build-hooks.js +4 -0
- package/scripts/command-contract-helpers.cjs +1 -1
- package/scripts/diagnose-windows-spawn-watcher.cjs +317 -0
- package/scripts/docs-guard-registry.cjs +22 -7
- package/scripts/gen-health-docs.cjs +13 -1
- package/scripts/gen-pi-package-skills.cjs +217 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +19 -0
- package/scripts/lib/platform-conformance-tier.generated.cjs +41 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +3 -3
- package/scripts/lint-phase-arg-assignment.cjs +2 -2
- package/scripts/lint-retired-runtime-name.cjs +5 -0
- package/scripts/lint-workflow-shellcheck-baseline.json +16 -16
- package/scripts/npm-audit-baseline.cjs +41 -7
- package/scripts/release-tarball-smoke.cjs +1 -0
- 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/skills/gsd-code-review/SKILL.md +8 -0
- package/skills/gsd-pause-work/SKILL.md +1 -1
- package/vscode/package.json +1 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* read-only-git-env.cts — the single owner of the read-only git env block
|
|
4
|
+
* (#5048). CONTEXT.md / OS Shell Projection seam.
|
|
5
|
+
*
|
|
6
|
+
* By default `git status` refreshes the index and takes an *optional*
|
|
7
|
+
* `.git/index.lock` to write the refreshed copy back. That is a write the caller
|
|
8
|
+
* never asked for, and it turns a pure read into a contender for the lock a
|
|
9
|
+
* real `git add` / `git commit` needs — so a read-only statusline render can
|
|
10
|
+
* make a concurrent commit fail with
|
|
11
|
+
* `Unable to create '.git/index.lock': File exists`. `GIT_OPTIONAL_LOCKS=0`
|
|
12
|
+
* tells git to skip only those *optional* index operations. Nothing a read
|
|
13
|
+
* needs is lost: `git status` reads the index, it just doesn't need to rewrite
|
|
14
|
+
* it.
|
|
15
|
+
*
|
|
16
|
+
* ## Why this module exists
|
|
17
|
+
*
|
|
18
|
+
* The block used to be hand-written at every seam that spawns git for a read.
|
|
19
|
+
* Six copies of `{ ...process.env, GIT_OPTIONAL_LOCKS: '0' }` is six places to
|
|
20
|
+
* forget when a seam is added, and a probe that checks each seam for the literal
|
|
21
|
+
* value passes even when a seam stopped consulting the owner. One owner makes
|
|
22
|
+
* the drift structural instead: the parity test patches THIS function to a
|
|
23
|
+
* sentinel and asserts every seam's spawn carries the sentinel, so a seam that
|
|
24
|
+
* hand-writes the variable again fails red rather than passing quietly.
|
|
25
|
+
* (tests/git-optional-locks-parity.test.cjs, "#5048 every seam reads the shared
|
|
26
|
+
* owner".)
|
|
27
|
+
*
|
|
28
|
+
* ## Why the hook scripts require the built artifact
|
|
29
|
+
*
|
|
30
|
+
* `hooks/*.js` are staged as standalone files at install time, so they reach
|
|
31
|
+
* compiled `src/` modules through `../gsd-core/bin/lib/*.cjs` rather than a
|
|
32
|
+
* sibling hooks/-tree file — the same rule hooks/lib/git-cmd.js follows for
|
|
33
|
+
* token-scanner. They call `readOnlyGitEnv()` per spawn rather than snapshotting
|
|
34
|
+
* the result at module load, so a later `process.env` mutation is visible and the
|
|
35
|
+
* two behave identically.
|
|
36
|
+
*/
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.readOnlyGitEnv = readOnlyGitEnv;
|
|
39
|
+
/**
|
|
40
|
+
* Build the env for a read-only git spawn.
|
|
41
|
+
*
|
|
42
|
+
* @param base Environment to spread, `process.env` by default. Callers that
|
|
43
|
+
* layer extra git variables on top (GIT_TERMINAL_PROMPT, a caller's own
|
|
44
|
+
* overrides) pass them in `base`; callers that must let a caller-supplied
|
|
45
|
+
* override win spread the result and apply their own keys afterwards.
|
|
46
|
+
* @returns A fresh object each call — never the cached `process.env`.
|
|
47
|
+
*/
|
|
48
|
+
function readOnlyGitEnv(base = process.env) {
|
|
49
|
+
const env = {};
|
|
50
|
+
for (const [key, value] of Object.entries(base)) {
|
|
51
|
+
// process.env carries undefined-valued keys on some platforms; spawn()
|
|
52
|
+
// rejects a non-string value rather than ignoring it.
|
|
53
|
+
if (value !== undefined)
|
|
54
|
+
env[key] = value;
|
|
55
|
+
}
|
|
56
|
+
env.GIT_OPTIONAL_LOCKS = '0';
|
|
57
|
+
return env;
|
|
58
|
+
}
|
|
@@ -6,7 +6,7 @@ exports.parseTestReport = parseTestReport;
|
|
|
6
6
|
const tap_parser_cjs_1 = require("./vendor/tap-parser.cjs");
|
|
7
7
|
const saxes_cjs_1 = require("./vendor/saxes.cjs");
|
|
8
8
|
exports.ReportFormat = {
|
|
9
|
-
Tap: 'tap', Junit: 'junit', SwiftTesting: 'swift-testing', Unittest: 'unittest', Unknown: 'unknown',
|
|
9
|
+
Tap: 'tap', Junit: 'junit', SwiftTesting: 'swift-testing', Unittest: 'unittest', GoTest: 'go-test', Unknown: 'unknown',
|
|
10
10
|
};
|
|
11
11
|
exports.TestStatus = { Passed: 'passed', Failed: 'failed', Skipped: 'skipped', Todo: 'todo' };
|
|
12
12
|
function parseTap(output) {
|
|
@@ -247,7 +247,63 @@ function parseUnittest(output) {
|
|
|
247
247
|
report.valid = report.issues.length === 0;
|
|
248
248
|
return report;
|
|
249
249
|
}
|
|
250
|
+
/**
|
|
251
|
+
* `go test` text output (#5106). Plain console text, so the shape is matched by line:
|
|
252
|
+
* --- FAIL: TestName (0.00s) one per failed test (every test with -v; subtests indented)
|
|
253
|
+
* FAIL\texample.com/pkg\t0.004s one package summary per package, after that package's tests
|
|
254
|
+
* FAIL\texample.com/pkg [build failed] the package did not compile — nothing asserted anything
|
|
255
|
+
* A test's name carries no package, so each test is also known as `<package>.<name>`, attributed to
|
|
256
|
+
* the next package summary line. The same name failing in two packages is ambiguous until qualified.
|
|
257
|
+
* `go test -json` is not text and stays unsupported.
|
|
258
|
+
*/
|
|
259
|
+
const GO_TEST_RESULT = /^[ \t]*-{3} (PASS|FAIL|SKIP): (\S+) \(\d+(?:\.\d+)?s\)$/; // -{3}: not a literal fence, see frontmatter-fence-drift
|
|
260
|
+
const GO_PACKAGE_LINE = /^(ok|FAIL|\?)[ \t]+(\S+)[ \t]+(?:\d+(?:\.\d+)?s\b|\(cached\)|\[([a-z ]+)\])/;
|
|
261
|
+
function isGoTestOutput(output) {
|
|
262
|
+
if (/^TAP version \d+/.test(output.trimStart()))
|
|
263
|
+
return false;
|
|
264
|
+
return output.split(/\r?\n/).some((line) => GO_TEST_RESULT.test(line) || GO_PACKAGE_LINE.test(line));
|
|
265
|
+
}
|
|
266
|
+
function parseGoTest(output) {
|
|
267
|
+
const report = { format: exports.ReportFormat.GoTest, valid: true, tests: [], issues: [] };
|
|
268
|
+
let segment = [];
|
|
269
|
+
let packages = 0;
|
|
270
|
+
for (const line of output.split(/\r?\n/)) {
|
|
271
|
+
const result = GO_TEST_RESULT.exec(line);
|
|
272
|
+
if (result) {
|
|
273
|
+
const name = result[2];
|
|
274
|
+
const status = result[1] === 'FAIL' ? exports.TestStatus.Failed : result[1] === 'SKIP' ? exports.TestStatus.Skipped : exports.TestStatus.Passed;
|
|
275
|
+
if (!segment.some((test) => test.name === name && test.status === status)) {
|
|
276
|
+
segment.push({ name, identities: [name], group: null, groupIdentities: [], status });
|
|
277
|
+
}
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
const pkg = GO_PACKAGE_LINE.exec(line);
|
|
281
|
+
if (!pkg)
|
|
282
|
+
continue;
|
|
283
|
+
packages++;
|
|
284
|
+
const [, outcome, importPath, bracket] = pkg;
|
|
285
|
+
if (outcome === 'FAIL' && (bracket === 'build failed' || bracket === 'setup failed')) {
|
|
286
|
+
report.buildFailed = true;
|
|
287
|
+
report.issues.push(`go test package ${importPath} ${bracket}`);
|
|
288
|
+
}
|
|
289
|
+
else if (outcome === 'ok' && segment.some((test) => test.status === exports.TestStatus.Failed)) {
|
|
290
|
+
report.issues.push(`go test package ${importPath} is ok but its output reports a failed test`);
|
|
291
|
+
}
|
|
292
|
+
for (const test of segment)
|
|
293
|
+
test.identities.push(`${importPath}.${test.name}`);
|
|
294
|
+
report.tests.push(...segment);
|
|
295
|
+
segment = [];
|
|
296
|
+
}
|
|
297
|
+
if (packages === 0)
|
|
298
|
+
report.issues.push('Missing go test package summary');
|
|
299
|
+
if (segment.length > 0)
|
|
300
|
+
report.issues.push('go test results without a following package summary');
|
|
301
|
+
report.valid = report.issues.length === 0;
|
|
302
|
+
return report;
|
|
303
|
+
}
|
|
250
304
|
const adapters = [
|
|
305
|
+
// Before TAP: a run whose first package is fine begins `ok <TAB>pkg`, which the TAP matcher reads as a point.
|
|
306
|
+
{ matches: isGoTestOutput, parse: parseGoTest },
|
|
251
307
|
{ matches: (output) => /^(?:TAP version \d+|(?:not )?ok\b|1\.\.\d+|#)/.test(output.trimStart()), parse: parseTap },
|
|
252
308
|
{ matches: (output) => output.trimStart().startsWith('<'), parse: parseJunit },
|
|
253
309
|
{ matches: (output) => new RegExp(SWIFT_AGGREGATE.source, 'm').test(output), parse: parseSwiftTesting },
|
|
@@ -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
|
*
|
|
@@ -576,6 +577,7 @@ exports.PARITY_VIOLATION = Object.freeze({
|
|
|
576
577
|
REGISTRY_LANE_UNDECLARED: 'registry_lane_undeclared',
|
|
577
578
|
DESCRIPTOR_LANE_NOT_IN_REGISTRY: 'descriptor_lane_not_in_registry',
|
|
578
579
|
BESPOKE_LEG_PRESENT: 'bespoke_leg_present',
|
|
580
|
+
AVAILABILITY_FALLBACK_MISMATCH: 'availability_fallback_mismatch',
|
|
579
581
|
DUPLICATE_SLUG: 'duplicate_slug',
|
|
580
582
|
DUPLICATE_FLAG: 'duplicate_flag',
|
|
581
583
|
DUPLICATE_SECTION: 'duplicate_section',
|
|
@@ -607,6 +609,10 @@ const LEG_MARKER_RE = /<!--\s*reviewer-lane:\s*([a-z0-9_-]+)\s*-->/g;
|
|
|
607
609
|
* design principle of this module.
|
|
608
610
|
*/
|
|
609
611
|
exports.LANE_SLUG_RE = /^[a-z0-9][a-z0-9_-]*$/;
|
|
612
|
+
/** The workflow's availability call: `gsd_run review-lane availability ...` at command position. */
|
|
613
|
+
const AVAILABILITY_CALL_RE = /^\s*gsd_run review-lane availability(?:\s|$)/;
|
|
614
|
+
/** One `<slug>:missing` row in the printf fallback; slug is LANE_SLUG_RE's grammar capped at 32 chars. */
|
|
615
|
+
const AVAILABILITY_FALLBACK_ROW_RE = /(?:'|\\n)([a-z0-9][a-z0-9_-]{0,31}):missing/g;
|
|
610
616
|
/** Bounds of the step a bespoke leg marker could appear inside. */
|
|
611
617
|
const INVOKE_STEP_RE = /<step name="invoke_reviewers">([\s\S]*?)<\/step>/;
|
|
612
618
|
function sliceStep(workflowText, re) {
|
|
@@ -627,8 +633,10 @@ function countOccurrences(haystack, re) {
|
|
|
627
633
|
}
|
|
628
634
|
/**
|
|
629
635
|
* Bidirectional parity across three surfaces: the descriptor, the roster
|
|
630
|
-
* (`KNOWN_REVIEWER_SLUGS`), and the generated capability **registry** — plus
|
|
631
|
-
*
|
|
636
|
+
* (`KNOWN_REVIEWER_SLUGS`), and the generated capability **registry** — plus two assertions
|
|
637
|
+
* against the workflow: the anti-parity check, and the availability-fallback check (the workflow
|
|
638
|
+
* makes the availability call, has a fallback row per lane, and the fallback slug set equals the
|
|
639
|
+
* openai-http lanes).
|
|
632
640
|
*
|
|
633
641
|
* **Re-pointed by Phase 5b (#2799).** Through Phase 5a this function also required a literal
|
|
634
642
|
* `<!-- reviewer-lane: <slug> -->` per lane inside `invoke_reviewers` and a literal
|
|
@@ -671,6 +679,7 @@ function checkReviewerLaneParity(input) {
|
|
|
671
679
|
const seenSlug = new Set();
|
|
672
680
|
const seenFlag = new Set();
|
|
673
681
|
const seenSection = new Set();
|
|
682
|
+
const httpSlugs = new Set();
|
|
674
683
|
// The declared parameter type says `ReviewerLane[]`, but this function is a
|
|
675
684
|
// trust boundary — narrow from `unknown` rather than believing the annotation.
|
|
676
685
|
const rawLanes = Array.isArray(descriptor) ? descriptor : [];
|
|
@@ -689,6 +698,8 @@ function checkReviewerLaneParity(input) {
|
|
|
689
698
|
if (seenSlug.has(slug))
|
|
690
699
|
add(exports.PARITY_VIOLATION.DUPLICATE_SLUG, slug);
|
|
691
700
|
seenSlug.add(slug);
|
|
701
|
+
if (lane.transport === 'openai-http')
|
|
702
|
+
httpSlugs.add(slug);
|
|
692
703
|
const flags = Array.isArray(lane.flags) ? lane.flags : [];
|
|
693
704
|
for (const flag of flags) {
|
|
694
705
|
if (typeof flag !== 'string')
|
|
@@ -740,6 +751,28 @@ function checkReviewerLaneParity(input) {
|
|
|
740
751
|
for (const slug of markerSlugs.keys()) {
|
|
741
752
|
add(exports.PARITY_VIOLATION.BESPOKE_LEG_PRESENT, slug);
|
|
742
753
|
}
|
|
754
|
+
// --- the availability call's `||` fallback must name exactly the openai-http lanes ---
|
|
755
|
+
//
|
|
756
|
+
// review.md prints these rows only when an older gsd-tools lacks `review-lane availability`, so
|
|
757
|
+
// they are a second hand-kept copy of the roster. Checked only when the call is present.
|
|
758
|
+
// Anchored to the command position so a comment or prose mention cannot shadow the real call;
|
|
759
|
+
// a missing call is itself a violation (otherwise deleting it would silently skip this check).
|
|
760
|
+
const availabilityLine = (0, text_lines_cjs_1.splitLines)(workflowText).find((line) => AVAILABILITY_CALL_RE.test(line));
|
|
761
|
+
if (availabilityLine === undefined) {
|
|
762
|
+
add(exports.PARITY_VIOLATION.AVAILABILITY_FALLBACK_MISMATCH, 'no-call');
|
|
763
|
+
}
|
|
764
|
+
else {
|
|
765
|
+
if (!availabilityLine.includes('review-lane availability ||')) {
|
|
766
|
+
add(exports.PARITY_VIOLATION.AVAILABILITY_FALLBACK_MISMATCH, 'no-fallback');
|
|
767
|
+
}
|
|
768
|
+
const fallback = new Set(Array.from(availabilityLine.matchAll(AVAILABILITY_FALLBACK_ROW_RE), (m) => m[1]));
|
|
769
|
+
for (const slug of fallback)
|
|
770
|
+
if (!httpSlugs.has(slug))
|
|
771
|
+
add(exports.PARITY_VIOLATION.AVAILABILITY_FALLBACK_MISMATCH, slug);
|
|
772
|
+
for (const slug of httpSlugs)
|
|
773
|
+
if (!fallback.has(slug))
|
|
774
|
+
add(exports.PARITY_VIOLATION.AVAILABILITY_FALLBACK_MISMATCH, slug);
|
|
775
|
+
}
|
|
743
776
|
return { ok: violations.length === 0, violations };
|
|
744
777
|
}
|
|
745
778
|
/* ------------------------------------------------------------------ *
|
|
@@ -31,6 +31,7 @@ exports.resolveTimeoutMs = resolveTimeoutMs;
|
|
|
31
31
|
exports.nativeTimeoutToken = nativeTimeoutToken;
|
|
32
32
|
exports.isEmptyReview = isEmptyReview;
|
|
33
33
|
exports.fileRefPrompt = fileRefPrompt;
|
|
34
|
+
exports.applyPromptOverride = applyPromptOverride;
|
|
34
35
|
exports.artifactPaths = artifactPaths;
|
|
35
36
|
exports.resolveLaneBudget = resolveLaneBudget;
|
|
36
37
|
exports.resolveLanePlan = resolveLanePlan;
|
|
@@ -229,6 +230,45 @@ function fileRefPrompt(promptPath, repoRoot) {
|
|
|
229
230
|
`review request against that absolute root. Output only the resulting markdown review. ` +
|
|
230
231
|
`Do not edit any files.`);
|
|
231
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Re-point a resolved plan at a different prompt file (`review-lane invoke --prompt-file`, #5049).
|
|
235
|
+
*
|
|
236
|
+
* The override carries a budget-trimmed prompt, so it has to land wherever THIS lane actually
|
|
237
|
+
* reads its prompt, and that differs by channel:
|
|
238
|
+
* - `stdin`: the runner streams the file `plan.stdin` names.
|
|
239
|
+
* - `argv-file-ref`: the prompt PATH is embedded in a sentence in argv (`fileRefPrompt`), already
|
|
240
|
+
* expanded by the time an override can run. Swapping `plan.promptPath` alone changes nothing
|
|
241
|
+
* the CLI reads, which is how the override was dropped silently for cursor, antigravity and
|
|
242
|
+
* kimi-code.
|
|
243
|
+
* - `argv`: the bare path is an argv element.
|
|
244
|
+
* - `openai-http`: the runner reads `plan.promptPath`.
|
|
245
|
+
* Argv elements are matched whole (the file-ref sentence, or the bare path), never by substring,
|
|
246
|
+
* so an unrelated argument that merely contains the path is left alone. `promptPath` moves with
|
|
247
|
+
* argv: the antigravity handler re-derives the sentence it swaps from `plan.promptPath` and would
|
|
248
|
+
* otherwise stop recognising it. A plan that takes no prompt (`none`) is returned unchanged.
|
|
249
|
+
* Pure: returns a new plan and never mutates the one it is given.
|
|
250
|
+
*/
|
|
251
|
+
function applyPromptOverride(plan, promptPath, repoRoot) {
|
|
252
|
+
if (plan.transport !== 'spawn')
|
|
253
|
+
return { ...plan, promptPath };
|
|
254
|
+
if (plan.stdin)
|
|
255
|
+
return { ...plan, stdin: promptPath, promptPath };
|
|
256
|
+
const oldRef = fileRefPrompt(plan.promptPath, repoRoot);
|
|
257
|
+
const newRef = fileRefPrompt(promptPath, repoRoot);
|
|
258
|
+
let replaced = false;
|
|
259
|
+
const argv = plan.argv.map((a) => {
|
|
260
|
+
if (a === oldRef) {
|
|
261
|
+
replaced = true;
|
|
262
|
+
return newRef;
|
|
263
|
+
}
|
|
264
|
+
if (a === plan.promptPath) {
|
|
265
|
+
replaced = true;
|
|
266
|
+
return promptPath;
|
|
267
|
+
}
|
|
268
|
+
return a;
|
|
269
|
+
});
|
|
270
|
+
return replaced ? { ...plan, argv, promptPath } : plan;
|
|
271
|
+
}
|
|
232
272
|
/** Run-dir artifact paths. POSIX-joined: these are workflow-visible strings, not OS paths. */
|
|
233
273
|
function artifactPaths(runDir, slug) {
|
|
234
274
|
const base = String(runDir ?? '').replace(/\/+$/, '');
|
|
@@ -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);
|
|
@@ -113,6 +113,22 @@ exports.KNOWN_REVIEWER_SLUGS = (() => {
|
|
|
113
113
|
return [];
|
|
114
114
|
}
|
|
115
115
|
})();
|
|
116
|
+
/**
|
|
117
|
+
* #5359: map a lane flag alias (`agy` for `--agy`) to its canonical slug via the
|
|
118
|
+
* descriptor roster's declared `flags` (same source as `review-lane explicit-from-argv`).
|
|
119
|
+
* Guarded like KNOWN_REVIEWER_SLUGS: a load failure degrades to the plain error.
|
|
120
|
+
*/
|
|
121
|
+
function laneSlugForAlias(name, lanes) {
|
|
122
|
+
try {
|
|
123
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
124
|
+
const roster = lanes ?? require('./review-lane-descriptor.cjs').REVIEWER_LANES;
|
|
125
|
+
// `l.slug !== name`: an undetected canonical slug (`--codex` flag) is not an alias.
|
|
126
|
+
return roster.find((l) => l.slug !== name && l.flags.includes(`--${name}`))?.slug;
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
116
132
|
/** Instance names are lowercase slugs that must not shadow a built-in slug. */
|
|
117
133
|
exports.INSTANCE_NAME_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
118
134
|
function normalizeConfiguredDefaultReviewers(rawValue) {
|
|
@@ -239,7 +255,10 @@ function resolveReviewerSelection(input) {
|
|
|
239
255
|
// Sorted so the error order does not depend on flag order on the command line.
|
|
240
256
|
const missing = [...explicitFlags].filter((slug) => !detected.has(slug)).sort();
|
|
241
257
|
for (const slug of missing) {
|
|
242
|
-
|
|
258
|
+
const canonical = laneSlugForAlias(slug, input.lanes);
|
|
259
|
+
errors.push(canonical
|
|
260
|
+
? `explicit reviewer '${slug}' is a flag alias; pass its canonical slug '${canonical}'`
|
|
261
|
+
: `explicit reviewer '${slug}' is not available on this host`);
|
|
243
262
|
}
|
|
244
263
|
// Guarded on the error count as it stood BEFORE this branch, so the
|
|
245
264
|
// aggregate message fires under exactly the conditions it did previously.
|
|
@@ -78,6 +78,17 @@ function isClosedMilestoneHeading(headingText) {
|
|
|
78
78
|
function stripShippedMilestones(content) {
|
|
79
79
|
return (0, markdown_sectionizer_cjs_1.stripTaggedBlocks)(content, 'details');
|
|
80
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* #5543: run `edit` over the ROADMAP with every shipped `<details>` block hidden
|
|
83
|
+
* and restored byte-for-byte afterwards. For writers whose active milestone
|
|
84
|
+
* could not be resolved: the first `### Phase N:` in document order must never
|
|
85
|
+
* be the one inside a shipped block. Layout-independent (the active phase may
|
|
86
|
+
* sit before or after a shipped block) and, unlike a "region after the last
|
|
87
|
+
* `</details>`" cut, not fooled by a `</details>` in a fence or inline code.
|
|
88
|
+
*/
|
|
89
|
+
function editOutsideShippedBlocks(content, edit) {
|
|
90
|
+
return (0, markdown_sectionizer_cjs_1.editOutsideTaggedBlocks)(content, 'details', edit);
|
|
91
|
+
}
|
|
81
92
|
/**
|
|
82
93
|
* #3982: strip only <details> blocks whose <summary> marks a CLOSED milestone
|
|
83
94
|
* (ARCHIVED/SHIPPED/✅/… without an active marker) — the narrow form of
|
|
@@ -2287,6 +2298,7 @@ module.exports = {
|
|
|
2287
2298
|
getMilestonePhaseFilter,
|
|
2288
2299
|
currentMilestoneRawRanges,
|
|
2289
2300
|
withPhaseSection,
|
|
2301
|
+
editOutsideShippedBlocks,
|
|
2290
2302
|
computeMilestoneSectionEnd,
|
|
2291
2303
|
locateMilestoneHeadings,
|
|
2292
2304
|
listMilestoneHeadings,
|
|
@@ -12,7 +12,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
};
|
|
13
13
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
14
14
|
const node_path_1 = __importDefault(require("node:path"));
|
|
15
|
-
const node_child_process_1 = require("node:child_process");
|
|
16
15
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
17
16
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
18
17
|
const planningWorkspace = require("./planning-workspace.cjs");
|
|
@@ -1923,7 +1922,45 @@ function applyMigration(cwd, plan, options = {}) {
|
|
|
1923
1922
|
// ── Real run: verify clean working tree ───────────────────────────────────
|
|
1924
1923
|
let gitStatus;
|
|
1925
1924
|
try {
|
|
1926
|
-
|
|
1925
|
+
// #5048: this is a read-only spawn, but git still refreshes the index under
|
|
1926
|
+
// it and takes the optional `.git/index.lock` to write the refreshed copy
|
|
1927
|
+
// back — which can lose a race against a real `git add` / `git commit` in
|
|
1928
|
+
// the same repo. Routing through the shared execGit seam (CONTEXT.md, OS
|
|
1929
|
+
// Shell Projection) is what gets GIT_OPTIONAL_LOCKS=0 here; a bare execSync
|
|
1930
|
+
// bypassed the seam and therefore the opt-out, so this call site was the one
|
|
1931
|
+
// read-only `git status` the seam change did not reach. shell-free, so no
|
|
1932
|
+
// argv quoting or PATH-resolution policy is introduced.
|
|
1933
|
+
const statusTimeoutMs = 10_000;
|
|
1934
|
+
const result = (0, shell_command_projection_cjs_1.execGit)(['status', '--porcelain'], { cwd, timeout: statusTimeoutMs });
|
|
1935
|
+
// #5048: execSync carried the cause on the thrown error. execGit reports a
|
|
1936
|
+
// timeout, a spawn/buffer failure or a signal through `timedOut`/`error`/
|
|
1937
|
+
// `signal` with an exit code of `status ?? 1` and often an empty stderr.
|
|
1938
|
+
// Order matters: a maxBuffer overflow returns signal SIGTERM *and*
|
|
1939
|
+
// error.code ENOBUFS — check `error` before `signal` so the real cause is
|
|
1940
|
+
// not reported as "killed by SIGTERM". Only a genuine non-zero exit falls
|
|
1941
|
+
// through. (ENOENT is rewritten by `_spawnResult` to exit 127 + stderr.)
|
|
1942
|
+
if (result.timedOut) {
|
|
1943
|
+
throw new Error(`git status timed out after ${statusTimeoutMs} ms`);
|
|
1944
|
+
}
|
|
1945
|
+
if (result.error) {
|
|
1946
|
+
// The cause is not always a failed spawn: ENOBUFS and EPERM reach this
|
|
1947
|
+
// branch with the process already started (a maxBuffer overflow returns
|
|
1948
|
+
// signal SIGTERM *and* error.code ENOBUFS). So the message stays neutral
|
|
1949
|
+
// about starting and names the code instead of inferring a cause from it.
|
|
1950
|
+
const code = result.error.code;
|
|
1951
|
+
const why = code === 'ENOBUFS' ? 'output exceeded the buffer' : code;
|
|
1952
|
+
const detail = why && !result.error.message.includes(why)
|
|
1953
|
+
? `${result.error.message} (${why})`
|
|
1954
|
+
: result.error.message;
|
|
1955
|
+
throw new Error(detail);
|
|
1956
|
+
}
|
|
1957
|
+
if (result.signal) {
|
|
1958
|
+
throw new Error(`git status was killed by ${result.signal}`);
|
|
1959
|
+
}
|
|
1960
|
+
if (result.exitCode !== 0) {
|
|
1961
|
+
throw new Error(result.stderr || `git exited ${result.exitCode}`);
|
|
1962
|
+
}
|
|
1963
|
+
gitStatus = result.stdout;
|
|
1927
1964
|
}
|
|
1928
1965
|
catch (err) {
|
|
1929
1966
|
throw new Error(`git status failed: ${err.message}`);
|