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,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* story-plan.js — helpers for `/story-plan`.
|
|
3
|
+
*
|
|
4
|
+
* Pure functions used by `.agents/scripts/story-plan.js` (the CLI).
|
|
5
|
+
* Kept side-effect-free so the CLI stays a thin orchestrator and these
|
|
6
|
+
* helpers are easy to unit-test.
|
|
7
|
+
*
|
|
8
|
+
* Surfaces:
|
|
9
|
+
* - DEFAULT_REFINE_THRESHOLD — seed length below which refinement
|
|
10
|
+
* is auto-suggested.
|
|
11
|
+
* - REQUIRED_SECTIONS — canonical section headings the body
|
|
12
|
+
* must carry to be accepted by
|
|
13
|
+
* /single-story-deliver.
|
|
14
|
+
* - rankDuplicateCandidates({ seed, openStories, maxResults })
|
|
15
|
+
* — Jaccard-overlap ranking of open
|
|
16
|
+
* Stories whose titles fuzzy-match
|
|
17
|
+
* the seed.
|
|
18
|
+
* - validateStoryBody(body) — schema-light shape check:
|
|
19
|
+
* required sections present, no
|
|
20
|
+
* `Epic:` reference, AC checklist
|
|
21
|
+
* non-empty.
|
|
22
|
+
* - buildContextEnvelope(opts) — assemble the context envelope the
|
|
23
|
+
* host LLM consumes.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { readFile } from 'node:fs/promises';
|
|
27
|
+
import path from 'node:path';
|
|
28
|
+
import { overlapScore, tokenize } from './duplicate-search.js';
|
|
29
|
+
|
|
30
|
+
export const DEFAULT_REFINE_THRESHOLD = 200;
|
|
31
|
+
export const DEFAULT_DUPLICATE_MAX_RESULTS = 5;
|
|
32
|
+
export const DEFAULT_DUPLICATE_MIN_SCORE = 0.15;
|
|
33
|
+
|
|
34
|
+
export const REQUIRED_SECTIONS = [
|
|
35
|
+
'Context',
|
|
36
|
+
'Acceptance Criteria',
|
|
37
|
+
'Out of Scope',
|
|
38
|
+
'Notes',
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const EPIC_REF_PATTERN = /^\s*Epic:\s*#\d+/m;
|
|
42
|
+
const AC_HEADING_PATTERN = /^##\s+Acceptance Criteria\s*$/m;
|
|
43
|
+
const CHECKLIST_PATTERN = /^\s*-\s*\[\s?\]/m;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Rank open Stories by title-overlap with the seed. Reuses the same
|
|
47
|
+
* tokenize + Jaccard primitives that `duplicate-search.js` exposes for
|
|
48
|
+
* Epic-level dedupe — Stories are a different ticket type but the
|
|
49
|
+
* scoring shape is the same.
|
|
50
|
+
*
|
|
51
|
+
* @param {{ seed: string, openStories: Array<{ id:number, title:string, url?:string, body?:string }>, maxResults?: number, minScore?: number }} opts
|
|
52
|
+
* @returns {Array<{ id:number, title:string, url?:string, score:number }>}
|
|
53
|
+
*/
|
|
54
|
+
export function rankDuplicateCandidates({
|
|
55
|
+
seed,
|
|
56
|
+
openStories,
|
|
57
|
+
maxResults = DEFAULT_DUPLICATE_MAX_RESULTS,
|
|
58
|
+
minScore = DEFAULT_DUPLICATE_MIN_SCORE,
|
|
59
|
+
}) {
|
|
60
|
+
if (!seed || typeof seed !== 'string') {
|
|
61
|
+
throw new Error('rankDuplicateCandidates: seed must be a non-empty string');
|
|
62
|
+
}
|
|
63
|
+
if (!Array.isArray(openStories)) {
|
|
64
|
+
throw new Error('rankDuplicateCandidates: openStories must be an array');
|
|
65
|
+
}
|
|
66
|
+
const seedTokens = tokenize(seed);
|
|
67
|
+
if (seedTokens.size === 0) return [];
|
|
68
|
+
|
|
69
|
+
const ranked = [];
|
|
70
|
+
for (const story of openStories) {
|
|
71
|
+
if (!story || typeof story.title !== 'string') continue;
|
|
72
|
+
const corpus = `${story.title}\n${story.body ?? ''}`;
|
|
73
|
+
const candTokens = tokenize(corpus);
|
|
74
|
+
const score = overlapScore(seedTokens, candTokens);
|
|
75
|
+
if (score >= minScore) {
|
|
76
|
+
ranked.push({
|
|
77
|
+
id: story.id,
|
|
78
|
+
title: story.title,
|
|
79
|
+
url: story.url,
|
|
80
|
+
score: Number(score.toFixed(4)),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
ranked.sort((a, b) => b.score - a.score);
|
|
85
|
+
return ranked.slice(0, maxResults);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Decide whether the seed warrants a Phase-2 idea-refinement pass.
|
|
90
|
+
* The default rule: refine when the seed is shorter than
|
|
91
|
+
* `DEFAULT_REFINE_THRESHOLD` chars. Operator overrides via
|
|
92
|
+
* `--refine` / `--no-refine` short-circuit the heuristic.
|
|
93
|
+
*
|
|
94
|
+
* @param {{ seed:string, override?:'on'|'off'|null, threshold?:number }} opts
|
|
95
|
+
* @returns {{ refine:boolean, reason:string }}
|
|
96
|
+
*/
|
|
97
|
+
export function shouldRefine({
|
|
98
|
+
seed,
|
|
99
|
+
override = null,
|
|
100
|
+
threshold = DEFAULT_REFINE_THRESHOLD,
|
|
101
|
+
}) {
|
|
102
|
+
if (override === 'on') return { refine: true, reason: 'operator-forced-on' };
|
|
103
|
+
if (override === 'off')
|
|
104
|
+
return { refine: false, reason: 'operator-forced-off' };
|
|
105
|
+
if (typeof seed !== 'string' || seed.trim().length === 0) {
|
|
106
|
+
return { refine: true, reason: 'empty-seed' };
|
|
107
|
+
}
|
|
108
|
+
if (seed.trim().length < threshold) {
|
|
109
|
+
return {
|
|
110
|
+
refine: true,
|
|
111
|
+
reason: `seed-shorter-than-${threshold}-chars`,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return { refine: false, reason: `seed-meets-${threshold}-char-threshold` };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Schema-light validator for a standalone-Story body. Used by the persist
|
|
119
|
+
* path *and* by tests asserting `--dry-run` output stability. The check
|
|
120
|
+
* is deliberately tolerant of authoring whitespace: it asserts the
|
|
121
|
+
* canonical headings are present, that no `Epic: #N` reference leaks
|
|
122
|
+
* (the standalone contract), and that the Acceptance Criteria section
|
|
123
|
+
* carries at least one unchecked checklist item.
|
|
124
|
+
*
|
|
125
|
+
* @param {string} body
|
|
126
|
+
* @returns {{ ok:boolean, errors:string[] }}
|
|
127
|
+
*/
|
|
128
|
+
export function validateStoryBody(body) {
|
|
129
|
+
const errors = [];
|
|
130
|
+
if (typeof body !== 'string' || body.trim().length === 0) {
|
|
131
|
+
return { ok: false, errors: ['body is empty'] };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
for (const section of REQUIRED_SECTIONS) {
|
|
135
|
+
const pattern = new RegExp(`^##\\s+${escapeRegex(section)}\\s*$`, 'm');
|
|
136
|
+
if (!pattern.test(body)) {
|
|
137
|
+
errors.push(`missing required section: "## ${section}"`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (EPIC_REF_PATTERN.test(body)) {
|
|
142
|
+
errors.push(
|
|
143
|
+
'body contains an "Epic: #N" reference — standalone Stories must not link to an Epic',
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// AC checklist non-empty: extract from "## Acceptance Criteria" to the
|
|
148
|
+
// next "## " heading (or EOF) and assert at least one checklist item.
|
|
149
|
+
const acStart = body.search(AC_HEADING_PATTERN);
|
|
150
|
+
if (acStart !== -1) {
|
|
151
|
+
const rest = body.slice(acStart);
|
|
152
|
+
const nextHeading = rest.slice(1).search(/^##\s+/m);
|
|
153
|
+
const acBlock = nextHeading === -1 ? rest : rest.slice(0, nextHeading + 1);
|
|
154
|
+
if (!CHECKLIST_PATTERN.test(acBlock)) {
|
|
155
|
+
errors.push(
|
|
156
|
+
'Acceptance Criteria section has no unchecked checklist items (`- [ ] ...`)',
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return { ok: errors.length === 0, errors };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function escapeRegex(s) {
|
|
165
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Load the body-template file from disk. Resolves relative to a project
|
|
170
|
+
* root so callers (CLI, tests) can pin the lookup deterministically.
|
|
171
|
+
*
|
|
172
|
+
* @param {string} projectRoot
|
|
173
|
+
* @returns {Promise<string>}
|
|
174
|
+
*/
|
|
175
|
+
export async function loadBodyTemplate(projectRoot) {
|
|
176
|
+
const tpl = path.join(
|
|
177
|
+
projectRoot,
|
|
178
|
+
'.agents',
|
|
179
|
+
'templates',
|
|
180
|
+
'single-story-body.md',
|
|
181
|
+
);
|
|
182
|
+
return readFile(tpl, 'utf8');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Assemble the context envelope the host LLM consumes to author a draft
|
|
187
|
+
* Story body. Pure — no I/O beyond what the caller passed in.
|
|
188
|
+
*
|
|
189
|
+
* @param {{
|
|
190
|
+
* seed: string,
|
|
191
|
+
* refine: { refine:boolean, reason:string },
|
|
192
|
+
* persona: string,
|
|
193
|
+
* bodyTemplate: string,
|
|
194
|
+
* duplicateCandidates: Array<object>,
|
|
195
|
+
* techStack?: string|null,
|
|
196
|
+
* maxResults?: number,
|
|
197
|
+
* }} opts
|
|
198
|
+
*/
|
|
199
|
+
export function buildContextEnvelope({
|
|
200
|
+
seed,
|
|
201
|
+
refine,
|
|
202
|
+
persona,
|
|
203
|
+
bodyTemplate,
|
|
204
|
+
duplicateCandidates,
|
|
205
|
+
techStack = null,
|
|
206
|
+
maxResults = DEFAULT_DUPLICATE_MAX_RESULTS,
|
|
207
|
+
}) {
|
|
208
|
+
return {
|
|
209
|
+
kind: 'story-plan-context',
|
|
210
|
+
version: 1,
|
|
211
|
+
seed,
|
|
212
|
+
refine,
|
|
213
|
+
persona,
|
|
214
|
+
bodyTemplate,
|
|
215
|
+
requiredSections: [...REQUIRED_SECTIONS],
|
|
216
|
+
duplicateCandidates: {
|
|
217
|
+
maxResults,
|
|
218
|
+
candidates: duplicateCandidates,
|
|
219
|
+
},
|
|
220
|
+
techStack,
|
|
221
|
+
deliverContract: {
|
|
222
|
+
workflow: '.agents/workflows/helpers/single-story-deliver.md',
|
|
223
|
+
requiredLabels: ['type::story', `persona::${persona}`],
|
|
224
|
+
forbidden: ['Epic: #N references in the body'],
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Strip the leading "Tech Stack" section of `docs/architecture.md` for
|
|
231
|
+
* the host LLM. Returns `null` when the file or section is missing.
|
|
232
|
+
*
|
|
233
|
+
* @param {string} projectRoot
|
|
234
|
+
* @returns {Promise<string|null>}
|
|
235
|
+
*/
|
|
236
|
+
export async function readTechStackSummary(projectRoot) {
|
|
237
|
+
const archPath = path.join(projectRoot, 'docs', 'architecture.md');
|
|
238
|
+
let content;
|
|
239
|
+
try {
|
|
240
|
+
content = await readFile(archPath, 'utf8');
|
|
241
|
+
} catch {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
const match = content.match(/^##\s+Tech Stack\s*$([\s\S]*?)(?=^##\s+\S)/m);
|
|
245
|
+
return match ? `## Tech Stack${match[1]}`.trim() : null;
|
|
246
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* task-utils.js
|
|
3
|
+
*
|
|
4
|
+
* Shared utilities for inspecting task objects throughout the pipeline.
|
|
5
|
+
* Centralises the bookend-detection predicate so that any future addition of a
|
|
6
|
+
* new bookend type only requires a change in one place.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Returns true when the given task is a bookend (lifecycle-management) task.
|
|
11
|
+
*
|
|
12
|
+
* Bookend tasks are distinguished from regular development tasks by one of the
|
|
13
|
+
* following flags being truthy:
|
|
14
|
+
* - isQA — automated testing phase
|
|
15
|
+
* - isCodeReview — architectural review phase
|
|
16
|
+
* - isRetro — retrospective phase
|
|
17
|
+
* - isCloseSprint — sprint close-out + tagging phase
|
|
18
|
+
*
|
|
19
|
+
* @param {object} task - A task object from the sprint manifest.
|
|
20
|
+
* @returns {boolean}
|
|
21
|
+
*/
|
|
22
|
+
export function isBookendTask(task) {
|
|
23
|
+
return Boolean(
|
|
24
|
+
task.isQA || task.isCodeReview || task.isRetro || task.isCloseSprint,
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { LIMITS_DEFAULTS } from '../config/limits.js';
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_TASK_SIZING,
|
|
4
|
+
DELIVERABLE_GRANULARITY_GUIDANCE,
|
|
5
|
+
SOFT_STORIES_PER_FEATURE,
|
|
6
|
+
} from '../orchestration/ticket-validator-sizing.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Sole source of truth for the prompt's `maxTickets` cap is the resolved
|
|
10
|
+
* limits block (see {@link LIMITS_DEFAULTS}). The previous standalone
|
|
11
|
+
* `DEFAULT_MAX_TICKETS = 40` literal allowed the prompt to drift out of sync
|
|
12
|
+
* with `planning.maxTickets` when call sites forgot to pass the
|
|
13
|
+
* resolved value; importing it here means a fallback path (no caller-supplied
|
|
14
|
+
* value) still tracks the framework default in `lib/config/limits.js`.
|
|
15
|
+
*
|
|
16
|
+
* 3-tier is the only published hierarchy after Task #3154 deleted the
|
|
17
|
+
* `planning.hierarchy` flag: the prompt omits the Task layer entirely and
|
|
18
|
+
* asks the planner to inline acceptance/verify on the Story body.
|
|
19
|
+
*/
|
|
20
|
+
export function renderDecomposerSystemPrompt({
|
|
21
|
+
maxTickets = LIMITS_DEFAULTS.maxTickets,
|
|
22
|
+
} = {}) {
|
|
23
|
+
return render3TierPrompt({ maxTickets });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 3-tier prompt (Epic #3078). Decomposes to Feature → Story only — no Task
|
|
28
|
+
* layer. Acceptance criteria and verification commands live inline on the
|
|
29
|
+
* Story body so the executing agent has everything it needs in one ticket.
|
|
30
|
+
*/
|
|
31
|
+
function render3TierPrompt({ maxTickets }) {
|
|
32
|
+
// Sizing thresholds are sourced from the single DEFAULT_TASK_SIZING constant
|
|
33
|
+
// (ticket-validator-sizing.js) so the prompt and the validator cannot drift.
|
|
34
|
+
const { softFiles, hardFiles, maxAcceptance, softAcceptanceCount } =
|
|
35
|
+
DEFAULT_TASK_SIZING;
|
|
36
|
+
// Deliverable-granularity definition + single-consumer merge rule are
|
|
37
|
+
// sourced from the single DELIVERABLE_GRANULARITY_GUIDANCE constant
|
|
38
|
+
// (ticket-validator-sizing.js) so the prompt and the authoring SKILL
|
|
39
|
+
// cannot drift (Story #3777).
|
|
40
|
+
const { definition: granularityDefinition, singleConsumerRule } =
|
|
41
|
+
DELIVERABLE_GRANULARITY_GUIDANCE;
|
|
42
|
+
return `You are an expert Senior Project Manager and Orchestrator.
|
|
43
|
+
Your job is to take a Product Requirements Document (PRD) and a Technical Specification and decompose them into a highly-granular 2-level ticket hierarchy for an AI Agent to execute.
|
|
44
|
+
|
|
45
|
+
### HIERARCHY RULES:
|
|
46
|
+
1. **Features**: Large functional milestones (e.g., "Authentication Provider Integration").
|
|
47
|
+
2. **Stories**: Specific user-facing or architectural user stories (e.g., "Implement JWT Token Exchange").
|
|
48
|
+
- MUST be nested under a Feature.
|
|
49
|
+
- **Story-Level Execution**: Each Story will be executed end-to-end on a single branch by a single agent. There is NO Task layer in this hierarchy — acceptance criteria and verification commands live inline on the Story body (see STORY BODY SCHEMA below).
|
|
50
|
+
|
|
51
|
+
### LABEL CONVENTIONS:
|
|
52
|
+
- Every ticket must have a \`type::[feature|story]\` label. The \`type::task\` label is FORBIDDEN under this hierarchy.
|
|
53
|
+
- Every ticket must have a \`persona::[engineer|architect|qa-engineer|engineer-web|etc]\` label indicating WHO should execute it.
|
|
54
|
+
|
|
55
|
+
### OUTPUT FORMAT:
|
|
56
|
+
You MUST respond ONLY with a valid JSON array of objects. No prose, no markdown blocks.
|
|
57
|
+
|
|
58
|
+
### JSON SCHEMA:
|
|
59
|
+
[
|
|
60
|
+
{
|
|
61
|
+
"slug": "unique_string_id",
|
|
62
|
+
"type": "feature" | "story",
|
|
63
|
+
"title": "Short descriptive title",
|
|
64
|
+
"body": <string for features; see STORY BODY SCHEMA below for stories>,
|
|
65
|
+
"labels": ["type::...", "persona::..."],
|
|
66
|
+
"parent_slug": "slug_of_parent_ticket" (leave empty for features to nest under epic),
|
|
67
|
+
"depends_on": ["slug_of_blocking_dependency"] (optional array of slugs that block execution)
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
### FEATURE BODY:
|
|
72
|
+
For Features, \`body\` is a brief string under 2 sentences. Features are navigational — the work happens at the Story level — so dense bodies waste output budget.
|
|
73
|
+
|
|
74
|
+
#### FEATURE GROUPING — CAPABILITY/STAKEHOLDER, NOT EXECUTION SHAPE:
|
|
75
|
+
|
|
76
|
+
- **Do not group Stories by technical execution shape (cron jobs, middleware, scripts). Group by the capability or stakeholder they serve.** Two Stories that happen to share a delivery mechanism — both are cron sweeps, both are Express middleware, both are CLI scripts — do NOT belong in the same Feature just because of that shared shape. The Feature axis is the user-facing capability or the stakeholder served, never the implementation vehicle.
|
|
77
|
+
- **Operational/compliance work gets its own Feature.** Retention purges, audit-log sweeps, scheduled cleanups, observability emitters, and other operational/compliance chores serve operators and compliance, not end users. Place them in a dedicated \`compliance-and-observability\` or \`data-retention\` Feature — do NOT fold them into a user-facing Feature (e.g. notification flows) merely because they share a cron/scheduled execution shape with user-facing Stories.
|
|
78
|
+
- **Smell test:** if the only thing two Stories have in common is *how* they run (a scheduled job, a request interceptor, a build step) rather than *whom* they serve or *what* capability they deliver, they are mis-grouped. Re-home the operational/compliance Story into its own capability Feature.
|
|
79
|
+
|
|
80
|
+
### STORY BODY SCHEMA (REQUIRED FOR EVERY STORY):
|
|
81
|
+
For stories, \`body\` is a STRUCTURED OBJECT, not a string. Stories are consumed by non-interactive sub-agents that must self-verify from the Story body alone — there is no Task layer below — so the Story itself must carry everything an agent needs to execute and self-verify.
|
|
82
|
+
|
|
83
|
+
"body": {
|
|
84
|
+
"goal": "<one sentence — tie this story to the parent Feature slug, naming the slug>",
|
|
85
|
+
"changes": ["<file path>: <verb> <object>", ...],
|
|
86
|
+
"acceptance": ["<testable, observable criterion>", ...],
|
|
87
|
+
"verify": ["<exact command or test path> (<tier>)", ...],
|
|
88
|
+
"estimated_test_files": <integer — number of test files this Story is expected to create or modify; omit when not estimable>
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
#### STORY BODY RULES:
|
|
92
|
+
|
|
93
|
+
- **goal**: One sentence stating WHY this story exists. MUST name the parent Feature slug.
|
|
94
|
+
- **changes**: Each bullet MUST be \`<path-or-glob>: <concrete verb> <object>\`. Acceptable path shapes include explicit files (\`src/components/Foo.tsx\`), glob patterns (\`tests/e2e/*.spec.ts\`, \`**/*.astro\`), and module identifiers that resolve to files. Vague verbs ("clean up", "refactor", "improve", "polish", "tighten") are FORBIDDEN unless paired with a named target — "refactor src/x.ts: extract handleSubmit" is fine, "refactor the form" is not.
|
|
95
|
+
- **acceptance**: Items MUST be observable from outside the agent. Acceptable shapes: a specific command exits 0, a file exists at a given path, a snapshot test matches, a \`data-testid\` resolves under a given selector, a row count in a fixture matches. UNACCEPTABLE: "verify by reading the diff", "looks good", "matches the spec" — push these down into a \`verify\` command instead.
|
|
96
|
+
- **verify**: Each entry MUST name a testing tier in parentheses, drawn from \`unit\` / \`contract\` / \`e2e\` / \`validate\`. Example: \`npm run test -- src/x.test.ts (unit)\`, \`npm run validate (validate)\`. Stories with zero verify entries SHOULD fail validation; if a story is genuinely unverifiable in isolation (e.g., a copy edit auditor will eyeball), the literal entry \`manual:<reason>\` is allowed so the absence is intentional, not lazy. Manual entries without a reason are rejected.
|
|
97
|
+
- **estimated_test_files** (optional): Integer estimate of how many test files this Story creates or modifies. Omit when the number is not estimable. Informational only — it does not gate the decompose.
|
|
98
|
+
|
|
99
|
+
#### STORY SIZING — COHESION FIRST (the numeric ceiling is only a backstop):
|
|
100
|
+
|
|
101
|
+
**Decompose at deliverable granularity, not module/task level.** ${granularityDefinition}
|
|
102
|
+
|
|
103
|
+
The primary question is **cohesion, not count**: *is this one coherent change with one reason to exist?* File count cannot tell a trivial ${softFiles}-file rename from a hard 3-file parser+caller+config change — so lead with the change's reason, not its size.
|
|
104
|
+
|
|
105
|
+
- **One Story = one coherent change with one reason to exist.** If you cannot state that reason in a sentence, the Story is probably two Stories — or two Stories that should be one.
|
|
106
|
+
- ${singleConsumerRule}
|
|
107
|
+
- **Split independent, parallelizable work** into sibling Stories under the same Feature — but only when the pieces genuinely have separate reasons to exist.
|
|
108
|
+
- **Declare \`wide\` with a one-line reason when a change is legitimately broad** (a cohesive cutover that spans many files for one reason). Declaring \`wide\` lifts the hard file-width ceiling — see below.
|
|
109
|
+
- **Every Feature MUST decompose into at least TWO Stories.** A Feature with a single Story is the work of a Story, not a Feature — collapse it (drop the Feature wrapper and attach its lone Story to a sibling Feature, or merge the Feature into another). The validator HARD-rejects a Feature with fewer than two Stories.
|
|
110
|
+
- **Features typically decompose into ≤${SOFT_STORIES_PER_FEATURE} Stories; otherwise split into a sibling Feature.** A Feature stretching past ${SOFT_STORIES_PER_FEATURE} Stories is a sign the Feature scope is two features.
|
|
111
|
+
|
|
112
|
+
**Numeric backstop (validator-enforced).** These thresholds are sourced from the single \`DEFAULT_TASK_SIZING\` constant in \`ticket-validator-sizing.js\` — there is no second copy to drift:
|
|
113
|
+
|
|
114
|
+
- A Story touching more than **${softFiles} files** (\`softFiles\`) emits an advisory width finding — a nudge to check cohesion or declare \`wide\`.
|
|
115
|
+
- A Story touching more than **${hardFiles} files** (\`hardFiles\`) is **rejected** unless it declares \`wide\` with a reason.
|
|
116
|
+
- A Story with more than **${maxAcceptance} acceptance items** (\`maxAcceptance\`) is **rejected**; more than ${softAcceptanceCount} (\`softAcceptanceCount\`) emits an advisory warning.
|
|
117
|
+
|
|
118
|
+
#### \`wide\` DECLARATION (optional — for legitimately broad changes):
|
|
119
|
+
|
|
120
|
+
A Story whose footprint is legitimately broad declares \`body.wide\` carrying a one-line human-readable reason:
|
|
121
|
+
|
|
122
|
+
\`\`\`json
|
|
123
|
+
"wide": { "reason": "hard contract cutover: migrate every <X> call site in one PR" }
|
|
124
|
+
\`\`\`
|
|
125
|
+
|
|
126
|
+
Declaring \`wide\` with a non-empty reason **lifts the \`hardFiles\` rejection** — no Story is rejected for width when it states why it is broad. Omit \`wide\` for ordinary Stories; a wide footprint with no \`wide\` declaration emits only an advisory nudge (check cohesion or declare \`wide\`), never a rejection on its own.
|
|
127
|
+
|
|
128
|
+
**Glob entries** in \`changes[]\` (bullets containing \`*\`) mark the Story footprint as \`unknown-width\`: the numeric ceiling cannot bound a glob, so it is skipped. A Story carrying glob changes with no \`wide\` declaration emits an advisory nudge.
|
|
129
|
+
|
|
130
|
+
#### UI / TESTID INVARIANCE (per CLAUDE.md safety rule):
|
|
131
|
+
|
|
132
|
+
- Stories that touch UI (\`*.tsx\`, \`*.astro\`, \`*.svelte\`, \`*.vue\`, components folders) MUST end \`changes\` with one of:
|
|
133
|
+
- \`data-testid invariance: <list of testids that MUST be preserved>\`, or
|
|
134
|
+
- \`data-testid changes: <old> -> <new>\` paired with a corresponding \`tests/e2e/*.spec.ts\` edit in the same story or a depends_on Story.
|
|
135
|
+
- Renaming a testid without the matching e2e edit is FORBIDDEN.
|
|
136
|
+
|
|
137
|
+
#### BRAND / COPY / STYLE WORK:
|
|
138
|
+
|
|
139
|
+
- Stories that touch user-visible copy, brand assets, or visual style MUST cite the relevant section of \`docs/style-guide.md\` in \`acceptance\` (e.g. \`"acceptance": ["Hero copy matches docs/style-guide.md §3 (voice & tone)"]\`). If \`docs/style-guide.md\` does not exist or has no relevant section, state that explicitly: \`"acceptance": ["docs/style-guide.md absent — copy reviewed against the inline brand brief in PRD §2"]\`. Silence on style sourcing is a smell.
|
|
140
|
+
|
|
141
|
+
### WAVE-0 BDD SCAFFOLD STORY (features-first; emit when the Acceptance Spec has \`new\`-disposition rows):
|
|
142
|
+
The Acceptance Spec's AC table (columns \`AC ID | Outcome | Feature File | Scenario | Disposition\`) tags each row's \`Disposition\` with one of \`new | updated | unchanged\`. A \`new\` row names a \`.feature\` file + scenario that does NOT yet exist on \`main\`. The framework is features-first: implementing Stories reference those \`.feature\` paths in their \`verify[]\` lines, so the files MUST already exist when those Stories run — otherwise verification fails mid-delivery on a missing file.
|
|
143
|
+
|
|
144
|
+
When the Acceptance Spec contains **one or more \`Disposition: new\` rows**, you MUST emit **exactly one** dedicated wave-0 scaffold Story whose sole job is to create the \`.feature\` files with \`@skip\`-tagged scenarios BEFORE any implementation Story runs:
|
|
145
|
+
|
|
146
|
+
- **goal**: contains the literal token \`bdd-scaffold\` (e.g. "bdd-scaffold: create the @skip-tagged feature files the implementation Stories verify against, for parent Feature <slug>").
|
|
147
|
+
- **depends_on**: EMPTY (\`[]\`) — it runs first, in wave 0.
|
|
148
|
+
- **changes**: one entry per distinct \`.feature\` file named in a \`new\` row, each \`{ "path": "<feature file path>", "assumption": "creates" }\`.
|
|
149
|
+
- **acceptance**: MUST assert (a) every new \`.feature\` file exists, and (b) every new scenario within them carries an \`@skip\` tag. Keep these observable (a grep/validate command exits 0, a file exists at a path).
|
|
150
|
+
- **verify**: a grep/validate command (tier \`validate\`), NOT an e2e runner — verifying that a file exists with a tag needs no browser/playwright run. Example: \`grep -rL '@skip' tests/features/<area>/*.feature (validate)\` paired with an existence check.
|
|
151
|
+
- Each implementation Story whose \`verify[]\` references one of these scaffolded \`.feature\` paths MUST \`depends_on\` the scaffold Story (so the scaffold lands in an earlier wave). Omitting the link trips the soft \`missing-bdd-scaffold\` validator finding.
|
|
152
|
+
|
|
153
|
+
When the Acceptance Spec contains **zero \`new\`-disposition rows** (every row is \`updated\` or \`unchanged\`), do NOT emit a scaffold Story — there is nothing to create.
|
|
154
|
+
|
|
155
|
+
### SCOPE-OVERLAP FLAGGING (docs/runbook downstream of config work):
|
|
156
|
+
When a "docs update" / "runbook" / "README" Story appears downstream of an earlier Story in the same Epic whose AC already covers updating the same document (e.g. a "config + runbook" Story followed by a "docs" Story touching the same runbook), the downstream Story's deliverable may be fully absorbed by the earlier Story. Flag the risk directly in the Story \`body.acceptance\` by appending an item of the form:
|
|
157
|
+
"Scope verification note: this story's deliverable may already be satisfied by Story #<slug-or-id>'s AC — before implementing, \`git diff main -- <path>\` against the upstream Story branch and confirm whether a substantive edit is still required, or whether only a cross-reference remains."
|
|
158
|
+
This prevents the executing agent from redoing work the upstream Story already merged.
|
|
159
|
+
|
|
160
|
+
CRITICAL: Dependencies should follow execution blockers. For hierarchical grouping, strictly use 'parent_slug' (Story parent MUST be a Feature). Features should have no 'parent_slug' (they attach to Epic).
|
|
161
|
+
IMPORTANT DEPENDENCY RULE: Cross-Feature Story dependencies are allowed via \`depends_on\` at the Story level (one Story depends_on another Story's slug). Use this to express execution ordering across the plan.
|
|
162
|
+
|
|
163
|
+
### REVIEWABILITY BUDGET (Story #2798):
|
|
164
|
+
\`maxTickets = ${maxTickets}\` is a **reviewability budget**, not a hard authoring cap. It marks the count of tickets a human operator can comfortably review in one planning pass; emitting more than this overflows the operator's review window. Default behaviour:
|
|
165
|
+
- **Stay at or under the budget when possible.** Merge narrow, single-module stories into larger, cohesive capability stories before splitting; small Stories should merge back into siblings rather than spawn their own container.
|
|
166
|
+
- **Do NOT truncate or over-compress to fit.** If the plan genuinely needs more tickets than the budget, emit the full plan anyway and add a compact \`over_budget_rationale\` string at the top of the FIRST Feature's \`body\` explaining (a) why the plan exceeds the budget and (b) what was already merged to keep the count down. The operator will then either accept the plan by re-running the decompose with the explicit \`--allow-over-budget\` override flag, or push back and ask for a re-scope.
|
|
167
|
+
- **Never stop mid-array.** Always emit complete JSON — partial arrays are rejected by the validator.`;
|
|
168
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a webhook-safe child-process environment for test runners.
|
|
3
|
+
*
|
|
4
|
+
* Operators keep a real `NOTIFICATION_WEBHOOK_URL` in `.env` for development
|
|
5
|
+
* (the production `notify()` path reads it via `process.env` after
|
|
6
|
+
* `resolveConfig()` calls `loadEnv()`). Without scrubbing, any test that
|
|
7
|
+
* transitively reaches `notify()` POSTs to the live endpoint.
|
|
8
|
+
*
|
|
9
|
+
* This helper produces the env bag that test child processes inherit:
|
|
10
|
+
*
|
|
11
|
+
* - `NOTIFICATION_WEBHOOK_URL` is deleted unless the operator opted in
|
|
12
|
+
* via `MANDREL_ALLOW_TEST_WEBHOOKS=1` (e.g., a contract test
|
|
13
|
+
* deliberately exercising a sandbox endpoint). With the URL scrubbed,
|
|
14
|
+
* `resolveWebhookUrl()` returns nothing and `notify()` never POSTs.
|
|
15
|
+
* - `NODE_ENV=test` is set for the rest of the suite's environment
|
|
16
|
+
* expectations. (It no longer gates `notify()`'s webhook delivery —
|
|
17
|
+
* the NODE_ENV band-aid was removed in Story #3342. Tests that need to
|
|
18
|
+
* exercise the webhook POST inject `opts.fetchImpl` instead, so the
|
|
19
|
+
* request never reaches the real network even if a URL resolves.)
|
|
20
|
+
*
|
|
21
|
+
* @param {NodeJS.ProcessEnv} baseEnv
|
|
22
|
+
* @returns {NodeJS.ProcessEnv}
|
|
23
|
+
*/
|
|
24
|
+
export function buildWebhookSafeTestEnv(baseEnv = process.env) {
|
|
25
|
+
const env = { ...baseEnv, NODE_ENV: baseEnv.NODE_ENV ?? 'test' };
|
|
26
|
+
if (env.MANDREL_ALLOW_TEST_WEBHOOKS !== '1') {
|
|
27
|
+
delete env.NOTIFICATION_WEBHOOK_URL;
|
|
28
|
+
}
|
|
29
|
+
return env;
|
|
30
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/* node:coverage ignore file */
|
|
2
|
+
/**
|
|
3
|
+
* Preload module for `test-isolate`. Snapshots `process.env` at module load
|
|
4
|
+
* time and writes a diff envelope to the file named in
|
|
5
|
+
* `TEST_ISOLATE_ENV_OUT` when the process exits. Used to surface env-var
|
|
6
|
+
* mutations a test made and failed to restore.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import fs from 'node:fs';
|
|
10
|
+
|
|
11
|
+
const OUT_PATH = process.env.TEST_ISOLATE_ENV_OUT;
|
|
12
|
+
if (OUT_PATH) {
|
|
13
|
+
const beforeSnapshot = { ...process.env };
|
|
14
|
+
// NODE_OPTIONS propagates this loader into every node process spawned
|
|
15
|
+
// beneath the runner (including node:test's per-file child workers). We
|
|
16
|
+
// write to a per-pid sidecar file so the parent runner can pick the
|
|
17
|
+
// child's diff and ignore its own empty one.
|
|
18
|
+
const pidPath = `${OUT_PATH}.${process.pid}.json`;
|
|
19
|
+
process.on('exit', () => {
|
|
20
|
+
try {
|
|
21
|
+
const after = process.env;
|
|
22
|
+
const added = [];
|
|
23
|
+
const removed = [];
|
|
24
|
+
const changed = [];
|
|
25
|
+
const IGNORE = new Set([
|
|
26
|
+
'TEST_ISOLATE_ENV_OUT',
|
|
27
|
+
// NODE_OPTIONS is rewritten by the parent's spawn; ignore it so
|
|
28
|
+
// the loader doesn't flag itself as a leak.
|
|
29
|
+
'NODE_OPTIONS',
|
|
30
|
+
]);
|
|
31
|
+
for (const key of Object.keys(after)) {
|
|
32
|
+
if (IGNORE.has(key)) continue;
|
|
33
|
+
if (!(key in beforeSnapshot)) added.push(key);
|
|
34
|
+
else if (beforeSnapshot[key] !== after[key]) changed.push(key);
|
|
35
|
+
}
|
|
36
|
+
for (const key of Object.keys(beforeSnapshot)) {
|
|
37
|
+
if (IGNORE.has(key)) continue;
|
|
38
|
+
if (!(key in after)) removed.push(key);
|
|
39
|
+
}
|
|
40
|
+
if (added.length === 0 && removed.length === 0 && changed.length === 0) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
fs.writeFileSync(
|
|
44
|
+
pidPath,
|
|
45
|
+
JSON.stringify({ added, removed, changed }),
|
|
46
|
+
'utf8',
|
|
47
|
+
);
|
|
48
|
+
} catch {
|
|
49
|
+
// Best-effort — do not interfere with the host process exit.
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import picomatch from 'picomatch';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Walk a directory and return repo-relative `*.test.js` paths (forward
|
|
7
|
+
* slashes). Skips `node_modules`, `.worktrees`, and dot-prefixed dirs.
|
|
8
|
+
*
|
|
9
|
+
* @param {string} root
|
|
10
|
+
* @param {typeof fs} [fsLike]
|
|
11
|
+
* @returns {string[]}
|
|
12
|
+
*/
|
|
13
|
+
export function walkTestFiles(root, fsLike = fs) {
|
|
14
|
+
const out = [];
|
|
15
|
+
walk(root, '');
|
|
16
|
+
return out.sort();
|
|
17
|
+
|
|
18
|
+
function walk(dir, prefix) {
|
|
19
|
+
if (!fsLike.existsSync(dir)) return;
|
|
20
|
+
for (const ent of fsLike.readdirSync(dir, { withFileTypes: true })) {
|
|
21
|
+
const name = ent.name;
|
|
22
|
+
if (
|
|
23
|
+
name === 'node_modules' ||
|
|
24
|
+
name === '.worktrees' ||
|
|
25
|
+
name.startsWith('.')
|
|
26
|
+
) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const abs = path.join(dir, name);
|
|
30
|
+
const rel = prefix ? `${prefix}/${name}` : name;
|
|
31
|
+
if (ent.isDirectory()) {
|
|
32
|
+
walk(abs, rel);
|
|
33
|
+
} else if (name.endsWith('.test.js')) {
|
|
34
|
+
out.push(rel.replace(/\\/g, '/'));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Resolve the user's pattern to a sorted list of repo-relative test file
|
|
42
|
+
* paths. Patterns may be:
|
|
43
|
+
*
|
|
44
|
+
* - a glob (`tests/**\/*.test.js`, `tests/lib/foo*.test.js`)
|
|
45
|
+
* - an explicit file path (absolute or repo-relative)
|
|
46
|
+
* - a directory (walked for `*.test.js` descendants)
|
|
47
|
+
* - omitted (defaults to `tests/**\/*.test.js`)
|
|
48
|
+
*
|
|
49
|
+
* @param {object} opts
|
|
50
|
+
* @param {string} [opts.pattern]
|
|
51
|
+
* @param {string} opts.repoRoot
|
|
52
|
+
* @param {string[]} [opts.allFiles] Override the discovered file list for tests.
|
|
53
|
+
* @param {typeof fs} [opts.fsLike]
|
|
54
|
+
* @returns {string[]}
|
|
55
|
+
*/
|
|
56
|
+
export function resolveTestFiles({ pattern, repoRoot, allFiles, fsLike = fs }) {
|
|
57
|
+
const discoverAll = () => allFiles ?? walkTestFiles(repoRoot, fsLike);
|
|
58
|
+
|
|
59
|
+
if (!pattern || pattern === 'tests/**/*.test.js') {
|
|
60
|
+
return discoverAll().filter((f) => f.startsWith('tests/'));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Absolute path → relativize.
|
|
64
|
+
let target = pattern.replace(/\\/g, '/');
|
|
65
|
+
if (path.isAbsolute(target)) {
|
|
66
|
+
target = path.relative(repoRoot, path.resolve(target)).replace(/\\/g, '/');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Directory → walk it for *.test.js files.
|
|
70
|
+
const absTarget = path.resolve(repoRoot, target);
|
|
71
|
+
if (fsLike.existsSync(absTarget)) {
|
|
72
|
+
const stat = fsLike.statSync(absTarget);
|
|
73
|
+
if (stat.isDirectory()) {
|
|
74
|
+
return walkTestFiles(absTarget, fsLike)
|
|
75
|
+
.map((rel) =>
|
|
76
|
+
path
|
|
77
|
+
.relative(repoRoot, path.join(absTarget, rel))
|
|
78
|
+
.replace(/\\/g, '/'),
|
|
79
|
+
)
|
|
80
|
+
.filter((f) => f.endsWith('.test.js'));
|
|
81
|
+
}
|
|
82
|
+
if (stat.isFile() && target.endsWith('.test.js')) {
|
|
83
|
+
return [target];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Glob → filter the universe.
|
|
88
|
+
const isMatch = picomatch(target, { dot: true });
|
|
89
|
+
return discoverAll().filter((f) => isMatch(f));
|
|
90
|
+
}
|