mandrel 1.93.0 → 2.0.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 +59 -73
- package/.agents/agents/acceptance-critic.md +129 -0
- package/.agents/agents/story-worker.md +161 -0
- package/.agents/docs/SDLC.md +489 -1285
- package/.agents/docs/agentrc-reference.json +177 -67
- package/.agents/docs/configuration.md +108 -136
- package/.agents/docs/execution-reference.md +44 -22
- package/.agents/docs/quality-gates.md +13 -19
- package/.agents/docs/workflows.md +3 -3
- package/.agents/instructions.md +107 -108
- package/.agents/rules/ci-remediation.md +8 -12
- package/.agents/rules/git-conventions-reference.md +224 -0
- package/.agents/rules/git-conventions.md +42 -223
- package/.agents/rules/security-baseline.md +5 -0
- package/.agents/rules/testing-standards.md +106 -13
- package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
- package/.agents/schemas/agentrc.schema.json +71 -201
- package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
- package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
- package/.agents/schemas/risk-verdict.schema.json +0 -13
- package/.agents/scripts/acceptance-eval.js +62 -18
- package/.agents/scripts/agents-bootstrap-github.js +1 -1
- package/.agents/scripts/analyze-execution.js +1 -1
- package/.agents/scripts/audit-to-stories.js +7 -7
- package/.agents/scripts/boot-sweep.js +1 -1
- package/.agents/scripts/check-context-budget.js +62 -5
- package/.agents/scripts/check-lifecycle-lint.js +6 -9
- package/.agents/scripts/check-prepush-recovery.js +1 -1
- package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
- package/.agents/scripts/diagnose-friction.js +0 -6
- 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 +5 -5
- 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 -4
- package/.agents/scripts/lib/baselines/reader.js +1 -6
- package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
- package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +56 -18
- package/.agents/scripts/lib/checks/core-bare-clean.js +2 -2
- package/.agents/scripts/lib/checks/index.js +2 -1
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +23 -21
- package/.agents/scripts/lib/cli/standard-args.js +13 -22
- package/.agents/scripts/lib/cli-args.js +16 -7
- package/.agents/scripts/lib/close-validation/gates.js +160 -22
- package/.agents/scripts/lib/config/acceptance-eval.js +52 -5
- package/.agents/scripts/lib/config/ci.js +6 -31
- package/.agents/scripts/lib/config/delivery-routing.js +103 -0
- package/.agents/scripts/lib/config/explain.js +57 -36
- package/.agents/scripts/lib/config/limits.js +17 -58
- package/.agents/scripts/lib/config/paths.js +0 -2
- package/.agents/scripts/lib/config/quality.js +1 -1
- package/.agents/scripts/lib/config/runners.js +17 -50
- package/.agents/scripts/lib/config/temp-paths.js +19 -14
- package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
- package/.agents/scripts/lib/config-resolver.js +3 -8
- package/.agents/scripts/lib/config-settings-schema-delivery.js +46 -136
- package/.agents/scripts/lib/config-settings-schema-quality.js +17 -14
- package/.agents/scripts/lib/config-settings-schema.js +52 -38
- package/.agents/scripts/lib/dependency-parser.js +3 -2
- package/.agents/scripts/lib/doc-tiers.js +39 -4
- package/.agents/scripts/lib/duplicate-search.js +211 -41
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
- package/.agents/scripts/lib/findings/promote-finding.js +5 -5
- package/.agents/scripts/lib/framework-version.js +2 -3
- package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
- package/.agents/scripts/lib/git-branch-lifecycle.js +17 -22
- package/.agents/scripts/lib/git-utils.js +32 -6
- package/.agents/scripts/lib/github/framework-repo.js +6 -0
- package/.agents/scripts/lib/label-constants.js +10 -23
- package/.agents/scripts/lib/label-taxonomy.js +9 -43
- package/.agents/scripts/lib/observability/active-story-env.js +112 -3
- package/.agents/scripts/lib/observability/hook-heartbeat.js +187 -0
- package/.agents/scripts/lib/observability/source-classifier.js +3 -3
- package/.agents/scripts/lib/observability/tool-trace-hook.js +15 -4
- package/.agents/scripts/lib/onboard/init-tail.js +1 -3
- package/.agents/scripts/lib/orchestration/acceptance-clusters.js +111 -0
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +32 -4
- package/.agents/scripts/lib/orchestration/audit-lens-routing.js +128 -0
- package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +273 -0
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +204 -0
- package/.agents/scripts/lib/orchestration/code-review.js +20 -268
- package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
- package/.agents/scripts/lib/orchestration/consolidation-precondition.js +1 -1
- package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
- 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/lifecycle/emit-loop-tick.js +8 -8
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +2 -2
- package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +17 -43
- package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
- package/.agents/scripts/lib/orchestration/merge-block-class.js +1 -1
- package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
- package/.agents/scripts/lib/orchestration/plan-context.js +248 -266
- package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +3 -2
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +1 -1
- package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
- package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +61 -0
- package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +97 -0
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +223 -854
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +361 -0
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +35 -108
- 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 +14 -14
- package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
- package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/risk-verdict.js +3 -4
- package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +2 -2
- package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +8 -20
- package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +3 -2
- package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
- package/.agents/scripts/lib/orchestration/preflight-cache.js +5 -5
- package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
- package/.agents/scripts/lib/orchestration/resolve-plan-run.js +155 -0
- package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
- package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +8 -8
- package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
- package/.agents/scripts/lib/orchestration/review-depth.js +26 -12
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
- package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
- package/.agents/scripts/lib/orchestration/run-epilogue.js +426 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +1 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +95 -41
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +16 -13
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +40 -0
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +11 -3
- 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/phases/code-review.js +15 -12
- package/.agents/scripts/lib/orchestration/story-follow-ups.js +237 -0
- package/.agents/scripts/lib/orchestration/story-init-remote.js +47 -0
- package/.agents/scripts/lib/orchestration/story-plan-state.js +48 -0
- package/.agents/scripts/lib/orchestration/{epic-runner → story-progress}/story-run-progress-writer.js +3 -3
- package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
- package/.agents/scripts/lib/orchestration/task-body-validator.js +8 -18
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +11 -61
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +189 -373
- package/.agents/scripts/lib/orchestration/ticket-validator.js +3 -8
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +0 -25
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +29 -26
- package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -5
- package/.agents/scripts/lib/planning-corpus.js +16 -11
- package/.agents/scripts/lib/preflight-runner.js +2 -2
- package/.agents/scripts/lib/provider-factory.js +1 -1
- package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
- package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +36 -0
- package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
- package/.agents/scripts/lib/story-adjacency.js +11 -14
- package/.agents/scripts/lib/story-body/story-body.js +124 -70
- package/.agents/scripts/lib/story-plan.js +2 -4
- package/.agents/scripts/lib/templates/decomposer-prompts.js +46 -45
- package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
- package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +26 -26
- package/.agents/scripts/lib/validation-evidence.js +1 -1
- package/.agents/scripts/lib/wave-runner/ready-set.js +6 -6
- package/.agents/scripts/lib/workspace-provisioner.js +1 -1
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +5 -7
- 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 +64 -74
- package/.agents/scripts/plan-persist.js +121 -280
- package/.agents/scripts/plan-run-epilogue.js +97 -0
- package/.agents/scripts/post-structured-comment.js +38 -0
- package/.agents/scripts/providers/github/issues.js +17 -33
- package/.agents/scripts/providers/github/mappers.js +0 -12
- package/.agents/scripts/providers/github/tickets.js +2 -5
- package/.agents/scripts/resolve-plan-run.js +117 -0
- package/.agents/scripts/signals-view.js +24 -19
- package/.agents/scripts/single-story-close.js +11 -14
- package/.agents/scripts/single-story-confirm-merge.js +39 -23
- package/.agents/scripts/single-story-init.js +29 -20
- package/.agents/scripts/stories-wave-tick.js +6 -6
- package/.agents/scripts/story-plan.js +26 -47
- package/.agents/scripts/sync-claude-agents.js +165 -0
- package/.agents/scripts/update-ticket-state.js +37 -15
- package/.agents/skills/core/analyze-execution/SKILL.md +21 -18
- package/.agents/skills/core/api-and-interface-design/SKILL.md +5 -3
- package/.agents/skills/core/code-review-and-quality/SKILL.md +63 -7
- package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +1 -1
- package/.agents/skills/core/gates-and-baselines/SKILL.md +149 -0
- package/.agents/skills/core/idea-refinement/SKILL.md +8 -14
- package/.agents/skills/core/qa-coverage-mapping/SKILL.md +7 -7
- package/.agents/skills/core/scope-triage/SKILL.md +28 -172
- package/.agents/skills/skills.index.json +8 -418
- package/.agents/starter-agentrc.json +0 -5
- package/.agents/templates/agent-protocol.md +9 -10
- package/.agents/workflows/audit-architecture.md +3 -3
- package/.agents/workflows/audit-clean-code.md +3 -3
- package/.agents/workflows/audit-dependencies.md +3 -3
- package/.agents/workflows/audit-devops.md +3 -3
- package/.agents/workflows/audit-documentation.md +5 -5
- package/.agents/workflows/audit-lighthouse.md +3 -3
- package/.agents/workflows/audit-navigability.md +3 -2
- package/.agents/workflows/audit-performance.md +3 -3
- package/.agents/workflows/audit-privacy.md +3 -3
- package/.agents/workflows/audit-quality.md +3 -3
- package/.agents/workflows/audit-security.md +3 -3
- package/.agents/workflows/audit-seo.md +3 -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 +3 -3
- package/.agents/workflows/deliver.md +122 -131
- package/.agents/workflows/git-cleanup.md +3 -4
- package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
- package/.agents/workflows/helpers/acceptance-self-eval.md +52 -40
- package/.agents/workflows/helpers/code-review.md +70 -193
- package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +12 -14
- package/.agents/workflows/helpers/{single-story-deliver.md → deliver-story.md} +113 -139
- package/.agents/workflows/helpers/diagnose.md +10 -10
- package/.agents/workflows/helpers/mandrel-sync-config.md +1 -1
- package/.agents/workflows/helpers/parallel-tooling.md +1 -1
- package/.agents/workflows/helpers/signals.md +16 -16
- package/.agents/workflows/helpers/worktree-lifecycle.md +48 -64
- package/.agents/workflows/mandrel-update.md +3 -2
- package/.agents/workflows/plan.md +112 -145
- package/.agents/workflows/qa-assist.md +24 -30
- package/.agents/workflows/qa-explore.md +29 -38
- package/.agents/workflows/qa-run.md +2 -2
- package/README.md +9 -8
- package/docs/CHANGELOG.md +46 -0
- package/lib/cli/registry.js +95 -0
- package/lib/migrations/index.js +6 -5
- package/package.json +5 -3
- package/.agents/personas/architect.md +0 -113
- package/.agents/personas/devops-engineer.md +0 -38
- package/.agents/personas/engineer-mobile.md +0 -120
- package/.agents/personas/engineer-web.md +0 -111
- package/.agents/personas/engineer.md +0 -119
- package/.agents/personas/product.md +0 -94
- package/.agents/personas/project-manager.md +0 -114
- package/.agents/personas/qa-engineer.md +0 -95
- package/.agents/personas/refactorer.md +0 -113
- package/.agents/personas/security-engineer.md +0 -112
- package/.agents/personas/sre.md +0 -86
- package/.agents/personas/technical-writer.md +0 -101
- package/.agents/personas/ux-designer.md +0 -95
- package/.agents/schemas/dispatch-manifest.json +0 -232
- package/.agents/schemas/epic-spec.schema.json +0 -153
- package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
- 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 -590
- package/.agents/scripts/epic-execute-record-wave.js +0 -449
- package/.agents/scripts/epic-plan-clarity.js +0 -211
- package/.agents/scripts/epic-plan-decompose.js +0 -54
- package/.agents/scripts/epic-plan-healthcheck.js +0 -581
- package/.agents/scripts/epic-plan-spec.js +0 -64
- 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/orchestration/context-hydration-engine.js +0 -660
- 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/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 -388
- 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/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/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-story-dispatch-end.js +0 -147
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -384
- 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 -278
- 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/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/post-merge-pipeline.js +0 -205
- 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-runner.js +0 -197
- package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +0 -109
- 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 -301
- 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/plan-critics.js +0 -199
- package/.agents/scripts/retro-run.js +0 -218
- 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 -335
- package/.agents/skills/core/baseline-refresh/SKILL.md +0 -181
- package/.agents/skills/core/ci-cd-and-automation/SKILL.md +0 -274
- package/.agents/skills/core/ci-cd-and-automation/examples.md +0 -211
- package/.agents/skills/core/code-simplification/SKILL.md +0 -389
- package/.agents/skills/core/context-engineering/SKILL.md +0 -309
- package/.agents/skills/core/context-engineering/examples.md +0 -58
- package/.agents/skills/core/deprecation-and-migration/SKILL.md +0 -250
- 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 -413
- package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
- package/.agents/skills/core/frontend-ui-engineering/SKILL.md +0 -357
- package/.agents/skills/core/hydrate-context/SKILL.md +0 -123
- package/.agents/skills/core/idea-refinement/examples.md +0 -437
- package/.agents/skills/core/idea-refinement/frameworks.md +0 -135
- package/.agents/skills/core/incremental-implementation/SKILL.md +0 -271
- package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +0 -213
- package/.agents/skills/core/knowledge-transfer/SKILL.md +0 -180
- package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +0 -117
- package/.agents/skills/core/performance-optimization/SKILL.md +0 -314
- package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +0 -277
- package/.agents/skills/core/property-based-testing/SKILL.md +0 -148
- package/.agents/skills/core/refactoring-discipline/SKILL.md +0 -111
- package/.agents/skills/core/shipping-and-launch/SKILL.md +0 -328
- package/.agents/skills/core/spec-driven-development/SKILL.md +0 -252
- package/.agents/skills/core/test-driven-development/SKILL.md +0 -475
- package/.agents/skills/core/using-agent-skills/SKILL.md +0 -232
- package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +0 -31
- package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +0 -51
- package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +0 -76
- package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +0 -31
- package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +0 -33
- package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +0 -31
- package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +0 -51
- package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +0 -54
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +0 -29
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +0 -30
- package/.agents/skills/stack/backend/stripe-integration/SKILL.md +0 -57
- package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +0 -9
- package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +0 -48
- package/.agents/skills/stack/frontend/astro/SKILL.md +0 -62
- package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +0 -30
- package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +0 -29
- package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +0 -50
- package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +0 -58
- package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +0 -34
- package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +0 -51
- package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +0 -199
- package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +0 -68
- package/.agents/workflows/helpers/deliver-epic-reference.md +0 -534
- package/.agents/workflows/helpers/deliver-epic.md +0 -955
- package/.agents/workflows/helpers/deliver-stories.md +0 -440
- package/.agents/workflows/helpers/epic-audit.md +0 -189
- package/.agents/workflows/helpers/epic-deliver-story.md +0 -427
- 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 -351
- package/.agents/workflows/helpers/plan-story.md +0 -251
- package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
- /package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +0 -0
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
// .agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js
|
|
2
|
-
/**
|
|
3
|
-
* Cleaner — lifecycle listener that owns the post-arm temp archive and
|
|
4
|
-
* the terminal `epic.complete` emit. Story #2259 / Task #2265
|
|
5
|
-
* (Epic #2172).
|
|
6
|
-
*
|
|
7
|
-
* Subscribes to:
|
|
8
|
-
* - `epic.merge.confirmed` → and ONLY this event.
|
|
9
|
-
*
|
|
10
|
-
* Story #2896 (Epic #2880) rebound this listener from
|
|
11
|
-
* `epic.merge.armed` to `epic.merge.confirmed` so the Epic only
|
|
12
|
-
* transitions to its terminal state AFTER the MergeWatcher has
|
|
13
|
-
* observed `gh pr view --json mergeCommit` returning a non-null
|
|
14
|
-
* `mergeCommit` (i.e. the PR has actually merged), rather than after
|
|
15
|
-
* `gh pr merge --auto` was merely armed. The chain ordering is:
|
|
16
|
-
*
|
|
17
|
-
* epic.merge.armed → MergeWatcher polls
|
|
18
|
-
* epic.merge.confirmed → Cleaner (this listener) + LabelTransitioner
|
|
19
|
-
*
|
|
20
|
-
* Side effects executed inside `handle()`:
|
|
21
|
-
* 1. Emit `epic.cleanup.start`.
|
|
22
|
-
* 2. Emit `epic.cleanup.end`.
|
|
23
|
-
* 3. Emit `epic.complete` carrying `{ epicId, prUrl }` — the terminal
|
|
24
|
-
* event of a successful Epic run. LabelTransitioner flips the
|
|
25
|
-
* Epic ticket to `agent::done` on this event (see listener
|
|
26
|
-
* README). The emit order is "complete BEFORE archive" so the
|
|
27
|
-
* ledger written into `temp/epic-<id>/lifecycle.ndjson` carries
|
|
28
|
-
* `epic.complete` as its last record — this is Task #2265's
|
|
29
|
-
* acceptance contract.
|
|
30
|
-
* 4. Move `temp/epic-<id>/` to `temp/archive/epic-<id>-<ts>/`. The
|
|
31
|
-
* move is atomic on the same filesystem (`fs.renameSync`) so a
|
|
32
|
-
* crash between rename and ledger flush leaves either the source
|
|
33
|
-
* or the destination on disk — never both. When the source is
|
|
34
|
-
* absent (because a prior interrupted run already moved it), the
|
|
35
|
-
* step short-circuits to the resume contract: no second archive
|
|
36
|
-
* directory is created (AC-10 Cleaner idempotency).
|
|
37
|
-
*
|
|
38
|
-
* Idempotency contract (AC-10): two-layer defence.
|
|
39
|
-
* 1. Per-instance `Set<string>` of `${event}:${seqId}` keys — repeat
|
|
40
|
-
* `(event, seqId)` invocation short-circuits and emits nothing.
|
|
41
|
-
* This is the bus-level replay defence.
|
|
42
|
-
* 2. On-disk archive probe — when the source `temp/epic-<id>/`
|
|
43
|
-
* directory is absent (the prior process moved it before
|
|
44
|
-
* crashing), the listener records the existing archive directory
|
|
45
|
-
* and proceeds to emit `epic.cleanup.end` + `epic.complete`
|
|
46
|
-
* exactly once. This defends against cross-process re-run after
|
|
47
|
-
* a crash between the rename and the `epic.cleanup.end` emit.
|
|
48
|
-
*
|
|
49
|
-
* Side-effect firewall: the listener emits on the bus and moves a
|
|
50
|
-
* directory under `tempRoot`. It does NOT mutate ticket labels, post
|
|
51
|
-
* comments, or call `notify` — downstream listeners
|
|
52
|
-
* (LabelTransitioner on `epic.complete`) own those side effects.
|
|
53
|
-
*
|
|
54
|
-
* Why move (rename) rather than copy + delete: a rename is atomic at
|
|
55
|
-
* the OS level when source and destination share a filesystem (which
|
|
56
|
-
* they do — both live under `temp/`). Copy + delete leaves a window
|
|
57
|
-
* where both directories exist; a crash there would produce two
|
|
58
|
-
* archive entries on the next run. The rename guarantees that the
|
|
59
|
-
* source either still exists OR the destination does, never neither
|
|
60
|
-
* and never both.
|
|
61
|
-
*/
|
|
62
|
-
|
|
63
|
-
import { existsSync, mkdirSync, readdirSync, renameSync } from 'node:fs';
|
|
64
|
-
import path from 'node:path';
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Default clock — exported so tests can stub the timestamp suffix on
|
|
68
|
-
* the archive directory name.
|
|
69
|
-
*/
|
|
70
|
-
export function defaultNow() {
|
|
71
|
-
return new Date();
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Format a `Date` as a filesystem-safe timestamp suffix for the archive
|
|
76
|
-
* directory name. ISO-8601 with `:` replaced by `-` so the result is
|
|
77
|
-
* usable on Windows. Pure — exported for tests.
|
|
78
|
-
*
|
|
79
|
-
* Example: 2026-05-17T21:55:09.123Z → 2026-05-17T21-55-09-123Z
|
|
80
|
-
*/
|
|
81
|
-
export function formatArchiveTimestamp(date) {
|
|
82
|
-
const iso = date.toISOString();
|
|
83
|
-
return iso.replace(/[:.]/g, '-');
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Resolve the archive destination directory for an Epic. Pure helper
|
|
88
|
-
* that builds the `<tempRoot>/archive/epic-<id>-<ts>` path. Exported
|
|
89
|
-
* for tests so the layout pin is reviewable.
|
|
90
|
-
*/
|
|
91
|
-
export function resolveArchiveDest({ tempRoot, epicId, now }) {
|
|
92
|
-
const suffix = formatArchiveTimestamp(now);
|
|
93
|
-
return path.join(tempRoot, 'archive', `epic-${epicId}-${suffix}`);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Find an existing archive directory for an Epic. Returns the absolute
|
|
98
|
-
* path of the FIRST match (alphabetic order; archive names are
|
|
99
|
-
* timestamped so this is also chronological), or `null` when no
|
|
100
|
-
* archive exists yet. Pure — exported for tests.
|
|
101
|
-
*
|
|
102
|
-
* Used by the on-disk idempotency probe: when `temp/epic-<id>/` is
|
|
103
|
-
* absent AND an archive directory already exists, we know a prior run
|
|
104
|
-
* completed the move; the listener short-circuits to a single
|
|
105
|
-
* `epic.cleanup.end` + `epic.complete` emit without re-archiving.
|
|
106
|
-
*/
|
|
107
|
-
export function findExistingArchive({
|
|
108
|
-
tempRoot,
|
|
109
|
-
epicId,
|
|
110
|
-
readdirFn = readdirSync,
|
|
111
|
-
}) {
|
|
112
|
-
const archiveRoot = path.join(tempRoot, 'archive');
|
|
113
|
-
let entries;
|
|
114
|
-
try {
|
|
115
|
-
entries = readdirFn(archiveRoot, { withFileTypes: true });
|
|
116
|
-
} catch (err) {
|
|
117
|
-
// Missing archive root is the typical first-run case.
|
|
118
|
-
if (err && err.code === 'ENOENT') return null;
|
|
119
|
-
throw err;
|
|
120
|
-
}
|
|
121
|
-
const prefix = `epic-${epicId}-`;
|
|
122
|
-
const matches = entries
|
|
123
|
-
.filter((e) => e.isDirectory?.() && e.name.startsWith(prefix))
|
|
124
|
-
.map((e) => e.name)
|
|
125
|
-
.sort();
|
|
126
|
-
if (matches.length === 0) return null;
|
|
127
|
-
return path.join(archiveRoot, matches[0]);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Cleaner listener.
|
|
132
|
-
*/
|
|
133
|
-
export class Cleaner {
|
|
134
|
-
/**
|
|
135
|
-
* @param {object} opts
|
|
136
|
-
* @param {object} opts.bus
|
|
137
|
-
* @param {number} opts.epicId
|
|
138
|
-
* @param {string} opts.tempRoot - absolute or repo-relative path; the
|
|
139
|
-
* listener resolves `<tempRoot>/epic-<id>/` as the source and
|
|
140
|
-
* `<tempRoot>/archive/epic-<id>-<ts>/` as the destination.
|
|
141
|
-
* @param {() => Date} [opts.now] - injectable clock for tests.
|
|
142
|
-
* @param {typeof renameSync} [opts.renameFn] - injectable rename for
|
|
143
|
-
* tests.
|
|
144
|
-
* @param {typeof existsSync} [opts.existsFn] - injectable presence
|
|
145
|
-
* probe for tests.
|
|
146
|
-
* @param {typeof mkdirSync} [opts.mkdirFn] - injectable directory
|
|
147
|
-
* creator for tests.
|
|
148
|
-
* @param {typeof readdirSync} [opts.readdirFn] - injectable directory
|
|
149
|
-
* reader for the existing-archive probe.
|
|
150
|
-
* @param {{ info?: Function, warn?: Function, debug?: Function }} [opts.logger]
|
|
151
|
-
*/
|
|
152
|
-
constructor(opts = {}) {
|
|
153
|
-
if (
|
|
154
|
-
!opts.bus ||
|
|
155
|
-
typeof opts.bus.on !== 'function' ||
|
|
156
|
-
typeof opts.bus.emit !== 'function'
|
|
157
|
-
) {
|
|
158
|
-
throw new TypeError('Cleaner requires a bus with on() and emit()');
|
|
159
|
-
}
|
|
160
|
-
if (!Number.isInteger(opts.epicId) || opts.epicId < 1) {
|
|
161
|
-
throw new TypeError('Cleaner requires a numeric epicId');
|
|
162
|
-
}
|
|
163
|
-
if (typeof opts.tempRoot !== 'string' || opts.tempRoot.length === 0) {
|
|
164
|
-
throw new TypeError('Cleaner requires a non-empty tempRoot string');
|
|
165
|
-
}
|
|
166
|
-
this.bus = opts.bus;
|
|
167
|
-
this.epicId = opts.epicId;
|
|
168
|
-
this.tempRoot = opts.tempRoot;
|
|
169
|
-
this.now = typeof opts.now === 'function' ? opts.now : defaultNow;
|
|
170
|
-
this.renameFn = opts.renameFn ?? renameSync;
|
|
171
|
-
this.existsFn = opts.existsFn ?? existsSync;
|
|
172
|
-
this.mkdirFn = opts.mkdirFn ?? mkdirSync;
|
|
173
|
-
this.readdirFn = opts.readdirFn ?? readdirSync;
|
|
174
|
-
this.logger = opts.logger ?? console;
|
|
175
|
-
/** @type {Set<string>} `${event}:${seqId}` idempotency cache. */
|
|
176
|
-
this._seen = new Set();
|
|
177
|
-
/**
|
|
178
|
-
* Classification log — every `epic.merge.confirmed` observed
|
|
179
|
-
* lands here with the outcome (`archived`, `existing-archive`,
|
|
180
|
-
* `skipped-duplicate`, `failed`). Mirrors the
|
|
181
|
-
* Finalizer / AutomergeArmer "no silent skip" surface.
|
|
182
|
-
*/
|
|
183
|
-
this.classifications = [];
|
|
184
|
-
// Frozen tuple — Cleaner subscribes to EXACTLY one event.
|
|
185
|
-
// Story #2896 rebind: was `epic.merge.armed`, now
|
|
186
|
-
// `epic.merge.confirmed` (downstream of MergeWatcher).
|
|
187
|
-
this.events = Object.freeze(['epic.merge.confirmed']);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
register() {
|
|
191
|
-
return this.events.map((event) =>
|
|
192
|
-
this.bus.on(event, async (ctx) => this.handle(ctx)),
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
async handle({ event, seqId, payload }) {
|
|
197
|
-
const key = `${event}:${seqId}`;
|
|
198
|
-
if (this._seen.has(key)) {
|
|
199
|
-
this.classifications.push({
|
|
200
|
-
event,
|
|
201
|
-
seqId,
|
|
202
|
-
outcome: 'skipped',
|
|
203
|
-
reason: 'duplicate-seqId',
|
|
204
|
-
});
|
|
205
|
-
this.logger.debug?.(`[Cleaner] skip duplicate ${key} (idempotent)`);
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
this._seen.add(key);
|
|
209
|
-
|
|
210
|
-
const prUrl = payload?.prUrl;
|
|
211
|
-
if (typeof prUrl !== 'string' || prUrl.length === 0) {
|
|
212
|
-
this.classifications.push({
|
|
213
|
-
event,
|
|
214
|
-
seqId,
|
|
215
|
-
outcome: 'failed',
|
|
216
|
-
reason: 'no-pr-url',
|
|
217
|
-
});
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const epicId = this.epicId;
|
|
222
|
-
const epicDir = path.join(this.tempRoot, `epic-${epicId}`);
|
|
223
|
-
|
|
224
|
-
// 0. Cross-process resume probe — if an archive directory for
|
|
225
|
-
// this Epic already exists on disk, a prior run already
|
|
226
|
-
// completed the rename. Honour the AC-10 idempotency
|
|
227
|
-
// contract: emit the terminal sequence exactly once (so
|
|
228
|
-
// LabelTransitioner / downstream listeners stay in sync) but
|
|
229
|
-
// do NOT re-archive the just-recreated source directory. The
|
|
230
|
-
// `archivedTo` field carries the FIRST archive directory.
|
|
231
|
-
//
|
|
232
|
-
// This probe runs BEFORE the emit chain so the LedgerWriter's
|
|
233
|
-
// `_ensureDir` recreation of `temp/epic-<id>/` (lazy on the
|
|
234
|
-
// first append) does not mask the resume signal.
|
|
235
|
-
const existingArchive = findExistingArchive({
|
|
236
|
-
tempRoot: this.tempRoot,
|
|
237
|
-
epicId,
|
|
238
|
-
readdirFn: this.readdirFn,
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
// 1. Emit the terminal sequence FIRST so the ledger inside
|
|
242
|
-
// `temp/epic-<id>/lifecycle.ndjson` captures the full
|
|
243
|
-
// `epic.cleanup.start` → `epic.cleanup.end` → `epic.complete`
|
|
244
|
-
// trail BEFORE the archive rename moves the directory. AC
|
|
245
|
-
// contract: "epic.complete is the last event recorded in the
|
|
246
|
-
// ledger before archive."
|
|
247
|
-
//
|
|
248
|
-
// Emits that throw are caught and recorded as `failed`; the
|
|
249
|
-
// archive step is still attempted afterwards on resume but
|
|
250
|
-
// NOT during this same handler invocation, because schema or
|
|
251
|
-
// bus-shape errors are signal of a real problem we do not
|
|
252
|
-
// want to mask.
|
|
253
|
-
try {
|
|
254
|
-
await this.bus.emit('epic.cleanup.start', { epicId });
|
|
255
|
-
} catch (err) {
|
|
256
|
-
this.classifications.push({
|
|
257
|
-
event,
|
|
258
|
-
seqId,
|
|
259
|
-
outcome: 'failed',
|
|
260
|
-
reason: `start-emit-failed:${err?.message ?? err}`,
|
|
261
|
-
});
|
|
262
|
-
this.logger.warn?.(
|
|
263
|
-
`[Cleaner] epic.cleanup.start emit failed: ${err?.message ?? err}`,
|
|
264
|
-
);
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
try {
|
|
268
|
-
await this.bus.emit('epic.cleanup.end', { epicId });
|
|
269
|
-
} catch (err) {
|
|
270
|
-
this.classifications.push({
|
|
271
|
-
event,
|
|
272
|
-
seqId,
|
|
273
|
-
outcome: 'failed',
|
|
274
|
-
reason: `end-emit-failed:${err?.message ?? err}`,
|
|
275
|
-
});
|
|
276
|
-
this.logger.warn?.(
|
|
277
|
-
`[Cleaner] epic.cleanup.end emit failed: ${err?.message ?? err}`,
|
|
278
|
-
);
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
try {
|
|
282
|
-
await this.bus.emit('epic.complete', { epicId, prUrl });
|
|
283
|
-
} catch (err) {
|
|
284
|
-
this.classifications.push({
|
|
285
|
-
event,
|
|
286
|
-
seqId,
|
|
287
|
-
outcome: 'failed',
|
|
288
|
-
reason: `complete-emit-failed:${err?.message ?? err}`,
|
|
289
|
-
});
|
|
290
|
-
this.logger.warn?.(
|
|
291
|
-
`[Cleaner] epic.complete emit failed: ${err?.message ?? err}`,
|
|
292
|
-
);
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// 2. Archive. Three states:
|
|
297
|
-
// (a) prior archive exists — resume contract; short-circuit
|
|
298
|
-
// and record `existing-archive` without re-archiving the
|
|
299
|
-
// (LedgerWriter-recreated) source directory.
|
|
300
|
-
// (b) no prior archive + source exists — rename it under
|
|
301
|
-
// `archive/`. Happy path.
|
|
302
|
-
// (c) no prior archive + source absent — nothing to archive.
|
|
303
|
-
let archivedTo;
|
|
304
|
-
let outcome;
|
|
305
|
-
if (existingArchive) {
|
|
306
|
-
archivedTo = existingArchive;
|
|
307
|
-
outcome = 'existing-archive';
|
|
308
|
-
this.logger.info?.(
|
|
309
|
-
`[Cleaner] existing archive ${existingArchive} found — resume contract honored; not re-archiving.`,
|
|
310
|
-
);
|
|
311
|
-
} else if (this.existsFn(epicDir)) {
|
|
312
|
-
const dest = resolveArchiveDest({
|
|
313
|
-
tempRoot: this.tempRoot,
|
|
314
|
-
epicId,
|
|
315
|
-
now: this.now(),
|
|
316
|
-
});
|
|
317
|
-
try {
|
|
318
|
-
this.mkdirFn(path.dirname(dest), { recursive: true });
|
|
319
|
-
this.renameFn(epicDir, dest);
|
|
320
|
-
} catch (err) {
|
|
321
|
-
this.classifications.push({
|
|
322
|
-
event,
|
|
323
|
-
seqId,
|
|
324
|
-
outcome: 'failed',
|
|
325
|
-
reason: `archive-failed:${err?.message ?? err}`,
|
|
326
|
-
});
|
|
327
|
-
this.logger.warn?.(
|
|
328
|
-
`[Cleaner] archive rename failed (${epicDir} → ${dest}): ${err?.message ?? err}`,
|
|
329
|
-
);
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
332
|
-
archivedTo = dest;
|
|
333
|
-
outcome = 'archived';
|
|
334
|
-
} else {
|
|
335
|
-
archivedTo = null;
|
|
336
|
-
outcome = 'no-source';
|
|
337
|
-
this.logger.info?.(
|
|
338
|
-
`[Cleaner] source ${epicDir} absent and no prior archive — nothing to do.`,
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
this.classifications.push({
|
|
343
|
-
event,
|
|
344
|
-
seqId,
|
|
345
|
-
outcome,
|
|
346
|
-
epicId,
|
|
347
|
-
archivedTo,
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
reset() {
|
|
352
|
-
this._seen.clear();
|
|
353
|
-
this.classifications = [];
|
|
354
|
-
}
|
|
355
|
-
}
|