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,691 @@
|
|
|
1
|
+
import { ValidationError } from '../errors/index.js';
|
|
2
|
+
import { detectCycle } from '../Graph.js';
|
|
3
|
+
import { gitSpawn } from '../git-utils.js';
|
|
4
|
+
|
|
5
|
+
import { Logger } from '../Logger.js';
|
|
6
|
+
import { parse as parseStoryBody } from '../story-body/story-body.js';
|
|
7
|
+
import { validateStoryFileAssumptions } from './file-assumptions.js';
|
|
8
|
+
import {
|
|
9
|
+
computeConflictFindings,
|
|
10
|
+
renderHardConflictError,
|
|
11
|
+
} from './ticket-validator-conflicts.js';
|
|
12
|
+
import {
|
|
13
|
+
computeSizingFindings,
|
|
14
|
+
DEFAULT_TASK_SIZING,
|
|
15
|
+
renderHardFindingError,
|
|
16
|
+
} from './ticket-validator-sizing.js';
|
|
17
|
+
|
|
18
|
+
// Re-exported for callers that want the constants without reaching into the
|
|
19
|
+
// sizing helper module directly.
|
|
20
|
+
export { DEFAULT_TASK_SIZING };
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Regex matching code-asset paths the freshness gate cares about. The three
|
|
24
|
+
* roots — `.agents/scripts`, `lib`, and `tests` — cover the executable surface
|
|
25
|
+
* the decomposer's tasks legitimately reference. Anchoring on the leading dot
|
|
26
|
+
* for `.agents` and a word boundary for `lib`/`tests` keeps URLs, image paths,
|
|
27
|
+
* and unrelated prose ("library", "testimonial", "established") from being
|
|
28
|
+
* scanned as fictitious file references.
|
|
29
|
+
*
|
|
30
|
+
* The regex is intentionally global + multi-match per body string so a single
|
|
31
|
+
* Task naming several files surfaces every miss in one error.
|
|
32
|
+
*/
|
|
33
|
+
const FRESHNESS_PATH_RE =
|
|
34
|
+
/(?:^|[\s`([<])(\.agents\/scripts|lib|tests)\/[\w./-]+\.js\b/g;
|
|
35
|
+
|
|
36
|
+
function collectPathsFromText(text, paths) {
|
|
37
|
+
if (!text || typeof text !== 'string') return;
|
|
38
|
+
// Reset lastIndex on the shared regex literal between calls.
|
|
39
|
+
FRESHNESS_PATH_RE.lastIndex = 0;
|
|
40
|
+
let match = FRESHNESS_PATH_RE.exec(text);
|
|
41
|
+
while (match !== null) {
|
|
42
|
+
// Capture group 1 is the root; full match index 0 includes the leading
|
|
43
|
+
// delimiter — slice it off so the path is a clean repo-relative reference.
|
|
44
|
+
const captured = match[0];
|
|
45
|
+
const rootStart = captured.indexOf(match[1]);
|
|
46
|
+
paths.add(captured.slice(rootStart));
|
|
47
|
+
match = FRESHNESS_PATH_RE.exec(text);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function collectTaskPathReferences(task) {
|
|
52
|
+
const paths = new Set();
|
|
53
|
+
const body = task.body;
|
|
54
|
+
if (typeof body === 'string') {
|
|
55
|
+
collectPathsFromText(body, paths);
|
|
56
|
+
} else if (body !== null && typeof body === 'object') {
|
|
57
|
+
if (typeof body.goal === 'string') collectPathsFromText(body.goal, paths);
|
|
58
|
+
for (const arr of [body.changes, body.acceptance, body.verify]) {
|
|
59
|
+
if (!Array.isArray(arr)) continue;
|
|
60
|
+
for (const item of arr) collectPathsFromText(String(item ?? ''), paths);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Some planner shapes carry a top-level `acceptance` array even on string
|
|
64
|
+
// bodies — scan it defensively.
|
|
65
|
+
if (Array.isArray(task.acceptance)) {
|
|
66
|
+
for (const item of task.acceptance) {
|
|
67
|
+
collectPathsFromText(String(item ?? ''), paths);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return paths;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Collect every code-asset path a Task declares it will *create or modify*
|
|
75
|
+
* via its `body.changes` array. These paths are net-new (or about to be
|
|
76
|
+
* touched) from the planner's perspective, so the freshness gate must
|
|
77
|
+
* accept them even when they're absent from `baseBranchRef`.
|
|
78
|
+
*
|
|
79
|
+
* Three shapes are accepted:
|
|
80
|
+
*
|
|
81
|
+
* 1. **Canonical string body** — the body is a markdown string produced by
|
|
82
|
+
* `serialize()` from `story-body.js`. Parsed via `parse()` to extract
|
|
83
|
+
* the structured `changes[]` and `references[]` arrays. This is the
|
|
84
|
+
* shape emitted by the decomposer after Story #3302.
|
|
85
|
+
* 2. **Legacy string bullets** — `"<path>: <verb> <object>"` inside an
|
|
86
|
+
* object body's `changes[]`. The regex `FRESHNESS_PATH_RE` picks the
|
|
87
|
+
* path out of the prose.
|
|
88
|
+
* 3. **Object form** — `{ path: "<path>", assumption: "creates" | ... }`,
|
|
89
|
+
* introduced by Story #2636 as the canonical declaration shape and
|
|
90
|
+
* documented in `epic-plan-decompose-author/SKILL.md`. The path is
|
|
91
|
+
* trusted verbatim.
|
|
92
|
+
*
|
|
93
|
+
* Only `body.changes` (and `body.references`) is consulted —
|
|
94
|
+
* `body.goal`, `body.acceptance`, and `body.verify` are deliberately
|
|
95
|
+
* excluded so the gate continues to flag a planner that hallucinates a
|
|
96
|
+
* fictitious file in narrative copy without declaring it in the
|
|
97
|
+
* changes/references contract.
|
|
98
|
+
*/
|
|
99
|
+
function collectTaskChangesPaths(task) {
|
|
100
|
+
const paths = new Set();
|
|
101
|
+
const body = task.body;
|
|
102
|
+
|
|
103
|
+
// Story #3302: when the body is a markdown string (canonical serialized
|
|
104
|
+
// form), parse it to extract the structured changes[] / references[]
|
|
105
|
+
// arrays before scanning. Without this, a string body causes the
|
|
106
|
+
// object-form branch below to fall through on every item, leaving the
|
|
107
|
+
// freshness gate blind to declared paths.
|
|
108
|
+
if (typeof body === 'string' && body.trim().length > 0) {
|
|
109
|
+
let parsed;
|
|
110
|
+
try {
|
|
111
|
+
parsed = parseStoryBody(body).body;
|
|
112
|
+
} catch {
|
|
113
|
+
// Unparseable body — no paths to whitelist; the freshness gate will
|
|
114
|
+
// catch any real references in the text scan below.
|
|
115
|
+
return paths;
|
|
116
|
+
}
|
|
117
|
+
for (const arrName of ['changes', 'references']) {
|
|
118
|
+
const arr = parsed[arrName];
|
|
119
|
+
if (!Array.isArray(arr)) continue;
|
|
120
|
+
for (const item of arr) {
|
|
121
|
+
if (typeof item === 'string') {
|
|
122
|
+
collectPathsFromText(item, paths);
|
|
123
|
+
} else if (
|
|
124
|
+
item !== null &&
|
|
125
|
+
typeof item === 'object' &&
|
|
126
|
+
typeof item.path === 'string' &&
|
|
127
|
+
item.path.length > 0
|
|
128
|
+
) {
|
|
129
|
+
paths.add(item.path);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return paths;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (body === null || typeof body !== 'object') return paths;
|
|
137
|
+
for (const arrName of ['changes', 'references']) {
|
|
138
|
+
const arr = body[arrName];
|
|
139
|
+
if (!Array.isArray(arr)) continue;
|
|
140
|
+
for (const item of arr) {
|
|
141
|
+
if (typeof item === 'string') {
|
|
142
|
+
collectPathsFromText(item, paths);
|
|
143
|
+
} else if (
|
|
144
|
+
item !== null &&
|
|
145
|
+
typeof item === 'object' &&
|
|
146
|
+
typeof item.path === 'string' &&
|
|
147
|
+
item.path.length > 0
|
|
148
|
+
) {
|
|
149
|
+
paths.add(item.path);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return paths;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Default git probe: returns true when `path` exists at `ref` in the cwd repo.
|
|
158
|
+
* Uses `git cat-file -e <ref>:<path>` which is the standard low-cost existence
|
|
159
|
+
* check (no blob materialisation, no tree walk in node).
|
|
160
|
+
*
|
|
161
|
+
* Callers may inject their own runner with the same `(ref, path) => boolean`
|
|
162
|
+
* signature for unit tests.
|
|
163
|
+
*/
|
|
164
|
+
function defaultGitRunner({ baseBranchRef, path, cwd }) {
|
|
165
|
+
const result = gitSpawn(
|
|
166
|
+
cwd ?? process.cwd(),
|
|
167
|
+
'cat-file',
|
|
168
|
+
'-e',
|
|
169
|
+
`${baseBranchRef}:${path}`,
|
|
170
|
+
);
|
|
171
|
+
return result.status === 0;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Wrap a `(ref, path) → boolean` git runner in a memoizing closure keyed by
|
|
176
|
+
* `"${baseBranchRef}:${path}"`. The wrapper is created once per
|
|
177
|
+
* `validateAndNormalizeTickets` call and threaded into both
|
|
178
|
+
* `validateAcFreshness` and `validateStoryFileAssumptions` so the two gates
|
|
179
|
+
* share a single probe cache rather than maintaining independent ones.
|
|
180
|
+
*
|
|
181
|
+
* @param {Function} runner - The underlying `({ baseBranchRef, path, cwd }) => boolean` probe.
|
|
182
|
+
* @returns {Function} A memoized probe with the same signature.
|
|
183
|
+
*/
|
|
184
|
+
function makeMemoizedGitRunner(runner) {
|
|
185
|
+
const cache = new Map();
|
|
186
|
+
return function memoizedGitRunner({ baseBranchRef, path, cwd }) {
|
|
187
|
+
const key = `${baseBranchRef}:${path}`;
|
|
188
|
+
let result = cache.get(key);
|
|
189
|
+
if (result === undefined) {
|
|
190
|
+
result = Boolean(runner({ baseBranchRef, path, cwd }));
|
|
191
|
+
cache.set(key, result);
|
|
192
|
+
}
|
|
193
|
+
return result;
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Verify that every code-asset path referenced by a Task body or AC exists at
|
|
199
|
+
* `baseBranchRef`. A missing path means the planner LLM hallucinated (or the
|
|
200
|
+
* path was deleted between planning and decomposition) — refuse to decompose
|
|
201
|
+
* because the resulting Task would be unimplementable as written.
|
|
202
|
+
*
|
|
203
|
+
* Only Tasks are scanned; Features and Stories carry narrative copy, not
|
|
204
|
+
* implementation paths, and their bodies routinely reference docs/templates
|
|
205
|
+
* the freshness regex would (correctly) ignore.
|
|
206
|
+
*
|
|
207
|
+
* @param {object} opts
|
|
208
|
+
* @param {object[]} opts.tickets - Validated ticket hierarchy.
|
|
209
|
+
* @param {string} opts.baseBranchRef - Ref to probe (e.g. 'main' or 'origin/main').
|
|
210
|
+
* @param {Function} [opts.gitRunner] - Probe override (testing seam).
|
|
211
|
+
* @param {string} [opts.cwd] - Repo cwd (forwarded to default runner).
|
|
212
|
+
* @throws {ValidationError} when one or more Story references are stale.
|
|
213
|
+
*/
|
|
214
|
+
export function validateAcFreshness({
|
|
215
|
+
tickets,
|
|
216
|
+
baseBranchRef,
|
|
217
|
+
gitRunner = defaultGitRunner,
|
|
218
|
+
cwd,
|
|
219
|
+
}) {
|
|
220
|
+
if (!baseBranchRef || typeof baseBranchRef !== 'string') {
|
|
221
|
+
throw new ValidationError(
|
|
222
|
+
'validateAcFreshness: baseBranchRef is required.',
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
const stories = (tickets ?? []).filter((t) => t.type === 'story');
|
|
226
|
+
// Union every Story's `body.changes` paths into an expected-new set. Any
|
|
227
|
+
// path the planner has declared in `changes` is considered intentional
|
|
228
|
+
// (net-new or about-to-be-modified) and the git probe is skipped for it
|
|
229
|
+
// — otherwise the freshness gate would reject the very test/source file
|
|
230
|
+
// a Story is meant to create, even when the Story is well-formed.
|
|
231
|
+
const expectedNewPaths = new Set();
|
|
232
|
+
for (const story of stories) {
|
|
233
|
+
for (const path of collectTaskChangesPaths(story)) {
|
|
234
|
+
expectedNewPaths.add(path);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
const misses = [];
|
|
238
|
+
// Cache per-path probe results — sibling Stories frequently cite the same
|
|
239
|
+
// helper module; avoid re-spawning git for each repeat.
|
|
240
|
+
const probeCache = new Map();
|
|
241
|
+
for (const story of stories) {
|
|
242
|
+
const refs = collectTaskPathReferences(story);
|
|
243
|
+
for (const path of refs) {
|
|
244
|
+
if (expectedNewPaths.has(path)) continue;
|
|
245
|
+
let exists = probeCache.get(path);
|
|
246
|
+
if (exists === undefined) {
|
|
247
|
+
exists = gitRunner({ baseBranchRef, path, cwd });
|
|
248
|
+
probeCache.set(path, exists);
|
|
249
|
+
}
|
|
250
|
+
if (!exists) {
|
|
251
|
+
misses.push({ slug: story.slug ?? '<unknown>', path });
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (misses.length === 0) return;
|
|
256
|
+
const lines = misses.map((m) => renderMissLine(m)).join('\n');
|
|
257
|
+
throw new ValidationError(
|
|
258
|
+
`Cross-Validation Failed: ${misses.length} Story reference(s) name files that do not exist at ${baseBranchRef}:\n${lines}\n\nEither declare the path in body.changes (signals net-new) or correct the reference.`,
|
|
259
|
+
{ misses, baseBranchRef },
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Allowed leading Conventional-Commits types. Mirrors the `changelog-sections`
|
|
265
|
+
* keys in `release-please-config.json` and the `type-enum` list in
|
|
266
|
+
* `commitlint.config.js`. When a planner LLM prescribes a commit subject in a
|
|
267
|
+
* Task acceptance item via the "Commit subject begins with '<prefix>:'" form,
|
|
268
|
+
* the captured prefix must reduce to one of these types (optionally followed
|
|
269
|
+
* by a `(scope)` qualifier) — anything else fails commitlint locally and
|
|
270
|
+
* release-please's changelog parser on `main`, so the decompose is rejected
|
|
271
|
+
* before the Story branch is ever cut.
|
|
272
|
+
*
|
|
273
|
+
* Epic #2501 introduced this guard after the legacy `baseline-refresh`
|
|
274
|
+
* leading-token prescription created a wave of commit-msg hook failures
|
|
275
|
+
* across story-deliver sub-agents. See
|
|
276
|
+
* `.agents/skills/core/baseline-refresh/SKILL.md` for the canonical refresh
|
|
277
|
+
* shape (Conventional-Commits subject + `baseline-refresh: true` body
|
|
278
|
+
* trailer).
|
|
279
|
+
*/
|
|
280
|
+
const ALLOWED_COMMIT_TYPES = new Set([
|
|
281
|
+
'feat',
|
|
282
|
+
'fix',
|
|
283
|
+
'chore',
|
|
284
|
+
'refactor',
|
|
285
|
+
'perf',
|
|
286
|
+
'docs',
|
|
287
|
+
'style',
|
|
288
|
+
'test',
|
|
289
|
+
'build',
|
|
290
|
+
'ci',
|
|
291
|
+
'revert',
|
|
292
|
+
]);
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Regex matching the canonical "Commit subject begins with '<prefix>:'"
|
|
296
|
+
* prescription shape the planner emits in `body.acceptance[]` entries.
|
|
297
|
+
* The leading quote is captured loosely (single, double, or backtick) so the
|
|
298
|
+
* three quoting styles the decomposer LLM has historically emitted all
|
|
299
|
+
* match. The captured group is the prefix token *without* the trailing
|
|
300
|
+
* colon — callers normalize by stripping an optional `(scope)` qualifier
|
|
301
|
+
* before comparing against the allowed-types set.
|
|
302
|
+
*/
|
|
303
|
+
const SUBJECT_PREFIX_RE = /Commit subject begins with ['"`]([^'"`]+):['"`]/g;
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Scan every Story's `body.acceptance[]` for "Commit subject begins with
|
|
307
|
+
* '<prefix>:'" prescriptions and reject the decompose when any captured
|
|
308
|
+
* prefix is not a valid Conventional-Commits type.
|
|
309
|
+
*
|
|
310
|
+
* A captured prefix of the form `chore(baselines)` is accepted — the
|
|
311
|
+
* leading `chore` is in the allowed-types set, and the `(scope)` qualifier
|
|
312
|
+
* is the standard Conventional-Commits scope shape. A captured prefix of
|
|
313
|
+
* the form `baseline-refresh` is rejected because no Conventional-Commits
|
|
314
|
+
* type starts with that token.
|
|
315
|
+
*
|
|
316
|
+
* Only `body.acceptance[]` is scanned; `body.goal` / `body.verify` /
|
|
317
|
+
* `body.changes` are not commit-subject prescriptions by convention and
|
|
318
|
+
* scanning them would surface false positives from prose that happens to
|
|
319
|
+
* quote a forbidden prefix while explaining why it's forbidden.
|
|
320
|
+
*
|
|
321
|
+
* @param {object} opts
|
|
322
|
+
* @param {object[]} opts.tickets - Validated ticket hierarchy.
|
|
323
|
+
* @throws {ValidationError} when one or more Story acceptance items
|
|
324
|
+
* prescribe a forbidden subject prefix. The error carries
|
|
325
|
+
* `code: 'forbidden-subject-prefix'` and a `violations[]` payload
|
|
326
|
+
* listing each `{ slug, prefix, line }` so the decompose loop can
|
|
327
|
+
* surface the exact offending text to the operator.
|
|
328
|
+
*/
|
|
329
|
+
export function validateAcceptanceSubjectPrefix({ tickets }) {
|
|
330
|
+
const violations = [];
|
|
331
|
+
const stories = (tickets ?? []).filter((t) => t.type === 'story');
|
|
332
|
+
for (const story of stories) {
|
|
333
|
+
const body = story.body;
|
|
334
|
+
if (body === null || typeof body !== 'object') continue;
|
|
335
|
+
if (!Array.isArray(body.acceptance)) continue;
|
|
336
|
+
for (const item of body.acceptance) {
|
|
337
|
+
const line = String(item ?? '');
|
|
338
|
+
// Reset the global regex between iterations.
|
|
339
|
+
SUBJECT_PREFIX_RE.lastIndex = 0;
|
|
340
|
+
let match = SUBJECT_PREFIX_RE.exec(line);
|
|
341
|
+
while (match !== null) {
|
|
342
|
+
const rawPrefix = match[1];
|
|
343
|
+
// Strip an optional `(scope)` qualifier — `chore(baselines)` reduces
|
|
344
|
+
// to `chore` for the allowed-types check.
|
|
345
|
+
const type = rawPrefix.replace(/\(.*\)$/, '').trim();
|
|
346
|
+
if (!ALLOWED_COMMIT_TYPES.has(type)) {
|
|
347
|
+
violations.push({
|
|
348
|
+
slug: story.slug ?? '<unknown>',
|
|
349
|
+
prefix: rawPrefix,
|
|
350
|
+
line,
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
match = SUBJECT_PREFIX_RE.exec(line);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
if (violations.length === 0) return;
|
|
358
|
+
const allowed = [...ALLOWED_COMMIT_TYPES].join('|');
|
|
359
|
+
const lines = violations
|
|
360
|
+
.map(
|
|
361
|
+
(v) =>
|
|
362
|
+
` - "${v.slug}" → forbidden subject prefix "${v.prefix}:" in acceptance item: ${v.line}`,
|
|
363
|
+
)
|
|
364
|
+
.join('\n');
|
|
365
|
+
const err = new ValidationError(
|
|
366
|
+
`Cross-Validation Failed: ${violations.length} Story acceptance item(s) prescribe a non-Conventional-Commits subject prefix:\n${lines}\n\nAllowed leading types: ${allowed}. Use a Conventional-Commits subject (e.g. "chore(baselines): refresh ...") and a body trailer (e.g. "baseline-refresh: true") for machine-readable markers. See Epic #2501.`,
|
|
367
|
+
{ violations },
|
|
368
|
+
);
|
|
369
|
+
err.code = 'forbidden-subject-prefix';
|
|
370
|
+
throw err;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Render one missing-path line with a remediation hint pointing at the
|
|
375
|
+
* task's `body.changes`. For `tests/**` paths we suggest the explicit
|
|
376
|
+
* "add the test file" verb; for everything else we emit a generic hint
|
|
377
|
+
* since the planner knows whether the path is net-new or a typo.
|
|
378
|
+
*/
|
|
379
|
+
function renderMissLine({ slug, path }) {
|
|
380
|
+
const verb = path.startsWith('tests/') ? 'add test file' : 'create';
|
|
381
|
+
return ` - "${slug}" → ${path}\n hint: if net-new, add '${path}: ${verb}' to body.changes; otherwise fix the typo or stale reference against current main.`;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Validates the generated ticket hierarchy and handles lifting cross-story dependencies.
|
|
386
|
+
*
|
|
387
|
+
* The returned tickets array carries two extra non-array properties:
|
|
388
|
+
* - `findings` — structured sizing findings (hard + soft) keyed by the
|
|
389
|
+
* three-layer sizing model. The bounded re-decomposition loop in
|
|
390
|
+
* `epic-plan-decompose` reads `findings.filter(f => f.severity === 'hard')`
|
|
391
|
+
* to decide whether to re-prompt.
|
|
392
|
+
* - `errors` — human-readable strings, one per hard finding. Non-empty
|
|
393
|
+
* `errors[]` is the AC-visible "block normalization" signal; the legacy
|
|
394
|
+
* hierarchy/cycle/freshness checks continue to throw, so callers that
|
|
395
|
+
* only inspect the array shape are unaffected when no sizing
|
|
396
|
+
* violations occur.
|
|
397
|
+
*
|
|
398
|
+
* @param {object[]} tickets - Array of ticket objects parsed from LLM output.
|
|
399
|
+
* @param {object} [opts]
|
|
400
|
+
* @param {string} [opts.baseBranchRef] - When set, runs `validateAcFreshness` against this ref.
|
|
401
|
+
* @param {Function} [opts.gitRunner] - Optional git probe override.
|
|
402
|
+
* @param {string} [opts.cwd] - Repo cwd (forwarded to the freshness gate).
|
|
403
|
+
* @param {object} [opts.taskSizing] - Override the three-layer sizing thresholds. Defaults to `DEFAULT_TASK_SIZING`.
|
|
404
|
+
* @param {object} [opts.conflictPolicy] - Severity controls for cross-Story conflict findings.
|
|
405
|
+
* @param {boolean} [opts.conflictPolicy.failOnSharedEditors=false] - Upgrade `shared-editor` findings to `hard`.
|
|
406
|
+
* @param {boolean} [opts.conflictPolicy.requireExplicitCrossStoryDeps=false] - Upgrade `implicit-cross-story-dep` findings to `hard`.
|
|
407
|
+
* @returns {object[] & { findings: object[], errors: string[] }} Validated tickets with normalized dependencies and attached sizing + conflict findings.
|
|
408
|
+
*/
|
|
409
|
+
/**
|
|
410
|
+
* Internal helpers extracted from `validateAndNormalizeTickets` so each
|
|
411
|
+
* stage can be unit-tested in isolation and the orchestration method stays
|
|
412
|
+
* at a low cyclomatic complexity. Exported via the `_internal` bundle at
|
|
413
|
+
* the bottom of the module for tests; production callers should keep
|
|
414
|
+
* using `validateAndNormalizeTickets`.
|
|
415
|
+
*/
|
|
416
|
+
|
|
417
|
+
function indexTicketsBySlug(tickets) {
|
|
418
|
+
const ticketBySlug = new Map();
|
|
419
|
+
const features = [];
|
|
420
|
+
const stories = [];
|
|
421
|
+
const slugAdjacency = new Map();
|
|
422
|
+
for (const t of tickets) {
|
|
423
|
+
if (t.slug) {
|
|
424
|
+
if (ticketBySlug.has(t.slug)) {
|
|
425
|
+
throw new Error(
|
|
426
|
+
`Cross-Validation Failed: Duplicate slug "${t.slug}" — slugs must be unique across the backlog. Colliding titles: "${ticketBySlug.get(t.slug).title}" and "${t.title}".`,
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
ticketBySlug.set(t.slug, t);
|
|
430
|
+
}
|
|
431
|
+
slugAdjacency.set(t.slug, t.depends_on ?? []);
|
|
432
|
+
if (t.type === 'feature') features.push(t);
|
|
433
|
+
else if (t.type === 'story') stories.push(t);
|
|
434
|
+
}
|
|
435
|
+
return { ticketBySlug, features, stories, slugAdjacency };
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function assertEachTypePresent({ features, stories }) {
|
|
439
|
+
if (features.length === 0)
|
|
440
|
+
throw new Error(
|
|
441
|
+
'Cross-Validation Failed: Backlog must contain at least one Feature.',
|
|
442
|
+
);
|
|
443
|
+
if (stories.length === 0)
|
|
444
|
+
throw new Error(
|
|
445
|
+
'Cross-Validation Failed: Backlog must contain at least one Story.',
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function assertHierarchy({ stories, ticketBySlug }) {
|
|
450
|
+
for (const story of stories) {
|
|
451
|
+
if (!story.parent_slug)
|
|
452
|
+
throw new Error(
|
|
453
|
+
`Cross-Validation Failed: Story "${story.title}" must have a parent_slug.`,
|
|
454
|
+
);
|
|
455
|
+
const parent = ticketBySlug.get(story.parent_slug);
|
|
456
|
+
if (!parent || parent.type !== 'feature')
|
|
457
|
+
throw new Error(
|
|
458
|
+
`Cross-Validation Failed: Story "${story.title}" parent must be a Feature.`,
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Deterministic invariant (Story #3777): a Feature MUST decompose into at
|
|
465
|
+
* least two Stories. A single-Story Feature is the work of a Story, not a
|
|
466
|
+
* Feature — the Feature wrapper is dead weight and signals decomposition at
|
|
467
|
+
* module/task granularity rather than deliverable granularity. HARD-reject
|
|
468
|
+
* the decomposition, naming the offending Feature(s) and telling the planner
|
|
469
|
+
* to collapse them, in the same throw-on-violation style as the surrounding
|
|
470
|
+
* hierarchy invariants.
|
|
471
|
+
*/
|
|
472
|
+
function assertNoSingleStoryFeature({ features, stories }) {
|
|
473
|
+
const storyCountByParent = new Map();
|
|
474
|
+
for (const story of stories) {
|
|
475
|
+
if (!story.parent_slug) continue;
|
|
476
|
+
storyCountByParent.set(
|
|
477
|
+
story.parent_slug,
|
|
478
|
+
(storyCountByParent.get(story.parent_slug) ?? 0) + 1,
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
const undersized = features.filter(
|
|
482
|
+
(feature) => (storyCountByParent.get(feature.slug) ?? 0) < 2,
|
|
483
|
+
);
|
|
484
|
+
if (undersized.length === 0) return;
|
|
485
|
+
const list = undersized
|
|
486
|
+
.map((feature) => {
|
|
487
|
+
const count = storyCountByParent.get(feature.slug) ?? 0;
|
|
488
|
+
return `"${feature.title}" (${feature.slug}, ${count} ${count === 1 ? 'Story' : 'Stories'})`;
|
|
489
|
+
})
|
|
490
|
+
.join(', ');
|
|
491
|
+
throw new Error(
|
|
492
|
+
`Cross-Validation Failed: ${undersized.length} Feature(s) decompose into fewer than two Stories: ${list}. ` +
|
|
493
|
+
'Every Feature MUST contain at least two Stories — a single-Story Feature is the work of a Story, not a Feature. ' +
|
|
494
|
+
'Collapse each offending Feature: drop the Feature wrapper and attach its lone Story to a sibling Feature, or merge the Feature into another.',
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Return true when a Story object carries inline acceptance + verify
|
|
500
|
+
* arrays — the 3-tier shape (Epic #3078) where the Story is itself the
|
|
501
|
+
* implementation unit and acceptance / verify live on the Story body
|
|
502
|
+
* rather than in child Task tickets.
|
|
503
|
+
*
|
|
504
|
+
* Both arrays must be present, be actual arrays, and contain at least
|
|
505
|
+
* one entry. Either alone is insufficient — a Story with only
|
|
506
|
+
* `acceptance[]` (no `verify[]`) cannot be implemented without a
|
|
507
|
+
* verification handle, and a Story with only `verify[]` (no
|
|
508
|
+
* `acceptance[]`) carries no observable criterion. Requiring both is the
|
|
509
|
+
* inline-contract invariant every Story must satisfy in the 3-tier model.
|
|
510
|
+
*/
|
|
511
|
+
function hasInlineAcceptanceAndVerify(story) {
|
|
512
|
+
if (story === null || typeof story !== 'object') return false;
|
|
513
|
+
const { acceptance, verify } = story;
|
|
514
|
+
return (
|
|
515
|
+
Array.isArray(acceptance) &&
|
|
516
|
+
acceptance.length > 0 &&
|
|
517
|
+
Array.isArray(verify) &&
|
|
518
|
+
verify.length > 0
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
function assertEveryStoryHasInlineContract({ stories }) {
|
|
523
|
+
// 3-tier (Epic #3078 / #3238): every Story is its own implementation
|
|
524
|
+
// unit and MUST carry a non-empty inline contract — top-level
|
|
525
|
+
// `acceptance[]` AND `verify[]`. A Story missing either is the legacy
|
|
526
|
+
// 4-tier shape that expected child Tasks; there is no Task tier any
|
|
527
|
+
// more, so such a Story is unimplementable and the decompose is
|
|
528
|
+
// rejected outright.
|
|
529
|
+
const missing = stories.filter((s) => !hasInlineAcceptanceAndVerify(s));
|
|
530
|
+
if (missing.length === 0) return;
|
|
531
|
+
const list = missing.map((s) => `"${s.title}" (${s.slug})`).join(', ');
|
|
532
|
+
throw new Error(
|
|
533
|
+
`Cross-Validation Failed: ${missing.length} Story/Stories lack an inline acceptance + verify contract: ${list}. Every Story must carry non-empty top-level acceptance[] and verify[].`,
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
function assertNoUnknownDeps({ tickets, ticketBySlug }) {
|
|
538
|
+
const unknownDeps = [];
|
|
539
|
+
for (const t of tickets) {
|
|
540
|
+
for (const depSlug of t.depends_on ?? []) {
|
|
541
|
+
if (!ticketBySlug.has(depSlug)) {
|
|
542
|
+
unknownDeps.push({ slug: t.slug, title: t.title, dep: depSlug });
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
if (unknownDeps.length === 0) return;
|
|
547
|
+
const list = unknownDeps
|
|
548
|
+
.map((u) => `"${u.title}" (${u.slug}) → "${u.dep}"`)
|
|
549
|
+
.join(', ');
|
|
550
|
+
throw new Error(
|
|
551
|
+
`Cross-Validation Failed: ${unknownDeps.length} depends_on reference(s) use unknown slugs: ${list}. Every slug in depends_on must match a slug present in the backlog.`,
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
function assertAcyclic(slugAdjacency) {
|
|
556
|
+
const cycle = detectCycle(slugAdjacency);
|
|
557
|
+
if (cycle) {
|
|
558
|
+
throw new Error(
|
|
559
|
+
`Cross-Validation Failed: Circular dependency detected: ${cycle.join(' → ')}.`,
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
function attachFindingsAndErrors(tickets, findings, errors) {
|
|
565
|
+
Object.defineProperty(tickets, 'findings', {
|
|
566
|
+
value: findings,
|
|
567
|
+
enumerable: false,
|
|
568
|
+
configurable: true,
|
|
569
|
+
writable: true,
|
|
570
|
+
});
|
|
571
|
+
Object.defineProperty(tickets, 'errors', {
|
|
572
|
+
value: errors,
|
|
573
|
+
enumerable: false,
|
|
574
|
+
configurable: true,
|
|
575
|
+
writable: true,
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
export function validateAndNormalizeTickets(tickets, opts = {}) {
|
|
580
|
+
const { ticketBySlug, features, stories, slugAdjacency } =
|
|
581
|
+
indexTicketsBySlug(tickets);
|
|
582
|
+
|
|
583
|
+
assertEachTypePresent({ features, stories });
|
|
584
|
+
assertHierarchy({ stories, ticketBySlug });
|
|
585
|
+
assertNoSingleStoryFeature({ features, stories });
|
|
586
|
+
assertEveryStoryHasInlineContract({ stories });
|
|
587
|
+
assertNoUnknownDeps({ tickets, ticketBySlug });
|
|
588
|
+
|
|
589
|
+
assertAcyclic(slugAdjacency);
|
|
590
|
+
|
|
591
|
+
// Reject any Task acceptance item that prescribes a non-Conventional-Commits
|
|
592
|
+
// subject prefix (e.g. legacy "Commit subject begins with 'baseline-refresh:'"
|
|
593
|
+
// from pre-Epic-#2501 planner output). Runs before the freshness gate so
|
|
594
|
+
// the failure mode is reported up-front rather than after a git probe.
|
|
595
|
+
validateAcceptanceSubjectPrefix({ tickets });
|
|
596
|
+
|
|
597
|
+
// Hoist a single memoized (ref, path) → boolean probe shared across both
|
|
598
|
+
// git-probe gates below. Without this, `validateAcFreshness` and
|
|
599
|
+
// `validateStoryFileAssumptions` each maintain an independent cache, so a
|
|
600
|
+
// path that appears in both the AC-freshness scan and the file-assumption
|
|
601
|
+
// scan spawns two `git cat-file` processes. The memoizing wrapper captures
|
|
602
|
+
// results by `"${baseBranchRef}:${path}"` key so the second gate reuses
|
|
603
|
+
// the first's results without any additional git I/O.
|
|
604
|
+
const sharedGitRunner = opts.baseBranchRef
|
|
605
|
+
? makeMemoizedGitRunner(opts.gitRunner ?? defaultGitRunner)
|
|
606
|
+
: null;
|
|
607
|
+
|
|
608
|
+
// Refuse to decompose when any Task body or AC names a code-asset path
|
|
609
|
+
// missing from the Epic's base branch tree. Skipped when the caller
|
|
610
|
+
// omits `baseBranchRef` so legacy unit tests keep their existing
|
|
611
|
+
// semantics; production call-sites always pass it.
|
|
612
|
+
if (opts.baseBranchRef) {
|
|
613
|
+
validateAcFreshness({
|
|
614
|
+
tickets,
|
|
615
|
+
baseBranchRef: opts.baseBranchRef,
|
|
616
|
+
gitRunner: sharedGitRunner,
|
|
617
|
+
cwd: opts.cwd,
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// Story #2636 — Phase 8 path-assumption gate. Cross-check every Story's
|
|
622
|
+
// declared `{ path, assumption }` against the actual state of the base
|
|
623
|
+
// branch and batch the mismatches per-Story into the validator's errors
|
|
624
|
+
// envelope. Skipped when the caller omits `baseBranchRef` so legacy
|
|
625
|
+
// unit tests keep their semantics; production call-sites always pass
|
|
626
|
+
// it.
|
|
627
|
+
let assumptionErrors = [];
|
|
628
|
+
if (opts.baseBranchRef) {
|
|
629
|
+
const assumptionReport = validateStoryFileAssumptions({
|
|
630
|
+
tickets,
|
|
631
|
+
baseBranchRef: opts.baseBranchRef,
|
|
632
|
+
gitRunner: sharedGitRunner,
|
|
633
|
+
cwd: opts.cwd,
|
|
634
|
+
});
|
|
635
|
+
for (const warning of assumptionReport.warnings) {
|
|
636
|
+
Logger.warn(`[ticket-validator] assumption-deprecation: ${warning}`);
|
|
637
|
+
}
|
|
638
|
+
assumptionErrors = assumptionReport.errors;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
const sizingFindings = computeSizingFindings({
|
|
642
|
+
stories,
|
|
643
|
+
sizing: opts.taskSizing,
|
|
644
|
+
});
|
|
645
|
+
// Cross-Story path-conflict pass observes the story-level depends_on
|
|
646
|
+
// graph. Findings are appended to the same `findings` array consumed by
|
|
647
|
+
// the decompose-loop's hard-finding gate; severity is controlled by
|
|
648
|
+
// `opts.conflictPolicy`.
|
|
649
|
+
const conflictFindings = computeConflictFindings({
|
|
650
|
+
stories,
|
|
651
|
+
policy: opts.conflictPolicy,
|
|
652
|
+
});
|
|
653
|
+
const findings = [...sizingFindings, ...conflictFindings];
|
|
654
|
+
const CONFLICT_KINDS = new Set([
|
|
655
|
+
'shared-editor',
|
|
656
|
+
'implicit-cross-story-dep',
|
|
657
|
+
'cross-cutting-registries',
|
|
658
|
+
'fan-out-warning',
|
|
659
|
+
'missing-bdd-scaffold',
|
|
660
|
+
]);
|
|
661
|
+
const errors = findings
|
|
662
|
+
.filter((f) => f.severity === 'hard')
|
|
663
|
+
.map((f) =>
|
|
664
|
+
CONFLICT_KINDS.has(f.kind)
|
|
665
|
+
? renderHardConflictError(f)
|
|
666
|
+
: renderHardFindingError(f),
|
|
667
|
+
);
|
|
668
|
+
// Append per-Story path-assumption mismatches (Story #2636) to the
|
|
669
|
+
// hard-error list. The decompose loop already gates on
|
|
670
|
+
// `errors.length > 0` to trigger a re-prompt, so the new check
|
|
671
|
+
// participates in the same loop without bespoke wiring.
|
|
672
|
+
for (const e of assumptionErrors) {
|
|
673
|
+
errors.push(`File assumption mismatch: ${e}`);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
attachFindingsAndErrors(tickets, findings, errors);
|
|
677
|
+
return tickets;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// Internal helpers exposed for unit tests; not part of the public surface.
|
|
681
|
+
export const _internal = {
|
|
682
|
+
indexTicketsBySlug,
|
|
683
|
+
assertEachTypePresent,
|
|
684
|
+
assertHierarchy,
|
|
685
|
+
assertNoSingleStoryFeature,
|
|
686
|
+
assertEveryStoryHasInlineContract,
|
|
687
|
+
assertNoUnknownDeps,
|
|
688
|
+
assertAcyclic,
|
|
689
|
+
attachFindingsAndErrors,
|
|
690
|
+
hasInlineAcceptanceAndVerify,
|
|
691
|
+
};
|