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,783 @@
|
|
|
1
|
+
import { collectStoryAssumptionEntries } from './file-assumptions.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cross-Story path-conflict & implicit-dependency findings.
|
|
5
|
+
*
|
|
6
|
+
* Two related gaps in the original decomposition validator motivate this
|
|
7
|
+
* module:
|
|
8
|
+
*
|
|
9
|
+
* 1. The legacy freshness gate only audits paths under
|
|
10
|
+
* `.agents/scripts | lib | tests` and operates on individual Tasks. A
|
|
11
|
+
* decomposition that produces multiple Wave-0 Stories each editing the
|
|
12
|
+
* same shared file (e.g. `.github/workflows/quality.yml`) sails through
|
|
13
|
+
* validation, but parallel dispatch produces merge conflicts on every
|
|
14
|
+
* Story-to-Epic close after the first.
|
|
15
|
+
*
|
|
16
|
+
* 2. The validator's `depends_on` graph only honors explicit slug links.
|
|
17
|
+
* A Story whose Task `verify` block reads a file produced by a Task in
|
|
18
|
+
* a different Story has no dependency expressed, even though the
|
|
19
|
+
* consumer Story would fail execution-time verification when run in
|
|
20
|
+
* the same wave as the producer.
|
|
21
|
+
*
|
|
22
|
+
* Both gaps share a single underlying mechanism — a path-keyed graph across
|
|
23
|
+
* all Tasks in the spec — which is why detection lives in one module.
|
|
24
|
+
*
|
|
25
|
+
* The module is pure: it consumes the already-normalized ticket array (with
|
|
26
|
+
* lifted Task→Story `depends_on` deps applied) and returns a structured
|
|
27
|
+
* findings array. Severity is `'soft'` by default; the caller's policy
|
|
28
|
+
* flags upgrade findings to `'hard'`, which routes them through
|
|
29
|
+
* `renderHardConflictError` and into the validator's `errors[]` channel.
|
|
30
|
+
*
|
|
31
|
+
* @typedef {object} SharedEditorFinding
|
|
32
|
+
* @property {'shared-editor'} kind
|
|
33
|
+
* @property {'hard'|'soft'} severity
|
|
34
|
+
* @property {string} path Producer path written by ≥2 Stories.
|
|
35
|
+
* @property {string[]} storySlugs Story slugs in the conflict cluster.
|
|
36
|
+
*
|
|
37
|
+
* @typedef {object} ImplicitCrossStoryDepFinding
|
|
38
|
+
* @property {'implicit-cross-story-dep'} kind
|
|
39
|
+
* @property {'hard'|'soft'} severity
|
|
40
|
+
* @property {string} path Path consumed without a depends_on link.
|
|
41
|
+
* @property {{ storySlug: string, taskSlug: string }} producer
|
|
42
|
+
* @property {{ storySlug: string, taskSlug: string, sourceField: 'acceptance'|'verify' }} consumer
|
|
43
|
+
*
|
|
44
|
+
* @typedef {SharedEditorFinding | ImplicitCrossStoryDepFinding} ConflictFinding
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
const DEFAULT_POLICY = Object.freeze({
|
|
48
|
+
failOnSharedEditors: false,
|
|
49
|
+
requireExplicitCrossStoryDeps: false,
|
|
50
|
+
failOnRegistryConflicts: false,
|
|
51
|
+
failOnMissingBddScaffold: false,
|
|
52
|
+
largeFanOutThreshold: 10,
|
|
53
|
+
registries: null, // null = use DEFAULT_REGISTRY_PATTERNS
|
|
54
|
+
fanOutCounter: null, // null = no fan-out probe (skip)
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Default cross-cutting registry / barrel files. Story #2962 — these are
|
|
59
|
+
* files whose primary purpose is to wire siblings together (registries,
|
|
60
|
+
* handler maps, listener barrels). When two or more concurrent Stories
|
|
61
|
+
* either edit the registry directly OR create sibling files that need
|
|
62
|
+
* registration in it, the registry edits collide on every Story-to-Epic
|
|
63
|
+
* close after the first.
|
|
64
|
+
*
|
|
65
|
+
* Patterns support two shapes:
|
|
66
|
+
* - exact path — `lib/orchestration/lifecycle/listeners/index.js`
|
|
67
|
+
* - `**` suffix — `**\/listeners/index.js` (matches any depth)
|
|
68
|
+
*/
|
|
69
|
+
const DEFAULT_REGISTRY_PATTERNS = Object.freeze([
|
|
70
|
+
'lib/orchestration/lifecycle/listeners/index.js',
|
|
71
|
+
'**/listeners/index.js',
|
|
72
|
+
'**/handlers/index.js',
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
function matchRegistryPattern(path, pattern) {
|
|
76
|
+
if (pattern.startsWith('**/')) {
|
|
77
|
+
const tail = pattern.slice(3);
|
|
78
|
+
return path === tail || path.endsWith(`/${tail}`);
|
|
79
|
+
}
|
|
80
|
+
return path === pattern;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function isRegistryPath(path, patterns) {
|
|
84
|
+
for (const p of patterns) if (matchRegistryPattern(path, p)) return true;
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function parentDirOf(path) {
|
|
89
|
+
const idx = path.lastIndexOf('/');
|
|
90
|
+
return idx <= 0 ? '' : path.slice(0, idx);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Assumptions that imply a *write* to a path — and therefore make the Story
|
|
95
|
+
* a producer for shared-editor / implicit-dep purposes. `exists` declares a
|
|
96
|
+
* read-only dependency (and `references` reads are likewise not writes), so
|
|
97
|
+
* neither produces a `shared-editor` conflict.
|
|
98
|
+
*/
|
|
99
|
+
const WRITE_IMPLYING_ASSUMPTIONS = Object.freeze(
|
|
100
|
+
new Set(['creates', 'refactors-existing', 'deletes']),
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Extract the path-shaped head from a single legacy string-form
|
|
105
|
+
* `body.changes` bullet.
|
|
106
|
+
*
|
|
107
|
+
* Conventional shape is `"<path>: <verb> <object>"`; we slice on the first
|
|
108
|
+
* colon and return the head when it contains a slash or a dot, otherwise
|
|
109
|
+
* `null`. Mirrors the heuristic in `ticket-validator-sizing.js` so producer
|
|
110
|
+
* extraction and `fileCount` accounting agree on what counts as a path.
|
|
111
|
+
*
|
|
112
|
+
* Object-form entries (`{ path, assumption }`) are *not* handled here — they
|
|
113
|
+
* are extracted via `collectStoryAssumptionEntries` in `indexProducers`. This
|
|
114
|
+
* helper only understands the legacy string shape and returns `null` for any
|
|
115
|
+
* non-string input.
|
|
116
|
+
*/
|
|
117
|
+
function extractChangeBulletPath(bullet) {
|
|
118
|
+
if (typeof bullet !== 'string') return null;
|
|
119
|
+
const colonIdx = bullet.indexOf(':');
|
|
120
|
+
if (colonIdx <= 0) return null;
|
|
121
|
+
const head = bullet.slice(0, colonIdx).trim();
|
|
122
|
+
if (!/[\\/.]/.test(head)) return null;
|
|
123
|
+
return head;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Collect the write-implying producer paths a single Story declares.
|
|
128
|
+
*
|
|
129
|
+
* Two shapes are honoured so the modern object-form `changes` contract and
|
|
130
|
+
* the legacy string-bullet contract both feed the producer index:
|
|
131
|
+
*
|
|
132
|
+
* - **Object form** (`{ path, assumption }`) — reuses
|
|
133
|
+
* `collectStoryAssumptionEntries` (the same extractor the Phase-8
|
|
134
|
+
* file-assumption gate uses), then keeps only `changes`-sourced entries
|
|
135
|
+
* whose assumption writes the path (`creates` / `refactors-existing` /
|
|
136
|
+
* `deletes`). `exists` reads and `references` entries are dropped.
|
|
137
|
+
* - **Legacy string bullets** (`"<path>: <verb> ..."`) — slice the
|
|
138
|
+
* colon-head via `extractChangeBulletPath`. Legacy bullets carry no
|
|
139
|
+
* assumption, so they are treated as writes (preserving pre-migration
|
|
140
|
+
* behaviour).
|
|
141
|
+
*
|
|
142
|
+
* Returns a de-duplicated array of producer paths for the Story.
|
|
143
|
+
*/
|
|
144
|
+
function collectStoryProducerPaths(story) {
|
|
145
|
+
const paths = new Set();
|
|
146
|
+
|
|
147
|
+
// Object-form entries via the shared extractor. Only `changes`-sourced
|
|
148
|
+
// write-implying assumptions count as producers.
|
|
149
|
+
for (const entry of collectStoryAssumptionEntries(story)) {
|
|
150
|
+
if (entry.source !== 'changes') continue;
|
|
151
|
+
if (!WRITE_IMPLYING_ASSUMPTIONS.has(entry.assumption)) continue;
|
|
152
|
+
paths.add(entry.path);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Legacy string bullets — extract the colon-head path. Skip non-string
|
|
156
|
+
// entries (object-form already handled above).
|
|
157
|
+
const body = story?.body;
|
|
158
|
+
const changes =
|
|
159
|
+
body && typeof body === 'object' && Array.isArray(body.changes)
|
|
160
|
+
? body.changes
|
|
161
|
+
: [];
|
|
162
|
+
for (const bullet of changes) {
|
|
163
|
+
if (typeof bullet !== 'string') continue;
|
|
164
|
+
const path = extractChangeBulletPath(bullet);
|
|
165
|
+
if (path) paths.add(path);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return Array.from(paths);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Resolve the Story-identifying slug for a 3-tier Story. A Story is its
|
|
173
|
+
* own implementation unit (Epic #3238) — there is no parent Task — so the
|
|
174
|
+
* producer/consumer indices key on the Story's own `slug`.
|
|
175
|
+
*/
|
|
176
|
+
function storySlugOf(story) {
|
|
177
|
+
return story.slug;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Build the producers index — `Map<path, Array<{storySlug, taskSlug}>>` —
|
|
182
|
+
* by walking every Story's declared writes. Both object-form
|
|
183
|
+
* `{ path, assumption }` entries and legacy `"<path>: <verb> ..."` string
|
|
184
|
+
* bullets are honoured via `collectStoryProducerPaths`; only write-implying
|
|
185
|
+
* assumptions (and legacy bullets, which carry no assumption) count as
|
|
186
|
+
* producers.
|
|
187
|
+
*
|
|
188
|
+
* `taskSlug` is retained in the entry shape for finding/render
|
|
189
|
+
* compatibility; in the 3-tier model it carries the Story's own slug since
|
|
190
|
+
* the Story is the implementation unit.
|
|
191
|
+
*/
|
|
192
|
+
function indexProducers(stories) {
|
|
193
|
+
const producers = new Map();
|
|
194
|
+
for (const story of stories) {
|
|
195
|
+
for (const path of collectStoryProducerPaths(story)) {
|
|
196
|
+
const entry = { storySlug: storySlugOf(story), taskSlug: story.slug };
|
|
197
|
+
const existing = producers.get(path);
|
|
198
|
+
if (existing) existing.push(entry);
|
|
199
|
+
else producers.set(path, [entry]);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return producers;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Build the consumers index — `Array<{path, storySlug, taskSlug, sourceField}>`.
|
|
207
|
+
*
|
|
208
|
+
* For each Task, scan `body.acceptance` and `body.verify` joined text for
|
|
209
|
+
* literal substring occurrences of any known producer path. Only producer
|
|
210
|
+
* paths are matched (intersect-then-test), so free-text path-like tokens
|
|
211
|
+
* that no one writes never produce false positives.
|
|
212
|
+
*
|
|
213
|
+
* A Story is not its own consumer — entries whose producer is the same
|
|
214
|
+
* Story are skipped to keep the surface focused on cross-Story signal.
|
|
215
|
+
*/
|
|
216
|
+
function indexConsumers(stories, producers) {
|
|
217
|
+
const consumers = [];
|
|
218
|
+
if (producers.size === 0) return consumers;
|
|
219
|
+
const producerPaths = Array.from(producers.keys()).sort(
|
|
220
|
+
(a, b) => b.length - a.length,
|
|
221
|
+
);
|
|
222
|
+
for (const story of stories) {
|
|
223
|
+
const body = story.body;
|
|
224
|
+
if (!body || typeof body !== 'object') continue;
|
|
225
|
+
for (const sourceField of ['acceptance', 'verify']) {
|
|
226
|
+
const items = Array.isArray(body[sourceField]) ? body[sourceField] : [];
|
|
227
|
+
if (items.length === 0) continue;
|
|
228
|
+
const joined = items.map((it) => String(it ?? '')).join('\n');
|
|
229
|
+
for (const path of producerPaths) {
|
|
230
|
+
if (!joined.includes(path)) continue;
|
|
231
|
+
const producerEntries = producers.get(path) ?? [];
|
|
232
|
+
if (producerEntries.some((p) => p.taskSlug === story.slug)) continue;
|
|
233
|
+
consumers.push({
|
|
234
|
+
path,
|
|
235
|
+
storySlug: storySlugOf(story),
|
|
236
|
+
taskSlug: story.slug,
|
|
237
|
+
sourceField,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return consumers;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Compute transitive predecessor sets over the story-level `depends_on`
|
|
247
|
+
* graph. The returned map is `Map<storySlug, Set<storySlug>>`, where the
|
|
248
|
+
* set contains every story reachable by following `depends_on` edges from
|
|
249
|
+
* the key (i.e. every story the key transitively depends on).
|
|
250
|
+
*
|
|
251
|
+
* BFS, no cycles assumed — callers must run `assertAcyclic` first.
|
|
252
|
+
*
|
|
253
|
+
* Exported so the wave-aware file-assumption gate
|
|
254
|
+
* (`file-assumptions.js`) can reuse the same transitive-predecessor walk
|
|
255
|
+
* rather than re-deriving the `depends_on` closure.
|
|
256
|
+
*/
|
|
257
|
+
export function computeStoryReachability(stories) {
|
|
258
|
+
const reach = new Map();
|
|
259
|
+
for (const story of stories) reach.set(story.slug, new Set());
|
|
260
|
+
for (const story of stories) {
|
|
261
|
+
const visited = reach.get(story.slug);
|
|
262
|
+
const stack = [...(story.depends_on ?? [])];
|
|
263
|
+
while (stack.length > 0) {
|
|
264
|
+
const next = stack.pop();
|
|
265
|
+
if (!reach.has(next)) continue;
|
|
266
|
+
if (visited.has(next)) continue;
|
|
267
|
+
visited.add(next);
|
|
268
|
+
const nextStory = stories.find((s) => s.slug === next);
|
|
269
|
+
if (nextStory && Array.isArray(nextStory.depends_on)) {
|
|
270
|
+
for (const dep of nextStory.depends_on) stack.push(dep);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return reach;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function inSameWave(reach, slugA, slugB) {
|
|
278
|
+
if (slugA === slugB) return false;
|
|
279
|
+
const a = reach.get(slugA);
|
|
280
|
+
const b = reach.get(slugB);
|
|
281
|
+
if (a?.has(slugB)) return false;
|
|
282
|
+
if (b?.has(slugA)) return false;
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Emit one `shared-editor` finding per path that is written by Tasks in
|
|
288
|
+
* two or more distinct Stories where no `depends_on` path orders the
|
|
289
|
+
* Stories relative to one another. Stories serialized by an explicit chain
|
|
290
|
+
* are not flagged — the operator already accepted the merge order.
|
|
291
|
+
*/
|
|
292
|
+
function computeSharedEditorFindings(producers, reach, severity) {
|
|
293
|
+
const findings = [];
|
|
294
|
+
for (const [path, entries] of producers.entries()) {
|
|
295
|
+
const distinct = Array.from(new Set(entries.map((e) => e.storySlug)));
|
|
296
|
+
if (distinct.length < 2) continue;
|
|
297
|
+
const cluster = new Set();
|
|
298
|
+
for (let i = 0; i < distinct.length; i += 1) {
|
|
299
|
+
for (let j = i + 1; j < distinct.length; j += 1) {
|
|
300
|
+
if (inSameWave(reach, distinct[i], distinct[j])) {
|
|
301
|
+
cluster.add(distinct[i]);
|
|
302
|
+
cluster.add(distinct[j]);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (cluster.size === 0) continue;
|
|
307
|
+
findings.push({
|
|
308
|
+
kind: 'shared-editor',
|
|
309
|
+
severity,
|
|
310
|
+
path,
|
|
311
|
+
storySlugs: Array.from(cluster).sort(),
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
return findings;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Emit one `implicit-cross-story-dep` finding per consumer entry whose
|
|
319
|
+
* producer Story is not transitively reachable from the consumer Story.
|
|
320
|
+
*
|
|
321
|
+
* Multiple producers per path are possible — the finding pins the *first*
|
|
322
|
+
* producer in declaration order (sufficient signal; the operator typically
|
|
323
|
+
* fixes the missing `depends_on` by linking to whichever Story they
|
|
324
|
+
* recognize). Consumers already covered by a transitive dependency to
|
|
325
|
+
* *some* producer are silently allowed even if other producers exist.
|
|
326
|
+
*/
|
|
327
|
+
function computeImplicitDepFindings(consumers, producers, reach, severity) {
|
|
328
|
+
const findings = [];
|
|
329
|
+
for (const consumer of consumers) {
|
|
330
|
+
const producerEntries = producers.get(consumer.path) ?? [];
|
|
331
|
+
if (producerEntries.length === 0) continue;
|
|
332
|
+
const reachable = reach.get(consumer.storySlug) ?? new Set();
|
|
333
|
+
const alreadyDependsOnSome = producerEntries.some(
|
|
334
|
+
(p) => p.storySlug === consumer.storySlug || reachable.has(p.storySlug),
|
|
335
|
+
);
|
|
336
|
+
if (alreadyDependsOnSome) continue;
|
|
337
|
+
const producer = producerEntries[0];
|
|
338
|
+
findings.push({
|
|
339
|
+
kind: 'implicit-cross-story-dep',
|
|
340
|
+
severity,
|
|
341
|
+
path: consumer.path,
|
|
342
|
+
producer: {
|
|
343
|
+
storySlug: producer.storySlug,
|
|
344
|
+
taskSlug: producer.taskSlug,
|
|
345
|
+
},
|
|
346
|
+
consumer: {
|
|
347
|
+
storySlug: consumer.storySlug,
|
|
348
|
+
taskSlug: consumer.taskSlug,
|
|
349
|
+
sourceField: consumer.sourceField,
|
|
350
|
+
},
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
return findings;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Index every object-form `body.changes` entry by `{ path, assumption }`
|
|
358
|
+
* along with its parent Task/Story so the registry-and-fan-out passes can
|
|
359
|
+
* reason about creates/deletes without re-walking the ticket array.
|
|
360
|
+
*/
|
|
361
|
+
function indexAssumptionEntries(stories) {
|
|
362
|
+
const entries = [];
|
|
363
|
+
for (const story of stories) {
|
|
364
|
+
const body = story?.body;
|
|
365
|
+
if (!body || typeof body !== 'object') continue;
|
|
366
|
+
const changes = Array.isArray(body.changes) ? body.changes : [];
|
|
367
|
+
for (const change of changes) {
|
|
368
|
+
if (
|
|
369
|
+
change === null ||
|
|
370
|
+
typeof change !== 'object' ||
|
|
371
|
+
typeof change.path !== 'string' ||
|
|
372
|
+
change.path.length === 0
|
|
373
|
+
)
|
|
374
|
+
continue;
|
|
375
|
+
entries.push({
|
|
376
|
+
path: change.path,
|
|
377
|
+
assumption: change.assumption ?? null,
|
|
378
|
+
storySlug: storySlugOf(story),
|
|
379
|
+
taskSlug: story.slug,
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return entries;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Compute `missing-bdd-scaffold` findings (Story #3857).
|
|
388
|
+
*
|
|
389
|
+
* The features-first delivery model requires every `.feature` file a Story
|
|
390
|
+
* verifies against to already exist when that Story runs. When a Story's
|
|
391
|
+
* `verify[]` references a `.feature` path that another Story declares with
|
|
392
|
+
* `assumption: "creates"`, the consumer is correct only if the producer
|
|
393
|
+
* lands in an *earlier* wave — otherwise the consumer's `verify[]` runs
|
|
394
|
+
* against a file that does not yet exist and verification fails mid-delivery.
|
|
395
|
+
*
|
|
396
|
+
* A finding fires for each consumer/producer pair where:
|
|
397
|
+
* - the path ends in `.feature`,
|
|
398
|
+
* - a *different* Story declares that path as `assumption: "creates"`, and
|
|
399
|
+
* - the consumer Story does not transitively `depends_on` the producer
|
|
400
|
+
* (i.e. they share a wave, or the producer runs later).
|
|
401
|
+
*
|
|
402
|
+
* The finding is advisory (`'soft'`) — it is a nudge to add a `depends_on`
|
|
403
|
+
* link to the wave-0 scaffold Story (or to the producing Story), not a hard
|
|
404
|
+
* block. The remediation is the same shape as `implicit-cross-story-dep`:
|
|
405
|
+
* order the consumer after the producer so the scaffold lands first.
|
|
406
|
+
*
|
|
407
|
+
* @param {object[]} stories
|
|
408
|
+
* @param {Map<string, Set<string>>} reach Transitive predecessor sets.
|
|
409
|
+
* @param {'soft'|'hard'} severity
|
|
410
|
+
* @returns {object[]} `missing-bdd-scaffold` findings.
|
|
411
|
+
*/
|
|
412
|
+
function computeMissingBddScaffoldFindings(stories, reach, severity) {
|
|
413
|
+
// Index every `.feature` path declared `creates` to its producing Story.
|
|
414
|
+
// A path may be created by more than one Story (unusual); pin the first in
|
|
415
|
+
// declaration order, mirroring the implicit-dep finding's single-producer
|
|
416
|
+
// shape.
|
|
417
|
+
const featureCreators = new Map(); // path -> storySlug (first creator)
|
|
418
|
+
for (const story of stories) {
|
|
419
|
+
const body = story?.body;
|
|
420
|
+
if (!body || typeof body !== 'object') continue;
|
|
421
|
+
const changes = Array.isArray(body.changes) ? body.changes : [];
|
|
422
|
+
for (const change of changes) {
|
|
423
|
+
if (
|
|
424
|
+
change === null ||
|
|
425
|
+
typeof change !== 'object' ||
|
|
426
|
+
change.assumption !== 'creates' ||
|
|
427
|
+
typeof change.path !== 'string' ||
|
|
428
|
+
!change.path.endsWith('.feature')
|
|
429
|
+
)
|
|
430
|
+
continue;
|
|
431
|
+
if (!featureCreators.has(change.path)) {
|
|
432
|
+
featureCreators.set(change.path, storySlugOf(story));
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
if (featureCreators.size === 0) return [];
|
|
437
|
+
|
|
438
|
+
const creatorPaths = Array.from(featureCreators.keys()).sort(
|
|
439
|
+
(a, b) => b.length - a.length,
|
|
440
|
+
);
|
|
441
|
+
const findings = [];
|
|
442
|
+
const seen = new Set(); // dedupe `${consumerSlug}::${path}` pairs
|
|
443
|
+
for (const story of stories) {
|
|
444
|
+
const body = story?.body;
|
|
445
|
+
if (!body || typeof body !== 'object') continue;
|
|
446
|
+
const verifyItems = Array.isArray(body.verify) ? body.verify : [];
|
|
447
|
+
if (verifyItems.length === 0) continue;
|
|
448
|
+
const joined = verifyItems.map((it) => String(it ?? '')).join('\n');
|
|
449
|
+
const consumerSlug = storySlugOf(story);
|
|
450
|
+
for (const path of creatorPaths) {
|
|
451
|
+
if (!joined.includes(path)) continue;
|
|
452
|
+
const producerSlug = featureCreators.get(path);
|
|
453
|
+
// A Story that creates the file it verifies is fine — no cross-Story gap.
|
|
454
|
+
if (producerSlug === consumerSlug) continue;
|
|
455
|
+
// Producer already runs in an earlier wave → consumer is correctly
|
|
456
|
+
// ordered, scaffold lands first, no finding.
|
|
457
|
+
const reachable = reach.get(consumerSlug) ?? new Set();
|
|
458
|
+
if (reachable.has(producerSlug)) continue;
|
|
459
|
+
const key = `${consumerSlug}::${path}`;
|
|
460
|
+
if (seen.has(key)) continue;
|
|
461
|
+
seen.add(key);
|
|
462
|
+
findings.push({
|
|
463
|
+
kind: 'missing-bdd-scaffold',
|
|
464
|
+
severity,
|
|
465
|
+
path,
|
|
466
|
+
producer: { storySlug: producerSlug },
|
|
467
|
+
consumer: { storySlug: consumerSlug, sourceField: 'verify' },
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return findings;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Compute `cross-cutting-registries` findings (Story #2962).
|
|
476
|
+
*
|
|
477
|
+
* A registry/barrel file (e.g. `lib/orchestration/lifecycle/listeners/index.js`)
|
|
478
|
+
* collides whenever two or more concurrent Stories either
|
|
479
|
+
*
|
|
480
|
+
* (a) directly edit the registry file, OR
|
|
481
|
+
* (b) create a new sibling file in the same directory that the registry
|
|
482
|
+
* would have to wire up.
|
|
483
|
+
*
|
|
484
|
+
* For each known registry pattern (`patterns`), we collect every Story whose
|
|
485
|
+
* Tasks satisfy (a) or (b). When ≥2 such Stories sit in the same wave (no
|
|
486
|
+
* transitive `depends_on` between them), emit a single finding keyed by the
|
|
487
|
+
* registry path.
|
|
488
|
+
*/
|
|
489
|
+
function computeRegistryFindings({
|
|
490
|
+
stories,
|
|
491
|
+
reach,
|
|
492
|
+
patterns,
|
|
493
|
+
producers,
|
|
494
|
+
assumptionEntries,
|
|
495
|
+
severity,
|
|
496
|
+
}) {
|
|
497
|
+
const findings = [];
|
|
498
|
+
// Build the matching registry path set from producer & creator paths.
|
|
499
|
+
const registryHits = new Map(); // registryPath -> Map<storySlug, producers[]>
|
|
500
|
+
function bump(registryPath, entry) {
|
|
501
|
+
let perStory = registryHits.get(registryPath);
|
|
502
|
+
if (!perStory) {
|
|
503
|
+
perStory = new Map();
|
|
504
|
+
registryHits.set(registryPath, perStory);
|
|
505
|
+
}
|
|
506
|
+
const existing = perStory.get(entry.storySlug) ?? [];
|
|
507
|
+
existing.push(entry);
|
|
508
|
+
perStory.set(entry.storySlug, existing);
|
|
509
|
+
}
|
|
510
|
+
// (a) direct registry edits — accept both legacy string-form producers
|
|
511
|
+
// (from `indexProducers`) and modern object-form `{ path, assumption }`
|
|
512
|
+
// entries (from `indexAssumptionEntries`).
|
|
513
|
+
for (const [path, entries] of producers.entries()) {
|
|
514
|
+
if (!isRegistryPath(path, patterns)) continue;
|
|
515
|
+
for (const e of entries) {
|
|
516
|
+
bump(path, {
|
|
517
|
+
storySlug: e.storySlug,
|
|
518
|
+
taskSlug: e.taskSlug,
|
|
519
|
+
path,
|
|
520
|
+
reason: 'edits-registry',
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
for (const e of assumptionEntries) {
|
|
525
|
+
if (!isRegistryPath(e.path, patterns)) continue;
|
|
526
|
+
bump(e.path, {
|
|
527
|
+
storySlug: e.storySlug,
|
|
528
|
+
taskSlug: e.taskSlug,
|
|
529
|
+
path: e.path,
|
|
530
|
+
reason: 'edits-registry',
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
// (b) sibling creates that would require registration in a registry.
|
|
534
|
+
// A registry path's parent dir defines its "registration scope" — any
|
|
535
|
+
// new file in that scope is a wiring candidate.
|
|
536
|
+
const scopeByRegistry = new Map();
|
|
537
|
+
for (const story of stories) {
|
|
538
|
+
const body = story?.body;
|
|
539
|
+
if (!body || typeof body !== 'object') continue;
|
|
540
|
+
for (const change of body.changes ?? []) {
|
|
541
|
+
if (
|
|
542
|
+
change === null ||
|
|
543
|
+
typeof change !== 'object' ||
|
|
544
|
+
change.assumption !== 'creates' ||
|
|
545
|
+
typeof change.path !== 'string'
|
|
546
|
+
)
|
|
547
|
+
continue;
|
|
548
|
+
const childParent = parentDirOf(change.path);
|
|
549
|
+
if (!childParent) continue;
|
|
550
|
+
for (const reg of registryRegistry(
|
|
551
|
+
producers,
|
|
552
|
+
assumptionEntries,
|
|
553
|
+
patterns,
|
|
554
|
+
scopeByRegistry,
|
|
555
|
+
)) {
|
|
556
|
+
if (reg.parentDir !== childParent) continue;
|
|
557
|
+
bump(reg.path, {
|
|
558
|
+
storySlug: storySlugOf(story),
|
|
559
|
+
taskSlug: story.slug,
|
|
560
|
+
path: change.path,
|
|
561
|
+
reason: 'creates-sibling',
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
for (const [registryPath, perStory] of registryHits.entries()) {
|
|
567
|
+
const stories = Array.from(perStory.keys());
|
|
568
|
+
if (stories.length < 2) continue;
|
|
569
|
+
const cluster = new Set();
|
|
570
|
+
for (let i = 0; i < stories.length; i += 1) {
|
|
571
|
+
for (let j = i + 1; j < stories.length; j += 1) {
|
|
572
|
+
if (inSameWave(reach, stories[i], stories[j])) {
|
|
573
|
+
cluster.add(stories[i]);
|
|
574
|
+
cluster.add(stories[j]);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
if (cluster.size === 0) continue;
|
|
579
|
+
const clusterSlugs = Array.from(cluster).sort();
|
|
580
|
+
const producerList = [];
|
|
581
|
+
for (const slug of clusterSlugs) {
|
|
582
|
+
for (const p of perStory.get(slug) ?? []) producerList.push(p);
|
|
583
|
+
}
|
|
584
|
+
findings.push({
|
|
585
|
+
kind: 'cross-cutting-registries',
|
|
586
|
+
severity,
|
|
587
|
+
registryPath,
|
|
588
|
+
storySlugs: clusterSlugs,
|
|
589
|
+
producers: producerList,
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
return findings;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* Resolve the set of registry paths that should be considered in scope for
|
|
597
|
+
* the sibling-create check. We treat any path that already matches a
|
|
598
|
+
* registry pattern (whether produced by a Task or not — the path exists in
|
|
599
|
+
* the project) as in-scope. To stay path-knowledge-free at plan time, we
|
|
600
|
+
* only consider patterns that are explicit paths (no `**`) or that match a
|
|
601
|
+
* path produced by some Task in the spec.
|
|
602
|
+
*/
|
|
603
|
+
function registryRegistry(producers, assumptionEntries, patterns, cache) {
|
|
604
|
+
if (cache.size > 0) return cache.values();
|
|
605
|
+
// Explicit (no-glob) patterns: always in scope as their own path.
|
|
606
|
+
for (const pat of patterns) {
|
|
607
|
+
if (pat.startsWith('**/')) continue;
|
|
608
|
+
cache.set(pat, { path: pat, parentDir: parentDirOf(pat) });
|
|
609
|
+
}
|
|
610
|
+
// Glob patterns: in scope iff some Task in the spec references a matching
|
|
611
|
+
// path via changes (edits or creates). Avoids false positives when a
|
|
612
|
+
// glob pattern doesn't apply to this repo at all.
|
|
613
|
+
for (const path of producers.keys()) {
|
|
614
|
+
if (cache.has(path)) continue;
|
|
615
|
+
if (isRegistryPath(path, patterns)) {
|
|
616
|
+
cache.set(path, { path, parentDir: parentDirOf(path) });
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
for (const e of assumptionEntries) {
|
|
620
|
+
if (cache.has(e.path)) continue;
|
|
621
|
+
if (isRegistryPath(e.path, patterns)) {
|
|
622
|
+
cache.set(e.path, { path: e.path, parentDir: parentDirOf(e.path) });
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return cache.values();
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Compute `fan-out-warning` findings (Story #2962).
|
|
630
|
+
*
|
|
631
|
+
* For each `body.changes` entry whose `assumption` is `"deletes"` (or
|
|
632
|
+
* `"refactors-existing"` when the planner declared a symbol replacement),
|
|
633
|
+
* count the number of distinct files in the base branch that reference
|
|
634
|
+
* the deleted module via its basename. When the count exceeds the
|
|
635
|
+
* configured `largeFanOutThreshold`, emit a finding.
|
|
636
|
+
*
|
|
637
|
+
* The default severity is always `'soft'` — the persist gate enforces a
|
|
638
|
+
* hard refusal via the `--allow-large-fan-out` operator flag, since the
|
|
639
|
+
* planner cannot reduce call sites by re-prompting. Severity may still be
|
|
640
|
+
* upgraded to `'hard'` via `failOnLargeFanOut` for callers that want the
|
|
641
|
+
* standard `errors[]` path (e.g. CI dry-runs).
|
|
642
|
+
*/
|
|
643
|
+
function computeFanOutFindings({
|
|
644
|
+
assumptionEntries,
|
|
645
|
+
threshold,
|
|
646
|
+
counter,
|
|
647
|
+
severity,
|
|
648
|
+
}) {
|
|
649
|
+
if (typeof counter !== 'function') return [];
|
|
650
|
+
if (!Number.isFinite(threshold) || threshold < 0) return [];
|
|
651
|
+
const findings = [];
|
|
652
|
+
const cache = new Map();
|
|
653
|
+
for (const entry of assumptionEntries) {
|
|
654
|
+
if (entry.assumption !== 'deletes') continue;
|
|
655
|
+
let count = cache.get(entry.path);
|
|
656
|
+
if (count === undefined) {
|
|
657
|
+
count = counter({ path: entry.path }) ?? 0;
|
|
658
|
+
cache.set(entry.path, count);
|
|
659
|
+
}
|
|
660
|
+
if (count <= threshold) continue;
|
|
661
|
+
findings.push({
|
|
662
|
+
kind: 'fan-out-warning',
|
|
663
|
+
severity,
|
|
664
|
+
taskSlug: entry.taskSlug,
|
|
665
|
+
storySlug: entry.storySlug,
|
|
666
|
+
path: entry.path,
|
|
667
|
+
callSiteCount: count,
|
|
668
|
+
threshold,
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
return findings;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Public entry point. Walks the normalized ticket spec once and returns
|
|
676
|
+
* the structured cross-Story findings array. The caller's `policy` flags
|
|
677
|
+
* decide whether each finding class lands as `'soft'` (advisory, won't
|
|
678
|
+
* trigger re-decompose) or `'hard'` (rendered into `errors[]`).
|
|
679
|
+
*
|
|
680
|
+
* @param {object} input
|
|
681
|
+
* @param {object[]} input.stories
|
|
682
|
+
* @param {object} [input.policy]
|
|
683
|
+
* @param {boolean} [input.policy.failOnSharedEditors=false]
|
|
684
|
+
* @param {boolean} [input.policy.requireExplicitCrossStoryDeps=false]
|
|
685
|
+
* @param {boolean} [input.policy.failOnRegistryConflicts=false]
|
|
686
|
+
* @param {boolean} [input.policy.failOnMissingBddScaffold=false]
|
|
687
|
+
* @param {boolean} [input.policy.failOnLargeFanOut=false]
|
|
688
|
+
* @param {number} [input.policy.largeFanOutThreshold=10]
|
|
689
|
+
* @param {string[]} [input.policy.registries] Registry patterns (defaults to DEFAULT_REGISTRY_PATTERNS).
|
|
690
|
+
* @param {(arg: { path: string }) => number} [input.policy.fanOutCounter] Optional probe; when omitted the fan-out pass is skipped.
|
|
691
|
+
* @returns {ConflictFinding[]}
|
|
692
|
+
*/
|
|
693
|
+
export function computeConflictFindings({ stories, policy } = {}) {
|
|
694
|
+
const merged = { ...DEFAULT_POLICY, ...(policy ?? {}) };
|
|
695
|
+
const storyList = stories ?? [];
|
|
696
|
+
const producers = indexProducers(storyList);
|
|
697
|
+
const consumers = indexConsumers(storyList, producers);
|
|
698
|
+
const reach = computeStoryReachability(storyList);
|
|
699
|
+
const assumptionEntries = indexAssumptionEntries(storyList);
|
|
700
|
+
const sharedSeverity = merged.failOnSharedEditors ? 'hard' : 'soft';
|
|
701
|
+
const implicitSeverity = merged.requireExplicitCrossStoryDeps
|
|
702
|
+
? 'hard'
|
|
703
|
+
: 'soft';
|
|
704
|
+
const registrySeverity = merged.failOnRegistryConflicts ? 'hard' : 'soft';
|
|
705
|
+
const fanOutSeverity = merged.failOnLargeFanOut ? 'hard' : 'soft';
|
|
706
|
+
const bddScaffoldSeverity = merged.failOnMissingBddScaffold ? 'hard' : 'soft';
|
|
707
|
+
const patterns =
|
|
708
|
+
Array.isArray(merged.registries) && merged.registries.length > 0
|
|
709
|
+
? merged.registries
|
|
710
|
+
: DEFAULT_REGISTRY_PATTERNS;
|
|
711
|
+
return [
|
|
712
|
+
...computeSharedEditorFindings(producers, reach, sharedSeverity),
|
|
713
|
+
...computeImplicitDepFindings(
|
|
714
|
+
consumers,
|
|
715
|
+
producers,
|
|
716
|
+
reach,
|
|
717
|
+
implicitSeverity,
|
|
718
|
+
),
|
|
719
|
+
...computeRegistryFindings({
|
|
720
|
+
stories: storyList,
|
|
721
|
+
reach,
|
|
722
|
+
patterns,
|
|
723
|
+
producers,
|
|
724
|
+
assumptionEntries,
|
|
725
|
+
severity: registrySeverity,
|
|
726
|
+
}),
|
|
727
|
+
...computeFanOutFindings({
|
|
728
|
+
assumptionEntries,
|
|
729
|
+
threshold: merged.largeFanOutThreshold,
|
|
730
|
+
counter: merged.fanOutCounter,
|
|
731
|
+
severity: fanOutSeverity,
|
|
732
|
+
}),
|
|
733
|
+
...computeMissingBddScaffoldFindings(storyList, reach, bddScaffoldSeverity),
|
|
734
|
+
];
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Render a `'hard'`-severity conflict finding as a human-readable error
|
|
739
|
+
* message. Used by the validator when policy flags upgrade a finding to
|
|
740
|
+
* the AC-visible `errors[]` channel.
|
|
741
|
+
*/
|
|
742
|
+
export function renderHardConflictError(finding) {
|
|
743
|
+
if (finding.kind === 'shared-editor') {
|
|
744
|
+
const stories = finding.storySlugs.map((s) => `"${s}"`).join(', ');
|
|
745
|
+
return `Shared-editor conflict: "${finding.path}" is written by ${finding.storySlugs.length} concurrent Stories (${stories}). Add depends_on chains between them or split the edits into a dedicated late-wave wiring Story.`;
|
|
746
|
+
}
|
|
747
|
+
if (finding.kind === 'implicit-cross-story-dep') {
|
|
748
|
+
return `Implicit cross-Story dependency: Task "${finding.consumer.taskSlug}" in Story "${finding.consumer.storySlug}" references "${finding.path}" (produced by Task "${finding.producer.taskSlug}" in Story "${finding.producer.storySlug}") via body.${finding.consumer.sourceField}, but Story "${finding.consumer.storySlug}" has no depends_on link to Story "${finding.producer.storySlug}". Add depends_on: ["${finding.producer.storySlug}"] to the consumer Story or remove the reference.`;
|
|
749
|
+
}
|
|
750
|
+
if (finding.kind === 'cross-cutting-registries') {
|
|
751
|
+
const stories = finding.storySlugs.map((s) => `"${s}"`).join(', ');
|
|
752
|
+
return `Cross-cutting registry conflict: ${finding.storySlugs.length} concurrent Stories (${stories}) edit or register into "${finding.registryPath}". Add depends_on chains between them so the registry updates serialize, or split the registration into a dedicated late-wave wiring Story.`;
|
|
753
|
+
}
|
|
754
|
+
if (finding.kind === 'fan-out-warning') {
|
|
755
|
+
return `Large fan-out: Task "${finding.taskSlug}" in Story "${finding.storySlug}" deletes "${finding.path}" with ${finding.callSiteCount} call site(s) on the base branch (threshold ${finding.threshold}). Split into a subsystem-by-subsystem migration across multiple Stories, or rerun --allow-large-fan-out after confirming the deletion is intentional.`;
|
|
756
|
+
}
|
|
757
|
+
if (finding.kind === 'missing-bdd-scaffold') {
|
|
758
|
+
return `Missing BDD scaffold: Story "${finding.consumer.storySlug}" verifies against "${finding.path}" (created by Story "${finding.producer.storySlug}") via body.${finding.consumer.sourceField}, but "${finding.consumer.storySlug}" has no depends_on path to "${finding.producer.storySlug}" — the .feature file is scaffolded in the same wave (or later), so verification runs before the file exists. Add depends_on: ["${finding.producer.storySlug}"] to the consumer Story so the scaffold lands in an earlier wave.`;
|
|
759
|
+
}
|
|
760
|
+
return `Conflict finding ${finding.kind} on path "${finding.path ?? '<unknown>'}".`;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// Internal helpers exposed for unit tests; not part of the public surface.
|
|
764
|
+
export const _internal = {
|
|
765
|
+
extractChangeBulletPath,
|
|
766
|
+
collectStoryProducerPaths,
|
|
767
|
+
WRITE_IMPLYING_ASSUMPTIONS,
|
|
768
|
+
indexProducers,
|
|
769
|
+
indexConsumers,
|
|
770
|
+
computeStoryReachability,
|
|
771
|
+
inSameWave,
|
|
772
|
+
computeSharedEditorFindings,
|
|
773
|
+
computeImplicitDepFindings,
|
|
774
|
+
computeMissingBddScaffoldFindings,
|
|
775
|
+
indexAssumptionEntries,
|
|
776
|
+
computeRegistryFindings,
|
|
777
|
+
computeFanOutFindings,
|
|
778
|
+
matchRegistryPattern,
|
|
779
|
+
isRegistryPath,
|
|
780
|
+
parentDirOf,
|
|
781
|
+
DEFAULT_POLICY,
|
|
782
|
+
DEFAULT_REGISTRY_PATTERNS,
|
|
783
|
+
};
|