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,619 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/orchestration/epic-spec-reconciler-diff.js — pure-function diff
|
|
3
|
+
* engine for the epic-spec reconciler (Epic #1182 / Tech Spec #1483 /
|
|
4
|
+
* Story #1492).
|
|
5
|
+
*
|
|
6
|
+
* `diff({ spec, state, ghState })` walks the three inputs and emits a
|
|
7
|
+
* `Plan` (see `epic-spec-reconciler-ops.js`) carrying the structural
|
|
8
|
+
* mutations the apply engine needs to perform. The function is **pure**:
|
|
9
|
+
*
|
|
10
|
+
* • No file I/O, no GitHub provider calls, no clock, no env lookups.
|
|
11
|
+
* • Same inputs → byte-identical plan (operations sorted by slug; field
|
|
12
|
+
* keys + label arrays canonicalised).
|
|
13
|
+
* • Safe to call repeatedly. An empty diff is idempotent — re-running
|
|
14
|
+
* against the same `(spec, state, ghState)` triple yields the same
|
|
15
|
+
* empty plan.
|
|
16
|
+
*
|
|
17
|
+
* ## Inputs
|
|
18
|
+
*
|
|
19
|
+
* @typedef {object} SpecInput
|
|
20
|
+
* The parsed YAML returned by `lib/spec/loader.js#loadSpec`. Shape is
|
|
21
|
+
* `{ epic: {...}, features: [{slug, stories: [...]}], gates?: {...} }`
|
|
22
|
+
* per `.agents/schemas/epic-spec.schema.json`.
|
|
23
|
+
*
|
|
24
|
+
* @typedef {object} StateMappingEntry
|
|
25
|
+
* @property {number} issueNumber GH issue number this slug maps to.
|
|
26
|
+
* @property {string} entity 'epic'|'feature'|'story'|'task'.
|
|
27
|
+
* @property {string} [contentHash] Content hash captured at last
|
|
28
|
+
* reconcile; absence forces an
|
|
29
|
+
* update when ghState carries
|
|
30
|
+
* structural fields. Present from
|
|
31
|
+
* the writer in the apply phase.
|
|
32
|
+
* @property {string} [parentSlug] Parent slug at last reconcile.
|
|
33
|
+
* Used for relink detection.
|
|
34
|
+
* @property {string[]} [dependsOn] Sibling-story slugs at last
|
|
35
|
+
* reconcile (stories only).
|
|
36
|
+
*
|
|
37
|
+
* @typedef {object} StateInput
|
|
38
|
+
* @property {number} epicId
|
|
39
|
+
* @property {Record<string, StateMappingEntry>} mapping Slug → entry.
|
|
40
|
+
* @property {string} [lastReconciledAt]
|
|
41
|
+
*
|
|
42
|
+
* @typedef {object} GhIssueObservation
|
|
43
|
+
* @property {string} title
|
|
44
|
+
* @property {string} [body]
|
|
45
|
+
* @property {string[]} [labels]
|
|
46
|
+
* @property {'open'|'closed'} [state]
|
|
47
|
+
*
|
|
48
|
+
* @typedef {Record<string|number, GhIssueObservation>} GhStateInput
|
|
49
|
+
* Keyed by GH issue number. Stringified numeric keys are coerced so
|
|
50
|
+
* callers may pass either `{ 1234: {...} }` or `{ "1234": {...} }`.
|
|
51
|
+
*
|
|
52
|
+
* ## Algorithm
|
|
53
|
+
*
|
|
54
|
+
* 1. Walk the spec depth-first, emitting one logical entity per
|
|
55
|
+
* `(epic|feature|story|task)`. For each entity:
|
|
56
|
+
* - look up the slug in `state.mapping`.
|
|
57
|
+
* - if no mapping → Create.
|
|
58
|
+
* - if mapped → compare structural fields against ghState[
|
|
59
|
+
* mapping.issueNumber] → Update for any diff in title/body/
|
|
60
|
+
* labels/wave.
|
|
61
|
+
* - if mapping carries `parentSlug` or `dependsOn` and they
|
|
62
|
+
* differ from the spec → Relink.
|
|
63
|
+
* 2. Walk `state.mapping` for any slug that did NOT appear in the
|
|
64
|
+
* spec walk → Close.
|
|
65
|
+
* 3. Sort each bucket by slug for deterministic output, then return
|
|
66
|
+
* the plan.
|
|
67
|
+
*
|
|
68
|
+
* Edge cases the engine deliberately handles:
|
|
69
|
+
*
|
|
70
|
+
* • Epic-level entity has no parent → `parentSlug` is always `null`
|
|
71
|
+
* for the epic; relink never fires on the epic.
|
|
72
|
+
* • Tasks have no `wave` / `dependsOn` → those fields are skipped on
|
|
73
|
+
* tasks even when present in the input (defensive).
|
|
74
|
+
* • A slug in the mapping whose `ghState` is missing entirely still
|
|
75
|
+
* yields a Close (the mapping itself is the ground truth that the
|
|
76
|
+
* spec dropped this entity).
|
|
77
|
+
* • Label comparisons ignore order: arrays are sorted before compare.
|
|
78
|
+
* • `body` and other optional fields treat `undefined === ''` as
|
|
79
|
+
* equality so a spec that omits `body` does not flap against a GH
|
|
80
|
+
* issue with an empty body.
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
import { assertPlanLabelAllowList } from './epic-spec-reconciler-discriminator.js';
|
|
84
|
+
import {
|
|
85
|
+
closeOp,
|
|
86
|
+
createOp,
|
|
87
|
+
ENTITY_KINDS,
|
|
88
|
+
emptyPlan,
|
|
89
|
+
relinkOp,
|
|
90
|
+
updateOp,
|
|
91
|
+
} from './epic-spec-reconciler-ops.js';
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Compare two label arrays for equality, ignoring order. Returns true
|
|
95
|
+
* when both lists carry the same multiset of strings.
|
|
96
|
+
*
|
|
97
|
+
* @param {string[]|undefined} a
|
|
98
|
+
* @param {string[]|undefined} b
|
|
99
|
+
* @returns {boolean}
|
|
100
|
+
*/
|
|
101
|
+
function labelsEqual(a, b) {
|
|
102
|
+
const left = [...(a ?? [])].sort();
|
|
103
|
+
const right = [...(b ?? [])].sort();
|
|
104
|
+
if (left.length !== right.length) return false;
|
|
105
|
+
for (let i = 0; i < left.length; i += 1) {
|
|
106
|
+
if (left[i] !== right[i]) return false;
|
|
107
|
+
}
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Label-namespace prefixes that the reconciler must NOT strip from the
|
|
113
|
+
* Epic on persist. The decomposer renders the Epic spec entry from
|
|
114
|
+
* `{ id, title }` only — it does not carry `epic.labels` through — so
|
|
115
|
+
* a naive replace-style label diff would propose removing operator-
|
|
116
|
+
* managed metadata that lives in these namespaces.
|
|
117
|
+
*
|
|
118
|
+
* Why: Story #2056 / Epic #1994 — `/epic-plan` was silently stripping
|
|
119
|
+
* `type::epic` and `risk::*` from the parent Epic on every decompose,
|
|
120
|
+
* which then broke `dispatcher.js` (`type "unknown"`). Defence-in-depth
|
|
121
|
+
* lives here in the diff engine: even if a future spec author drops
|
|
122
|
+
* these labels, the reconciler will not propose their removal.
|
|
123
|
+
*
|
|
124
|
+
* Symmetry with the `agent::*` allow-list (owned by the wave-runner,
|
|
125
|
+
* defended in `epic-spec-reconciler-discriminator.js`): the diff engine
|
|
126
|
+
* treats both namespaces as out-of-scope for structural reconciliation,
|
|
127
|
+
* but via different mechanisms — `agent::*` is rejected at construction
|
|
128
|
+
* time, while these structural namespaces are merged into the Epic's
|
|
129
|
+
* after-set so the comparison stays a no-op.
|
|
130
|
+
*/
|
|
131
|
+
const PROTECTED_EPIC_LABEL_NAMESPACES = Object.freeze([
|
|
132
|
+
'type::',
|
|
133
|
+
'risk::',
|
|
134
|
+
// Story #3050 — `acceptance::*` is set by Phase 7 spec-persist when
|
|
135
|
+
// `planningRisk.acceptanceDisposition='not-applicable'` (or another
|
|
136
|
+
// disposition) and gates downstream `/epic-deliver` start/finalize
|
|
137
|
+
// behavior. Before this namespace was protected, Phase 8 decompose
|
|
138
|
+
// diffed the Epic's labels against a spec entry that doesn't carry
|
|
139
|
+
// `acceptance::*`, silently emitting an Update that stripped the
|
|
140
|
+
// waiver and broke the contract documented in `.agents/docs/SDLC.md`.
|
|
141
|
+
'acceptance::',
|
|
142
|
+
// `planning::*` carries operator-applied planning-gate waivers
|
|
143
|
+
// (e.g. `planning::healthcheck-waived`, see persist.js gate). Same
|
|
144
|
+
// failure mode as `acceptance::*`: applied between spec and
|
|
145
|
+
// decompose, stripped by the naive replace-style diff.
|
|
146
|
+
'planning::',
|
|
147
|
+
]);
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @param {unknown} label
|
|
151
|
+
* @returns {boolean}
|
|
152
|
+
*/
|
|
153
|
+
function isProtectedEpicLabel(label) {
|
|
154
|
+
if (typeof label !== 'string') return false;
|
|
155
|
+
return PROTECTED_EPIC_LABEL_NAMESPACES.some((ns) => label.startsWith(ns));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Return the spec's label list for the Epic entity, augmented with any
|
|
160
|
+
* protected-namespace labels observed on the live GH issue. Stable
|
|
161
|
+
* across calls (uses a Set to deduplicate). When neither input carries
|
|
162
|
+
* anything to merge, the original `specLabels` reference is returned
|
|
163
|
+
* unchanged so callers that compare references stay correct.
|
|
164
|
+
*
|
|
165
|
+
* @param {string[]|undefined} specLabels
|
|
166
|
+
* @param {string[]|undefined} obsLabels
|
|
167
|
+
* @returns {string[]|undefined}
|
|
168
|
+
*/
|
|
169
|
+
function mergeProtectedEpicLabels(specLabels, obsLabels) {
|
|
170
|
+
if (!Array.isArray(obsLabels) || obsLabels.length === 0) return specLabels;
|
|
171
|
+
const preserved = obsLabels.filter(isProtectedEpicLabel);
|
|
172
|
+
if (preserved.length === 0) return specLabels;
|
|
173
|
+
const merged = new Set([...(specLabels ?? []), ...preserved]);
|
|
174
|
+
return [...merged];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Treat undefined/null body as the empty string for comparison.
|
|
179
|
+
*
|
|
180
|
+
* @param {string|undefined|null} value
|
|
181
|
+
* @returns {string}
|
|
182
|
+
*/
|
|
183
|
+
function normaliseBody(value) {
|
|
184
|
+
return typeof value === 'string' ? value : '';
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Match the canonical orchestrator footer anchored on a `---` separator
|
|
189
|
+
* line followed by `parent: #<digits>`. Greedy through end of string so
|
|
190
|
+
* duplicate footer blocks and trailing `blocked by` lines are removed in
|
|
191
|
+
* a single pass. Kept local to this module so the diff engine does not
|
|
192
|
+
* depend on the Task-body renderer (Story #3185 / Epic #3163: the renderer
|
|
193
|
+
* is going away with the 3-tier producer cutover).
|
|
194
|
+
*/
|
|
195
|
+
const ORCHESTRATOR_FOOTER_RE = /\n?---[ \t]*\r?\n+parent:\s*#\d+[\s\S]*$/;
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Strip the canonical orchestrator footer from a body and return just the
|
|
199
|
+
* description portion. Safe to call on bodies without a footer — returns
|
|
200
|
+
* the input unchanged modulo a trailing-whitespace trim. The trim keeps
|
|
201
|
+
* the result byte-stable when fed back through `composeBodyWithFooter`.
|
|
202
|
+
*
|
|
203
|
+
* @param {string|null|undefined} body
|
|
204
|
+
* @returns {string}
|
|
205
|
+
*/
|
|
206
|
+
function stripFooter(body) {
|
|
207
|
+
const value = typeof body === 'string' ? body : '';
|
|
208
|
+
return value.replace(ORCHESTRATOR_FOOTER_RE, '').replace(/\s+$/, '');
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Render the canonical orchestrator footer (no leading newline). Format
|
|
213
|
+
* matches the byte-stable shape that the cascade-reading consumers
|
|
214
|
+
* (story-init, dispatcher, manifest, close-gate) parse line-anchored:
|
|
215
|
+
*
|
|
216
|
+
* ---
|
|
217
|
+
* parent: #<parentId>
|
|
218
|
+
* [Epic: #<epicId>] // only when epicId !== parentId
|
|
219
|
+
*
|
|
220
|
+
* [blocked by #<dep>] // one per dependency
|
|
221
|
+
*
|
|
222
|
+
* @param {{parentId: number, epicId?: number, dependencies?: number[]}} opts
|
|
223
|
+
* @returns {string}
|
|
224
|
+
*/
|
|
225
|
+
function renderFooter({ parentId, epicId, dependencies = [] }) {
|
|
226
|
+
const lines = ['---', `parent: #${parentId}`];
|
|
227
|
+
if (epicId !== undefined && epicId !== null && epicId !== parentId) {
|
|
228
|
+
lines.push(`Epic: #${epicId}`);
|
|
229
|
+
}
|
|
230
|
+
if (dependencies.length > 0) {
|
|
231
|
+
lines.push('');
|
|
232
|
+
for (const dep of dependencies) {
|
|
233
|
+
lines.push(`blocked by #${dep}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return lines.join('\n');
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Compose the canonical orchestrator footer onto a spec body for non-epic
|
|
241
|
+
* entities. Resolves `parentSlug`/`dependsOn` slugs against the running
|
|
242
|
+
* `state.mapping` so the rendered footer carries the live issue numbers.
|
|
243
|
+
* Pure: identical inputs produce a byte-identical body.
|
|
244
|
+
*
|
|
245
|
+
* Story #2982 — without this re-composition, a body Update sourced from
|
|
246
|
+
* the YAML spec writes just the description, silently stripping
|
|
247
|
+
* `parent: #N` / `Epic: #M` / `blocked by #X` and breaking the cascade.
|
|
248
|
+
*
|
|
249
|
+
* Story #3185 — the footer compose/strip logic is inlined here rather
|
|
250
|
+
* than reused from the legacy Task-body renderer module. Under the
|
|
251
|
+
* 3-tier hierarchy (Epic → Feature → Story) that renderer is being
|
|
252
|
+
* removed, so the diff engine carries its own footer shape. The shape
|
|
253
|
+
* is byte-identical to the legacy renderer's `parent: #<n>` /
|
|
254
|
+
* `Epic: #<m>` / `blocked by #<x>` output so cascade-readers continue
|
|
255
|
+
* to parse it unchanged.
|
|
256
|
+
*
|
|
257
|
+
* @param {{entity: string, parentSlug?: string|null, dependsOn?: string[]}} specEntity
|
|
258
|
+
* @param {string} specBody
|
|
259
|
+
* @param {{state?: StateInput}} ctx
|
|
260
|
+
* @returns {string}
|
|
261
|
+
*/
|
|
262
|
+
function composeBodyWithFooter(specEntity, specBody, ctx) {
|
|
263
|
+
const state = ctx?.state ?? {};
|
|
264
|
+
const mapping = state.mapping ?? {};
|
|
265
|
+
const parentSlug = specEntity.parentSlug ?? null;
|
|
266
|
+
const parentId =
|
|
267
|
+
parentSlug && mapping[parentSlug]
|
|
268
|
+
? mapping[parentSlug].issueNumber
|
|
269
|
+
: undefined;
|
|
270
|
+
// Without a resolved parent we cannot render a meaningful footer.
|
|
271
|
+
// Fall back to the raw spec body — apply still writes something the
|
|
272
|
+
// operator can inspect; the missing-parent case is rare (the only
|
|
273
|
+
// current trigger is a relink-in-flight where the new parent has not
|
|
274
|
+
// landed yet, which surfaces elsewhere via the relink op anyway).
|
|
275
|
+
if (typeof parentId !== 'number') return specBody;
|
|
276
|
+
const epicId = typeof state.epicId === 'number' ? state.epicId : undefined;
|
|
277
|
+
const dependencies = Array.isArray(specEntity.dependsOn)
|
|
278
|
+
? specEntity.dependsOn
|
|
279
|
+
.map((slug) => mapping[slug]?.issueNumber)
|
|
280
|
+
.filter((id) => typeof id === 'number')
|
|
281
|
+
: [];
|
|
282
|
+
// Strip any orchestrator footer the spec already carries before
|
|
283
|
+
// recomposing. Without the strip we double-wrap when the spec body
|
|
284
|
+
// came from a producer that stored the raw GH body verbatim (footer
|
|
285
|
+
// included) or emits a canonical-form body. With the strip, the
|
|
286
|
+
// function is idempotent against its own output.
|
|
287
|
+
const head = stripFooter(specBody);
|
|
288
|
+
const footer = renderFooter({ parentId, epicId, dependencies });
|
|
289
|
+
return `${head}\n\n${footer}`;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Pick the ghState observation for an issue number, coercing the key
|
|
294
|
+
* type so numeric and string keys interop.
|
|
295
|
+
*
|
|
296
|
+
* @param {GhStateInput|undefined|null} ghState
|
|
297
|
+
* @param {number} issueNumber
|
|
298
|
+
* @returns {GhIssueObservation|undefined}
|
|
299
|
+
*/
|
|
300
|
+
function ghObservation(ghState, issueNumber) {
|
|
301
|
+
if (!ghState) return undefined;
|
|
302
|
+
return ghState[issueNumber] ?? ghState[String(issueNumber)] ?? undefined;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Compute the structural-field changes between a spec entity and the GH
|
|
307
|
+
* observation. Returns an empty object when nothing changed.
|
|
308
|
+
*
|
|
309
|
+
* @param {{title: string, body?: string, labels?: string[], wave?: number, entity: string}} specEntity
|
|
310
|
+
* @param {GhIssueObservation|undefined} obs
|
|
311
|
+
* @param {StateMappingEntry} mapping
|
|
312
|
+
* @returns {Record<string, {before: unknown, after: unknown}>}
|
|
313
|
+
*/
|
|
314
|
+
function fieldChanges(specEntity, obs, mapping, ctx = {}) {
|
|
315
|
+
const changes = {};
|
|
316
|
+
if (!obs) {
|
|
317
|
+
// Mapped but GH side missing → treat as full update (apply will
|
|
318
|
+
// recreate body/labels/title). Callers can choose to escalate via
|
|
319
|
+
// the close-discriminator.
|
|
320
|
+
return changes;
|
|
321
|
+
}
|
|
322
|
+
if (specEntity.title !== obs.title) {
|
|
323
|
+
changes.title = { before: obs.title, after: specEntity.title };
|
|
324
|
+
}
|
|
325
|
+
// Schema contract (epic-spec.schema.json §epic.body and the parallel
|
|
326
|
+
// feature/story/task body fields): "When omitted, the GH issue body
|
|
327
|
+
// is left untouched". Pre-Story-#2283 the engine treated `undefined`
|
|
328
|
+
// as `""`, which emitted a destructive `body: <existing> → ""` Update
|
|
329
|
+
// on every `/epic-plan` Phase 8 because the decomposer's renderer
|
|
330
|
+
// projects the Epic spec entry from `{ id, title }` only. Skip the
|
|
331
|
+
// body diff entirely when the spec did not carry a body string. An
|
|
332
|
+
// explicit `body: ""` in the spec still produces a clear-op when the
|
|
333
|
+
// GH side is non-empty (operator-authored intent to blank the body).
|
|
334
|
+
if (typeof specEntity.body === 'string') {
|
|
335
|
+
const specBody = specEntity.body;
|
|
336
|
+
const obsBody = normaliseBody(obs.body);
|
|
337
|
+
const isEpic = specEntity.entity === ENTITY_KINDS.EPIC;
|
|
338
|
+
if (isEpic) {
|
|
339
|
+
if (specBody !== obsBody) {
|
|
340
|
+
changes.body = { before: obsBody, after: specBody };
|
|
341
|
+
}
|
|
342
|
+
} else {
|
|
343
|
+
// Story #2982 — for non-epic entities, compare the spec body
|
|
344
|
+
// (re-composed with the canonical orchestrator footer) against
|
|
345
|
+
// the raw GH body. Single comparison catches:
|
|
346
|
+
// • description-only changes,
|
|
347
|
+
// • parent/Epic id changes (footer differs),
|
|
348
|
+
// • dependsOn changes (`blocked by` block differs),
|
|
349
|
+
// • duplicated footer blocks (obs has more than one),
|
|
350
|
+
// • missing footer (obs has none).
|
|
351
|
+
// Emit a body change only when the canonical form differs from
|
|
352
|
+
// what is on GH today — and write the canonical form back, so the
|
|
353
|
+
// footer cascade-readers depend on stays intact across resumes.
|
|
354
|
+
const after = composeBodyWithFooter(specEntity, specBody, ctx);
|
|
355
|
+
if (after !== obsBody) {
|
|
356
|
+
changes.body = { before: obsBody, after };
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
const effectiveAfterLabels =
|
|
361
|
+
specEntity.entity === ENTITY_KINDS.EPIC
|
|
362
|
+
? mergeProtectedEpicLabels(specEntity.labels, obs.labels)
|
|
363
|
+
: specEntity.labels;
|
|
364
|
+
if (!labelsEqual(effectiveAfterLabels, obs.labels)) {
|
|
365
|
+
changes.labels = {
|
|
366
|
+
before: [...(obs.labels ?? [])].sort(),
|
|
367
|
+
after: [...(effectiveAfterLabels ?? [])].sort(),
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
// wave is story-only; only fire when both sides carry an integer and
|
|
371
|
+
// they differ. Mapping carries the last-known wave under
|
|
372
|
+
// `mapping.wave` (apply-engine populates it); absent → skip.
|
|
373
|
+
if (specEntity.entity === ENTITY_KINDS.STORY) {
|
|
374
|
+
const beforeWave =
|
|
375
|
+
typeof mapping.wave === 'number' ? mapping.wave : undefined;
|
|
376
|
+
const afterWave =
|
|
377
|
+
typeof specEntity.wave === 'number' ? specEntity.wave : undefined;
|
|
378
|
+
if (
|
|
379
|
+
beforeWave !== undefined &&
|
|
380
|
+
afterWave !== undefined &&
|
|
381
|
+
beforeWave !== afterWave
|
|
382
|
+
) {
|
|
383
|
+
changes.wave = { before: beforeWave, after: afterWave };
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return changes;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Compare two parent-edge values. `null` represents "no parent" (the
|
|
391
|
+
* epic root). Strings compare by value.
|
|
392
|
+
*
|
|
393
|
+
* @param {string|null|undefined} a
|
|
394
|
+
* @param {string|null|undefined} b
|
|
395
|
+
* @returns {boolean}
|
|
396
|
+
*/
|
|
397
|
+
function parentEqual(a, b) {
|
|
398
|
+
const left = a == null ? null : a;
|
|
399
|
+
const right = b == null ? null : b;
|
|
400
|
+
return left === right;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Sort an array of operations by slug, returning a new array.
|
|
405
|
+
*
|
|
406
|
+
* @template {{slug: string}} T
|
|
407
|
+
* @param {T[]} ops
|
|
408
|
+
* @returns {T[]}
|
|
409
|
+
*/
|
|
410
|
+
function sortBySlug(ops) {
|
|
411
|
+
return [...ops].sort((a, b) => a.slug.localeCompare(b.slug));
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Walk the spec and yield one structural-entity record per visited
|
|
416
|
+
* node. The walker is iterative-via-recursion but bounded by the spec's
|
|
417
|
+
* nesting (epic → features → stories → tasks); the depth never exceeds
|
|
418
|
+
* 4 so an explicit work-queue would just obscure the shape.
|
|
419
|
+
*
|
|
420
|
+
* @param {SpecInput} spec
|
|
421
|
+
* @returns {Array<{
|
|
422
|
+
* slug: string,
|
|
423
|
+
* entity: string,
|
|
424
|
+
* title: string,
|
|
425
|
+
* body?: string,
|
|
426
|
+
* labels?: string[],
|
|
427
|
+
* wave?: number,
|
|
428
|
+
* parentSlug: string|null,
|
|
429
|
+
* dependsOn?: string[],
|
|
430
|
+
* }>}
|
|
431
|
+
*/
|
|
432
|
+
function flattenSpec(spec) {
|
|
433
|
+
const out = [];
|
|
434
|
+
if (!spec || typeof spec !== 'object') return out;
|
|
435
|
+
|
|
436
|
+
// Epic — no parent.
|
|
437
|
+
if (spec.epic && typeof spec.epic === 'object') {
|
|
438
|
+
out.push({
|
|
439
|
+
slug: epicSlug(spec.epic),
|
|
440
|
+
entity: ENTITY_KINDS.EPIC,
|
|
441
|
+
title: String(spec.epic.title ?? ''),
|
|
442
|
+
body: spec.epic.body,
|
|
443
|
+
labels: spec.epic.labels,
|
|
444
|
+
parentSlug: null,
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const epicAnchor = spec.epic ? epicSlug(spec.epic) : null;
|
|
449
|
+
for (const feature of spec.features ?? []) {
|
|
450
|
+
out.push({
|
|
451
|
+
slug: feature.slug,
|
|
452
|
+
entity: ENTITY_KINDS.FEATURE,
|
|
453
|
+
title: String(feature.title ?? ''),
|
|
454
|
+
body: feature.body,
|
|
455
|
+
labels: feature.labels,
|
|
456
|
+
parentSlug: epicAnchor,
|
|
457
|
+
});
|
|
458
|
+
for (const story of feature.stories ?? []) {
|
|
459
|
+
out.push({
|
|
460
|
+
slug: story.slug,
|
|
461
|
+
entity: ENTITY_KINDS.STORY,
|
|
462
|
+
title: String(story.title ?? ''),
|
|
463
|
+
body: story.body,
|
|
464
|
+
labels: story.labels,
|
|
465
|
+
wave: story.wave,
|
|
466
|
+
parentSlug: feature.slug,
|
|
467
|
+
dependsOn: story.dependsOn ?? [],
|
|
468
|
+
});
|
|
469
|
+
for (const task of story.tasks ?? []) {
|
|
470
|
+
out.push({
|
|
471
|
+
slug: task.slug,
|
|
472
|
+
entity: ENTITY_KINDS.TASK,
|
|
473
|
+
title: String(task.title ?? ''),
|
|
474
|
+
body: task.body,
|
|
475
|
+
labels: task.labels,
|
|
476
|
+
parentSlug: story.slug,
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
return out;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* The epic-level slug is synthetic — the spec keys the epic by GH issue
|
|
486
|
+
* number, not by a slug — but the reconciler needs a stable identifier
|
|
487
|
+
* to thread the epic entity through the operation surface (state
|
|
488
|
+
* mapping, plan formatter, etc). We use the canonical literal `epic`
|
|
489
|
+
* so the formatter can render it without special-casing.
|
|
490
|
+
*
|
|
491
|
+
* @param {{id: number}} epic
|
|
492
|
+
* @returns {string}
|
|
493
|
+
*/
|
|
494
|
+
function epicSlug(_epic) {
|
|
495
|
+
// Single epic per spec — schema requires it — so a constant slug is
|
|
496
|
+
// unambiguous and matches the way mapping is keyed in writeState
|
|
497
|
+
// (where the epic entry is stored under `epic`).
|
|
498
|
+
return `epic`;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Compute equality between two `dependsOn` lists, ignoring order.
|
|
503
|
+
*
|
|
504
|
+
* @param {string[]|undefined} a
|
|
505
|
+
* @param {string[]|undefined} b
|
|
506
|
+
* @returns {boolean}
|
|
507
|
+
*/
|
|
508
|
+
function dependsOnEqual(a, b) {
|
|
509
|
+
return labelsEqual(a, b);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Diff `(spec, state, ghState)` into a `Plan`. See the module header for
|
|
514
|
+
* the full contract.
|
|
515
|
+
*
|
|
516
|
+
* @param {{spec: SpecInput, state: StateInput, ghState?: GhStateInput}} input
|
|
517
|
+
* @returns {import('./epic-spec-reconciler-ops.js').Plan}
|
|
518
|
+
*/
|
|
519
|
+
export function diff({ spec, state, ghState } = {}) {
|
|
520
|
+
const plan = emptyPlan();
|
|
521
|
+
if (!spec || typeof spec !== 'object') return plan;
|
|
522
|
+
if (!state || typeof state !== 'object') {
|
|
523
|
+
throw new TypeError('diff: state argument is required');
|
|
524
|
+
}
|
|
525
|
+
const mapping = state.mapping ?? {};
|
|
526
|
+
const seenSpecSlugs = new Set();
|
|
527
|
+
|
|
528
|
+
for (const entity of flattenSpec(spec)) {
|
|
529
|
+
seenSpecSlugs.add(entity.slug);
|
|
530
|
+
const mapped = mapping[entity.slug];
|
|
531
|
+
|
|
532
|
+
if (!mapped) {
|
|
533
|
+
plan.creates.push(
|
|
534
|
+
createOp({
|
|
535
|
+
slug: entity.slug,
|
|
536
|
+
entity: entity.entity,
|
|
537
|
+
title: entity.title,
|
|
538
|
+
body: entity.body,
|
|
539
|
+
labels: entity.labels,
|
|
540
|
+
parentSlug:
|
|
541
|
+
entity.parentSlug === null ? undefined : entity.parentSlug,
|
|
542
|
+
dependsOn: entity.dependsOn,
|
|
543
|
+
wave: entity.wave,
|
|
544
|
+
}),
|
|
545
|
+
);
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// Mapped: check for content updates.
|
|
550
|
+
const obs = ghObservation(ghState, mapped.issueNumber);
|
|
551
|
+
const changes = fieldChanges(entity, obs, mapped, { state });
|
|
552
|
+
if (Object.keys(changes).length > 0) {
|
|
553
|
+
plan.updates.push(
|
|
554
|
+
updateOp({
|
|
555
|
+
slug: entity.slug,
|
|
556
|
+
entity: entity.entity,
|
|
557
|
+
issueNumber: mapped.issueNumber,
|
|
558
|
+
changes,
|
|
559
|
+
}),
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// Mapped: check for relink (parent / dependsOn edge changes).
|
|
564
|
+
const relinkPayload = {};
|
|
565
|
+
const beforeParent = mapped.parentSlug ?? null;
|
|
566
|
+
const afterParent = entity.parentSlug ?? null;
|
|
567
|
+
if (
|
|
568
|
+
!parentEqual(beforeParent, afterParent) &&
|
|
569
|
+
entity.entity !== ENTITY_KINDS.EPIC
|
|
570
|
+
) {
|
|
571
|
+
relinkPayload.parent = { before: beforeParent, after: afterParent };
|
|
572
|
+
}
|
|
573
|
+
if (entity.entity === ENTITY_KINDS.STORY) {
|
|
574
|
+
const beforeDeps = mapped.dependsOn ?? [];
|
|
575
|
+
const afterDeps = entity.dependsOn ?? [];
|
|
576
|
+
if (!dependsOnEqual(beforeDeps, afterDeps)) {
|
|
577
|
+
relinkPayload.dependsOn = { before: beforeDeps, after: afterDeps };
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
if (Object.keys(relinkPayload).length > 0) {
|
|
581
|
+
plan.relinks.push(
|
|
582
|
+
relinkOp({
|
|
583
|
+
slug: entity.slug,
|
|
584
|
+
entity: entity.entity,
|
|
585
|
+
issueNumber: mapped.issueNumber,
|
|
586
|
+
...relinkPayload,
|
|
587
|
+
}),
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// Closes — anything in mapping not seen in spec.
|
|
593
|
+
for (const [slug, mapped] of Object.entries(mapping)) {
|
|
594
|
+
if (seenSpecSlugs.has(slug)) continue;
|
|
595
|
+
plan.closes.push(
|
|
596
|
+
closeOp({
|
|
597
|
+
slug,
|
|
598
|
+
entity: mapped.entity ?? ENTITY_KINDS.TASK,
|
|
599
|
+
issueNumber: mapped.issueNumber,
|
|
600
|
+
title: mapped.title,
|
|
601
|
+
}),
|
|
602
|
+
);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
plan.creates = sortBySlug(plan.creates);
|
|
606
|
+
plan.updates = sortBySlug(plan.updates);
|
|
607
|
+
plan.closes = sortBySlug(plan.closes);
|
|
608
|
+
plan.relinks = sortBySlug(plan.relinks);
|
|
609
|
+
|
|
610
|
+
// Diff-time safety net (Story #1493 / Task #1515). The diff engine
|
|
611
|
+
// never *intends* to emit an agent::* payload, but defence-in-depth
|
|
612
|
+
// catches both a future spec-loader bug that would smuggle an agent::*
|
|
613
|
+
// through a structural field and an apply-pipeline regression that
|
|
614
|
+
// would otherwise silently corrupt wave-runner state. Throws
|
|
615
|
+
// `LabelAllowListViolation` synchronously.
|
|
616
|
+
assertPlanLabelAllowList(plan);
|
|
617
|
+
|
|
618
|
+
return plan;
|
|
619
|
+
}
|