@opengsd/gsd-core 1.15.0 → 1.16.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 +85 -5
- package/agents/gsd-code-fixer.compact.md +1 -1
- package/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-code-reviewer.compact.md +5 -3
- package/agents/gsd-code-reviewer.md +8 -6
- package/agents/gsd-debug-session-manager.compact.md +1 -1
- package/agents/gsd-debug-session-manager.md +1 -1
- package/agents/gsd-debugger.md +2 -2
- package/agents/gsd-eval-auditor.compact.md +1 -1
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +4 -4
- package/agents/gsd-intel-updater.compact.md +1 -1
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +2 -2
- package/agents/gsd-phase-researcher.md +1 -1
- package/agents/gsd-plan-checker.md +7 -2
- package/agents/gsd-planner.md +3 -3
- package/agents/gsd-project-researcher.compact.md +1 -1
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.compact.md +1 -1
- package/agents/gsd-research-synthesizer.md +1 -1
- package/agents/gsd-ui-auditor.compact.md +21 -30
- package/agents/gsd-ui-auditor.md +42 -51
- package/agents/gsd-ui-researcher.compact.md +1 -1
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-verifier.md +31 -9
- package/bin/install.js +126 -196
- package/commands/gsd/add-tests.md +6 -1
- package/commands/gsd/ai-integration-phase.md +6 -1
- package/commands/gsd/audit-fix.md +5 -0
- package/commands/gsd/audit-milestone.md +6 -1
- package/commands/gsd/autonomous.md +5 -0
- package/commands/gsd/capture.md +8 -4
- package/commands/gsd/code-review.md +7 -2
- package/commands/gsd/complete-milestone.md +4 -0
- package/commands/gsd/config.md +7 -3
- package/commands/gsd/debug.md +11 -7
- package/commands/gsd/discuss-phase.md +7 -3
- package/commands/gsd/docs-update.md +12 -7
- package/commands/gsd/eval-review.md +6 -1
- package/commands/gsd/execute-phase.md +12 -7
- package/commands/gsd/extract-learnings.md +5 -0
- package/commands/gsd/fast.md +4 -0
- package/commands/gsd/forensics.md +5 -1
- package/commands/gsd/graphify.md +10 -6
- package/commands/gsd/health.md +5 -0
- package/commands/gsd/help.md +7 -2
- package/commands/gsd/import.md +7 -3
- package/commands/gsd/inbox.md +5 -0
- package/commands/gsd/ingest-docs.md +5 -1
- package/commands/gsd/manager.md +6 -1
- package/commands/gsd/map-codebase.md +7 -3
- package/commands/gsd/mempalace-capture.md +5 -1
- package/commands/gsd/mempalace-recall.md +5 -1
- package/commands/gsd/milestone-summary.md +5 -1
- package/commands/gsd/mvp-phase.md +8 -3
- package/commands/gsd/new-milestone.md +6 -1
- package/commands/gsd/new-project.md +5 -0
- package/commands/gsd/next.md +6 -1
- package/commands/gsd/ns-context.md +4 -0
- package/commands/gsd/ns-ideate.md +4 -0
- package/commands/gsd/ns-manage.md +4 -0
- package/commands/gsd/ns-project.md +4 -0
- package/commands/gsd/ns-review.md +4 -0
- package/commands/gsd/ns-workflow.md +4 -0
- package/commands/gsd/onboard.md +6 -1
- package/commands/gsd/pause-work.md +5 -1
- package/commands/gsd/phase.md +8 -4
- package/commands/gsd/plan-phase.md +6 -1
- package/commands/gsd/plan-review-convergence.md +5 -1
- package/commands/gsd/pr-branch.md +4 -0
- package/commands/gsd/profile-user.md +5 -1
- package/commands/gsd/progress.md +6 -1
- package/commands/gsd/quick-batch.md +20 -8
- package/commands/gsd/quick.md +12 -7
- package/commands/gsd/review.md +5 -1
- package/commands/gsd/secure-phase.md +6 -1
- package/commands/gsd/ship.md +5 -0
- package/commands/gsd/sketch.md +7 -2
- package/commands/gsd/spec-phase.md +5 -1
- package/commands/gsd/spike.md +8 -3
- package/commands/gsd/surface.md +5 -1
- package/commands/gsd/thread.md +4 -0
- package/commands/gsd/ui-phase.md +6 -1
- package/commands/gsd/ui-review.md +6 -1
- package/commands/gsd/ultraplan-phase.md +5 -1
- package/commands/gsd/undo.md +5 -1
- package/commands/gsd/update.md +6 -2
- package/commands/gsd/validate-phase.md +6 -1
- package/commands/gsd/verify-work.md +6 -1
- package/commands/gsd/workspace.md +7 -3
- package/gsd-core/bin/gsd-tools.cjs +142 -56
- package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
- package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
- package/gsd-core/bin/lib/audit.cjs +78 -44
- package/gsd-core/bin/lib/broken-windows.cjs +13 -13
- package/gsd-core/bin/lib/capability-activation.cjs +9 -4
- package/gsd-core/bin/lib/capability-registry.cjs +183 -103
- package/gsd-core/bin/lib/capability-validator.cjs +16 -0
- package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
- package/gsd-core/bin/lib/check-command-router.cjs +164 -1712
- package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
- package/gsd-core/bin/lib/cli-exit.cjs +12 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +11 -8
- package/gsd-core/bin/lib/command-aliases.cjs +7 -0
- package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
- package/gsd-core/bin/lib/commands.cjs +173 -170
- package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
- package/gsd-core/bin/lib/config.cjs +43 -12
- package/gsd-core/bin/lib/core-utils.cjs +6 -1
- package/gsd-core/bin/lib/coverage.cjs +4 -8
- package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
- package/gsd-core/bin/lib/drift.cjs +177 -42
- package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
- package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
- package/gsd-core/bin/lib/frontmatter.cjs +413 -234
- package/gsd-core/bin/lib/gap-checker.cjs +72 -29
- package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
- package/gsd-core/bin/lib/gate-args.cjs +53 -0
- package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
- package/gsd-core/bin/lib/gate-config.cjs +46 -0
- package/gsd-core/bin/lib/gate-context-drift.cjs +141 -0
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
- package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
- package/gsd-core/bin/lib/gate-exit.cjs +27 -0
- package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
- package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
- package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
- package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
- package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
- package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
- package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
- package/gsd-core/bin/lib/gate-ui-safety.cjs +80 -0
- package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
- package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
- package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
- package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
- package/gsd-core/bin/lib/init.cjs +162 -96
- package/gsd-core/bin/lib/install-engine.cjs +19 -35
- package/gsd-core/bin/lib/install-profiles.cjs +7 -4
- package/gsd-core/bin/lib/io.cjs +122 -3
- package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
- package/gsd-core/bin/lib/milestone.cjs +19 -1
- package/gsd-core/bin/lib/model-resolver.cjs +18 -18
- package/gsd-core/bin/lib/observability/event.cjs +1 -1
- package/gsd-core/bin/lib/observability/logger.cjs +46 -1
- package/gsd-core/bin/lib/pattern.cjs +10 -0
- package/gsd-core/bin/lib/phase-command-router.cjs +11 -4
- package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
- package/gsd-core/bin/lib/phase-id.cjs +1 -1
- package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
- package/gsd-core/bin/lib/phase-status.cjs +360 -0
- package/gsd-core/bin/lib/phase.cjs +280 -80
- package/gsd-core/bin/lib/plan-document.cjs +93 -19
- package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
- package/gsd-core/bin/lib/planning-document.cjs +273 -40
- package/gsd-core/bin/lib/planning-inspect.cjs +42 -8
- package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +76 -53
- package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
- package/gsd-core/bin/lib/profile-output.cjs +6 -3
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
- package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +11 -8
- package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
- package/gsd-core/bin/lib/report-parser.cjs +269 -0
- package/gsd-core/bin/lib/roadmap-command-router.cjs +13 -15
- package/gsd-core/bin/lib/roadmap-parser.cjs +82 -15
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +127 -65
- package/gsd-core/bin/lib/roadmap.cjs +169 -72
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +91 -157
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +2 -1
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
- package/gsd-core/bin/lib/runtime-homes.cjs +13 -10
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +307 -591
- package/gsd-core/bin/lib/runtime-name-policy.cjs +142 -27
- package/gsd-core/bin/lib/runtime-slash.cjs +47 -30
- package/gsd-core/bin/lib/shell-command-projection.cjs +37 -2
- package/gsd-core/bin/lib/smart-entry.cjs +19 -3
- package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
- package/gsd-core/bin/lib/state-contract.cjs +15 -18
- package/gsd-core/bin/lib/state-document.cjs +100 -22
- package/gsd-core/bin/lib/state.cjs +214 -105
- package/gsd-core/bin/lib/surface.cjs +2 -1
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -152
- package/gsd-core/bin/lib/uat-predicate.cjs +313 -35
- package/gsd-core/bin/lib/uat.cjs +424 -7
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +94 -58
- package/gsd-core/bin/lib/vendor/README.md +31 -9
- package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
- package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +1165 -314
- package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
- package/gsd-core/bin/lib/verify.cjs +286 -567
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
- package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
- package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
- package/gsd-core/bin/lib/workstream.cjs +11 -2
- package/gsd-core/bin/shared/config-defaults.manifest.json +5 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +4 -0
- package/gsd-core/references/autonomous-smart-discuss.md +2 -1
- package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
- package/gsd-core/references/execute-mvp-tdd.md +5 -10
- package/gsd-core/references/execute-phase-between-wave-reset.md +3 -0
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +7 -1
- package/gsd-core/references/offer-next.md +1 -1
- package/gsd-core/references/planning-config.md +1 -1
- package/gsd-core/references/spidr-splitting.md +1 -1
- package/gsd-core/references/tdd.md +10 -4
- package/gsd-core/references/verifier-phase-gates.md +5 -2
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -3
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/UAT.md +17 -1
- package/gsd-core/templates/config.json +2 -11
- package/gsd-core/templates/verification-report.md +1 -1
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +8 -7
- package/gsd-core/workflows/add-tests.md +3 -2
- package/gsd-core/workflows/add-todo.md +4 -3
- package/gsd-core/workflows/ai-integration-phase.md +3 -2
- package/gsd-core/workflows/audit-fix.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +4 -3
- package/gsd-core/workflows/audit-uat.md +1 -1
- package/gsd-core/workflows/autonomous.md +28 -18
- package/gsd-core/workflows/check-todos.md +6 -5
- package/gsd-core/workflows/cleanup.md +1 -1
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
- package/gsd-core/workflows/code-review-fix.md +5 -4
- package/gsd-core/workflows/code-review.md +84 -90
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
- package/gsd-core/workflows/complete-milestone.md +12 -7
- package/gsd-core/workflows/debug.md +30 -5
- package/gsd-core/workflows/diagnose-issues.md +3 -2
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +4 -3
- package/gsd-core/workflows/do.md +1 -1
- package/gsd-core/workflows/docs-update.md +4 -3
- package/gsd-core/workflows/edit-phase.md +4 -3
- package/gsd-core/workflows/eval-review.md +5 -3
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +4 -2
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
- package/gsd-core/workflows/execute-phase.md +78 -170
- package/gsd-core/workflows/execute-plan.md +13 -19
- package/gsd-core/workflows/explore.md +2 -2
- package/gsd-core/workflows/extract-learnings.md +3 -2
- package/gsd-core/workflows/fast.md +1 -1
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +2 -1
- package/gsd-core/workflows/import.md +3 -2
- package/gsd-core/workflows/inbox.md +1 -1
- package/gsd-core/workflows/ingest-docs.md +1 -1
- package/gsd-core/workflows/insert-phase.md +4 -3
- package/gsd-core/workflows/list-seeds.md +1 -1
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +5 -3
- package/gsd-core/workflows/map-codebase.md +4 -3
- package/gsd-core/workflows/milestone-summary.md +3 -2
- package/gsd-core/workflows/mvp-phase.md +14 -14
- package/gsd-core/workflows/new-milestone.md +10 -10
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +1 -1
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +1 -1
- package/gsd-core/workflows/pause-work.md +2 -2
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +1 -1
- package/gsd-core/workflows/plan-phase.md +27 -18
- package/gsd-core/workflows/plan-review-convergence.md +1 -1
- package/gsd-core/workflows/plant-seed.md +1 -1
- package/gsd-core/workflows/pr-branch.md +1 -1
- package/gsd-core/workflows/profile-user.md +1 -1
- package/gsd-core/workflows/progress.md +19 -49
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +4 -2
- package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +9 -3
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
- package/gsd-core/workflows/quick-batch.md +15 -10
- package/gsd-core/workflows/quick.md +42 -31
- package/gsd-core/workflows/remove-phase.md +3 -2
- package/gsd-core/workflows/remove-workspace.md +1 -1
- package/gsd-core/workflows/resume-project.md +3 -2
- package/gsd-core/workflows/review.md +3 -2
- package/gsd-core/workflows/scan.md +3 -2
- package/gsd-core/workflows/secure-phase.md +11 -12
- package/gsd-core/workflows/settings-advanced.md +1 -1
- package/gsd-core/workflows/settings-integrations.md +1 -1
- package/gsd-core/workflows/settings.md +1 -1
- package/gsd-core/workflows/ship.md +12 -12
- package/gsd-core/workflows/sketch-wrap-up.md +1 -1
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/smart-entry.md +1 -1
- package/gsd-core/workflows/spec-phase.md +1 -1
- package/gsd-core/workflows/spike-wrap-up.md +1 -1
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +1 -1
- package/gsd-core/workflows/sync-skills.md +1 -1
- package/gsd-core/workflows/thread.md +2 -2
- package/gsd-core/workflows/transition.md +13 -23
- package/gsd-core/workflows/ui-phase.md +5 -4
- package/gsd-core/workflows/ui-review.md +4 -3
- package/gsd-core/workflows/ultraplan-phase.md +3 -2
- package/gsd-core/workflows/undo.md +1 -1
- package/gsd-core/workflows/validate-phase.md +10 -12
- package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
- package/gsd-core/workflows/verify-work.md +68 -59
- package/hooks/dist/gsd-agent-isolation-guard.js +8 -0
- package/hooks/dist/gsd-check-update-worker.js +8 -0
- package/hooks/dist/gsd-check-update.js +8 -0
- package/hooks/dist/gsd-context-monitor.js +31 -8
- package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
- package/hooks/dist/gsd-secret-read-guard.js +147 -16
- package/hooks/dist/gsd-statusline.js +15 -7
- package/hooks/dist/gsd-update-banner.js +8 -0
- package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
- package/hooks/dist/gsd-workflow-guard.js +5 -4
- package/hooks/dist/gsd-worktree-path-guard.js +6 -2
- package/hooks/dist/lib/cli-exit.js +12 -0
- package/hooks/dist/lib/git-probe.js +17 -1
- package/hooks/dist/lib/isolation-sentinel.js +2 -2
- package/hooks/gsd-agent-isolation-guard.js +8 -0
- package/hooks/gsd-check-update-worker.js +8 -0
- package/hooks/gsd-check-update.js +8 -0
- package/hooks/gsd-context-monitor.js +31 -8
- package/hooks/gsd-cursor-subagent-start.js +8 -0
- package/hooks/gsd-secret-read-guard.js +147 -16
- package/hooks/gsd-statusline.js +15 -7
- package/hooks/gsd-update-banner.js +8 -0
- package/hooks/gsd-windsurf-pre-write.js +11 -2
- package/hooks/gsd-workflow-guard.js +5 -4
- package/hooks/gsd-worktree-path-guard.js +6 -2
- package/hooks/hooks.json +5 -5
- package/hooks/lib/cli-exit.js +12 -0
- package/hooks/lib/git-probe.js +17 -1
- package/hooks/lib/isolation-sentinel.js +2 -2
- package/package.json +21 -4
- package/scripts/changeset/parse.cjs +52 -4
- package/scripts/ci-timeout-report.cjs +770 -4
- package/scripts/command-contract-helpers.cjs +12 -8
- package/scripts/docs-guard-registry.cjs +6 -0
- package/scripts/gen-features.cjs +13 -8
- package/scripts/gen-hooks-cli-exit.cjs +12 -28
- package/scripts/gen-loop-host-contract.cjs +10 -1
- package/scripts/gen-platform-conformance-tier.cjs +187 -1
- package/scripts/gen-plugin-skills.cjs +87 -1
- package/scripts/gen-research-agents.cjs +24 -31
- package/scripts/gen-scripts-cli-exit.cjs +30 -3
- package/scripts/gen-test-timings.cjs +32 -7
- package/scripts/lib/cli-exit.cjs +12 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +20 -2
- package/scripts/lib/ndjson-reporter.cjs +28 -3
- package/scripts/lib/platform-conformance-tier.generated.cjs +34 -5
- package/scripts/lib/registration-ledger-preload.cjs +155 -0
- package/scripts/lib/vendor-bundle.cjs +59 -0
- package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
- 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-completion-predicate-drift.cjs +18 -19
- package/scripts/lint-descriptions.cjs +7 -3
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +10 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
- package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
- package/scripts/lint-phase-enumeration-drift.cjs +12 -8
- package/scripts/lint-phase-id-drift.cjs +29 -0
- package/scripts/lint-planning-document-positive-control.cjs +329 -0
- package/scripts/lint-response-language-coverage.cjs +3 -0
- package/scripts/lint-skill-deps.cjs +7 -3
- package/scripts/lint-test-file-count.allowlist.json +11 -1
- package/scripts/lint-test-file-count.cjs +34 -1
- package/scripts/lint-vendored-deps.cjs +41 -5
- package/scripts/lint-workflow-shellcheck-baseline.json +10 -10
- package/scripts/mutation-matrix.cjs +50 -5
- package/scripts/require-issue-link-policy.cjs +6 -2
- package/scripts/sync-runtime-launcher.cjs +184 -2
- package/scripts/verify-npm-publish.cjs +76 -20
- package/skills/gsd-add-tests/SKILL.md +6 -1
- package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
- package/skills/gsd-audit-fix/SKILL.md +5 -0
- package/skills/gsd-audit-milestone/SKILL.md +6 -1
- package/skills/gsd-autonomous/SKILL.md +5 -0
- package/skills/gsd-capture/SKILL.md +8 -4
- package/skills/gsd-code-review/SKILL.md +7 -2
- package/skills/gsd-complete-milestone/SKILL.md +4 -0
- package/skills/gsd-config/SKILL.md +8 -4
- package/skills/gsd-debug/SKILL.md +11 -7
- package/skills/gsd-discuss-phase/SKILL.md +7 -3
- package/skills/gsd-docs-update/SKILL.md +12 -7
- package/skills/gsd-eval-review/SKILL.md +6 -1
- package/skills/gsd-execute-phase/SKILL.md +12 -7
- package/skills/gsd-extract-learnings/SKILL.md +5 -0
- package/skills/gsd-fast/SKILL.md +4 -0
- package/skills/gsd-forensics/SKILL.md +5 -1
- package/skills/gsd-graphify/SKILL.md +10 -6
- package/skills/gsd-health/SKILL.md +5 -0
- package/skills/gsd-help/SKILL.md +7 -2
- package/skills/gsd-import/SKILL.md +7 -3
- package/skills/gsd-inbox/SKILL.md +5 -0
- package/skills/gsd-ingest-docs/SKILL.md +5 -1
- package/skills/gsd-manager/SKILL.md +6 -1
- package/skills/gsd-map-codebase/SKILL.md +7 -3
- package/skills/gsd-mempalace-capture/SKILL.md +5 -1
- package/skills/gsd-mempalace-recall/SKILL.md +5 -1
- package/skills/gsd-milestone-summary/SKILL.md +5 -1
- package/skills/gsd-mvp-phase/SKILL.md +8 -3
- package/skills/gsd-new-milestone/SKILL.md +6 -1
- package/skills/gsd-new-project/SKILL.md +5 -0
- package/skills/gsd-next/SKILL.md +6 -1
- package/skills/gsd-ns-context/SKILL.md +4 -0
- package/skills/gsd-ns-ideate/SKILL.md +4 -0
- package/skills/gsd-ns-manage/SKILL.md +4 -0
- package/skills/gsd-ns-project/SKILL.md +4 -0
- package/skills/gsd-ns-review/SKILL.md +4 -0
- package/skills/gsd-ns-workflow/SKILL.md +4 -0
- package/skills/gsd-onboard/SKILL.md +6 -1
- package/skills/gsd-pause-work/SKILL.md +5 -1
- package/skills/gsd-phase/SKILL.md +8 -4
- package/skills/gsd-plan-phase/SKILL.md +6 -1
- package/skills/gsd-plan-review-convergence/SKILL.md +5 -1
- package/skills/gsd-pr-branch/SKILL.md +4 -0
- package/skills/gsd-profile-user/SKILL.md +5 -1
- package/skills/gsd-progress/SKILL.md +6 -1
- package/skills/gsd-quick/SKILL.md +16 -10
- package/skills/gsd-quick-batch/SKILL.md +20 -8
- package/skills/gsd-review/SKILL.md +5 -1
- package/skills/gsd-review-backlog/SKILL.md +3 -2
- package/skills/gsd-secure-phase/SKILL.md +6 -1
- package/skills/gsd-ship/SKILL.md +5 -0
- package/skills/gsd-sketch/SKILL.md +7 -2
- package/skills/gsd-spec-phase/SKILL.md +5 -1
- package/skills/gsd-spike/SKILL.md +8 -3
- package/skills/gsd-surface/SKILL.md +5 -1
- package/skills/gsd-thread/SKILL.md +4 -0
- package/skills/gsd-ui-phase/SKILL.md +6 -1
- package/skills/gsd-ui-review/SKILL.md +6 -1
- package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
- package/skills/gsd-undo/SKILL.md +5 -1
- package/skills/gsd-update/SKILL.md +6 -2
- package/skills/gsd-validate-phase/SKILL.md +6 -1
- package/skills/gsd-verify-work/SKILL.md +6 -1
- package/skills/gsd-workspace/SKILL.md +7 -3
- package/skills/gsd-workstreams/SKILL.md +6 -6
- package/vscode/package.json +1 -1
- package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +0 -24
|
@@ -65,15 +65,40 @@ const BANNER = [
|
|
|
65
65
|
'',
|
|
66
66
|
].join('\n');
|
|
67
67
|
|
|
68
|
-
/**
|
|
68
|
+
/**
|
|
69
|
+
* Compile ONLY src/cli-exit.cts (and whatever it imports — tsc follows
|
|
70
|
+
* `./exit-code-registry.cjs` on its own) to a throwaway outDir, so the work
|
|
71
|
+
* tree is untouched. A whole-project `-p tsconfig.build.json` type-checks and
|
|
72
|
+
* emits every .cts file in src/ under a fixed COMPILE_TIMEOUT_MS ceiling; on a
|
|
73
|
+
* CPU-contended shared bench that whole-project compile can exceed the
|
|
74
|
+
* ceiling and get killed even though the one file this script actually needs
|
|
75
|
+
* compiles in a fraction of the time. A throwaway tsconfig that `extends`
|
|
76
|
+
* tsconfig.build.json but overrides `files`/`include` to name only
|
|
77
|
+
* cli-exit.cts keeps every compiler option (target, strict, rootDir, etc.)
|
|
78
|
+
* while scoping the type-check + emit to that file's own import closure.
|
|
79
|
+
*/
|
|
69
80
|
function compileToTemp() {
|
|
70
81
|
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-scripts-cli-exit-'));
|
|
82
|
+
const scopedTsconfigPath = path.join(tmp, 'tsconfig.scoped.json');
|
|
71
83
|
try {
|
|
84
|
+
const scopedTsconfig = {
|
|
85
|
+
extends: path.join(REPO_ROOT, 'tsconfig.build.json'),
|
|
86
|
+
// typeRoots must be pinned to the real repo's node_modules/@types: tsc
|
|
87
|
+
// resolves a bare "types": ["node"] by walking up from the config
|
|
88
|
+
// file's own directory, and our scoped tsconfig lives outside the repo
|
|
89
|
+
// tree (in the throwaway tmp dir), so without this it cannot find
|
|
90
|
+
// @types/node at all.
|
|
91
|
+
compilerOptions: { typeRoots: [path.join(REPO_ROOT, 'node_modules', '@types')] },
|
|
92
|
+
files: [path.join(REPO_ROOT, 'src', 'cli-exit.cts')],
|
|
93
|
+
include: [],
|
|
94
|
+
};
|
|
95
|
+
fs.writeFileSync(scopedTsconfigPath, JSON.stringify(scopedTsconfig, null, 2), 'utf8');
|
|
96
|
+
|
|
72
97
|
execFileSync(
|
|
73
98
|
process.execPath,
|
|
74
99
|
[
|
|
75
100
|
path.join(REPO_ROOT, 'node_modules', 'typescript', 'bin', 'tsc'),
|
|
76
|
-
'-p',
|
|
101
|
+
'-p', scopedTsconfigPath,
|
|
77
102
|
'--outDir', tmp,
|
|
78
103
|
// A throwaway outDir must not reuse the in-tree incremental state, or
|
|
79
104
|
// tsc skips emit for files it believes are already current.
|
|
@@ -87,6 +112,8 @@ function compileToTemp() {
|
|
|
87
112
|
fs.rmSync(tmp, { recursive: true, force: true });
|
|
88
113
|
const detail = [err.stdout, err.stderr].filter(Boolean).join('\n').trim();
|
|
89
114
|
return { ok: false, detail };
|
|
115
|
+
} finally {
|
|
116
|
+
fs.rmSync(scopedTsconfigPath, { force: true });
|
|
90
117
|
}
|
|
91
118
|
}
|
|
92
119
|
|
|
@@ -182,4 +209,4 @@ function main() {
|
|
|
182
209
|
|
|
183
210
|
if (require.main === module) process.exitCode = main();
|
|
184
211
|
|
|
185
|
-
module.exports = { REASON, buildExpectedContent, OUTPUT_PATH, BANNER };
|
|
212
|
+
module.exports = { REASON, buildExpectedContent, compileToTemp, OUTPUT_PATH, BANNER };
|
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
// node scripts/gen-test-timings.cjs <events.jsonl> [<events.jsonl> ...]
|
|
20
20
|
// node scripts/gen-test-timings.cjs ~/.local/state/gsd-test/runs/*/test-events-*.jsonl
|
|
21
21
|
// node scripts/gen-test-timings.cjs events.jsonl --out tests/test-timings.json
|
|
22
|
+
// node scripts/gen-test-timings.cjs --platform win32 test-timings-windows-shard*.jsonl
|
|
23
|
+
// (#5071: the per-shard exports CI uploads from its Windows conformance
|
|
24
|
+
// jobs -> tests/test-timings.win32.json, preferred by run-tests.cjs on win32)
|
|
22
25
|
//
|
|
23
26
|
// When several streams are supplied (multiple lanes, e.g. node22 + node24), a
|
|
24
27
|
// file's recorded time is the MAX across them, not the mean: the packer exists
|
|
@@ -28,9 +31,9 @@
|
|
|
28
31
|
// The table is ADVISORY and deliberately un-gated — there is no `--check` mode
|
|
29
32
|
// and no CI lint that fails on staleness, because timing data legitimately
|
|
30
33
|
// varies run to run. A file missing from the table falls back to the table's
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
// drifted, not on a schedule.
|
|
34
|
+
// mean weight (see makeFileWeigher in run-tests.cjs), so a stale table
|
|
35
|
+
// degrades chunk BALANCE gracefully instead of failing the build. Regenerate
|
|
36
|
+
// it when the suite's cost profile has visibly drifted, not on a schedule.
|
|
34
37
|
'use strict';
|
|
35
38
|
|
|
36
39
|
const fs = require('fs');
|
|
@@ -40,12 +43,32 @@ const { ExitError, runMain } = require('./lib/cli-exit.cjs');
|
|
|
40
43
|
const DEFAULT_OUT = join(__dirname, '..', 'tests', 'test-timings.json');
|
|
41
44
|
const SCHEMA_VERSION = 1;
|
|
42
45
|
|
|
46
|
+
// #5071: `--platform <p>` writes the table measured ON that platform, which
|
|
47
|
+
// scripts/run-tests.cjs prefers there (see its makeFileWeigher). The default
|
|
48
|
+
// path must match run-tests.cjs's platformTimingsPath() —
|
|
49
|
+
// tests/run-tests-harness.test.cjs pins the two together. A closed set, in
|
|
50
|
+
// exactly Node's own `process.platform` spelling, because the value becomes
|
|
51
|
+
// part of a filename the runner looks up by that spelling.
|
|
52
|
+
const PLATFORMS = ['win32', 'darwin', 'linux'];
|
|
53
|
+
function platformOut(platform) {
|
|
54
|
+
return join(__dirname, '..', 'tests', `test-timings.${platform}.json`);
|
|
55
|
+
}
|
|
56
|
+
|
|
43
57
|
function parseArgs(argv) {
|
|
44
58
|
const inputs = [];
|
|
45
|
-
let out =
|
|
59
|
+
let out = null;
|
|
60
|
+
let platform = null;
|
|
46
61
|
for (let i = 0; i < argv.length; i++) {
|
|
47
62
|
const arg = argv[i];
|
|
48
|
-
if (arg === '--
|
|
63
|
+
if (arg === '--platform' || arg.startsWith('--platform=')) {
|
|
64
|
+
if (platform !== null) return { error: 'duplicate --platform flag' };
|
|
65
|
+
const value = arg === '--platform' ? argv[++i] : arg.slice('--platform='.length);
|
|
66
|
+
if (!value || value.startsWith('-')) return { error: `--platform requires one of: ${PLATFORMS.join(', ')}` };
|
|
67
|
+
if (!PLATFORMS.includes(value)) {
|
|
68
|
+
return { error: `unknown --platform "${value}" (expected one of: ${PLATFORMS.join(', ')})` };
|
|
69
|
+
}
|
|
70
|
+
platform = value;
|
|
71
|
+
} else if (arg === '--out') {
|
|
49
72
|
const value = argv[++i];
|
|
50
73
|
if (!value) return { error: '--out requires a path' };
|
|
51
74
|
out = value;
|
|
@@ -60,9 +83,10 @@ function parseArgs(argv) {
|
|
|
60
83
|
}
|
|
61
84
|
}
|
|
62
85
|
if (inputs.length === 0) {
|
|
63
|
-
return { error: 'usage: gen-test-timings.cjs <reporter-events.jsonl> [...] [--out <path>]' };
|
|
86
|
+
return { error: 'usage: gen-test-timings.cjs <reporter-events.jsonl> [...] [--platform <win32|darwin|linux>] [--out <path>]' };
|
|
64
87
|
}
|
|
65
|
-
|
|
88
|
+
if (out === null) out = platform ? platformOut(platform) : DEFAULT_OUT;
|
|
89
|
+
return { inputs, out, platform };
|
|
66
90
|
}
|
|
67
91
|
|
|
68
92
|
// Fold one reporter event stream into `acc`, keeping the MAX duration seen for
|
|
@@ -180,6 +204,7 @@ function main() {
|
|
|
180
204
|
const payload = {
|
|
181
205
|
schema_version: SCHEMA_VERSION,
|
|
182
206
|
generated_by: 'scripts/gen-test-timings.cjs',
|
|
207
|
+
...(parsed.platform ? { platform: parsed.platform } : {}),
|
|
183
208
|
unit: 'ms',
|
|
184
209
|
sources: sources.sort(),
|
|
185
210
|
file_count: acc.size,
|
package/scripts/lib/cli-exit.cjs
CHANGED
|
@@ -183,6 +183,17 @@ function setPendingOutcome(v) {
|
|
|
183
183
|
function getPendingOutcome() {
|
|
184
184
|
return globalThis[PENDING_OUTCOME_KEY];
|
|
185
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Declare the outcome a void-returning `main()` ends with (#5170, ADR-5057 §4): writes the
|
|
188
|
+
* pending-outcome cell that `runMain` projects. Validates `name` is an outcome
|
|
189
|
+
* `projectOutcome` accepts (PASS, FAIL or a registered name) and THROWS otherwise, so a typo'd
|
|
190
|
+
* name fails at the declaration rather than at process exit. Call it AFTER `output()`, which
|
|
191
|
+
* rewrites the cell on every call. `output()` and this are the only writers of the cell.
|
|
192
|
+
*/
|
|
193
|
+
function declareOutcome(name) {
|
|
194
|
+
projectOutcome(name, 'v1');
|
|
195
|
+
setPendingOutcome(name);
|
|
196
|
+
}
|
|
186
197
|
const EXIT_CONTRACT_FLAG_PREFIX = '--exit-contract=';
|
|
187
198
|
/** Scan argv for the FIRST `--exit-contract=<value>` token; undefined if absent. */
|
|
188
199
|
function findExitContractFlag(argv) {
|
|
@@ -555,4 +566,5 @@ module.exports = {
|
|
|
555
566
|
terminateNow,
|
|
556
567
|
setPendingOutcome,
|
|
557
568
|
getPendingOutcome,
|
|
569
|
+
declareOutcome,
|
|
558
570
|
};
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
module.exports = {
|
|
8
8
|
MACOS_CONFORMANCE_TIER_FILES: [
|
|
9
|
+
"tests/active-workstream-store.unit.test.cjs",
|
|
9
10
|
"tests/adr-612-bracket-phase-counting.test.cjs",
|
|
10
11
|
"tests/adr-index-gate.test.cjs",
|
|
11
12
|
"tests/adr-parser.property.test.cjs",
|
|
@@ -32,6 +33,7 @@ module.exports = {
|
|
|
32
33
|
"tests/changeset-parse.test.cjs",
|
|
33
34
|
"tests/check-contract-drift.test.cjs",
|
|
34
35
|
"tests/check-predicate.test.cjs",
|
|
36
|
+
"tests/check-router-cutover-equivalence.test.cjs",
|
|
35
37
|
"tests/check-ui-plan-gate.test.cjs",
|
|
36
38
|
"tests/check-ui-safety-gate.test.cjs",
|
|
37
39
|
"tests/check-update-config-dir.test.cjs",
|
|
@@ -44,7 +46,7 @@ module.exports = {
|
|
|
44
46
|
"tests/codex-config-hooks.test.cjs",
|
|
45
47
|
"tests/codex-config-install.test.cjs",
|
|
46
48
|
"tests/codex-config.test.cjs",
|
|
47
|
-
"tests/commands.test.cjs",
|
|
49
|
+
"tests/commands.platform.test.cjs",
|
|
48
50
|
"tests/commit-docs-bypass.test.cjs",
|
|
49
51
|
"tests/commit-files-deletion.test.cjs",
|
|
50
52
|
"tests/commit-files-pathspec.test.cjs",
|
|
@@ -61,6 +63,7 @@ module.exports = {
|
|
|
61
63
|
"tests/default-flip-documentation-lint.test.cjs",
|
|
62
64
|
"tests/discuss-phase-power.test.cjs",
|
|
63
65
|
"tests/docs-parity-live-registry.test.cjs",
|
|
66
|
+
"tests/drift-whole-change-set.test.cjs",
|
|
64
67
|
"tests/effort-surface-axis.test.cjs",
|
|
65
68
|
"tests/effort-sync-installed-runtime.test.cjs",
|
|
66
69
|
"tests/emitted-attribution.test.cjs",
|
|
@@ -75,12 +78,18 @@ module.exports = {
|
|
|
75
78
|
"tests/features-index-gate.test.cjs",
|
|
76
79
|
"tests/frontmatter.unit.test.cjs",
|
|
77
80
|
"tests/gap-checker.property.test.cjs",
|
|
81
|
+
"tests/gate-api-coverage-verify-pre-escape.test.cjs",
|
|
82
|
+
"tests/gate-codebase-drift.unit.test.cjs",
|
|
83
|
+
"tests/gate-tdd-red-evidence-containment.test.cjs",
|
|
84
|
+
"tests/gate-ui-plan.unit.test.cjs",
|
|
85
|
+
"tests/gate-verify-command-paths.unit.test.cjs",
|
|
78
86
|
"tests/gemini-runtime-removed.test.cjs",
|
|
79
87
|
"tests/gen-context-index.test.cjs",
|
|
80
88
|
"tests/gen-section-manifest.test.cjs",
|
|
81
89
|
"tests/git-base-branch.test.cjs",
|
|
82
90
|
"tests/graphify-query.test.cjs",
|
|
83
91
|
"tests/graphify-visualization.test.cjs",
|
|
92
|
+
"tests/gsd-agent-isolation-guard.test.cjs",
|
|
84
93
|
"tests/gsd-secret-read-guard.test.cjs",
|
|
85
94
|
"tests/gsd-settings-advanced.test.cjs",
|
|
86
95
|
"tests/gsd-statusline.test.cjs",
|
|
@@ -96,7 +105,6 @@ module.exports = {
|
|
|
96
105
|
"tests/hooks-opt-in.test.cjs",
|
|
97
106
|
"tests/host-integration.test.cjs",
|
|
98
107
|
"tests/init-manager.test.cjs",
|
|
99
|
-
"tests/init.test.cjs",
|
|
100
108
|
"tests/install-minimal-hooks.test.cjs",
|
|
101
109
|
"tests/install-path-detection.test.cjs",
|
|
102
110
|
"tests/install-regressions.test.cjs",
|
|
@@ -115,9 +123,11 @@ module.exports = {
|
|
|
115
123
|
"tests/issue-version-gate.test.cjs",
|
|
116
124
|
"tests/kimi-upgrades.test.cjs",
|
|
117
125
|
"tests/lint-docs-command-form.test.cjs",
|
|
126
|
+
"tests/lint-frontmatter-scalar-broad-grep.test.cjs",
|
|
118
127
|
"tests/lint-retired-runtime-name.test.cjs",
|
|
119
128
|
"tests/lint-workflow-shellcheck-fetch.test.cjs",
|
|
120
129
|
"tests/list-seeds.test.cjs",
|
|
130
|
+
"tests/markdown-sectionizer-xml-tags.property.test.cjs",
|
|
121
131
|
"tests/markdown-sectionizer.test.cjs",
|
|
122
132
|
"tests/mcp-catalog.test.cjs",
|
|
123
133
|
"tests/milestone-archive.test.cjs",
|
|
@@ -142,6 +152,8 @@ module.exports = {
|
|
|
142
152
|
"tests/phase-id-drift-guard.test.cjs",
|
|
143
153
|
"tests/phase-id.test.cjs",
|
|
144
154
|
"tests/phase-locator.test.cjs",
|
|
155
|
+
"tests/phase-status.test.cjs",
|
|
156
|
+
"tests/phase.platform.test.cjs",
|
|
145
157
|
"tests/phase.test.cjs",
|
|
146
158
|
"tests/plan-count-single-owner.test.cjs",
|
|
147
159
|
"tests/plan-document.test.cjs",
|
|
@@ -162,6 +174,7 @@ module.exports = {
|
|
|
162
174
|
"tests/profile-output.test.cjs",
|
|
163
175
|
"tests/profile-pipeline.test.cjs",
|
|
164
176
|
"tests/project-root.test.cjs",
|
|
177
|
+
"tests/quick-batch-command-router.stdin.test.cjs",
|
|
165
178
|
"tests/quick-batch.test.cjs",
|
|
166
179
|
"tests/quick-branching.test.cjs",
|
|
167
180
|
"tests/quick-research.test.cjs",
|
|
@@ -183,6 +196,7 @@ module.exports = {
|
|
|
183
196
|
"tests/roadmap-phase-fallback.test.cjs",
|
|
184
197
|
"tests/roadmap-upgrade-bracket.test.cjs",
|
|
185
198
|
"tests/roadmap.test.cjs",
|
|
199
|
+
"tests/run-tests-accounting.test.cjs",
|
|
186
200
|
"tests/run-tests-harness.test.cjs",
|
|
187
201
|
"tests/runtime-artifact-layout.test.cjs",
|
|
188
202
|
"tests/runtime-identity.test.cjs",
|
|
@@ -196,11 +210,14 @@ module.exports = {
|
|
|
196
210
|
"tests/spawn-liveness-banner.test.cjs",
|
|
197
211
|
"tests/state-document.test.cjs",
|
|
198
212
|
"tests/state-transition.test.cjs",
|
|
213
|
+
"tests/state.platform.test.cjs",
|
|
199
214
|
"tests/state.test.cjs",
|
|
200
215
|
"tests/todos-workstream-scope.test.cjs",
|
|
201
216
|
"tests/tracer-bullet.test.cjs",
|
|
217
|
+
"tests/uat-complete-session.test.cjs",
|
|
202
218
|
"tests/uat-predicate.test.cjs",
|
|
203
219
|
"tests/uat.test.cjs",
|
|
220
|
+
"tests/ui-auditor-screenshot-block.test.cjs",
|
|
204
221
|
"tests/ui-interaction-capture.test.cjs",
|
|
205
222
|
"tests/ui-safety-gate.test.cjs",
|
|
206
223
|
"tests/ui-spec-inventory-provenance.test.cjs",
|
|
@@ -209,6 +226,7 @@ module.exports = {
|
|
|
209
226
|
"tests/unusable-input.test.cjs",
|
|
210
227
|
"tests/update-custom-backup.test.cjs",
|
|
211
228
|
"tests/user-artifact-staging.test.cjs",
|
|
229
|
+
"tests/verification-append-audit.test.cjs",
|
|
212
230
|
"tests/verification-overrides.test.cjs",
|
|
213
231
|
"tests/verification-status.test.cjs",
|
|
214
232
|
"tests/verify-archive-dirs-live-path.test.cjs",
|
|
@@ -50,8 +50,9 @@
|
|
|
50
50
|
// repo's `engines.node` requires >=24.0.0 (package.json), where both
|
|
51
51
|
// contracts have been stable since Node 20.
|
|
52
52
|
//
|
|
53
|
-
// Kept intentionally tiny: only the
|
|
54
|
-
// handled — `test:
|
|
53
|
+
// Kept intentionally tiny: only the event types run-tests.cjs needs are
|
|
54
|
+
// handled — per-file `test:summary` (#5071, see the loop) plus these five:
|
|
55
|
+
// `test:enqueue`/`test:dequeue` (emitted by the RUNNER as it queues
|
|
55
56
|
// and begins each spawned test-file child, independent of whether anything
|
|
56
57
|
// inside that file ever completes) plus `test:start`/`test:pass`/`test:fail`
|
|
57
58
|
// (emitted per-subtest, once the child reports it). `test:dequeue` is the
|
|
@@ -94,13 +95,19 @@ module.exports = async function ndjsonEventReporter(source) {
|
|
|
94
95
|
event.type === 'test:pass' ||
|
|
95
96
|
event.type === 'test:fail'
|
|
96
97
|
) {
|
|
97
|
-
const { file, name, nesting, testNumber } = event.data || {};
|
|
98
|
+
const { file, name, nesting, testNumber, details } = event.data || {};
|
|
99
|
+
// #4031: `kind` is node:test's `details.type` ('suite' for a suite,
|
|
100
|
+
// otherwise a test). run-tests.cjs's per-chunk accounting counts the
|
|
101
|
+
// pass/fail events that are NOT suites and compares them with the
|
|
102
|
+
// registration ledger (scripts/lib/registration-ledger-preload.cjs).
|
|
103
|
+
const kind = details && typeof details.type === 'string' ? details.type : undefined;
|
|
98
104
|
const line = `${JSON.stringify({
|
|
99
105
|
type: event.type,
|
|
100
106
|
file,
|
|
101
107
|
name,
|
|
102
108
|
nesting,
|
|
103
109
|
testNumber,
|
|
110
|
+
kind,
|
|
104
111
|
ts: Date.now(),
|
|
105
112
|
})}\n`;
|
|
106
113
|
try {
|
|
@@ -109,6 +116,24 @@ module.exports = async function ndjsonEventReporter(source) {
|
|
|
109
116
|
// Best-effort: a write failure here (e.g. the events dir vanished)
|
|
110
117
|
// must never crash the test run this reporter is only observing.
|
|
111
118
|
}
|
|
119
|
+
} else if (event.type === 'test:summary' && typeof (event.data || {}).file === 'string') {
|
|
120
|
+
// #5071: node:test emits one `test:summary` per test FILE (its
|
|
121
|
+
// `duration_ms` is that file's wall-clock) plus a run-level one with no
|
|
122
|
+
// `file`. Only the per-file ones are recorded: run-tests.cjs exports
|
|
123
|
+
// them, when asked, as the raw input for a per-platform timing table
|
|
124
|
+
// (scripts/gen-test-timings.cjs --platform). The run-level summary is
|
|
125
|
+
// not a file measurement and is skipped here.
|
|
126
|
+
const line = `${JSON.stringify({
|
|
127
|
+
type: event.type,
|
|
128
|
+
file: event.data.file,
|
|
129
|
+
duration_ms: event.data.duration_ms,
|
|
130
|
+
ts: Date.now(),
|
|
131
|
+
})}\n`;
|
|
132
|
+
try {
|
|
133
|
+
require('fs').appendFileSync(eventsPath, line);
|
|
134
|
+
} catch {
|
|
135
|
+
// Best-effort, as above.
|
|
136
|
+
}
|
|
112
137
|
}
|
|
113
138
|
}
|
|
114
139
|
// Falls through to an implicit `return undefined` (nully): this reporter is
|
|
@@ -14,7 +14,9 @@ module.exports = {
|
|
|
14
14
|
"tests/assumption-delta-checkpoint-e2e.test.cjs",
|
|
15
15
|
"tests/assumption-delta.test.cjs",
|
|
16
16
|
"tests/audit-command-cutover.test.cjs",
|
|
17
|
+
"tests/audit-workstream-layouts.test.cjs",
|
|
17
18
|
"tests/augment-upgrades.test.cjs",
|
|
19
|
+
"tests/blocking-guard-budget-parity.test.cjs",
|
|
18
20
|
"tests/broken-windows.test.cjs",
|
|
19
21
|
"tests/capability-cli.test.cjs",
|
|
20
22
|
"tests/capability-command-dispatch.test.cjs",
|
|
@@ -32,6 +34,8 @@ module.exports = {
|
|
|
32
34
|
"tests/check-gap-analysis-plan-post-e2e.test.cjs",
|
|
33
35
|
"tests/check-glossary-refs.test.cjs",
|
|
34
36
|
"tests/check-predicate.test.cjs",
|
|
37
|
+
"tests/check-router-cutover-equivalence.test.cjs",
|
|
38
|
+
"tests/check-router-gate-boundaries.test.cjs",
|
|
35
39
|
"tests/check-tdd-review-checkpoint-e2e.test.cjs",
|
|
36
40
|
"tests/check-ui-safety-gate.test.cjs",
|
|
37
41
|
"tests/check-update-config-dir.test.cjs",
|
|
@@ -53,7 +57,7 @@ module.exports = {
|
|
|
53
57
|
"tests/codex-config.test.cjs",
|
|
54
58
|
"tests/codex-inherit-smoke.test.cjs",
|
|
55
59
|
"tests/command-routing-hub.test.cjs",
|
|
56
|
-
"tests/commands.test.cjs",
|
|
60
|
+
"tests/commands.platform.test.cjs",
|
|
57
61
|
"tests/commit-files-deletion.test.cjs",
|
|
58
62
|
"tests/commit-files-pathspec.test.cjs",
|
|
59
63
|
"tests/commonjs-marker.test.cjs",
|
|
@@ -63,17 +67,21 @@ module.exports = {
|
|
|
63
67
|
"tests/config-get-default.test.cjs",
|
|
64
68
|
"tests/config-loader.test.cjs",
|
|
65
69
|
"tests/config-schema.property.test.cjs",
|
|
66
|
-
"tests/config.test.cjs",
|
|
70
|
+
"tests/config.platform.test.cjs",
|
|
67
71
|
"tests/configured-entrypoint-validation.test.cjs",
|
|
72
|
+
"tests/context-drift.test.cjs",
|
|
68
73
|
"tests/copilot-install.test.cjs",
|
|
69
74
|
"tests/copilot-upgrades.test.cjs",
|
|
70
75
|
"tests/core-utils.test.cjs",
|
|
71
76
|
"tests/cursor-hook-workspace-roots.test.cjs",
|
|
72
77
|
"tests/cursor-hooks.test.cjs",
|
|
73
78
|
"tests/cursor-subagent-isolation.test.cjs",
|
|
79
|
+
"tests/debug-session-management.test.cjs",
|
|
74
80
|
"tests/dispatch-identity.test.cjs",
|
|
75
81
|
"tests/dispatcher.test.cjs",
|
|
76
82
|
"tests/drift-detection.test.cjs",
|
|
83
|
+
"tests/drift-whole-change-set.test.cjs",
|
|
84
|
+
"tests/effort-local-install.test.cjs",
|
|
77
85
|
"tests/effort-surface-axis.test.cjs",
|
|
78
86
|
"tests/effort-sync-installed-runtime.test.cjs",
|
|
79
87
|
"tests/emitted-ack-trailer.test.cjs",
|
|
@@ -95,6 +103,16 @@ module.exports = {
|
|
|
95
103
|
"tests/features-index-gate.test.cjs",
|
|
96
104
|
"tests/frontmatter.test.cjs",
|
|
97
105
|
"tests/gap-checker.property.test.cjs",
|
|
106
|
+
"tests/gate-api-coverage-verify-pre-escape.test.cjs",
|
|
107
|
+
"tests/gate-consumer-exit-awareness.test.cjs",
|
|
108
|
+
"tests/gate-decision-coverage-verify-stderr.test.cjs",
|
|
109
|
+
"tests/gate-exit.test.cjs",
|
|
110
|
+
"tests/gate-tdd-red-evidence-containment.test.cjs",
|
|
111
|
+
"tests/gate-tdd-review-checkpoint-hardening.test.cjs",
|
|
112
|
+
"tests/gate-tdd-review-checkpoint.unit.test.cjs",
|
|
113
|
+
"tests/gate-ui-plan.unit.test.cjs",
|
|
114
|
+
"tests/gate-ui-safety.unit.test.cjs",
|
|
115
|
+
"tests/gate-verify-command-paths.unit.test.cjs",
|
|
98
116
|
"tests/gemini-runtime-removed.test.cjs",
|
|
99
117
|
"tests/gen-context-index.test.cjs",
|
|
100
118
|
"tests/gen-health-docs.test.cjs",
|
|
@@ -118,12 +136,12 @@ module.exports = {
|
|
|
118
136
|
"tests/helpers-cleanup.test.cjs",
|
|
119
137
|
"tests/helpers-process-isolation.test.cjs",
|
|
120
138
|
"tests/hermes-skills-migration.test.cjs",
|
|
139
|
+
"tests/hook-activation-probe.test.cjs",
|
|
121
140
|
"tests/hooks-commonjs-marker.test.cjs",
|
|
122
141
|
"tests/hooks-crash-policy.test.cjs",
|
|
123
142
|
"tests/hooks-opt-in.test.cjs",
|
|
124
143
|
"tests/host-integration.test.cjs",
|
|
125
144
|
"tests/init-manager.test.cjs",
|
|
126
|
-
"tests/init.test.cjs",
|
|
127
145
|
"tests/install-minimal-hooks.test.cjs",
|
|
128
146
|
"tests/install-nested-layout.test.cjs",
|
|
129
147
|
"tests/install-path-detection.test.cjs",
|
|
@@ -145,6 +163,7 @@ module.exports = {
|
|
|
145
163
|
"tests/kimi-agent-converter.test.cjs",
|
|
146
164
|
"tests/kimi-upgrades.test.cjs",
|
|
147
165
|
"tests/kimi-variant-disambiguation.test.cjs",
|
|
166
|
+
"tests/launcher-homes-derivation.test.cjs",
|
|
148
167
|
"tests/lint-phase-arg-assignment.test.cjs",
|
|
149
168
|
"tests/lint-workflow-shellcheck-fetch.test.cjs",
|
|
150
169
|
"tests/live-config-guard.test.cjs",
|
|
@@ -170,6 +189,7 @@ module.exports = {
|
|
|
170
189
|
"tests/no-unbounded-dirname-walk.rule.test.cjs",
|
|
171
190
|
"tests/no-unbounded-spawn.test.cjs",
|
|
172
191
|
"tests/no-unguarded-nonportable-exec.rule.test.cjs",
|
|
192
|
+
"tests/node-compile-cache.test.cjs",
|
|
173
193
|
"tests/npm-audit-baseline.test.cjs",
|
|
174
194
|
"tests/npm-integrity-gate.test.cjs",
|
|
175
195
|
"tests/nsegment-phase-grammar.test.cjs",
|
|
@@ -185,7 +205,7 @@ module.exports = {
|
|
|
185
205
|
"tests/phase-completion-single-owner.test.cjs",
|
|
186
206
|
"tests/phase-estimation.test.cjs",
|
|
187
207
|
"tests/phase-locator.test.cjs",
|
|
188
|
-
"tests/phase.test.cjs",
|
|
208
|
+
"tests/phase.platform.test.cjs",
|
|
189
209
|
"tests/phase6-capstone-conformance.test.cjs",
|
|
190
210
|
"tests/pi-config-dir-env-override.test.cjs",
|
|
191
211
|
"tests/plan-count-single-owner.test.cjs",
|
|
@@ -212,6 +232,7 @@ module.exports = {
|
|
|
212
232
|
"tests/profile-pipeline.test.cjs",
|
|
213
233
|
"tests/prohibition-enforcement.test.cjs",
|
|
214
234
|
"tests/project-root.test.cjs",
|
|
235
|
+
"tests/quick-batch-command-router.stdin.test.cjs",
|
|
215
236
|
"tests/quick-batch.test.cjs",
|
|
216
237
|
"tests/quick-branching.test.cjs",
|
|
217
238
|
"tests/quick-research.test.cjs",
|
|
@@ -238,15 +259,18 @@ module.exports = {
|
|
|
238
259
|
"tests/roadmap-parser.test.cjs",
|
|
239
260
|
"tests/roadmap-upgrade-bracket.test.cjs",
|
|
240
261
|
"tests/roadmap.test.cjs",
|
|
262
|
+
"tests/run-tests-accounting.test.cjs",
|
|
241
263
|
"tests/run-tests-harness.test.cjs",
|
|
242
264
|
"tests/run-tests-temp-root.test.cjs",
|
|
243
265
|
"tests/run-with-timeout.test.cjs",
|
|
244
266
|
"tests/runtime-artifact-layout-surface.test.cjs",
|
|
245
267
|
"tests/runtime-artifact-layout.test.cjs",
|
|
246
268
|
"tests/runtime-converters.test.cjs",
|
|
269
|
+
"tests/runtime-descriptor-owner.test.cjs",
|
|
247
270
|
"tests/runtime-homes-descriptor-drive.test.cjs",
|
|
248
271
|
"tests/runtime-identity.test.cjs",
|
|
249
272
|
"tests/runtime-launcher-parity.test.cjs",
|
|
273
|
+
"tests/schema-drift.test.cjs",
|
|
250
274
|
"tests/security.test.cjs",
|
|
251
275
|
"tests/settings-jsonc.test.cjs",
|
|
252
276
|
"tests/sh-hook-paths.test.cjs",
|
|
@@ -258,10 +282,12 @@ module.exports = {
|
|
|
258
282
|
"tests/skill-manifest.test.cjs",
|
|
259
283
|
"tests/slug-derivation-drift-guard.test.cjs",
|
|
260
284
|
"tests/state-todos-render.test.cjs",
|
|
261
|
-
"tests/state.test.cjs",
|
|
285
|
+
"tests/state.platform.test.cjs",
|
|
262
286
|
"tests/teams-status.test.cjs",
|
|
263
287
|
"tests/test-gate-watch-mode.test.cjs",
|
|
264
288
|
"tests/todos-workstream-scope.test.cjs",
|
|
289
|
+
"tests/uat-complete-session.test.cjs",
|
|
290
|
+
"tests/ui-auditor-screenshot-block.test.cjs",
|
|
265
291
|
"tests/ui-interaction-capture.test.cjs",
|
|
266
292
|
"tests/undo-commit-selection-4465.test.cjs",
|
|
267
293
|
"tests/undo-commit-selection.test.cjs",
|
|
@@ -270,9 +296,12 @@ module.exports = {
|
|
|
270
296
|
"tests/unusable-input.test.cjs",
|
|
271
297
|
"tests/update-custom-backup.test.cjs",
|
|
272
298
|
"tests/user-artifact-staging.test.cjs",
|
|
299
|
+
"tests/verification-append-audit.test.cjs",
|
|
273
300
|
"tests/verification-status.test.cjs",
|
|
274
301
|
"tests/verify-archive-dirs-live-path.test.cjs",
|
|
275
302
|
"tests/verify-command-grounding.test.cjs",
|
|
303
|
+
"tests/verify-lifecycle-writes-e2e.test.cjs",
|
|
304
|
+
"tests/verify-work-auto-transition.test.cjs",
|
|
276
305
|
"tests/verify.test.cjs",
|
|
277
306
|
"tests/windsurf-hooks-bridge.test.cjs",
|
|
278
307
|
"tests/workflow-guard.test.cjs",
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Registration ledger preload for scripts/run-tests.cjs (#4031).
|
|
4
|
+
//
|
|
5
|
+
// Why this exists. The runner passes `--test-force-exit` to every chunk (the
|
|
6
|
+
// Windows post-test hang backstop, #1051/#869). Under process isolation each
|
|
7
|
+
// test file's child streams its results to the `node --test` parent over a
|
|
8
|
+
// pipe, and a force-exit can end the parent while bytes of that pipe are still
|
|
9
|
+
// unread (nodejs/node#64833). The reporters never see the lost tail, so the
|
|
10
|
+
// run printed a smaller pass count and exited 0: a test that executed and
|
|
11
|
+
// passed (or failed) was indistinguishable from one that never existed.
|
|
12
|
+
//
|
|
13
|
+
// The parent cannot know what it did not receive, so the count of results the
|
|
14
|
+
// child produced has to come from the child, over a channel that does not
|
|
15
|
+
// share the pipe: this module is loaded into each test-file child with
|
|
16
|
+
// `--require` (`--test` forwards it to the file children) and counts the leaf
|
|
17
|
+
// `test:pass` / `test:fail` events the child's own reporter hands to the V8
|
|
18
|
+
// serializer that frames them onto that pipe, keyed by the `file` each event
|
|
19
|
+
// carries. When the child exits it appends one line per file to the file named
|
|
20
|
+
// by GSD_RUN_TESTS_LEDGER_FILE. The runner compares that per-file count with
|
|
21
|
+
// the leaf results its ndjson reporter actually received
|
|
22
|
+
// (analyzeChunkAccounting in run-tests.cjs) and fails the chunk when
|
|
23
|
+
// registered > reported.
|
|
24
|
+
//
|
|
25
|
+
// Why it taps the serializer and does NOT wrap `test()` / `it()`. node:test
|
|
26
|
+
// stamps every test with the location of the code that called it
|
|
27
|
+
// (`getCallerLocation()` in lib/internal/test_runner/harness.js) and reports
|
|
28
|
+
// that as the event's `file`. A wrapper around `test` is a JS frame between the
|
|
29
|
+
// test file and node:test, so every event would report THIS file as its
|
|
30
|
+
// location: spec-reporter failure locations would point here and no result
|
|
31
|
+
// could be matched back to its test file. Counting at the serializer adds no
|
|
32
|
+
// frame to the call and counts exactly what is put on the pipe, so the count
|
|
33
|
+
// and the parent's report are compared like for like: a skipped or todo test,
|
|
34
|
+
// a skipped suite and a test name/only filter need no special case
|
|
35
|
+
// (an excluded test emits no event on either side).
|
|
36
|
+
//
|
|
37
|
+
// Blind spots, stated plainly: a child that emits nothing counts 0 (no loss is
|
|
38
|
+
// visible); a SIGKILLed child never runs the `exit` handler below, so it leaves no
|
|
39
|
+
// ledger line; a file the parent reported but the ledger never saw is not flagged
|
|
40
|
+
// per file; and the whole count depends on node:test's child reporter framing its
|
|
41
|
+
// events through v8.DefaultSerializer.prototype.writeValue (true on Node 24). If a
|
|
42
|
+
// Node change moves that, every count becomes 0: the runner then fails a chunk whose
|
|
43
|
+
// ledger counted 0 while its reporter received results (analyzeChunkAccounting,
|
|
44
|
+
// `ledgerCountedNothing`), and tests/run-tests-accounting.test.cjs pins the hook.
|
|
45
|
+
//
|
|
46
|
+
// Inert unless it is inside a test-file child (NODE_TEST_CONTEXT is set by
|
|
47
|
+
// `node --test` for those, not for the runner parent), so requiring it anywhere
|
|
48
|
+
// else is a no-op. There it does two things: it makes the child's stdout pipe
|
|
49
|
+
// blocking (blockChildStdout: this is what stops `--test-force-exit` from
|
|
50
|
+
// discarding queued results, the loss this accounting exists to detect), and,
|
|
51
|
+
// when a ledger path was supplied, counts results. Never throws into the code it
|
|
52
|
+
// observes.
|
|
53
|
+
|
|
54
|
+
const fs = require('fs');
|
|
55
|
+
const path = require('path');
|
|
56
|
+
const { DefaultSerializer } = require('v8');
|
|
57
|
+
|
|
58
|
+
const RESULT_TYPES = new Set(['test:pass', 'test:fail']);
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The file a reporter event counts toward, or null when the event is not a leaf test result the
|
|
62
|
+
* runner's ndjson reporter would record (anything but a pass/fail, a suite, an event with no file).
|
|
63
|
+
* analyzeChunkAccounting applies the same three conditions to the events it reads back.
|
|
64
|
+
*/
|
|
65
|
+
function resultFileOf(item) {
|
|
66
|
+
if (item === null || typeof item !== 'object' || !RESULT_TYPES.has(item.type)) return null;
|
|
67
|
+
const data = item.data;
|
|
68
|
+
if (data === null || typeof data !== 'object' || typeof data.file !== 'string') return null;
|
|
69
|
+
if (data.details && data.details.type === 'suite') return null;
|
|
70
|
+
return data.file;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* One spelling for every ledger line: the real path. node reports a result's `file` already resolved
|
|
75
|
+
* through symlinks (macOS /var -> /private/var), while a zero-result child's only name is process.argv[1],
|
|
76
|
+
* as given, so without this the two kinds of line disagree on the same file. Best-effort: a path that cannot
|
|
77
|
+
* be resolved keeps its absolute spelling (analyzeChunkAccounting normalizes both sides again regardless).
|
|
78
|
+
*/
|
|
79
|
+
function canonicalPath(file) {
|
|
80
|
+
const absolute = path.resolve(file);
|
|
81
|
+
try {
|
|
82
|
+
return fs.realpathSync.native(absolute);
|
|
83
|
+
} catch {
|
|
84
|
+
return absolute;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function install(ledgerPath,serializerPrototype = DefaultSerializer.prototype) {
|
|
89
|
+
const counts = new Map(); // file -> leaf results handed to the serializer
|
|
90
|
+
|
|
91
|
+
const original = serializerPrototype.writeValue;
|
|
92
|
+
serializerPrototype.writeValue = function writeValueCountingResults(value) {
|
|
93
|
+
try {
|
|
94
|
+
const file = resultFileOf(value);
|
|
95
|
+
if (file !== null) counts.set(file, (counts.get(file) || 0) + 1);
|
|
96
|
+
} catch {
|
|
97
|
+
// Counting must never change what is serialized.
|
|
98
|
+
}
|
|
99
|
+
return Reflect.apply(original, this, arguments);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
process.on('exit', () => {
|
|
103
|
+
try {
|
|
104
|
+
// A child that produced no result still records itself (count 0), so the runner can tell
|
|
105
|
+
// "the preload ran and saw nothing" from "the preload never ran".
|
|
106
|
+
if (counts.size === 0 && process.argv[1]) counts.set(process.argv[1], 0);
|
|
107
|
+
const lines = [];
|
|
108
|
+
for (const [file, count] of counts) {
|
|
109
|
+
lines.push(JSON.stringify({ type: 'registered', file: canonicalPath(file), count }));
|
|
110
|
+
}
|
|
111
|
+
fs.appendFileSync(ledgerPath, `${lines.join('\n')}\n`);
|
|
112
|
+
} catch {
|
|
113
|
+
// Best-effort: the ledger is a diagnostic channel and must never change
|
|
114
|
+
// the exit status of the test file it observes.
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Make the test-file child's stdout (the pipe its results travel to the `node --test` parent on)
|
|
121
|
+
* blocking, so every frame it wrote has reached the OS when the child exits.
|
|
122
|
+
*
|
|
123
|
+
* Why: the runner passes `--test-force-exit`, and node forwards it to each file child. A forced
|
|
124
|
+
* child calls process.exit() as soon as its root test ends; its stdout is a non-blocking pipe on
|
|
125
|
+
* POSIX, so frames still queued in the Socket are discarded and the parent never receives those
|
|
126
|
+
* results (nodejs/node#64833; the fix proposed there, nodejs/node#64875, does exactly this with
|
|
127
|
+
* `_handle.setBlocking(true)` at force-exit). Measured on Node 24.18 / Linux with 20 files x 300
|
|
128
|
+
* tests, `--test-force-exit --test-concurrency=8`: 5039-5139 of 6000 results reported without
|
|
129
|
+
* this, 6000 of 6000 with it (and 6000 without force-exit). Doing it at load time rather than at
|
|
130
|
+
* exit means nothing is ever queued. The Windows hang guard that force-exit exists for (#1051)
|
|
131
|
+
* is untouched. Best-effort: a stdout with no pipe handle (a file, a TTY) is left alone.
|
|
132
|
+
*/
|
|
133
|
+
function blockChildStdout(stdout) {
|
|
134
|
+
try {
|
|
135
|
+
const target = stdout === undefined ? process.stdout : stdout;
|
|
136
|
+
const handle = target && target._handle;
|
|
137
|
+
if (handle && typeof handle.setBlocking === 'function') {
|
|
138
|
+
handle.setBlocking(true);
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
} catch {
|
|
142
|
+
// Never throw into the test file this observes.
|
|
143
|
+
}
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Inside a test-file child only (NODE_TEST_CONTEXT is set by `node --test` for those, not for the
|
|
148
|
+
// runner parent): the blocking stdout needs no ledger path; the ledger count needs one.
|
|
149
|
+
if (process.env.NODE_TEST_CONTEXT) {
|
|
150
|
+
blockChildStdout();
|
|
151
|
+
const ledgerPath = process.env.GSD_RUN_TESTS_LEDGER_FILE;
|
|
152
|
+
if (ledgerPath) install(ledgerPath);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
module.exports = { install, resultFileOf, blockChildStdout };
|