mandrel 1.57.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 +954 -0
- package/.agents/docs/SDLC.md +1420 -0
- package/.agents/docs/agentrc-reference.json +278 -0
- package/.agents/docs/configuration.md +1040 -0
- package/.agents/docs/workflows.md +59 -0
- package/.agents/instructions.md +384 -0
- package/.agents/personas/architect.md +107 -0
- package/.agents/personas/devops-engineer.md +36 -0
- package/.agents/personas/engineer-mobile.md +119 -0
- package/.agents/personas/engineer-web.md +110 -0
- package/.agents/personas/engineer.md +90 -0
- package/.agents/personas/product.md +88 -0
- package/.agents/personas/project-manager.md +110 -0
- package/.agents/personas/qa-engineer.md +91 -0
- package/.agents/personas/refactorer.md +110 -0
- package/.agents/personas/security-engineer.md +112 -0
- package/.agents/personas/sre.md +86 -0
- package/.agents/personas/technical-writer.md +100 -0
- package/.agents/personas/ux-designer.md +95 -0
- package/.agents/rules/api-conventions.md +75 -0
- package/.agents/rules/changelog-style.md +238 -0
- package/.agents/rules/gherkin-standards.md +146 -0
- package/.agents/rules/git-conventions.md +146 -0
- package/.agents/rules/orchestration-error-handling.md +35 -0
- package/.agents/rules/security-baseline.md +92 -0
- package/.agents/rules/shell-conventions.md +70 -0
- package/.agents/rules/test-seams.md +59 -0
- package/.agents/rules/testing-standards.md +177 -0
- package/.agents/runtime-deps.json +18 -0
- package/.agents/schemas/acceptance-eval-verdict.schema.json +93 -0
- package/.agents/schemas/agentrc.schema.json +1583 -0
- package/.agents/schemas/audit-results.schema.json +69 -0
- package/.agents/schemas/audit-rules.json +134 -0
- package/.agents/schemas/audit-rules.schema.json +69 -0
- package/.agents/schemas/baselines/baseline-envelope.schema.json +44 -0
- package/.agents/schemas/baselines/bundle-size.schema.json +47 -0
- package/.agents/schemas/baselines/coverage.schema.json +50 -0
- package/.agents/schemas/baselines/crap.schema.json +52 -0
- package/.agents/schemas/baselines/duplication.schema.json +62 -0
- package/.agents/schemas/baselines/lighthouse.schema.json +59 -0
- package/.agents/schemas/baselines/lint.schema.json +47 -0
- package/.agents/schemas/baselines/maintainability.schema.json +71 -0
- package/.agents/schemas/baselines/mutation.schema.json +52 -0
- package/.agents/schemas/crap-baseline.schema.json +57 -0
- package/.agents/schemas/crap-report.schema.json +102 -0
- package/.agents/schemas/dispatch-manifest.json +232 -0
- package/.agents/schemas/epic-perf-report.schema.json +89 -0
- package/.agents/schemas/epic-spec.schema.json +183 -0
- package/.agents/schemas/friction-event.schema.json +56 -0
- package/.agents/schemas/lifecycle/README.md +18 -0
- package/.agents/schemas/lifecycle/acceptance.reconcile.failed.schema.json +13 -0
- package/.agents/schemas/lifecycle/acceptance.reconcile.ok.schema.json +13 -0
- package/.agents/schemas/lifecycle/acceptance.reconcile.skipped.schema.json +13 -0
- package/.agents/schemas/lifecycle/acceptance.reconcile.start.schema.json +12 -0
- package/.agents/schemas/lifecycle/acceptance.reconcile.waived.schema.json +13 -0
- package/.agents/schemas/lifecycle/checkpoint.written.schema.json +13 -0
- package/.agents/schemas/lifecycle/close-validate.end.schema.json +18 -0
- package/.agents/schemas/lifecycle/close-validate.start.schema.json +13 -0
- package/.agents/schemas/lifecycle/code-review.end.schema.json +30 -0
- package/.agents/schemas/lifecycle/code-review.start.schema.json +12 -0
- package/.agents/schemas/lifecycle/epic.automerge.end.schema.json +14 -0
- package/.agents/schemas/lifecycle/epic.automerge.start.schema.json +13 -0
- package/.agents/schemas/lifecycle/epic.blocked.schema.json +13 -0
- package/.agents/schemas/lifecycle/epic.cleanup.end.schema.json +12 -0
- package/.agents/schemas/lifecycle/epic.cleanup.start.schema.json +12 -0
- package/.agents/schemas/lifecycle/epic.close.end.schema.json +12 -0
- package/.agents/schemas/lifecycle/epic.complete.schema.json +13 -0
- package/.agents/schemas/lifecycle/epic.finalize.end.schema.json +13 -0
- package/.agents/schemas/lifecycle/epic.finalize.start.schema.json +12 -0
- package/.agents/schemas/lifecycle/epic.merge.armed.schema.json +13 -0
- package/.agents/schemas/lifecycle/epic.merge.blocked.schema.json +14 -0
- package/.agents/schemas/lifecycle/epic.merge.confirmed.schema.json +17 -0
- package/.agents/schemas/lifecycle/epic.merge.ready.schema.json +15 -0
- package/.agents/schemas/lifecycle/epic.plan.end.schema.json +18 -0
- package/.agents/schemas/lifecycle/epic.plan.start.schema.json +12 -0
- package/.agents/schemas/lifecycle/epic.snapshot.end.schema.json +16 -0
- package/.agents/schemas/lifecycle/epic.snapshot.start.schema.json +12 -0
- package/.agents/schemas/lifecycle/epic.watch.end.schema.json +28 -0
- package/.agents/schemas/lifecycle/epic.watch.start.schema.json +16 -0
- package/.agents/schemas/lifecycle/intervention.recorded.schema.json +15 -0
- package/.agents/schemas/lifecycle/ledger-record.schema.json +59 -0
- package/.agents/schemas/lifecycle/notification.emitted.schema.json +18 -0
- package/.agents/schemas/lifecycle/pr.created.schema.json +14 -0
- package/.agents/schemas/lifecycle/retro.end.schema.json +16 -0
- package/.agents/schemas/lifecycle/retro.start.schema.json +12 -0
- package/.agents/schemas/lifecycle/story.blocked.schema.json +13 -0
- package/.agents/schemas/lifecycle/story.dispatch.end.schema.json +17 -0
- package/.agents/schemas/lifecycle/story.dispatch.start.schema.json +15 -0
- package/.agents/schemas/lifecycle/story.heartbeat.schema.json +20 -0
- package/.agents/schemas/lifecycle/story.merged.schema.json +13 -0
- package/.agents/schemas/mi-report.schema.json +58 -0
- package/.agents/schemas/model-attribution.schema.json +49 -0
- package/.agents/schemas/qa-finding.schema.json +133 -0
- package/.agents/schemas/qa-ledger.schema.json +89 -0
- package/.agents/schemas/risk-verdict.schema.json +53 -0
- package/.agents/schemas/signal-event.schema.json +58 -0
- package/.agents/schemas/skill.schema.json +31 -0
- package/.agents/schemas/skills-index.schema.json +81 -0
- package/.agents/schemas/story-perf-summary.schema.json +73 -0
- package/.agents/schemas/validation-evidence.schema.json +78 -0
- package/.agents/scripts/README.md +93 -0
- package/.agents/scripts/acceptance-eval.js +284 -0
- package/.agents/scripts/acceptance-spec-reconciler.js +556 -0
- package/.agents/scripts/agents-bootstrap-github.js +634 -0
- package/.agents/scripts/analyze-execution.js +369 -0
- package/.agents/scripts/assert-branch.js +83 -0
- package/.agents/scripts/audit-labels-bootstrap.js +253 -0
- package/.agents/scripts/audit-to-stories.js +257 -0
- package/.agents/scripts/bootstrap.js +1378 -0
- package/.agents/scripts/check-baselines.js +81 -0
- package/.agents/scripts/check-dead-exports.js +311 -0
- package/.agents/scripts/check-doc-links.js +401 -0
- package/.agents/scripts/check-gherkin-placeholders.js +663 -0
- package/.agents/scripts/check-lifecycle-doc-drift.js +402 -0
- package/.agents/scripts/check-lifecycle-lint.js +379 -0
- package/.agents/scripts/check-prepush-recovery.js +90 -0
- package/.agents/scripts/check-windows-git-perf.js +138 -0
- package/.agents/scripts/cleanup-repo-test-temp.js +67 -0
- package/.agents/scripts/coverage-capture.js +112 -0
- package/.agents/scripts/detect-merges.js +111 -0
- package/.agents/scripts/diagnose-friction.js +257 -0
- package/.agents/scripts/diagnose.js +240 -0
- package/.agents/scripts/dispatcher.js +295 -0
- package/.agents/scripts/drain-pending-cleanup.js +147 -0
- package/.agents/scripts/epic-audit-prepare.js +419 -0
- package/.agents/scripts/epic-audit-recheck.js +241 -0
- package/.agents/scripts/epic-deliver-note-intervention.js +192 -0
- package/.agents/scripts/epic-deliver-preflight.js +407 -0
- package/.agents/scripts/epic-deliver-prepare.js +383 -0
- package/.agents/scripts/epic-execute-record-wave.js +463 -0
- package/.agents/scripts/epic-plan-clarity.js +201 -0
- package/.agents/scripts/epic-plan-decompose.js +79 -0
- package/.agents/scripts/epic-plan-healthcheck.js +363 -0
- package/.agents/scripts/epic-plan-spec-validate.js +111 -0
- package/.agents/scripts/epic-plan-spec.js +198 -0
- package/.agents/scripts/epic-reconcile.js +637 -0
- package/.agents/scripts/evidence-gate.js +235 -0
- package/.agents/scripts/generate-config-docs.js +516 -0
- package/.agents/scripts/generate-lifecycle-docs.js +224 -0
- package/.agents/scripts/generate-skills-index.js +252 -0
- package/.agents/scripts/generate-workflows-doc.js +168 -0
- package/.agents/scripts/git-cleanup.js +124 -0
- package/.agents/scripts/git-pr-quality-gate.js +203 -0
- package/.agents/scripts/git-rebase-and-resolve.js +234 -0
- package/.agents/scripts/hierarchy-gate.js +176 -0
- package/.agents/scripts/hydrate-context.js +179 -0
- package/.agents/scripts/install-matrix-assert.js +282 -0
- package/.agents/scripts/lib/Graph.js +326 -0
- package/.agents/scripts/lib/ITicketingProvider.js +349 -0
- package/.agents/scripts/lib/Logger.js +194 -0
- package/.agents/scripts/lib/audit-suite/cli.js +64 -0
- package/.agents/scripts/lib/audit-suite/findings.js +164 -0
- package/.agents/scripts/lib/audit-suite/frontmatter-lint.js +32 -0
- package/.agents/scripts/lib/audit-suite/frontmatter.js +110 -0
- package/.agents/scripts/lib/audit-suite/index.js +22 -0
- package/.agents/scripts/lib/audit-suite/runner.js +233 -0
- package/.agents/scripts/lib/audit-suite/selector.js +235 -0
- package/.agents/scripts/lib/audit-suite/substitutions.js +124 -0
- package/.agents/scripts/lib/audit-suite/workflow-loader.js +49 -0
- package/.agents/scripts/lib/audit-to-stories/build-story-body.js +130 -0
- package/.agents/scripts/lib/audit-to-stories/dedupe-against-github.js +114 -0
- package/.agents/scripts/lib/audit-to-stories/finding-adapter.js +93 -0
- package/.agents/scripts/lib/audit-to-stories/group-findings.js +265 -0
- package/.agents/scripts/lib/audit-to-stories/parse-audit-md.js +246 -0
- package/.agents/scripts/lib/audit-to-stories/seed-epic-from-findings.js +160 -0
- package/.agents/scripts/lib/auto-refresh-baselines.js +308 -0
- package/.agents/scripts/lib/baseline-loader.js +0 -0
- package/.agents/scripts/lib/baseline-schema-registry.js +69 -0
- package/.agents/scripts/lib/baseline-snapshot.js +716 -0
- package/.agents/scripts/lib/baselines/component-matcher.js +21 -0
- package/.agents/scripts/lib/baselines/components.js +126 -0
- package/.agents/scripts/lib/baselines/diff-scope-cli.js +203 -0
- package/.agents/scripts/lib/baselines/duplication-scanner.js +220 -0
- package/.agents/scripts/lib/baselines/env-overrides.js +129 -0
- package/.agents/scripts/lib/baselines/envelope.js +368 -0
- package/.agents/scripts/lib/baselines/exit-codes.js +89 -0
- package/.agents/scripts/lib/baselines/git-base.js +0 -0
- package/.agents/scripts/lib/baselines/kernel.js +111 -0
- package/.agents/scripts/lib/baselines/kinds/_shared-metric.js +220 -0
- package/.agents/scripts/lib/baselines/kinds/bundle-size.js +157 -0
- package/.agents/scripts/lib/baselines/kinds/coverage.js +194 -0
- package/.agents/scripts/lib/baselines/kinds/crap.js +555 -0
- package/.agents/scripts/lib/baselines/kinds/duplication.js +197 -0
- package/.agents/scripts/lib/baselines/kinds/lighthouse.js +185 -0
- package/.agents/scripts/lib/baselines/kinds/lint.js +172 -0
- package/.agents/scripts/lib/baselines/kinds/maintainability.js +340 -0
- package/.agents/scripts/lib/baselines/kinds/mutation.js +153 -0
- package/.agents/scripts/lib/baselines/path-canon.js +279 -0
- package/.agents/scripts/lib/baselines/preview-gates.js +298 -0
- package/.agents/scripts/lib/baselines/reader.js +321 -0
- package/.agents/scripts/lib/baselines/refresh-service.js +733 -0
- package/.agents/scripts/lib/baselines/scope.js +291 -0
- package/.agents/scripts/lib/baselines/writer.js +312 -0
- package/.agents/scripts/lib/bdd-runner-detect.js +417 -0
- package/.agents/scripts/lib/bdd-scenario-scanner.js +310 -0
- package/.agents/scripts/lib/bootstrap/baselines-layout-migration.js +202 -0
- package/.agents/scripts/lib/bootstrap/branch-protection.js +222 -0
- package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +171 -0
- package/.agents/scripts/lib/bootstrap/commit-push.js +146 -0
- package/.agents/scripts/lib/bootstrap/gh-list.js +153 -0
- package/.agents/scripts/lib/bootstrap/gh-preflight.js +306 -0
- package/.agents/scripts/lib/bootstrap/hitl-confirm.js +89 -0
- package/.agents/scripts/lib/bootstrap/install-ledger.js +174 -0
- package/.agents/scripts/lib/bootstrap/manifest.js +272 -0
- package/.agents/scripts/lib/bootstrap/merge-methods.js +108 -0
- package/.agents/scripts/lib/bootstrap/preflight.js +195 -0
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +801 -0
- package/.agents/scripts/lib/bootstrap/prompt.js +480 -0
- package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +370 -0
- package/.agents/scripts/lib/bootstrap/summary.js +75 -0
- package/.agents/scripts/lib/bootstrap/workflow-audit.js +256 -0
- package/.agents/scripts/lib/branch-name-guard.js +98 -0
- package/.agents/scripts/lib/c8-cli-path.js +21 -0
- package/.agents/scripts/lib/changed-files.js +184 -0
- package/.agents/scripts/lib/checks/baseline-drift-main-checkout.js +104 -0
- package/.agents/scripts/lib/checks/core-bare-clean.js +48 -0
- package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +54 -0
- package/.agents/scripts/lib/checks/index.js +288 -0
- package/.agents/scripts/lib/checks/push-hook-parity.js +106 -0
- package/.agents/scripts/lib/checks/stale-origin-epic.js +49 -0
- package/.agents/scripts/lib/checks/state.js +558 -0
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +186 -0
- package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +182 -0
- package/.agents/scripts/lib/checks/windows-coverage-noise-floor.js +92 -0
- package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +81 -0
- package/.agents/scripts/lib/checks/worktree-residue-biome.js +55 -0
- package/.agents/scripts/lib/cli/parse-numeric.js +60 -0
- package/.agents/scripts/lib/cli/standard-args.js +351 -0
- package/.agents/scripts/lib/cli-args.js +286 -0
- package/.agents/scripts/lib/cli-utils.js +69 -0
- package/.agents/scripts/lib/close-validation/projections/head-sha.js +44 -0
- package/.agents/scripts/lib/close-validation/projections/inputs.js +86 -0
- package/.agents/scripts/lib/close-validation/projections/maintainability.js +286 -0
- package/.agents/scripts/lib/close-validation.js +897 -0
- package/.agents/scripts/lib/codebase-snapshot.js +513 -0
- package/.agents/scripts/lib/command-header.js +33 -0
- package/.agents/scripts/lib/config/acceptance-eval.js +95 -0
- package/.agents/scripts/lib/config/baselines.js +60 -0
- package/.agents/scripts/lib/config/ci.js +30 -0
- package/.agents/scripts/lib/config/commands.js +36 -0
- package/.agents/scripts/lib/config/defaults.js +119 -0
- package/.agents/scripts/lib/config/explain.js +348 -0
- package/.agents/scripts/lib/config/gates/bundle-size.schema.js +23 -0
- package/.agents/scripts/lib/config/gates/coverage.schema.js +18 -0
- package/.agents/scripts/lib/config/gates/crap.schema.js +33 -0
- package/.agents/scripts/lib/config/gates/duplication.schema.js +26 -0
- package/.agents/scripts/lib/config/gates/index.js +36 -0
- package/.agents/scripts/lib/config/gates/lighthouse.schema.js +23 -0
- package/.agents/scripts/lib/config/gates/lint.schema.js +9 -0
- package/.agents/scripts/lib/config/gates/maintainability.schema.js +20 -0
- package/.agents/scripts/lib/config/gates/mutation.schema.js +12 -0
- package/.agents/scripts/lib/config/gates/shared.js +117 -0
- package/.agents/scripts/lib/config/github.js +122 -0
- package/.agents/scripts/lib/config/lifecycle.js +40 -0
- package/.agents/scripts/lib/config/limits.js +211 -0
- package/.agents/scripts/lib/config/paths.js +73 -0
- package/.agents/scripts/lib/config/preflight.js +58 -0
- package/.agents/scripts/lib/config/quality.js +665 -0
- package/.agents/scripts/lib/config/retro.js +77 -0
- package/.agents/scripts/lib/config/runners.js +105 -0
- package/.agents/scripts/lib/config/runtime.js +167 -0
- package/.agents/scripts/lib/config/shared.js +46 -0
- package/.agents/scripts/lib/config/sync-agentrc.js +243 -0
- package/.agents/scripts/lib/config/temp-paths.js +373 -0
- package/.agents/scripts/lib/config/validate-orchestration.js +81 -0
- package/.agents/scripts/lib/config/worktree-isolation.js +80 -0
- package/.agents/scripts/lib/config-resolver.js +298 -0
- package/.agents/scripts/lib/config-schema-shared.js +32 -0
- package/.agents/scripts/lib/config-schema.js +20 -0
- package/.agents/scripts/lib/config-settings-schema-delivery.js +332 -0
- package/.agents/scripts/lib/config-settings-schema-quality.js +165 -0
- package/.agents/scripts/lib/config-settings-schema.js +420 -0
- package/.agents/scripts/lib/coverage-baseline.js +352 -0
- package/.agents/scripts/lib/coverage-capture.js +195 -0
- package/.agents/scripts/lib/coverage-utils.js +239 -0
- package/.agents/scripts/lib/cpu-pool.js +223 -0
- package/.agents/scripts/lib/crap-engine.js +119 -0
- package/.agents/scripts/lib/crap-utils.js +479 -0
- package/.agents/scripts/lib/degraded-mode.js +69 -0
- package/.agents/scripts/lib/dependency-parser.js +129 -0
- package/.agents/scripts/lib/duplicate-search.js +189 -0
- package/.agents/scripts/lib/dynamic-workflow/architecture-report-contract.js +70 -0
- package/.agents/scripts/lib/dynamic-workflow/audit-orchestrator.js +197 -0
- package/.agents/scripts/lib/dynamic-workflow/capability.js +396 -0
- package/.agents/scripts/lib/dynamic-workflow/clean-code-report-contract.js +80 -0
- package/.agents/scripts/lib/dynamic-workflow/performance-report-contract.js +72 -0
- package/.agents/scripts/lib/dynamic-workflow/quality-report-contract.js +90 -0
- package/.agents/scripts/lib/dynamic-workflow/report-contract-core.js +43 -0
- package/.agents/scripts/lib/dynamic-workflow/security-report-contract.js +83 -0
- package/.agents/scripts/lib/env-loader.js +52 -0
- package/.agents/scripts/lib/epic-merge-lock.js +239 -0
- package/.agents/scripts/lib/epic-plan-clarity.js +142 -0
- package/.agents/scripts/lib/epic-plan-ideation.js +228 -0
- package/.agents/scripts/lib/error-redactor.js +125 -0
- package/.agents/scripts/lib/errors/index.js +67 -0
- package/.agents/scripts/lib/feedback-loop/audit-results-graduator.js +230 -0
- package/.agents/scripts/lib/feedback-loop/code-review-graduator.js +207 -0
- package/.agents/scripts/lib/feedback-loop/graduator-core.js +421 -0
- package/.agents/scripts/lib/feedback-loop/memory-freshness.js +480 -0
- package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +229 -0
- package/.agents/scripts/lib/findings/classify-finding.js +195 -0
- package/.agents/scripts/lib/findings/promote-finding.js +353 -0
- package/.agents/scripts/lib/findings/route-finding.js +283 -0
- package/.agents/scripts/lib/findings/semantic-issue-search.js +179 -0
- package/.agents/scripts/lib/findings/severity.js +102 -0
- package/.agents/scripts/lib/gates/baseline-store.js +106 -0
- package/.agents/scripts/lib/gates/friction.js +43 -0
- package/.agents/scripts/lib/gh-exec.js +553 -0
- package/.agents/scripts/lib/git/cached-fetch.js +0 -0
- package/.agents/scripts/lib/git/sync-from-base.js +162 -0
- package/.agents/scripts/lib/git-branch-cleanup.js +213 -0
- package/.agents/scripts/lib/git-branch-lifecycle.js +353 -0
- package/.agents/scripts/lib/git-merge-orchestrator.js +261 -0
- package/.agents/scripts/lib/git-utils.js +363 -0
- package/.agents/scripts/lib/github-url.js +29 -0
- package/.agents/scripts/lib/install-cmd-parser.js +51 -0
- package/.agents/scripts/lib/issue-link-parser.js +74 -0
- package/.agents/scripts/lib/json-utils.js +60 -0
- package/.agents/scripts/lib/label-constants.js +169 -0
- package/.agents/scripts/lib/label-taxonomy.js +200 -0
- package/.agents/scripts/lib/maintainability-engine.js +164 -0
- package/.agents/scripts/lib/maintainability-utils.js +343 -0
- package/.agents/scripts/lib/mandrel-catalog.js +170 -0
- package/.agents/scripts/lib/mutation/baseline-snapshot.js +238 -0
- package/.agents/scripts/lib/mutation/config-detector.js +119 -0
- package/.agents/scripts/lib/mutation/stryker-runner.js +306 -0
- package/.agents/scripts/lib/mutation/survivor-report.js +160 -0
- package/.agents/scripts/lib/notifications/notifier.js +75 -0
- package/.agents/scripts/lib/observability/active-story-env.js +182 -0
- package/.agents/scripts/lib/observability/baseline-refresh-rate.js +221 -0
- package/.agents/scripts/lib/observability/perf-aggregator.js +887 -0
- package/.agents/scripts/lib/observability/perf-report-readers.js +319 -0
- package/.agents/scripts/lib/observability/perf-report-render.js +182 -0
- package/.agents/scripts/lib/observability/signals-writer.js +296 -0
- package/.agents/scripts/lib/observability/source-classifier.js +103 -0
- package/.agents/scripts/lib/observability/tool-trace-hook.js +417 -0
- package/.agents/scripts/lib/onboard/detect-stack.js +300 -0
- package/.agents/scripts/lib/onboard/scaffold-docs.js +128 -0
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +173 -0
- package/.agents/scripts/lib/orchestration/cascade-grouping.js +275 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/compare.js +131 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +80 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/floors.js +132 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/friction.js +142 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/parse-args.js +149 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/pipeline.js +158 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +56 -0
- package/.agents/scripts/lib/orchestration/code-review.js +652 -0
- package/.agents/scripts/lib/orchestration/column-sync.js +286 -0
- package/.agents/scripts/lib/orchestration/context-envelope.js +280 -0
- package/.agents/scripts/lib/orchestration/context-hydration-engine.js +581 -0
- package/.agents/scripts/lib/orchestration/dependency-analyzer.js +88 -0
- package/.agents/scripts/lib/orchestration/detectors-phase.js +188 -0
- package/.agents/scripts/lib/orchestration/dispatch-engine.js +144 -0
- package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +206 -0
- package/.agents/scripts/lib/orchestration/doc-reader.js +94 -0
- package/.agents/scripts/lib/orchestration/epic-cleanup.js +473 -0
- package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +310 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/cli.js +167 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +151 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +74 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +78 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +72 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +155 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +321 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +75 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +86 -0
- package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +235 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/authoring-context.js +197 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/cli-args.js +48 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +94 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +414 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +55 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/risk-verdict.js +105 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +235 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +120 -0
- package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +118 -0
- package/.agents/scripts/lib/orchestration/epic-run-state-store.js +295 -0
- package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +186 -0
- package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +50 -0
- package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +146 -0
- package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +110 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +392 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +217 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +235 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter.js +69 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +32 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +291 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +175 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +37 -0
- package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +127 -0
- package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +400 -0
- package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +285 -0
- package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +66 -0
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +797 -0
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +619 -0
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +335 -0
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +230 -0
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +363 -0
- package/.agents/scripts/lib/orchestration/error-journal.js +139 -0
- package/.agents/scripts/lib/orchestration/file-assumption-enum.js +31 -0
- package/.agents/scripts/lib/orchestration/file-assumptions.js +506 -0
- package/.agents/scripts/lib/orchestration/finalize/close-planning-tickets.js +116 -0
- package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +241 -0
- package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +489 -0
- package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +88 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-reap.js +219 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches.js +309 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +99 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +123 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/filters.js +57 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes-ff.js +114 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes.js +426 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/parse-args.js +84 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/phase-drivers.js +365 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/prompts.js +72 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/prune.js +69 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/render.js +214 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/stashes.js +137 -0
- package/.agents/scripts/lib/orchestration/label-transitions.js +43 -0
- package/.agents/scripts/lib/orchestration/lifecycle/bus.js +309 -0
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +147 -0
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +155 -0
- package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +226 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +69 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +378 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +248 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +527 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +259 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +278 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +355 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +647 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +331 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +140 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +421 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +168 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +668 -0
- package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +322 -0
- package/.agents/scripts/lib/orchestration/lint-baseline-service.js +114 -0
- package/.agents/scripts/lib/orchestration/manifest-builder.js +216 -0
- package/.agents/scripts/lib/orchestration/model-attribution.js +390 -0
- package/.agents/scripts/lib/orchestration/parked-follow-ons.js +147 -0
- package/.agents/scripts/lib/orchestration/phase-runner.js +87 -0
- package/.agents/scripts/lib/orchestration/plan-review-routing.js +63 -0
- package/.agents/scripts/lib/orchestration/plan-runner/plan-router.js +86 -0
- package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +212 -0
- package/.agents/scripts/lib/orchestration/planning-context-budget.js +213 -0
- package/.agents/scripts/lib/orchestration/planning-risk.js +155 -0
- package/.agents/scripts/lib/orchestration/planning-state-manager.js +318 -0
- package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +56 -0
- package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +33 -0
- package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +78 -0
- package/.agents/scripts/lib/orchestration/post-merge/phases/temp-cleanup.js +68 -0
- package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +118 -0
- package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +396 -0
- package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +205 -0
- package/.agents/scripts/lib/orchestration/pr-base-guard.js +47 -0
- package/.agents/scripts/lib/orchestration/preflight-cache.js +164 -0
- package/.agents/scripts/lib/orchestration/reassert-status-column.js +202 -0
- package/.agents/scripts/lib/orchestration/reconciler.js +137 -0
- package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +152 -0
- package/.agents/scripts/lib/orchestration/recut.js +56 -0
- package/.agents/scripts/lib/orchestration/resolves-token.js +127 -0
- package/.agents/scripts/lib/orchestration/retro/phases/checks.js +94 -0
- package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +448 -0
- package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +335 -0
- package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +133 -0
- package/.agents/scripts/lib/orchestration/retro-heuristics.js +57 -0
- package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +275 -0
- package/.agents/scripts/lib/orchestration/retro-proposals.js +395 -0
- package/.agents/scripts/lib/orchestration/retro-runner.js +171 -0
- package/.agents/scripts/lib/orchestration/review-depth.js +93 -0
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +363 -0
- package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +205 -0
- package/.agents/scripts/lib/orchestration/review-providers/native.js +805 -0
- package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +73 -0
- package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +396 -0
- package/.agents/scripts/lib/orchestration/review-providers/security-review.js +373 -0
- package/.agents/scripts/lib/orchestration/review-providers/types.js +89 -0
- package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +107 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +159 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +194 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +81 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +190 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +70 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +106 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +42 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +73 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +225 -0
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +315 -0
- package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +149 -0
- package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +110 -0
- package/.agents/scripts/lib/orchestration/spec-freshness.js +320 -0
- package/.agents/scripts/lib/orchestration/spec-renderer.js +456 -0
- package/.agents/scripts/lib/orchestration/spec-section-validator.js +80 -0
- package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +797 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +163 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +152 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +387 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +266 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +48 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +67 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +161 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +117 -0
- package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +86 -0
- package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +147 -0
- package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +142 -0
- package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +62 -0
- package/.agents/scripts/lib/orchestration/story-close/format-autofix-scoped.js +221 -0
- package/.agents/scripts/lib/orchestration/story-close/format-autofix-shared.js +123 -0
- package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +216 -0
- package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +636 -0
- package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +198 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +105 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/close.js +222 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +220 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +291 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +234 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +110 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +86 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +112 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +157 -0
- package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +434 -0
- package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +290 -0
- package/.agents/scripts/lib/orchestration/story-close-recovery.js +643 -0
- package/.agents/scripts/lib/orchestration/structured-comment-parser.js +67 -0
- package/.agents/scripts/lib/orchestration/task-body-validator.js +391 -0
- package/.agents/scripts/lib/orchestration/ticket-lease.js +358 -0
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +783 -0
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +367 -0
- package/.agents/scripts/lib/orchestration/ticket-validator.js +691 -0
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +723 -0
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +474 -0
- package/.agents/scripts/lib/orchestration/ticketing/state.js +559 -0
- package/.agents/scripts/lib/orchestration/ticketing.js +55 -0
- package/.agents/scripts/lib/orchestration/wave-marker.js +28 -0
- package/.agents/scripts/lib/orchestration/wave-record-io.js +277 -0
- package/.agents/scripts/lib/orchestration/wave-record-notifications.js +189 -0
- package/.agents/scripts/lib/orchestration/wave-record-projection.js +423 -0
- package/.agents/scripts/lib/path-security.js +25 -0
- package/.agents/scripts/lib/plan-phase-cleanup.js +125 -0
- package/.agents/scripts/lib/preflight-runner.js +196 -0
- package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +95 -0
- package/.agents/scripts/lib/presentation/manifest-builder.js +245 -0
- package/.agents/scripts/lib/presentation/manifest-formatter.js +243 -0
- package/.agents/scripts/lib/presentation/manifest-helpers.js +213 -0
- package/.agents/scripts/lib/presentation/manifest-persistence.js +262 -0
- package/.agents/scripts/lib/presentation/manifest-procedures.js +55 -0
- package/.agents/scripts/lib/presentation/manifest-render-waves.js +252 -0
- package/.agents/scripts/lib/presentation/manifest-renderer.js +188 -0
- package/.agents/scripts/lib/presentation/manifest-story-views.js +119 -0
- package/.agents/scripts/lib/provider-factory.js +80 -0
- package/.agents/scripts/lib/push-epic-retry.js +209 -0
- package/.agents/scripts/lib/qa/console-allowlist.js +151 -0
- package/.agents/scripts/lib/qa/coverage-report.js +181 -0
- package/.agents/scripts/lib/qa/coverage-verdict.js +296 -0
- package/.agents/scripts/lib/qa/propose-missing-test.js +95 -0
- package/.agents/scripts/lib/qa/qa-context-hydrator.js +296 -0
- package/.agents/scripts/lib/qa/qa-session.js +197 -0
- package/.agents/scripts/lib/qa/redact-evidence.js +245 -0
- package/.agents/scripts/lib/qa/resolve-qa-contract.js +190 -0
- package/.agents/scripts/lib/qa/resolve-selection.js +373 -0
- package/.agents/scripts/lib/runtime-deps/ensure-installed.js +100 -0
- package/.agents/scripts/lib/runtime-deps/manifest.js +96 -0
- package/.agents/scripts/lib/runtime-deps/preflight.js +78 -0
- package/.agents/scripts/lib/runtime-deps/scan-imports.js +202 -0
- package/.agents/scripts/lib/signals/detectors/common.js +36 -0
- package/.agents/scripts/lib/signals/detectors/hotspot.js +298 -0
- package/.agents/scripts/lib/signals/detectors/index.js +14 -0
- package/.agents/scripts/lib/signals/detectors/retry.js +289 -0
- package/.agents/scripts/lib/signals/detectors/rework.js +204 -0
- package/.agents/scripts/lib/signals/index.js +39 -0
- package/.agents/scripts/lib/signals/read.js +268 -0
- package/.agents/scripts/lib/signals/schema.js +225 -0
- package/.agents/scripts/lib/signals/span-tree.js +290 -0
- package/.agents/scripts/lib/signals/write.js +19 -0
- package/.agents/scripts/lib/single-story/confirm-merge.js +201 -0
- package/.agents/scripts/lib/single-story/story-merged-notify.js +126 -0
- package/.agents/scripts/lib/single-story-sweep/protection.js +274 -0
- package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +169 -0
- package/.agents/scripts/lib/single-story-sweep.js +329 -0
- package/.agents/scripts/lib/skills/parse-skill.js +202 -0
- package/.agents/scripts/lib/skills/walk-skill-files.js +56 -0
- package/.agents/scripts/lib/spec/index.js +36 -0
- package/.agents/scripts/lib/spec/loader.js +425 -0
- package/.agents/scripts/lib/spec/state.js +217 -0
- package/.agents/scripts/lib/story-body/story-body.js +743 -0
- package/.agents/scripts/lib/story-init/blocker-validator.js +68 -0
- package/.agents/scripts/lib/story-init/branch-initializer.js +422 -0
- package/.agents/scripts/lib/story-init/context-resolver.js +92 -0
- package/.agents/scripts/lib/story-init/donor-precheck.js +207 -0
- package/.agents/scripts/lib/story-init/hierarchy-tracer.js +36 -0
- package/.agents/scripts/lib/story-init/state-transitioner.js +80 -0
- package/.agents/scripts/lib/story-init/task-graph-builder.js +114 -0
- package/.agents/scripts/lib/story-init/transition-summary.js +34 -0
- package/.agents/scripts/lib/story-lifecycle.js +186 -0
- package/.agents/scripts/lib/story-plan.js +246 -0
- package/.agents/scripts/lib/task-utils.js +26 -0
- package/.agents/scripts/lib/templates/decomposer-prompts.js +168 -0
- package/.agents/scripts/lib/test-env.js +30 -0
- package/.agents/scripts/lib/test-isolate/env-snapshot-loader.js +52 -0
- package/.agents/scripts/lib/test-isolate/list-files.js +90 -0
- package/.agents/scripts/lib/test-isolate/parse-tap.js +75 -0
- package/.agents/scripts/lib/test-isolate/runner.js +483 -0
- package/.agents/scripts/lib/test-profile/parse-tap.js +136 -0
- package/.agents/scripts/lib/test-profile/render-report.js +45 -0
- package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +35 -0
- package/.agents/scripts/lib/test-tiers.js +94 -0
- package/.agents/scripts/lib/util/concurrent-map.js +59 -0
- package/.agents/scripts/lib/util/phase-timer-state.js +72 -0
- package/.agents/scripts/lib/util/phase-timer.js +163 -0
- package/.agents/scripts/lib/util/poll-loop.js +86 -0
- package/.agents/scripts/lib/util/with-timeout.js +32 -0
- package/.agents/scripts/lib/validation-evidence.js +323 -0
- package/.agents/scripts/lib/wave-runner/tick.js +665 -0
- package/.agents/scripts/lib/wave-runner/wave-checkpoint.js +91 -0
- package/.agents/scripts/lib/wave-runner/wave-runner-error.js +19 -0
- package/.agents/scripts/lib/workers/crap-worker.js +197 -0
- package/.agents/scripts/lib/workers/maintainability-report-worker.js +137 -0
- package/.agents/scripts/lib/workers/maintainability-worker.js +79 -0
- package/.agents/scripts/lib/workspace-provisioner.js +189 -0
- package/.agents/scripts/lib/worktree/bootstrapper.js +48 -0
- package/.agents/scripts/lib/worktree/inspector.js +140 -0
- package/.agents/scripts/lib/worktree/lifecycle/creation.js +118 -0
- package/.agents/scripts/lib/worktree/lifecycle/drift-detection.js +62 -0
- package/.agents/scripts/lib/worktree/lifecycle/force-drain.js +276 -0
- package/.agents/scripts/lib/worktree/lifecycle/gc.js +49 -0
- package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +178 -0
- package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +264 -0
- package/.agents/scripts/lib/worktree/lifecycle/precheck.js +100 -0
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +588 -0
- package/.agents/scripts/lib/worktree/lifecycle/registry-sync.js +124 -0
- package/.agents/scripts/lib/worktree/lifecycle/shared.js +26 -0
- package/.agents/scripts/lib/worktree/lifecycle-manager.js +40 -0
- package/.agents/scripts/lib/worktree/node-modules-strategy.js +349 -0
- package/.agents/scripts/lib/worktree-manager.js +243 -0
- package/.agents/scripts/lifecycle-diff.js +206 -0
- package/.agents/scripts/lifecycle-emit-story-dispatch.js +194 -0
- package/.agents/scripts/lifecycle-emit.js +479 -0
- package/.agents/scripts/lint-baseline.js +507 -0
- package/.agents/scripts/lint-label-vocabulary.js +237 -0
- package/.agents/scripts/loc-delta.js +205 -0
- package/.agents/scripts/notify.js +307 -0
- package/.agents/scripts/package.json +3 -0
- package/.agents/scripts/post-structured-comment.js +127 -0
- package/.agents/scripts/pr-watch-with-update.js +152 -0
- package/.agents/scripts/providers/github/auth.js +65 -0
- package/.agents/scripts/providers/github/board-add.js +63 -0
- package/.agents/scripts/providers/github/branch-protection.js +186 -0
- package/.agents/scripts/providers/github/cache.js +72 -0
- package/.agents/scripts/providers/github/comments.js +131 -0
- package/.agents/scripts/providers/github/compose.js +111 -0
- package/.agents/scripts/providers/github/errors.js +242 -0
- package/.agents/scripts/providers/github/issues.js +242 -0
- package/.agents/scripts/providers/github/labels.js +179 -0
- package/.agents/scripts/providers/github/mappers.js +126 -0
- package/.agents/scripts/providers/github/merge-methods.js +82 -0
- package/.agents/scripts/providers/github/project-board.js +47 -0
- package/.agents/scripts/providers/github/projects-v2-graphql.js +472 -0
- package/.agents/scripts/providers/github/prs.js +103 -0
- package/.agents/scripts/providers/github/request-helpers.js +110 -0
- package/.agents/scripts/providers/github/sub-issues.js +369 -0
- package/.agents/scripts/providers/github/tickets.js +381 -0
- package/.agents/scripts/providers/github/transient-retry.js +62 -0
- package/.agents/scripts/providers/github.js +157 -0
- package/.agents/scripts/quality-preview.js +327 -0
- package/.agents/scripts/quality-watch.js +223 -0
- package/.agents/scripts/render-manifest.js +143 -0
- package/.agents/scripts/resync-status-column.js +176 -0
- package/.agents/scripts/retro-run.js +167 -0
- package/.agents/scripts/run-audit-suite.js +97 -0
- package/.agents/scripts/run-coverage.js +103 -0
- package/.agents/scripts/run-lint.js +94 -0
- package/.agents/scripts/run-test-profile.js +126 -0
- package/.agents/scripts/run-tests.js +185 -0
- package/.agents/scripts/run-verify.js +56 -0
- package/.agents/scripts/select-audits.js +155 -0
- package/.agents/scripts/signals-view.js +294 -0
- package/.agents/scripts/single-story-close.js +83 -0
- package/.agents/scripts/single-story-confirm-merge.js +183 -0
- package/.agents/scripts/single-story-init.js +692 -0
- package/.agents/scripts/stories-wave-tick.js +415 -0
- package/.agents/scripts/story-close.js +246 -0
- package/.agents/scripts/story-deliver-prepare.js +267 -0
- package/.agents/scripts/story-init.js +516 -0
- package/.agents/scripts/story-phase.js +327 -0
- package/.agents/scripts/story-plan.js +284 -0
- package/.agents/scripts/sync-agentrc.js +71 -0
- package/.agents/scripts/sync-branch-from-base.js +138 -0
- package/.agents/scripts/sync-claude-commands.js +151 -0
- package/.agents/scripts/test-isolate.js +222 -0
- package/.agents/scripts/test-wrapper.js +108 -0
- package/.agents/scripts/update-coverage-baseline.js +129 -0
- package/.agents/scripts/update-crap-baseline.js +177 -0
- package/.agents/scripts/update-duplication-baseline.js +134 -0
- package/.agents/scripts/update-maintainability-baseline.js +183 -0
- package/.agents/scripts/update-mutation-baseline.js +189 -0
- package/.agents/scripts/update-ticket-state.js +107 -0
- package/.agents/scripts/validate-docs-freshness.js +259 -0
- package/.agents/scripts/validate-skills.js +278 -0
- package/.agents/scripts/wave-tick.js +335 -0
- package/.agents/skills/core/analyze-execution/SKILL.md +98 -0
- package/.agents/skills/core/api-and-interface-design/SKILL.md +327 -0
- package/.agents/skills/core/baseline-refresh/SKILL.md +181 -0
- package/.agents/skills/core/browser-testing-with-devtools/SKILL.md +352 -0
- package/.agents/skills/core/ci-cd-and-automation/SKILL.md +274 -0
- package/.agents/skills/core/ci-cd-and-automation/examples.md +211 -0
- package/.agents/skills/core/code-review-and-quality/SKILL.md +421 -0
- package/.agents/skills/core/code-simplification/SKILL.md +389 -0
- package/.agents/skills/core/context-engineering/SKILL.md +309 -0
- package/.agents/skills/core/context-engineering/examples.md +58 -0
- package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +338 -0
- package/.agents/skills/core/deprecation-and-migration/SKILL.md +250 -0
- package/.agents/skills/core/diagnose-friction/SKILL.md +79 -0
- package/.agents/skills/core/documentation-and-adrs/SKILL.md +323 -0
- package/.agents/skills/core/epic-plan-consolidate/SKILL.md +145 -0
- package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +425 -0
- package/.agents/skills/core/epic-plan-spec-author/SKILL.md +393 -0
- package/.agents/skills/core/frontend-ui-engineering/SKILL.md +357 -0
- package/.agents/skills/core/git-workflow-and-versioning/SKILL.md +352 -0
- package/.agents/skills/core/hydrate-context/SKILL.md +118 -0
- package/.agents/skills/core/idea-refinement/SKILL.md +317 -0
- package/.agents/skills/core/idea-refinement/examples.md +437 -0
- package/.agents/skills/core/idea-refinement/frameworks.md +135 -0
- package/.agents/skills/core/idea-refinement/refinement-criteria.md +155 -0
- package/.agents/skills/core/idea-refinement/scripts/idea-refine.sh +15 -0
- package/.agents/skills/core/incremental-implementation/SKILL.md +271 -0
- package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +213 -0
- package/.agents/skills/core/knowledge-transfer/SKILL.md +175 -0
- package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +117 -0
- package/.agents/skills/core/performance-optimization/SKILL.md +314 -0
- package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +277 -0
- package/.agents/skills/core/property-based-testing/SKILL.md +148 -0
- package/.agents/skills/core/qa-coverage-mapping/SKILL.md +105 -0
- package/.agents/skills/core/refactoring-discipline/SKILL.md +111 -0
- package/.agents/skills/core/scope-triage/SKILL.md +127 -0
- package/.agents/skills/core/security-and-hardening/SKILL.md +400 -0
- package/.agents/skills/core/shipping-and-launch/SKILL.md +328 -0
- package/.agents/skills/core/spec-driven-development/SKILL.md +252 -0
- package/.agents/skills/core/test-driven-development/SKILL.md +475 -0
- package/.agents/skills/core/using-agent-skills/SKILL.md +232 -0
- package/.agents/skills/skills.index.json +596 -0
- package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +31 -0
- package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +51 -0
- package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +48 -0
- package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +31 -0
- package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +33 -0
- package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +31 -0
- package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +51 -0
- package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +54 -0
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +29 -0
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +30 -0
- package/.agents/skills/stack/backend/stripe-integration/SKILL.md +57 -0
- package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +9 -0
- package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +48 -0
- package/.agents/skills/stack/frontend/astro/SKILL.md +62 -0
- package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +30 -0
- package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +29 -0
- package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +50 -0
- package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +58 -0
- package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +34 -0
- package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +51 -0
- package/.agents/skills/stack/qa/gherkin-authoring/SKILL.md +257 -0
- package/.agents/skills/stack/qa/gherkin-authoring/examples/invoice-issue.feature +41 -0
- package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +199 -0
- package/.agents/skills/stack/qa/playwright/SKILL.md +50 -0
- package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +188 -0
- package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +142 -0
- package/.agents/skills/stack/qa/qa-harness/SKILL.md +220 -0
- package/.agents/skills/stack/qa/vitest/SKILL.md +51 -0
- package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +68 -0
- package/.agents/starter-agentrc.json +22 -0
- package/.agents/templates/agent-protocol.md +72 -0
- package/.agents/templates/docs/architecture.md +30 -0
- package/.agents/templates/docs/decisions.md +24 -0
- package/.agents/templates/epic-from-idea.md +21 -0
- package/.agents/templates/single-story-body.md +17 -0
- package/.agents/workflows/agents-update.md +415 -0
- package/.agents/workflows/audit-architecture.md +312 -0
- package/.agents/workflows/audit-clean-code.md +179 -0
- package/.agents/workflows/audit-dependencies.md +91 -0
- package/.agents/workflows/audit-devops.md +110 -0
- package/.agents/workflows/audit-lighthouse.md +260 -0
- package/.agents/workflows/audit-performance.md +161 -0
- package/.agents/workflows/audit-privacy.md +104 -0
- package/.agents/workflows/audit-quality.md +191 -0
- package/.agents/workflows/audit-security.md +156 -0
- package/.agents/workflows/audit-seo.md +118 -0
- package/.agents/workflows/audit-sre.md +139 -0
- package/.agents/workflows/audit-to-stories.md +257 -0
- package/.agents/workflows/audit-ux-ui.md +102 -0
- package/.agents/workflows/epic-deliver.md +864 -0
- package/.agents/workflows/epic-plan.md +998 -0
- package/.agents/workflows/explain.md +118 -0
- package/.agents/workflows/git-cleanup.md +250 -0
- package/.agents/workflows/git-commit-all.md +15 -0
- package/.agents/workflows/git-merge-pr.md +377 -0
- package/.agents/workflows/git-pr-all.md +278 -0
- package/.agents/workflows/git-push.md +60 -0
- package/.agents/workflows/helpers/_merge-conflict-template.md +54 -0
- package/.agents/workflows/helpers/acceptance-self-eval.md +74 -0
- package/.agents/workflows/helpers/agents-sync-config.md +129 -0
- package/.agents/workflows/helpers/code-quality-guardrails.md +101 -0
- package/.agents/workflows/helpers/code-review.md +370 -0
- package/.agents/workflows/helpers/diagnose.md +117 -0
- package/.agents/workflows/helpers/epic-audit.md +295 -0
- package/.agents/workflows/helpers/epic-deliver-story.md +370 -0
- package/.agents/workflows/helpers/epic-plan-decompose.md +199 -0
- package/.agents/workflows/helpers/epic-plan-spec.md +184 -0
- package/.agents/workflows/helpers/epic-testing.md +125 -0
- package/.agents/workflows/helpers/parallel-tooling.md +88 -0
- package/.agents/workflows/helpers/signals.md +112 -0
- package/.agents/workflows/helpers/single-story-deliver.md +636 -0
- package/.agents/workflows/helpers/worktree-lifecycle.md +317 -0
- package/.agents/workflows/onboard.md +207 -0
- package/.agents/workflows/qa-assist.md +293 -0
- package/.agents/workflows/qa-explore.md +350 -0
- package/.agents/workflows/qa-run-harness.md +288 -0
- package/.agents/workflows/story-deliver.md +327 -0
- package/.agents/workflows/story-plan.md +233 -0
- package/LICENSE +21 -0
- package/README.md +193 -0
- package/bin/mandrel.js +56 -0
- package/bin/postinstall.js +195 -0
- package/lib/cli/__tests__/migrate.test.js +268 -0
- package/lib/cli/__tests__/sync-local-zone.test.js +247 -0
- package/lib/cli/__tests__/sync.test.js +372 -0
- package/lib/cli/__tests__/update-major.test.js +217 -0
- package/lib/cli/__tests__/update.test.js +696 -0
- package/lib/cli/__tests__/version-check.test.js +398 -0
- package/lib/cli/doctor.js +124 -0
- package/lib/cli/explain.js +107 -0
- package/lib/cli/migrate.js +260 -0
- package/lib/cli/registry.js +830 -0
- package/lib/cli/sync-commands.js +50 -0
- package/lib/cli/sync.js +200 -0
- package/lib/cli/uninstall.js +795 -0
- package/lib/cli/update.js +854 -0
- package/lib/cli/version-check.js +206 -0
- package/lib/migrations/README.md +69 -0
- package/lib/migrations/__tests__/index.test.js +216 -0
- package/lib/migrations/index.js +164 -0
- package/package.json +105 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* render.js — pure rendering helpers for git-cleanup (Story #2466).
|
|
3
|
+
*
|
|
4
|
+
* Owns the text + JSON envelope renderers and the `computeExitCode`
|
|
5
|
+
* helper. Extracted verbatim from `git-cleanup.js` so every named export
|
|
6
|
+
* keeps its contract.
|
|
7
|
+
*
|
|
8
|
+
* @module lib/orchestration/git-cleanup/phases/render
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const TAG = '[git-cleanup]';
|
|
12
|
+
|
|
13
|
+
/** Pure: render the dry-run plan as the operator-facing text block. */
|
|
14
|
+
export function renderDryRun(plan, opts = {}) {
|
|
15
|
+
const { baseBranch = null } = opts;
|
|
16
|
+
const lines = [
|
|
17
|
+
`${TAG} DRY RUN (nothing deleted) — ${plan.candidates.length} candidate(s)`,
|
|
18
|
+
];
|
|
19
|
+
if (plan.candidates.length === 0) {
|
|
20
|
+
lines.push(' (no merged branches to clean up)');
|
|
21
|
+
} else {
|
|
22
|
+
for (const c of plan.candidates) {
|
|
23
|
+
const pr = c.prNumber ? `PR #${c.prNumber}` : c.detectedBy;
|
|
24
|
+
const wt = c.hasWorktree ? ` (worktree: ${c.worktreePath})` : '';
|
|
25
|
+
const remoteOnly = c.localExists === false ? ' (remote-only)' : '';
|
|
26
|
+
lines.push(` • ${c.branch} — ${pr}${wt}${remoteOnly}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const skipped = plan.skipped ?? [];
|
|
30
|
+
const currentHeadSkip = skipped.find((s) => s.reason === 'current-head');
|
|
31
|
+
if (currentHeadSkip) {
|
|
32
|
+
const hint = baseBranch
|
|
33
|
+
? `checkout ${baseBranch} first to include this branch`
|
|
34
|
+
: 'checkout the base branch first to include this branch';
|
|
35
|
+
lines.push(
|
|
36
|
+
`${TAG} ⓘ ${currentHeadSkip.branch} skipped — current HEAD (${hint})`,
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
for (const skip of skipped) {
|
|
40
|
+
const line = renderLatestPrSkipLine(skip);
|
|
41
|
+
if (line) lines.push(line);
|
|
42
|
+
}
|
|
43
|
+
return lines;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Pure: render a single latest-PR-state skip line. Returns null when the
|
|
48
|
+
* skip reason is not one of the latest-PR family — `renderDryRun` filters
|
|
49
|
+
* by truthy return value so unrelated skip reasons (`protected`,
|
|
50
|
+
* `current-head`, `filtered`, `not-merged`) stay quiet.
|
|
51
|
+
*
|
|
52
|
+
* @param {{ branch: string, reason: string, prNumber?: number, tipSha?: string, mergedSha?: string }} skip
|
|
53
|
+
* @returns {string | null}
|
|
54
|
+
*/
|
|
55
|
+
export function renderLatestPrSkipLine(skip) {
|
|
56
|
+
if (!skip) return null;
|
|
57
|
+
const prRef = skip.prNumber ? `PR #${skip.prNumber}` : 'latest PR';
|
|
58
|
+
if (skip.reason === 'latest-pr-closed-not-merged') {
|
|
59
|
+
return `${TAG} ⏭️ ${skip.branch} skipped — ${prRef} was closed without merging`;
|
|
60
|
+
}
|
|
61
|
+
if (skip.reason === 'latest-pr-open') {
|
|
62
|
+
return `${TAG} ⏭️ ${skip.branch} skipped — ${prRef} is still open`;
|
|
63
|
+
}
|
|
64
|
+
if (skip.reason === 'tip-diverged-from-merge') {
|
|
65
|
+
const tip = skip.tipSha ? skip.tipSha.slice(0, 7) : '<unknown>';
|
|
66
|
+
const merged = skip.mergedSha ? skip.mergedSha.slice(0, 7) : '<unknown>';
|
|
67
|
+
return `${TAG} ⏭️ ${skip.branch} skipped — tip ${tip} diverges from ${prRef}'s merged ${merged} (post-merge force-push)`;
|
|
68
|
+
}
|
|
69
|
+
if (skip.reason === 'latest-pr-unknown-state') {
|
|
70
|
+
return `${TAG} ⏭️ ${skip.branch} skipped — ${prRef} has an unrecognized state`;
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Pure: render a per-branch execution line. */
|
|
76
|
+
export function renderExecutionLine(entry, scope) {
|
|
77
|
+
const icon = entry.ok ? '✅' : '❌';
|
|
78
|
+
const label = scope.padEnd(8);
|
|
79
|
+
const tag =
|
|
80
|
+
scope === 'local' || scope === 'remote' ? entry.branch : entry.path;
|
|
81
|
+
const note = entry.alreadyGone
|
|
82
|
+
? ' (already gone)'
|
|
83
|
+
: entry.dirty
|
|
84
|
+
? ' (forced — was dirty)'
|
|
85
|
+
: '';
|
|
86
|
+
return `${TAG} ${icon} ${label} ${tag}${note}`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Pure: render the optional prune line. */
|
|
90
|
+
export function renderPruneLine(prune) {
|
|
91
|
+
if (!prune?.attempted) return null;
|
|
92
|
+
if (!prune.ok) {
|
|
93
|
+
return `${TAG} ❌ prune ${prune.remote} (${prune.stderr ?? 'failed'})`;
|
|
94
|
+
}
|
|
95
|
+
if (prune.pruned.length === 0) {
|
|
96
|
+
return `${TAG} ✅ prune ${prune.remote} (no stale refs)`;
|
|
97
|
+
}
|
|
98
|
+
const list = prune.pruned.map((n) => `${prune.remote}/${n}`).join(', ');
|
|
99
|
+
return `${TAG} ✅ prune ${prune.remote} (dropped ${prune.pruned.length} stale ref(s): ${list})`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Pure: render a single deferred-worktree line. A lock-class
|
|
104
|
+
* worktree-removal failure (Windows file lock on an already-merged
|
|
105
|
+
* branch's directory) is non-fatal — the branch ref was still reaped and
|
|
106
|
+
* the directory is handed off to the pending-cleanup sweep. Returns the
|
|
107
|
+
* operator-facing warning so the deferred signal is visible even on a
|
|
108
|
+
* clean (`ok: true`) run.
|
|
109
|
+
*
|
|
110
|
+
* @param {{ branch?: string, path: string, pendingCleanup?: object|null }} entry
|
|
111
|
+
* @returns {string}
|
|
112
|
+
*/
|
|
113
|
+
export function renderDeferredLine(entry) {
|
|
114
|
+
const ref = entry.branch ? `${entry.branch} ` : '';
|
|
115
|
+
const handoff = entry.pendingCleanup
|
|
116
|
+
? ' (deferred to pending-cleanup sweep)'
|
|
117
|
+
: ' (deferred)';
|
|
118
|
+
return `${TAG} ⚠️ deferred ${ref}${entry.path} — worktree locked; ref reaped${handoff}`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Pure: render the trailing summary line. */
|
|
122
|
+
export function renderExecutionSummary(result) {
|
|
123
|
+
if (!result.ok) {
|
|
124
|
+
return `${TAG} ❌ ${result.failures.length} failure(s) during cleanup.`;
|
|
125
|
+
}
|
|
126
|
+
const prunedCount = result.prune?.pruned?.length ?? 0;
|
|
127
|
+
const pruneNote =
|
|
128
|
+
prunedCount > 0 ? ` + ${prunedCount} stale tracking ref(s)` : '';
|
|
129
|
+
const deferredCount = result.deferred?.length ?? 0;
|
|
130
|
+
const deferredNote =
|
|
131
|
+
deferredCount > 0
|
|
132
|
+
? ` (${deferredCount} worktree(s) deferred to sweep)`
|
|
133
|
+
: '';
|
|
134
|
+
return `${TAG} ✅ Reaped ${result.local.length} local + ${result.remote.length} remote + ${result.worktrees.length} worktree(s)${pruneNote}.${deferredNote}`;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const EMPTY_RESULT = Object.freeze({
|
|
138
|
+
worktrees: [],
|
|
139
|
+
local: [],
|
|
140
|
+
remote: [],
|
|
141
|
+
prune: null,
|
|
142
|
+
failures: [],
|
|
143
|
+
deferred: [],
|
|
144
|
+
ok: true,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
/** Pure: build the JSON envelope emitted in `--json` mode. */
|
|
148
|
+
export function buildJsonEnvelope({
|
|
149
|
+
dryRun,
|
|
150
|
+
baseBranch,
|
|
151
|
+
plan,
|
|
152
|
+
result,
|
|
153
|
+
fastForward = null,
|
|
154
|
+
prune = null,
|
|
155
|
+
stashes = null,
|
|
156
|
+
}) {
|
|
157
|
+
const r = result ?? EMPTY_RESULT;
|
|
158
|
+
return {
|
|
159
|
+
dryRun,
|
|
160
|
+
baseBranch,
|
|
161
|
+
candidates: plan.candidates,
|
|
162
|
+
skipped: plan.skipped,
|
|
163
|
+
worktrees: r.worktrees,
|
|
164
|
+
local: r.local,
|
|
165
|
+
remote: r.remote,
|
|
166
|
+
prune: r.prune ?? prune ?? null,
|
|
167
|
+
fastForward,
|
|
168
|
+
stashes,
|
|
169
|
+
failures: r.failures,
|
|
170
|
+
deferred: r.deferred ?? [],
|
|
171
|
+
ok: r.ok,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function legacyExitCode(plan, result) {
|
|
176
|
+
if ((plan?.candidates?.length ?? 0) === 0) return 2;
|
|
177
|
+
if (result && !result.ok) return 1;
|
|
178
|
+
return 0;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Pure: derive the process exit code. Supports both the legacy
|
|
183
|
+
* `(plan, result)` signature and the new multi-phase context object.
|
|
184
|
+
*
|
|
185
|
+
* @param {{ candidates?: Array, branchesPlan?: object, branchesResult?: object, fastForward?: object, prune?: object, stashes?: object } | { candidates: Array }} ctx
|
|
186
|
+
* @param {{ ok: boolean } | null | undefined} [legacyResult]
|
|
187
|
+
* @returns {0 | 1 | 2}
|
|
188
|
+
*/
|
|
189
|
+
export function computeExitCode(ctx, legacyResult) {
|
|
190
|
+
if (legacyResult !== undefined || Array.isArray(ctx?.candidates)) {
|
|
191
|
+
return legacyExitCode(ctx, legacyResult);
|
|
192
|
+
}
|
|
193
|
+
const {
|
|
194
|
+
branchesPlan = null,
|
|
195
|
+
branchesResult = null,
|
|
196
|
+
fastForward = null,
|
|
197
|
+
prune = null,
|
|
198
|
+
stashes = null,
|
|
199
|
+
} = ctx ?? {};
|
|
200
|
+
const anyFailure =
|
|
201
|
+
(branchesResult && !branchesResult.ok) ||
|
|
202
|
+
(fastForward && !fastForward.ok) ||
|
|
203
|
+
(prune && !prune.ok) ||
|
|
204
|
+
(stashes && !stashes.ok);
|
|
205
|
+
if (anyFailure) return 1;
|
|
206
|
+
const anyWork =
|
|
207
|
+
(branchesPlan && branchesPlan.candidates.length > 0) ||
|
|
208
|
+
fastForward?.applied ||
|
|
209
|
+
(prune && (prune.pruned?.length ?? 0) > 0) ||
|
|
210
|
+
(stashes &&
|
|
211
|
+
(stashes.actions ?? []).some((a) => a.action === 'drop' && a.dropped));
|
|
212
|
+
if (!anyWork) return 2;
|
|
213
|
+
return 0;
|
|
214
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* stashes.js — stash-triage phase of git-cleanup (Story #2466).
|
|
3
|
+
*
|
|
4
|
+
* Owns `parseStashList`, `planStashes`, `executeStashes`, `stashRefIndex`,
|
|
5
|
+
* and `buildAllowlistDecider`. Extracted verbatim from `git-cleanup.js`.
|
|
6
|
+
*
|
|
7
|
+
* @module lib/orchestration/git-cleanup/phases/stashes
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { gitSpawn } from '../../../git-utils.js';
|
|
11
|
+
import { Logger } from '../../../Logger.js';
|
|
12
|
+
import { dropStash } from './git-probes.js';
|
|
13
|
+
|
|
14
|
+
const TAG = '[git-cleanup]';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Pure: parse `git stash list --format='%gd|%ci|%s'` output into
|
|
18
|
+
* structured stash entries.
|
|
19
|
+
*/
|
|
20
|
+
export function parseStashList(stdout) {
|
|
21
|
+
const out = [];
|
|
22
|
+
for (const raw of (stdout ?? '').split('\n')) {
|
|
23
|
+
const line = raw.trim();
|
|
24
|
+
if (!line) continue;
|
|
25
|
+
const idx = line.indexOf('|');
|
|
26
|
+
if (idx < 0) continue;
|
|
27
|
+
const ref = line.slice(0, idx).trim();
|
|
28
|
+
const rest = line.slice(idx + 1);
|
|
29
|
+
const idx2 = rest.indexOf('|');
|
|
30
|
+
if (idx2 < 0) continue;
|
|
31
|
+
const createdAt = rest.slice(0, idx2).trim();
|
|
32
|
+
const message = rest.slice(idx2 + 1).trim();
|
|
33
|
+
if (!ref) continue;
|
|
34
|
+
out.push({ ref, createdAt, message });
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* node:coverage ignore next */
|
|
40
|
+
function listStashes(cwd) {
|
|
41
|
+
const res = gitSpawn(cwd, 'stash', 'list', '--format=%gd|%ci|%s');
|
|
42
|
+
if (res.status !== 0) return [];
|
|
43
|
+
return parseStashList(res.stdout);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Plan the stash phase: enumerate stashes, no mutation. */
|
|
47
|
+
export function planStashes(ctx) {
|
|
48
|
+
const { cwd, stashListerFn = listStashes } = ctx;
|
|
49
|
+
return { stashes: stashListerFn(cwd) };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Pure: extract the numeric index from a stash ref like `stash@{3}`.
|
|
54
|
+
*/
|
|
55
|
+
export function stashRefIndex(ref) {
|
|
56
|
+
const m = /^stash@\{(\d+)\}$/.exec(ref ?? '');
|
|
57
|
+
return m ? Number(m[1]) : -1;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Build a non-interactive `decideFn` that drops stashes whose refs
|
|
62
|
+
* appear in `allowlist`, and keeps every other stash. Used in JSON /
|
|
63
|
+
* --yes mode.
|
|
64
|
+
*/
|
|
65
|
+
export function buildAllowlistDecider(allowlist) {
|
|
66
|
+
const set = new Set(allowlist ?? []);
|
|
67
|
+
return (entry) => (set.has(entry.ref) ? 'drop' : 'keep');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function applyDecision({
|
|
71
|
+
s,
|
|
72
|
+
decideFn,
|
|
73
|
+
dropFn,
|
|
74
|
+
cwd,
|
|
75
|
+
actions,
|
|
76
|
+
failures,
|
|
77
|
+
logger,
|
|
78
|
+
}) {
|
|
79
|
+
const decision = decideFn(s);
|
|
80
|
+
if (decision === 'quit') {
|
|
81
|
+
actions.push({ ref: s.ref, action: 'quit' });
|
|
82
|
+
return { quit: true };
|
|
83
|
+
}
|
|
84
|
+
if (decision === 'keep') {
|
|
85
|
+
actions.push({ ref: s.ref, action: 'keep' });
|
|
86
|
+
return { quit: false };
|
|
87
|
+
}
|
|
88
|
+
const res = dropFn(s.ref, cwd);
|
|
89
|
+
if (res.ok) {
|
|
90
|
+
logger.info?.(`${TAG} ✅ dropped ${s.ref}: ${s.message}`);
|
|
91
|
+
actions.push({ ref: s.ref, action: 'drop', dropped: true });
|
|
92
|
+
} else {
|
|
93
|
+
logger.warn?.(`${TAG} ❌ drop ${s.ref} failed: ${res.stderr}`);
|
|
94
|
+
actions.push({
|
|
95
|
+
ref: s.ref,
|
|
96
|
+
action: 'drop',
|
|
97
|
+
dropped: false,
|
|
98
|
+
stderr: res.stderr,
|
|
99
|
+
});
|
|
100
|
+
failures.push({ ref: s.ref, stderr: res.stderr });
|
|
101
|
+
}
|
|
102
|
+
return { quit: false };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Execute the stash phase. Dispatches per-stash via the injected
|
|
107
|
+
* `decideFn` so interactive prompts (readline) and non-interactive
|
|
108
|
+
* allowlists (`--drop-stashes <ref>`) share the same engine.
|
|
109
|
+
*/
|
|
110
|
+
export function executeStashes(ctx) {
|
|
111
|
+
const { cwd, stashes, decideFn, dropFn = dropStash, logger = Logger } = ctx;
|
|
112
|
+
const actions = [];
|
|
113
|
+
const failures = [];
|
|
114
|
+
let quit = false;
|
|
115
|
+
// Drop stashes high-index-first so the indices of remaining stashes
|
|
116
|
+
// stay stable across calls — git renumbers from the top of the stack.
|
|
117
|
+
const ordered = [...stashes].sort(
|
|
118
|
+
(a, b) => stashRefIndex(b.ref) - stashRefIndex(a.ref),
|
|
119
|
+
);
|
|
120
|
+
for (const s of ordered) {
|
|
121
|
+
if (quit) {
|
|
122
|
+
actions.push({ ref: s.ref, action: 'quit' });
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const out = applyDecision({
|
|
126
|
+
s,
|
|
127
|
+
decideFn,
|
|
128
|
+
dropFn,
|
|
129
|
+
cwd,
|
|
130
|
+
actions,
|
|
131
|
+
failures,
|
|
132
|
+
logger,
|
|
133
|
+
});
|
|
134
|
+
if (out.quit) quit = true;
|
|
135
|
+
}
|
|
136
|
+
return { ok: failures.length === 0, actions, failures };
|
|
137
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* label-transitions.js — readability wrappers over `transitionTicketState`.
|
|
3
|
+
*
|
|
4
|
+
* These are deliberately thin: each helper names the *target* state and
|
|
5
|
+
* forwards to the underlying SDK call. They exist so that init / close /
|
|
6
|
+
* deliver-tail call sites read as prose ("toExecuting(provider, taskId)")
|
|
7
|
+
* instead of forcing readers to parse the `STATE_LABELS.X` constant at
|
|
8
|
+
* every call site.
|
|
9
|
+
*
|
|
10
|
+
* Not an abstraction — the underlying `transitionTicketState` remains the
|
|
11
|
+
* authoritative single-ticket transition path. Opts are forwarded verbatim.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { STATE_LABELS, transitionTicketState } from './ticketing.js';
|
|
15
|
+
|
|
16
|
+
/** Transition a ticket to `agent::executing`. */
|
|
17
|
+
export function toExecuting(provider, ticketId, opts) {
|
|
18
|
+
return transitionTicketState(
|
|
19
|
+
provider,
|
|
20
|
+
ticketId,
|
|
21
|
+
STATE_LABELS.EXECUTING,
|
|
22
|
+
opts,
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Transition an array of tickets to `agent::done`, in order. Each call
|
|
28
|
+
* triggers its own cascade (via `transitionTicketState`). Failures for
|
|
29
|
+
* individual tickets propagate — callers that need per-ticket tolerance
|
|
30
|
+
* should use `batchTransitionTickets` instead.
|
|
31
|
+
*
|
|
32
|
+
* @param {object} provider
|
|
33
|
+
* @param {number[]} ticketIds
|
|
34
|
+
* @param {object} [opts]
|
|
35
|
+
*/
|
|
36
|
+
export async function toDone(provider, ticketIds, opts) {
|
|
37
|
+
if (!Array.isArray(ticketIds)) {
|
|
38
|
+
throw new TypeError('toDone: ticketIds must be an array');
|
|
39
|
+
}
|
|
40
|
+
for (const id of ticketIds) {
|
|
41
|
+
await transitionTicketState(provider, id, STATE_LABELS.DONE, opts);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
// .agents/scripts/lib/orchestration/lifecycle/bus.js
|
|
2
|
+
/**
|
|
3
|
+
* Lifecycle event bus — sequential awaited mediator.
|
|
4
|
+
*
|
|
5
|
+
* The bus is the only authorized emitter of typed lifecycle events. It is a
|
|
6
|
+
* mediator (not pub/sub): listeners run in registration order, awaited,
|
|
7
|
+
* and a throw in any listener short-circuits the remaining listeners and
|
|
8
|
+
* propagates to the caller. There is no Promise.all over listener arrays
|
|
9
|
+
* — that pattern breaks repeatability and is forbidden by the lint rule in
|
|
10
|
+
* `biome.json`.
|
|
11
|
+
*
|
|
12
|
+
* Wildcard subscriptions (`bus.on('*', fn)`) are permitted for trace /
|
|
13
|
+
* heartbeat observers. They MUST NOT perform side effects on the system
|
|
14
|
+
* under orchestration; the firewall against state-mutating imports in
|
|
15
|
+
* wildcard listeners is documented in
|
|
16
|
+
* `.agents/scripts/lib/orchestration/lifecycle/listeners/README.md`.
|
|
17
|
+
*
|
|
18
|
+
* Schema validation: `emit()` validates the payload against the schema at
|
|
19
|
+
* `.agents/schemas/lifecycle/<event>.schema.json` BEFORE invoking any
|
|
20
|
+
* listener. Validation failures throw immediately; no `emitted` ledger
|
|
21
|
+
* record is written, no listener runs. This guarantees that every record
|
|
22
|
+
* in the ledger carries a payload conformant to its event schema.
|
|
23
|
+
*
|
|
24
|
+
* The bus does NOT write the ledger directly. `LedgerWriter` registers as
|
|
25
|
+
* the first listener on every event and handles persistence. This keeps
|
|
26
|
+
* the bus a pure mediator and makes the ledger boundary easy to fake in
|
|
27
|
+
* tests.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { readFileSync } from 'node:fs';
|
|
31
|
+
import path from 'node:path';
|
|
32
|
+
import { fileURLToPath } from 'node:url';
|
|
33
|
+
|
|
34
|
+
import Ajv2020 from 'ajv/dist/2020.js';
|
|
35
|
+
import addFormats from 'ajv-formats';
|
|
36
|
+
|
|
37
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
38
|
+
const DEFAULT_SCHEMA_DIR = path.resolve(
|
|
39
|
+
__dirname,
|
|
40
|
+
'..',
|
|
41
|
+
'..',
|
|
42
|
+
'..',
|
|
43
|
+
'..',
|
|
44
|
+
'schemas',
|
|
45
|
+
'lifecycle',
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Compile a validator for a single event by loading its schema lazily. The
|
|
50
|
+
* result is cached per Bus instance so repeated emits of the same event
|
|
51
|
+
* don't re-parse JSON.
|
|
52
|
+
*/
|
|
53
|
+
function buildValidator(ajv, schemaDir, event) {
|
|
54
|
+
const schemaPath = path.join(schemaDir, `${event}.schema.json`);
|
|
55
|
+
const schema = JSON.parse(readFileSync(schemaPath, 'utf8'));
|
|
56
|
+
return ajv.compile(schema);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Format AJV error array into a single-line message suitable for a thrown
|
|
61
|
+
* Error. Reviewers prefer a compact summary over a stringified blob.
|
|
62
|
+
*/
|
|
63
|
+
function formatAjvErrors(errors) {
|
|
64
|
+
if (!Array.isArray(errors) || errors.length === 0) return 'invalid payload';
|
|
65
|
+
return errors
|
|
66
|
+
.map((e) => `${e.instancePath || '/'} ${e.message}`.trim())
|
|
67
|
+
.join('; ');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export class Bus {
|
|
71
|
+
/**
|
|
72
|
+
* @param {object} [opts]
|
|
73
|
+
* @param {string} [opts.schemaDir] absolute path to the lifecycle schema
|
|
74
|
+
* directory. Defaults to `.agents/schemas/lifecycle/` resolved against
|
|
75
|
+
* this module's location. Tests pass a fixture directory.
|
|
76
|
+
*/
|
|
77
|
+
constructor(opts = {}) {
|
|
78
|
+
this._schemaDir = opts.schemaDir ?? DEFAULT_SCHEMA_DIR;
|
|
79
|
+
this._ajv = new Ajv2020({ allErrors: true });
|
|
80
|
+
addFormats(this._ajv);
|
|
81
|
+
/** @type {Map<string, Array<{ fn: Function, wildcard: boolean }>>} */
|
|
82
|
+
this._listeners = new Map();
|
|
83
|
+
/** @type {Array<{ fn: Function, wildcard: boolean }>} */
|
|
84
|
+
this._wildcards = [];
|
|
85
|
+
/** @type {Map<string, Function>} cached AJV validators. */
|
|
86
|
+
this._validators = new Map();
|
|
87
|
+
this._nextSeqId = 1;
|
|
88
|
+
/**
|
|
89
|
+
* Hooks that run AFTER schema validation + seqId assignment but
|
|
90
|
+
* BEFORE any listener. LedgerWriter installs an `onEmitted` hook
|
|
91
|
+
* here so its `emitted` ledger line lands on disk before downstream
|
|
92
|
+
* listeners execute (the resume contract depends on this).
|
|
93
|
+
*
|
|
94
|
+
* Hooks are NOT regular listeners and intentionally not exposed via
|
|
95
|
+
* `bus.on()` — they are a privileged seam used by the ledger writer
|
|
96
|
+
* and (later) the resume coordinator. Each hook receives the same
|
|
97
|
+
* `{ event, seqId, payload }` context shape a listener sees.
|
|
98
|
+
*
|
|
99
|
+
* Hooks run sequentially with await, in registration order. A throw
|
|
100
|
+
* from a hook is treated like a thrown listener — it propagates to
|
|
101
|
+
* the caller and short-circuits everything after it.
|
|
102
|
+
*
|
|
103
|
+
* @type {Array<(ctx: {event: string, seqId: number, payload: object}) => unknown | Promise<unknown>>}
|
|
104
|
+
*/
|
|
105
|
+
this._onEmittedHooks = [];
|
|
106
|
+
/**
|
|
107
|
+
* Hooks that run AFTER every listener resolves successfully — the
|
|
108
|
+
* `completed` boundary. LedgerWriter installs an `onCompleted` hook
|
|
109
|
+
* to write its `completed` ledger line. Same execution contract as
|
|
110
|
+
* `_onEmittedHooks` (sequential, awaited, registration order).
|
|
111
|
+
*
|
|
112
|
+
* @type {Array<(ctx: {event: string, seqId: number, payload: object}) => unknown | Promise<unknown>>}
|
|
113
|
+
*/
|
|
114
|
+
this._onCompletedHooks = [];
|
|
115
|
+
/**
|
|
116
|
+
* Hooks that run when a listener throws — the `failed` boundary.
|
|
117
|
+
* They receive the same context PLUS the error and the inferred
|
|
118
|
+
* listener name (best-effort; `bus` does not currently annotate
|
|
119
|
+
* which listener threw, but the LedgerWriter hook tags `unknown`
|
|
120
|
+
* when no annotation is present).
|
|
121
|
+
*
|
|
122
|
+
* @type {Array<(ctx: {event: string, seqId: number, payload: object, listener: string, error: Error}) => unknown | Promise<unknown>>}
|
|
123
|
+
*/
|
|
124
|
+
this._onFailedHooks = [];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Privileged seam — install a hook that runs after schema validation
|
|
129
|
+
* and seqId assignment but BEFORE any listener for the event. Used by
|
|
130
|
+
* LedgerWriter to land the `emitted` ledger record on disk before any
|
|
131
|
+
* downstream side effect runs (resume contract).
|
|
132
|
+
*/
|
|
133
|
+
onEmitted(fn) {
|
|
134
|
+
if (typeof fn !== 'function') {
|
|
135
|
+
throw new TypeError('Bus.onEmitted: hook must be a function');
|
|
136
|
+
}
|
|
137
|
+
this._onEmittedHooks.push(fn);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Privileged seam — install a hook that runs AFTER every listener for
|
|
142
|
+
* the event resolves. Used by LedgerWriter to land the `completed`
|
|
143
|
+
* ledger record.
|
|
144
|
+
*/
|
|
145
|
+
onCompleted(fn) {
|
|
146
|
+
if (typeof fn !== 'function') {
|
|
147
|
+
throw new TypeError('Bus.onCompleted: hook must be a function');
|
|
148
|
+
}
|
|
149
|
+
this._onCompletedHooks.push(fn);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Privileged seam — install a hook that runs when a listener throws.
|
|
154
|
+
* Used by LedgerWriter to land the `failed` ledger record before
|
|
155
|
+
* re-propagating.
|
|
156
|
+
*/
|
|
157
|
+
onFailed(fn) {
|
|
158
|
+
if (typeof fn !== 'function') {
|
|
159
|
+
throw new TypeError('Bus.onFailed: hook must be a function');
|
|
160
|
+
}
|
|
161
|
+
this._onFailedHooks.push(fn);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Register a listener. Use `event === '*'` for a wildcard observer; the
|
|
166
|
+
* `wildcard: true` flag is set on the listener record so the lint rule
|
|
167
|
+
* (and downstream reviewers) can identify observer-only listeners.
|
|
168
|
+
*
|
|
169
|
+
* Returns an unsubscribe function for symmetry with conventional emitter
|
|
170
|
+
* APIs; the runner doesn't currently use it, but tests do.
|
|
171
|
+
*/
|
|
172
|
+
on(event, fn) {
|
|
173
|
+
if (typeof fn !== 'function') {
|
|
174
|
+
throw new TypeError('Bus.on: listener must be a function');
|
|
175
|
+
}
|
|
176
|
+
if (typeof event !== 'string' || event.length === 0) {
|
|
177
|
+
throw new TypeError('Bus.on: event must be a non-empty string');
|
|
178
|
+
}
|
|
179
|
+
const record = { fn, wildcard: event === '*' };
|
|
180
|
+
if (event === '*') {
|
|
181
|
+
this._wildcards.push(record);
|
|
182
|
+
return () => {
|
|
183
|
+
this._wildcards = this._wildcards.filter((r) => r !== record);
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
const list = this._listeners.get(event) ?? [];
|
|
187
|
+
list.push(record);
|
|
188
|
+
this._listeners.set(event, list);
|
|
189
|
+
return () => {
|
|
190
|
+
const next = (this._listeners.get(event) ?? []).filter(
|
|
191
|
+
(r) => r !== record,
|
|
192
|
+
);
|
|
193
|
+
if (next.length === 0) this._listeners.delete(event);
|
|
194
|
+
else this._listeners.set(event, next);
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Get (and cache) the compiled AJV validator for a given event.
|
|
200
|
+
*/
|
|
201
|
+
_getValidator(event) {
|
|
202
|
+
let validator = this._validators.get(event);
|
|
203
|
+
if (!validator) {
|
|
204
|
+
validator = buildValidator(this._ajv, this._schemaDir, event);
|
|
205
|
+
this._validators.set(event, validator);
|
|
206
|
+
}
|
|
207
|
+
return validator;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Emit a typed event.
|
|
212
|
+
*
|
|
213
|
+
* Contract (Tech Spec § Bus contract):
|
|
214
|
+
* 1. validate payload (throw before any listener runs on mismatch);
|
|
215
|
+
* 2. assign monotonic per-run seqId;
|
|
216
|
+
* 3. invoke registered named listeners sequentially with await;
|
|
217
|
+
* 4. invoke wildcard listeners sequentially with await AFTER named
|
|
218
|
+
* listeners (observer order);
|
|
219
|
+
* 5. propagate the first thrown error.
|
|
220
|
+
*
|
|
221
|
+
* The bus does NOT write the ledger directly; LedgerWriter is wired in
|
|
222
|
+
* by the runner as the first registered named listener for every event.
|
|
223
|
+
*
|
|
224
|
+
* @param {string} event
|
|
225
|
+
* @param {object} payload
|
|
226
|
+
* @returns {Promise<{ seqId: number }>}
|
|
227
|
+
*/
|
|
228
|
+
async emit(event, payload) {
|
|
229
|
+
if (typeof event !== 'string' || event.length === 0) {
|
|
230
|
+
throw new TypeError('Bus.emit: event must be a non-empty string');
|
|
231
|
+
}
|
|
232
|
+
const validator = this._getValidator(event);
|
|
233
|
+
const ok = validator(payload);
|
|
234
|
+
if (!ok) {
|
|
235
|
+
const err = new Error(
|
|
236
|
+
`Bus.emit: schema validation failed for "${event}": ${formatAjvErrors(validator.errors)}`,
|
|
237
|
+
);
|
|
238
|
+
err.code = 'BUS_SCHEMA_VALIDATION';
|
|
239
|
+
err.event = event;
|
|
240
|
+
err.ajvErrors = validator.errors;
|
|
241
|
+
throw err;
|
|
242
|
+
}
|
|
243
|
+
const seqId = this._nextSeqId;
|
|
244
|
+
this._nextSeqId += 1;
|
|
245
|
+
const context = { event, seqId, payload };
|
|
246
|
+
// Privileged onEmitted hooks run BEFORE any listener — gives
|
|
247
|
+
// LedgerWriter the seam to land the `emitted` line on disk before
|
|
248
|
+
// any downstream side effect (resume contract).
|
|
249
|
+
for (const hook of this._onEmittedHooks) {
|
|
250
|
+
await hook(context);
|
|
251
|
+
}
|
|
252
|
+
const named = this._listeners.get(event) ?? [];
|
|
253
|
+
try {
|
|
254
|
+
for (const record of named) {
|
|
255
|
+
await record.fn(context);
|
|
256
|
+
}
|
|
257
|
+
for (const record of this._wildcards) {
|
|
258
|
+
await record.fn(context);
|
|
259
|
+
}
|
|
260
|
+
} catch (err) {
|
|
261
|
+
// Failed boundary — let writers/observers persist before we
|
|
262
|
+
// propagate. Listener name annotation is best-effort: when the
|
|
263
|
+
// error carries `.listener`, we honor it; otherwise we tag
|
|
264
|
+
// 'unknown' so the ledger record still validates against
|
|
265
|
+
// `ledger-record.schema.json` (which requires a `listener` field
|
|
266
|
+
// on failed records).
|
|
267
|
+
const listener =
|
|
268
|
+
(err && typeof err.listener === 'string' && err.listener) || 'unknown';
|
|
269
|
+
const failedCtx = { ...context, listener, error: err };
|
|
270
|
+
for (const hook of this._onFailedHooks) {
|
|
271
|
+
// Hook errors are intentionally swallowed here so we don't
|
|
272
|
+
// mask the originating listener error. The runner only sees the
|
|
273
|
+
// original throw.
|
|
274
|
+
try {
|
|
275
|
+
await hook(failedCtx);
|
|
276
|
+
} catch (hookErr) {
|
|
277
|
+
// Surface to stderr so a misbehaving writer doesn't go silent,
|
|
278
|
+
// but do not propagate — original error wins.
|
|
279
|
+
process.stderr.write(
|
|
280
|
+
`[Bus.onFailed] hook threw while recording failure for "${event}" (seqId=${seqId}): ${hookErr.message}\n`,
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
throw err;
|
|
285
|
+
}
|
|
286
|
+
// Completed boundary — writers persist `completed` after every
|
|
287
|
+
// listener resolves.
|
|
288
|
+
for (const hook of this._onCompletedHooks) {
|
|
289
|
+
await hook(context);
|
|
290
|
+
}
|
|
291
|
+
return { seqId };
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Inspect the next seqId without emitting. Useful for tests asserting
|
|
296
|
+
* monotonicity across multiple bus instances or after replay.
|
|
297
|
+
*/
|
|
298
|
+
peekNextSeqId() {
|
|
299
|
+
return this._nextSeqId;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Convenience factory. Lets the runner own bus construction without
|
|
305
|
+
* importing the class name directly.
|
|
306
|
+
*/
|
|
307
|
+
export function createBus(opts = {}) {
|
|
308
|
+
return new Bus(opts);
|
|
309
|
+
}
|