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,854 @@
|
|
|
1
|
+
// lib/cli/update.js
|
|
2
|
+
/**
|
|
3
|
+
* `mandrel update` subcommand — the auto-update orchestrator (f-update-command,
|
|
4
|
+
* Story #3503, Epic #3437 — Auto-Update & Version Lifecycle).
|
|
5
|
+
*
|
|
6
|
+
* Advances `mandrel` to the newest **non-major** published version,
|
|
7
|
+
* re-materializes `.agents/`, runs applicable version-keyed migrations,
|
|
8
|
+
* surfaces the target changelog, and verifies the result via the doctor
|
|
9
|
+
* registry. A **major** crossing (e.g. `1.x → 2.0`) is gated: the orchestrator
|
|
10
|
+
* refuses to apply it without `--major`, prints a pointer to
|
|
11
|
+
* `docs/upgrade-major.md`, and exits non-zero without touching anything.
|
|
12
|
+
*
|
|
13
|
+
* ## Ordered cycle (happy path, non-major bump)
|
|
14
|
+
*
|
|
15
|
+
* 1. resolve target version (newest published) and the current version
|
|
16
|
+
* 2. **major gate** — decline + non-zero exit when the target crosses a
|
|
17
|
+
* major boundary and `--major` is absent
|
|
18
|
+
* 3. no-op short-circuit — already on the newest version ⇒ nothing to do
|
|
19
|
+
* 4. install — bump the dependency (lockfile bump left STAGED).
|
|
20
|
+
* The package manager is auto-detected from the lockfile in the project
|
|
21
|
+
* root: `pnpm-lock.yaml` ⇒ `pnpm add -D …` (with `-w` at a
|
|
22
|
+
* `pnpm-workspace.yaml` root), `yarn.lock` ⇒ `yarn add -D …`, otherwise
|
|
23
|
+
* `npm install …`. An explicit `--install-cmd "<pm> <args>"` overrides
|
|
24
|
+
* detection; a `{target}` placeholder in the override is substituted with
|
|
25
|
+
* the resolved version so an override can still consume the auto-probed
|
|
26
|
+
* newest. The registry probe in step 1 always stays on `npm view` (a
|
|
27
|
+
* PM-agnostic registry query).
|
|
28
|
+
* 5. runSync — re-materialize ./.agents/ from the new payload
|
|
29
|
+
* 6. runMigrations — apply version-keyed steps for the crossed range
|
|
30
|
+
* 7. doctor — run the check registry; success ⇒ all checks pass
|
|
31
|
+
* 8. surface the changelog for the target version
|
|
32
|
+
*
|
|
33
|
+
* ## No git mutation
|
|
34
|
+
*
|
|
35
|
+
* The npm dependency bump rewrites `package.json` / `package-lock.json` in the
|
|
36
|
+
* working tree but the orchestrator performs **no** `git add` / `git commit`:
|
|
37
|
+
* the lockfile bump is left staged-on-disk for the operator to review and
|
|
38
|
+
* commit. This module never shells out to git.
|
|
39
|
+
*
|
|
40
|
+
* ## `--dry-run`
|
|
41
|
+
*
|
|
42
|
+
* Prints the resolved target version and the ordered step plan, then returns
|
|
43
|
+
* without invoking any effectful seam (no npm update, no sync, no migrations,
|
|
44
|
+
* no doctor) and writing nothing.
|
|
45
|
+
*
|
|
46
|
+
* ## Major gate
|
|
47
|
+
*
|
|
48
|
+
* The project sits on the **1.x** line under release-please
|
|
49
|
+
* `always-bump-minor` ([AGENTS.md § Major-version policy]); a major release is
|
|
50
|
+
* a deliberate manual operator decision, so adopting one must be equally
|
|
51
|
+
* deliberate. When the newest version's major exceeds the current major:
|
|
52
|
+
* - **without `--major`**: print the available version + the
|
|
53
|
+
* `docs/upgrade-major.md` runbook pointer, exit non-zero, and invoke
|
|
54
|
+
* **no** npm-update / sync / migration / doctor seam.
|
|
55
|
+
* - **with `--major`**: apply the major target and print the runbook inline.
|
|
56
|
+
* Routine minor/patch bumps within the 1.x line are never gated.
|
|
57
|
+
*
|
|
58
|
+
* ## Injectable seams (used by lib/cli/__tests__/update*.test.js)
|
|
59
|
+
*
|
|
60
|
+
* - `argv` — subcommand args (after `mandrel update`)
|
|
61
|
+
* - `currentVersion` — the installed `mandrel` version string
|
|
62
|
+
* - `resolveTargetVersion`— async, returns the newest published version
|
|
63
|
+
* - `npmUpdate` — async, performs the dependency bump (no git);
|
|
64
|
+
* receives `(target, { installCmd })`
|
|
65
|
+
* - `runSync` — re-materializes ./.agents/ (lib/cli/sync.js)
|
|
66
|
+
* - `runMigrations` — version-keyed migration runner (lib/migrations)
|
|
67
|
+
* - `runDoctor` — async, returns { ok, results } from the registry
|
|
68
|
+
* - `surfaceChangelog` — emits the target changelog section
|
|
69
|
+
* - `write` / `writeErr` — stdout / stderr sinks
|
|
70
|
+
* - `exit` — process.exit replacement
|
|
71
|
+
*
|
|
72
|
+
* Security (security-baseline § 5 — Data Leakage & Logging): logs only version
|
|
73
|
+
* strings, step names, and the runbook path. No tokens, credentials, or env
|
|
74
|
+
* values are read or logged; no shell-string interpolation occurs here (the
|
|
75
|
+
* npm bump is delegated to the injected `npmUpdate` seam, which owns transport).
|
|
76
|
+
*
|
|
77
|
+
* ## Windows spawn (CVE-2024-27980)
|
|
78
|
+
*
|
|
79
|
+
* Both child-process boundaries — the `npm view` registry probe and the
|
|
80
|
+
* install — route through helpers that pass `shell: process.platform ===
|
|
81
|
+
* 'win32'`. On Windows `npm`/`pnpm`/`yarn` resolve to `.cmd` shims, and
|
|
82
|
+
* Node 18.20+/20.12+/22+/24 refuses to spawn `.cmd`/`.bat` with `shell:false`
|
|
83
|
+
* (the CVE-2024-27980 hardening), throwing `spawnSync npm ENOENT`. The win32
|
|
84
|
+
* shell flag is the documented fix. It is injection-safe because every argv
|
|
85
|
+
* here is a **fixed vector**: the probe argv is the constant package name, and
|
|
86
|
+
* the install argv is a tokenized list whose only variable segment is a
|
|
87
|
+
* resolved semver string — see `lib/install-cmd-parser.js` for the shared
|
|
88
|
+
* tokenize-and-spawn rationale this module reuses (no duplicated workaround).
|
|
89
|
+
*/
|
|
90
|
+
|
|
91
|
+
import { spawnSync } from 'node:child_process';
|
|
92
|
+
import nodeFs from 'node:fs';
|
|
93
|
+
import path from 'node:path';
|
|
94
|
+
import { fileURLToPath } from 'node:url';
|
|
95
|
+
|
|
96
|
+
import { runInstallCommand } from '../../.agents/scripts/lib/install-cmd-parser.js';
|
|
97
|
+
import { runMigrations as defaultRunMigrations } from '../migrations/index.js';
|
|
98
|
+
import { registry } from './registry.js';
|
|
99
|
+
import { runSync as defaultRunSync } from './sync.js';
|
|
100
|
+
import { isStale } from './version-check.js';
|
|
101
|
+
|
|
102
|
+
/** Path (relative to project root) of the major-upgrade runbook. */
|
|
103
|
+
const RUNBOOK_PATH = 'docs/upgrade-major.md';
|
|
104
|
+
|
|
105
|
+
/** The published package whose newest version `mandrel update` advances to. */
|
|
106
|
+
const PACKAGE_NAME = 'mandrel';
|
|
107
|
+
|
|
108
|
+
/** Default freshness-cache filename — mirrors version-check.js. */
|
|
109
|
+
const DEFAULT_CACHE_FILENAME = 'version-check.json';
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Parse a dotted semver-ish string into a numeric tuple. Non-numeric or
|
|
113
|
+
* missing segments coerce to 0 so a partial version still compares sanely.
|
|
114
|
+
*
|
|
115
|
+
* @param {string} version
|
|
116
|
+
* @returns {[number, number, number]}
|
|
117
|
+
*/
|
|
118
|
+
function parseVersion(version) {
|
|
119
|
+
const [major, minor, patch] = String(version).split('.');
|
|
120
|
+
return [
|
|
121
|
+
Number.parseInt(major, 10) || 0,
|
|
122
|
+
Number.parseInt(minor, 10) || 0,
|
|
123
|
+
Number.parseInt(patch, 10) || 0,
|
|
124
|
+
];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Compare two version strings. Negative when `a < b`, zero when equal,
|
|
129
|
+
* positive when `a > b` (the standard `Array.sort` comparator contract).
|
|
130
|
+
*
|
|
131
|
+
* @param {string} a
|
|
132
|
+
* @param {string} b
|
|
133
|
+
* @returns {number}
|
|
134
|
+
*/
|
|
135
|
+
function compareVersions(a, b) {
|
|
136
|
+
const pa = parseVersion(a);
|
|
137
|
+
const pb = parseVersion(b);
|
|
138
|
+
for (let i = 0; i < 3; i += 1) {
|
|
139
|
+
if (pa[i] !== pb[i]) return pa[i] - pb[i];
|
|
140
|
+
}
|
|
141
|
+
return 0;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* True when `target`'s major axis is strictly greater than `current`'s — the
|
|
146
|
+
* gated "crosses a major boundary" condition.
|
|
147
|
+
*
|
|
148
|
+
* @param {string} current
|
|
149
|
+
* @param {string} target
|
|
150
|
+
* @returns {boolean}
|
|
151
|
+
*/
|
|
152
|
+
function crossesMajor(current, target) {
|
|
153
|
+
return parseVersion(target)[0] > parseVersion(current)[0];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Resolve the installed `mandrel` version from this package's own
|
|
158
|
+
* `package.json`. The module lives at `<root>/lib/cli/update.js`, so the
|
|
159
|
+
* manifest is two directories up.
|
|
160
|
+
*
|
|
161
|
+
* @param {typeof nodeFs} [fs]
|
|
162
|
+
* @returns {string}
|
|
163
|
+
*/
|
|
164
|
+
function defaultCurrentVersion(fs = nodeFs) {
|
|
165
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
166
|
+
const manifestPath = path.resolve(here, '..', '..', 'package.json');
|
|
167
|
+
const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
168
|
+
return String(parsed.version);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Resolve the project root — the directory two levels up from this module
|
|
173
|
+
* (`<root>/lib/cli/update.js`). Mirrors `lib/cli/registry.js#resolveProjectRoot`.
|
|
174
|
+
*
|
|
175
|
+
* @returns {string}
|
|
176
|
+
*/
|
|
177
|
+
function resolveProjectRoot() {
|
|
178
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
179
|
+
return path.resolve(here, '..', '..');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Default `resolveTargetVersion` seam: determine the newest published
|
|
184
|
+
* `mandrel` version via the daily freshness cache (`version-check.js`).
|
|
185
|
+
*
|
|
186
|
+
* This delegates to `isStale`, which honours the 24h-cache semantics: a fresh
|
|
187
|
+
* cache returns the cached version with **zero** network I/O, while a missing,
|
|
188
|
+
* corrupt, or stale cache triggers exactly one network probe (`npm view
|
|
189
|
+
* mandrel version`) and refreshes `temp/version-check.json`. Wiring the
|
|
190
|
+
* production update path through `isStale` is precisely what populates that
|
|
191
|
+
* daily cache, which the `version-current` doctor advisory reads.
|
|
192
|
+
*
|
|
193
|
+
* The network probe shells `npm view` through `spawnSync` with a fixed argument
|
|
194
|
+
* vector (no shell-string interpolation; the package name is a constant). On
|
|
195
|
+
* Windows the spawn sets `shell: true` so the `npm.cmd` shim resolves under the
|
|
196
|
+
* CVE-2024-27980 hardening (mirrors `lib/install-cmd-parser.js`); the fixed
|
|
197
|
+
* argv carries no injection risk even with the shell flag set
|
|
198
|
+
* (security-baseline § Output & Rendering).
|
|
199
|
+
*
|
|
200
|
+
* @param {{
|
|
201
|
+
* cachePath?: string,
|
|
202
|
+
* fs?: typeof nodeFs,
|
|
203
|
+
* runner?: () => string,
|
|
204
|
+
* now?: Date,
|
|
205
|
+
* log?: (msg: string) => void,
|
|
206
|
+
* }} [opts]
|
|
207
|
+
* @returns {Promise<string>} The newest published version string.
|
|
208
|
+
*/
|
|
209
|
+
async function defaultResolveTargetVersion({
|
|
210
|
+
cachePath = path.join(resolveProjectRoot(), 'temp', DEFAULT_CACHE_FILENAME),
|
|
211
|
+
fs = nodeFs,
|
|
212
|
+
runner = defaultVersionRunner,
|
|
213
|
+
now = new Date(),
|
|
214
|
+
log = () => {},
|
|
215
|
+
} = {}) {
|
|
216
|
+
const result = await isStale({ cachePath, now, runner, fs, log });
|
|
217
|
+
return String(result.latestVersion);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Default network `runner` for the freshness probe: shells
|
|
222
|
+
* `npm view mandrel version` synchronously and returns the trimmed
|
|
223
|
+
* stdout. Fixed argv (the package name is a constant), and `shell:true` only on
|
|
224
|
+
* Windows so the `npm.cmd` shim resolves under CVE-2024-27980 — the fixed
|
|
225
|
+
* vector keeps it injection-safe with or without the shell flag.
|
|
226
|
+
*
|
|
227
|
+
* @param {{ spawnSync?: typeof spawnSync }} [deps] — test seam for the spawn
|
|
228
|
+
* boundary; defaults to the real `node:child_process` spawnSync.
|
|
229
|
+
* @returns {string} The newest published version string.
|
|
230
|
+
*/
|
|
231
|
+
export function defaultVersionRunner({ spawnSync: spawn = spawnSync } = {}) {
|
|
232
|
+
const r = spawn('npm', ['view', PACKAGE_NAME, 'version'], {
|
|
233
|
+
encoding: 'utf8',
|
|
234
|
+
shell: process.platform === 'win32',
|
|
235
|
+
});
|
|
236
|
+
if (r.error) {
|
|
237
|
+
throw new Error(
|
|
238
|
+
`mandrel update: failed to probe newest ${PACKAGE_NAME} version: ${r.error.message}`,
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
if (r.status !== 0) {
|
|
242
|
+
const snippet = (r.stderr || r.stdout || '').trim().slice(0, 200);
|
|
243
|
+
throw new Error(
|
|
244
|
+
`mandrel update: \`npm view ${PACKAGE_NAME} version\` exited ${r.status}: ${snippet}`,
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
const version = String(r.stdout || '').trim();
|
|
248
|
+
if (!version) {
|
|
249
|
+
throw new Error(
|
|
250
|
+
`mandrel update: \`npm view ${PACKAGE_NAME} version\` returned no version`,
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
return version;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Map a detected package manager to the command that re-runs a full install.
|
|
258
|
+
* Surfaced in the repair hint when an install fails so the operator can restore
|
|
259
|
+
* `node_modules` to a consistent state (Story #3575 AC-4).
|
|
260
|
+
*
|
|
261
|
+
* @param {'pnpm' | 'yarn' | 'npm'} packageManager
|
|
262
|
+
* @returns {string}
|
|
263
|
+
*/
|
|
264
|
+
function repairInstallCommand(packageManager) {
|
|
265
|
+
if (packageManager === 'pnpm') return 'pnpm install';
|
|
266
|
+
if (packageManager === 'yarn') return 'yarn install';
|
|
267
|
+
return 'npm install';
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Detect the project's package manager by probing for a lockfile in `cwd`.
|
|
272
|
+
* Precedence mirrors the ecosystem norm: a `pnpm-lock.yaml` wins over a
|
|
273
|
+
* `yarn.lock`, which wins over the npm default. `workspaceRoot` is true only
|
|
274
|
+
* for pnpm when a `pnpm-workspace.yaml` sits alongside the lockfile — the
|
|
275
|
+
* signal that `pnpm add` must carry `-w` to target the workspace-root manifest.
|
|
276
|
+
*
|
|
277
|
+
* Running the wrong package manager (e.g. `npm install` in a pnpm workspace) is
|
|
278
|
+
* the root cause this resolves (Story #3575): npm chokes on the pnpm-managed
|
|
279
|
+
* tree, exits non-zero, and can flip `node_modules` to a stale store entry.
|
|
280
|
+
* Detecting the lockfile keeps the bump on the operator's real package manager
|
|
281
|
+
* so the change lands in the matching lockfile.
|
|
282
|
+
*
|
|
283
|
+
* @param {string} [cwd] - Project root to probe (default `process.cwd()`).
|
|
284
|
+
* @param {typeof nodeFs} [fs]
|
|
285
|
+
* @returns {{ packageManager: 'pnpm' | 'yarn' | 'npm', workspaceRoot: boolean }}
|
|
286
|
+
*/
|
|
287
|
+
export function detectPackageManager(cwd = process.cwd(), fs = nodeFs) {
|
|
288
|
+
const has = (file) => {
|
|
289
|
+
try {
|
|
290
|
+
return fs.existsSync(path.join(cwd, file));
|
|
291
|
+
} catch {
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
if (has('pnpm-lock.yaml')) {
|
|
296
|
+
return {
|
|
297
|
+
packageManager: 'pnpm',
|
|
298
|
+
workspaceRoot: has('pnpm-workspace.yaml'),
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
if (has('yarn.lock')) {
|
|
302
|
+
return { packageManager: 'yarn', workspaceRoot: false };
|
|
303
|
+
}
|
|
304
|
+
return { packageManager: 'npm', workspaceRoot: false };
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Resolve the install command string `defaultNpmUpdate` runs.
|
|
309
|
+
*
|
|
310
|
+
* With no override the command is built from the detected package manager:
|
|
311
|
+
* - `pnpm` ⇒ `pnpm add -D mandrel@<target>` (plus ` -w` at a pnpm
|
|
312
|
+
* workspace root)
|
|
313
|
+
* - `yarn` ⇒ `yarn add -D mandrel@<target>`
|
|
314
|
+
* - `npm` ⇒ `npm install mandrel@<target>` (the unchanged default)
|
|
315
|
+
*
|
|
316
|
+
* An explicit `--install-cmd` override is used verbatim, except that a
|
|
317
|
+
* `{target}` placeholder is substituted with the resolved semver so an override
|
|
318
|
+
* can still consume the auto-probed newest version (Story #3575 AC-3).
|
|
319
|
+
*
|
|
320
|
+
* This function is pure: package-manager detection happens in
|
|
321
|
+
* `detectPackageManager` (the only filesystem seam) and is passed in as
|
|
322
|
+
* `detected`, keeping the command-string assembly trivially unit-testable.
|
|
323
|
+
*
|
|
324
|
+
* @param {string} target - The resolved semver to install.
|
|
325
|
+
* @param {string} [override] - Operator-supplied `--install-cmd` value.
|
|
326
|
+
* @param {{
|
|
327
|
+
* packageManager?: 'pnpm' | 'yarn' | 'npm',
|
|
328
|
+
* workspaceRoot?: boolean,
|
|
329
|
+
* }} [detected]
|
|
330
|
+
* @returns {string}
|
|
331
|
+
*/
|
|
332
|
+
export function resolveInstallCmd(
|
|
333
|
+
target,
|
|
334
|
+
override,
|
|
335
|
+
{ packageManager = 'npm', workspaceRoot = false } = {},
|
|
336
|
+
) {
|
|
337
|
+
const trimmed = String(override ?? '').trim();
|
|
338
|
+
if (trimmed.length > 0) {
|
|
339
|
+
return trimmed.includes('{target}')
|
|
340
|
+
? trimmed.replaceAll('{target}', target)
|
|
341
|
+
: trimmed;
|
|
342
|
+
}
|
|
343
|
+
if (packageManager === 'pnpm') {
|
|
344
|
+
return `pnpm add -D ${PACKAGE_NAME}@${target}${workspaceRoot ? ' -w' : ''}`;
|
|
345
|
+
}
|
|
346
|
+
if (packageManager === 'yarn') {
|
|
347
|
+
return `yarn add -D ${PACKAGE_NAME}@${target}`;
|
|
348
|
+
}
|
|
349
|
+
return `npm install ${PACKAGE_NAME}@${target}`;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Default `npmUpdate` seam: install the resolved target version. The install
|
|
354
|
+
* rewrites `package.json` / the lockfile on disk (left staged for the
|
|
355
|
+
* operator); this performs no git mutation.
|
|
356
|
+
*
|
|
357
|
+
* The package manager is auto-detected from `cwd`'s lockfile (Story #3575) so
|
|
358
|
+
* the bump lands in the operator's real lockfile rather than running
|
|
359
|
+
* `npm install` against a pnpm/yarn-managed tree. The install routes through
|
|
360
|
+
* the shared `runInstallCommand` helper from `lib/install-cmd-parser.js`, which
|
|
361
|
+
* tokenizes the command and spawns with `shell: process.platform === 'win32'`
|
|
362
|
+
* so the Windows `.cmd` shim resolves under CVE-2024-27980 — the win32 shell
|
|
363
|
+
* handling and tokenization are reused, not re-implemented here. The resolved
|
|
364
|
+
* argv is a fixed vector; an `--install-cmd` override is tokenized and escaped
|
|
365
|
+
* per-arg by the parser even when the win32 shell flag is required.
|
|
366
|
+
*
|
|
367
|
+
* On any install failure the thrown error names the detected package manager's
|
|
368
|
+
* own `install` command so the operator can restore `node_modules` to a
|
|
369
|
+
* consistent state — `mandrel update` never silently leaves a half-mutated
|
|
370
|
+
* tree (Story #3575 AC-4).
|
|
371
|
+
*
|
|
372
|
+
* @param {string} target - The version to install.
|
|
373
|
+
* @param {{
|
|
374
|
+
* installCmd?: string,
|
|
375
|
+
* runInstall?: typeof runInstallCommand,
|
|
376
|
+
* cwd?: string,
|
|
377
|
+
* fs?: typeof nodeFs,
|
|
378
|
+
* }} [opts]
|
|
379
|
+
* @returns {void}
|
|
380
|
+
*/
|
|
381
|
+
export function defaultNpmUpdate(
|
|
382
|
+
target,
|
|
383
|
+
{
|
|
384
|
+
installCmd,
|
|
385
|
+
runInstall = runInstallCommand,
|
|
386
|
+
cwd = process.cwd(),
|
|
387
|
+
fs = nodeFs,
|
|
388
|
+
} = {},
|
|
389
|
+
) {
|
|
390
|
+
const detected = detectPackageManager(cwd, fs);
|
|
391
|
+
const cmd = resolveInstallCmd(target, installCmd, detected);
|
|
392
|
+
const repairHint =
|
|
393
|
+
`\n → If node_modules looks wrong, run \`${repairInstallCommand(detected.packageManager)}\`` +
|
|
394
|
+
' to restore it to a consistent state.';
|
|
395
|
+
let r;
|
|
396
|
+
try {
|
|
397
|
+
r = runInstall(cmd, cwd);
|
|
398
|
+
} catch (err) {
|
|
399
|
+
throw new Error(
|
|
400
|
+
`mandrel update: install command \`${cmd}\` failed to spawn: ${err.message}${repairHint}`,
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
if (r.status !== 0) {
|
|
404
|
+
const snippet = (r.stderr || '').trim().slice(0, 200);
|
|
405
|
+
throw new Error(
|
|
406
|
+
`mandrel update: install command \`${cmd}\` exited ${r.status}: ${snippet}${repairHint}`,
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Default `surfaceChangelog` seam: print the `docs/CHANGELOG.md` section(s)
|
|
413
|
+
* covering the applied version range `(current, target]`. The changelog is
|
|
414
|
+
* authored by release-please with `## [<version>](…)` section headers; this
|
|
415
|
+
* prints every section whose version is newer than `current` and no newer than
|
|
416
|
+
* `target`.
|
|
417
|
+
*
|
|
418
|
+
* Degrades gracefully (warns, never throws) when the file is absent or no
|
|
419
|
+
* matching section is found — surfacing the changelog is best-effort and must
|
|
420
|
+
* never fail an otherwise-successful upgrade.
|
|
421
|
+
*
|
|
422
|
+
* @param {string} target - The applied target version.
|
|
423
|
+
* @param {{
|
|
424
|
+
* current?: string,
|
|
425
|
+
* changelogPath?: string,
|
|
426
|
+
* fs?: typeof nodeFs,
|
|
427
|
+
* write?: (s: string) => void,
|
|
428
|
+
* writeErr?: (s: string) => void,
|
|
429
|
+
* }} [opts]
|
|
430
|
+
* @returns {void}
|
|
431
|
+
*/
|
|
432
|
+
function defaultSurfaceChangelog(
|
|
433
|
+
target,
|
|
434
|
+
{
|
|
435
|
+
current,
|
|
436
|
+
changelogPath = path.join(resolveProjectRoot(), 'docs', 'CHANGELOG.md'),
|
|
437
|
+
fs = nodeFs,
|
|
438
|
+
write = (s) => process.stdout.write(s),
|
|
439
|
+
writeErr = (s) => process.stderr.write(s),
|
|
440
|
+
} = {},
|
|
441
|
+
) {
|
|
442
|
+
let raw;
|
|
443
|
+
try {
|
|
444
|
+
raw = fs.readFileSync(changelogPath, 'utf8');
|
|
445
|
+
} catch {
|
|
446
|
+
writeErr(
|
|
447
|
+
`mandrel update: changelog not found at ${changelogPath} — skipping changelog surface.\n`,
|
|
448
|
+
);
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const sections = parseChangelogSections(raw);
|
|
453
|
+
const relevant = sections.filter((s) => {
|
|
454
|
+
const aboveFloor = current ? compareVersions(s.version, current) > 0 : true;
|
|
455
|
+
const atOrBelowTarget = compareVersions(s.version, target) <= 0;
|
|
456
|
+
return aboveFloor && atOrBelowTarget;
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
if (relevant.length === 0) {
|
|
460
|
+
writeErr(
|
|
461
|
+
`mandrel update: no CHANGELOG section found for v${target} — skipping changelog surface.\n`,
|
|
462
|
+
);
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
write(`\nChangelog for v${target}:\n`);
|
|
467
|
+
for (const section of relevant) {
|
|
468
|
+
write(`${section.body.trimEnd()}\n`);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Split a release-please `CHANGELOG.md` into `{ version, body }` sections keyed
|
|
474
|
+
* by the `## [<version>]…` headers. Each `body` includes the header line and
|
|
475
|
+
* everything up to (but not including) the next version header.
|
|
476
|
+
*
|
|
477
|
+
* @param {string} raw
|
|
478
|
+
* @returns {Array<{ version: string, body: string }>}
|
|
479
|
+
*/
|
|
480
|
+
function parseChangelogSections(raw) {
|
|
481
|
+
const lines = String(raw).split('\n');
|
|
482
|
+
const headerRe = /^## \[(\d+\.\d+\.\d+)\]/;
|
|
483
|
+
const sections = [];
|
|
484
|
+
let curVersion = null;
|
|
485
|
+
let curLines = [];
|
|
486
|
+
|
|
487
|
+
const flush = () => {
|
|
488
|
+
if (curVersion) {
|
|
489
|
+
sections.push({ version: curVersion, body: curLines.join('\n') });
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
for (const line of lines) {
|
|
494
|
+
const m = headerRe.exec(line);
|
|
495
|
+
if (m) {
|
|
496
|
+
flush();
|
|
497
|
+
curVersion = m[1];
|
|
498
|
+
curLines = [line];
|
|
499
|
+
} else if (curVersion) {
|
|
500
|
+
curLines.push(line);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
flush();
|
|
504
|
+
return sections;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Default doctor seam: run every check in the registry sequentially and
|
|
509
|
+
* report whether all passed. Mirrors lib/cli/doctor.js's pass accounting
|
|
510
|
+
* without the formatted report (the orchestrator owns its own output).
|
|
511
|
+
*
|
|
512
|
+
* @param {{ checks?: typeof registry }} [opts]
|
|
513
|
+
* @returns {Promise<{ ok: boolean, results: Array<{ name: string, ok: boolean }> }>}
|
|
514
|
+
*/
|
|
515
|
+
async function defaultRunDoctor({ checks = registry } = {}) {
|
|
516
|
+
const results = [];
|
|
517
|
+
for (const check of checks) {
|
|
518
|
+
const r = await check.run();
|
|
519
|
+
results.push({ name: check.name, ok: Boolean(r.ok) });
|
|
520
|
+
}
|
|
521
|
+
return { ok: results.every((r) => r.ok), results };
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* The ordered step names the orchestrator drives on a non-major bump. Shared
|
|
526
|
+
* by the live path and the `--dry-run` plan printout so the two never drift.
|
|
527
|
+
*/
|
|
528
|
+
const STEP_PLAN = ['npm-update', 'runSync', 'runMigrations', 'doctor'];
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Extract the `--install-cmd "<cmd>"` value from the subcommand argv. Accepts
|
|
532
|
+
* both the space form (`--install-cmd npm install …`, captured as the single
|
|
533
|
+
* following token group) and the `=` form (`--install-cmd="<cmd>"`). Returns
|
|
534
|
+
* `undefined` when the flag is absent so the default package manager is used.
|
|
535
|
+
*
|
|
536
|
+
* The argv tokenizer hands us a pre-split array; with the space form the shell
|
|
537
|
+
* has already collapsed a quoted value into one element, so the immediate next
|
|
538
|
+
* token is the full command string.
|
|
539
|
+
*
|
|
540
|
+
* @param {string[]} argv
|
|
541
|
+
* @returns {string | undefined}
|
|
542
|
+
*/
|
|
543
|
+
function parseInstallCmdFlag(argv) {
|
|
544
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
545
|
+
const arg = argv[i];
|
|
546
|
+
if (arg === '--install-cmd') {
|
|
547
|
+
return argv[i + 1];
|
|
548
|
+
}
|
|
549
|
+
if (arg.startsWith('--install-cmd=')) {
|
|
550
|
+
return arg.slice('--install-cmd='.length);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return undefined;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* Print the major-gate refusal: the available version, the runbook pointer,
|
|
558
|
+
* and the re-run hint. No effectful seam runs after this.
|
|
559
|
+
*
|
|
560
|
+
* @param {string} target
|
|
561
|
+
* @param {(s: string) => void} writeErr
|
|
562
|
+
*/
|
|
563
|
+
function emitMajorRefusal(target, writeErr) {
|
|
564
|
+
writeErr(
|
|
565
|
+
`mandrel update: a newer MAJOR version (${target}) is available; ` +
|
|
566
|
+
'this is a breaking upgrade.\n' +
|
|
567
|
+
` → Review ${RUNBOOK_PATH}, then re-run with --major to apply it.\n`,
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Run the `mandrel update` orchestration cycle.
|
|
573
|
+
*
|
|
574
|
+
* @param {{
|
|
575
|
+
* argv?: string[],
|
|
576
|
+
* currentVersion?: string | (() => string),
|
|
577
|
+
* resolveTargetVersion?: () => (string | Promise<string>),
|
|
578
|
+
* npmUpdate?: (version: string, opts: { installCmd?: string }) => unknown | Promise<unknown>,
|
|
579
|
+
* runSync?: typeof defaultRunSync,
|
|
580
|
+
* runMigrations?: typeof defaultRunMigrations,
|
|
581
|
+
* runDoctor?: typeof defaultRunDoctor,
|
|
582
|
+
* surfaceChangelog?: (version: string) => unknown | Promise<unknown>,
|
|
583
|
+
* write?: (s: string) => void,
|
|
584
|
+
* writeErr?: (s: string) => void,
|
|
585
|
+
* exit?: (code: number) => void,
|
|
586
|
+
* }} [opts]
|
|
587
|
+
* @returns {Promise<{
|
|
588
|
+
* ok: boolean,
|
|
589
|
+
* action: 'updated' | 'declined-major' | 'dry-run' | 'up-to-date' | 'doctor-failed',
|
|
590
|
+
* currentVersion: string,
|
|
591
|
+
* targetVersion: string | null,
|
|
592
|
+
* major: boolean,
|
|
593
|
+
* stepsRun: string[],
|
|
594
|
+
* dryRun: boolean,
|
|
595
|
+
* }>}
|
|
596
|
+
*/
|
|
597
|
+
export async function runUpdate({
|
|
598
|
+
argv = [],
|
|
599
|
+
currentVersion,
|
|
600
|
+
resolveTargetVersion,
|
|
601
|
+
npmUpdate,
|
|
602
|
+
runSync = defaultRunSync,
|
|
603
|
+
runMigrations = defaultRunMigrations,
|
|
604
|
+
runDoctor = defaultRunDoctor,
|
|
605
|
+
surfaceChangelog,
|
|
606
|
+
write = (s) => process.stdout.write(s),
|
|
607
|
+
writeErr = (s) => process.stderr.write(s),
|
|
608
|
+
exit = (code) => process.exit(code),
|
|
609
|
+
} = {}) {
|
|
610
|
+
const dryRun = argv.includes('--dry-run');
|
|
611
|
+
const allowMajor = argv.includes('--major');
|
|
612
|
+
const installCmd = parseInstallCmdFlag(argv);
|
|
613
|
+
|
|
614
|
+
const current =
|
|
615
|
+
typeof currentVersion === 'function'
|
|
616
|
+
? currentVersion()
|
|
617
|
+
: (currentVersion ?? defaultCurrentVersion());
|
|
618
|
+
|
|
619
|
+
if (typeof resolveTargetVersion !== 'function') {
|
|
620
|
+
throw new Error(
|
|
621
|
+
'mandrel update: resolveTargetVersion seam is required to determine the newest version',
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
const target = String(await resolveTargetVersion());
|
|
625
|
+
|
|
626
|
+
const major = crossesMajor(current, target);
|
|
627
|
+
|
|
628
|
+
// --- Major gate -----------------------------------------------------------
|
|
629
|
+
// A major crossing without --major is refused outright: no npm-update, no
|
|
630
|
+
// sync, no migration, no doctor — print the runbook pointer and exit non-zero.
|
|
631
|
+
if (major && !allowMajor) {
|
|
632
|
+
emitMajorRefusal(target, writeErr);
|
|
633
|
+
exit(1);
|
|
634
|
+
return {
|
|
635
|
+
ok: false,
|
|
636
|
+
action: 'declined-major',
|
|
637
|
+
currentVersion: current,
|
|
638
|
+
targetVersion: target,
|
|
639
|
+
major: true,
|
|
640
|
+
stepsRun: [],
|
|
641
|
+
dryRun,
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
// --- No-op short-circuit --------------------------------------------------
|
|
646
|
+
// Already on (or ahead of) the newest version: nothing to apply.
|
|
647
|
+
if (compareVersions(target, current) <= 0) {
|
|
648
|
+
write(`✅ Already up to date (v${current} is the newest version).\n`);
|
|
649
|
+
return {
|
|
650
|
+
ok: true,
|
|
651
|
+
action: 'up-to-date',
|
|
652
|
+
currentVersion: current,
|
|
653
|
+
targetVersion: target,
|
|
654
|
+
major,
|
|
655
|
+
stepsRun: [],
|
|
656
|
+
dryRun,
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// --- Dry run --------------------------------------------------------------
|
|
661
|
+
// Print the resolved target and the ordered step plan; invoke no seam and
|
|
662
|
+
// write nothing to disk.
|
|
663
|
+
if (dryRun) {
|
|
664
|
+
write(`mandrel update — planned upgrade v${current} → v${target}\n`);
|
|
665
|
+
if (major) {
|
|
666
|
+
write(' (major upgrade — --major supplied)\n');
|
|
667
|
+
}
|
|
668
|
+
STEP_PLAN.forEach((step, i) => {
|
|
669
|
+
write(` ${i + 1}. ${step}\n`);
|
|
670
|
+
});
|
|
671
|
+
write(' 5. surface changelog\n');
|
|
672
|
+
write('Dry run: no files written, no dependency bumped.\n');
|
|
673
|
+
return {
|
|
674
|
+
ok: true,
|
|
675
|
+
action: 'dry-run',
|
|
676
|
+
currentVersion: current,
|
|
677
|
+
targetVersion: target,
|
|
678
|
+
major,
|
|
679
|
+
stepsRun: [],
|
|
680
|
+
dryRun: true,
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// --- Major runbook (inline, when --major applies) -------------------------
|
|
685
|
+
if (major) {
|
|
686
|
+
write(
|
|
687
|
+
`Applying MAJOR upgrade v${current} → v${target} (--major). ` +
|
|
688
|
+
`Review the runbook: ${RUNBOOK_PATH}\n`,
|
|
689
|
+
);
|
|
690
|
+
} else {
|
|
691
|
+
write(`Updating v${current} → v${target}…\n`);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
const stepsRun = [];
|
|
695
|
+
|
|
696
|
+
// 1. npm update — bump the dependency. The lockfile change is left STAGED
|
|
697
|
+
// on disk; this module never commits.
|
|
698
|
+
if (typeof npmUpdate !== 'function') {
|
|
699
|
+
throw new Error(
|
|
700
|
+
'mandrel update: npmUpdate seam is required to bump the dependency',
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
await npmUpdate(target, { installCmd });
|
|
704
|
+
stepsRun.push('npm-update');
|
|
705
|
+
|
|
706
|
+
// 2. runSync — re-materialize ./.agents/ from the freshly installed payload.
|
|
707
|
+
runSync({ argv: [] });
|
|
708
|
+
stepsRun.push('runSync');
|
|
709
|
+
|
|
710
|
+
// 3. runMigrations — apply version-keyed steps for the crossed range.
|
|
711
|
+
runMigrations({ fromVersion: current, toVersion: target, ctx: {} });
|
|
712
|
+
stepsRun.push('runMigrations');
|
|
713
|
+
|
|
714
|
+
// 4. doctor — verify the resulting install.
|
|
715
|
+
const doctor = await runDoctor();
|
|
716
|
+
stepsRun.push('doctor');
|
|
717
|
+
|
|
718
|
+
// 5. surface the target changelog (best-effort; optional seam).
|
|
719
|
+
if (typeof surfaceChangelog === 'function') {
|
|
720
|
+
await surfaceChangelog(target);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
if (!doctor.ok) {
|
|
724
|
+
const failed = doctor.results.filter((r) => !r.ok).map((r) => r.name);
|
|
725
|
+
writeErr(
|
|
726
|
+
`mandrel update: upgraded to v${target} but doctor reported failures: ` +
|
|
727
|
+
`${failed.join(', ')}\n` +
|
|
728
|
+
' → Run `mandrel doctor` for remedies.\n',
|
|
729
|
+
);
|
|
730
|
+
exit(1);
|
|
731
|
+
return {
|
|
732
|
+
ok: false,
|
|
733
|
+
action: 'doctor-failed',
|
|
734
|
+
currentVersion: current,
|
|
735
|
+
targetVersion: target,
|
|
736
|
+
major,
|
|
737
|
+
stepsRun,
|
|
738
|
+
dryRun: false,
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
write(`✅ Updated to v${target}. The lockfile bump is staged for review.\n`);
|
|
743
|
+
return {
|
|
744
|
+
ok: true,
|
|
745
|
+
action: 'updated',
|
|
746
|
+
currentVersion: current,
|
|
747
|
+
targetVersion: target,
|
|
748
|
+
major,
|
|
749
|
+
stepsRun,
|
|
750
|
+
dryRun: false,
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Default export consumed by `bin/mandrel.js`.
|
|
756
|
+
*
|
|
757
|
+
* Wires the production-default seams that `runUpdate` leaves injectable:
|
|
758
|
+
* - `resolveTargetVersion` probes the newest published `mandrel`
|
|
759
|
+
* version through the daily freshness cache (`version-check.js#isStale`),
|
|
760
|
+
* which ALSO populates `temp/version-check.json` — the cache the
|
|
761
|
+
* `version-current` doctor advisory reads.
|
|
762
|
+
* - `npmUpdate` runs the install command — auto-detected from the project
|
|
763
|
+
* lockfile (`pnpm`/`yarn`/`npm`), or the `--install-cmd` override —
|
|
764
|
+
* through the shared `runInstallCommand` helper — no git mutation;
|
|
765
|
+
* lockfile left staged.
|
|
766
|
+
* - `surfaceChangelog` prints the relevant `docs/CHANGELOG.md` section(s)
|
|
767
|
+
* for the applied range, degrading gracefully when the file is absent.
|
|
768
|
+
*
|
|
769
|
+
* Every seam stays injectable on `runUpdate`; these are merely the
|
|
770
|
+
* no-seam-provided fallbacks, so the existing seam-driven tests stay green.
|
|
771
|
+
* `--major` / `--dry-run` / `--install-cmd` are parsed from `argv` by
|
|
772
|
+
* `runUpdate` itself.
|
|
773
|
+
*
|
|
774
|
+
* The second `deps` argument exposes the **process boundaries** the production
|
|
775
|
+
* defaults shell out across (`versionRunner` = `npm view`, `runInstall` =
|
|
776
|
+
* the install spawn) plus `fs` / `cachePath` / `now`, so the entrypoint can be
|
|
777
|
+
* driven end-to-end with the network/npm boundary stubbed and no real I/O.
|
|
778
|
+
* `bin/mandrel.js` calls `run(argv)` with no `deps`, getting the production
|
|
779
|
+
* wiring; tests pass fakes. The `deps` surface is NOT part of the public
|
|
780
|
+
* subcommand contract — `bin/mandrel.js` only ever supplies `argv`.
|
|
781
|
+
*
|
|
782
|
+
* @param {string[]} argv - Subcommand arguments (after `mandrel update`).
|
|
783
|
+
* @param {{
|
|
784
|
+
* currentVersion?: string,
|
|
785
|
+
* cachePath?: string,
|
|
786
|
+
* fs?: typeof nodeFs,
|
|
787
|
+
* now?: Date,
|
|
788
|
+
* versionRunner?: () => string,
|
|
789
|
+
* runInstall?: (installCmd: string, cwd: string) => { status: number, stderr: string },
|
|
790
|
+
* changelogPath?: string,
|
|
791
|
+
* runUpdate?: typeof runUpdate,
|
|
792
|
+
* runSync?: typeof defaultRunSync,
|
|
793
|
+
* runMigrations?: typeof defaultRunMigrations,
|
|
794
|
+
* runDoctor?: typeof defaultRunDoctor,
|
|
795
|
+
* write?: (s: string) => void,
|
|
796
|
+
* writeErr?: (s: string) => void,
|
|
797
|
+
* exit?: (code: number) => void,
|
|
798
|
+
* log?: (msg: string) => void,
|
|
799
|
+
* }} [deps]
|
|
800
|
+
* @returns {Promise<void>}
|
|
801
|
+
*/
|
|
802
|
+
export default async function run(argv = [], deps = {}) {
|
|
803
|
+
const {
|
|
804
|
+
fs = nodeFs,
|
|
805
|
+
cachePath,
|
|
806
|
+
now,
|
|
807
|
+
versionRunner,
|
|
808
|
+
runInstall,
|
|
809
|
+
changelogPath,
|
|
810
|
+
runUpdate: runUpdateImpl = runUpdate,
|
|
811
|
+
runSync,
|
|
812
|
+
runMigrations,
|
|
813
|
+
runDoctor,
|
|
814
|
+
write,
|
|
815
|
+
writeErr,
|
|
816
|
+
exit,
|
|
817
|
+
log,
|
|
818
|
+
} = deps;
|
|
819
|
+
|
|
820
|
+
const current = deps.currentVersion ?? defaultCurrentVersion(fs);
|
|
821
|
+
|
|
822
|
+
await runUpdateImpl({
|
|
823
|
+
argv,
|
|
824
|
+
currentVersion: current,
|
|
825
|
+
resolveTargetVersion: () =>
|
|
826
|
+
defaultResolveTargetVersion({
|
|
827
|
+
...(cachePath ? { cachePath } : {}),
|
|
828
|
+
fs,
|
|
829
|
+
...(versionRunner ? { runner: versionRunner } : {}),
|
|
830
|
+
...(now ? { now } : {}),
|
|
831
|
+
...(log ? { log } : {}),
|
|
832
|
+
}),
|
|
833
|
+
npmUpdate: (target, { installCmd } = {}) =>
|
|
834
|
+
defaultNpmUpdate(target, {
|
|
835
|
+
...(installCmd ? { installCmd } : {}),
|
|
836
|
+
...(runInstall ? { runInstall } : {}),
|
|
837
|
+
fs,
|
|
838
|
+
}),
|
|
839
|
+
surfaceChangelog: (target) =>
|
|
840
|
+
defaultSurfaceChangelog(target, {
|
|
841
|
+
current,
|
|
842
|
+
fs,
|
|
843
|
+
...(changelogPath ? { changelogPath } : {}),
|
|
844
|
+
...(write ? { write } : {}),
|
|
845
|
+
...(writeErr ? { writeErr } : {}),
|
|
846
|
+
}),
|
|
847
|
+
...(runSync ? { runSync } : {}),
|
|
848
|
+
...(runMigrations ? { runMigrations } : {}),
|
|
849
|
+
...(runDoctor ? { runDoctor } : {}),
|
|
850
|
+
...(write ? { write } : {}),
|
|
851
|
+
...(writeErr ? { writeErr } : {}),
|
|
852
|
+
...(exit ? { exit } : {}),
|
|
853
|
+
});
|
|
854
|
+
}
|