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,801 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bootstrap/project-bootstrap — deterministic port of the
|
|
3
|
+
* `/agents-bootstrap-project` workflow (Story #2074, hard cutover).
|
|
4
|
+
*
|
|
5
|
+
* Each exported `ensure*` function is one step of the bootstrap. Every step
|
|
6
|
+
* is idempotent and additive — re-running on an already-bootstrapped clone
|
|
7
|
+
* produces zero file mutations and zero network I/O.
|
|
8
|
+
*
|
|
9
|
+
* Injectable seams: every function that performs filesystem I/O or spawns a
|
|
10
|
+
* child process accepts an optional `fsImpl` / `spawnImpl` default-param so
|
|
11
|
+
* unit tests can stub I/O without touching the real filesystem. The seam
|
|
12
|
+
* contract is defined in `.agents/rules/test-seams.md`.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { spawnSync as defaultSpawnSync } from 'node:child_process';
|
|
16
|
+
import fs from 'node:fs';
|
|
17
|
+
import os from 'node:os';
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
import { LEDGER_RELATIVE_PATH } from './install-ledger.js';
|
|
20
|
+
import { PHASE_GROUPS, previewMutationManifest } from './manifest.js';
|
|
21
|
+
import { applyQualityBootstrap } from './quality-bootstrap.js';
|
|
22
|
+
|
|
23
|
+
export const SYNC_COMMAND = 'node .agents/scripts/sync-claude-commands.js';
|
|
24
|
+
|
|
25
|
+
export const BOOTSTRAP_COMMAND = 'node .agents/scripts/bootstrap.js';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Marker that identifies the framework's system-prompt import inside a
|
|
29
|
+
* consumer `CLAUDE.md`. The wiring step keys idempotence off this exact
|
|
30
|
+
* import path so a re-run never duplicates the import line.
|
|
31
|
+
*/
|
|
32
|
+
export const SYSTEM_PROMPT_IMPORT = '@.agents/instructions.md';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Import block appended to an existing `CLAUDE.md` that lacks the import.
|
|
36
|
+
* Mirrors the root `CLAUDE.md` shape (a `## System Prompt` heading above
|
|
37
|
+
* the import) so the consumer file reads the same as this repo's own.
|
|
38
|
+
*/
|
|
39
|
+
export const SYSTEM_PROMPT_BLOCK = `## System Prompt
|
|
40
|
+
|
|
41
|
+
${SYSTEM_PROMPT_IMPORT}
|
|
42
|
+
`;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Full `CLAUDE.md` body written when the consumer has no `CLAUDE.md` at
|
|
46
|
+
* all. A bare title plus the import block is enough for Claude Code to
|
|
47
|
+
* hydrate the framework system prompt on cold start.
|
|
48
|
+
*/
|
|
49
|
+
export const SYSTEM_PROMPT_CLAUDE_MD = `# Agent Protocols
|
|
50
|
+
|
|
51
|
+
${SYSTEM_PROMPT_BLOCK}`;
|
|
52
|
+
|
|
53
|
+
export const GITIGNORE_BLOCKS = Object.freeze({
|
|
54
|
+
commands: {
|
|
55
|
+
pattern: /^\s*\.claude\/commands\/?\s*$/m,
|
|
56
|
+
block:
|
|
57
|
+
'\n# Claude Code command projection is generated from .agents/workflows/ — do not commit.\n.claude/commands/\n',
|
|
58
|
+
},
|
|
59
|
+
mcp: {
|
|
60
|
+
pattern: /^\s*\.mcp\.json\s*$/m,
|
|
61
|
+
block:
|
|
62
|
+
'\n# Project-scoped MCP config carries secrets — keep out of git.\n.mcp.json\n',
|
|
63
|
+
},
|
|
64
|
+
// Story #3894: `.env` holds real secrets (`/onboard` instructs operators to
|
|
65
|
+
// put `GITHUB_TOKEN` here). It MUST be ignored by default so a cold-start
|
|
66
|
+
// provision never stages/pushes it. The pattern matches a bare `.env` (with
|
|
67
|
+
// an optional trailing slash) but deliberately NOT `.env.example`, the
|
|
68
|
+
// committed placeholder that `security-baseline.md` § Secrets Management
|
|
69
|
+
// exempts.
|
|
70
|
+
env: {
|
|
71
|
+
pattern: /^\s*\.env\/?\s*$/m,
|
|
72
|
+
block:
|
|
73
|
+
'\n# Secrets live in .env (e.g. GITHUB_TOKEN) — never commit it. Only .env.example (placeholders) is checked in.\n.env\n',
|
|
74
|
+
},
|
|
75
|
+
// Story #3894: the install ledger is a per-clone install record, not a
|
|
76
|
+
// checked-in source artifact. `install-ledger.js` documents that the
|
|
77
|
+
// bootstrap `.gitignore` step ignores it — key the entry off the exact
|
|
78
|
+
// `LEDGER_RELATIVE_PATH` constant so the doc and code never drift again.
|
|
79
|
+
installLedger: {
|
|
80
|
+
pattern: new RegExp(
|
|
81
|
+
`^\\s*${LEDGER_RELATIVE_PATH.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*$`,
|
|
82
|
+
'm',
|
|
83
|
+
),
|
|
84
|
+
block: `\n# Per-clone install record written by bootstrap — not a source artifact.\n${LEDGER_RELATIVE_PATH}\n`,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Read a JSON file if it exists; return null when missing. Accepts an
|
|
90
|
+
* injectable `fsImpl` so callers can stub filesystem access in tests.
|
|
91
|
+
*
|
|
92
|
+
* @param {string} p
|
|
93
|
+
* @param {typeof fs} [fsImpl]
|
|
94
|
+
* @returns {object|null}
|
|
95
|
+
*/
|
|
96
|
+
function readJsonIfExists(p, fsImpl = fs) {
|
|
97
|
+
if (!fsImpl.existsSync(p)) return null;
|
|
98
|
+
return JSON.parse(fsImpl.readFileSync(p, 'utf8'));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Write a pretty-printed JSON file, creating parent directories as needed.
|
|
103
|
+
* Accepts an injectable `fsImpl` so callers can stub filesystem access in
|
|
104
|
+
* tests.
|
|
105
|
+
*
|
|
106
|
+
* @param {string} p
|
|
107
|
+
* @param {object} obj
|
|
108
|
+
* @param {typeof fs} [fsImpl]
|
|
109
|
+
*/
|
|
110
|
+
function writeJson(p, obj, fsImpl = fs) {
|
|
111
|
+
fsImpl.mkdirSync(path.dirname(p), { recursive: true });
|
|
112
|
+
fsImpl.writeFileSync(p, `${JSON.stringify(obj, null, 2)}\n`, 'utf8');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Matches root `package.json` `engines.node`. */
|
|
116
|
+
export const REQUIRED_NODE_FLOOR = '22.22.1';
|
|
117
|
+
export const REQUIRED_NODE_CEILING_MAJOR = 25;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Return true when `version` satisfies `>=22.22.1 <25` (same as `engines`).
|
|
121
|
+
*
|
|
122
|
+
* @param {string} version
|
|
123
|
+
* @returns {boolean}
|
|
124
|
+
*/
|
|
125
|
+
export function satisfiesNodeEngine(version) {
|
|
126
|
+
const [majorRaw, minorRaw, patchRaw] = version.split('.');
|
|
127
|
+
const major = Number.parseInt(majorRaw, 10) || 0;
|
|
128
|
+
const minor = Number.parseInt(minorRaw, 10) || 0;
|
|
129
|
+
const patch = Number.parseInt(patchRaw, 10) || 0;
|
|
130
|
+
if (major >= REQUIRED_NODE_CEILING_MAJOR) return false;
|
|
131
|
+
if (major > 22) return true;
|
|
132
|
+
if (major < 22) return false;
|
|
133
|
+
if (minor > 22) return true;
|
|
134
|
+
if (minor < 22) return false;
|
|
135
|
+
return patch >= 1;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Step 1 — Verify Node satisfies `engines.node`. Returns `{ ok, version,
|
|
140
|
+
* required }` so the CLI can report the detected version regardless of
|
|
141
|
+
* whether the check passed.
|
|
142
|
+
*
|
|
143
|
+
* @param {string} [version=process.versions.node]
|
|
144
|
+
*/
|
|
145
|
+
export function checkNodeVersion(version = process.versions.node) {
|
|
146
|
+
return {
|
|
147
|
+
ok: satisfiesNodeEngine(version),
|
|
148
|
+
version,
|
|
149
|
+
required: REQUIRED_NODE_FLOOR,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Detect the package manager based on lockfile presence. Defaults to
|
|
155
|
+
* `npm` when no lock is found.
|
|
156
|
+
*
|
|
157
|
+
* @param {string} projectRoot
|
|
158
|
+
* @param {typeof fs} [fsImpl]
|
|
159
|
+
*/
|
|
160
|
+
export function detectPackageManager(projectRoot, fsImpl = fs) {
|
|
161
|
+
if (fsImpl.existsSync(path.join(projectRoot, 'pnpm-lock.yaml')))
|
|
162
|
+
return 'pnpm';
|
|
163
|
+
if (fsImpl.existsSync(path.join(projectRoot, 'yarn.lock'))) return 'yarn';
|
|
164
|
+
return 'npm';
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Step 2a/2b/2c — Ensure `package.json` exists and carries the
|
|
169
|
+
* `sync:commands` + `prepare` + `bootstrap` scripts. The consumer manifest
|
|
170
|
+
* is never mutated with framework runtime dependencies: those arrive
|
|
171
|
+
* transitively via the `mandrel` package, so bootstrap leaves the
|
|
172
|
+
* `dependencies` block untouched (Story #3466). Returns the per-key outcome
|
|
173
|
+
* the caller can render.
|
|
174
|
+
*
|
|
175
|
+
* @param {object} ctx
|
|
176
|
+
* @param {typeof fs} [ctx.fsImpl]
|
|
177
|
+
*/
|
|
178
|
+
export function ensurePackageJson(ctx) {
|
|
179
|
+
const { fsImpl = fs } = ctx;
|
|
180
|
+
const pkgPath = path.join(ctx.projectRoot, 'package.json');
|
|
181
|
+
const projectName = path.basename(path.resolve(ctx.projectRoot));
|
|
182
|
+
const outcomes = {
|
|
183
|
+
created: false,
|
|
184
|
+
scriptsSyncCommands: 'already-present',
|
|
185
|
+
scriptsPrepare: 'already-present',
|
|
186
|
+
scriptsBootstrap: 'already-present',
|
|
187
|
+
};
|
|
188
|
+
let pkg = readJsonIfExists(pkgPath, fsImpl);
|
|
189
|
+
if (!pkg) {
|
|
190
|
+
pkg = {
|
|
191
|
+
name: projectName,
|
|
192
|
+
version: '0.0.0',
|
|
193
|
+
private: true,
|
|
194
|
+
type: 'module',
|
|
195
|
+
};
|
|
196
|
+
outcomes.created = true;
|
|
197
|
+
}
|
|
198
|
+
pkg.scripts = pkg.scripts ?? {};
|
|
199
|
+
if (!pkg.scripts['sync:commands']) {
|
|
200
|
+
pkg.scripts['sync:commands'] = SYNC_COMMAND;
|
|
201
|
+
outcomes.scriptsSyncCommands = 'added';
|
|
202
|
+
}
|
|
203
|
+
const prepare = pkg.scripts.prepare;
|
|
204
|
+
if (!prepare) {
|
|
205
|
+
pkg.scripts.prepare = SYNC_COMMAND;
|
|
206
|
+
outcomes.scriptsPrepare = 'added';
|
|
207
|
+
} else if (!prepare.includes('sync-claude-commands.js')) {
|
|
208
|
+
pkg.scripts.prepare = `${prepare} && ${SYNC_COMMAND}`;
|
|
209
|
+
outcomes.scriptsPrepare = 'appended';
|
|
210
|
+
}
|
|
211
|
+
// Expose a discoverable `npm run bootstrap` alias for the framework
|
|
212
|
+
// setup command. An operator-defined `bootstrap` script always wins —
|
|
213
|
+
// we only seed the default when the key is absent.
|
|
214
|
+
if (!pkg.scripts.bootstrap) {
|
|
215
|
+
pkg.scripts.bootstrap = BOOTSTRAP_COMMAND;
|
|
216
|
+
outcomes.scriptsBootstrap = 'added';
|
|
217
|
+
}
|
|
218
|
+
const mutated =
|
|
219
|
+
outcomes.created ||
|
|
220
|
+
outcomes.scriptsSyncCommands === 'added' ||
|
|
221
|
+
outcomes.scriptsPrepare !== 'already-present' ||
|
|
222
|
+
outcomes.scriptsBootstrap === 'added';
|
|
223
|
+
if (mutated) writeJson(pkgPath, pkg, fsImpl);
|
|
224
|
+
return { ...outcomes, path: pkgPath, mutated };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Step 2d — Install dependencies when the framework's sentinel module is
|
|
229
|
+
* unresolvable. Bootstrap no longer seeds framework deps into the consumer
|
|
230
|
+
* manifest (Story #3466) — they arrive transitively via `mandrel`
|
|
231
|
+
* — so the install is triggered purely by an empty/stale `node_modules`.
|
|
232
|
+
* Returns `{ ran, manager, skipped, reason }`.
|
|
233
|
+
*
|
|
234
|
+
* @param {object} ctx
|
|
235
|
+
* @param {typeof fs} [ctx.fsImpl]
|
|
236
|
+
* @param {typeof defaultSpawnSync} [ctx.spawnImpl]
|
|
237
|
+
*/
|
|
238
|
+
export function ensureDependenciesInstalled(ctx) {
|
|
239
|
+
const { fsImpl = fs, spawnImpl = defaultSpawnSync } = ctx;
|
|
240
|
+
const manager = detectPackageManager(ctx.projectRoot, fsImpl);
|
|
241
|
+
const sentinel = path.join(
|
|
242
|
+
ctx.projectRoot,
|
|
243
|
+
'node_modules',
|
|
244
|
+
'ajv',
|
|
245
|
+
'package.json',
|
|
246
|
+
);
|
|
247
|
+
const needsInstall = !fsImpl.existsSync(sentinel);
|
|
248
|
+
if (!needsInstall) {
|
|
249
|
+
return { ran: false, manager, skipped: true, reason: 'already-installed' };
|
|
250
|
+
}
|
|
251
|
+
if (ctx.skipInstall) {
|
|
252
|
+
return { ran: false, manager, skipped: true, reason: 'skip-install-flag' };
|
|
253
|
+
}
|
|
254
|
+
const result = spawnImpl(manager, ['install'], {
|
|
255
|
+
cwd: ctx.projectRoot,
|
|
256
|
+
stdio: ctx.quiet ? 'ignore' : 'inherit',
|
|
257
|
+
shell: process.platform === 'win32',
|
|
258
|
+
});
|
|
259
|
+
if (result.status !== 0) {
|
|
260
|
+
throw new Error(
|
|
261
|
+
`[bootstrap] ${manager} install failed (exit ${result.status}). Resolve the install error and re-run.`,
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
return { ran: true, manager, skipped: false };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Step 2.5a — Seed `.agentrc.json` when missing.
|
|
269
|
+
*
|
|
270
|
+
* Seeds from the bundled `starter-agentrc.json` reference, applying the
|
|
271
|
+
* operator-identity placeholder substitution (`[OWNER]` / `[REPO]` /
|
|
272
|
+
* `[USERNAME]`) and the `baseBranch` override. (Story #3690 removed the
|
|
273
|
+
* named config-profile seeding path — the starter reference is the single
|
|
274
|
+
* seed source.)
|
|
275
|
+
*
|
|
276
|
+
* An existing `.agentrc.json` is never overwritten — operator wins.
|
|
277
|
+
*
|
|
278
|
+
* @param {object} ctx
|
|
279
|
+
* @param {typeof fs} [ctx.fsImpl]
|
|
280
|
+
* @returns {{ action: string, path: string, source?: string }}
|
|
281
|
+
*/
|
|
282
|
+
export function ensureAgentrc(ctx) {
|
|
283
|
+
const { fsImpl = fs } = ctx;
|
|
284
|
+
const target = path.join(ctx.projectRoot, '.agentrc.json');
|
|
285
|
+
if (fsImpl.existsSync(target)) {
|
|
286
|
+
return { action: 'already-present', path: target };
|
|
287
|
+
}
|
|
288
|
+
const starter = path.join(
|
|
289
|
+
ctx.agentRoot ?? path.join(ctx.projectRoot, '.agents'),
|
|
290
|
+
'starter-agentrc.json',
|
|
291
|
+
);
|
|
292
|
+
if (!fsImpl.existsSync(starter)) {
|
|
293
|
+
return { action: 'missing-starter', path: target };
|
|
294
|
+
}
|
|
295
|
+
let body = fsImpl.readFileSync(starter, 'utf8');
|
|
296
|
+
body = body
|
|
297
|
+
.replace(/\[OWNER\]/g, ctx.answers.owner)
|
|
298
|
+
.replace(/\[REPO\]/g, ctx.answers.repo)
|
|
299
|
+
.replace(/\[USERNAME\]/g, ctx.answers.operatorHandle ?? ctx.answers.owner);
|
|
300
|
+
// The starter pins baseBranch to "main"; if the operator chose a
|
|
301
|
+
// different default, update the seeded copy so the per-clone config
|
|
302
|
+
// matches the live remote HEAD.
|
|
303
|
+
if (ctx.answers.baseBranch && ctx.answers.baseBranch !== 'main') {
|
|
304
|
+
body = body.replace(
|
|
305
|
+
/"baseBranch":\s*"main"/,
|
|
306
|
+
`"baseBranch": "${ctx.answers.baseBranch}"`,
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
fsImpl.writeFileSync(target, body, 'utf8');
|
|
310
|
+
return { action: 'seeded', path: target, source: 'starter' };
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Step 2.5b — Validate `.agentrc.json` against the framework's AJV schema.
|
|
315
|
+
* Returns `{ ok, errors }`. Caller decides whether to abort.
|
|
316
|
+
*
|
|
317
|
+
* @param {object} ctx
|
|
318
|
+
* @param {typeof fs} [ctx.fsImpl]
|
|
319
|
+
*/
|
|
320
|
+
export async function validateAgentrc(ctx) {
|
|
321
|
+
const { fsImpl = fs } = ctx;
|
|
322
|
+
const schemaModule = path.join(
|
|
323
|
+
ctx.agentRoot ?? path.join(ctx.projectRoot, '.agents'),
|
|
324
|
+
'scripts',
|
|
325
|
+
'lib',
|
|
326
|
+
'config-settings-schema.js',
|
|
327
|
+
);
|
|
328
|
+
if (!fsImpl.existsSync(schemaModule)) {
|
|
329
|
+
return { ok: false, errors: ['config-settings-schema.js not found'] };
|
|
330
|
+
}
|
|
331
|
+
const mod = await import(`file://${schemaModule.replace(/\\/g, '/')}`);
|
|
332
|
+
const validate = mod.getAgentrcValidator();
|
|
333
|
+
const data = readJsonIfExists(
|
|
334
|
+
path.join(ctx.projectRoot, '.agentrc.json'),
|
|
335
|
+
fsImpl,
|
|
336
|
+
);
|
|
337
|
+
if (!data) return { ok: false, errors: ['.agentrc.json missing'] };
|
|
338
|
+
const ok = validate(data);
|
|
339
|
+
return { ok: !!ok, errors: ok ? [] : (validate.errors ?? []) };
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Step 3 — Merge the `UserPromptSubmit` sync hook into `.claude/settings.json`.
|
|
344
|
+
* Returns `{ action }`.
|
|
345
|
+
*
|
|
346
|
+
* The sync hook keeps the generated flat `/<name>` command tree
|
|
347
|
+
* (`.claude/commands/`) current. The flat projection needs no plugin
|
|
348
|
+
* enablement keys — it loads in every Claude Code environment, including those
|
|
349
|
+
* where the plugin system (`/plugin`) is unavailable (the #3576 plugin cutover
|
|
350
|
+
* was reverted for exactly that reason).
|
|
351
|
+
*
|
|
352
|
+
* @param {object} ctx
|
|
353
|
+
* @param {typeof fs} [ctx.fsImpl]
|
|
354
|
+
*/
|
|
355
|
+
export function ensureClaudeSettings(ctx) {
|
|
356
|
+
const { fsImpl = fs } = ctx;
|
|
357
|
+
const target = path.join(ctx.projectRoot, '.claude', 'settings.json');
|
|
358
|
+
const hook = { type: 'command', command: SYNC_COMMAND };
|
|
359
|
+
if (!fsImpl.existsSync(target)) {
|
|
360
|
+
fsImpl.mkdirSync(path.dirname(target), { recursive: true });
|
|
361
|
+
const fresh = {
|
|
362
|
+
hooks: {
|
|
363
|
+
UserPromptSubmit: [{ hooks: [hook] }],
|
|
364
|
+
},
|
|
365
|
+
};
|
|
366
|
+
writeJson(target, fresh, fsImpl);
|
|
367
|
+
return { action: 'created', path: target };
|
|
368
|
+
}
|
|
369
|
+
const settings = readJsonIfExists(target, fsImpl);
|
|
370
|
+
settings.hooks = settings.hooks ?? {};
|
|
371
|
+
settings.hooks.UserPromptSubmit = settings.hooks.UserPromptSubmit ?? [];
|
|
372
|
+
const hookAlready = settings.hooks.UserPromptSubmit.some((group) =>
|
|
373
|
+
(group?.hooks ?? []).some(
|
|
374
|
+
(h) =>
|
|
375
|
+
typeof h?.command === 'string' &&
|
|
376
|
+
h.command.includes('sync-claude-commands.js'),
|
|
377
|
+
),
|
|
378
|
+
);
|
|
379
|
+
let mutated = false;
|
|
380
|
+
if (!hookAlready) {
|
|
381
|
+
settings.hooks.UserPromptSubmit.push({ hooks: [hook] });
|
|
382
|
+
mutated = true;
|
|
383
|
+
}
|
|
384
|
+
if (!mutated) return { action: 'already-present', path: target };
|
|
385
|
+
writeJson(target, settings, fsImpl);
|
|
386
|
+
return { action: 'merged', path: target };
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Step 4 + Step 8 — Ensure `.gitignore` carries every {@link GITIGNORE_BLOCKS}
|
|
391
|
+
* entry (`.claude/commands/`, `.mcp.json`, `.env`, and the per-clone install
|
|
392
|
+
* ledger). Each block is marker-keyed off a presence pattern, so a re-run is a
|
|
393
|
+
* zero-mutation no-op and never appends a duplicate block. Returns a per-block
|
|
394
|
+
* outcome (`added` | `already-present`).
|
|
395
|
+
*
|
|
396
|
+
* @param {object} ctx
|
|
397
|
+
* @param {typeof fs} [ctx.fsImpl]
|
|
398
|
+
*/
|
|
399
|
+
export function ensureGitignore(ctx) {
|
|
400
|
+
const { fsImpl = fs } = ctx;
|
|
401
|
+
const target = path.join(ctx.projectRoot, '.gitignore');
|
|
402
|
+
const existing = fsImpl.existsSync(target)
|
|
403
|
+
? fsImpl.readFileSync(target, 'utf8')
|
|
404
|
+
: '';
|
|
405
|
+
let body = existing;
|
|
406
|
+
const outcomes = {};
|
|
407
|
+
for (const [key, def] of Object.entries(GITIGNORE_BLOCKS)) {
|
|
408
|
+
if (def.pattern.test(body)) {
|
|
409
|
+
outcomes[key] = 'already-present';
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
body =
|
|
413
|
+
(body.length > 0 && !body.endsWith('\n') ? `${body}\n` : body) +
|
|
414
|
+
def.block;
|
|
415
|
+
outcomes[key] = 'added';
|
|
416
|
+
}
|
|
417
|
+
if (body !== existing) fsImpl.writeFileSync(target, body, 'utf8');
|
|
418
|
+
return { ...outcomes, path: target };
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Step 5 — Run the sync script. Step 6 (parity) is enforced by the
|
|
423
|
+
* sync script itself (it removes stale entries and writes from the
|
|
424
|
+
* single source of truth), so a successful exit equals parity.
|
|
425
|
+
*
|
|
426
|
+
* Returns `{ ok, stdout }`.
|
|
427
|
+
*
|
|
428
|
+
* @param {object} ctx
|
|
429
|
+
* @param {typeof defaultSpawnSync} [ctx.spawnImpl]
|
|
430
|
+
*/
|
|
431
|
+
export function runSyncCommands(ctx) {
|
|
432
|
+
const { spawnImpl = defaultSpawnSync } = ctx;
|
|
433
|
+
const script = path.join(
|
|
434
|
+
ctx.agentRoot ?? path.join(ctx.projectRoot, '.agents'),
|
|
435
|
+
'scripts',
|
|
436
|
+
'sync-claude-commands.js',
|
|
437
|
+
);
|
|
438
|
+
const result = spawnImpl(process.execPath, [script], {
|
|
439
|
+
cwd: ctx.projectRoot,
|
|
440
|
+
encoding: 'utf8',
|
|
441
|
+
});
|
|
442
|
+
if (result.status !== 0) {
|
|
443
|
+
throw new Error(
|
|
444
|
+
`[bootstrap] sync-claude-commands.js failed (exit ${result.status}): ${(
|
|
445
|
+
result.stderr ?? ''
|
|
446
|
+
)
|
|
447
|
+
.trim()
|
|
448
|
+
.slice(0, 400)}`,
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
return { ok: true, stdout: (result.stdout ?? '').trim() };
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Step 6 — Parity check between `.agents/workflows/*.md` and the generated
|
|
456
|
+
* flat command tree `.claude/commands/*.md`. Step 5's sync already enforces
|
|
457
|
+
* this; this is a belt-and-braces verification that the command projection
|
|
458
|
+
* covers every top-level workflow.
|
|
459
|
+
*
|
|
460
|
+
* @param {object} ctx
|
|
461
|
+
* @param {typeof fs} [ctx.fsImpl]
|
|
462
|
+
*/
|
|
463
|
+
export function checkParity(ctx) {
|
|
464
|
+
const { fsImpl = fs } = ctx;
|
|
465
|
+
const workflowsDir = path.join(
|
|
466
|
+
ctx.agentRoot ?? path.join(ctx.projectRoot, '.agents'),
|
|
467
|
+
'workflows',
|
|
468
|
+
);
|
|
469
|
+
const commandsDir = path.join(ctx.projectRoot, '.claude', 'commands');
|
|
470
|
+
const list = (dir) =>
|
|
471
|
+
fsImpl.existsSync(dir)
|
|
472
|
+
? fsImpl
|
|
473
|
+
.readdirSync(dir, { withFileTypes: true })
|
|
474
|
+
.filter((e) => e.isFile() && e.name.endsWith('.md'))
|
|
475
|
+
.map((e) => e.name.replace(/\.md$/, ''))
|
|
476
|
+
.sort()
|
|
477
|
+
: [];
|
|
478
|
+
const workflows = new Set(list(workflowsDir));
|
|
479
|
+
const commands = new Set(list(commandsDir));
|
|
480
|
+
const missingCommand = [...workflows].filter((n) => !commands.has(n));
|
|
481
|
+
const orphanCommand = [...commands].filter((n) => !workflows.has(n));
|
|
482
|
+
return {
|
|
483
|
+
ok: missingCommand.length === 0 && orphanCommand.length === 0,
|
|
484
|
+
missingCommand,
|
|
485
|
+
orphanCommand,
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Step 8.5 — Wire the framework system prompt into a consumer `CLAUDE.md`.
|
|
491
|
+
*
|
|
492
|
+
* Claude Code hydrates its always-loaded context from a project-root
|
|
493
|
+
* `CLAUDE.md`; without the `@.agents/instructions.md` import the framework
|
|
494
|
+
* system prompt never loads on cold start. This step makes that wiring
|
|
495
|
+
* automatic and idempotent:
|
|
496
|
+
*
|
|
497
|
+
* - No `CLAUDE.md` at all → write a minimal one carrying the import.
|
|
498
|
+
* - `CLAUDE.md` exists but lacks the import → append the import block.
|
|
499
|
+
* - `CLAUDE.md` already imports it → no-op (no duplicate import line).
|
|
500
|
+
*
|
|
501
|
+
* Idempotence is keyed off the literal `SYSTEM_PROMPT_IMPORT` path, so a
|
|
502
|
+
* re-run on an already-wired file is a guaranteed zero-mutation no-op.
|
|
503
|
+
*
|
|
504
|
+
* Returns `{ action, path }` where `action` is one of `created`,
|
|
505
|
+
* `appended`, or `already-present`.
|
|
506
|
+
*
|
|
507
|
+
* @param {object} ctx
|
|
508
|
+
* @param {typeof fs} [ctx.fsImpl]
|
|
509
|
+
*/
|
|
510
|
+
export function ensureSystemPromptWiring(ctx) {
|
|
511
|
+
const { fsImpl = fs } = ctx;
|
|
512
|
+
const target = path.join(ctx.projectRoot, 'CLAUDE.md');
|
|
513
|
+
if (!fsImpl.existsSync(target)) {
|
|
514
|
+
fsImpl.writeFileSync(target, SYSTEM_PROMPT_CLAUDE_MD, 'utf8');
|
|
515
|
+
return { action: 'created', path: target };
|
|
516
|
+
}
|
|
517
|
+
const existing = fsImpl.readFileSync(target, 'utf8');
|
|
518
|
+
if (existing.includes(SYSTEM_PROMPT_IMPORT)) {
|
|
519
|
+
return { action: 'already-present', path: target };
|
|
520
|
+
}
|
|
521
|
+
const separator = existing.length > 0 && !existing.endsWith('\n') ? '\n' : '';
|
|
522
|
+
fsImpl.writeFileSync(
|
|
523
|
+
target,
|
|
524
|
+
`${existing}${separator}\n${SYSTEM_PROMPT_BLOCK}`,
|
|
525
|
+
'utf8',
|
|
526
|
+
);
|
|
527
|
+
return { action: 'appended', path: target };
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Step 9 — Windows git-perf hints (warn-only). On non-Windows this is a
|
|
532
|
+
* silent no-op. On Windows the check probes three settings and reports
|
|
533
|
+
* which are missing; it never mutates global git config.
|
|
534
|
+
*
|
|
535
|
+
* @param {object} ctx
|
|
536
|
+
* @param {typeof fs} [ctx.fsImpl]
|
|
537
|
+
* @param {typeof defaultSpawnSync} [ctx.spawnImpl]
|
|
538
|
+
*/
|
|
539
|
+
export function checkWindowsGitPerf(ctx) {
|
|
540
|
+
const { fsImpl = fs, spawnImpl = defaultSpawnSync } = ctx;
|
|
541
|
+
if (os.platform() !== 'win32') {
|
|
542
|
+
return { platform: process.platform, skipped: true };
|
|
543
|
+
}
|
|
544
|
+
const script = path.join(
|
|
545
|
+
ctx.agentRoot ?? path.join(ctx.projectRoot, '.agents'),
|
|
546
|
+
'scripts',
|
|
547
|
+
'check-windows-git-perf.js',
|
|
548
|
+
);
|
|
549
|
+
if (!fsImpl.existsSync(script)) {
|
|
550
|
+
return { platform: 'win32', skipped: true, reason: 'script-missing' };
|
|
551
|
+
}
|
|
552
|
+
const result = spawnImpl(process.execPath, [script], {
|
|
553
|
+
cwd: ctx.projectRoot,
|
|
554
|
+
encoding: 'utf8',
|
|
555
|
+
});
|
|
556
|
+
return {
|
|
557
|
+
platform: 'win32',
|
|
558
|
+
skipped: false,
|
|
559
|
+
ok: result.status === 0,
|
|
560
|
+
stdout: (result.stdout ?? '').trim(),
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// ---------------------------------------------------------------------------
|
|
565
|
+
// BOOTSTRAP_PHASES (Story #2459 / Task #2473)
|
|
566
|
+
//
|
|
567
|
+
// The previous `applyProjectBootstrap` was an 11-step inline pipeline with
|
|
568
|
+
// three fatal-abort branches (`nodeCheck`, `validation`, `parity`). Each
|
|
569
|
+
// phase is now a declarative `{ name, run, isFatal?, formatError? }`
|
|
570
|
+
// entry. The single-pass driver `runPhases` reads the array, calls each
|
|
571
|
+
// `run(ctx, report)`, accumulates the result onto `report[phase.name]`,
|
|
572
|
+
// and routes fatal phases through `throwIfFatal` so the abort message
|
|
573
|
+
// remains operator-visible.
|
|
574
|
+
//
|
|
575
|
+
// `applyProjectBootstrap` collapses to two lines: instantiate an empty
|
|
576
|
+
// report, hand it to `runPhases`, return it.
|
|
577
|
+
// ---------------------------------------------------------------------------
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* @typedef {object} BootstrapPhase
|
|
581
|
+
* @property {string} name — key used to land the result on the report.
|
|
582
|
+
* @property {(ctx: object, report: object) => any|Promise<any>} run
|
|
583
|
+
* — executes the phase. May read prior
|
|
584
|
+
* phases via `report.<name>`.
|
|
585
|
+
* @property {boolean} [isFatal] — when `true`, the driver passes the
|
|
586
|
+
* result through `formatError`; if the
|
|
587
|
+
* formatter returns a non-empty string,
|
|
588
|
+
* the driver throws with that message.
|
|
589
|
+
* @property {(result: any) => string|null} [formatError]
|
|
590
|
+
* — produces the error message when the
|
|
591
|
+
* phase result indicates a fatal abort.
|
|
592
|
+
*/
|
|
593
|
+
|
|
594
|
+
const fatalNodeCheck = (result) =>
|
|
595
|
+
result.ok
|
|
596
|
+
? null
|
|
597
|
+
: `[bootstrap] Node ${result.version} is below required ${result.required}. Upgrade Node and re-run.`;
|
|
598
|
+
|
|
599
|
+
const fatalValidation = (result) =>
|
|
600
|
+
result.ok
|
|
601
|
+
? null
|
|
602
|
+
: `[bootstrap] .agentrc.json failed schema validation: ${JSON.stringify(
|
|
603
|
+
result.errors,
|
|
604
|
+
null,
|
|
605
|
+
2,
|
|
606
|
+
)}`;
|
|
607
|
+
|
|
608
|
+
const fatalParity = (result) =>
|
|
609
|
+
result.ok
|
|
610
|
+
? null
|
|
611
|
+
: `[bootstrap] Parity check failed — workflows missing commands: ${
|
|
612
|
+
result.missingCommand.join(', ') || '(none)'
|
|
613
|
+
}; orphan commands: ${result.orphanCommand.join(', ') || '(none)'}`;
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Pipeline definition — the order, the helpers, and the fatal-abort
|
|
617
|
+
* branches. Exported so tests can assert phase ordering, the fatal flag,
|
|
618
|
+
* and the report-shape parity guarantee without driving the whole
|
|
619
|
+
* bootstrap.
|
|
620
|
+
*
|
|
621
|
+
* Each project-side mutation phase carries a `phaseGroup` matching one of
|
|
622
|
+
* the consent-first {@link PHASE_GROUPS}. When a phased-approval gate is
|
|
623
|
+
* supplied via `ctx.approvedGroups`, a phase whose `phaseGroup` is not in
|
|
624
|
+
* the approved set is skipped (recorded as a `phase-group-declined` no-op)
|
|
625
|
+
* — declining one group never short-circuits the others (Story #3524).
|
|
626
|
+
* Phases with no `phaseGroup` (the Node-version precondition and the
|
|
627
|
+
* dependency install) are always-run infrastructure, never gated.
|
|
628
|
+
*/
|
|
629
|
+
export const BOOTSTRAP_PHASES = Object.freeze([
|
|
630
|
+
{
|
|
631
|
+
name: 'nodeCheck',
|
|
632
|
+
run: () => checkNodeVersion(),
|
|
633
|
+
isFatal: true,
|
|
634
|
+
formatError: fatalNodeCheck,
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
name: 'pkg',
|
|
638
|
+
phaseGroup: PHASE_GROUPS.REPO_CONFIG,
|
|
639
|
+
run: (ctx) => ensurePackageJson(ctx),
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
name: 'install',
|
|
643
|
+
run: (ctx) => ensureDependenciesInstalled(ctx),
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
name: 'agentrc',
|
|
647
|
+
phaseGroup: PHASE_GROUPS.REPO_CONFIG,
|
|
648
|
+
run: (ctx) => ensureAgentrc(ctx),
|
|
649
|
+
},
|
|
650
|
+
{
|
|
651
|
+
name: 'validation',
|
|
652
|
+
phaseGroup: PHASE_GROUPS.REPO_CONFIG,
|
|
653
|
+
run: async (ctx) => validateAgentrc(ctx),
|
|
654
|
+
isFatal: true,
|
|
655
|
+
formatError: fatalValidation,
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
name: 'claudeSettings',
|
|
659
|
+
phaseGroup: PHASE_GROUPS.IDE_WIRING,
|
|
660
|
+
run: (ctx) => ensureClaudeSettings(ctx),
|
|
661
|
+
},
|
|
662
|
+
{
|
|
663
|
+
name: 'systemPromptWiring',
|
|
664
|
+
phaseGroup: PHASE_GROUPS.IDE_WIRING,
|
|
665
|
+
run: (ctx) => ensureSystemPromptWiring(ctx),
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
name: 'gitignore',
|
|
669
|
+
phaseGroup: PHASE_GROUPS.IDE_WIRING,
|
|
670
|
+
run: (ctx) => ensureGitignore(ctx),
|
|
671
|
+
},
|
|
672
|
+
{
|
|
673
|
+
name: 'sync',
|
|
674
|
+
phaseGroup: PHASE_GROUPS.IDE_WIRING,
|
|
675
|
+
run: (ctx) => runSyncCommands(ctx),
|
|
676
|
+
},
|
|
677
|
+
{
|
|
678
|
+
name: 'parity',
|
|
679
|
+
phaseGroup: PHASE_GROUPS.IDE_WIRING,
|
|
680
|
+
run: (ctx) => checkParity(ctx),
|
|
681
|
+
isFatal: true,
|
|
682
|
+
formatError: fatalParity,
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
name: 'quality',
|
|
686
|
+
phaseGroup: PHASE_GROUPS.QUALITY_GATES,
|
|
687
|
+
run: (ctx) =>
|
|
688
|
+
ctx.skipQuality
|
|
689
|
+
? { skipped: true }
|
|
690
|
+
: applyQualityBootstrap({ projectRoot: ctx.projectRoot }),
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
name: 'winPerf',
|
|
694
|
+
run: (ctx) => checkWindowsGitPerf(ctx),
|
|
695
|
+
},
|
|
696
|
+
]);
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* Decide whether a phase should run given the approved-phase-group gate.
|
|
700
|
+
* An always-run infrastructure phase (no `phaseGroup`) runs unconditionally.
|
|
701
|
+
* A grouped phase runs only when no gate is supplied (`approvedGroups`
|
|
702
|
+
* absent — the un-gated legacy path) or when its group is in the gate.
|
|
703
|
+
*
|
|
704
|
+
* Exported for unit testing.
|
|
705
|
+
*
|
|
706
|
+
* @param {BootstrapPhase} phase
|
|
707
|
+
* @param {Set<string>|undefined} approvedGroups
|
|
708
|
+
* @returns {boolean}
|
|
709
|
+
*/
|
|
710
|
+
export function isPhaseApproved(phase, approvedGroups) {
|
|
711
|
+
if (!phase.phaseGroup) return true;
|
|
712
|
+
if (!approvedGroups) return true;
|
|
713
|
+
return approvedGroups.has(phase.phaseGroup);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* Throw with the formatted message when the phase is marked fatal and
|
|
718
|
+
* the result indicates an abort. Pure helper so the driver stays a
|
|
719
|
+
* single-branch loop.
|
|
720
|
+
*
|
|
721
|
+
* Exported for tests.
|
|
722
|
+
*
|
|
723
|
+
* @param {BootstrapPhase} phase
|
|
724
|
+
* @param {any} result
|
|
725
|
+
*/
|
|
726
|
+
export function throwIfFatal(phase, result) {
|
|
727
|
+
if (!phase.isFatal) return;
|
|
728
|
+
const msg = phase.formatError?.(result);
|
|
729
|
+
if (typeof msg === 'string' && msg.length > 0) throw new Error(msg);
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Iterate `phases` in order; await each phase's `run(ctx, report)`, land
|
|
734
|
+
* the result on `report[phase.name]`, then route fatal phases through
|
|
735
|
+
* `throwIfFatal`. Returns the accumulated report.
|
|
736
|
+
*
|
|
737
|
+
* When `ctx.approvedGroups` is a `Set`, a grouped phase whose `phaseGroup`
|
|
738
|
+
* is not approved is skipped and recorded as
|
|
739
|
+
* `{ skipped: true, reason: 'phase-group-declined', phaseGroup }` — it never
|
|
740
|
+
* runs, never throws (so a declined `ide-wiring` group also skips its
|
|
741
|
+
* fatal `parity` check), and never short-circuits the remaining phases.
|
|
742
|
+
*
|
|
743
|
+
* Exported for tests so phase ordering and fatal behaviour can be
|
|
744
|
+
* asserted without spawning a full bootstrap.
|
|
745
|
+
*
|
|
746
|
+
* @param {ReadonlyArray<BootstrapPhase>} phases
|
|
747
|
+
* @param {object} ctx
|
|
748
|
+
* @returns {Promise<object>}
|
|
749
|
+
*/
|
|
750
|
+
export async function runPhases(phases, ctx) {
|
|
751
|
+
const report = {};
|
|
752
|
+
for (const phase of phases) {
|
|
753
|
+
if (!isPhaseApproved(phase, ctx.approvedGroups)) {
|
|
754
|
+
report[phase.name] = {
|
|
755
|
+
skipped: true,
|
|
756
|
+
reason: 'phase-group-declined',
|
|
757
|
+
phaseGroup: phase.phaseGroup,
|
|
758
|
+
};
|
|
759
|
+
continue;
|
|
760
|
+
}
|
|
761
|
+
const result = await phase.run(ctx, report);
|
|
762
|
+
report[phase.name] = result;
|
|
763
|
+
throwIfFatal(phase, result);
|
|
764
|
+
}
|
|
765
|
+
return report;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* Compose every step in order. Each returned key is the outcome of one
|
|
770
|
+
* step so the CLI can render a structured summary.
|
|
771
|
+
*
|
|
772
|
+
* When `ctx.preview` is truthy, the function performs **no writes and no
|
|
773
|
+
* network I/O**. Instead it derives the operator-facing change list from
|
|
774
|
+
* the single mutation-manifest source ({@link previewMutationManifest}) and
|
|
775
|
+
* returns `{ preview: true, groups, entries }` — the exact same source the
|
|
776
|
+
* consent-first install screen renders. Deriving the preview from
|
|
777
|
+
* `buildMutationManifest` (rather than from a parallel hand-maintained list)
|
|
778
|
+
* guarantees the preview the operator approves and the execution that
|
|
779
|
+
* follows enumerate one identical set of mutations (Story #3521).
|
|
780
|
+
*
|
|
781
|
+
* @param {object} ctx
|
|
782
|
+
* @param {string} ctx.projectRoot
|
|
783
|
+
* @param {string} [ctx.agentRoot]
|
|
784
|
+
* @param {{ owner: string, repo: string, baseBranch: string,
|
|
785
|
+
* operatorHandle: string|null }} ctx.answers
|
|
786
|
+
* @param {boolean} [ctx.preview] — no-write preview from the manifest.
|
|
787
|
+
* @param {Set<string>} [ctx.approvedGroups] — when present, only phases
|
|
788
|
+
* whose `phaseGroup` is in this set execute (the consent-first gate from
|
|
789
|
+
* Story #3524); always-run infrastructure phases ignore it.
|
|
790
|
+
* @param {boolean} [ctx.skipQuality]
|
|
791
|
+
* @param {boolean} [ctx.skipGithub]
|
|
792
|
+
* @param {boolean} [ctx.skipInstall]
|
|
793
|
+
* @param {boolean} [ctx.quiet]
|
|
794
|
+
* @param {typeof fs} [ctx.fsImpl] — injectable filesystem seam (test-seams.md).
|
|
795
|
+
* @param {typeof defaultSpawnSync} [ctx.spawnImpl] — injectable spawn seam (test-seams.md).
|
|
796
|
+
* @returns {Promise<object>}
|
|
797
|
+
*/
|
|
798
|
+
export async function applyProjectBootstrap(ctx) {
|
|
799
|
+
if (ctx.preview) return previewMutationManifest(ctx);
|
|
800
|
+
return runPhases(BOOTSTRAP_PHASES, ctx);
|
|
801
|
+
}
|