mandrel 1.94.0 → 2.1.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/.agents/README.md +116 -99
- package/.agents/agents/acceptance-critic.md +9 -7
- package/.agents/agents/story-worker.md +45 -51
- package/.agents/audit-checklists/performance.md +1 -1
- package/.agents/docs/SDLC.md +498 -1287
- package/.agents/docs/agentrc-reference.json +185 -80
- package/.agents/docs/configuration.md +132 -190
- package/.agents/docs/execution-reference.md +51 -25
- package/.agents/docs/quality-gates.md +25 -33
- package/.agents/docs/workflows.md +8 -8
- package/.agents/instructions.md +113 -139
- package/.agents/rules/ci-remediation.md +11 -15
- package/.agents/rules/git-conventions-reference.md +48 -58
- package/.agents/rules/git-conventions.md +16 -22
- package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
- package/.agents/schemas/agentrc.schema.json +83 -254
- package/.agents/schemas/audit-rules.json +59 -1
- package/.agents/schemas/audit-rules.schema.json +33 -1
- package/.agents/schemas/lifecycle/README.md +1 -2
- package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
- package/.agents/schemas/lifecycle/merge.flip-failed.schema.json +33 -0
- package/.agents/schemas/lifecycle/merge.unlanded.schema.json +1 -0
- package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
- package/.agents/schemas/lifecycle/story.merged.schema.json +1 -1
- package/.agents/schemas/signal-event.schema.json +3 -3
- package/.agents/schemas/story-deliver-terminal.schema.json +152 -0
- package/.agents/schemas/validation-evidence.schema.json +1 -1
- package/.agents/scripts/acceptance-eval.js +22 -66
- package/.agents/scripts/agents-bootstrap-github.js +1 -1
- package/.agents/scripts/audit-to-stories.js +7 -7
- package/.agents/scripts/boot-sweep.js +1 -1
- package/.agents/scripts/bootstrap.js +3 -3
- package/.agents/scripts/check-dead-exports.js +43 -104
- package/.agents/scripts/check-doc-links.js +2 -2
- package/.agents/scripts/check-lifecycle-lint.js +7 -10
- package/.agents/scripts/check-workflow-cli-lint.js +91 -0
- package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
- package/.agents/scripts/deliver-recover.js +122 -0
- package/.agents/scripts/drain-pending-cleanup.js +1 -1
- package/.agents/scripts/evidence-gate.js +20 -50
- package/.agents/scripts/generate-skills-index.js +17 -1
- package/.agents/scripts/generate-workflows-doc.js +4 -4
- package/.agents/scripts/lib/ITicketingProvider.js +1 -19
- package/.agents/scripts/lib/Logger.js +6 -10
- package/.agents/scripts/lib/audit-suite/runner.js +2 -2
- package/.agents/scripts/lib/audit-suite/selector.js +328 -28
- package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
- package/.agents/scripts/lib/baselines/kernel.js +206 -18
- package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -15
- package/.agents/scripts/lib/baselines/reader.js +1 -6
- package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
- package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +28 -33
- package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
- package/.agents/scripts/lib/bootstrap/manifest.js +8 -11
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +30 -53
- package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +0 -2
- package/.agents/scripts/lib/checks/core-bare-clean.js +6 -3
- package/.agents/scripts/lib/checks/index.js +3 -2
- package/.agents/scripts/lib/checks/loop-health.js +12 -11
- package/.agents/scripts/lib/checks/state.js +17 -248
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +26 -24
- package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +3 -4
- package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +2 -2
- package/.agents/scripts/lib/checks/worktree-residue-biome.js +3 -3
- package/.agents/scripts/lib/cli/standard-args.js +13 -22
- package/.agents/scripts/lib/cli-args.js +39 -9
- package/.agents/scripts/lib/close-validation/gates.js +15 -15
- package/.agents/scripts/lib/close-validation/projections/inputs.js +7 -7
- package/.agents/scripts/lib/close-validation/projections/maintainability.js +12 -12
- package/.agents/scripts/lib/close-validation/runner.js +13 -21
- package/.agents/scripts/lib/close-validation/telemetry.js +17 -8
- package/.agents/scripts/lib/config/ci.js +6 -31
- package/.agents/scripts/lib/config/delivery-routing.js +52 -35
- package/.agents/scripts/lib/config/explain.js +61 -48
- package/.agents/scripts/lib/config/github.js +7 -5
- package/.agents/scripts/lib/config/limits.js +29 -80
- package/.agents/scripts/lib/config/paths.js +0 -2
- package/.agents/scripts/lib/config/quality.js +12 -15
- package/.agents/scripts/lib/config/runners.js +20 -66
- package/.agents/scripts/lib/config/temp-paths.js +30 -63
- package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
- package/.agents/scripts/lib/config-resolver.js +2 -7
- package/.agents/scripts/lib/config-settings-schema-delivery.js +55 -161
- package/.agents/scripts/lib/config-settings-schema-quality.js +17 -16
- package/.agents/scripts/lib/config-settings-schema.js +100 -60
- package/.agents/scripts/lib/dead-exports-knip.js +105 -0
- package/.agents/scripts/lib/dead-exports-mode.js +51 -0
- package/.agents/scripts/lib/dependency-parser.js +3 -2
- package/.agents/scripts/lib/doc-tiers.js +2 -2
- package/.agents/scripts/lib/duplicate-search.js +242 -41
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
- package/.agents/scripts/lib/findings/promote-finding.js +23 -14
- package/.agents/scripts/lib/format-generated-json.js +97 -0
- package/.agents/scripts/lib/framework-version.js +19 -190
- package/.agents/scripts/lib/gh-exec.js +8 -0
- package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
- package/.agents/scripts/lib/git-branch-lifecycle.js +17 -180
- package/.agents/scripts/lib/git-utils.js +32 -20
- package/.agents/scripts/lib/github/framework-repo.js +6 -0
- package/.agents/scripts/lib/json-utils.js +1 -2
- package/.agents/scripts/lib/label-constants.js +10 -38
- package/.agents/scripts/lib/label-taxonomy.js +10 -55
- package/.agents/scripts/lib/observability/active-story-env.js +44 -165
- package/.agents/scripts/lib/observability/runtime-friction.js +243 -0
- package/.agents/scripts/lib/observability/signal-validator.js +4 -4
- package/.agents/scripts/lib/observability/signals-writer.js +6 -82
- package/.agents/scripts/lib/observability/source-classifier.js +5 -5
- package/.agents/scripts/lib/observability/tool-trace-hook.js +2 -12
- package/.agents/scripts/lib/onboard/init-tail.js +1 -3
- package/.agents/scripts/lib/orchestration/acceptance-clusters.js +1 -1
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +2 -2
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +105 -44
- package/.agents/scripts/lib/orchestration/code-review.js +78 -436
- package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
- package/.agents/scripts/lib/orchestration/consolidation-precondition.js +4 -4
- package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
- package/.agents/scripts/lib/orchestration/deliver-recover.js +328 -0
- package/.agents/scripts/lib/orchestration/detectors-phase.js +12 -6
- package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
- package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +34 -0
- package/.agents/scripts/lib/orchestration/lease-guard-shared.js +3 -2
- package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +142 -0
- package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +17 -19
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +86 -0
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +37 -103
- package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +21 -43
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +50 -85
- package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +3 -14
- package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
- package/.agents/scripts/lib/orchestration/merge-block-class.js +77 -21
- package/.agents/scripts/lib/orchestration/merge-poll.js +104 -0
- package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
- package/.agents/scripts/lib/orchestration/plan-context.js +354 -282
- package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +11 -22
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +4 -8
- package/.agents/scripts/lib/orchestration/plan-metrics.js +38 -6
- package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
- package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +71 -0
- package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +245 -0
- package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +116 -0
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +432 -858
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +778 -0
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +47 -115
- package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +509 -0
- package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
- package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
- package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +52 -51
- package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
- package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +1 -1
- package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
- package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
- package/.agents/scripts/lib/orchestration/resolve-stories.js +344 -0
- package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
- package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
- package/.agents/scripts/lib/orchestration/review-depth.js +126 -47
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
- package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +3 -13
- package/.agents/scripts/lib/orchestration/review-providers/native.js +1 -154
- package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +3 -2
- package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
- package/.agents/scripts/lib/orchestration/review-providers/security-review.js +1 -1
- package/.agents/scripts/lib/orchestration/review-providers/types.js +5 -4
- package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +1 -1
- package/.agents/scripts/lib/orchestration/run-epilogue.js +784 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +25 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +11 -9
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +4 -4
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +86 -41
- package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +608 -152
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +77 -32
- package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +305 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +44 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +37 -4
- package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +2 -2
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +275 -46
- package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +1 -1
- package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
- package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
- package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
- package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
- package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
- package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +10 -10
- package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +28 -42
- package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +360 -0
- package/.agents/scripts/lib/orchestration/story-follow-ups.js +298 -0
- package/.agents/scripts/lib/orchestration/story-init-remote.js +51 -0
- package/.agents/scripts/lib/orchestration/story-plan-state.js +33 -0
- package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
- package/.agents/scripts/lib/orchestration/task-body-validator.js +60 -25
- package/.agents/scripts/lib/orchestration/ticket-lease.js +27 -74
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +130 -75
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +192 -377
- package/.agents/scripts/lib/orchestration/ticket-validator.js +123 -25
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +14 -72
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +45 -55
- package/.agents/scripts/lib/orchestration/ticketing/transition.js +66 -6
- package/.agents/scripts/lib/orchestration/ticketing.js +0 -1
- package/.agents/scripts/lib/plan-phase-cleanup.js +12 -14
- package/.agents/scripts/lib/planning-corpus.js +12 -281
- package/.agents/scripts/lib/preflight-runner.js +4 -4
- package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
- package/.agents/scripts/lib/qa/qa-context-hydrator.js +5 -5
- package/.agents/scripts/lib/signals/index.js +4 -17
- package/.agents/scripts/lib/signals/read.js +35 -35
- package/.agents/scripts/lib/signals/schema.js +8 -11
- package/.agents/scripts/lib/signals/span-tree.js +7 -7
- package/.agents/scripts/lib/signals/write.js +0 -1
- package/.agents/scripts/lib/single-story/story-merged-notify.js +13 -2
- package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
- package/.agents/scripts/lib/skills/parse-skill.js +16 -3
- package/.agents/scripts/lib/story-adjacency.js +17 -19
- package/.agents/scripts/lib/story-body/story-body.js +130 -75
- package/.agents/scripts/lib/story-plan.js +2 -4
- package/.agents/scripts/lib/templates/decomposer-prompts.js +51 -46
- package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
- package/.agents/scripts/lib/test-env.js +14 -1
- package/.agents/scripts/lib/test-tiers.js +0 -3
- package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +25 -39
- package/.agents/scripts/lib/validation-evidence.js +32 -60
- package/.agents/scripts/lib/wave-runner/ready-set.js +38 -12
- package/.agents/scripts/lib/workspace-provisioner.js +1 -1
- package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +1 -1
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +72 -25
- package/.agents/scripts/lib/worktree/lifecycle-manager.js +1 -2
- package/.agents/scripts/lint-issue-body.js +71 -40
- package/.agents/scripts/mandrel-update-preflight.js +1 -1
- package/.agents/scripts/notify.js +4 -3
- package/.agents/scripts/plan-context.js +102 -80
- package/.agents/scripts/plan-persist.js +230 -279
- package/.agents/scripts/plan-run-epilogue.js +142 -0
- package/.agents/scripts/post-structured-comment.js +0 -38
- package/.agents/scripts/pr-watch-with-update.js +43 -22
- package/.agents/scripts/providers/github/compose.js +0 -1
- package/.agents/scripts/providers/github/errors.js +0 -19
- package/.agents/scripts/providers/github/issues.js +13 -39
- package/.agents/scripts/providers/github/mappers.js +5 -12
- package/.agents/scripts/providers/github/sub-issues.js +0 -47
- package/.agents/scripts/providers/github/tickets.js +33 -156
- package/.agents/scripts/providers/github.js +17 -6
- package/.agents/scripts/resolve-stories.js +236 -0
- package/.agents/scripts/run-coverage.js +4 -1
- package/.agents/scripts/run-lint.js +2 -2
- package/.agents/scripts/run-verify.js +31 -2
- package/.agents/scripts/signals-view.js +25 -21
- package/.agents/scripts/single-story-close.js +178 -26
- package/.agents/scripts/single-story-confirm-merge.js +313 -24
- package/.agents/scripts/single-story-init.js +35 -30
- package/.agents/scripts/stories-wave-tick.js +85 -10
- package/.agents/scripts/story-plan.js +28 -49
- package/.agents/scripts/update-ticket-state.js +14 -65
- package/.agents/skills/core/code-review-and-quality/SKILL.md +28 -450
- package/.agents/skills/core/code-review-and-quality/reference.md +458 -0
- package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +22 -315
- package/.agents/skills/core/debugging-and-error-recovery/reference.md +323 -0
- package/.agents/skills/core/diagnose-friction/SKILL.md +14 -18
- package/.agents/skills/core/documentation-and-adrs/SKILL.md +25 -397
- package/.agents/skills/core/documentation-and-adrs/reference.md +403 -0
- package/.agents/skills/core/gates-and-baselines/SKILL.md +12 -12
- package/.agents/skills/core/idea-refinement/SKILL.md +9 -9
- package/.agents/skills/core/scope-triage/SKILL.md +31 -172
- package/.agents/skills/core/security-and-hardening/SKILL.md +22 -367
- package/.agents/skills/core/security-and-hardening/reference.md +375 -0
- package/.agents/skills/skills.index.json +3 -53
- package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +2 -4
- package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +1 -1
- package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -3
- package/.agents/starter-agentrc.json +0 -5
- package/.agents/templates/agent-protocol.md +9 -10
- package/.agents/workflows/audit-architecture.md +6 -7
- package/.agents/workflows/audit-clean-code.md +7 -7
- package/.agents/workflows/audit-dependencies.md +3 -3
- package/.agents/workflows/audit-devops.md +3 -3
- package/.agents/workflows/audit-documentation.md +9 -10
- package/.agents/workflows/audit-lighthouse.md +11 -3
- package/.agents/workflows/audit-navigability.md +13 -2
- package/.agents/workflows/audit-performance.md +5 -6
- package/.agents/workflows/audit-privacy.md +3 -3
- package/.agents/workflows/audit-quality.md +11 -12
- package/.agents/workflows/audit-security.md +4 -5
- package/.agents/workflows/audit-seo.md +13 -3
- package/.agents/workflows/audit-sre.md +3 -3
- package/.agents/workflows/audit-to-stories.md +20 -20
- package/.agents/workflows/audit-ux-ui.md +10 -3
- package/.agents/workflows/deliver.md +177 -176
- package/.agents/workflows/git-cleanup.md +5 -6
- package/.agents/workflows/git-deliver.md +1 -1
- package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
- package/.agents/workflows/helpers/acceptance-self-eval.md +35 -40
- package/.agents/workflows/helpers/code-quality-guardrails.md +7 -7
- package/.agents/workflows/helpers/code-review.md +75 -196
- package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +83 -44
- package/.agents/workflows/helpers/deliver-story.md +606 -0
- package/.agents/workflows/helpers/diagnose.md +10 -10
- package/.agents/workflows/helpers/parallel-tooling.md +3 -3
- package/.agents/workflows/helpers/signals.md +16 -16
- package/.agents/workflows/helpers/worktree-lifecycle.md +66 -86
- package/.agents/workflows/mandrel-update.md +2 -1
- package/.agents/workflows/plan.md +277 -145
- package/.agents/workflows/qa-assist.md +27 -33
- package/.agents/workflows/qa-explore.md +29 -38
- package/.agents/workflows/qa-run.md +2 -6
- package/README.md +9 -8
- package/bin/mandrel.js +12 -1
- package/docs/CHANGELOG.md +70 -0
- package/lib/cli/registry.js +262 -19
- package/lib/cli/sync-agents.js +157 -0
- package/lib/cli/sync-commands.js +115 -6
- package/lib/cli/sync.js +168 -6
- package/lib/cli/update.js +105 -8
- package/lib/cli/version-helpers.js +131 -0
- package/lib/migrations/README.md +7 -5
- package/lib/migrations/index.js +12 -8
- package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +100 -0
- package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +101 -0
- package/package.json +2 -2
- package/.agents/agents/retro.md +0 -42
- package/.agents/personas/architect.md +0 -113
- package/.agents/personas/devops-engineer.md +0 -38
- package/.agents/personas/engineer.md +0 -33
- package/.agents/personas/project-manager.md +0 -114
- package/.agents/personas/qa-engineer.md +0 -95
- package/.agents/personas/security-engineer.md +0 -111
- package/.agents/personas/technical-writer.md +0 -101
- package/.agents/schemas/dispatch-manifest.json +0 -232
- package/.agents/schemas/epic-perf-report.schema.json +0 -89
- package/.agents/schemas/epic-spec.schema.json +0 -153
- package/.agents/schemas/lifecycle/acceptance.reconcile.failed.schema.json +0 -13
- package/.agents/schemas/lifecycle/acceptance.reconcile.ok.schema.json +0 -13
- package/.agents/schemas/lifecycle/acceptance.reconcile.skipped.schema.json +0 -13
- package/.agents/schemas/lifecycle/acceptance.reconcile.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/acceptance.reconcile.waived.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.automerge.end.schema.json +0 -15
- package/.agents/schemas/lifecycle/epic.automerge.start.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.blocked.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.cleanup.end.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.cleanup.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.close.end.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.complete.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.finalize.end.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.finalize.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.merge.armed.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.merge.blocked.schema.json +0 -14
- package/.agents/schemas/lifecycle/epic.merge.confirmed.schema.json +0 -17
- package/.agents/schemas/lifecycle/epic.merge.ready.schema.json +0 -15
- package/.agents/schemas/lifecycle/epic.plan.end.schema.json +0 -18
- package/.agents/schemas/lifecycle/epic.plan.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.snapshot.end.schema.json +0 -16
- package/.agents/schemas/lifecycle/epic.snapshot.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.watch.end.schema.json +0 -29
- package/.agents/schemas/lifecycle/epic.watch.start.schema.json +0 -16
- package/.agents/schemas/lifecycle/slice.end.schema.json +0 -21
- package/.agents/schemas/lifecycle/slice.heartbeat.schema.json +0 -20
- package/.agents/schemas/lifecycle/slice.start.schema.json +0 -17
- package/.agents/schemas/lifecycle/story.heartbeat.schema.json +0 -20
- package/.agents/schemas/risk-verdict.schema.json +0 -66
- package/.agents/schemas/story-perf-summary.schema.json +0 -73
- package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
- package/.agents/scripts/analyze-execution.js +0 -444
- package/.agents/scripts/bookkeeping-reconcile.js +0 -117
- package/.agents/scripts/check-prepush-recovery.js +0 -90
- package/.agents/scripts/dispatcher.js +0 -295
- package/.agents/scripts/epic-audit-prepare.js +0 -497
- package/.agents/scripts/epic-audit-recheck.js +0 -274
- package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
- package/.agents/scripts/epic-deliver-preflight.js +0 -462
- package/.agents/scripts/epic-deliver-prepare.js +0 -852
- package/.agents/scripts/epic-execute-record-wave.js +0 -449
- package/.agents/scripts/epic-plan-clarity.js +0 -211
- package/.agents/scripts/epic-plan-healthcheck.js +0 -581
- package/.agents/scripts/epic-reconcile.js +0 -625
- package/.agents/scripts/lib/baseline-snapshot.js +0 -979
- package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
- package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
- package/.agents/scripts/lib/config/lifecycle.js +0 -40
- package/.agents/scripts/lib/config/preflight.js +0 -58
- package/.agents/scripts/lib/config/retro.js +0 -77
- package/.agents/scripts/lib/epic-merge-lock.js +0 -322
- package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
- package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
- package/.agents/scripts/lib/git-merge-orchestrator.js +0 -261
- package/.agents/scripts/lib/observability/baseline-refresh-rate.js +0 -221
- package/.agents/scripts/lib/observability/hook-heartbeat.js +0 -219
- package/.agents/scripts/lib/observability/perf-aggregator.js +0 -813
- package/.agents/scripts/lib/observability/perf-report-readers.js +0 -328
- package/.agents/scripts/lib/observability/perf-report-render.js +0 -182
- package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +0 -270
- package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -539
- package/.agents/scripts/lib/orchestration/deliver-route.js +0 -173
- package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
- package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
- package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
- package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
- package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/risk-verdict.js +0 -105
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
- package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
- package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -621
- package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
- package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
- package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
- package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
- package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
- package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +0 -400
- package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
- package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
- package/.agents/scripts/lib/orchestration/error-journal.js +0 -139
- package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
- package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
- package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
- package/.agents/scripts/lib/orchestration/lifecycle/emit-slice-lifecycle.js +0 -270
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +0 -155
- package/.agents/scripts/lib/orchestration/lifecycle/ledger-diff.js +0 -140
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -465
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -284
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +0 -665
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
- package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
- package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
- package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
- package/.agents/scripts/lib/orchestration/plan-review-routing.js +0 -63
- package/.agents/scripts/lib/orchestration/planning-context-budget.js +0 -213
- package/.agents/scripts/lib/orchestration/planning-risk.js +0 -194
- package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +0 -56
- package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +0 -33
- package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +0 -78
- package/.agents/scripts/lib/orchestration/post-merge/phases/temp-cleanup.js +0 -68
- package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +0 -118
- package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +0 -396
- package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
- package/.agents/scripts/lib/orchestration/preflight-cache.js +0 -187
- package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
- package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
- package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
- package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
- package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
- package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
- package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +0 -275
- package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
- package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
- package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
- package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
- package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
- package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
- package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
- package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
- package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
- package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
- package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
- package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
- package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
- package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
- package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
- package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
- package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
- package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
- package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
- package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -302
- package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
- package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
- package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
- package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
- package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
- package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
- package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
- package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
- package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
- package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
- package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
- package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
- package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
- package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
- package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
- package/.agents/scripts/lib/push-epic-retry.js +0 -209
- package/.agents/scripts/lib/spec/index.js +0 -36
- package/.agents/scripts/lib/spec/loader.js +0 -425
- package/.agents/scripts/lib/spec/state.js +0 -208
- package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
- package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
- package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
- package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
- package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
- package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
- package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
- package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
- package/.agents/scripts/lib/wave-runner/tick.js +0 -754
- package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
- package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
- package/.agents/scripts/lifecycle-emit.js +0 -510
- package/.agents/scripts/retro-run.js +0 -218
- package/.agents/scripts/slice-phase.js +0 -361
- package/.agents/scripts/standalone-feedback-rollup.js +0 -188
- package/.agents/scripts/story-close.js +0 -294
- package/.agents/scripts/story-init.js +0 -599
- package/.agents/scripts/story-phase.js +0 -369
- package/.agents/scripts/wave-tick.js +0 -464
- package/.agents/skills/core/analyze-execution/SKILL.md +0 -98
- package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
- package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
- package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
- package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
- package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
- package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
- package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -383
- package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
- package/.agents/workflows/helpers/deliver-epic-reference.md +0 -547
- package/.agents/workflows/helpers/deliver-epic-single.md +0 -331
- package/.agents/workflows/helpers/deliver-epic.md +0 -998
- package/.agents/workflows/helpers/deliver-stories.md +0 -450
- package/.agents/workflows/helpers/epic-audit.md +0 -189
- package/.agents/workflows/helpers/epic-deliver-story.md +0 -436
- package/.agents/workflows/helpers/epic-testing.md +0 -125
- package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
- package/.agents/workflows/helpers/plan-epic.md +0 -353
- package/.agents/workflows/helpers/plan-story.md +0 -251
- package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
- package/.agents/workflows/helpers/single-story-deliver.md +0 -557
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* Emits a single `audit-to-stories-plan.json` envelope to --out (or
|
|
13
13
|
* stdout when --json is set).
|
|
14
14
|
*
|
|
15
|
-
* --emit-
|
|
16
|
-
* Read the plan envelope from disk, render the `/plan --
|
|
15
|
+
* --emit-plan-seed --plan <plan.json> --out <path>
|
|
16
|
+
* Read the plan envelope from disk, render the `/plan --seed`
|
|
17
17
|
* seed markdown, persist to --out.
|
|
18
18
|
*
|
|
19
19
|
* --emit-stories --plan <plan.json>
|
|
@@ -37,7 +37,7 @@ import { classifyGroupsAgainstGitHub } from './lib/audit-to-stories/dedupe-again
|
|
|
37
37
|
import { withFingerprints } from './lib/audit-to-stories/finding-adapter.js';
|
|
38
38
|
import { groupFindings } from './lib/audit-to-stories/group-findings.js';
|
|
39
39
|
import { parseAuditReports } from './lib/audit-to-stories/parse-audit-md.js';
|
|
40
|
-
import {
|
|
40
|
+
import { buildPlanSeedMarkdown } from './lib/audit-to-stories/seed-from-findings.js';
|
|
41
41
|
import { runAsCli } from './lib/cli-utils.js';
|
|
42
42
|
import { Logger } from './lib/Logger.js';
|
|
43
43
|
import { parse as parseStoryBody } from './lib/story-body/story-body.js';
|
|
@@ -291,7 +291,7 @@ async function main() {
|
|
|
291
291
|
args: process.argv.slice(2),
|
|
292
292
|
options: {
|
|
293
293
|
scan: { type: 'boolean' },
|
|
294
|
-
'emit-
|
|
294
|
+
'emit-plan-seed': { type: 'boolean' },
|
|
295
295
|
'emit-stories': { type: 'boolean' },
|
|
296
296
|
glob: { type: 'string' },
|
|
297
297
|
severity: { type: 'string' },
|
|
@@ -315,9 +315,9 @@ async function main() {
|
|
|
315
315
|
return;
|
|
316
316
|
}
|
|
317
317
|
|
|
318
|
-
if (values['emit-
|
|
318
|
+
if (values['emit-plan-seed']) {
|
|
319
319
|
const plan = loadPlan(values.plan);
|
|
320
|
-
const md =
|
|
320
|
+
const md = buildPlanSeedMarkdown({
|
|
321
321
|
groups: plan.groups ?? [],
|
|
322
322
|
findings: plan.findings ?? [],
|
|
323
323
|
sourceReports: plan.sourceReports ?? [],
|
|
@@ -346,7 +346,7 @@ async function main() {
|
|
|
346
346
|
}
|
|
347
347
|
|
|
348
348
|
throw new Error(
|
|
349
|
-
'Usage: node audit-to-stories.js (--scan | --emit-
|
|
349
|
+
'Usage: node audit-to-stories.js (--scan | --emit-plan-seed | --emit-stories) [options]',
|
|
350
350
|
);
|
|
351
351
|
}
|
|
352
352
|
|
|
@@ -72,7 +72,7 @@ Options:
|
|
|
72
72
|
* returns the sweep envelope so no caller can be blocked by a failure.
|
|
73
73
|
*
|
|
74
74
|
* DI-friendly: `injectedConfig` / `injectedProvider` let a caller (e.g.
|
|
75
|
-
* `
|
|
75
|
+
* `single-story-init.js`) reuse an already-resolved config + provider,
|
|
76
76
|
* and `injectedSweep` swaps the engine for unit tests.
|
|
77
77
|
*
|
|
78
78
|
* @param {{
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
* and custom fields. Off by default — the project
|
|
46
46
|
* board object is still created when a project
|
|
47
47
|
* name is supplied, but decoration is skipped.
|
|
48
|
-
* --with-issue-forms Opt-in: generate .github/ISSUE_TEMPLATE/story.yml
|
|
49
|
-
*
|
|
48
|
+
* --with-issue-forms Opt-in: generate .github/ISSUE_TEMPLATE/story.yml.
|
|
49
|
+
* Off by default.
|
|
50
50
|
* --reap-conflicting-workflows Delete Projects V2 built-in workflows that
|
|
51
51
|
* race against the orchestrator (destructive)
|
|
52
52
|
* --help Print this help
|
|
@@ -112,7 +112,7 @@ Flags:
|
|
|
112
112
|
--with-project-board Opt-in: provision the Projects V2 Status field
|
|
113
113
|
and custom fields (default: off — prompted y/N).
|
|
114
114
|
--with-issue-forms Opt-in: generate .github/ISSUE_TEMPLATE/story.yml
|
|
115
|
-
|
|
115
|
+
(default: off — prompted y/N).
|
|
116
116
|
--reap-conflicting-workflows Delete Projects V2 built-in workflows that
|
|
117
117
|
race against the orchestrator (destructive)
|
|
118
118
|
--help Print this help
|
|
@@ -9,12 +9,18 @@
|
|
|
9
9
|
* misconfigured knip installation cannot block CI when we have no current
|
|
10
10
|
* snapshot to compare against.
|
|
11
11
|
*
|
|
12
|
+
* Story #4575 adds the **production pass** (`--production`), the test-only-
|
|
13
|
+
* importer discount: default mode counts a test as an importer, so
|
|
14
|
+
* production-dead code hides behind its own tests. See
|
|
15
|
+
* `lib/dead-exports-mode.js` for why the two passes carry separate baselines.
|
|
16
|
+
*
|
|
12
17
|
* Contract:
|
|
13
|
-
* - Reads the committed baseline at `baselines/dead-exports.json`
|
|
14
|
-
*
|
|
18
|
+
* - Reads the committed baseline at `baselines/dead-exports.json` — or
|
|
19
|
+
* `baselines/dead-exports-production.json` under `--production`
|
|
20
|
+
* (override either with `--baseline <path>`). Envelope shape:
|
|
15
21
|
* { $schema, kernelVersion, generatedAt, rows: [{ file, symbol }] }
|
|
16
|
-
* - Spawns `npx knip --reporter json --no-progress
|
|
17
|
-
* extracts `{ file, symbol }` rows from `issues[].exports[]`.
|
|
22
|
+
* - Spawns `npx knip --reporter json --no-progress` (plus `--production`),
|
|
23
|
+
* parses stdout, extracts `{ file, symbol }` rows from `issues[].exports[]`.
|
|
18
24
|
* - Diffs current vs. baseline by `(file, symbol)` identity.
|
|
19
25
|
* - Prints `+ <file>: <symbol>` for each added dead export and
|
|
20
26
|
* `- <file>: <symbol>` for each removed one, then a summary line.
|
|
@@ -25,24 +31,30 @@
|
|
|
25
31
|
* Knip spawn/parse failure exits 0 (advisory) with a stderr warning.
|
|
26
32
|
*/
|
|
27
33
|
|
|
28
|
-
import { spawnSync } from 'node:child_process';
|
|
29
34
|
import fs from 'node:fs';
|
|
30
35
|
import path from 'node:path';
|
|
31
36
|
import process from 'node:process';
|
|
32
37
|
import { runAsCli } from './lib/cli-utils.js';
|
|
38
|
+
import {
|
|
39
|
+
extractRowsFromKnip,
|
|
40
|
+
readKnipOutput,
|
|
41
|
+
runKnip,
|
|
42
|
+
} from './lib/dead-exports-knip.js';
|
|
43
|
+
import { resolveDeadExportsMode } from './lib/dead-exports-mode.js';
|
|
33
44
|
|
|
34
45
|
/**
|
|
35
|
-
* Parse argv for `--baseline <path>`, `--json`,
|
|
36
|
-
* `--knip-output` is a test seam: pass a pre-captured knip JSON
|
|
37
|
-
* of spawning knip. Exported so unit tests can pin the parser.
|
|
46
|
+
* Parse argv for `--baseline <path>`, `--json`, `--knip-output <path>`, and
|
|
47
|
+
* `--production`. `--knip-output` is a test seam: pass a pre-captured knip JSON
|
|
48
|
+
* file instead of spawning knip. Exported so unit tests can pin the parser.
|
|
38
49
|
*
|
|
39
50
|
* @param {string[]} argv
|
|
40
|
-
* @returns {{ baselinePath: string | null, json: boolean, knipOutputPath: string | null }}
|
|
51
|
+
* @returns {{ baselinePath: string | null, json: boolean, knipOutputPath: string | null, production: boolean }}
|
|
41
52
|
*/
|
|
42
53
|
export function parseArgv(argv = []) {
|
|
43
54
|
let baselinePath = null;
|
|
44
55
|
let json = false;
|
|
45
56
|
let knipOutputPath = null;
|
|
57
|
+
let production = false;
|
|
46
58
|
for (let i = 0; i < argv.length; i += 1) {
|
|
47
59
|
const a = argv[i];
|
|
48
60
|
if (a === '--baseline') {
|
|
@@ -53,6 +65,8 @@ export function parseArgv(argv = []) {
|
|
|
53
65
|
}
|
|
54
66
|
} else if (a === '--json') {
|
|
55
67
|
json = true;
|
|
68
|
+
} else if (a === '--production') {
|
|
69
|
+
production = true;
|
|
56
70
|
} else if (a === '--knip-output') {
|
|
57
71
|
const next = argv[i + 1];
|
|
58
72
|
if (next && !next.startsWith('--')) {
|
|
@@ -61,7 +75,7 @@ export function parseArgv(argv = []) {
|
|
|
61
75
|
}
|
|
62
76
|
}
|
|
63
77
|
}
|
|
64
|
-
return { baselinePath, json, knipOutputPath };
|
|
78
|
+
return { baselinePath, json, knipOutputPath, production };
|
|
65
79
|
}
|
|
66
80
|
|
|
67
81
|
/**
|
|
@@ -84,36 +98,6 @@ export function loadBaseline(baselinePath) {
|
|
|
84
98
|
}
|
|
85
99
|
}
|
|
86
100
|
|
|
87
|
-
/**
|
|
88
|
-
* Pure helper: normalize knip's `--reporter json` output into a flat array of
|
|
89
|
-
* `{ file, symbol }` rows. Knip emits `{ issues: [{ file, exports: [{ name, ... }], ... }, ...] }`.
|
|
90
|
-
* Only `exports` rows are mapped — the dead-export ratchet ignores file-level,
|
|
91
|
-
* dependency-level, and duplicate-level issues (knip surfaces those via
|
|
92
|
-
* separate `rules` keys).
|
|
93
|
-
*
|
|
94
|
-
* @param {unknown} knipEnvelope The parsed knip JSON report.
|
|
95
|
-
* @returns {Array<{ file: string, symbol: string }>}
|
|
96
|
-
*/
|
|
97
|
-
export function extractRowsFromKnip(knipEnvelope) {
|
|
98
|
-
const rows = [];
|
|
99
|
-
if (!knipEnvelope || typeof knipEnvelope !== 'object') return rows;
|
|
100
|
-
const issues = Array.isArray(knipEnvelope.issues) ? knipEnvelope.issues : [];
|
|
101
|
-
for (const issue of issues) {
|
|
102
|
-
const file = issue?.file;
|
|
103
|
-
if (typeof file !== 'string' || file.length === 0) continue;
|
|
104
|
-
const exports_ = Array.isArray(issue.exports) ? issue.exports : [];
|
|
105
|
-
for (const e of exports_) {
|
|
106
|
-
const symbol =
|
|
107
|
-
(e && typeof e.name === 'string' && e.name) ||
|
|
108
|
-
(e && typeof e.symbol === 'string' && e.symbol) ||
|
|
109
|
-
null;
|
|
110
|
-
if (!symbol) continue;
|
|
111
|
-
rows.push({ file, symbol });
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return rows;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
101
|
/**
|
|
118
102
|
* Pure helper: diff two `{ file, symbol }` row sets. Returns `added` (in
|
|
119
103
|
* current but not baseline) and `removed` (in baseline but not current).
|
|
@@ -151,75 +135,24 @@ export function diffRows(baselineRows, currentRows) {
|
|
|
151
135
|
* "no drift" signal. When added rows are present the summary includes a
|
|
152
136
|
* "(gate fail)" marker so the ratchet violation is visible in CI output.
|
|
153
137
|
*
|
|
138
|
+
* `label` distinguishes the two passes in CI logs, which run back to back and
|
|
139
|
+
* would otherwise emit two identical-looking summaries.
|
|
140
|
+
*
|
|
154
141
|
* @param {{ added: Array, removed: Array }} diff
|
|
142
|
+
* @param {string} [label='dead-exports']
|
|
155
143
|
* @returns {string}
|
|
156
144
|
*/
|
|
157
|
-
export function renderDiff(diff) {
|
|
145
|
+
export function renderDiff(diff, label = 'dead-exports') {
|
|
158
146
|
const lines = [];
|
|
159
147
|
for (const r of diff.added) lines.push(`+ ${r.file}: ${r.symbol}`);
|
|
160
148
|
for (const r of diff.removed) lines.push(`- ${r.file}: ${r.symbol}`);
|
|
161
149
|
const tag = diff.added.length > 0 ? '(gate fail)' : '(ok)';
|
|
162
150
|
lines.push(
|
|
163
|
-
`[
|
|
151
|
+
`[${label}] added=${diff.added.length} removed=${diff.removed.length} ${tag}`,
|
|
164
152
|
);
|
|
165
153
|
return lines.join('\n');
|
|
166
154
|
}
|
|
167
155
|
|
|
168
|
-
/**
|
|
169
|
-
* Spawn `npx knip --reporter json --no-progress` and return the parsed
|
|
170
|
-
* envelope. Returns `null` on spawn / parse failure — the caller logs the
|
|
171
|
-
* underlying error and falls back to treating current rows as empty (which
|
|
172
|
-
* surfaces every baseline row as "removed", a loud-but-safe signal).
|
|
173
|
-
*
|
|
174
|
-
* Exported as a hook so tests can stub the spawn without setting up a
|
|
175
|
-
* functioning knip workspace.
|
|
176
|
-
*
|
|
177
|
-
* @param {{ cwd?: string, spawn?: typeof spawnSync }} [opts]
|
|
178
|
-
* @returns {{ ok: true, envelope: unknown } | { ok: false, error: string }}
|
|
179
|
-
*/
|
|
180
|
-
export function runKnip({ cwd = process.cwd(), spawn = spawnSync } = {}) {
|
|
181
|
-
const result = spawn(
|
|
182
|
-
process.platform === 'win32' ? 'npx.cmd' : 'npx',
|
|
183
|
-
['knip', '--reporter', 'json', '--no-progress'],
|
|
184
|
-
{
|
|
185
|
-
cwd,
|
|
186
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
187
|
-
encoding: 'utf-8',
|
|
188
|
-
shell: process.platform === 'win32',
|
|
189
|
-
},
|
|
190
|
-
);
|
|
191
|
-
if (result.error) {
|
|
192
|
-
return { ok: false, error: `spawn failed: ${result.error.message}` };
|
|
193
|
-
}
|
|
194
|
-
const stdout = typeof result.stdout === 'string' ? result.stdout : '';
|
|
195
|
-
if (stdout.trim().length === 0) {
|
|
196
|
-
return { ok: false, error: 'knip produced empty stdout' };
|
|
197
|
-
}
|
|
198
|
-
try {
|
|
199
|
-
return { ok: true, envelope: JSON.parse(stdout) };
|
|
200
|
-
} catch (err) {
|
|
201
|
-
return {
|
|
202
|
-
ok: false,
|
|
203
|
-
error: `knip JSON parse failed: ${err?.message ?? err}`,
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Read a pre-captured knip JSON envelope from disk (for the `--knip-output`
|
|
210
|
-
* test seam). Returns the parsed envelope or `null` on failure.
|
|
211
|
-
*
|
|
212
|
-
* @param {string} filePath
|
|
213
|
-
* @returns {unknown}
|
|
214
|
-
*/
|
|
215
|
-
function readKnipOutput(filePath) {
|
|
216
|
-
try {
|
|
217
|
-
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
218
|
-
} catch {
|
|
219
|
-
return null;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
156
|
/**
|
|
224
157
|
* Top-level CLI entry. Exported so tests can drive the full pipeline through
|
|
225
158
|
* injected hooks without spawning knip.
|
|
@@ -242,10 +175,15 @@ export async function runCli({
|
|
|
242
175
|
runKnipImpl = runKnip,
|
|
243
176
|
loadBaselineImpl = loadBaseline,
|
|
244
177
|
} = {}) {
|
|
245
|
-
const { baselinePath, json, knipOutputPath } = parseArgv(argv);
|
|
178
|
+
const { baselinePath, json, knipOutputPath, production } = parseArgv(argv);
|
|
179
|
+
const {
|
|
180
|
+
mode,
|
|
181
|
+
label,
|
|
182
|
+
baseline: defaultBaseline,
|
|
183
|
+
} = resolveDeadExportsMode(production);
|
|
246
184
|
const resolvedBaselinePath = path.resolve(
|
|
247
185
|
cwd,
|
|
248
|
-
baselinePath ??
|
|
186
|
+
baselinePath ?? defaultBaseline,
|
|
249
187
|
);
|
|
250
188
|
const baseline = loadBaselineImpl(resolvedBaselinePath);
|
|
251
189
|
const baselineRows = Array.isArray(baseline?.rows) ? baseline.rows : [];
|
|
@@ -256,7 +194,7 @@ export async function runCli({
|
|
|
256
194
|
knipEnvelope = readKnipOutput(path.resolve(cwd, knipOutputPath));
|
|
257
195
|
if (!knipEnvelope) knipError = `failed to read ${knipOutputPath}`;
|
|
258
196
|
} else {
|
|
259
|
-
const result = runKnipImpl({ cwd });
|
|
197
|
+
const result = runKnipImpl({ cwd, production });
|
|
260
198
|
if (result.ok) {
|
|
261
199
|
knipEnvelope = result.envelope;
|
|
262
200
|
} else {
|
|
@@ -275,6 +213,7 @@ export async function runCli({
|
|
|
275
213
|
if (json) {
|
|
276
214
|
const envelope = {
|
|
277
215
|
kind: 'dead-exports-report',
|
|
216
|
+
mode,
|
|
278
217
|
baselinePath: resolvedBaselinePath,
|
|
279
218
|
baselineRows,
|
|
280
219
|
currentRows,
|
|
@@ -287,14 +226,14 @@ export async function runCli({
|
|
|
287
226
|
} else {
|
|
288
227
|
if (!baseline) {
|
|
289
228
|
stderr.write(
|
|
290
|
-
`[
|
|
229
|
+
`[${label}] ⚠ baseline not found at ${resolvedBaselinePath} — treating as empty\n`,
|
|
291
230
|
);
|
|
292
231
|
}
|
|
293
232
|
if (knipError) {
|
|
294
|
-
stderr.write(`[
|
|
233
|
+
stderr.write(`[${label}] ⚠ knip run failed: ${knipError}\n`);
|
|
295
234
|
}
|
|
296
|
-
stdout.write(`\n---
|
|
297
|
-
stdout.write(`${renderDiff(diff)}\n`);
|
|
235
|
+
stdout.write(`\n--- ${label} preview ---\n`);
|
|
236
|
+
stdout.write(`${renderDiff(diff, label)}\n`);
|
|
298
237
|
}
|
|
299
238
|
|
|
300
239
|
return exitCode;
|
|
@@ -257,8 +257,8 @@ function stripAnchorAndQuery(target) {
|
|
|
257
257
|
// A slash token is `/<name>` where:
|
|
258
258
|
// - the preceding char is NOT a word char, `/`, `:`, `.`, `>`, `]`, `)`,
|
|
259
259
|
// so we don't match URL path segments or fragments embedded in paths
|
|
260
|
-
// like `temp/
|
|
261
|
-
// `temp/
|
|
260
|
+
// like `temp/run-<id>/lifecycle.ndjson` (preceded by `>`) or
|
|
261
|
+
// `temp/run-[ID]/tickets.json` (preceded by `]`).
|
|
262
262
|
// - the following char is NOT a word char, `-`, or `.`, so file
|
|
263
263
|
// extensions like `/tickets.json` and identifier suffixes don't match.
|
|
264
264
|
// The optional `(?::[a-z][a-z0-9-]*)?` tail captures the namespaced
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* Any module under `.agents/scripts/lib/orchestration/lifecycle/listeners/**`
|
|
18
18
|
* that calls `bus.on('*', …)` MUST NOT import a side-effecting module.
|
|
19
19
|
* The static blocklist is small (the modules that mutate GitHub state,
|
|
20
|
-
* the worktree, or write outside `temp/
|
|
20
|
+
* the worktree, or write outside `temp/run-<id>/`); we match by module
|
|
21
21
|
* specifier suffix to keep the rule simple and stable.
|
|
22
22
|
*
|
|
23
23
|
* Rule 3 — "Auto-merge lockout" (Story #2253 / Task #2255, Epic #2172
|
|
@@ -80,17 +80,14 @@ const SCRIPTS_DIR = path.join(REPO_ROOT, '.agents', 'scripts');
|
|
|
80
80
|
* auto-merge call could re-enter the codebase.
|
|
81
81
|
*/
|
|
82
82
|
const MERGE_LOCKOUT_ALLOWED_SUFFIXES = Object.freeze([
|
|
83
|
-
// Story
|
|
84
|
-
//
|
|
85
|
-
// The legacy `.agents/scripts/epic-deliver-automerge.js` exemption was
|
|
86
|
-
// removed in Story #2336 / Task #2340 once the CLI was reduced to a
|
|
87
|
-
// pure `epic.automerge.start` emit shim.
|
|
83
|
+
// v2 Story close path — the sole production code path authorized to
|
|
84
|
+
// call `gh pr merge` after the Epic AutomergeArmer listener was removed.
|
|
88
85
|
path.join(
|
|
89
86
|
'lib',
|
|
90
87
|
'orchestration',
|
|
91
|
-
'
|
|
92
|
-
'
|
|
93
|
-
'
|
|
88
|
+
'single-story-close',
|
|
89
|
+
'phases',
|
|
90
|
+
'auto-merge.js',
|
|
94
91
|
),
|
|
95
92
|
]);
|
|
96
93
|
|
|
@@ -339,7 +336,7 @@ export function findMergeLockoutViolations(
|
|
|
339
336
|
violations.push({
|
|
340
337
|
file,
|
|
341
338
|
line: i + 1,
|
|
342
|
-
hint: `String literal containing '${FORBIDDEN}' is forbidden outside
|
|
339
|
+
hint: `String literal containing '${FORBIDDEN}' is forbidden outside single-story-close/phases/auto-merge.js. Auto-merge enablement must flow through the Story close path.`,
|
|
343
340
|
});
|
|
344
341
|
break; // one violation per line is enough
|
|
345
342
|
}
|
|
@@ -61,6 +61,19 @@ const BACKTICK_CALL_RE = /`[A-Za-z_$][\w$]*\s*\(/;
|
|
|
61
61
|
const EXPORTED_FROM_RE = /\bexported from\b/;
|
|
62
62
|
const LIB_IMPORT_RE = /\b(?:import|require)\(\s*['"`][^'"`]*scripts\/lib\//;
|
|
63
63
|
|
|
64
|
+
/** A markdown table row (leading pipe, optionally indented). */
|
|
65
|
+
const TABLE_ROW_RE = /^\s*\|/;
|
|
66
|
+
/** A markdown heading of any level — the lookback boundary for Rule 4. */
|
|
67
|
+
const HEADING_RE = /^\s*#{1,6}\s/;
|
|
68
|
+
/** A backticked `--flag` occupying a table row's first cell. */
|
|
69
|
+
const FLAG_CELL_RE = /^\s*\|\s*`?--[\w-]+/;
|
|
70
|
+
/** A `.js` script filename — bare or path-qualified. */
|
|
71
|
+
const SCRIPT_NAME_RE = /([\w./-]*[\w-]+\.js)\b/;
|
|
72
|
+
/** A markdown table's delimiter row (`| --- | --- |`). */
|
|
73
|
+
const TABLE_DELIMITER_RE = /^\s*\|[\s|:-]+\|?\s*$/;
|
|
74
|
+
/** Minimum `--flag` rows before a table counts as a flag *table*. */
|
|
75
|
+
export const MIN_FLAG_ROWS = 2;
|
|
76
|
+
|
|
64
77
|
/**
|
|
65
78
|
* Strip fenced code blocks (``` / ~~~), replacing their lines with empty
|
|
66
79
|
* strings so line numbers stay stable. Complete runnable commands live in
|
|
@@ -106,6 +119,82 @@ export function toParagraphs(lines) {
|
|
|
106
119
|
return paragraphs;
|
|
107
120
|
}
|
|
108
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Rule 4 — CLI flag table. Find markdown tables that enumerate the `--flags`
|
|
124
|
+
* of a script the repo already owns, and flag them as duplicated surface.
|
|
125
|
+
*
|
|
126
|
+
* The script's own argument parser is the source of truth for its flags, and
|
|
127
|
+
* it prints them itself; a copy in prose is drift waiting to happen (the very
|
|
128
|
+
* drift Story #4546 removed). Prose must point at the command instead.
|
|
129
|
+
*
|
|
130
|
+
* The signal is deliberately narrow, to stay at zero false positives:
|
|
131
|
+
*
|
|
132
|
+
* 1. The table has at least `MIN_FLAG_ROWS` data rows whose **first cell**
|
|
133
|
+
* is a `--flag`. One flag row among prose rows is a contract/behaviour
|
|
134
|
+
* table (e.g. "Default | …", "`--dry-run` | …"), not a flag enumeration.
|
|
135
|
+
* 2. A `.js` script is named between the table and the nearest preceding
|
|
136
|
+
* heading (inclusive) — i.e. the section is *about* that script, so the
|
|
137
|
+
* table is restating its surface.
|
|
138
|
+
*
|
|
139
|
+
* A slash command's own argument table (`/plan`, `/deliver`) has no script
|
|
140
|
+
* behind it — nothing owns those flags but the workflow prose itself — so
|
|
141
|
+
* condition 2 leaves it alone by design.
|
|
142
|
+
*
|
|
143
|
+
* @param {string[]} rawLines unstripped source lines (fenced commands are the
|
|
144
|
+
* usual place a script is named, so this rule reads the original text).
|
|
145
|
+
* @returns {Array<{ rule: string, line: number, hint: string }>}
|
|
146
|
+
*/
|
|
147
|
+
export function lintFlagTables(rawLines) {
|
|
148
|
+
const violations = [];
|
|
149
|
+
let inFence = false;
|
|
150
|
+
|
|
151
|
+
for (let i = 0; i < rawLines.length; i++) {
|
|
152
|
+
if (/^\s*(```|~~~)/.test(rawLines[i])) {
|
|
153
|
+
inFence = !inFence;
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
if (inFence || !TABLE_ROW_RE.test(rawLines[i])) continue;
|
|
157
|
+
|
|
158
|
+
// Collect the contiguous table block starting here.
|
|
159
|
+
const start = i;
|
|
160
|
+
let end = i;
|
|
161
|
+
while (end + 1 < rawLines.length && TABLE_ROW_RE.test(rawLines[end + 1])) {
|
|
162
|
+
end += 1;
|
|
163
|
+
}
|
|
164
|
+
i = end; // continue scanning after this table
|
|
165
|
+
|
|
166
|
+
const flagRows = rawLines
|
|
167
|
+
.slice(start, end + 1)
|
|
168
|
+
.filter((l) => !TABLE_DELIMITER_RE.test(l) && FLAG_CELL_RE.test(l));
|
|
169
|
+
if (flagRows.length < MIN_FLAG_ROWS) continue;
|
|
170
|
+
|
|
171
|
+
// Look back to the nearest heading (inclusive) for a named script.
|
|
172
|
+
let script = null;
|
|
173
|
+
for (let j = start - 1; j >= 0; j--) {
|
|
174
|
+
const m = SCRIPT_NAME_RE.exec(rawLines[j]);
|
|
175
|
+
if (m) {
|
|
176
|
+
script = m[1];
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
if (HEADING_RE.test(rawLines[j])) break;
|
|
180
|
+
}
|
|
181
|
+
if (!script) continue;
|
|
182
|
+
|
|
183
|
+
const base = script.split('/').pop();
|
|
184
|
+
violations.push({
|
|
185
|
+
rule: 'no-cli-flag-table',
|
|
186
|
+
line: start + 1,
|
|
187
|
+
hint:
|
|
188
|
+
`Workflow prose restates the flag surface of \`${base}\` as a table (${flagRows.length} flag rows). ` +
|
|
189
|
+
"The script's argument parser owns those flags, so a prose copy is drift waiting to happen. " +
|
|
190
|
+
`Delete the table and point at the command (\`node .agents/scripts/${base} …\`), keeping only the ` +
|
|
191
|
+
'judgement a reader cannot get from the command itself. If the script has no help output to point ' +
|
|
192
|
+
'at, add one — do not re-inline the table.',
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
return violations;
|
|
196
|
+
}
|
|
197
|
+
|
|
109
198
|
/**
|
|
110
199
|
* Lint one markdown source. Returns violations
|
|
111
200
|
* `{ rule, line, hint }[]` (empty when clean).
|
|
@@ -115,7 +204,9 @@ export function toParagraphs(lines) {
|
|
|
115
204
|
*/
|
|
116
205
|
export function lintWorkflowSource(source) {
|
|
117
206
|
const violations = [];
|
|
207
|
+
const rawLines = source.split('\n');
|
|
118
208
|
const lines = stripFences(source);
|
|
209
|
+
violations.push(...lintFlagTables(rawLines));
|
|
119
210
|
for (const para of toParagraphs(lines)) {
|
|
120
211
|
if (IMPERATIVE_CALL_RE.test(para.text)) {
|
|
121
212
|
violations.push({
|
|
@@ -20,7 +20,12 @@
|
|
|
20
20
|
import { existsSync, readdirSync, rmSync } from 'node:fs';
|
|
21
21
|
import path from 'node:path';
|
|
22
22
|
import { runAsCli } from './lib/cli-utils.js';
|
|
23
|
-
|
|
23
|
+
|
|
24
|
+
const RESERVED_TEST_EPIC_TEMP_DIR = /^epic-999\d{3}$/;
|
|
25
|
+
|
|
26
|
+
function isReservedTestEpicTempDirName(name) {
|
|
27
|
+
return RESERVED_TEST_EPIC_TEMP_DIR.test(name);
|
|
28
|
+
}
|
|
24
29
|
|
|
25
30
|
/**
|
|
26
31
|
* @param {object} [opts]
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* deliver-recover.js — probe a stranded Story's live state and print the ONE
|
|
5
|
+
* command that resumes it (Story #4543).
|
|
6
|
+
*
|
|
7
|
+
* Read-only by construction. This CLI mutates nothing: it reads the ticket's
|
|
8
|
+
* labels and lease, the Story branch locally and via its tracking ref, the
|
|
9
|
+
* worktree, and the PR (state + checks), then walks a fixed decision table
|
|
10
|
+
* and prints one command with the evidence it was derived from. It never
|
|
11
|
+
* prints a menu — a menu of options is what the operator already has, and it
|
|
12
|
+
* is the thing they cannot act on.
|
|
13
|
+
*
|
|
14
|
+
* The strand this exists for above all others is the **merged-but-label-stale**
|
|
15
|
+
* Story: a `/deliver` re-run refuses it outright, because
|
|
16
|
+
* `single-story-init.js` hard-errors on an already-closed Story. Before this
|
|
17
|
+
* surface, that Story had no automated way back.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* node .agents/scripts/deliver-recover.js --story <STORY_ID> [--cwd <main-repo>]
|
|
21
|
+
* [--json]
|
|
22
|
+
*
|
|
23
|
+
* Exit codes:
|
|
24
|
+
* 0 — a recovery shape was resolved and its next command printed (including
|
|
25
|
+
* the "nothing to recover" shapes). Reading state is not a failure.
|
|
26
|
+
* 1 — the probe itself could not run (unreadable ticket, bad input).
|
|
27
|
+
*
|
|
28
|
+
* @see .agents/scripts/lib/orchestration/deliver-recover.js
|
|
29
|
+
* @see .agents/schemas/story-deliver-terminal.schema.json
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import { parseArgs } from 'node:util';
|
|
33
|
+
import { runAsCli } from './lib/cli-utils.js';
|
|
34
|
+
import { resolveConfig } from './lib/config-resolver.js';
|
|
35
|
+
import { Logger } from './lib/Logger.js';
|
|
36
|
+
import {
|
|
37
|
+
recoverStory,
|
|
38
|
+
renderRecovery,
|
|
39
|
+
} from './lib/orchestration/deliver-recover.js';
|
|
40
|
+
import { PROJECT_ROOT } from './lib/project-root.js';
|
|
41
|
+
import { createProvider } from './lib/provider-factory.js';
|
|
42
|
+
|
|
43
|
+
const HELP = `Usage: node .agents/scripts/deliver-recover.js --story <id> [--cwd <main-repo>] [--json]
|
|
44
|
+
|
|
45
|
+
Probes a Story's live delivery state — labels, lease, branch, worktree, PR
|
|
46
|
+
state and checks — and prints the single next command that resumes it, with
|
|
47
|
+
the evidence it was derived from. Read-only: mutates nothing.
|
|
48
|
+
|
|
49
|
+
Flags:
|
|
50
|
+
--story GitHub issue number of the Story (required).
|
|
51
|
+
--cwd Main-repo checkout to probe (default: project root).
|
|
52
|
+
--json Emit the full recovery envelope as JSON instead of prose.
|
|
53
|
+
--help Show this message.
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
export function parseArgv(argv) {
|
|
57
|
+
const { values } = parseArgs({
|
|
58
|
+
args: argv,
|
|
59
|
+
options: {
|
|
60
|
+
story: { type: 'string' },
|
|
61
|
+
cwd: { type: 'string' },
|
|
62
|
+
json: { type: 'boolean', default: false },
|
|
63
|
+
help: { type: 'boolean', default: false },
|
|
64
|
+
},
|
|
65
|
+
strict: false,
|
|
66
|
+
});
|
|
67
|
+
return {
|
|
68
|
+
storyId: Number.parseInt(String(values.story ?? ''), 10),
|
|
69
|
+
cwd: values.cwd ?? null,
|
|
70
|
+
json: Boolean(values.json),
|
|
71
|
+
help: Boolean(values.help),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Probe and report. Exported for testing.
|
|
77
|
+
*/
|
|
78
|
+
export async function runDeliverRecover({
|
|
79
|
+
storyId: storyIdParam,
|
|
80
|
+
cwd: cwdParam,
|
|
81
|
+
json: jsonParam,
|
|
82
|
+
argv,
|
|
83
|
+
injectedProvider,
|
|
84
|
+
injectedConfig,
|
|
85
|
+
injectedGh,
|
|
86
|
+
injectedGitSpawn,
|
|
87
|
+
} = {}) {
|
|
88
|
+
const parsed =
|
|
89
|
+
storyIdParam !== undefined
|
|
90
|
+
? { storyId: storyIdParam, cwd: cwdParam ?? null, json: !!jsonParam }
|
|
91
|
+
: parseArgv(argv ?? process.argv.slice(2));
|
|
92
|
+
|
|
93
|
+
if (parsed.help) {
|
|
94
|
+
Logger.info(HELP);
|
|
95
|
+
return { success: true, result: null };
|
|
96
|
+
}
|
|
97
|
+
if (!Number.isInteger(parsed.storyId) || parsed.storyId <= 0) {
|
|
98
|
+
throw new Error(
|
|
99
|
+
'Usage: node deliver-recover.js --story <STORY_ID> [--cwd <main-repo>] [--json]',
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const cwd = parsed.cwd ?? PROJECT_ROOT;
|
|
104
|
+
const config = injectedConfig || resolveConfig({ cwd });
|
|
105
|
+
const provider = injectedProvider || createProvider(config);
|
|
106
|
+
|
|
107
|
+
const recovery = await recoverStory({
|
|
108
|
+
storyId: parsed.storyId,
|
|
109
|
+
cwd,
|
|
110
|
+
provider,
|
|
111
|
+
config,
|
|
112
|
+
gh: injectedGh,
|
|
113
|
+
gitSpawnFn: injectedGitSpawn,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
Logger.info(
|
|
117
|
+
parsed.json ? JSON.stringify(recovery, null, 2) : renderRecovery(recovery),
|
|
118
|
+
);
|
|
119
|
+
return { success: true, result: recovery };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
runAsCli(import.meta.url, runDeliverRecover, { source: 'deliver-recover' });
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* any still-stuck entries by enumerating the processes holding handles
|
|
9
9
|
* inside the worktree path and terminating them.
|
|
10
10
|
*
|
|
11
|
-
* Invoked by `/deliver
|
|
11
|
+
* Invoked by `/deliver` and `/plan`
|
|
12
12
|
* (via `drainPendingCleanupAtBoot` → `worktree-sweep.js`), and
|
|
13
13
|
* `story-close` so the pending-cleanup ledger drains automatically
|
|
14
14
|
* across the sprint lifecycle. Operators can also run it standalone:
|