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,795 @@
|
|
|
1
|
+
// lib/cli/uninstall.js
|
|
2
|
+
/**
|
|
3
|
+
* `mandrel uninstall` subcommand.
|
|
4
|
+
*
|
|
5
|
+
* Reverses a recorded install by consuming the install ledger written by the
|
|
6
|
+
* consent-first bootstrap (`.agents/.install-manifest.json`, Story #3524).
|
|
7
|
+
* Each ledger entry is a mutation-manifest record
|
|
8
|
+
* (`{ phaseGroup, target, action, reversible }`); uninstall walks the
|
|
9
|
+
* reversible entries and undoes exactly the mutation the install applied,
|
|
10
|
+
* keyed off the entry's `target` path.
|
|
11
|
+
*
|
|
12
|
+
* Design goals
|
|
13
|
+
* ------------
|
|
14
|
+
* - **Preserve pre-existing user content.** Reversal is marker-based, not
|
|
15
|
+
* blunt file deletion: the CLAUDE.md import block is stripped (not the file
|
|
16
|
+
* removed) so a CLAUDE.md the operator authored before install survives;
|
|
17
|
+
* the `.claude/settings.json` sync hook is spliced out without touching
|
|
18
|
+
* other hooks; the `.gitignore` entries are removed without disturbing the
|
|
19
|
+
* operator's own ignore rules; only the framework's own npm scripts are
|
|
20
|
+
* removed from `package.json`. A file is deleted outright only when
|
|
21
|
+
* stripping the framework block leaves it empty / framework-only (the
|
|
22
|
+
* install created it from nothing).
|
|
23
|
+
* - **GitHub-side state is never touched by default.** The `github-admin`
|
|
24
|
+
* ledger entries carry `reversible: false`; they are surfaced as a manual
|
|
25
|
+
* rollback checklist and are only acted on when the operator opts in with
|
|
26
|
+
* `--include-github` (which, for now, still only enumerates them — remote
|
|
27
|
+
* admin reversal is out of scope for this Story and would require the same
|
|
28
|
+
* `gh` plumbing the bootstrap uses).
|
|
29
|
+
* - **Idempotent.** Re-running after a successful uninstall is a no-op: the
|
|
30
|
+
* ledger is removed last, and every reversal step is a no-op when the
|
|
31
|
+
* marker is already absent.
|
|
32
|
+
*
|
|
33
|
+
* Output contract
|
|
34
|
+
* ---------------
|
|
35
|
+
* reversed file → "✔ reverted <target> <detail>"
|
|
36
|
+
* skipped → "• skipped <target> <reason>"
|
|
37
|
+
* manual (gh) → "! manual <target> <detail>"
|
|
38
|
+
* final → "✅ Uninstalled (<n> reversed, <m> manual follow-ups)"
|
|
39
|
+
* | "❌ No install ledger found — nothing to uninstall."
|
|
40
|
+
*
|
|
41
|
+
* All output goes to process.stdout (never console.log — the repo enforces a
|
|
42
|
+
* no-console rule). Exit code 0 on success (including the no-ledger case,
|
|
43
|
+
* which is a benign no-op), 1 only on an unrecoverable error.
|
|
44
|
+
*
|
|
45
|
+
* Injectable seams (used by tests so no real filesystem is touched):
|
|
46
|
+
* - `projectRoot` — overrides the resolved consumer root.
|
|
47
|
+
* - `fsImpl` — replaces the `node:fs` surface.
|
|
48
|
+
* - `write` — replaces process.stdout.write.
|
|
49
|
+
* - `exit` — replaces process.exit.
|
|
50
|
+
* - `includeGithub`— forces the --include-github behaviour.
|
|
51
|
+
*
|
|
52
|
+
* @module cli/uninstall
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
import fs from 'node:fs';
|
|
56
|
+
import path from 'node:path';
|
|
57
|
+
import { fileURLToPath } from 'node:url';
|
|
58
|
+
|
|
59
|
+
import {
|
|
60
|
+
LEDGER_SCHEMA_VERSION,
|
|
61
|
+
ledgerPath,
|
|
62
|
+
readInstallLedger,
|
|
63
|
+
} from '../../.agents/scripts/lib/bootstrap/install-ledger.js';
|
|
64
|
+
import {
|
|
65
|
+
BOOTSTRAP_COMMAND,
|
|
66
|
+
GITIGNORE_BLOCKS,
|
|
67
|
+
SYNC_COMMAND,
|
|
68
|
+
SYSTEM_PROMPT_BLOCK,
|
|
69
|
+
SYSTEM_PROMPT_CLAUDE_MD,
|
|
70
|
+
SYSTEM_PROMPT_IMPORT,
|
|
71
|
+
} from '../../.agents/scripts/lib/bootstrap/project-bootstrap.js';
|
|
72
|
+
import {
|
|
73
|
+
DOWNSTREAM_PRE_COMMIT,
|
|
74
|
+
PRE_COMMIT_MARKER,
|
|
75
|
+
QUALITY_NPM_SCRIPTS,
|
|
76
|
+
} from '../../.agents/scripts/lib/bootstrap/quality-bootstrap.js';
|
|
77
|
+
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Project-root resolution
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Resolve the consumer project root — the directory that holds `.agents/`.
|
|
84
|
+
* `mandrel uninstall` runs from the consumer's checkout, so the install
|
|
85
|
+
* ledger and every target path are anchored at `process.cwd()`. This mirrors
|
|
86
|
+
* how `lib/cli/sync.js` and the doctor checks anchor consumer-facing paths.
|
|
87
|
+
*
|
|
88
|
+
* @param {() => string} [cwd=process.cwd]
|
|
89
|
+
* @returns {string}
|
|
90
|
+
*/
|
|
91
|
+
function resolveProjectRoot(cwd = () => process.cwd()) {
|
|
92
|
+
return cwd();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// npm-script removal set
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* The exact `package.json` scripts the bootstrap seeds. Reversal removes a
|
|
101
|
+
* script key only when its value still equals the framework-seeded command —
|
|
102
|
+
* an operator who overwrote the value keeps their version. `prepare` is
|
|
103
|
+
* special: the bootstrap may *append* the sync command to an existing
|
|
104
|
+
* `prepare`, so reversal strips the framework fragment rather than deleting
|
|
105
|
+
* the whole key. Mirrors `ensurePackageJson` / `ensureQualityNpmScripts`.
|
|
106
|
+
*
|
|
107
|
+
* @type {Readonly<Record<string, string>>}
|
|
108
|
+
*/
|
|
109
|
+
const FRAMEWORK_NPM_SCRIPTS = Object.freeze({
|
|
110
|
+
'sync:commands': SYNC_COMMAND,
|
|
111
|
+
bootstrap: BOOTSTRAP_COMMAND,
|
|
112
|
+
...QUALITY_NPM_SCRIPTS,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
// Pure reversal helpers (filesystem effects via the injected fsImpl)
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @typedef {object} ReversalOutcome
|
|
121
|
+
* @property {'reverted'|'skipped'|'manual'} kind
|
|
122
|
+
* @property {string} target
|
|
123
|
+
* @property {string} detail
|
|
124
|
+
*/
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Strip the framework system-prompt import block from a `CLAUDE.md`. The file
|
|
128
|
+
* is removed only when it is byte-identical to the install-authored template
|
|
129
|
+
* (`SYSTEM_PROMPT_CLAUDE_MD`). Any other file — including one whose only
|
|
130
|
+
* operator content is markdown headings — is preserved with just the framework
|
|
131
|
+
* block excised.
|
|
132
|
+
*
|
|
133
|
+
* Using a byte-equality check rather than a "non-`#` meaningful lines"
|
|
134
|
+
* heuristic prevents data loss when an operator's pre-install `CLAUDE.md`
|
|
135
|
+
* consists entirely of markdown headings (all lines start with `#`).
|
|
136
|
+
*
|
|
137
|
+
* @param {string} projectRoot
|
|
138
|
+
* @param {typeof fs} fsImpl
|
|
139
|
+
* @returns {ReversalOutcome}
|
|
140
|
+
*/
|
|
141
|
+
function revertClaudeMd(projectRoot, fsImpl) {
|
|
142
|
+
const target = path.join(projectRoot, 'CLAUDE.md');
|
|
143
|
+
const rel = 'CLAUDE.md';
|
|
144
|
+
if (!fsImpl.existsSync(target)) {
|
|
145
|
+
return { kind: 'skipped', target: rel, detail: 'file absent' };
|
|
146
|
+
}
|
|
147
|
+
const original = fsImpl.readFileSync(target, 'utf8');
|
|
148
|
+
if (!original.includes(SYSTEM_PROMPT_IMPORT)) {
|
|
149
|
+
return { kind: 'skipped', target: rel, detail: 'import already absent' };
|
|
150
|
+
}
|
|
151
|
+
// Delete only when the file is exactly the install-authored template — i.e.
|
|
152
|
+
// the install created it from nothing. Operator-authored content (even an
|
|
153
|
+
// all-headings file) must survive.
|
|
154
|
+
if (original.trim() === SYSTEM_PROMPT_CLAUDE_MD.trim()) {
|
|
155
|
+
fsImpl.rmSync(target, { force: true });
|
|
156
|
+
return {
|
|
157
|
+
kind: 'reverted',
|
|
158
|
+
target: rel,
|
|
159
|
+
detail: 'removed install-created CLAUDE.md',
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
// Remove the full block first (heading + import), then fall back to the
|
|
163
|
+
// bare import line so a hand-edited block without the heading still clears.
|
|
164
|
+
let next = original.includes(SYSTEM_PROMPT_BLOCK)
|
|
165
|
+
? original.replace(SYSTEM_PROMPT_BLOCK, '')
|
|
166
|
+
: original;
|
|
167
|
+
if (next.includes(SYSTEM_PROMPT_IMPORT)) {
|
|
168
|
+
next = next
|
|
169
|
+
.split('\n')
|
|
170
|
+
.filter((line) => line.trim() !== SYSTEM_PROMPT_IMPORT)
|
|
171
|
+
.join('\n');
|
|
172
|
+
}
|
|
173
|
+
// Collapse any run of 3+ blank lines the splice may have produced.
|
|
174
|
+
next = next.replace(/\n{3,}/g, '\n\n').replace(/^\n+/, '');
|
|
175
|
+
fsImpl.writeFileSync(
|
|
176
|
+
target,
|
|
177
|
+
next.endsWith('\n') ? next : `${next}\n`,
|
|
178
|
+
'utf8',
|
|
179
|
+
);
|
|
180
|
+
return {
|
|
181
|
+
kind: 'reverted',
|
|
182
|
+
target: rel,
|
|
183
|
+
detail: 'stripped system-prompt import block',
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Splice the framework UserPromptSubmit sync hook **and** the plugin
|
|
189
|
+
* enablement keys (Story #3576) out of `.claude/settings.json`, leaving every
|
|
190
|
+
* other hook and setting intact. When the settings file is left with no hooks
|
|
191
|
+
* and no other keys, it is removed.
|
|
192
|
+
*
|
|
193
|
+
* @param {string} projectRoot
|
|
194
|
+
* @param {typeof fs} fsImpl
|
|
195
|
+
* @returns {ReversalOutcome}
|
|
196
|
+
*/
|
|
197
|
+
function revertClaudeSettings(projectRoot, fsImpl) {
|
|
198
|
+
const target = path.join(projectRoot, '.claude', 'settings.json');
|
|
199
|
+
const rel = '.claude/settings.json';
|
|
200
|
+
if (!fsImpl.existsSync(target)) {
|
|
201
|
+
return { kind: 'skipped', target: rel, detail: 'file absent' };
|
|
202
|
+
}
|
|
203
|
+
const settings = JSON.parse(fsImpl.readFileSync(target, 'utf8'));
|
|
204
|
+
const groups = settings?.hooks?.UserPromptSubmit;
|
|
205
|
+
const isFrameworkHook = (h) =>
|
|
206
|
+
typeof h?.command === 'string' &&
|
|
207
|
+
h.command.includes('sync-claude-commands.js');
|
|
208
|
+
|
|
209
|
+
let mutated = false;
|
|
210
|
+
|
|
211
|
+
// 1. Strip any legacy plugin-enablement keys (#3576). The flat-command
|
|
212
|
+
// projection no longer writes these, but a consumer upgraded from a
|
|
213
|
+
// #3576 install may still carry them — clean them up on uninstall.
|
|
214
|
+
if (
|
|
215
|
+
settings.enabledPlugins &&
|
|
216
|
+
settings.enabledPlugins['mandrel@mandrel'] !== undefined
|
|
217
|
+
) {
|
|
218
|
+
delete settings.enabledPlugins['mandrel@mandrel'];
|
|
219
|
+
if (Object.keys(settings.enabledPlugins).length === 0) {
|
|
220
|
+
delete settings.enabledPlugins;
|
|
221
|
+
}
|
|
222
|
+
mutated = true;
|
|
223
|
+
}
|
|
224
|
+
if (settings.extraKnownMarketplaces?.mandrel !== undefined) {
|
|
225
|
+
delete settings.extraKnownMarketplaces.mandrel;
|
|
226
|
+
if (Object.keys(settings.extraKnownMarketplaces).length === 0) {
|
|
227
|
+
delete settings.extraKnownMarketplaces;
|
|
228
|
+
}
|
|
229
|
+
mutated = true;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// 2. Splice out the UserPromptSubmit sync hook.
|
|
233
|
+
if (Array.isArray(groups)) {
|
|
234
|
+
const kept = groups
|
|
235
|
+
.map((group) => ({
|
|
236
|
+
...group,
|
|
237
|
+
hooks: (group?.hooks ?? []).filter((h) => !isFrameworkHook(h)),
|
|
238
|
+
}))
|
|
239
|
+
.filter((group) => (group.hooks ?? []).length > 0);
|
|
240
|
+
if (kept.length !== groups.length) {
|
|
241
|
+
if (kept.length === 0) {
|
|
242
|
+
delete settings.hooks.UserPromptSubmit;
|
|
243
|
+
} else {
|
|
244
|
+
settings.hooks.UserPromptSubmit = kept;
|
|
245
|
+
}
|
|
246
|
+
if (settings.hooks && Object.keys(settings.hooks).length === 0) {
|
|
247
|
+
delete settings.hooks;
|
|
248
|
+
}
|
|
249
|
+
mutated = true;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (!mutated) {
|
|
254
|
+
return { kind: 'skipped', target: rel, detail: 'framework wiring absent' };
|
|
255
|
+
}
|
|
256
|
+
if (Object.keys(settings).length === 0) {
|
|
257
|
+
fsImpl.rmSync(target, { force: true });
|
|
258
|
+
return {
|
|
259
|
+
kind: 'reverted',
|
|
260
|
+
target: rel,
|
|
261
|
+
detail: 'removed install-created settings.json',
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
fsImpl.writeFileSync(
|
|
265
|
+
target,
|
|
266
|
+
`${JSON.stringify(settings, null, 2)}\n`,
|
|
267
|
+
'utf8',
|
|
268
|
+
);
|
|
269
|
+
return {
|
|
270
|
+
kind: 'reverted',
|
|
271
|
+
target: rel,
|
|
272
|
+
detail: 'removed sync hook (and any legacy plugin enablement)',
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Remove the generated Claude Code command projection: the flat
|
|
278
|
+
* `.claude/commands/` tree. The tree is generated from `.agents/workflows/`, so
|
|
279
|
+
* it is safe to remove wholesale (it is gitignored and never hand-edited). Any
|
|
280
|
+
* legacy #3576 plugin projection (`.claude/plugins/mandrel/` +
|
|
281
|
+
* `.claude/.claude-plugin/`) left by an older install is also removed.
|
|
282
|
+
*
|
|
283
|
+
* @param {string} projectRoot
|
|
284
|
+
* @param {typeof fs} fsImpl
|
|
285
|
+
* @returns {ReversalOutcome}
|
|
286
|
+
*/
|
|
287
|
+
function revertClaudeCommands(projectRoot, fsImpl) {
|
|
288
|
+
const rel = '.claude/commands';
|
|
289
|
+
const targets = [
|
|
290
|
+
path.join(projectRoot, '.claude', 'commands'),
|
|
291
|
+
// Legacy #3576 plugin projection — clean it up too if present.
|
|
292
|
+
path.join(projectRoot, '.claude', 'plugins', 'mandrel'),
|
|
293
|
+
path.join(projectRoot, '.claude', '.claude-plugin'),
|
|
294
|
+
];
|
|
295
|
+
const present = targets.filter((t) => fsImpl.existsSync(t));
|
|
296
|
+
if (present.length === 0) {
|
|
297
|
+
return {
|
|
298
|
+
kind: 'skipped',
|
|
299
|
+
target: rel,
|
|
300
|
+
detail: 'command projection absent',
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
for (const t of present) {
|
|
304
|
+
fsImpl.rmSync(t, { recursive: true, force: true });
|
|
305
|
+
}
|
|
306
|
+
return {
|
|
307
|
+
kind: 'reverted',
|
|
308
|
+
target: rel,
|
|
309
|
+
detail: 'removed generated .claude/commands/ projection',
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Remove the two `.gitignore` blocks the install appended (the
|
|
315
|
+
* `.claude/commands/` and `.mcp.json` entries), preserving every other line
|
|
316
|
+
* the operator authored. When the file is left empty it is removed.
|
|
317
|
+
*
|
|
318
|
+
* The `.mcp.json` ignore block is intentionally retained when a real
|
|
319
|
+
* `.mcp.json` exists at the project root: that file may carry secrets and
|
|
320
|
+
* removing the ignore entry would expose it on the next `git add .`.
|
|
321
|
+
*
|
|
322
|
+
* @param {string} projectRoot
|
|
323
|
+
* @param {typeof fs} fsImpl
|
|
324
|
+
* @returns {ReversalOutcome}
|
|
325
|
+
*/
|
|
326
|
+
function revertGitignore(projectRoot, fsImpl) {
|
|
327
|
+
const target = path.join(projectRoot, '.gitignore');
|
|
328
|
+
const rel = '.gitignore';
|
|
329
|
+
if (!fsImpl.existsSync(target)) {
|
|
330
|
+
return { kind: 'skipped', target: rel, detail: 'file absent' };
|
|
331
|
+
}
|
|
332
|
+
const original = fsImpl.readFileSync(target, 'utf8');
|
|
333
|
+
const mcpJsonExists = fsImpl.existsSync(path.join(projectRoot, '.mcp.json'));
|
|
334
|
+
let next = original;
|
|
335
|
+
for (const [key, def] of Object.entries(GITIGNORE_BLOCKS)) {
|
|
336
|
+
if (next.includes(def.block)) {
|
|
337
|
+
// Retain the .mcp.json ignore entry when a real .mcp.json is present —
|
|
338
|
+
// removing it would expose a potentially secret-bearing file to git.
|
|
339
|
+
if (key === 'mcp' && mcpJsonExists) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
next = next.replace(def.block, '');
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
if (next === original) {
|
|
346
|
+
return { kind: 'skipped', target: rel, detail: 'ignore entries absent' };
|
|
347
|
+
}
|
|
348
|
+
next = next.replace(/\n{3,}/g, '\n\n');
|
|
349
|
+
if (next.trim().length === 0) {
|
|
350
|
+
fsImpl.rmSync(target, { force: true });
|
|
351
|
+
return {
|
|
352
|
+
kind: 'reverted',
|
|
353
|
+
target: rel,
|
|
354
|
+
detail: 'removed install-created .gitignore',
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
fsImpl.writeFileSync(target, next, 'utf8');
|
|
358
|
+
const detail = mcpJsonExists
|
|
359
|
+
? 'removed framework ignore entries; kept .mcp.json entry (.mcp.json exists)'
|
|
360
|
+
: 'removed framework ignore entries';
|
|
361
|
+
return { kind: 'reverted', target: rel, detail };
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Remove the framework-seeded npm scripts (and the appended `prepare`
|
|
366
|
+
* fragment) from `package.json`, leaving every operator-authored script and
|
|
367
|
+
* field intact. A script whose value the operator overwrote is preserved.
|
|
368
|
+
*
|
|
369
|
+
* @param {string} projectRoot
|
|
370
|
+
* @param {typeof fs} fsImpl
|
|
371
|
+
* @returns {ReversalOutcome}
|
|
372
|
+
*/
|
|
373
|
+
function revertPackageJson(projectRoot, fsImpl) {
|
|
374
|
+
const target = path.join(projectRoot, 'package.json');
|
|
375
|
+
const rel = 'package.json';
|
|
376
|
+
if (!fsImpl.existsSync(target)) {
|
|
377
|
+
return { kind: 'skipped', target: rel, detail: 'file absent' };
|
|
378
|
+
}
|
|
379
|
+
const pkg = JSON.parse(fsImpl.readFileSync(target, 'utf8'));
|
|
380
|
+
if (!pkg.scripts || typeof pkg.scripts !== 'object') {
|
|
381
|
+
return { kind: 'skipped', target: rel, detail: 'no framework scripts' };
|
|
382
|
+
}
|
|
383
|
+
const removed = [];
|
|
384
|
+
for (const [name, cmd] of Object.entries(FRAMEWORK_NPM_SCRIPTS)) {
|
|
385
|
+
if (pkg.scripts[name] === cmd) {
|
|
386
|
+
delete pkg.scripts[name];
|
|
387
|
+
removed.push(name);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
// `prepare` may be the bare sync command (delete it) or an operator command
|
|
391
|
+
// with the sync fragment appended via ` && ` (strip just the fragment).
|
|
392
|
+
// When stripping leaves an empty string, delete the key rather than writing
|
|
393
|
+
// `"prepare": ""`. Only push 'prepare' onto `removed` when the value
|
|
394
|
+
// actually changed (i.e. the fragment was present and was stripped).
|
|
395
|
+
const prepare = pkg.scripts.prepare;
|
|
396
|
+
if (typeof prepare === 'string' && prepare.includes(SYNC_COMMAND)) {
|
|
397
|
+
if (prepare === SYNC_COMMAND) {
|
|
398
|
+
delete pkg.scripts.prepare;
|
|
399
|
+
removed.push('prepare');
|
|
400
|
+
} else {
|
|
401
|
+
const stripped = prepare
|
|
402
|
+
.replace(` && ${SYNC_COMMAND}`, '')
|
|
403
|
+
.replace(`${SYNC_COMMAND} && `, '')
|
|
404
|
+
.trim();
|
|
405
|
+
if (stripped !== prepare) {
|
|
406
|
+
if (stripped === '') {
|
|
407
|
+
delete pkg.scripts.prepare;
|
|
408
|
+
} else {
|
|
409
|
+
pkg.scripts.prepare = stripped;
|
|
410
|
+
}
|
|
411
|
+
removed.push('prepare');
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
if (removed.length === 0) {
|
|
416
|
+
return { kind: 'skipped', target: rel, detail: 'no framework scripts' };
|
|
417
|
+
}
|
|
418
|
+
if (Object.keys(pkg.scripts).length === 0) {
|
|
419
|
+
delete pkg.scripts;
|
|
420
|
+
}
|
|
421
|
+
fsImpl.writeFileSync(target, `${JSON.stringify(pkg, null, 2)}\n`, 'utf8');
|
|
422
|
+
return {
|
|
423
|
+
kind: 'reverted',
|
|
424
|
+
target: rel,
|
|
425
|
+
detail: `removed npm scripts: ${removed.sort().join(', ')}`,
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Remove an install-created `.agentrc.json` — but never one the install did
|
|
431
|
+
* not create (Story #3895, data-loss fix for `docs/install-bootstrap-review.md`
|
|
432
|
+
* Finding B.2).
|
|
433
|
+
*
|
|
434
|
+
* The ledger now records the **live** outcome of the `agentrc` bootstrap phase
|
|
435
|
+
* as `executedAction` (schema v2). `ensureAgentrc` returns `seeded` when it
|
|
436
|
+
* wrote the file from the starter and `already-present` when it left a
|
|
437
|
+
* pre-existing, operator-authored file untouched. Reversal is gated on that:
|
|
438
|
+
*
|
|
439
|
+
* - `executedAction === 'already-present'` → the operator owned this file
|
|
440
|
+
* before the install ran; the install created nothing, so deleting it would
|
|
441
|
+
* be data loss. Skip.
|
|
442
|
+
* - `executedAction === 'seeded'` (or any other create-class outcome) → the
|
|
443
|
+
* install authored the file from nothing; deleting it returns the project to
|
|
444
|
+
* the pre-install state.
|
|
445
|
+
* - `executedAction` absent (legacy v1 ledger / no hint) → cannot happen for a
|
|
446
|
+
* v2 ledger written by this framework, but if encountered we fail **safe**
|
|
447
|
+
* and skip rather than risk deleting operator content.
|
|
448
|
+
*
|
|
449
|
+
* @param {string} projectRoot
|
|
450
|
+
* @param {typeof fs} fsImpl
|
|
451
|
+
* @param {string} [executedAction] — the recorded `agentrc` phase outcome.
|
|
452
|
+
* @returns {ReversalOutcome}
|
|
453
|
+
*/
|
|
454
|
+
function revertAgentrc(projectRoot, fsImpl, executedAction) {
|
|
455
|
+
const target = path.join(projectRoot, '.agentrc.json');
|
|
456
|
+
const rel = '.agentrc.json';
|
|
457
|
+
if (!fsImpl.existsSync(target)) {
|
|
458
|
+
return { kind: 'skipped', target: rel, detail: 'file absent' };
|
|
459
|
+
}
|
|
460
|
+
// Only delete a file the install actually created. Any non-`seeded` outcome
|
|
461
|
+
// (pre-existing `already-present`, a missing hint, or an unexpected value)
|
|
462
|
+
// is treated as "not install-created" → preserve the operator's file.
|
|
463
|
+
if (executedAction !== 'seeded') {
|
|
464
|
+
return {
|
|
465
|
+
kind: 'skipped',
|
|
466
|
+
target: rel,
|
|
467
|
+
detail: 'pre-existing .agentrc.json preserved (not install-created)',
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
fsImpl.rmSync(target, { force: true });
|
|
471
|
+
return {
|
|
472
|
+
kind: 'reverted',
|
|
473
|
+
target: rel,
|
|
474
|
+
detail: 'removed install-created .agentrc.json',
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Reverse the `.husky/pre-commit` quality hook. The file is removed only when
|
|
480
|
+
* it is byte-identical to the install-authored template (`DOWNSTREAM_PRE_COMMIT`).
|
|
481
|
+
* Any other hook — including one whose only non-framework lines are a shebang
|
|
482
|
+
* or comments — is preserved with just the quality-preview line stripped.
|
|
483
|
+
*
|
|
484
|
+
* Using a byte-equality check rather than a "non-`#` meaningful lines"
|
|
485
|
+
* heuristic prevents data loss when an operator's pre-install hook consists
|
|
486
|
+
* entirely of a shebang line and/or comments (all lines start with `#`).
|
|
487
|
+
*
|
|
488
|
+
* @param {string} projectRoot
|
|
489
|
+
* @param {typeof fs} fsImpl
|
|
490
|
+
* @returns {ReversalOutcome}
|
|
491
|
+
*/
|
|
492
|
+
function revertPreCommitHook(projectRoot, fsImpl) {
|
|
493
|
+
const target = path.join(projectRoot, '.husky', 'pre-commit');
|
|
494
|
+
const rel = '.husky/pre-commit';
|
|
495
|
+
if (!fsImpl.existsSync(target)) {
|
|
496
|
+
return { kind: 'skipped', target: rel, detail: 'hook absent' };
|
|
497
|
+
}
|
|
498
|
+
const original = fsImpl.readFileSync(target, 'utf8');
|
|
499
|
+
if (!original.includes(PRE_COMMIT_MARKER)) {
|
|
500
|
+
return { kind: 'skipped', target: rel, detail: 'quality line absent' };
|
|
501
|
+
}
|
|
502
|
+
// Delete only when the file is exactly the install-authored template — i.e.
|
|
503
|
+
// the install created it from nothing. Operator-authored content (even an
|
|
504
|
+
// all-comments hook) must survive.
|
|
505
|
+
if (original.trim() === DOWNSTREAM_PRE_COMMIT.trim()) {
|
|
506
|
+
fsImpl.rmSync(target, { force: true });
|
|
507
|
+
return {
|
|
508
|
+
kind: 'reverted',
|
|
509
|
+
target: rel,
|
|
510
|
+
detail: 'removed install-created pre-commit hook',
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
const kept = original
|
|
514
|
+
.split('\n')
|
|
515
|
+
.filter((line) => !line.includes(PRE_COMMIT_MARKER));
|
|
516
|
+
const remaining = kept.join('\n').trim();
|
|
517
|
+
fsImpl.writeFileSync(target, `${remaining}\n`, 'utf8');
|
|
518
|
+
return {
|
|
519
|
+
kind: 'reverted',
|
|
520
|
+
target: rel,
|
|
521
|
+
detail: 'stripped quality-preview line',
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// ---------------------------------------------------------------------------
|
|
526
|
+
// Dispatch table — ledger target → reversal helper
|
|
527
|
+
// ---------------------------------------------------------------------------
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Map a reversible ledger entry's `target` to the helper that undoes it.
|
|
531
|
+
* Targets that map to the same file (e.g. both `repo-config` and
|
|
532
|
+
* `quality-gates` touch `package.json`) are deduped by the caller so each
|
|
533
|
+
* file is reverted once.
|
|
534
|
+
*
|
|
535
|
+
* Handlers take `(root, fsImpl)`; `.agentrc.json` additionally takes the
|
|
536
|
+
* recorded `executedAction` (the third arg, ignored by the others) so it can
|
|
537
|
+
* preserve a pre-existing file the install did not create (Story #3895).
|
|
538
|
+
*
|
|
539
|
+
* @type {Readonly<Record<string, (root: string, fsImpl: typeof fs, executedAction?: string) => ReversalOutcome>>}
|
|
540
|
+
*/
|
|
541
|
+
const REVERSAL_BY_TARGET = Object.freeze({
|
|
542
|
+
'CLAUDE.md': revertClaudeMd,
|
|
543
|
+
'.claude/settings.json': revertClaudeSettings,
|
|
544
|
+
'.claude/plugins/mandrel': revertClaudeCommands,
|
|
545
|
+
'.gitignore': revertGitignore,
|
|
546
|
+
'package.json': revertPackageJson,
|
|
547
|
+
'.agentrc.json': revertAgentrc,
|
|
548
|
+
'.husky/pre-commit': revertPreCommitHook,
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
// ---------------------------------------------------------------------------
|
|
552
|
+
// Planner (pure over the ledger; effects deferred to the helpers)
|
|
553
|
+
// ---------------------------------------------------------------------------
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Partition a ledger's entries into the reversible local-file reversals to
|
|
557
|
+
* run, the remote (`github-admin`) entries to surface as manual follow-ups,
|
|
558
|
+
* and the set of unique file targets to revert (deduped).
|
|
559
|
+
*
|
|
560
|
+
* Pure — derives entirely from the ledger record, with no filesystem access.
|
|
561
|
+
*
|
|
562
|
+
* The returned `executedActionByTarget` map carries the per-target
|
|
563
|
+
* `executedAction` recorded in the ledger (schema v2, Story #3895). When more
|
|
564
|
+
* than one entry shares a target (e.g. the repo-config `create` and
|
|
565
|
+
* quality-gates `merge` entries for `.agentrc.json`), the first defined
|
|
566
|
+
* `executedAction` wins — they resolve to the same bootstrap phase outcome, so
|
|
567
|
+
* the choice is unambiguous.
|
|
568
|
+
*
|
|
569
|
+
* @param {{ entries: Array<import('../../.agents/scripts/lib/bootstrap/manifest.js').MutationManifestEntry & { executedAction?: string }> }} ledger
|
|
570
|
+
* @returns {{ fileTargets: string[], manual: import('../../.agents/scripts/lib/bootstrap/manifest.js').MutationManifestEntry[], executedActionByTarget: Record<string, string> }}
|
|
571
|
+
*/
|
|
572
|
+
export function planUninstall(ledger) {
|
|
573
|
+
const fileTargets = [];
|
|
574
|
+
const seen = new Set();
|
|
575
|
+
const manual = [];
|
|
576
|
+
const executedActionByTarget = {};
|
|
577
|
+
for (const entry of ledger.entries ?? []) {
|
|
578
|
+
if (entry.reversible === false) {
|
|
579
|
+
manual.push(entry);
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
582
|
+
if (!REVERSAL_BY_TARGET[entry.target]) {
|
|
583
|
+
// A reversible entry with no known handler is surfaced as manual so the
|
|
584
|
+
// operator is never silently left with an un-reverted mutation.
|
|
585
|
+
manual.push(entry);
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
if (
|
|
589
|
+
typeof entry.executedAction === 'string' &&
|
|
590
|
+
executedActionByTarget[entry.target] === undefined
|
|
591
|
+
) {
|
|
592
|
+
executedActionByTarget[entry.target] = entry.executedAction;
|
|
593
|
+
}
|
|
594
|
+
if (!seen.has(entry.target)) {
|
|
595
|
+
seen.add(entry.target);
|
|
596
|
+
fileTargets.push(entry.target);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
return { fileTargets, manual, executedActionByTarget };
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// ---------------------------------------------------------------------------
|
|
603
|
+
// Formatting
|
|
604
|
+
// ---------------------------------------------------------------------------
|
|
605
|
+
|
|
606
|
+
const TARGET_COL = 22;
|
|
607
|
+
|
|
608
|
+
function pad(value, width) {
|
|
609
|
+
const s = String(value);
|
|
610
|
+
return s.length >= width ? s : s + ' '.repeat(width - s.length);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* @param {ReversalOutcome} outcome
|
|
615
|
+
* @returns {string}
|
|
616
|
+
*/
|
|
617
|
+
function formatOutcome(outcome) {
|
|
618
|
+
const icon =
|
|
619
|
+
outcome.kind === 'reverted' ? '✔' : outcome.kind === 'manual' ? '!' : '•';
|
|
620
|
+
const label =
|
|
621
|
+
outcome.kind === 'reverted'
|
|
622
|
+
? 'reverted'
|
|
623
|
+
: outcome.kind === 'manual'
|
|
624
|
+
? 'manual '
|
|
625
|
+
: 'skipped ';
|
|
626
|
+
return `${icon} ${label} ${pad(outcome.target, TARGET_COL)} ${outcome.detail}\n`;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// ---------------------------------------------------------------------------
|
|
630
|
+
// Runner (exported for testing)
|
|
631
|
+
// ---------------------------------------------------------------------------
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Execute the uninstall against a project root.
|
|
635
|
+
*
|
|
636
|
+
* @param {{
|
|
637
|
+
* projectRoot?: string,
|
|
638
|
+
* cwd?: () => string,
|
|
639
|
+
* fsImpl?: typeof fs,
|
|
640
|
+
* write?: (s: string) => void,
|
|
641
|
+
* exit?: (code: number) => void,
|
|
642
|
+
* includeGithub?: boolean,
|
|
643
|
+
* }} [opts]
|
|
644
|
+
* @returns {{ revertedCount: number, manualCount: number, ledgerFound: boolean, parseErrorCount: number }}
|
|
645
|
+
*/
|
|
646
|
+
export function runUninstall({
|
|
647
|
+
projectRoot,
|
|
648
|
+
cwd,
|
|
649
|
+
fsImpl = fs,
|
|
650
|
+
write = (s) => process.stdout.write(s),
|
|
651
|
+
exit = (code) => process.exit(code),
|
|
652
|
+
includeGithub = false,
|
|
653
|
+
} = {}) {
|
|
654
|
+
const root = projectRoot ?? resolveProjectRoot(cwd);
|
|
655
|
+
|
|
656
|
+
let ledger;
|
|
657
|
+
try {
|
|
658
|
+
ledger = readInstallLedger(root);
|
|
659
|
+
} catch (err) {
|
|
660
|
+
write(`❌ Install ledger is unreadable: ${err.message}\n`);
|
|
661
|
+
exit(1);
|
|
662
|
+
return {
|
|
663
|
+
revertedCount: 0,
|
|
664
|
+
manualCount: 0,
|
|
665
|
+
ledgerFound: false,
|
|
666
|
+
parseErrorCount: 0,
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
if (!ledger) {
|
|
671
|
+
write('❌ No install ledger found — nothing to uninstall.\n');
|
|
672
|
+
// A missing ledger is a benign no-op (never installed, or already
|
|
673
|
+
// uninstalled), so this is success, not an error.
|
|
674
|
+
exit(0);
|
|
675
|
+
return {
|
|
676
|
+
revertedCount: 0,
|
|
677
|
+
manualCount: 0,
|
|
678
|
+
ledgerFound: false,
|
|
679
|
+
parseErrorCount: 0,
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
if (ledger.schemaVersion !== LEDGER_SCHEMA_VERSION) {
|
|
684
|
+
write(
|
|
685
|
+
`❌ Install ledger schema v${ledger.schemaVersion} is not supported by this mandrel (expected v${LEDGER_SCHEMA_VERSION}). Upgrade/downgrade mandrel to match, then re-run.\n`,
|
|
686
|
+
);
|
|
687
|
+
exit(1);
|
|
688
|
+
return {
|
|
689
|
+
revertedCount: 0,
|
|
690
|
+
manualCount: 0,
|
|
691
|
+
ledgerFound: true,
|
|
692
|
+
parseErrorCount: 0,
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
const { fileTargets, manual, executedActionByTarget } = planUninstall(ledger);
|
|
697
|
+
|
|
698
|
+
let revertedCount = 0;
|
|
699
|
+
let parseErrorCount = 0;
|
|
700
|
+
for (const target of fileTargets) {
|
|
701
|
+
let outcome;
|
|
702
|
+
try {
|
|
703
|
+
// The third arg carries the recorded `executedAction` for the target
|
|
704
|
+
// (schema v2). Only `revertAgentrc` consults it; the other handlers
|
|
705
|
+
// ignore extra arguments. This is how uninstall avoids deleting a
|
|
706
|
+
// pre-existing `.agentrc.json` the install did not create (Story #3895).
|
|
707
|
+
outcome = REVERSAL_BY_TARGET[target](
|
|
708
|
+
root,
|
|
709
|
+
fsImpl,
|
|
710
|
+
executedActionByTarget[target],
|
|
711
|
+
);
|
|
712
|
+
} catch (err) {
|
|
713
|
+
// An operator-edited file that contains invalid JSON (or any other
|
|
714
|
+
// unexpected throw from the reversal helper) must not abort the whole
|
|
715
|
+
// uninstall and leave earlier targets reverted while later ones are not.
|
|
716
|
+
// Emit a `skipped` outcome so the operator knows they must revert this
|
|
717
|
+
// target by hand, and leave the install ledger intact so a re-run after
|
|
718
|
+
// the file is fixed can resume cleanly.
|
|
719
|
+
outcome = {
|
|
720
|
+
kind: 'skipped',
|
|
721
|
+
target,
|
|
722
|
+
detail: `unparseable — revert manually (${err.message})`,
|
|
723
|
+
};
|
|
724
|
+
parseErrorCount += 1;
|
|
725
|
+
}
|
|
726
|
+
if (outcome.kind === 'reverted') revertedCount += 1;
|
|
727
|
+
write(formatOutcome(outcome));
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
// GitHub-admin (and any unhandled reversible) entries are manual follow-ups.
|
|
731
|
+
// They are NEVER acted on automatically; --include-github only annotates
|
|
732
|
+
// that the operator acknowledged them (remote reversal stays out of scope).
|
|
733
|
+
let manualCount = 0;
|
|
734
|
+
for (const entry of manual) {
|
|
735
|
+
manualCount += 1;
|
|
736
|
+
const note = includeGithub
|
|
737
|
+
? `${entry.detail} (acknowledged — reverse manually via the GitHub UI/API)`
|
|
738
|
+
: `${entry.detail} (left untouched — pass --include-github to acknowledge)`;
|
|
739
|
+
write(
|
|
740
|
+
formatOutcome({ kind: 'manual', target: entry.target, detail: note }),
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
// Remove the ledger last so a re-run is a clean no-op and a partial failure
|
|
745
|
+
// mid-reversal still leaves the ledger for a resume. When any target was
|
|
746
|
+
// skipped due to a parse error, leave the ledger in place so the operator
|
|
747
|
+
// can fix the corrupt file and re-run to complete the uninstall.
|
|
748
|
+
const lp = ledgerPath(root);
|
|
749
|
+
if (fsImpl.existsSync(lp) && parseErrorCount === 0) {
|
|
750
|
+
fsImpl.rmSync(lp, { force: true });
|
|
751
|
+
write(
|
|
752
|
+
formatOutcome({
|
|
753
|
+
kind: 'reverted',
|
|
754
|
+
target: '.agents/.install-manifest.json',
|
|
755
|
+
detail: 'removed install ledger',
|
|
756
|
+
}),
|
|
757
|
+
);
|
|
758
|
+
revertedCount += 1;
|
|
759
|
+
} else if (parseErrorCount > 0 && fsImpl.existsSync(lp)) {
|
|
760
|
+
write(
|
|
761
|
+
formatOutcome({
|
|
762
|
+
kind: 'skipped',
|
|
763
|
+
target: '.agents/.install-manifest.json',
|
|
764
|
+
detail: 'ledger retained — re-run after fixing unparseable file(s)',
|
|
765
|
+
}),
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
write(
|
|
770
|
+
`✅ Uninstalled (${revertedCount} reversed, ${manualCount} manual follow-up${
|
|
771
|
+
manualCount === 1 ? '' : 's'
|
|
772
|
+
})\n`,
|
|
773
|
+
);
|
|
774
|
+
exit(0);
|
|
775
|
+
return { revertedCount, manualCount, ledgerFound: true, parseErrorCount };
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// ---------------------------------------------------------------------------
|
|
779
|
+
// Subcommand entry point (called by bin/mandrel.js)
|
|
780
|
+
// ---------------------------------------------------------------------------
|
|
781
|
+
|
|
782
|
+
/**
|
|
783
|
+
* Default export consumed by `bin/mandrel.js`.
|
|
784
|
+
*
|
|
785
|
+
* @param {string[]} argv — supports the single `--include-github` flag.
|
|
786
|
+
* @returns {Promise<void>}
|
|
787
|
+
*/
|
|
788
|
+
export default async function run(argv = []) {
|
|
789
|
+
const includeGithub = argv.includes('--include-github');
|
|
790
|
+
runUninstall({ includeGithub });
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// Re-export so tests and callers can reference the resolved module path
|
|
794
|
+
// without re-deriving it.
|
|
795
|
+
export const __filenameForTests = fileURLToPath(import.meta.url);
|