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,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* donor-precheck.js — verify the symlink-strategy donor is primed.
|
|
3
|
+
*
|
|
4
|
+
* When `delivery.worktreeIsolation.nodeModulesStrategy === 'symlink'`, every
|
|
5
|
+
* Story worktree junctions/symlinks its `node_modules/` from a donor (the
|
|
6
|
+
* `primeFromPath` directory, typically the repo root). If the donor lacks
|
|
7
|
+
* `node_modules/` the symlink will resolve to nothing and the worktree
|
|
8
|
+
* cannot install or run tests. This module runs once, just before
|
|
9
|
+
* `applyNodeModulesStrategy`, to make sure the donor is primed.
|
|
10
|
+
*
|
|
11
|
+
* The pre-check is idempotent across concurrent wave dispatches via a
|
|
12
|
+
* filesystem lock directory at `<donor>/.agents-donor-precheck.lock`. The
|
|
13
|
+
* first arrival creates the lock atomically (`fs.mkdirSync`), runs
|
|
14
|
+
* `npm ci`, and removes the lock. Concurrent callers either skip
|
|
15
|
+
* (donor already primed) or wait for the lock to clear and re-check
|
|
16
|
+
* existence — they do not double-run the installer.
|
|
17
|
+
*
|
|
18
|
+
* The helpers are split so the pure decision logic (`planDonorAction`) is
|
|
19
|
+
* trivially testable without filesystem or child-process side-effects.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { spawnSync } from 'node:child_process';
|
|
23
|
+
import nodeFs from 'node:fs';
|
|
24
|
+
import nodePath from 'node:path';
|
|
25
|
+
|
|
26
|
+
const LOCK_DIRNAME = '.agents-donor-precheck.lock';
|
|
27
|
+
const LOCK_POLL_INTERVAL_MS = 100;
|
|
28
|
+
const LOCK_WAIT_TIMEOUT_MS = 5 * 60_000;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Pure: decide whether the donor needs a one-shot install.
|
|
32
|
+
*
|
|
33
|
+
* Returns one of:
|
|
34
|
+
* - `{ action: 'skip', reason }` — strategy is not symlink, or donor
|
|
35
|
+
* already has node_modules.
|
|
36
|
+
* - `{ action: 'install', donorPath }` — caller should run install at
|
|
37
|
+
* `donorPath`.
|
|
38
|
+
*
|
|
39
|
+
* @param {object} opts
|
|
40
|
+
* @param {string} opts.strategy The configured `nodeModulesStrategy`.
|
|
41
|
+
* @param {string|null} opts.primeFromPath Relative donor path.
|
|
42
|
+
* @param {string} opts.repoRoot Absolute repo root.
|
|
43
|
+
* @param {{ existsSync: (p: string) => boolean }} [opts.fs]
|
|
44
|
+
* Filesystem facade for tests.
|
|
45
|
+
* @returns {{ action: 'skip', reason: string } | { action: 'install', donorPath: string }}
|
|
46
|
+
*/
|
|
47
|
+
export function planDonorAction({
|
|
48
|
+
strategy,
|
|
49
|
+
primeFromPath,
|
|
50
|
+
repoRoot,
|
|
51
|
+
fs = nodeFs,
|
|
52
|
+
path = nodePath,
|
|
53
|
+
}) {
|
|
54
|
+
if (strategy !== 'symlink') {
|
|
55
|
+
return { action: 'skip', reason: 'strategy-not-symlink' };
|
|
56
|
+
}
|
|
57
|
+
if (!primeFromPath) {
|
|
58
|
+
return { action: 'skip', reason: 'no-prime-from-path' };
|
|
59
|
+
}
|
|
60
|
+
const donorPath = path.resolve(repoRoot, primeFromPath);
|
|
61
|
+
if (fs.existsSync(path.join(donorPath, 'node_modules'))) {
|
|
62
|
+
return { action: 'skip', reason: 'donor-already-primed' };
|
|
63
|
+
}
|
|
64
|
+
return { action: 'install', donorPath };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Wait for the donor lock directory to be removed by the lock holder.
|
|
69
|
+
* Returns true if the lock cleared in time, false on timeout.
|
|
70
|
+
*
|
|
71
|
+
* Exported for tests.
|
|
72
|
+
*/
|
|
73
|
+
export function waitForLockClear({
|
|
74
|
+
lockPath,
|
|
75
|
+
fs = nodeFs,
|
|
76
|
+
pollIntervalMs = LOCK_POLL_INTERVAL_MS,
|
|
77
|
+
timeoutMs = LOCK_WAIT_TIMEOUT_MS,
|
|
78
|
+
now = () => Date.now(),
|
|
79
|
+
sleepFn,
|
|
80
|
+
}) {
|
|
81
|
+
const start = now();
|
|
82
|
+
const sleep =
|
|
83
|
+
sleepFn ??
|
|
84
|
+
((ms) => {
|
|
85
|
+
const signal = new Int32Array(new SharedArrayBuffer(4));
|
|
86
|
+
Atomics.wait(signal, 0, 0, ms);
|
|
87
|
+
});
|
|
88
|
+
while (fs.existsSync(lockPath)) {
|
|
89
|
+
if (now() - start >= timeoutMs) return false;
|
|
90
|
+
sleep(pollIntervalMs);
|
|
91
|
+
}
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Ensure the symlink-strategy donor is primed. Runs at most once per
|
|
97
|
+
* dispatch wave because the lock directory is created atomically with
|
|
98
|
+
* `fs.mkdirSync` (EEXIST = another concurrent process already won).
|
|
99
|
+
*
|
|
100
|
+
* Behaviour by lock outcome:
|
|
101
|
+
* - Lock acquired → run `npm ci`, then remove the lock.
|
|
102
|
+
* - Lock contended → wait for the lock to clear, then re-check
|
|
103
|
+
* existence. If `node_modules` is now present, skip; otherwise,
|
|
104
|
+
* surface an error (the lock holder failed and the caller cannot
|
|
105
|
+
* safely proceed).
|
|
106
|
+
*
|
|
107
|
+
* @param {object} opts
|
|
108
|
+
* @param {string} opts.strategy
|
|
109
|
+
* @param {string|null} opts.primeFromPath
|
|
110
|
+
* @param {string} opts.repoRoot
|
|
111
|
+
* @param {{ progress?: (kind: string, msg: string) => void }} [opts.logger]
|
|
112
|
+
* @param {{ existsSync: typeof nodeFs.existsSync, mkdirSync: typeof nodeFs.mkdirSync, rmSync: typeof nodeFs.rmSync }} [opts.fs]
|
|
113
|
+
* @param {typeof spawnSync} [opts.spawnFn] Injected installer for tests.
|
|
114
|
+
* @param {(opts: object) => boolean} [opts.waitFn] Injected lock waiter.
|
|
115
|
+
* @returns {{ action: 'skip' | 'installed' | 'waited', reason?: string, donorPath?: string, durationMs?: number }}
|
|
116
|
+
*/
|
|
117
|
+
export function ensureDonorPrimed({
|
|
118
|
+
strategy,
|
|
119
|
+
primeFromPath,
|
|
120
|
+
repoRoot,
|
|
121
|
+
logger,
|
|
122
|
+
fs = nodeFs,
|
|
123
|
+
path = nodePath,
|
|
124
|
+
spawnFn = spawnSync,
|
|
125
|
+
waitFn = waitForLockClear,
|
|
126
|
+
now = () => Date.now(),
|
|
127
|
+
}) {
|
|
128
|
+
const t0 = now();
|
|
129
|
+
const progress = logger?.progress ?? (() => {});
|
|
130
|
+
const plan = planDonorAction({ strategy, primeFromPath, repoRoot, fs, path });
|
|
131
|
+
if (plan.action === 'skip') {
|
|
132
|
+
return { action: 'skip', reason: plan.reason, durationMs: now() - t0 };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const { donorPath } = plan;
|
|
136
|
+
const lockPath = path.join(donorPath, LOCK_DIRNAME);
|
|
137
|
+
let lockAcquired = false;
|
|
138
|
+
try {
|
|
139
|
+
fs.mkdirSync(lockPath);
|
|
140
|
+
lockAcquired = true;
|
|
141
|
+
} catch (err) {
|
|
142
|
+
if (err.code !== 'EEXIST') throw err;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!lockAcquired) {
|
|
146
|
+
progress('DONOR-PRECHECK', `donor=${donorPath} lock contended, waiting...`);
|
|
147
|
+
const cleared = waitFn({ lockPath, fs });
|
|
148
|
+
if (!cleared) {
|
|
149
|
+
throw new Error(
|
|
150
|
+
`donor-precheck: timed out waiting for lock ${lockPath} to clear after ${LOCK_WAIT_TIMEOUT_MS}ms`,
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
if (!fs.existsSync(path.join(donorPath, 'node_modules'))) {
|
|
154
|
+
throw new Error(
|
|
155
|
+
`donor-precheck: lock holder released ${lockPath} without priming node_modules at ${donorPath}`,
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
progress(
|
|
159
|
+
'DONOR-PRECHECK',
|
|
160
|
+
`donor=${donorPath} primed by concurrent dispatch, proceeding.`,
|
|
161
|
+
);
|
|
162
|
+
return { action: 'waited', donorPath, durationMs: now() - t0 };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
// Re-check between mkdir and install: another process could have run
|
|
167
|
+
// and finished while we were racing on mkdirSync.
|
|
168
|
+
if (fs.existsSync(path.join(donorPath, 'node_modules'))) {
|
|
169
|
+
progress(
|
|
170
|
+
'DONOR-PRECHECK',
|
|
171
|
+
`donor=${donorPath} already primed (post-lock recheck), skipping install.`,
|
|
172
|
+
);
|
|
173
|
+
return {
|
|
174
|
+
action: 'skip',
|
|
175
|
+
reason: 'donor-primed-post-lock',
|
|
176
|
+
donorPath,
|
|
177
|
+
durationMs: now() - t0,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
progress(
|
|
181
|
+
'DONOR-PRECHECK',
|
|
182
|
+
`donor=${donorPath} missing node_modules — running one-shot npm ci...`,
|
|
183
|
+
);
|
|
184
|
+
const result = spawnFn('npm', ['ci'], {
|
|
185
|
+
cwd: donorPath,
|
|
186
|
+
stdio: 'inherit',
|
|
187
|
+
shell: process.platform === 'win32',
|
|
188
|
+
timeout: 10 * 60_000,
|
|
189
|
+
});
|
|
190
|
+
if (result.status !== 0) {
|
|
191
|
+
throw new Error(
|
|
192
|
+
`donor-precheck: 'npm ci' at ${donorPath} exited with status ${result.status}`,
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
progress('DONOR-PRECHECK', `donor=${donorPath} primed in ${now() - t0}ms.`);
|
|
196
|
+
return { action: 'installed', donorPath, durationMs: now() - t0 };
|
|
197
|
+
} finally {
|
|
198
|
+
try {
|
|
199
|
+
fs.rmSync(lockPath, { recursive: true, force: true });
|
|
200
|
+
} catch (_err) {
|
|
201
|
+
// Best-effort lock release; subsequent runs will recover by
|
|
202
|
+
// re-checking node_modules existence.
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export const __LOCK_DIRNAME = LOCK_DIRNAME;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Logger } from '../Logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* hierarchy-tracer.js — Stage 2 of the story-init pipeline.
|
|
4
|
+
*
|
|
5
|
+
* Given an epicId, resolves the linked PRD and Tech Spec issue IDs by
|
|
6
|
+
* fetching the Epic. Fetch failures are logged but non-fatal — the result
|
|
7
|
+
* simply reports `null` for whichever linkage could not be resolved, which
|
|
8
|
+
* mirrors legacy behaviour in story-init.js.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {object} deps
|
|
13
|
+
* @param {object} deps.provider
|
|
14
|
+
* @param {object} [deps.logger]
|
|
15
|
+
* @param {object} deps.input
|
|
16
|
+
* @param {number} deps.input.epicId
|
|
17
|
+
* @returns {Promise<{ prdId: number|null, techSpecId: number|null }>}
|
|
18
|
+
*/
|
|
19
|
+
export async function traceHierarchy({ provider, logger, input }) {
|
|
20
|
+
const { epicId } = input;
|
|
21
|
+
const warn = logger?.warn ?? ((msg) => Logger.error(msg));
|
|
22
|
+
|
|
23
|
+
let prdId = null;
|
|
24
|
+
let techSpecId = null;
|
|
25
|
+
try {
|
|
26
|
+
const epic = await provider.getEpic(epicId);
|
|
27
|
+
prdId = epic.linkedIssues?.prd ?? null;
|
|
28
|
+
techSpecId = epic.linkedIssues?.techSpec ?? null;
|
|
29
|
+
} catch (err) {
|
|
30
|
+
warn(
|
|
31
|
+
`[story-init] Warning: Could not fetch Epic #${epicId}: ${err.message}`,
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return { prdId, techSpecId };
|
|
36
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* state-transitioner.js — Stage 6 of the story-init pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Flips the Story ticket to `agent::executing` at init time. Under the
|
|
5
|
+
* 3-tier hierarchy the Story has inline acceptance and no child Task
|
|
6
|
+
* lifecycle — `/story-deliver` runs a single Story-implementation phase.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
STATE_LABELS,
|
|
11
|
+
transitionTicketState,
|
|
12
|
+
} from '../orchestration/ticketing.js';
|
|
13
|
+
import { batchTransitionTickets } from '../story-lifecycle.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Flip the Story to `agent::executing` and cascade upward (Epic / Feature).
|
|
17
|
+
*
|
|
18
|
+
* @param {object} deps
|
|
19
|
+
* @param {object} deps.provider
|
|
20
|
+
* @param {object} [deps.logger]
|
|
21
|
+
* @param {object} deps.input
|
|
22
|
+
* @param {number} deps.input.storyId
|
|
23
|
+
* @param {object} deps.input.story - Prefetched Story ticket (`ticketSnapshot`).
|
|
24
|
+
* @param {Function|null} [deps.input.notify]
|
|
25
|
+
* @returns {Promise<{ ok: true }>}
|
|
26
|
+
*/
|
|
27
|
+
export async function transitionStoryToExecuting({ provider, logger, input }) {
|
|
28
|
+
const { storyId, story, notify = null } = input;
|
|
29
|
+
const progress = logger?.progress ?? (() => {});
|
|
30
|
+
|
|
31
|
+
progress('TICKETS', `Transitioning Story #${storyId} to agent::executing...`);
|
|
32
|
+
await transitionTicketState(provider, storyId, STATE_LABELS.EXECUTING, {
|
|
33
|
+
ticketSnapshot: story,
|
|
34
|
+
cascade: true,
|
|
35
|
+
notify,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return { ok: true };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Batch-transitions every child Task to a target label. Retained for
|
|
43
|
+
* `batchTransitionTickets` unit coverage and post-merge batch closes;
|
|
44
|
+
* story-init no longer calls this at startup.
|
|
45
|
+
*
|
|
46
|
+
* @param {object} deps
|
|
47
|
+
* @param {object} deps.provider
|
|
48
|
+
* @param {object} [deps.logger]
|
|
49
|
+
* @param {object} deps.input
|
|
50
|
+
* @param {Array<object>} deps.input.tasks
|
|
51
|
+
* @param {Function|null} [deps.input.notify]
|
|
52
|
+
* @returns {Promise<{
|
|
53
|
+
* ok: boolean,
|
|
54
|
+
* failed: Array<{id:number,attempts:number,error:string}>,
|
|
55
|
+
* transitioned: number[],
|
|
56
|
+
* skipped: number[],
|
|
57
|
+
* }>}
|
|
58
|
+
*/
|
|
59
|
+
export async function transitionTaskStates({ provider, logger, input }) {
|
|
60
|
+
const { tasks, notify = null } = input;
|
|
61
|
+
const progress = logger?.progress ?? (() => {});
|
|
62
|
+
|
|
63
|
+
progress(
|
|
64
|
+
'TICKETS',
|
|
65
|
+
`Transitioning ${tasks.length} Task(s) to agent::executing...`,
|
|
66
|
+
);
|
|
67
|
+
const transitionResult = await batchTransitionTickets(
|
|
68
|
+
provider,
|
|
69
|
+
tasks,
|
|
70
|
+
STATE_LABELS.EXECUTING,
|
|
71
|
+
{ progress, notify },
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
ok: transitionResult.failed.length === 0,
|
|
76
|
+
failed: transitionResult.failed,
|
|
77
|
+
transitioned: transitionResult.transitioned,
|
|
78
|
+
skipped: transitionResult.skipped,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* task-graph-builder.js — Stage 4 of the story-init pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Enumerates child Tasks of the Story, then topologically sorts them using
|
|
5
|
+
* `blocked by` edges that reference other Tasks in the same set. Inter-Task
|
|
6
|
+
* dependencies outside the child set are ignored (they are handled by the
|
|
7
|
+
* Story-level blocker validator).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { parseBlockedBy } from '../dependency-parser.js';
|
|
11
|
+
import { buildGraph, detectCycle, topologicalSort } from '../Graph.js';
|
|
12
|
+
import { Logger } from '../Logger.js';
|
|
13
|
+
import { fetchChildTickets } from '../story-lifecycle.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Detect whether a Story body carries inline acceptance criteria, the
|
|
17
|
+
* structural signal that the Story is authored in the 3-tier
|
|
18
|
+
* (Story-with-inline-acceptance) shape and therefore should not be expected
|
|
19
|
+
* to enumerate child Task tickets. Recognises both `## Acceptance` and
|
|
20
|
+
* `## Acceptance Criteria` headings, with at least one list bullet under
|
|
21
|
+
* them (mirroring the heading set the manifest-builder extracts).
|
|
22
|
+
*
|
|
23
|
+
* @param {string} body
|
|
24
|
+
* @returns {boolean}
|
|
25
|
+
*/
|
|
26
|
+
export function hasInlineAcceptance(body) {
|
|
27
|
+
if (typeof body !== 'string' || body.length === 0) return false;
|
|
28
|
+
const headingRe = /^##\s+Acceptance(?:\s+Criteria)?\s*$/im;
|
|
29
|
+
const match = body.match(headingRe);
|
|
30
|
+
if (!match || match.index == null) return false;
|
|
31
|
+
const rest = body.slice(match.index + match[0].length);
|
|
32
|
+
const nextHeading = rest.search(/^##\s+/m);
|
|
33
|
+
const block = nextHeading === -1 ? rest : rest.slice(0, nextHeading);
|
|
34
|
+
for (const rawLine of block.split(/\r?\n/)) {
|
|
35
|
+
const line = rawLine.trim();
|
|
36
|
+
if (/^[-*]\s+(?:\[[ xX]\]\s+)?\S/.test(line)) return true;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function sortTasksByDependencies(tasks) {
|
|
42
|
+
if (tasks.length <= 1) return tasks;
|
|
43
|
+
|
|
44
|
+
const graphTasks = tasks.map((t) => ({
|
|
45
|
+
...t,
|
|
46
|
+
dependsOn: parseBlockedBy(t.body ?? '').filter((dep) =>
|
|
47
|
+
tasks.some((tt) => tt.id === dep),
|
|
48
|
+
),
|
|
49
|
+
}));
|
|
50
|
+
const { adjacency, taskMap } = buildGraph(graphTasks);
|
|
51
|
+
|
|
52
|
+
const cycle = detectCycle(adjacency);
|
|
53
|
+
if (cycle) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`[story-init] Dependency cycle detected among child tasks: ` +
|
|
56
|
+
`#${cycle.join(' → #')}. Fix the \`blocked by\` references before retrying.`,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return topologicalSort(adjacency, taskMap);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @param {object} deps
|
|
65
|
+
* @param {object} deps.provider
|
|
66
|
+
* @param {object} [deps.logger]
|
|
67
|
+
* @param {object} deps.input
|
|
68
|
+
* @param {number} deps.input.storyId
|
|
69
|
+
* @param {string} [deps.input.storyBody] Story body — used to detect
|
|
70
|
+
* whether the Story carries inline acceptance (3-tier shape) so the
|
|
71
|
+
* empty-Task-list path is treated as expected rather than as a warning.
|
|
72
|
+
*
|
|
73
|
+
* Task #3154 (Epic #3078) deleted the `planning.hierarchy` flag; the
|
|
74
|
+
* 3-tier vs 4-tier mode is now derived entirely from the ticket shape —
|
|
75
|
+
* inline acceptance + zero Tasks resolves to `'3-tier'`, otherwise
|
|
76
|
+
* `'4-tier'`.
|
|
77
|
+
*
|
|
78
|
+
* @returns {Promise<{ sortedTasks: Array<object>, mode: '3-tier'|'4-tier' }>}
|
|
79
|
+
*/
|
|
80
|
+
export async function buildTaskGraph({ provider, logger, input }) {
|
|
81
|
+
const { storyId, storyBody = '' } = input;
|
|
82
|
+
const warn = logger?.warn ?? ((msg) => Logger.error(msg));
|
|
83
|
+
const progress = logger?.progress ?? (() => {});
|
|
84
|
+
|
|
85
|
+
const tasks = await fetchChildTickets(provider, storyId);
|
|
86
|
+
|
|
87
|
+
const inlineAcceptance = hasInlineAcceptance(storyBody);
|
|
88
|
+
const mode = tasks.length === 0 && inlineAcceptance ? '3-tier' : '4-tier';
|
|
89
|
+
|
|
90
|
+
if (tasks.length === 0) {
|
|
91
|
+
if (inlineAcceptance) {
|
|
92
|
+
progress(
|
|
93
|
+
'TASKS',
|
|
94
|
+
`Story #${storyId} has inline acceptance — no child Tasks expected (3-tier shape).`,
|
|
95
|
+
);
|
|
96
|
+
} else {
|
|
97
|
+
warn(
|
|
98
|
+
`[story-init] Warning: Story #${storyId} has no child Tasks. The agent will need to work from the Story body directly.`,
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const sortedTasks = sortTasksByDependencies(tasks);
|
|
104
|
+
if (sortedTasks.length > 0) {
|
|
105
|
+
progress(
|
|
106
|
+
'TASKS',
|
|
107
|
+
`Found ${sortedTasks.length} child Task(s) in dependency order`,
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return { sortedTasks, mode };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export { sortTasksByDependencies };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* transition-summary.js — Story-level summary of the batched task-start
|
|
3
|
+
* fanout produced by `transitionTaskStates`.
|
|
4
|
+
*
|
|
5
|
+
* Replaces the previous N-per-Task `agent::executing` GitHub-comment fanout
|
|
6
|
+
* with a single `low` notification routed to the Story. The dispatch
|
|
7
|
+
* carries no `event` field, so under the curated `commentEvents` /
|
|
8
|
+
* `webhookEvents` allowlists it never reaches either channel — init stays
|
|
9
|
+
* silent on the GitHub timeline by default. The call remains as a sentinel
|
|
10
|
+
* for operators who curate a `story-task-summary` event into their
|
|
11
|
+
* `commentEvents` allowlist (out-of-tree extension).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {object} deps
|
|
16
|
+
* @param {Function|null} deps.notify - The standard `notify(ticketId, payload)` hook.
|
|
17
|
+
* @param {number} deps.storyId
|
|
18
|
+
* @param {number[]} deps.transitioned - IDs of Tasks that flipped to `agent::executing`.
|
|
19
|
+
* @returns {Promise<{posted: boolean, message: string|null}>}
|
|
20
|
+
*/
|
|
21
|
+
export async function postBatchedTransitionSummary({
|
|
22
|
+
notify,
|
|
23
|
+
storyId,
|
|
24
|
+
transitioned,
|
|
25
|
+
}) {
|
|
26
|
+
if (typeof notify !== 'function') return { posted: false, message: null };
|
|
27
|
+
if (!Array.isArray(transitioned) || transitioned.length === 0) {
|
|
28
|
+
return { posted: false, message: null };
|
|
29
|
+
}
|
|
30
|
+
const taskList = transitioned.map((id) => `#${id}`).join(', ');
|
|
31
|
+
const message = `Story #${storyId} · ${transitioned.length} Task(s) transitioned to \`agent::executing\`: ${taskList}`;
|
|
32
|
+
await notify(storyId, { severity: 'low', message });
|
|
33
|
+
return { posted: true, message };
|
|
34
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Story lifecycle helpers shared between story-init and story-close.
|
|
3
|
+
*
|
|
4
|
+
* These three pure/IO-helpers capture the overlap previously duplicated across
|
|
5
|
+
* the two CLI scripts — parsing the `Epic: #N` / `parent: #N` references out
|
|
6
|
+
* of a Story body, fetching child sub-tickets, and batch-transitioning
|
|
7
|
+
* tickets to a target state label.
|
|
8
|
+
*
|
|
9
|
+
* The shape is narrow on purpose: init/close still own their own orchestration
|
|
10
|
+
* (branch bootstrap, merge, cascade, notifications). Expanding this module to
|
|
11
|
+
* cover those would over-abstract — they are genuinely different concerns.
|
|
12
|
+
*
|
|
13
|
+
* Under the 3-tier hierarchy (Epic #3078) Stories have no child tickets, so
|
|
14
|
+
* `fetchChildTickets` typically returns `[]` — but the helper remains in
|
|
15
|
+
* place so legacy callers still resolve the Story's direct children cleanly.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { Logger } from './Logger.js';
|
|
19
|
+
import {
|
|
20
|
+
STATE_LABELS,
|
|
21
|
+
transitionTicketState,
|
|
22
|
+
} from './orchestration/ticketing.js';
|
|
23
|
+
/**
|
|
24
|
+
* Parse the `Epic: #N` and `parent: #N` references from a Story body.
|
|
25
|
+
*
|
|
26
|
+
* @param {string} body Raw Story body Markdown.
|
|
27
|
+
* @returns {{ epicId: number|null, featureId: number|null }}
|
|
28
|
+
*/
|
|
29
|
+
export function resolveStoryHierarchy(body) {
|
|
30
|
+
const source = body ?? '';
|
|
31
|
+
const epicMatch = source.match(/(?:^\s*epic:\s*#(\d+))/im);
|
|
32
|
+
const parentMatch = source.match(/(?:^\s*parent:\s*#(\d+))/im);
|
|
33
|
+
return {
|
|
34
|
+
epicId: epicMatch ? Number.parseInt(epicMatch[1], 10) : null,
|
|
35
|
+
featureId: parentMatch ? Number.parseInt(parentMatch[1], 10) : null,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Fetch the Story's direct child tickets via the provider.
|
|
41
|
+
*
|
|
42
|
+
* Under the 3-tier hierarchy (Epic #3078) Stories no longer enumerate
|
|
43
|
+
* child Task tickets — acceptance criteria and verification steps live
|
|
44
|
+
* inline on the Story body, and decomposers emit only Epic / Feature /
|
|
45
|
+
* Story issues. For those Stories this helper resolves to an empty
|
|
46
|
+
* array because `provider.getSubTickets(storyId)` itself returns no
|
|
47
|
+
* rows. The helper is retained as a thin pass-through so the three
|
|
48
|
+
* orchestration callers (`story-deliver-prepare`, `task-graph-builder`,
|
|
49
|
+
* and `locked-pipeline`) keep a single, named seam for sub-ticket
|
|
50
|
+
* hydration that is easy to mock in tests and to instrument in the
|
|
51
|
+
* provider layer.
|
|
52
|
+
*
|
|
53
|
+
* Legacy ticket trees that were planned before the 3-tier cutover may
|
|
54
|
+
* still carry sub-tickets (PRD/Tech-Spec links recorded as direct
|
|
55
|
+
* children, for example). The helper deliberately does **not** filter
|
|
56
|
+
* those out — the caller is responsible for classifying anything that
|
|
57
|
+
* comes back. The previous `type::task`-only filter has been removed in
|
|
58
|
+
* Story #3191 because no current call site relies on that narrowing.
|
|
59
|
+
*
|
|
60
|
+
* @param {object} provider ITicketingProvider instance.
|
|
61
|
+
* @param {number} storyId Story ticket number to hydrate children for.
|
|
62
|
+
* @returns {Promise<object[]>} Array of child tickets (empty under 3-tier).
|
|
63
|
+
*/
|
|
64
|
+
export async function fetchChildTickets(provider, storyId) {
|
|
65
|
+
return provider.getSubTickets(storyId);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Detect transient HTTP errors (rate limits, gateways, server errors) that
|
|
70
|
+
* are worth retrying. Permission/validation errors are not retried — the
|
|
71
|
+
* second attempt would fail the same way.
|
|
72
|
+
*
|
|
73
|
+
* @param {Error} err
|
|
74
|
+
* @returns {boolean}
|
|
75
|
+
*/
|
|
76
|
+
function isRetryableError(err) {
|
|
77
|
+
const status = err?.status ?? err?.statusCode;
|
|
78
|
+
if (status === 429) return true;
|
|
79
|
+
if (typeof status === 'number' && status >= 500 && status < 600) return true;
|
|
80
|
+
const msg = (err?.message ?? '').toLowerCase();
|
|
81
|
+
return (
|
|
82
|
+
msg.includes('rate limit') ||
|
|
83
|
+
msg.includes('timeout') ||
|
|
84
|
+
msg.includes('econnreset') ||
|
|
85
|
+
msg.includes('etimedout') ||
|
|
86
|
+
msg.includes('socket hang up')
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Batch-transition a set of tickets to the target state label. Tickets
|
|
92
|
+
* already carrying `STATE_LABELS.DONE` (or the target itself) are skipped.
|
|
93
|
+
* Each transition runs in parallel with a per-ticket retry budget for
|
|
94
|
+
* transient errors (429, 5xx, network). Permanent failures are recorded
|
|
95
|
+
* in `failed` without aborting the batch.
|
|
96
|
+
*
|
|
97
|
+
* @param {object} provider ITicketingProvider instance.
|
|
98
|
+
* @param {object[]} tickets Array of ticket objects with `id` and `labels`.
|
|
99
|
+
* @param {string} targetLabel Target `agent::...` label (e.g. STATE_LABELS.EXECUTING).
|
|
100
|
+
* @param {object} [opts]
|
|
101
|
+
* @param {(phase: string, message: string) => void} [opts.progress] Progress reporter.
|
|
102
|
+
* @param {(ticketId: number, err: Error) => void} [opts.onError] Per-failure callback.
|
|
103
|
+
* @param {number} [opts.concurrency=10] Max parallel ticket transitions.
|
|
104
|
+
* @param {number} [opts.retries=3] Max attempts per ticket on transient errors.
|
|
105
|
+
* @param {number} [opts.retryBaseMs=500] Base for exponential backoff (attempt * base).
|
|
106
|
+
* @param {Function} [opts.notify] Optional notify function — forwarded to
|
|
107
|
+
* each `transitionTicketState` call so successful transitions fire a
|
|
108
|
+
* state-transition notification.
|
|
109
|
+
* @returns {Promise<{ transitioned: number[], skipped: number[], failed: Array<{ id: number, error: string, attempts: number }> }>}
|
|
110
|
+
*/
|
|
111
|
+
export async function batchTransitionTickets(
|
|
112
|
+
provider,
|
|
113
|
+
tickets,
|
|
114
|
+
targetLabel,
|
|
115
|
+
opts = {},
|
|
116
|
+
) {
|
|
117
|
+
const { progress, onError, notify } = opts;
|
|
118
|
+
const transitioned = [];
|
|
119
|
+
const skipped = [];
|
|
120
|
+
const failed = [];
|
|
121
|
+
|
|
122
|
+
const concurrency = opts.concurrency ?? 10;
|
|
123
|
+
const maxRetries = opts.retries ?? 3;
|
|
124
|
+
const retryBaseMs = opts.retryBaseMs ?? 500;
|
|
125
|
+
|
|
126
|
+
const processTicket = async (ticket) => {
|
|
127
|
+
if (ticket.labels.includes(targetLabel)) {
|
|
128
|
+
progress?.('TICKETS', ` #${ticket.id} already ${targetLabel} — skipped`);
|
|
129
|
+
skipped.push(ticket.id);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (
|
|
133
|
+
targetLabel !== STATE_LABELS.DONE &&
|
|
134
|
+
ticket.labels.includes(STATE_LABELS.DONE)
|
|
135
|
+
) {
|
|
136
|
+
progress?.('TICKETS', ` #${ticket.id} already done — skipped`);
|
|
137
|
+
skipped.push(ticket.id);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
let lastErr;
|
|
141
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
142
|
+
try {
|
|
143
|
+
// Story #1795 — thread the already-hydrated ticket through
|
|
144
|
+
// `opts.ticketSnapshot` so `transitionTicketState` skips both
|
|
145
|
+
// round-trips (notify snapshot + label merge). `batchTransitionTickets`
|
|
146
|
+
// is the single hot caller of this seam — every wave-close passes
|
|
147
|
+
// its full task list through here.
|
|
148
|
+
await transitionTicketState(provider, ticket.id, targetLabel, {
|
|
149
|
+
notify,
|
|
150
|
+
ticketSnapshot: ticket,
|
|
151
|
+
});
|
|
152
|
+
progress?.(
|
|
153
|
+
'TICKETS',
|
|
154
|
+
` #${ticket.id} → ${targetLabel} ✅${attempt > 1 ? ` (after ${attempt} attempts)` : ''}`,
|
|
155
|
+
);
|
|
156
|
+
transitioned.push(ticket.id);
|
|
157
|
+
return;
|
|
158
|
+
} catch (err) {
|
|
159
|
+
lastErr = err;
|
|
160
|
+
if (attempt >= maxRetries || !isRetryableError(err)) break;
|
|
161
|
+
const delay = retryBaseMs * 2 ** (attempt - 1);
|
|
162
|
+
progress?.(
|
|
163
|
+
'TICKETS',
|
|
164
|
+
` #${ticket.id} transient error (${err.message}); retrying in ${delay}ms (${attempt}/${maxRetries - 1})`,
|
|
165
|
+
);
|
|
166
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
failed.push({
|
|
170
|
+
id: ticket.id,
|
|
171
|
+
error: lastErr?.message ?? String(lastErr),
|
|
172
|
+
attempts: maxRetries,
|
|
173
|
+
});
|
|
174
|
+
if (onError) onError(ticket.id, lastErr);
|
|
175
|
+
else
|
|
176
|
+
Logger.error(` #${ticket.id} → FAILED: ${lastErr?.message ?? lastErr}`);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// Process in batches to avoid overwhelming the API with concurrent requests.
|
|
180
|
+
for (let i = 0; i < tickets.length; i += concurrency) {
|
|
181
|
+
const batch = tickets.slice(i, i + concurrency);
|
|
182
|
+
await Promise.all(batch.map(processTicket));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return { transitioned, skipped, failed };
|
|
186
|
+
}
|