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,291 @@
|
|
|
1
|
+
// .agents/scripts/lib/baselines/scope.js
|
|
2
|
+
//
|
|
3
|
+
// Story #1962 / Task #1970 — One ScopeResolution helper that the
|
|
4
|
+
// `check-baselines.js` dispatcher and the per-kind regression writers
|
|
5
|
+
// (Epic #1943) both consume. Routing every scope decision through this
|
|
6
|
+
// single function is what guarantees read/write parity: the dispatcher
|
|
7
|
+
// can never decide "diff against epic/1943" while the writer assumes
|
|
8
|
+
// "full repo", because both call `resolveScope()` with the same inputs.
|
|
9
|
+
//
|
|
10
|
+
// The resolver is intentionally pure — it takes already-extracted
|
|
11
|
+
// inputs and returns a frozen ScopeResolution. CLI parsing, env
|
|
12
|
+
// reading, and config loading happen in the caller; that keeps this
|
|
13
|
+
// module trivially testable and prevents the precedence rules from
|
|
14
|
+
// being silently re-implemented at every call site.
|
|
15
|
+
//
|
|
16
|
+
// Precedence (highest → lowest):
|
|
17
|
+
//
|
|
18
|
+
// 1. CLI flags — `cliFlags.fullScope: true` or `cliFlags.changedSinceRef`.
|
|
19
|
+
// Operator-typed beats anything in env/config. A CLI override of
|
|
20
|
+
// `--full-scope` wins even if the config says `'diff'`.
|
|
21
|
+
// 2. Environment — `BASELINE_SCOPE` ('full' | 'diff') and
|
|
22
|
+
// `BASELINE_REF` (any git ref). The dispatcher reads these from
|
|
23
|
+
// `process.env` and forwards via `cliFlags.envScope` /
|
|
24
|
+
// `cliFlags.envRef` so the resolver itself never touches process
|
|
25
|
+
// state. CI usually sets these.
|
|
26
|
+
// 3. Config — `configScope` ('full' | 'diff') and `configRef` (any
|
|
27
|
+
// git ref) from `delivery.quality.gateScoping` in `.agentrc.json`.
|
|
28
|
+
// 4. Default — `mode='diff'` against `ref='main'`. This is the
|
|
29
|
+
// framework-wide fallback when nothing else is configured.
|
|
30
|
+
//
|
|
31
|
+
// Missing-ref fallback: when the resolved mode is `'diff'` but no ref
|
|
32
|
+
// is supplied at any layer, the resolver falls back to `'main'` rather
|
|
33
|
+
// than producing a half-resolved scope with `ref=null`. The dispatcher
|
|
34
|
+
// would have to invent a default anyway; centralising it here keeps
|
|
35
|
+
// every gate aligned.
|
|
36
|
+
//
|
|
37
|
+
// `kind` (e.g. `'lint'`, `'coverage'`, `'crap'`) is currently echoed
|
|
38
|
+
// through to the resolution unchanged. The argument exists so future
|
|
39
|
+
// per-kind overrides (e.g. "lint always runs full") have a place to
|
|
40
|
+
// land without breaking call signatures. Today: pass it; ignore it.
|
|
41
|
+
//
|
|
42
|
+
// Returned shape:
|
|
43
|
+
//
|
|
44
|
+
// {
|
|
45
|
+
// kind: string, // echoed back for caller convenience
|
|
46
|
+
// mode: 'full' | 'diff',
|
|
47
|
+
// ref: string | null, // null in full mode; ref string in diff mode
|
|
48
|
+
// files: Set<string>, // empty Set in full mode (sentinel for "all")
|
|
49
|
+
// source: string, // which layer won (debug / friction signal)
|
|
50
|
+
// }
|
|
51
|
+
//
|
|
52
|
+
// `files` is intentionally a Set rather than an Array — callers
|
|
53
|
+
// repeatedly check membership during per-row filtering, and Set lookup
|
|
54
|
+
// is O(1). An empty Set in `'full'` mode means "no filter applies".
|
|
55
|
+
// A non-empty Set in `'diff'` mode means "only these paths are in
|
|
56
|
+
// scope" (the dispatcher pre-computes them via `git diff --name-only`
|
|
57
|
+
// and forwards via `cliFlags.changedFiles`); when omitted, the writer
|
|
58
|
+
// is expected to compute the diff itself against `ref`.
|
|
59
|
+
|
|
60
|
+
const VALID_MODES = new Set(['full', 'diff']);
|
|
61
|
+
const DEFAULT_DIFF_REF = 'main';
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Coerce a candidate value to a non-empty string, or `null`.
|
|
65
|
+
*
|
|
66
|
+
* @param {unknown} v
|
|
67
|
+
* @returns {string | null}
|
|
68
|
+
*/
|
|
69
|
+
function asNonEmptyString(v) {
|
|
70
|
+
return typeof v === 'string' && v.length > 0 ? v : null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Coerce a candidate scope value to one of the canonical modes, or
|
|
75
|
+
* `null` if it is not a recognised mode. Unknown strings are dropped
|
|
76
|
+
* rather than coerced — the layer "did not specify" rather than
|
|
77
|
+
* "specified an invalid value".
|
|
78
|
+
*
|
|
79
|
+
* @param {unknown} v
|
|
80
|
+
* @returns {'full' | 'diff' | null}
|
|
81
|
+
*/
|
|
82
|
+
function asMode(v) {
|
|
83
|
+
return typeof v === 'string' && VALID_MODES.has(v) ? v : null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Coerce a candidate set/array of files to a frozen Set. Returns an
|
|
88
|
+
* empty Set when the input is missing or empty.
|
|
89
|
+
*
|
|
90
|
+
* @param {unknown} v
|
|
91
|
+
* @returns {Set<string>}
|
|
92
|
+
*/
|
|
93
|
+
function asFilesSet(v) {
|
|
94
|
+
if (v instanceof Set) {
|
|
95
|
+
return new Set(
|
|
96
|
+
Array.from(v).filter((f) => typeof f === 'string' && f.length > 0),
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
if (Array.isArray(v)) {
|
|
100
|
+
return new Set(v.filter((f) => typeof f === 'string' && f.length > 0));
|
|
101
|
+
}
|
|
102
|
+
return new Set();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Resolve a scope against the layered precedence (CLI > env > config >
|
|
107
|
+
* default). Pure; no I/O.
|
|
108
|
+
*
|
|
109
|
+
* @param {object} input
|
|
110
|
+
* @param {string} input.kind - Baseline kind (e.g. `'lint'`).
|
|
111
|
+
* @param {string} [input.configScope] - `'full'` | `'diff'` from agentrc.
|
|
112
|
+
* @param {string} [input.configRef] - Diff ref from agentrc.
|
|
113
|
+
* @param {object} [input.cliFlags] - Pre-parsed CLI / env layer.
|
|
114
|
+
* @param {boolean} [input.cliFlags.fullScope] - `--full-scope`.
|
|
115
|
+
* @param {string} [input.cliFlags.changedSinceRef] - `--changed-since <ref>`.
|
|
116
|
+
* @param {string} [input.cliFlags.envScope] - From `BASELINE_SCOPE`.
|
|
117
|
+
* @param {string} [input.cliFlags.envRef] - From `BASELINE_REF`.
|
|
118
|
+
* @param {Iterable<string>} [input.cliFlags.changedFiles]
|
|
119
|
+
* Pre-computed diff paths (when caller already ran `git diff
|
|
120
|
+
* --name-only`). Becomes `files`; only meaningful in `'diff'` mode.
|
|
121
|
+
* @returns {{
|
|
122
|
+
* kind: string,
|
|
123
|
+
* mode: 'full' | 'diff',
|
|
124
|
+
* ref: string | null,
|
|
125
|
+
* files: Set<string>,
|
|
126
|
+
* source: string,
|
|
127
|
+
* }}
|
|
128
|
+
*/
|
|
129
|
+
export function resolveScope(input = {}) {
|
|
130
|
+
const kind =
|
|
131
|
+
typeof input.kind === 'string' && input.kind.length > 0
|
|
132
|
+
? input.kind
|
|
133
|
+
: 'unknown';
|
|
134
|
+
const cli = input.cliFlags ?? {};
|
|
135
|
+
|
|
136
|
+
// ---- Layer 1: CLI flags (highest precedence) -------------------------
|
|
137
|
+
if (cli.fullScope === true) {
|
|
138
|
+
return Object.freeze({
|
|
139
|
+
kind,
|
|
140
|
+
mode: 'full',
|
|
141
|
+
ref: null,
|
|
142
|
+
files: new Set(),
|
|
143
|
+
source: 'cli:--full-scope',
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
const cliRef = asNonEmptyString(cli.changedSinceRef);
|
|
147
|
+
if (cliRef) {
|
|
148
|
+
return Object.freeze({
|
|
149
|
+
kind,
|
|
150
|
+
mode: 'diff',
|
|
151
|
+
ref: cliRef,
|
|
152
|
+
files: asFilesSet(cli.changedFiles),
|
|
153
|
+
source: 'cli:--changed-since',
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ---- Layer 2: Environment (extracted by caller into cliFlags.env*) ---
|
|
158
|
+
const envMode = asMode(cli.envScope);
|
|
159
|
+
if (envMode === 'full') {
|
|
160
|
+
return Object.freeze({
|
|
161
|
+
kind,
|
|
162
|
+
mode: 'full',
|
|
163
|
+
ref: null,
|
|
164
|
+
files: new Set(),
|
|
165
|
+
source: 'env:BASELINE_SCOPE=full',
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
const envRef = asNonEmptyString(cli.envRef);
|
|
169
|
+
if (envMode === 'diff' || envRef) {
|
|
170
|
+
return Object.freeze({
|
|
171
|
+
kind,
|
|
172
|
+
mode: 'diff',
|
|
173
|
+
ref: envRef ?? DEFAULT_DIFF_REF,
|
|
174
|
+
files: asFilesSet(cli.changedFiles),
|
|
175
|
+
source: envRef ? 'env:BASELINE_REF' : 'env:BASELINE_SCOPE=diff',
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// ---- Layer 3: Config (delivery.quality.gateScoping) -----------------
|
|
180
|
+
const cfgMode = asMode(input.configScope);
|
|
181
|
+
if (cfgMode === 'full') {
|
|
182
|
+
return Object.freeze({
|
|
183
|
+
kind,
|
|
184
|
+
mode: 'full',
|
|
185
|
+
ref: null,
|
|
186
|
+
files: new Set(),
|
|
187
|
+
source: 'config:gateScoping.scope=full',
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
const cfgRef = asNonEmptyString(input.configRef);
|
|
191
|
+
if (cfgMode === 'diff' || cfgRef) {
|
|
192
|
+
return Object.freeze({
|
|
193
|
+
kind,
|
|
194
|
+
mode: 'diff',
|
|
195
|
+
ref: cfgRef ?? DEFAULT_DIFF_REF,
|
|
196
|
+
files: asFilesSet(cli.changedFiles),
|
|
197
|
+
source: cfgRef
|
|
198
|
+
? 'config:gateScoping.diffRef'
|
|
199
|
+
: 'config:gateScoping.scope=diff',
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// ---- Layer 4: Default ------------------------------------------------
|
|
204
|
+
return Object.freeze({
|
|
205
|
+
kind,
|
|
206
|
+
mode: 'diff',
|
|
207
|
+
ref: DEFAULT_DIFF_REF,
|
|
208
|
+
files: asFilesSet(cli.changedFiles),
|
|
209
|
+
source: 'default',
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Generic scope-aware row merge for s-diff-scoped-writes (Story #1974).
|
|
215
|
+
*
|
|
216
|
+
* Each per-kind module re-exports a thin wrapper that pins `scopeKey` to
|
|
217
|
+
* the field used to identify the file the row belongs to (path / route /
|
|
218
|
+
* bundle). This helper does the actual merge:
|
|
219
|
+
*
|
|
220
|
+
* - `scope.mode === 'full'` (or `scope` is null/undefined / `scope.files`
|
|
221
|
+
* is empty): regenerated wins everywhere — returned as-is. This keeps
|
|
222
|
+
* the legacy "always rewrite" behaviour intact when no scope filter is
|
|
223
|
+
* applied.
|
|
224
|
+
* - `scope.mode === 'diff'`: rows whose `scopeKey` value is OUTSIDE
|
|
225
|
+
* `scope.files` are preserved from `prior` verbatim. Rows whose
|
|
226
|
+
* `scopeKey` value is INSIDE `scope.files` are taken from
|
|
227
|
+
* `regenerated` (the regenerated values for in-scope files). Prior
|
|
228
|
+
* rows for in-scope files are dropped (regen replaces them); regen
|
|
229
|
+
* rows for out-of-scope files are dropped (the writer should not have
|
|
230
|
+
* computed them, but we filter defensively).
|
|
231
|
+
* - Missing `prior` (null / undefined / empty) — regenerated wins
|
|
232
|
+
* everywhere; behaves like full mode.
|
|
233
|
+
*
|
|
234
|
+
* Identity matching uses the per-kind `identity(row)` function — for
|
|
235
|
+
* coverage / lint / maintainability / mutation / lighthouse / bundle-size
|
|
236
|
+
* the identity is the keyField value; for crap it's a composite
|
|
237
|
+
* `path::method@startLine`. The merge preserves row ordering by
|
|
238
|
+
* concatenating in-scope regen rows then out-of-scope prior rows; the
|
|
239
|
+
* downstream `sortRows` from the per-kind module re-sorts before write.
|
|
240
|
+
*
|
|
241
|
+
* Pure. No I/O.
|
|
242
|
+
*
|
|
243
|
+
* @template TRow
|
|
244
|
+
* @param {object} args
|
|
245
|
+
* @param {Array<TRow>|null|undefined} args.prior
|
|
246
|
+
* @param {Array<TRow>|null|undefined} args.regenerated
|
|
247
|
+
* @param {{mode?: 'full'|'diff', files?: Set<string>|Iterable<string>}|null|undefined} args.scope
|
|
248
|
+
* @param {(row: TRow) => string} args.scopeKey Per-kind scope-key extractor — returns the
|
|
249
|
+
* file path / route / bundle name used to match against `scope.files`.
|
|
250
|
+
* @param {(row: TRow) => string} [args.identity] Per-kind identity extractor — defaults to
|
|
251
|
+
* the same as `scopeKey`. CRAP overrides this with `path::method@startLine`.
|
|
252
|
+
* @returns {Array<TRow>}
|
|
253
|
+
*/
|
|
254
|
+
export function mergeRowsByScope({
|
|
255
|
+
prior,
|
|
256
|
+
regenerated,
|
|
257
|
+
scope,
|
|
258
|
+
scopeKey,
|
|
259
|
+
identity,
|
|
260
|
+
} = {}) {
|
|
261
|
+
const regenRows = Array.isArray(regenerated) ? regenerated : [];
|
|
262
|
+
const priorRows = Array.isArray(prior) ? prior : [];
|
|
263
|
+
if (typeof scopeKey !== 'function') {
|
|
264
|
+
throw new TypeError('mergeRowsByScope: scopeKey must be a function');
|
|
265
|
+
}
|
|
266
|
+
const idFn = typeof identity === 'function' ? identity : scopeKey;
|
|
267
|
+
|
|
268
|
+
// No scope filter / full mode / no prior → regen wins everywhere.
|
|
269
|
+
const mode = scope?.mode;
|
|
270
|
+
if (!scope || mode === 'full' || priorRows.length === 0) {
|
|
271
|
+
return regenRows.slice();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Coerce scope.files to a Set for O(1) membership tests. An empty Set in
|
|
275
|
+
// diff mode means "no files in scope" — every prior row is preserved
|
|
276
|
+
// and every regen row is dropped (defensive: writer feeds in-scope rows).
|
|
277
|
+
const filesSet =
|
|
278
|
+
scope.files instanceof Set ? scope.files : new Set(scope.files ?? []);
|
|
279
|
+
|
|
280
|
+
// In-scope regen rows: keep regen.
|
|
281
|
+
const regenInScope = regenRows.filter((row) => filesSet.has(scopeKey(row)));
|
|
282
|
+
// Out-of-scope prior rows: keep prior, but drop any whose identity
|
|
283
|
+
// collides with an in-scope regen row (defensive — should not happen
|
|
284
|
+
// since identity within a kind is keyField-derived).
|
|
285
|
+
const inScopeIds = new Set(regenInScope.map((row) => idFn(row)));
|
|
286
|
+
const priorOutOfScope = priorRows.filter(
|
|
287
|
+
(row) => !filesSet.has(scopeKey(row)) && !inScopeIds.has(idFn(row)),
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
return regenInScope.concat(priorOutOfScope);
|
|
291
|
+
}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* writer.js — shared baseline writer (Story #1891, Epic #1786).
|
|
3
|
+
*
|
|
4
|
+
* Every legacy baseline-refresh script (`update-crap-baseline.js`,
|
|
5
|
+
* `update-maintainability-baseline.js`, `lib/coverage-baseline.js`,
|
|
6
|
+
* `lib/auto-refresh-baselines.js`) used to assemble its own envelope and
|
|
7
|
+
* call `fs.writeFileSync`. That meant the path canonicalisation, rollup
|
|
8
|
+
* math, kernel-version stamping, and JSON-serialisation conventions were
|
|
9
|
+
* duplicated five-ish times, each with subtly different rules. The
|
|
10
|
+
* worktree-prefix bug that prompted Story #1891 is the proof: each
|
|
11
|
+
* refresh path had to remember to strip `.worktrees/<workspace>/` on its
|
|
12
|
+
* own, and the maintainability path forgot.
|
|
13
|
+
*
|
|
14
|
+
* `write({ kind, rows, components, kernelVersion?, generatedAt? })` is
|
|
15
|
+
* the single funnel:
|
|
16
|
+
*
|
|
17
|
+
* 1. Look up the per-kind module via the kernel registry. The module
|
|
18
|
+
* declares the `keyField`, `projectRow`, `sortRows`, `rollup`, and
|
|
19
|
+
* `kernelVersion()` functions.
|
|
20
|
+
* 2. Run every row through `projectRow` — that's where the path is
|
|
21
|
+
* canonicalised via `path-canon.canonicalise()`. After projection,
|
|
22
|
+
* the writer asserts every key field is already canonical
|
|
23
|
+
* (`path-canon.assertCanonical()`), refusing to silently rewrite
|
|
24
|
+
* identity.
|
|
25
|
+
* 3. Sort the rows for deterministic on-disk diffs.
|
|
26
|
+
* 4. Compute the per-component rollup (always including `*`).
|
|
27
|
+
* 5. Stamp the envelope via `buildEnvelope` — `$schema`, `kernelVersion`,
|
|
28
|
+
* `generatedAt`.
|
|
29
|
+
* 6. Validate the envelope via `assertEnvelope` (AJV against the per-kind
|
|
30
|
+
* schema).
|
|
31
|
+
* 7. Return the envelope object. Callers serialise via `writeFile()`
|
|
32
|
+
* (separate seam so tests can round-trip without touching disk).
|
|
33
|
+
*
|
|
34
|
+
* `writeFile(absPath, envelope)` is the serialise + flush seam. It
|
|
35
|
+
* stringifies the envelope with two-space indent, appends a trailing
|
|
36
|
+
* newline, creates the parent directory, and writes atomically (write to
|
|
37
|
+
* `<path>.tmp` then `rename` — `rename` is atomic on every platform we
|
|
38
|
+
* support).
|
|
39
|
+
*
|
|
40
|
+
* @module lib/baselines/writer
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
import fs from 'node:fs';
|
|
44
|
+
import path from 'node:path';
|
|
45
|
+
import { deepEqual } from '../json-utils.js';
|
|
46
|
+
import { assertEnvelope, buildEnvelope } from './envelope.js';
|
|
47
|
+
import { currentKernelVersion, getKindModule } from './kernel.js';
|
|
48
|
+
import { assertCanonical } from './path-canon.js';
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Assemble + validate a baseline envelope. Returns the envelope object
|
|
52
|
+
* (no disk I/O). Callers feed the result into `writeFile()` when they're
|
|
53
|
+
* ready to persist.
|
|
54
|
+
*
|
|
55
|
+
* Story #1964 (s-stability-epsilon) added the optional `prior` and
|
|
56
|
+
* `epsilon` parameters. When both are present, the writer calls the
|
|
57
|
+
* per-kind `applyEpsilon(prior, regenerated, epsilon)` stabilizer
|
|
58
|
+
* **after** projection but **before** sort/rollup/serialise. Sub-epsilon
|
|
59
|
+
* row deltas resolve to the prior bytes, so env variance never rewrites
|
|
60
|
+
* the on-disk envelope. When either is absent (`undefined`), behaviour is
|
|
61
|
+
* unchanged from the pre-#1964 contract — this is regression-fail-safe by
|
|
62
|
+
* design so existing call sites stay untouched.
|
|
63
|
+
*
|
|
64
|
+
* Story #1974 (s-diff-scoped-writes) added the optional `scope` parameter.
|
|
65
|
+
* When `scope` is present *and* `prior` is supplied, the writer calls the
|
|
66
|
+
* per-kind `mergeRows(prior, projected, scope)` filter **after** projection
|
|
67
|
+
* but **before** `applyEpsilon`. The composition is intentional: scope-
|
|
68
|
+
* filter first (preserve out-of-scope prior rows verbatim), then stabilise
|
|
69
|
+
* the in-scope rows against the same prior under epsilon. The merged result
|
|
70
|
+
* is sorted, rolled up, and serialised exactly as before. When `scope` is
|
|
71
|
+
* absent (or `prior` is absent), behaviour is unchanged from the pre-#1974
|
|
72
|
+
* contract — also regression-fail-safe.
|
|
73
|
+
*
|
|
74
|
+
* `prior` MUST be an array of rows already in canonical (per-kind
|
|
75
|
+
* `projectRow`) shape — the on-disk baseline format is canonical
|
|
76
|
+
* end-to-end, and the writer no longer re-projects prior rows on entry.
|
|
77
|
+
*
|
|
78
|
+
* Story #2135 (Task #2146) added the structural-equality short-circuit on
|
|
79
|
+
* top of `prior`. When a `prior` envelope (or `priorEnvelope`) is supplied
|
|
80
|
+
* and the projected `rows + rollup` deep-equal the prior's `rows + rollup`,
|
|
81
|
+
* the writer returns the prior envelope unchanged — same `generatedAt`,
|
|
82
|
+
* same kernelVersion, same byte payload. Without this guard every
|
|
83
|
+
* auto-refresh that ran on a no-op Story would stamp a fresh
|
|
84
|
+
* `generatedAt` and surface a spurious one-line diff. The short-circuit
|
|
85
|
+
* is the semantic replacement for the legacy byte-equality compare that
|
|
86
|
+
* lived in `baseline-snapshot.js`.
|
|
87
|
+
*
|
|
88
|
+
* @param {{
|
|
89
|
+
* kind: string,
|
|
90
|
+
* rows: Array<object>,
|
|
91
|
+
* components?: Array<object>,
|
|
92
|
+
* kernelVersion?: string,
|
|
93
|
+
* generatedAt?: string,
|
|
94
|
+
* prior?: Array<object>,
|
|
95
|
+
* priorEnvelope?: object,
|
|
96
|
+
* epsilon?: number,
|
|
97
|
+
* scope?: {mode: 'full'|'diff', files: Set<string>|Iterable<string>}|null,
|
|
98
|
+
* }} params
|
|
99
|
+
* @returns {object}
|
|
100
|
+
*/
|
|
101
|
+
export function write({
|
|
102
|
+
kind,
|
|
103
|
+
rows,
|
|
104
|
+
components,
|
|
105
|
+
kernelVersion,
|
|
106
|
+
generatedAt,
|
|
107
|
+
prior,
|
|
108
|
+
priorEnvelope,
|
|
109
|
+
epsilon,
|
|
110
|
+
scope,
|
|
111
|
+
} = {}) {
|
|
112
|
+
if (typeof kind !== 'string' || kind.length === 0) {
|
|
113
|
+
throw new TypeError('writer.write: kind is required');
|
|
114
|
+
}
|
|
115
|
+
if (!Array.isArray(rows)) {
|
|
116
|
+
throw new TypeError('writer.write: rows must be an array');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const mod = getKindModule(kind);
|
|
120
|
+
const projected = rows.map((row, idx) => {
|
|
121
|
+
try {
|
|
122
|
+
return mod.projectRow(row);
|
|
123
|
+
} catch (err) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
`writer.write: failed to project ${kind} row at index ${idx}: ${err.message}`,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Defensive: assert every key field on the projected rows is canonical.
|
|
131
|
+
// The per-kind `projectRow` already funnels paths through `canonicalise`,
|
|
132
|
+
// but the assertion catches a future per-kind module that forgets — and
|
|
133
|
+
// catches absolute paths in inputs that the canonicaliser would also
|
|
134
|
+
// throw on (we surface a writer-scoped error pointing at the row).
|
|
135
|
+
if (mod.keyField === 'path') {
|
|
136
|
+
projected.forEach((row, idx) => {
|
|
137
|
+
try {
|
|
138
|
+
assertCanonical(row.path);
|
|
139
|
+
} catch (err) {
|
|
140
|
+
throw new Error(
|
|
141
|
+
`writer.write: ${kind} row at index ${idx} has a non-canonical path: ${err.message}`,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const merged = scopeMergeRows(mod, projected, prior, scope);
|
|
148
|
+
const stabilised = stabiliseRows(mod, merged, prior, epsilon);
|
|
149
|
+
|
|
150
|
+
const sortedRows = mod.sortRows(stabilised);
|
|
151
|
+
const rollup = mod.rollup(sortedRows, components ?? []);
|
|
152
|
+
|
|
153
|
+
// The rollup() implementations always seed `*` from `aggregate()`, but
|
|
154
|
+
// the AC pins this explicitly: the envelope ALWAYS carries `*` even
|
|
155
|
+
// when `components` is undefined or empty. Belt-and-braces.
|
|
156
|
+
if (!Object.hasOwn(rollup, '*')) {
|
|
157
|
+
throw new Error(
|
|
158
|
+
`writer.write: ${kind} rollup is missing the required "*" key`,
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Story #2135 / Task #2146 — structural-equality short-circuit. When the
|
|
163
|
+
// caller supplies a `priorEnvelope` (or, for backwards-compatibility, the
|
|
164
|
+
// bare `prior` array is itself a full envelope object), and the projected
|
|
165
|
+
// rows + rollup deep-equal what's on the prior, return the prior envelope
|
|
166
|
+
// unchanged. This is the semantic replacement for the byte-equality
|
|
167
|
+
// compare in `baseline-snapshot.js` and is what makes a no-op auto-refresh
|
|
168
|
+
// produce a zero-byte baseline diff.
|
|
169
|
+
const priorEnv = resolvePriorEnvelope(priorEnvelope, prior);
|
|
170
|
+
if (
|
|
171
|
+
priorEnv &&
|
|
172
|
+
deepEqual(sortedRows, priorEnv.rows) &&
|
|
173
|
+
deepEqual(rollup, priorEnv.rollup)
|
|
174
|
+
) {
|
|
175
|
+
// Re-validate defensively before returning so a caller cannot smuggle
|
|
176
|
+
// an invalid envelope through the short-circuit.
|
|
177
|
+
assertEnvelope(priorEnv);
|
|
178
|
+
return priorEnv;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const envelope = buildEnvelope({
|
|
182
|
+
kind,
|
|
183
|
+
rows: sortedRows,
|
|
184
|
+
rollup,
|
|
185
|
+
kernelVersion: kernelVersion ?? currentKernelVersion(kind),
|
|
186
|
+
generatedAt,
|
|
187
|
+
});
|
|
188
|
+
assertEnvelope(envelope);
|
|
189
|
+
return envelope;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Resolve the prior envelope used by the structural-equality short-circuit.
|
|
194
|
+
* Accepts either an explicit `priorEnvelope` (preferred) or, for backwards
|
|
195
|
+
* compatibility, recognises when `prior` is itself a full envelope object
|
|
196
|
+
* carrying `rows` + `rollup` rather than a bare rows array. Returns null
|
|
197
|
+
* when neither yields a usable envelope — the short-circuit is opt-in by
|
|
198
|
+
* design.
|
|
199
|
+
*/
|
|
200
|
+
function resolvePriorEnvelope(priorEnvelope, prior) {
|
|
201
|
+
if (
|
|
202
|
+
priorEnvelope &&
|
|
203
|
+
typeof priorEnvelope === 'object' &&
|
|
204
|
+
!Array.isArray(priorEnvelope) &&
|
|
205
|
+
Array.isArray(priorEnvelope.rows) &&
|
|
206
|
+
priorEnvelope.rollup &&
|
|
207
|
+
typeof priorEnvelope.rollup === 'object'
|
|
208
|
+
) {
|
|
209
|
+
return priorEnvelope;
|
|
210
|
+
}
|
|
211
|
+
if (
|
|
212
|
+
prior &&
|
|
213
|
+
typeof prior === 'object' &&
|
|
214
|
+
!Array.isArray(prior) &&
|
|
215
|
+
Array.isArray(prior.rows) &&
|
|
216
|
+
prior.rollup &&
|
|
217
|
+
typeof prior.rollup === 'object'
|
|
218
|
+
) {
|
|
219
|
+
return prior;
|
|
220
|
+
}
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Serialise an envelope to `absPath`. Deterministic: two-space indent,
|
|
226
|
+
* trailing newline, sorted keys for the top-level envelope keys (rows are
|
|
227
|
+
* already sorted by the per-kind module's `sortRows`). Atomic: writes to
|
|
228
|
+
* `<absPath>.tmp` then `rename`s onto the destination so a crash mid-write
|
|
229
|
+
* never leaves a half-flushed envelope on disk.
|
|
230
|
+
*
|
|
231
|
+
* Story #2135 / Task #2146 — the optional `fsImpl` seam lets tests inject
|
|
232
|
+
* a virtual filesystem (or an in-memory recorder) the way the legacy
|
|
233
|
+
* saver helpers allowed. Production callers omit it and fall through to
|
|
234
|
+
* `node:fs`. The seam covers `mkdirSync`, `writeFileSync`, and
|
|
235
|
+
* `renameSync` — the three calls this function actually makes — so a mock
|
|
236
|
+
* that exposes a subset of `fs` works without leaking real disk I/O.
|
|
237
|
+
*
|
|
238
|
+
* Backwards-compatible: two-argument callers (`writeFile(abs, env)`)
|
|
239
|
+
* continue to work unchanged.
|
|
240
|
+
*
|
|
241
|
+
* @param {string} absPath
|
|
242
|
+
* @param {object} envelope
|
|
243
|
+
* @param {{ fsImpl?: { mkdirSync: typeof fs.mkdirSync, writeFileSync: typeof fs.writeFileSync, renameSync: typeof fs.renameSync } }} [opts]
|
|
244
|
+
* @returns {string} The absolute path written.
|
|
245
|
+
*/
|
|
246
|
+
export function writeFile(absPath, envelope, opts = {}) {
|
|
247
|
+
if (typeof absPath !== 'string' || !path.isAbsolute(absPath)) {
|
|
248
|
+
throw new TypeError(
|
|
249
|
+
`writer.writeFile: absPath must be an absolute path (got ${JSON.stringify(absPath)})`,
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
// Re-validate at the seam — a caller might mutate the envelope between
|
|
253
|
+
// `write()` and `writeFile()`.
|
|
254
|
+
assertEnvelope(envelope);
|
|
255
|
+
|
|
256
|
+
const fsImpl = opts?.fsImpl ? opts.fsImpl : fs;
|
|
257
|
+
|
|
258
|
+
// Canonical key order on the top-level envelope keeps diffs stable
|
|
259
|
+
// across runs and platforms. Per-kind row keys retain their natural
|
|
260
|
+
// declaration order; the row sort is done by `sortRows()`.
|
|
261
|
+
const canonical = {
|
|
262
|
+
$schema: envelope.$schema,
|
|
263
|
+
kernelVersion: envelope.kernelVersion,
|
|
264
|
+
generatedAt: envelope.generatedAt,
|
|
265
|
+
rollup: envelope.rollup,
|
|
266
|
+
rows: envelope.rows,
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const tmpPath = `${absPath}.tmp`;
|
|
270
|
+
fsImpl.mkdirSync(path.dirname(absPath), { recursive: true });
|
|
271
|
+
fsImpl.writeFileSync(tmpPath, `${JSON.stringify(canonical, null, 2)}\n`);
|
|
272
|
+
fsImpl.renameSync(tmpPath, absPath);
|
|
273
|
+
return absPath;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Story #1974 — s-diff-scoped-writes scope-merge dispatch. When `scope` is
|
|
278
|
+
* present, defer to the per-kind `mergeRows(prior, projected, scope)` to
|
|
279
|
+
* preserve out-of-scope prior rows verbatim. Returns `projected` unchanged
|
|
280
|
+
* when `scope` is omitted, when the kind doesn't ship the merger
|
|
281
|
+
* (forward-compatible), or when `prior` is absent (nothing to preserve).
|
|
282
|
+
*/
|
|
283
|
+
function scopeMergeRows(mod, projected, prior, scope) {
|
|
284
|
+
if (scope === undefined || scope === null) return projected;
|
|
285
|
+
if (typeof mod.mergeRows !== 'function') return projected;
|
|
286
|
+
// mergeRows treats null/undefined/empty prior as "no preservation needed"
|
|
287
|
+
// and returns projected verbatim — that branch is covered upstream and
|
|
288
|
+
// here for symmetry.
|
|
289
|
+
return mod.mergeRows(prior ?? [], projected, scope);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Story #1964 — s-stability-epsilon stabilizer dispatch. When both
|
|
294
|
+
* `prior` and `epsilon` are present, fold sub-epsilon row deltas back to
|
|
295
|
+
* the prior bytes via the per-kind `applyEpsilon`. Returns `projected`
|
|
296
|
+
* unchanged when either is omitted, or when the kind doesn't ship the
|
|
297
|
+
* stabilizer (forward-compatible).
|
|
298
|
+
*/
|
|
299
|
+
function stabiliseRows(mod, projected, prior, epsilon) {
|
|
300
|
+
if (prior === undefined || epsilon === undefined) return projected;
|
|
301
|
+
if (!Array.isArray(prior)) {
|
|
302
|
+
throw new TypeError('writer.write: prior must be an array when provided');
|
|
303
|
+
}
|
|
304
|
+
if (typeof epsilon !== 'number' || !Number.isFinite(epsilon) || epsilon < 0) {
|
|
305
|
+
throw new TypeError(
|
|
306
|
+
`writer.write: epsilon must be a non-negative finite number (got ${JSON.stringify(epsilon)})`,
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
return typeof mod.applyEpsilon === 'function'
|
|
310
|
+
? mod.applyEpsilon(prior, projected, epsilon)
|
|
311
|
+
: projected;
|
|
312
|
+
}
|