@opengsd/gsd-core 1.12.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.opencode/plugins/gsd-core.js +12 -0
- package/agents/gsd-advisor-researcher.compact.md +85 -0
- package/agents/gsd-ai-researcher.compact.md +96 -0
- package/agents/gsd-assumptions-analyzer.compact.md +81 -0
- package/agents/gsd-code-fixer.compact.md +458 -0
- package/agents/gsd-code-fixer.md +5 -5
- package/agents/gsd-code-reviewer.compact.md +269 -0
- package/agents/gsd-code-reviewer.md +15 -3
- package/agents/gsd-codebase-mapper.compact.md +760 -0
- package/agents/gsd-debug-session-manager.compact.md +345 -0
- package/agents/gsd-doc-classifier.compact.md +192 -0
- package/agents/gsd-doc-synthesizer.compact.md +200 -0
- package/agents/gsd-doc-verifier.compact.md +143 -0
- package/agents/gsd-doc-writer.compact.md +440 -0
- package/agents/gsd-dom-verifier.compact.md +138 -0
- package/agents/gsd-domain-researcher.compact.md +141 -0
- package/agents/gsd-eval-auditor.compact.md +160 -0
- package/agents/gsd-eval-planner.compact.md +137 -0
- package/agents/gsd-executor.md +63 -35
- package/agents/gsd-framework-selector.compact.md +82 -0
- package/agents/gsd-integration-checker.compact.md +245 -0
- package/agents/gsd-intel-updater.compact.md +226 -0
- package/agents/gsd-mempalace-curator.compact.md +45 -0
- package/agents/gsd-nyquist-auditor.compact.md +179 -0
- package/agents/gsd-pattern-mapper.compact.md +275 -0
- package/agents/gsd-plan-checker.md +76 -57
- package/agents/gsd-planner.md +14 -0
- package/agents/gsd-project-researcher.compact.md +587 -0
- package/agents/gsd-research-synthesizer.compact.md +212 -0
- package/agents/gsd-roadmapper.compact.md +454 -0
- package/agents/gsd-roadmapper.md +13 -0
- package/agents/gsd-security-auditor.compact.md +162 -0
- package/agents/gsd-ui-auditor.compact.md +404 -0
- package/agents/gsd-ui-checker.compact.md +277 -0
- package/agents/gsd-ui-checker.md +19 -3
- package/agents/gsd-ui-researcher.compact.md +282 -0
- package/agents/gsd-ui-researcher.md +29 -0
- package/agents/gsd-user-profiler.compact.md +108 -0
- package/agents/gsd-verifier.md +23 -1
- package/bin/install.js +444 -134
- package/commands/gsd/cleanup.md +1 -0
- package/commands/gsd/code-review.md +2 -1
- package/commands/gsd/complete-milestone.md +1 -0
- package/commands/gsd/config.md +1 -0
- package/commands/gsd/debug.md +1 -0
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/graphify.md +1 -0
- package/commands/gsd/health.md +1 -0
- package/commands/gsd/mempalace-capture.md +1 -0
- package/commands/gsd/mempalace-recall.md +1 -0
- package/commands/gsd/new-milestone.md +1 -0
- package/commands/gsd/new-project.md +1 -0
- package/commands/gsd/next.md +1 -0
- package/commands/gsd/ns-workflow.md +2 -1
- package/commands/gsd/pause-work.md +1 -0
- package/commands/gsd/phase.md +2 -1
- package/commands/gsd/pr-branch.md +1 -0
- package/commands/gsd/quick-batch.md +105 -0
- package/commands/gsd/resume-work.md +1 -0
- package/commands/gsd/review-backlog.md +1 -0
- package/commands/gsd/settings.md +2 -1
- package/commands/gsd/stats.md +1 -0
- package/commands/gsd/surface.md +18 -8
- package/commands/gsd/thread.md +1 -0
- package/commands/gsd/workspace.md +1 -0
- package/commands/gsd/workstreams.md +1 -0
- package/gsd-core/bin/check-latest-version.cjs +8 -3
- package/gsd-core/bin/gsd-tools.cjs +532 -174
- package/gsd-core/bin/lib/adr-parser.cjs +1 -1
- package/gsd-core/bin/lib/artifacts.cjs +2 -1
- package/gsd-core/bin/lib/audit.cjs +39 -22
- package/gsd-core/bin/lib/broken-windows.cjs +168 -49
- package/gsd-core/bin/lib/capability-activation.cjs +27 -0
- package/gsd-core/bin/lib/capability-lifecycle.cjs +10 -6
- package/gsd-core/bin/lib/capability-loader.cjs +135 -1
- package/gsd-core/bin/lib/capability-registry.cjs +528 -116
- package/gsd-core/bin/lib/capability-source.cjs +19 -2
- package/gsd-core/bin/lib/capability-state.cjs +7 -1
- package/gsd-core/bin/lib/capability-validator.cjs +134 -5
- package/gsd-core/bin/lib/capability-writer.cjs +14 -4
- package/gsd-core/bin/lib/check-command-router.cjs +198 -38
- package/gsd-core/bin/lib/claude-orchestration.cjs +10 -25
- package/gsd-core/bin/lib/clusters.cjs +1 -0
- package/gsd-core/bin/lib/code-review-depth.cjs +2 -2
- package/gsd-core/bin/lib/command-aliases.cjs +16 -0
- package/gsd-core/bin/lib/commands.cjs +981 -79
- package/gsd-core/bin/lib/config-loader.cjs +4 -0
- package/gsd-core/bin/lib/config.cjs +153 -38
- package/gsd-core/bin/lib/core-utils.cjs +34 -7
- package/gsd-core/bin/lib/coverage.cjs +1 -1
- package/gsd-core/bin/lib/decisions.cjs +343 -28
- package/gsd-core/bin/lib/edge-probe.cjs +14 -1
- package/gsd-core/bin/lib/external-descriptor-trust.cjs +29 -14
- package/gsd-core/bin/lib/file-overlap-partitioner.cjs +74 -0
- package/gsd-core/bin/lib/frontmatter.cjs +137 -23
- package/gsd-core/bin/lib/gap-checker.cjs +22 -13
- package/gsd-core/bin/lib/git-base-branch.cjs +10 -2
- package/gsd-core/bin/lib/gsd2-import.cjs +1 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +8 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +54 -11
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +87 -23
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +1 -1
- package/gsd-core/bin/lib/host-integration.cjs +57 -5
- package/gsd-core/bin/lib/init-command-router.cjs +14 -0
- package/gsd-core/bin/lib/init.cjs +539 -60
- package/gsd-core/bin/lib/install-engine.cjs +199 -14
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +45 -0
- package/gsd-core/bin/lib/install-profiles.cjs +36 -14
- package/gsd-core/bin/lib/installer-migration-report.cjs +1 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +33 -4
- package/gsd-core/bin/lib/io.cjs +35 -0
- package/gsd-core/bin/lib/loop-resolver.cjs +64 -39
- package/gsd-core/bin/lib/markdown-table.cjs +123 -0
- package/gsd-core/bin/lib/mcp-catalog.cjs +2 -2
- package/gsd-core/bin/lib/milestone.cjs +41 -10
- package/gsd-core/bin/lib/model-resolver.cjs +101 -10
- package/gsd-core/bin/lib/phase-command-router.cjs +20 -7
- package/gsd-core/bin/lib/phase-id.cjs +412 -31
- package/gsd-core/bin/lib/phase-lifecycle.cjs +61 -0
- package/gsd-core/bin/lib/phase.cjs +941 -98
- package/gsd-core/bin/lib/plan-document.cjs +10 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +34 -18
- package/gsd-core/bin/lib/planning-snapshot.cjs +206 -30
- package/gsd-core/bin/lib/planning-workspace.cjs +153 -29
- package/gsd-core/bin/lib/pristine-baseline.cjs +182 -0
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +91 -4
- package/gsd-core/bin/lib/quick-batch-command-router.cjs +285 -0
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +250 -0
- package/gsd-core/bin/lib/quick-batch.cjs +840 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +61 -2
- package/gsd-core/bin/lib/research-store.cjs +11 -12
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +53 -5
- package/gsd-core/bin/lib/review-lane-invocation.cjs +96 -1
- package/gsd-core/bin/lib/review-lane-runner.cjs +136 -10
- package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +337 -0
- package/gsd-core/bin/lib/roadmap-parser.cjs +555 -41
- package/gsd-core/bin/lib/roadmap.cjs +292 -69
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +260 -43
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +28 -20
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +294 -108
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +408 -47
- package/gsd-core/bin/lib/security.cjs +126 -7
- package/gsd-core/bin/lib/shell-command-projection.cjs +4 -0
- package/gsd-core/bin/lib/smart-entry.cjs +7 -9
- package/gsd-core/bin/lib/state-document.cjs +159 -32
- package/gsd-core/bin/lib/state-md-schema.cjs +44 -27
- package/gsd-core/bin/lib/state-transition.cjs +465 -62
- package/gsd-core/bin/lib/state.cjs +906 -151
- package/gsd-core/bin/lib/surface.cjs +83 -10
- package/gsd-core/bin/lib/task-command-router.cjs +12 -6
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +133 -0
- package/gsd-core/bin/lib/uat.cjs +1420 -516
- package/gsd-core/bin/lib/update-context.cjs +36 -26
- package/gsd-core/bin/lib/validate.cjs +230 -12
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +11 -3
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +316 -23
- package/gsd-core/bin/lib/verify-command-grounding.cjs +1 -1
- package/gsd-core/bin/lib/verify-command-router.cjs +1 -0
- package/gsd-core/bin/lib/verify.cjs +531 -36
- package/gsd-core/bin/lib/workstream-inventory.cjs +21 -2
- package/gsd-core/bin/lib/worktree-safety.cjs +21 -7
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +13 -0
- package/gsd-core/bin/verify-reapply-patches.cjs +507 -81
- package/gsd-core/references/agent-contracts.md +3 -3
- package/gsd-core/references/compact-content-gate.md +66 -0
- package/gsd-core/references/edge-probe.md +17 -13
- package/gsd-core/references/execute-mvp-tdd.md +18 -16
- package/gsd-core/references/execute-phase-response-language.md +6 -0
- package/gsd-core/references/executor-examples.md +42 -0
- package/gsd-core/references/few-shot-examples/plan-checker.md +15 -15
- package/gsd-core/references/loop-hook-dispatch.md +18 -0
- package/gsd-core/references/model-profiles.md +12 -3
- package/gsd-core/references/mvp-concepts.md +2 -2
- package/gsd-core/references/plan-checker-examples.md +41 -0
- package/gsd-core/references/planner-antipatterns.md +25 -0
- package/gsd-core/references/planner-chunked.md +5 -1
- package/gsd-core/references/planner-coupling.md +42 -0
- package/gsd-core/references/planner-quick-batch.md +71 -0
- package/gsd-core/references/planner-reviews.md +47 -0
- package/gsd-core/references/planner-revision.md +75 -2
- package/gsd-core/references/planning-config.md +5 -1
- package/gsd-core/references/response-language-directive.md +9 -0
- package/gsd-core/references/revision-loop.md +118 -11
- package/gsd-core/references/tdd.md +17 -9
- package/gsd-core/references/thinking-models-planning.md +18 -2
- package/gsd-core/references/verification-patterns.md +17 -4
- package/gsd-core/references/verifier-evidence-gate.md +160 -0
- package/gsd-core/references/worktree-path-safety.md +112 -2
- package/gsd-core/templates/README.md +7 -1
- package/gsd-core/templates/phase-prompt.md +4 -0
- package/gsd-core/templates/state.md +6 -3
- package/gsd-core/templates/summary.compact.md +212 -0
- package/gsd-core/templates/user-setup.compact.md +199 -0
- package/gsd-core/templates/user-setup.md +0 -9
- package/gsd-core/templates/verification-report.md +5 -0
- package/gsd-core/workflows/add-backlog.md +2 -0
- package/gsd-core/workflows/add-phase.md +2 -0
- package/gsd-core/workflows/add-tests.md +1 -1
- package/gsd-core/workflows/add-todo.md +4 -3
- package/gsd-core/workflows/ai-integration-phase.md +1 -1
- package/gsd-core/workflows/analyze-dependencies.md +2 -0
- package/gsd-core/workflows/audit-fix.md +2 -0
- package/gsd-core/workflows/audit-milestone.md +2 -0
- package/gsd-core/workflows/audit-uat.md +2 -0
- package/gsd-core/workflows/autonomous.md +15 -10
- package/gsd-core/workflows/check-todos.md +5 -3
- package/gsd-core/workflows/cleanup.md +4 -2
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +22 -13
- package/gsd-core/workflows/code-review-fix.md +5 -3
- package/gsd-core/workflows/code-review.md +211 -43
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +274 -0
- package/gsd-core/workflows/complete-milestone.md +40 -254
- package/gsd-core/workflows/debug.md +1 -1
- package/gsd-core/workflows/diagnose-issues.md +5 -1
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/all.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/analyze.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/auto.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/batch.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/default.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/power.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/text.md +2 -0
- package/gsd-core/workflows/discuss-phase/templates/context.md +2 -0
- package/gsd-core/workflows/discuss-phase/templates/discussion-log.md +2 -0
- package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
- package/gsd-core/workflows/discuss-phase-power.md +2 -0
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +43 -13
- package/gsd-core/workflows/docs-update/detail/elaboration.md +179 -0
- package/gsd-core/workflows/docs-update.md +15 -156
- package/gsd-core/workflows/edit-phase.md +2 -0
- package/gsd-core/workflows/eval-review.md +1 -1
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +124 -0
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +20 -3
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +56 -0
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +24 -3
- package/gsd-core/workflows/execute-phase/steps/executor-progress-policy.md +43 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +8 -2
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -0
- package/gsd-core/workflows/execute-phase/steps/sequential-root-pin.md +35 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +25 -0
- package/gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md +2 -0
- package/gsd-core/workflows/execute-phase.md +78 -159
- package/gsd-core/workflows/execute-plan.md +28 -15
- package/gsd-core/workflows/explore.md +2 -0
- package/gsd-core/workflows/extract-learnings.md +2 -0
- package/gsd-core/workflows/fast.md +6 -0
- package/gsd-core/workflows/forensics.md +2 -0
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +1 -1
- package/gsd-core/workflows/help/modes/brief.md +2 -0
- package/gsd-core/workflows/help/modes/default.md +2 -0
- package/gsd-core/workflows/help/modes/full.compact.md +398 -0
- package/gsd-core/workflows/help/modes/full.md +12 -0
- package/gsd-core/workflows/help/modes/topic.md +2 -0
- package/gsd-core/workflows/help.md +3 -1
- package/gsd-core/workflows/import.md +3 -3
- package/gsd-core/workflows/inbox.md +1 -1
- package/gsd-core/workflows/ingest-docs.md +1 -1
- package/gsd-core/workflows/insert-phase.md +2 -0
- package/gsd-core/workflows/list-phase-assumptions.md +2 -0
- package/gsd-core/workflows/list-seeds.md +2 -0
- package/gsd-core/workflows/list-workspaces.md +2 -0
- package/gsd-core/workflows/manager.md +3 -3
- package/gsd-core/workflows/map-codebase.md +52 -3
- package/gsd-core/workflows/milestone-summary.md +2 -0
- package/gsd-core/workflows/mvp-phase.md +1 -1
- package/gsd-core/workflows/new-milestone.md +55 -13
- package/gsd-core/workflows/new-project/detail/elaboration.md +216 -0
- package/gsd-core/workflows/new-project.md +37 -205
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +2 -0
- package/gsd-core/workflows/node-repair.md +2 -0
- package/gsd-core/workflows/note.md +2 -0
- package/gsd-core/workflows/onboard.md +1 -1
- package/gsd-core/workflows/pause-work.md +19 -4
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +209 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +100 -18
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -0
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +9 -0
- package/gsd-core/workflows/plan-phase.md +144 -185
- package/gsd-core/workflows/plan-review-convergence.md +102 -10
- package/gsd-core/workflows/plant-seed.md +1 -1
- package/gsd-core/workflows/pr-branch.md +30 -10
- package/gsd-core/workflows/profile-user.md +1 -1
- package/gsd-core/workflows/progress/steps/forensic-audit.md +1 -1
- package/gsd-core/workflows/progress.md +25 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +37 -2
- package/gsd-core/workflows/quick/steps/research-phase.md +3 -3
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +55 -0
- package/gsd-core/workflows/quick-batch/steps/completion.md +65 -0
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +100 -0
- package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +147 -0
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +158 -0
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +95 -0
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +49 -0
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +73 -0
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +169 -0
- package/gsd-core/workflows/quick-batch.md +203 -0
- package/gsd-core/workflows/quick.md +21 -4
- package/gsd-core/workflows/reapply-patches.md +79 -3
- package/gsd-core/workflows/remove-phase.md +2 -0
- package/gsd-core/workflows/remove-workspace.md +1 -1
- package/gsd-core/workflows/resume-project.md +6 -2
- package/gsd-core/workflows/review.md +215 -10
- package/gsd-core/workflows/scan.md +2 -0
- package/gsd-core/workflows/section-manifest.json +12 -0
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/session-report.md +2 -0
- package/gsd-core/workflows/settings-advanced.md +2 -0
- package/gsd-core/workflows/settings-integrations.md +9 -8
- package/gsd-core/workflows/settings.md +19 -6
- package/gsd-core/workflows/ship.md +10 -10
- package/gsd-core/workflows/sketch-wrap-up.md +2 -0
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/smart-entry.md +1 -1
- package/gsd-core/workflows/spec-phase.md +24 -19
- package/gsd-core/workflows/spike-wrap-up.md +2 -0
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +2 -0
- package/gsd-core/workflows/sync-skills.md +12 -4
- package/gsd-core/workflows/thread.md +2 -0
- package/gsd-core/workflows/transition.md +2 -0
- package/gsd-core/workflows/ui-phase.md +26 -5
- package/gsd-core/workflows/ui-review.md +1 -1
- package/gsd-core/workflows/ultraplan-phase.md +2 -0
- package/gsd-core/workflows/undo.md +1 -1
- package/gsd-core/workflows/update.md +48 -43
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-work/detail/elaboration.md +230 -0
- package/gsd-core/workflows/verify-work.md +68 -182
- package/hooks/dist/gsd-agent-isolation-guard.js +42 -16
- package/hooks/dist/gsd-check-update-worker.js +19 -2
- package/hooks/dist/gsd-context-monitor.js +371 -27
- package/hooks/dist/gsd-cursor-subagent-start.js +34 -14
- package/hooks/dist/gsd-node-runner.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +30 -5
- package/hooks/dist/gsd-read-guard.js +2 -0
- package/hooks/dist/gsd-read-injection-scanner.js +5 -5
- package/hooks/dist/gsd-secret-read-guard.js +1105 -0
- package/hooks/dist/gsd-statusline.js +18 -10
- package/hooks/dist/gsd-validate-commit.sh +474 -7
- package/hooks/dist/gsd-workflow-guard.js +2 -1
- package/hooks/dist/gsd-worktree-path-guard.js +25 -14
- package/hooks/dist/gsd-write-guard.js +46 -1
- package/hooks/dist/lib/dispatch-identity.js +187 -0
- package/hooks/dist/lib/filename-classification.js +64 -0
- package/hooks/dist/lib/git-cmd.js +210 -1
- package/hooks/dist/lib/injection-patterns.js +36 -6
- package/hooks/dist/lib/isolation-deny-reason.js +53 -1
- package/hooks/dist/lib/isolation-sentinel.js +58 -19
- package/hooks/dist/managed-hooks-registry.cjs +1 -0
- package/hooks/gsd-agent-isolation-guard.js +42 -16
- package/hooks/gsd-check-update-worker.js +19 -2
- package/hooks/gsd-context-monitor.js +371 -27
- package/hooks/gsd-cursor-subagent-start.js +34 -14
- package/hooks/gsd-node-runner.sh +1 -0
- package/hooks/gsd-prompt-guard.js +30 -5
- package/hooks/gsd-read-guard.js +2 -0
- package/hooks/gsd-read-injection-scanner.js +5 -5
- package/hooks/gsd-secret-read-guard.js +1105 -0
- package/hooks/gsd-statusline.js +18 -10
- package/hooks/gsd-validate-commit.sh +474 -7
- package/hooks/gsd-workflow-guard.js +2 -1
- package/hooks/gsd-worktree-path-guard.js +25 -14
- package/hooks/gsd-write-guard.js +46 -1
- package/hooks/hooks.json +6 -0
- package/hooks/lib/dispatch-identity.js +187 -0
- package/hooks/lib/filename-classification.js +64 -0
- package/hooks/lib/git-cmd.js +210 -1
- package/hooks/lib/injection-patterns.js +36 -6
- package/hooks/lib/isolation-deny-reason.js +53 -1
- package/hooks/lib/isolation-sentinel.js +58 -19
- package/hooks/managed-hooks-registry.cjs +1 -0
- package/package.json +13 -9
- package/scripts/benchmark-compact-content-variants.cjs +298 -0
- package/scripts/benchmark-compact-content.cjs +368 -0
- package/scripts/build-hooks.js +11 -4
- package/scripts/check-contract-drift.cjs +4 -1
- package/scripts/check-env.cjs +36 -8
- package/scripts/check-glossary-refs.cjs +25 -21
- package/scripts/ci-next-health.cjs +271 -0
- package/scripts/ci-prepare-test-scope.cjs +7 -7
- package/scripts/ci-test-scope.cjs +133 -20
- package/scripts/ci-timeout-report.cjs +1 -1
- package/scripts/diff-touches-shipped-paths.cjs +1 -1
- package/scripts/docs-guard-registry.cjs +17 -2
- package/scripts/gen-adr-index.cjs +8 -2
- package/scripts/gen-inventory-manifest.cjs +12 -0
- package/scripts/gen-loop-host-contract.cjs +67 -15
- package/scripts/gen-platform-conformance-tier.cjs +557 -0
- package/scripts/lib/drift-scan.cjs +1 -1
- package/scripts/lib/macos-conformance-tier.generated.cjs +210 -0
- package/scripts/lib/npm-version-check-diagnosis.cjs +59 -0
- package/scripts/lib/platform-conformance-tier.generated.cjs +276 -0
- package/scripts/lib/shellcheck-fetch.cjs +247 -0
- package/scripts/lib/suite-detection.cjs +32 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -6
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-allowed-tools-parity.cjs +221 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +24 -2
- package/scripts/lint-phase-enumeration-drift.cjs +24 -6
- package/scripts/lint-phase-id-drift.cjs +465 -15
- package/scripts/lint-portable-grep.cjs +176 -0
- package/scripts/lint-response-language-coverage.cjs +530 -0
- package/scripts/lint-source-test-name-collision.cjs +1 -1
- package/scripts/lint-test-file-count.allowlist.json +4 -1
- package/scripts/lint-vendored-deps.cjs +128 -17
- package/scripts/lint-workflow-shellcheck-baseline.json +1112 -0
- package/scripts/lint-workflow-shellcheck.cjs +614 -0
- package/scripts/npm-audit-baseline.cjs +376 -0
- package/scripts/prompt-injection-scan.sh +22 -0
- package/scripts/require-issue-link-policy.cjs +16 -1
- package/scripts/workflow-size.cjs +139 -0
- package/skills/gsd-cleanup/SKILL.md +1 -0
- package/skills/gsd-code-review/SKILL.md +2 -1
- package/skills/gsd-complete-milestone/SKILL.md +1 -0
- package/skills/gsd-config/SKILL.md +1 -0
- package/skills/gsd-debug/SKILL.md +1 -0
- package/skills/gsd-execute-phase/SKILL.md +1 -1
- package/skills/gsd-graphify/SKILL.md +1 -0
- package/skills/gsd-health/SKILL.md +1 -0
- package/skills/gsd-mempalace-capture/SKILL.md +1 -0
- package/skills/gsd-mempalace-recall/SKILL.md +1 -0
- package/skills/gsd-new-milestone/SKILL.md +1 -0
- package/skills/gsd-new-project/SKILL.md +1 -0
- package/skills/gsd-next/SKILL.md +1 -0
- package/skills/gsd-ns-workflow/SKILL.md +1 -0
- package/skills/gsd-pause-work/SKILL.md +1 -0
- package/skills/gsd-phase/SKILL.md +2 -1
- package/skills/gsd-pr-branch/SKILL.md +1 -0
- package/skills/gsd-quick-batch/SKILL.md +105 -0
- package/skills/gsd-resume-work/SKILL.md +1 -0
- package/skills/gsd-review-backlog/SKILL.md +1 -0
- package/skills/gsd-settings/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +1 -0
- package/skills/gsd-surface/SKILL.md +18 -8
- package/skills/gsd-thread/SKILL.md +1 -0
- package/skills/gsd-workspace/SKILL.md +1 -0
- package/skills/gsd-workstreams/SKILL.md +1 -0
- package/vscode/package.json +1 -1
- package/gsd-core/templates/claude-md.md +0 -145
- package/gsd-core/templates/codebase/concerns.md +0 -310
- package/gsd-core/templates/codebase/conventions.md +0 -307
- package/gsd-core/templates/codebase/integrations.md +0 -280
- package/gsd-core/templates/codebase/structure.md +0 -285
- package/gsd-core/templates/codebase/testing.md +0 -480
- package/gsd-core/templates/debug-subagent-prompt.md +0 -91
- package/gsd-core/templates/discovery.md +0 -146
|
@@ -165,7 +165,7 @@ function normalizeSkillManifest(runtimeConfigDir, manifest) {
|
|
|
165
165
|
* - registry is threaded into resolveProfile so capability skills
|
|
166
166
|
* participate in the base skill set and their requires: chains expand.
|
|
167
167
|
*/
|
|
168
|
-
function resolveSurface(runtimeConfigDir, manifest, clusterMap, registry) {
|
|
168
|
+
function resolveSurface(runtimeConfigDir, manifest, clusterMap, registry, surfaceOverride) {
|
|
169
169
|
// Merge capability clusters into the cluster map when registry is provided.
|
|
170
170
|
// The ADR-857 phase 4a HARD gate guarantees that when a capId matches a CLUSTERS
|
|
171
171
|
// key, the values are EQUAL — so the spread is idempotent for matching names.
|
|
@@ -205,7 +205,7 @@ function resolveSurface(runtimeConfigDir, manifest, clusterMap, registry) {
|
|
|
205
205
|
cm = merged;
|
|
206
206
|
}
|
|
207
207
|
const skillManifest = normalizeSkillManifest(runtimeConfigDir, manifest);
|
|
208
|
-
const surface = readSurface(runtimeConfigDir);
|
|
208
|
+
const surface = surfaceOverride === undefined ? readSurface(runtimeConfigDir) : surfaceOverride;
|
|
209
209
|
// Determine base profile name: from surface state or from .gsd-profile marker
|
|
210
210
|
const baseProfileName = (surface && surface.baseProfile)
|
|
211
211
|
? surface.baseProfile
|
|
@@ -316,10 +316,9 @@ function applySurface(runtimeConfigDir, layout, manifest, clusterMap, registry,
|
|
|
316
316
|
os: deps.os, env: deps.env,
|
|
317
317
|
});
|
|
318
318
|
const skillManifest = normalizeSkillManifest(layout.configDir, manifest);
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
retiredArtifactCleanup.pruneRetiredRuntimeArtifacts(layout.runtime, layout.configDir);
|
|
319
|
+
const hasCandidateState = opts !== undefined && Object.prototype.hasOwnProperty.call(opts, 'surfaceState');
|
|
320
|
+
const candidateState = hasCandidateState ? (opts.surfaceState ?? null) : undefined;
|
|
321
|
+
const resolved = resolveSurface(layout.configDir, skillManifest, clusterMap, registry, candidateState);
|
|
323
322
|
// #1575: agents kind now mirrors createRuntimeArtifactInstallPlan — build
|
|
324
323
|
// agentCtx (pathPrefix + attribution) and pass it to kind.stage() so
|
|
325
324
|
// stageAgentsForRuntimeWithConverter applies the full inline-loop pipeline
|
|
@@ -353,7 +352,7 @@ function applySurface(runtimeConfigDir, layout, manifest, clusterMap, registry,
|
|
|
353
352
|
// not referenced by any skill's _calls_agents_ manifest entry would be silently
|
|
354
353
|
// dropped from the surface path. For tiered profiles (core/standard) or when
|
|
355
354
|
// surface mods exist, pass the resolved set so only the filtered subset stages.
|
|
356
|
-
const _surfaceState = readSurface(layout.configDir);
|
|
355
|
+
const _surfaceState = candidateState === undefined ? readSurface(layout.configDir) : candidateState;
|
|
357
356
|
const _baseProfileName = (_surfaceState && _surfaceState.baseProfile)
|
|
358
357
|
? _surfaceState.baseProfile
|
|
359
358
|
: (readActiveProfile(layout.configDir) || 'full');
|
|
@@ -361,17 +360,29 @@ function applySurface(runtimeConfigDir, layout, manifest, clusterMap, registry,
|
|
|
361
360
|
_surfaceState.explicitAdds.length > 0 ||
|
|
362
361
|
_surfaceState.explicitRemoves.length > 0);
|
|
363
362
|
const _isUnmodifiedFull = _baseProfileName === 'full' && !_hasSurfaceMods;
|
|
363
|
+
const stagedKinds = [];
|
|
364
364
|
try {
|
|
365
365
|
for (const kind of layout.kinds) {
|
|
366
366
|
let staged;
|
|
367
|
-
|
|
367
|
+
// #4211: kimi-agents is an AGENT kind — kimiAgentsKind.stage() forwards
|
|
368
|
+
// agentCtx into stageAgentsForRuntimeWithConverter exactly as agentsKind
|
|
369
|
+
// does, and createRuntimeArtifactInstallPlan hands every kind the
|
|
370
|
+
// context. Staging it bare here dropped the path-prefix rewrites and the
|
|
371
|
+
// attribution trailer from Kimi's generated subagents, and (under an
|
|
372
|
+
// unmodified `full` profile) staged only the skill-referenced subset the
|
|
373
|
+
// install path stages with `skills: '*'`.
|
|
374
|
+
if (kind.kind === 'agents' || kind.kind === 'kimi-agents') {
|
|
368
375
|
const agentProfile = _isUnmodifiedFull ? { ...resolved, skills: '*' } : resolved;
|
|
369
376
|
staged = kind.stage(agentProfile, agentCtx);
|
|
370
377
|
}
|
|
371
378
|
else {
|
|
372
379
|
staged = kind.stage(resolved);
|
|
373
380
|
}
|
|
374
|
-
|
|
381
|
+
// #4211: kimi-agents takes the skill-body rewrite too —
|
|
382
|
+
// createRuntimeArtifactInstallPlan routes `skills` and `kimi-agents`
|
|
383
|
+
// through rewriteStagedSkillBodies together, so omitting it here left
|
|
384
|
+
// Kimi's surface-materialized prompts with unrewritten paths.
|
|
385
|
+
if (kind.kind === 'skills' || kind.kind === 'kimi-agents') {
|
|
375
386
|
runtimeArtifactConversion.rewriteStagedSkillBodies(staged, {
|
|
376
387
|
runtime: layout.runtime,
|
|
377
388
|
configDir: layout.configDir,
|
|
@@ -396,7 +407,22 @@ function applySurface(runtimeConfigDir, layout, manifest, clusterMap, registry,
|
|
|
396
407
|
// the parity test in tests/runtime-artifact-layout-surface.test.cjs
|
|
397
408
|
// enforces that the two writers never diverge again.
|
|
398
409
|
const dest = assertDestWithinConfigHome(kind.home ?? layout.configDir, kind.destSubpath);
|
|
399
|
-
|
|
410
|
+
stagedKinds.push({ kind, staged, dest });
|
|
411
|
+
}
|
|
412
|
+
// Do not mutate installed artifacts until every kind has staged
|
|
413
|
+
// successfully. A missing source provider therefore leaves both artifacts
|
|
414
|
+
// and the persisted surface state untouched.
|
|
415
|
+
retiredArtifactCleanup.pruneRetiredRuntimeArtifacts(layout.runtime, layout.configDir);
|
|
416
|
+
for (const item of stagedKinds) {
|
|
417
|
+
_syncGsdDir(item.staged, item.dest, item.kind, skillManifest, layout.runtime);
|
|
418
|
+
}
|
|
419
|
+
if (hasCandidateState) {
|
|
420
|
+
if (candidateState === null) {
|
|
421
|
+
node_fs_1.default.rmSync(node_path_1.default.join(runtimeConfigDir, SURFACE_FILE_NAME), { force: true });
|
|
422
|
+
}
|
|
423
|
+
else if (candidateState !== undefined) {
|
|
424
|
+
writeSurface(runtimeConfigDir, candidateState);
|
|
425
|
+
}
|
|
400
426
|
}
|
|
401
427
|
}
|
|
402
428
|
finally {
|
|
@@ -557,6 +583,53 @@ function _syncGsdDir(stagedDir, destDir, kind, manifest, runtime) {
|
|
|
557
583
|
// (no agentFileExtension declared) keep the staged filename verbatim.
|
|
558
584
|
const _agentExt = runtime ? runtimeArtifactConversion.agentFileExtensionFor(runtime) : undefined;
|
|
559
585
|
const isRenamedAgents = !!_agentExt && kindName === 'agents';
|
|
586
|
+
if (kindName === 'kimi-agents') {
|
|
587
|
+
// #4211: Kimi's managed tree is `gsd.yaml` + `gsd.md` + `subagents/gsd-*.{yaml,md}`
|
|
588
|
+
// (runtime-artifact-layout.cts kimiAgentsKind), and install copies it
|
|
589
|
+
// RECURSIVELY (_copyStaged in src/install-engine.cts). Surface apply fell
|
|
590
|
+
// through to the flat command/agent branch below, which reads only `*.md`
|
|
591
|
+
// at the top level: the YAML half and the whole subagents/ subtree were
|
|
592
|
+
// dropped, and `gsd.md` was written as `gsdgsd.md` (the flat branch
|
|
593
|
+
// re-applies kind.prefix to a name that already carries it). A surface
|
|
594
|
+
// change could therefore corrupt Kimi's installed artifacts while still
|
|
595
|
+
// reporting success.
|
|
596
|
+
node_fs_1.default.cpSync(stagedDir, destDir, { recursive: true });
|
|
597
|
+
// Prune GSD-owned files the new surface no longer stages, with exactly the
|
|
598
|
+
// ownership rule install's _removeGsdEntries applies to this kind: the two
|
|
599
|
+
// root files, and `gsd-`-prefixed .yaml/.md under subagents/. Everything
|
|
600
|
+
// else in the directory is user-owned and is preserved.
|
|
601
|
+
const _rootStaged = new Set(node_fs_1.default.readdirSync(stagedDir));
|
|
602
|
+
for (const fileName of ['gsd.yaml', 'gsd.md']) {
|
|
603
|
+
if (!_rootStaged.has(fileName)) {
|
|
604
|
+
try {
|
|
605
|
+
node_fs_1.default.rmSync(node_path_1.default.join(destDir, fileName), { force: true });
|
|
606
|
+
}
|
|
607
|
+
catch { /* ignore */ }
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
const _stagedSubagentsDir = node_path_1.default.join(stagedDir, 'subagents');
|
|
611
|
+
const _destSubagentsDir = node_path_1.default.join(destDir, 'subagents');
|
|
612
|
+
const _stagedSubagents = node_fs_1.default.existsSync(_stagedSubagentsDir)
|
|
613
|
+
? new Set(node_fs_1.default.readdirSync(_stagedSubagentsDir))
|
|
614
|
+
: new Set();
|
|
615
|
+
if (node_fs_1.default.existsSync(_destSubagentsDir)) {
|
|
616
|
+
for (const entry of node_fs_1.default.readdirSync(_destSubagentsDir, { withFileTypes: true })) {
|
|
617
|
+
if (!entry.isFile())
|
|
618
|
+
continue;
|
|
619
|
+
if (!entry.name.startsWith('gsd-'))
|
|
620
|
+
continue;
|
|
621
|
+
if (!entry.name.endsWith('.yaml') && !entry.name.endsWith('.md'))
|
|
622
|
+
continue;
|
|
623
|
+
if (_stagedSubagents.has(entry.name))
|
|
624
|
+
continue;
|
|
625
|
+
try {
|
|
626
|
+
node_fs_1.default.rmSync(node_path_1.default.join(_destSubagentsDir, entry.name), { force: true });
|
|
627
|
+
}
|
|
628
|
+
catch { /* ignore */ }
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
560
633
|
if (kindName === 'skills') {
|
|
561
634
|
// Skills kind: work with directories, not files.
|
|
562
635
|
// Each staged entry is a directory named ${prefix}${stem}.
|
|
@@ -11,6 +11,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
11
11
|
};
|
|
12
12
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
13
13
|
const node_path_1 = __importDefault(require("node:path"));
|
|
14
|
+
const security_cjs_1 = require("./security.cjs");
|
|
14
15
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
15
16
|
const ioMod = require("./io.cjs");
|
|
16
17
|
const { output, error, ERROR_REASON } = ioMod;
|
|
@@ -108,12 +109,14 @@ function routeResolveContent({ args, cwd, raw }, deps = {}) {
|
|
|
108
109
|
return;
|
|
109
110
|
}
|
|
110
111
|
const projectRoot = node_path_1.default.resolve(cwd || process.cwd());
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
// Lexical containment (ADR-4650): this path is validated before existence is
|
|
113
|
+
// checked below, so realpath resolution is neither available nor required.
|
|
114
|
+
const contained = (0, security_cjs_1.tryWithinRootLexical)(plan, projectRoot);
|
|
115
|
+
if (contained === null) {
|
|
114
116
|
error(`Plan file is outside project scope: ${plan}`, ERROR_REASON.USAGE);
|
|
115
117
|
return;
|
|
116
118
|
}
|
|
119
|
+
const resolvedPlanPath = contained;
|
|
117
120
|
if (!node_fs_1.default.existsSync(resolvedPlanPath)) {
|
|
118
121
|
error(`Plan file not found: ${plan}`, ERROR_REASON.USAGE);
|
|
119
122
|
return;
|
|
@@ -173,11 +176,14 @@ function routeTaskCommand({ args, cwd, raw }) {
|
|
|
173
176
|
else if (args[2]) {
|
|
174
177
|
const projectRoot = node_path_1.default.resolve(cwd || process.cwd());
|
|
175
178
|
const requestedPath = args[2];
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
+
// Lexical containment (ADR-4650): validated before existence is checked below.
|
|
180
|
+
// `error()` here does not return/throw (preserved from before this migration),
|
|
181
|
+
// so resolvedTaskPath must still be computed identically on the rejected path.
|
|
182
|
+
const contained = (0, security_cjs_1.tryWithinRootLexical)(requestedPath, projectRoot);
|
|
183
|
+
if (contained === null) {
|
|
179
184
|
error(`Task file is outside project scope: ${requestedPath}`, ERROR_REASON.USAGE);
|
|
180
185
|
}
|
|
186
|
+
const resolvedTaskPath = contained ?? node_path_1.default.resolve(projectRoot, requestedPath);
|
|
181
187
|
if (!node_fs_1.default.existsSync(resolvedTaskPath)) {
|
|
182
188
|
error(`Task file not found: ${requestedPath}`, ERROR_REASON.USAGE);
|
|
183
189
|
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TDD RED-evidence classification (#3770).
|
|
4
|
+
*
|
|
5
|
+
* The `type: tdd` executor gate previously accepted ANY nonzero test command as
|
|
6
|
+
* RED: syntax errors, zero-test discovery, fixture crashes, parser errors, and
|
|
7
|
+
* unrelated assertions all authorized production edits (GREEN). This module
|
|
8
|
+
* defines the compact RED evidence the gate now requires — the TARGET test's
|
|
9
|
+
* identity plus a matching assertion failure — and classifies a persisted test
|
|
10
|
+
* run into exactly one verdict:
|
|
11
|
+
*
|
|
12
|
+
* RED_EVIDENCE_OK — nonzero exit AND the target test failed as a REAL test
|
|
13
|
+
* (distinctly named, TAP-reported failure). The ONLY
|
|
14
|
+
* verdict that may advance to GREEN.
|
|
15
|
+
* INVALID_RED — everything else, with a machine-readable reason:
|
|
16
|
+
* unexpected_green | zero_tests_discovered |
|
|
17
|
+
* nonzero_exit_without_test_failure |
|
|
18
|
+
* fixture_or_load_failure | no_target_test_failure |
|
|
19
|
+
* invalid_record | unreadable_record (router arm).
|
|
20
|
+
*
|
|
21
|
+
* Everything here is PURE — no fs, no spawn, no clock — so the executor can
|
|
22
|
+
* persist the record (command, exit code, failing test, expected, actual) and
|
|
23
|
+
* validate it via `gsd_run check tdd-red-evidence <record.json>`.
|
|
24
|
+
*
|
|
25
|
+
* TAP parsing reuses the proven primitives from prohibition-enforcement
|
|
26
|
+
* (`parseNodeTestSummary`, `tapFailedTestNames`) — the same contract the
|
|
27
|
+
* prohibition probe's fail-first prover already relies on (#1259).
|
|
28
|
+
*/
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.classifyRedEvidence = classifyRedEvidence;
|
|
31
|
+
exports.buildRedEvidenceRecord = buildRedEvidenceRecord;
|
|
32
|
+
const prohibition_enforcement_cjs_1 = require("./prohibition-enforcement.cjs");
|
|
33
|
+
/** Basename of a path-like string ('' for non-strings) — separators `/` and `\`. */
|
|
34
|
+
function baseOf(p) {
|
|
35
|
+
return typeof p === 'string' ? (p.split(/[\\/]/).pop() ?? p) : '';
|
|
36
|
+
}
|
|
37
|
+
/** Coerce and validate the raw record's scalar fields. Returns null exit_code only when absent/non-numeric. */
|
|
38
|
+
function readInput(input) {
|
|
39
|
+
const command = typeof input?.command === 'string' ? input.command : '';
|
|
40
|
+
const output = typeof input?.output === 'string' ? input.output : '';
|
|
41
|
+
const targetTest = typeof input?.targetTest === 'string' ? input.targetTest.trim() : '';
|
|
42
|
+
const exitCode = typeof input?.exitCode === 'number' && Number.isFinite(input.exitCode) ? input.exitCode : null;
|
|
43
|
+
if (!command || !targetTest || exitCode === null)
|
|
44
|
+
return null;
|
|
45
|
+
return { command, exitCode, output, targetTest };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Classify a persisted RED-phase test run. Fail-closed: malformed input, an
|
|
49
|
+
* unparseable/empty TAP summary, a file-named (load/crash) failure, or a
|
|
50
|
+
* failure that is not the target test's are all INVALID_RED — only a nonzero
|
|
51
|
+
* exit WITH the distinctly-named target test failing is RED_EVIDENCE_OK.
|
|
52
|
+
* Never throws.
|
|
53
|
+
*/
|
|
54
|
+
function classifyRedEvidence(input) {
|
|
55
|
+
const parsed = readInput(input);
|
|
56
|
+
if (!parsed) {
|
|
57
|
+
return {
|
|
58
|
+
verdict: 'INVALID_RED',
|
|
59
|
+
reason: 'invalid_record',
|
|
60
|
+
evidence: {
|
|
61
|
+
command: typeof input?.command === 'string' ? input.command : '',
|
|
62
|
+
exit_code: null,
|
|
63
|
+
target_test: '',
|
|
64
|
+
tests: 0,
|
|
65
|
+
pass: 0,
|
|
66
|
+
fail: 0,
|
|
67
|
+
failing_tests: [],
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const { command, exitCode, output, targetTest } = parsed;
|
|
72
|
+
const summary = (0, prohibition_enforcement_cjs_1.parseNodeTestSummary)(output);
|
|
73
|
+
const failing = (0, prohibition_enforcement_cjs_1.tapFailedTestNames)(output);
|
|
74
|
+
const evidence = {
|
|
75
|
+
command,
|
|
76
|
+
exit_code: exitCode,
|
|
77
|
+
target_test: targetTest,
|
|
78
|
+
tests: summary.tests,
|
|
79
|
+
pass: summary.pass,
|
|
80
|
+
fail: summary.fail,
|
|
81
|
+
failing_tests: failing,
|
|
82
|
+
};
|
|
83
|
+
// Existing fail-fast rule, now machine-checked: exit 0 during RED is an
|
|
84
|
+
// unexpected GREEN — the feature may already exist or the test is wrong.
|
|
85
|
+
if (exitCode === 0) {
|
|
86
|
+
return { verdict: 'INVALID_RED', reason: 'unexpected_green', evidence };
|
|
87
|
+
}
|
|
88
|
+
// Zero-test discovery: the discovery pattern / fixture matched no tests.
|
|
89
|
+
// A run that executed nothing cannot prove anything about the behavior.
|
|
90
|
+
if (summary.tests === 0) {
|
|
91
|
+
return { verdict: 'INVALID_RED', reason: 'zero_tests_discovered', evidence };
|
|
92
|
+
}
|
|
93
|
+
// Nonzero exit but TAP reports no failing test: harness/setup/parser crash
|
|
94
|
+
// whose failure never reached a test assertion (or unparseable output).
|
|
95
|
+
if (summary.fail === 0 || failing.length === 0) {
|
|
96
|
+
return { verdict: 'INVALID_RED', reason: 'nonzero_exit_without_test_failure', evidence };
|
|
97
|
+
}
|
|
98
|
+
// Fixture/load failure: every failing entry is named like the target FILE —
|
|
99
|
+
// node reports a load-time crash (throw-on-require, syntax error, ENOENT
|
|
100
|
+
// fixture) as a file-named `not ok 1 - <file>`, never the target test.
|
|
101
|
+
const targetBase = baseOf(input?.targetFile ?? '');
|
|
102
|
+
const distinctlyNamed = failing.filter((n) => (targetBase ? baseOf(n) !== targetBase : true));
|
|
103
|
+
if (distinctlyNamed.length === 0) {
|
|
104
|
+
return { verdict: 'INVALID_RED', reason: 'fixture_or_load_failure', evidence };
|
|
105
|
+
}
|
|
106
|
+
// Unrelated failure: real tests ran and failed, but none is the target test
|
|
107
|
+
// the plan named — an unrelated assertion must not authorize GREEN.
|
|
108
|
+
if (!distinctlyNamed.includes(targetTest)) {
|
|
109
|
+
return { verdict: 'INVALID_RED', reason: 'no_target_test_failure', evidence };
|
|
110
|
+
}
|
|
111
|
+
return { verdict: 'RED_EVIDENCE_OK', reason: 'target_test_failed', evidence };
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Project a classification into the persisted record shape — command, exit
|
|
115
|
+
* code, failing test, expected, actual, verdict, reason — so the evidence
|
|
116
|
+
* survives past the terminal and the gate can re-verify it deterministically.
|
|
117
|
+
* Pure: JSON-serializable, no timestamps (the record's mtime/commit carries time).
|
|
118
|
+
*/
|
|
119
|
+
function buildRedEvidenceRecord(input, result) {
|
|
120
|
+
const failingTest = result.evidence.failing_tests.find((n) => n === result.evidence.target_test) ??
|
|
121
|
+
result.evidence.failing_tests[0] ??
|
|
122
|
+
null;
|
|
123
|
+
return {
|
|
124
|
+
command: result.evidence.command,
|
|
125
|
+
exit_code: result.evidence.exit_code,
|
|
126
|
+
failing_test: failingTest,
|
|
127
|
+
target_test: result.evidence.target_test,
|
|
128
|
+
expected: typeof input?.expected === 'string' ? input.expected : null,
|
|
129
|
+
actual: typeof input?.actual === 'string' ? input.actual : null,
|
|
130
|
+
verdict: result.verdict,
|
|
131
|
+
reason: result.reason,
|
|
132
|
+
};
|
|
133
|
+
}
|