@opengsd/gsd-core 1.10.0 → 1.12.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/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-debug-session-manager.md +12 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-dom-verifier.md +169 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +22 -14
- package/agents/gsd-framework-selector.md +1 -3
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +5 -3
- package/agents/gsd-pattern-mapper.md +11 -0
- package/agents/gsd-phase-researcher.md +23 -2
- package/agents/gsd-plan-checker.md +50 -53
- package/agents/gsd-planner.md +50 -50
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.md +2 -2
- package/agents/gsd-roadmapper.md +15 -11
- package/agents/gsd-ui-checker.md +63 -4
- package/agents/gsd-ui-researcher.md +41 -3
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +13 -4
- package/bin/install.js +1448 -1103
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/discuss-phase.md +1 -1
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/import.md +1 -1
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/quick.md +9 -5
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +1035 -138
- package/gsd-core/bin/lib/active-workstream-store.cjs +146 -22
- package/gsd-core/bin/lib/adr-parser.cjs +13 -7
- package/gsd-core/bin/lib/agent-install-check.cjs +392 -32
- package/gsd-core/bin/lib/api-coverage.cjs +33 -14
- package/gsd-core/bin/lib/artifacts.cjs +5 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +32 -15
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +1026 -268
- package/gsd-core/bin/lib/broken-windows.cjs +306 -28
- package/gsd-core/bin/lib/capability-consent.cjs +149 -15
- package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
- package/gsd-core/bin/lib/capability-lock.cjs +10 -4
- package/gsd-core/bin/lib/capability-registry.cjs +845 -130
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-state.cjs +18 -3
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +700 -40
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +216 -42
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/cli-exit.cjs +496 -10
- package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +735 -0
- package/gsd-core/bin/lib/command-aliases.cjs +22 -0
- package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
- package/gsd-core/bin/lib/commands.cjs +1172 -108
- package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
- package/gsd-core/bin/lib/complexity-trigger.cjs +1192 -0
- package/gsd-core/bin/lib/config-loader.cjs +187 -23
- package/gsd-core/bin/lib/config.cjs +102 -3
- package/gsd-core/bin/lib/configuration.cjs +129 -37
- package/gsd-core/bin/lib/core-utils.cjs +208 -33
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/edge-probe.cjs +9 -1
- package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
- package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +899 -229
- package/gsd-core/bin/lib/gap-checker.cjs +95 -10
- package/gsd-core/bin/lib/git-base-branch.cjs +276 -39
- package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
- package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +149 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +268 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +187 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +451 -0
- package/gsd-core/bin/lib/host-integration.cjs +39 -6
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init-command-router.cjs +118 -21
- package/gsd-core/bin/lib/init.cjs +439 -168
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +811 -259
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +235 -0
- package/gsd-core/bin/lib/install-profiles.cjs +212 -61
- package/gsd-core/bin/lib/install-scope.cjs +270 -0
- package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
- package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
- package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
- package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +148 -38
- package/gsd-core/bin/lib/intel.cjs +101 -26
- package/gsd-core/bin/lib/io.cjs +170 -15
- package/gsd-core/bin/lib/learnings.cjs +85 -14
- package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
- package/gsd-core/bin/lib/markdown-table.cjs +183 -22
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +842 -73
- package/gsd-core/bin/lib/model-catalog.cjs +232 -16
- package/gsd-core/bin/lib/model-resolver.cjs +193 -68
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +18 -9
- package/gsd-core/bin/lib/phase-id.cjs +514 -40
- package/gsd-core/bin/lib/phase-lifecycle.cjs +52 -19
- package/gsd-core/bin/lib/phase-locator.cjs +262 -34
- package/gsd-core/bin/lib/phase.cjs +1038 -214
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
- package/gsd-core/bin/lib/plan-document.cjs +263 -0
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +98 -3
- package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +894 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +112 -6
- package/gsd-core/bin/lib/probe-core.cjs +5 -2
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
- package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
- package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +766 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +22 -13
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +59 -11
- package/gsd-core/bin/lib/roadmap-parser.cjs +1006 -184
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +442 -96
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +702 -52
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +459 -55
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +402 -58
- package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +96 -8
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +342 -7
- package/gsd-core/bin/lib/smart-entry.cjs +133 -23
- package/gsd-core/bin/lib/spec-section.cjs +12 -7
- package/gsd-core/bin/lib/state-command-router.cjs +52 -19
- package/gsd-core/bin/lib/state-contract.cjs +359 -0
- package/gsd-core/bin/lib/state-document.cjs +338 -8
- package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
- package/gsd-core/bin/lib/state-transition.cjs +846 -176
- package/gsd-core/bin/lib/state.cjs +2589 -369
- package/gsd-core/bin/lib/surface.cjs +33 -11
- package/gsd-core/bin/lib/task-command-router.cjs +111 -1
- package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
- package/gsd-core/bin/lib/teams-status.cjs +4 -1
- package/gsd-core/bin/lib/text-lines.cjs +80 -0
- package/gsd-core/bin/lib/token-scanner.cjs +76 -0
- package/gsd-core/bin/lib/uat-predicate.cjs +67 -23
- package/gsd-core/bin/lib/uat.cjs +1761 -167
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +51 -12
- package/gsd-core/bin/lib/unusable-input.cjs +37 -0
- package/gsd-core/bin/lib/update-context.cjs +8 -2
- package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
- package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
- package/gsd-core/bin/lib/validate.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +75 -0
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
- package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
- package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +272 -9
- package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
- package/gsd-core/bin/lib/verify.cjs +453 -918
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
- package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
- package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
- package/gsd-core/bin/lib/workstream.cjs +2 -2
- package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
- package/gsd-core/bin/lib/worktree-safety.cjs +341 -18
- package/gsd-core/bin/shared/config-defaults.manifest.json +8 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +12 -1
- package/gsd-core/bin/shared/exit-codes.json +8 -0
- package/gsd-core/bin/shared/exit-codes.sh +20 -0
- package/gsd-core/bin/shared/model-catalog.json +8 -1
- package/gsd-core/references/agent-contracts.md +44 -26
- package/gsd-core/references/api-coverage.md +24 -2
- package/gsd-core/references/autonomous-smart-discuss.md +3 -3
- package/gsd-core/references/checkpoints.md +39 -21
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/decimal-phase-calculation.md +5 -5
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/edge-probe.md +8 -0
- package/gsd-core/references/execute-mvp-tdd.md +4 -6
- package/gsd-core/references/execute-phase-between-wave-reset.md +15 -14
- package/gsd-core/references/execute-phase-context-guard.md +1 -1
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/execute-phase-wave-guard.md +17 -11
- package/gsd-core/references/failing-direction.md +78 -0
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-integration.md +5 -5
- package/gsd-core/references/git-planning-commit.md +5 -4
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +61 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/nyquist-compliance.md +74 -0
- package/gsd-core/references/offer-next.md +3 -5
- package/gsd-core/references/phase-argument-parsing.md +3 -3
- package/gsd-core/references/planner-failing-direction.md +53 -0
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-human-verify-mode.md +15 -1
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planner-revision.md +1 -1
- package/gsd-core/references/planner-verify-command-grounding.md +17 -0
- package/gsd-core/references/planning-config.md +44 -13
- package/gsd-core/references/reviewer-instances.md +31 -0
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/runtime-aware-dispatch.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +1 -1
- package/gsd-core/references/tdd.md +1 -3
- package/gsd-core/references/ui-brand.md +65 -21
- package/gsd-core/references/ui-consideration-probe.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +5 -5
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verify-command-path-resolvability.md +42 -0
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -17
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/SECURITY.md +3 -3
- package/gsd-core/templates/UI-SPEC.md +25 -3
- package/gsd-core/templates/VALIDATION.md +3 -3
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +5 -4
- package/gsd-core/templates/state.md +11 -4
- package/gsd-core/templates/verification-report.md +9 -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 +3 -3
- package/gsd-core/workflows/add-tests.md +3 -8
- package/gsd-core/workflows/add-todo.md +1 -1
- package/gsd-core/workflows/ai-integration-phase.md +13 -20
- package/gsd-core/workflows/audit-fix.md +12 -3
- package/gsd-core/workflows/audit-milestone.md +9 -9
- package/gsd-core/workflows/audit-uat.md +17 -2
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
- package/gsd-core/workflows/autonomous.md +11 -27
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +64 -5
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +14 -4
- package/gsd-core/workflows/code-review-fix.md +38 -11
- package/gsd-core/workflows/code-review.md +159 -52
- package/gsd-core/workflows/complete-milestone.md +151 -23
- package/gsd-core/workflows/debug.md +12 -8
- package/gsd-core/workflows/diagnose-issues.md +47 -15
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -8
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +3 -6
- package/gsd-core/workflows/docs-update.md +5 -4
- package/gsd-core/workflows/edit-phase.md +27 -2
- package/gsd-core/workflows/eval-review.md +7 -14
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +142 -15
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +24 -4
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
- package/gsd-core/workflows/execute-phase.md +72 -100
- package/gsd-core/workflows/execute-plan.md +52 -15
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +5 -5
- package/gsd-core/workflows/health.md +76 -10
- package/gsd-core/workflows/import.md +18 -15
- package/gsd-core/workflows/inbox.md +4 -5
- package/gsd-core/workflows/ingest-docs.md +49 -16
- package/gsd-core/workflows/insert-phase.md +5 -5
- package/gsd-core/workflows/list-seeds.md +5 -3
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +12 -23
- package/gsd-core/workflows/map-codebase.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +8 -5
- package/gsd-core/workflows/new-milestone.md +22 -29
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +26 -40
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +14 -2
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
- package/gsd-core/workflows/plan-phase.md +162 -59
- package/gsd-core/workflows/plan-review-convergence.md +96 -11
- package/gsd-core/workflows/plant-seed.md +2 -2
- package/gsd-core/workflows/pr-branch.md +187 -51
- package/gsd-core/workflows/profile-user.md +16 -14
- package/gsd-core/workflows/progress.md +61 -18
- package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +5 -7
- package/gsd-core/workflows/quick/steps/quick-verification.md +28 -9
- package/gsd-core/workflows/quick/steps/research-phase.md +4 -6
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
- package/gsd-core/workflows/quick.md +55 -44
- package/gsd-core/workflows/remove-phase.md +4 -4
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +8 -12
- package/gsd-core/workflows/review.md +219 -20
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +3 -3
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings-advanced.md +7 -9
- package/gsd-core/workflows/settings-integrations.md +64 -31
- package/gsd-core/workflows/settings.md +69 -7
- package/gsd-core/workflows/ship.md +116 -50
- package/gsd-core/workflows/sketch-wrap-up.md +11 -17
- package/gsd-core/workflows/sketch.md +12 -18
- package/gsd-core/workflows/smart-entry.md +3 -5
- package/gsd-core/workflows/spec-phase.md +53 -13
- package/gsd-core/workflows/spike-wrap-up.md +7 -11
- package/gsd-core/workflows/spike.md +20 -31
- package/gsd-core/workflows/stats.md +2 -2
- package/gsd-core/workflows/sync-skills.md +64 -9
- package/gsd-core/workflows/thread.md +11 -7
- package/gsd-core/workflows/transition.md +49 -14
- package/gsd-core/workflows/ui-phase.md +15 -21
- package/gsd-core/workflows/ui-review.md +8 -12
- package/gsd-core/workflows/ultraplan-phase.md +5 -13
- package/gsd-core/workflows/undo.md +8 -16
- package/gsd-core/workflows/update.md +7 -11
- package/gsd-core/workflows/validate-phase.md +3 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +66 -25
- package/hooks/dist/gsd-agent-isolation-guard.js +158 -30
- package/hooks/dist/gsd-check-update-worker.js +56 -13
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-config-reload.js +18 -12
- package/hooks/dist/gsd-context-monitor.js +19 -10
- package/hooks/dist/gsd-cursor-post-tool.js +3 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +2 -3
- package/hooks/dist/gsd-cursor-session-start.js +2 -1
- package/hooks/dist/gsd-cursor-stop.js +2 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +83 -3
- package/hooks/dist/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
- package/hooks/dist/gsd-graphify-update.sh +22 -18
- package/hooks/dist/gsd-node-runner.sh +76 -0
- package/hooks/dist/gsd-phase-boundary.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +37 -27
- package/hooks/dist/gsd-read-guard.js +16 -7
- package/hooks/dist/gsd-read-injection-scanner.js +55 -32
- package/hooks/dist/gsd-session-state.sh +1 -0
- package/hooks/dist/gsd-statusline.js +231 -24
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-validate-commit.sh +80 -6
- package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
- package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
- package/hooks/dist/gsd-workflow-guard.js +162 -46
- package/hooks/dist/gsd-worktree-path-guard.js +36 -21
- package/hooks/dist/gsd-write-guard.js +35 -25
- package/hooks/dist/lib/cli-exit.js +560 -0
- package/hooks/dist/lib/exit-code-registry.js +98 -0
- package/hooks/dist/lib/git-cmd.js +92 -59
- package/hooks/dist/lib/git-probe.js +84 -0
- package/hooks/dist/lib/hook-exit.js +81 -0
- package/hooks/dist/lib/injection-patterns.js +45 -0
- package/hooks/dist/lib/isolation-deny-reason.js +39 -0
- package/hooks/dist/lib/isolation-sentinel.js +9 -0
- package/hooks/dist/managed-hooks-registry.cjs +3 -0
- package/hooks/gsd-agent-isolation-guard.js +158 -30
- package/hooks/gsd-check-update-worker.js +56 -13
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-config-reload.js +18 -12
- package/hooks/gsd-context-monitor.js +19 -10
- package/hooks/gsd-cursor-post-tool.js +3 -1
- package/hooks/gsd-cursor-pre-tool.js +2 -3
- package/hooks/gsd-cursor-session-start.js +2 -1
- package/hooks/gsd-cursor-stop.js +2 -1
- package/hooks/gsd-cursor-subagent-start.js +83 -3
- package/hooks/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/gsd-ensure-canonical-path.js +2 -1
- package/hooks/gsd-graphify-update.sh +22 -18
- package/hooks/gsd-node-runner.sh +76 -0
- package/hooks/gsd-phase-boundary.sh +1 -0
- package/hooks/gsd-prompt-guard.js +37 -27
- package/hooks/gsd-read-guard.js +16 -7
- package/hooks/gsd-read-injection-scanner.js +55 -32
- package/hooks/gsd-session-state.sh +1 -0
- package/hooks/gsd-statusline.js +231 -24
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-validate-commit.sh +80 -6
- package/hooks/gsd-windsurf-pre-command.js +16 -11
- package/hooks/gsd-windsurf-pre-write.js +22 -13
- package/hooks/gsd-workflow-guard.js +162 -46
- package/hooks/gsd-worktree-path-guard.js +36 -21
- package/hooks/gsd-write-guard.js +35 -25
- package/hooks/lib/cli-exit.js +560 -0
- package/hooks/lib/exit-code-registry.js +98 -0
- package/hooks/lib/git-cmd.js +92 -59
- package/hooks/lib/git-probe.js +84 -0
- package/hooks/lib/hook-exit.js +81 -0
- package/hooks/lib/injection-patterns.js +45 -0
- package/hooks/lib/isolation-deny-reason.js +39 -0
- package/hooks/lib/isolation-sentinel.js +9 -0
- package/hooks/managed-hooks-registry.cjs +3 -0
- package/package.json +28 -11
- package/pi/gsd.cjs +19 -5
- package/scripts/base64-scan.sh +74 -12
- package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
- package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
- package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
- package/scripts/build-hooks.js +5 -0
- package/scripts/changeset/lint.cjs +60 -5
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/check-glossary-refs.cjs +77 -15
- package/scripts/check-mutation-score-ratchet.cjs +156 -0
- package/scripts/ci-check-job-near-cap.cjs +49 -0
- package/scripts/ci-pr-mergeability.cjs +262 -0
- package/scripts/ci-test-scope.cjs +64 -14
- package/scripts/ci-timeout-report.cjs +230 -0
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/docs-guard-registry.cjs +396 -0
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-registry.cjs +11 -21
- package/scripts/gen-context-index.cjs +2 -11
- package/scripts/gen-exit-code-docs.cjs +318 -0
- package/scripts/gen-exit-code-registry.cjs +891 -0
- package/scripts/gen-features.cjs +836 -0
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-hooks-cli-exit.cjs +239 -0
- package/scripts/gen-install-tree-fixtures.cjs +2 -2
- package/scripts/gen-inventory-manifest.cjs +50 -4
- package/scripts/gen-loop-host-contract.cjs +138 -25
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/gen-scripts-cli-exit.cjs +185 -0
- package/scripts/gen-state-md-docs.cjs +727 -0
- package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/ci-job-timing.cjs +72 -0
- package/scripts/lib/cli-exit.cjs +546 -44
- package/scripts/lib/drift-scan.cjs +308 -0
- package/scripts/lib/exit-code-registry.cjs +98 -0
- package/scripts/lib/ndjson-reporter.cjs +119 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
- package/scripts/lint-canary-version-leak.cjs +73 -0
- package/scripts/lint-command-contract.cjs +96 -13
- package/scripts/lint-completion-predicate-drift.cjs +933 -0
- package/scripts/lint-completion-ratio-drift.cjs +214 -0
- package/scripts/lint-default-flip-documentation.cjs +193 -0
- package/scripts/lint-docs-guard-registration.cjs +495 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +38 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +461 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
- package/scripts/lint-phase-enumeration-drift.cjs +492 -0
- package/scripts/lint-plan-count-drift.cjs +318 -0
- package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
- package/scripts/lint-planning-prompt-drift.cjs +471 -0
- package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
- package/scripts/lint-regression-test-names.cjs +15 -13
- package/scripts/lint-removed-but-needed.cjs +488 -0
- package/scripts/lint-seam-enforcement.cjs +182 -0
- package/scripts/lint-slug-derivation-drift.cjs +921 -0
- package/scripts/lint-source-test-name-collision.cjs +241 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +950 -0
- package/scripts/lint-test-file-count.allowlist.json +137 -8
- package/scripts/lint-test-file-count.cjs +25 -3
- package/scripts/lint-unreachable-guard-drift.cjs +830 -0
- package/scripts/lint-vendored-deps.cjs +297 -0
- package/scripts/mutation-matrix.cjs +599 -50
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +100 -14
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/secret-scan.sh +75 -13
- package/scripts/select-docs-guards.cjs +56 -0
- package/scripts/sync-runtime-launcher.cjs +24 -7
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-discuss-phase/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- package/skills/gsd-import/SKILL.md +1 -1
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +0 -1
- package/skills/gsd-progress/SKILL.md +0 -1
- package/skills/gsd-quick/SKILL.md +9 -5
- package/skills/gsd-review-backlog/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +0 -1
- package/skills/gsd-verify-work/SKILL.md +1 -1
- package/vscode/package.json +1 -1
- package/bin/lib/ui-safety-gate.cjs +0 -107
- package/gsd-core/workflows/discovery-phase.md +0 -298
- package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
- package/gsd-core/workflows/verify-phase.md +0 -574
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/lint-emitted-drift-ack.cjs +0 -344
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1051
|
@@ -39,6 +39,10 @@ const PROTECTED_WORKFLOWS = new Set([
|
|
|
39
39
|
'mutation.yml',
|
|
40
40
|
'security-scan.yml',
|
|
41
41
|
'release.yml',
|
|
42
|
+
// #3833: the reusable gate every `pull_request` compute lane depends on —
|
|
43
|
+
// marking it inert would let a change to the gate itself ship without ever
|
|
44
|
+
// running the full matrix it is responsible for enforcing.
|
|
45
|
+
'pr-mergeable-preflight.yml',
|
|
42
46
|
]);
|
|
43
47
|
for (const wf of PROTECTED_WORKFLOWS) {
|
|
44
48
|
if (INERT_WORKFLOWS.has(wf)) {
|
|
@@ -300,6 +304,23 @@ const RULES = [
|
|
|
300
304
|
'tests/require-fs-op-fallback.rule.test.cjs',
|
|
301
305
|
],
|
|
302
306
|
},
|
|
307
|
+
{
|
|
308
|
+
// ADR-3212 Phase 4 (#3415): no-unbounded-quantifier and the shared
|
|
309
|
+
// readfilesync-trace helper it uses (also now imported by
|
|
310
|
+
// no-crlf-fragile-split). NOT part of the ADR-1703 portability family above
|
|
311
|
+
// — kept as its own bucket so this rule's tests re-run without pulling in
|
|
312
|
+
// the ADR-1703 disable-ban / vocab-drift suites it is not governed by.
|
|
313
|
+
name: 'no-unbounded-quantifier + readfilesync-trace (ADR-3212 Phase 4)',
|
|
314
|
+
match: path => [
|
|
315
|
+
'eslint-rules/no-unbounded-quantifier.cjs',
|
|
316
|
+
'eslint-rules/lib/readfilesync-trace.cjs',
|
|
317
|
+
'eslint-rules/no-crlf-fragile-split.cjs',
|
|
318
|
+
].includes(path),
|
|
319
|
+
tests: [
|
|
320
|
+
'tests/no-unbounded-quantifier.rule.test.cjs',
|
|
321
|
+
'tests/readfilesync-trace-parity.test.cjs',
|
|
322
|
+
],
|
|
323
|
+
},
|
|
303
324
|
];
|
|
304
325
|
|
|
305
326
|
/**
|
|
@@ -324,19 +345,48 @@ function missingRuleTestFiles(rules) {
|
|
|
324
345
|
return [...referenced].filter(f => !existsSync(path.join(__dirname, '..', f))).sort();
|
|
325
346
|
}
|
|
326
347
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
)
|
|
337
|
-
|
|
348
|
+
/**
|
|
349
|
+
* Every PROTECTED_WORKFLOWS member that does not exist on disk.
|
|
350
|
+
* The name list and the real filenames are two surfaces over one fact
|
|
351
|
+
* (#3833): without this, renaming or deleting a gating workflow silently
|
|
352
|
+
* un-protects it and CI stays green while the protection is gone. Same
|
|
353
|
+
* shape and rationale as missingRuleTestFiles() above.
|
|
354
|
+
*/
|
|
355
|
+
function missingProtectedWorkflows(names = PROTECTED_WORKFLOWS) {
|
|
356
|
+
return [...names]
|
|
357
|
+
.filter(name => !existsSync(path.join(__dirname, '..', '.github', 'workflows', name)))
|
|
358
|
+
.sort();
|
|
338
359
|
}
|
|
339
360
|
|
|
361
|
+
/**
|
|
362
|
+
* Shared module-load assertion for the two "this list names something that
|
|
363
|
+
* does not exist on disk" guards above. Both are silent-coverage-hole guards:
|
|
364
|
+
* a name that no longer resolves stops selecting/protecting anything while CI
|
|
365
|
+
* stays green, so both must fail loudly at load rather than at test time.
|
|
366
|
+
*/
|
|
367
|
+
function assertNoneMissing(missing, summary, issueRef) {
|
|
368
|
+
if (missing.length === 0) return;
|
|
369
|
+
throw new Error(`ci-test-scope: ${summary} (${issueRef}):\n ${missing.join('\n ')}`);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Fail loudly at module load — this fires on EVERY invocation of the CLI
|
|
373
|
+
// (including the real `changes` job in .github/workflows/test.yml), not only
|
|
374
|
+
// when a test suite happens to run.
|
|
375
|
+
assertNoneMissing(
|
|
376
|
+
missingRuleTestFiles(RULES),
|
|
377
|
+
'RULES reference test file(s) that do not exist on disk (silent coverage hole)',
|
|
378
|
+
'see #2758',
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
// A PROTECTED_WORKFLOWS entry naming a file that does not exist means the
|
|
382
|
+
// workflow was renamed or deleted without updating this list, silently
|
|
383
|
+
// un-protecting it while CI stays green.
|
|
384
|
+
assertNoneMissing(
|
|
385
|
+
missingProtectedWorkflows(PROTECTED_WORKFLOWS),
|
|
386
|
+
'PROTECTED_WORKFLOWS reference workflow file(s) that do not exist on disk (silent protection hole)',
|
|
387
|
+
'see #3833',
|
|
388
|
+
);
|
|
389
|
+
|
|
340
390
|
function usage() {
|
|
341
391
|
return [
|
|
342
392
|
'Usage:',
|
|
@@ -474,8 +524,8 @@ function classify(files) {
|
|
|
474
524
|
// the scoped windows lane instead of triggering the three full parity
|
|
475
525
|
// lanes. (full_matrix fired on 15/15 sampled PRs because test-driven
|
|
476
526
|
// PRs always touch tests/, costing ~25 runner-minutes each.) Changed
|
|
477
|
-
// tests already run on
|
|
478
|
-
// residual macOS / windows
|
|
527
|
+
// tests already run on the two ubuntu-24 lanes via targeted_tests; the
|
|
528
|
+
// residual macOS / windows cross-product is covered by the full
|
|
479
529
|
// matrix on every push to next.
|
|
480
530
|
windows.add(file);
|
|
481
531
|
}
|
|
@@ -573,4 +623,4 @@ if (require.main === module) {
|
|
|
573
623
|
runMain(main);
|
|
574
624
|
}
|
|
575
625
|
|
|
576
|
-
module.exports = { RULES, missingRuleTestFiles };
|
|
626
|
+
module.exports = { RULES, missingRuleTestFiles, PROTECTED_WORKFLOWS, INERT_WORKFLOWS, missingProtectedWorkflows };
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* scripts/ci-timeout-report.cjs
|
|
5
|
+
*
|
|
6
|
+
* Scheduled CI-timeout trending report (#4036). Polls GitHub's Actions REST
|
|
7
|
+
* API for recently completed jobs across test.yml, mutation.yml, and
|
|
8
|
+
* install-smoke.yml, resolves each job's declared `timeout-minutes` budget,
|
|
9
|
+
* computes elapsed-vs-cap via scripts/lib/ci-job-timing.cjs, and appends
|
|
10
|
+
* new (never-before-seen) records to a JSONL history file. Every record also
|
|
11
|
+
* carries the triggering `runEvent` (e.g. `push`/`pull_request`) so entries
|
|
12
|
+
* for jobs whose matrix genuinely differs by trigger (e.g. `smoke`'s
|
|
13
|
+
* push-only macOS row) can be told apart in the persisted trend — records
|
|
14
|
+
* are never filtered by event, only labeled.
|
|
15
|
+
*
|
|
16
|
+
* Invoked from a GitHub Actions workflow via actions/github-script, e.g.:
|
|
17
|
+
* const report = require(`${process.env.GITHUB_WORKSPACE}/scripts/ci-timeout-report.cjs`);
|
|
18
|
+
* const result = await report.main({ github, context, core });
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const yaml = require('js-yaml');
|
|
22
|
+
const fs = require('node:fs');
|
|
23
|
+
const path = require('node:path');
|
|
24
|
+
const {
|
|
25
|
+
computeElapsedPct, isNearCap, formatNearCapNotice,
|
|
26
|
+
} = require('./lib/ci-job-timing.cjs');
|
|
27
|
+
|
|
28
|
+
const HISTORY_PATH = path.join(__dirname, '..', 'tests', 'ci-timeout-budget-history.jsonl');
|
|
29
|
+
const WORKFLOWS_DIR = path.join(__dirname, '..', '.github', 'workflows');
|
|
30
|
+
|
|
31
|
+
// Static job name → job-id rules, first match wins, checked in array order
|
|
32
|
+
// (test-inert before test, since both job names start with "test ").
|
|
33
|
+
const JOB_RULES = [
|
|
34
|
+
{ workflowFile: 'test.yml', jobKey: 'test-inert', test: (name) => name === 'test (inert CI)' },
|
|
35
|
+
{ workflowFile: 'test.yml', jobKey: 'test', test: (name) => name.startsWith('test (') && name !== 'test (inert CI)' },
|
|
36
|
+
{ workflowFile: 'test.yml', jobKey: 'test-full', test: (name) => name.startsWith('full test (') },
|
|
37
|
+
{ workflowFile: 'test.yml', jobKey: 'coverage-gate', test: (name) => name === 'Coverage gate (merged shards)' },
|
|
38
|
+
{ workflowFile: 'install-smoke.yml', jobKey: 'smoke', test: (name) => name.startsWith('smoke (') },
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
function resolveJobTimeoutMinutes({ jobName, workflowFile, workflowYamlText, covered }) {
|
|
42
|
+
if (workflowFile === 'mutation.yml') {
|
|
43
|
+
const m = jobName.match(/^Stryker \(([^)]+)\)$/);
|
|
44
|
+
if (!m) return null;
|
|
45
|
+
const moduleName = m[1];
|
|
46
|
+
if (!covered || !Object.prototype.hasOwnProperty.call(covered, moduleName)) return null;
|
|
47
|
+
return covered[moduleName].timeoutMinutes || 15;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const rule = JOB_RULES.find((r) => r.workflowFile === workflowFile && r.test(jobName));
|
|
51
|
+
if (!rule) return null;
|
|
52
|
+
|
|
53
|
+
const doc = yaml.load(workflowYamlText);
|
|
54
|
+
const budget = doc && doc.jobs && doc.jobs[rule.jobKey] ? doc.jobs[rule.jobKey]['timeout-minutes'] : undefined;
|
|
55
|
+
return typeof budget === 'number' ? budget : null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @param {{job: object, workflowFile: string, workflowYamlText: ?string, covered: ?object}} args
|
|
60
|
+
* `job.runEvent` is the triggering event (e.g. `push`/`pull_request`) — carried through to
|
|
61
|
+
* the returned record so entries whose matrix genuinely differs by trigger (e.g. `smoke`'s
|
|
62
|
+
* push-only macOS row) can be distinguished in the persisted history.
|
|
63
|
+
*/
|
|
64
|
+
function parseJobRecord({ job, workflowFile, workflowYamlText, covered }) {
|
|
65
|
+
if (!job.completed_at) return null;
|
|
66
|
+
|
|
67
|
+
const timeoutMinutes = resolveJobTimeoutMinutes({ jobName: job.name, workflowFile, workflowYamlText, covered });
|
|
68
|
+
if (timeoutMinutes == null) return null;
|
|
69
|
+
|
|
70
|
+
const { elapsedMs, pct } = computeElapsedPct({
|
|
71
|
+
startedAt: job.started_at, completedAt: job.completed_at, timeoutMinutes,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
runId: job.run_id,
|
|
76
|
+
jobName: job.name,
|
|
77
|
+
workflowFile,
|
|
78
|
+
sha: job.head_sha,
|
|
79
|
+
runEvent: job.runEvent,
|
|
80
|
+
completedAt: job.completed_at,
|
|
81
|
+
elapsedMs,
|
|
82
|
+
timeoutMinutes,
|
|
83
|
+
pct,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function buildReportLines(runs, { workflowFile, workflowYamlText, covered }) {
|
|
88
|
+
const records = [];
|
|
89
|
+
for (const { run, jobs } of runs) {
|
|
90
|
+
for (const job of jobs) {
|
|
91
|
+
const rec = parseJobRecord({
|
|
92
|
+
job: {
|
|
93
|
+
...job, run_id: run.id, head_sha: run.head_sha, runEvent: run.event,
|
|
94
|
+
},
|
|
95
|
+
workflowFile,
|
|
96
|
+
workflowYamlText,
|
|
97
|
+
covered,
|
|
98
|
+
});
|
|
99
|
+
if (rec) records.push(rec);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return records;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function dedupeAgainstHistory(newRecords, historyText) {
|
|
106
|
+
const seen = new Set();
|
|
107
|
+
for (const line of String(historyText || '').split('\n')) {
|
|
108
|
+
if (!line.trim()) continue;
|
|
109
|
+
try {
|
|
110
|
+
const rec = JSON.parse(line);
|
|
111
|
+
seen.add(`${rec.runId}::${rec.jobName}`);
|
|
112
|
+
} catch {
|
|
113
|
+
// Malformed history line — skip it rather than crash the whole report.
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return newRecords.filter((r) => !seen.has(`${r.runId}::${r.jobName}`));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function formatHistoryLine(record) {
|
|
120
|
+
return `${JSON.stringify(record)}\n`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const WORKFLOW_FILES = ['test.yml', 'mutation.yml', 'install-smoke.yml'];
|
|
124
|
+
const MAX_RUNS_PER_WORKFLOW = 15;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Orchestration entry point — impure, invoked from actions/github-script.
|
|
128
|
+
*
|
|
129
|
+
* @param {{github: object, context: object, core: object, historyPath?: string, fs?: object}} args
|
|
130
|
+
* @returns {Promise<{added: number, nearCap: number}>}
|
|
131
|
+
*/
|
|
132
|
+
async function main({
|
|
133
|
+
github, context, core, historyPath = HISTORY_PATH, fs: fsImpl = fs,
|
|
134
|
+
}) {
|
|
135
|
+
const { owner, repo } = context.repo;
|
|
136
|
+
const mutationMatrix = require('./mutation-matrix.cjs');
|
|
137
|
+
|
|
138
|
+
const allNewRecords = [];
|
|
139
|
+
|
|
140
|
+
for (const workflowFile of WORKFLOW_FILES) {
|
|
141
|
+
const covered = workflowFile === 'mutation.yml' ? mutationMatrix.COVERED : null;
|
|
142
|
+
const workflowYamlText = workflowFile === 'mutation.yml'
|
|
143
|
+
? null
|
|
144
|
+
: fsImpl.readFileSync(path.join(WORKFLOWS_DIR, workflowFile), 'utf8');
|
|
145
|
+
|
|
146
|
+
let runsList;
|
|
147
|
+
try {
|
|
148
|
+
runsList = await github.paginate(github.rest.actions.listWorkflowRuns, {
|
|
149
|
+
owner,
|
|
150
|
+
repo,
|
|
151
|
+
workflow_id: workflowFile,
|
|
152
|
+
status: 'completed',
|
|
153
|
+
per_page: 30,
|
|
154
|
+
});
|
|
155
|
+
} catch (err) {
|
|
156
|
+
core.warning(`ci-timeout-report: failed to list runs for ${workflowFile}: ${err.message}`);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const runs = runsList.slice(0, MAX_RUNS_PER_WORKFLOW);
|
|
161
|
+
const runsWithJobs = [];
|
|
162
|
+
|
|
163
|
+
for (const run of runs) {
|
|
164
|
+
try {
|
|
165
|
+
const jobs = await github.paginate(github.rest.actions.listJobsForWorkflowRun, {
|
|
166
|
+
owner,
|
|
167
|
+
repo,
|
|
168
|
+
run_id: run.id,
|
|
169
|
+
per_page: 50,
|
|
170
|
+
});
|
|
171
|
+
runsWithJobs.push({ run, jobs });
|
|
172
|
+
} catch (err) {
|
|
173
|
+
core.warning(`ci-timeout-report: failed to list jobs for ${workflowFile} run ${run.id}: ${err.message}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const records = buildReportLines(runsWithJobs, { workflowFile, workflowYamlText, covered });
|
|
178
|
+
allNewRecords.push(...records);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let historyText = '';
|
|
182
|
+
try {
|
|
183
|
+
historyText = fsImpl.readFileSync(historyPath, 'utf8');
|
|
184
|
+
} catch {
|
|
185
|
+
// First run — history file does not exist yet, treat as empty.
|
|
186
|
+
historyText = '';
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const deduped = dedupeAgainstHistory(allNewRecords, historyText);
|
|
190
|
+
|
|
191
|
+
if (deduped.length > 0) {
|
|
192
|
+
const newLines = deduped.map(formatHistoryLine).join('');
|
|
193
|
+
fsImpl.appendFileSync(historyPath, newLines);
|
|
194
|
+
}
|
|
195
|
+
// First-run bootstrap when there is nothing new to append is handled by
|
|
196
|
+
// `git add` picking up whatever the history file already contains.
|
|
197
|
+
|
|
198
|
+
let nearCapCount = 0;
|
|
199
|
+
for (const record of deduped) {
|
|
200
|
+
if (!isNearCap(record.pct)) continue;
|
|
201
|
+
nearCapCount += 1;
|
|
202
|
+
|
|
203
|
+
const notice = formatNearCapNotice({
|
|
204
|
+
label: `${record.jobName} (run ${record.runId})`,
|
|
205
|
+
pct: record.pct,
|
|
206
|
+
elapsedMs: record.elapsedMs,
|
|
207
|
+
capMs: record.timeoutMinutes * 60000,
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
core.warning(notice.warningLine.replace(/^::warning title=CI budget::/, ''));
|
|
211
|
+
|
|
212
|
+
if (core.summary) {
|
|
213
|
+
core.summary.addRaw(`${notice.summaryMarkdown}\n`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return { added: deduped.length, nearCap: nearCapCount };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
module.exports = {
|
|
221
|
+
HISTORY_PATH,
|
|
222
|
+
WORKFLOWS_DIR,
|
|
223
|
+
JOB_RULES,
|
|
224
|
+
resolveJobTimeoutMinutes,
|
|
225
|
+
parseJobRecord,
|
|
226
|
+
buildReportLines,
|
|
227
|
+
dedupeAgainstHistory,
|
|
228
|
+
formatHistoryLine,
|
|
229
|
+
main,
|
|
230
|
+
};
|