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,479 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import escomplex from 'typhonjs-escomplex';
|
|
4
|
+
import { canonicalise as canonicalisePath } from './baselines/path-canon.js';
|
|
5
|
+
import {
|
|
6
|
+
coverageForMethodInEntry,
|
|
7
|
+
findCoverageEntry,
|
|
8
|
+
} from './coverage-utils.js';
|
|
9
|
+
import { runOnPool } from './cpu-pool.js';
|
|
10
|
+
import { crapFormula } from './crap-engine.js';
|
|
11
|
+
import { Logger } from './Logger.js';
|
|
12
|
+
import {
|
|
13
|
+
resolveTsTranspilerVersion,
|
|
14
|
+
scanDirectory,
|
|
15
|
+
transpileIfNeeded,
|
|
16
|
+
} from './maintainability-utils.js';
|
|
17
|
+
|
|
18
|
+
const CRAP_WORKER_URL = new URL('./workers/crap-worker.js', import.meta.url);
|
|
19
|
+
|
|
20
|
+
// Below this batch size the pool's spawn overhead dominates — fall
|
|
21
|
+
// back to in-process serial scoring. The full repo (~200+ files)
|
|
22
|
+
// always takes the pool path; tests with handful-of-files fixtures
|
|
23
|
+
// stay serial and remain byte-identical to the pre-pool output.
|
|
24
|
+
const SERIAL_THRESHOLD = 8;
|
|
25
|
+
// 1.1.0 — TypeScript support landed in 5.29.0. Bumped from 1.0.0 because
|
|
26
|
+
// the scanner now emits CRAP rows for TS/TSX paths that the previous
|
|
27
|
+
// kernel could never reach. The CRAP formula and per-method scoring
|
|
28
|
+
// shape are unchanged for JS sources.
|
|
29
|
+
export const KERNEL_VERSION = '1.1.0';
|
|
30
|
+
export { resolveTsTranspilerVersion };
|
|
31
|
+
|
|
32
|
+
const SCHEMA_REF = '.agents/schemas/crap-baseline.schema.json';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Resolve the running `typhonjs-escomplex` version by walking up from `cwd`
|
|
36
|
+
* and reading the nearest `node_modules/typhonjs-escomplex/package.json`.
|
|
37
|
+
* Returns `'0.0.0'` when the dependency cannot be found — callers treat that
|
|
38
|
+
* sentinel as "unknown environment" and may refuse to persist a baseline.
|
|
39
|
+
*
|
|
40
|
+
* @param {string} [cwd]
|
|
41
|
+
* @returns {string}
|
|
42
|
+
*/
|
|
43
|
+
export function resolveEscomplexVersion(cwd = process.cwd()) {
|
|
44
|
+
let dir = path.resolve(cwd);
|
|
45
|
+
const { root } = path.parse(dir);
|
|
46
|
+
while (true) {
|
|
47
|
+
const pkgPath = path.join(
|
|
48
|
+
dir,
|
|
49
|
+
'node_modules',
|
|
50
|
+
'typhonjs-escomplex',
|
|
51
|
+
'package.json',
|
|
52
|
+
);
|
|
53
|
+
if (fs.existsSync(pkgPath)) {
|
|
54
|
+
try {
|
|
55
|
+
const parsed = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
56
|
+
if (parsed && typeof parsed.version === 'string') {
|
|
57
|
+
return parsed.version;
|
|
58
|
+
}
|
|
59
|
+
} catch {
|
|
60
|
+
// fall through to parent lookup
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (dir === root) break;
|
|
64
|
+
const parent = path.dirname(dir);
|
|
65
|
+
if (parent === dir) break;
|
|
66
|
+
dir = parent;
|
|
67
|
+
}
|
|
68
|
+
return '0.0.0';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function resolveBaselinePath({ cwd = process.cwd(), baselinePath } = {}) {
|
|
72
|
+
if (typeof baselinePath !== 'string' || baselinePath.length === 0) {
|
|
73
|
+
throw new TypeError(
|
|
74
|
+
'crap-utils: opts.baselinePath is required (Epic #730 Story 5.5 — ' +
|
|
75
|
+
'callers resolve the path via getBaselines(config).crap.path).',
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
return path.isAbsolute(baselinePath)
|
|
79
|
+
? baselinePath
|
|
80
|
+
: path.join(cwd, baselinePath);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Load the CRAP baseline envelope from disk.
|
|
85
|
+
*
|
|
86
|
+
* Returns the parsed envelope on success, or `null` when the file is missing,
|
|
87
|
+
* unreadable, or structurally unusable. Version-mismatch detection is a
|
|
88
|
+
* caller concern — this loader never silently rescores or mutates the
|
|
89
|
+
* envelope.
|
|
90
|
+
*
|
|
91
|
+
* @param {{cwd?: string, baselinePath?: string}} [opts]
|
|
92
|
+
* @returns {{
|
|
93
|
+
* kernelVersion: string,
|
|
94
|
+
* escomplexVersion: string,
|
|
95
|
+
* rows: Array<{file: string, method: string, startLine: number, crap: number}>,
|
|
96
|
+
* }|null}
|
|
97
|
+
*/
|
|
98
|
+
/**
|
|
99
|
+
* Story #1895: shipped baseline switched to the canonical envelope shape
|
|
100
|
+
* (`$schema`, `kernelVersion`, `generatedAt`, `rollup`, `rows` keyed on
|
|
101
|
+
* `path`). Backfill the legacy `escomplexVersion`/`tsTranspilerVersion`
|
|
102
|
+
* version fields from the running scorer and re-key rows by `file` so
|
|
103
|
+
* existing comparators keep working until Story #1912 lands the unified
|
|
104
|
+
* gate. Detection probes the first row for the new `path` key — the
|
|
105
|
+
* legacy envelope also carries `$schema` but keys rows by `file`.
|
|
106
|
+
*/
|
|
107
|
+
function projectCrapEnvelopeToLegacy(parsed) {
|
|
108
|
+
if (
|
|
109
|
+
!Array.isArray(parsed.rows) ||
|
|
110
|
+
parsed.rows.length === 0 ||
|
|
111
|
+
typeof parsed.rows[0]?.path !== 'string'
|
|
112
|
+
) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
kernelVersion: parsed.kernelVersion,
|
|
117
|
+
escomplexVersion: resolveEscomplexVersion(),
|
|
118
|
+
tsTranspilerVersion: resolveTsTranspilerVersion(),
|
|
119
|
+
rows: parsed.rows.map((row) => ({
|
|
120
|
+
crap: row.crap,
|
|
121
|
+
file: row.path,
|
|
122
|
+
method: row.method,
|
|
123
|
+
startLine: row.startLine,
|
|
124
|
+
})),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function getCrapBaseline(opts = {}) {
|
|
129
|
+
const filePath = resolveBaselinePath(opts);
|
|
130
|
+
if (!fs.existsSync(filePath)) return null;
|
|
131
|
+
let raw;
|
|
132
|
+
try {
|
|
133
|
+
raw = fs.readFileSync(filePath, 'utf-8');
|
|
134
|
+
} catch (err) {
|
|
135
|
+
Logger.warn(`[crap-utils] unable to read baseline: ${err.message}`);
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
let parsed;
|
|
139
|
+
try {
|
|
140
|
+
parsed = JSON.parse(raw);
|
|
141
|
+
} catch (err) {
|
|
142
|
+
Logger.warn(`[crap-utils] baseline is not valid JSON: ${err.message}`);
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
const projected = projectCrapEnvelopeToLegacy(parsed);
|
|
149
|
+
if (projected) return projected;
|
|
150
|
+
if (typeof parsed.kernelVersion !== 'string') return null;
|
|
151
|
+
if (typeof parsed.escomplexVersion !== 'string') return null;
|
|
152
|
+
if (!Array.isArray(parsed.rows)) return null;
|
|
153
|
+
// tsTranspilerVersion landed in kernel 1.1.0. Older envelopes (1.0.0)
|
|
154
|
+
// do not carry it; we surface that as the sentinel '0.0.0' so the
|
|
155
|
+
// version-drift detector can warn on first 1.1.0 check without
|
|
156
|
+
// crashing on a missing field.
|
|
157
|
+
if (typeof parsed.tsTranspilerVersion !== 'string') {
|
|
158
|
+
parsed.tsTranspilerVersion = '0.0.0';
|
|
159
|
+
}
|
|
160
|
+
return parsed;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Project rich scan rows onto the minimal baseline row shape and assemble an
|
|
165
|
+
* envelope ready for the shared V2 writer.
|
|
166
|
+
*
|
|
167
|
+
* `tsTranspilerVersion` stamps the resolved `typescript` package version so
|
|
168
|
+
* consumers can detect transpiler drift on TS rows. Defaults to the
|
|
169
|
+
* sentinel `'0.0.0'` when typescript is unresolvable — drift detection
|
|
170
|
+
* then becomes a no-op rather than failing the bake.
|
|
171
|
+
*
|
|
172
|
+
* @param {{
|
|
173
|
+
* rows: Array<{file: string, method: string, startLine: number, crap: number|null}>,
|
|
174
|
+
* escomplexVersion: string,
|
|
175
|
+
* kernelVersion?: string,
|
|
176
|
+
* tsTranspilerVersion?: string,
|
|
177
|
+
* }} params
|
|
178
|
+
*/
|
|
179
|
+
export function buildBaselineEnvelope({
|
|
180
|
+
rows,
|
|
181
|
+
escomplexVersion,
|
|
182
|
+
kernelVersion = KERNEL_VERSION,
|
|
183
|
+
tsTranspilerVersion = resolveTsTranspilerVersion(),
|
|
184
|
+
}) {
|
|
185
|
+
if (typeof escomplexVersion !== 'string' || !escomplexVersion) {
|
|
186
|
+
throw new TypeError('buildBaselineEnvelope: escomplexVersion is required');
|
|
187
|
+
}
|
|
188
|
+
const scored = (rows ?? []).filter(
|
|
189
|
+
(r) => typeof r?.crap === 'number' && Number.isFinite(r.crap),
|
|
190
|
+
);
|
|
191
|
+
return {
|
|
192
|
+
$schema: SCHEMA_REF,
|
|
193
|
+
escomplexVersion,
|
|
194
|
+
kernelVersion,
|
|
195
|
+
rows: scored.map((r) => ({
|
|
196
|
+
crap: r.crap,
|
|
197
|
+
file: r.file,
|
|
198
|
+
method: r.method,
|
|
199
|
+
startLine: r.startLine,
|
|
200
|
+
})),
|
|
201
|
+
tsTranspilerVersion,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Parse `source` exactly once with escomplex and derive both the
|
|
207
|
+
* maintainability score and the raw CRAP method rows from that single report.
|
|
208
|
+
*
|
|
209
|
+
* Callers that need both scores for the same source string (e.g. a combined
|
|
210
|
+
* CRAP + MI scan) MUST use this helper rather than calling `calculateCrapForSource`
|
|
211
|
+
* and `calculateForSource` separately — doing so would parse the AST twice.
|
|
212
|
+
*
|
|
213
|
+
* Coverage-dependent CRAP values require a `coverageForFile` entry (the value
|
|
214
|
+
* from `coverage-final.json` for this file). Pass `null` when no coverage is
|
|
215
|
+
* available; method rows whose coverage cannot be resolved will carry
|
|
216
|
+
* `coverage: null` and `crap: null`.
|
|
217
|
+
*
|
|
218
|
+
* @param {string} source Prepared (possibly transpiled) JavaScript source text.
|
|
219
|
+
* @param {object|null} coverageForFile Istanbul coverage entry for this file.
|
|
220
|
+
* @returns {{
|
|
221
|
+
* report: object,
|
|
222
|
+
* miScore: number,
|
|
223
|
+
* crapRows: Array<{
|
|
224
|
+
* method: string,
|
|
225
|
+
* startLine: number,
|
|
226
|
+
* cyclomatic: number,
|
|
227
|
+
* coverage: number|null,
|
|
228
|
+
* crap: number|null,
|
|
229
|
+
* }>,
|
|
230
|
+
* parseError: boolean,
|
|
231
|
+
* }}
|
|
232
|
+
*/
|
|
233
|
+
export function analyzeOnce(source, coverageForFile) {
|
|
234
|
+
let report;
|
|
235
|
+
try {
|
|
236
|
+
report = escomplex.analyzeModule(source);
|
|
237
|
+
} catch {
|
|
238
|
+
return { report: null, miScore: 0, crapRows: [], parseError: true };
|
|
239
|
+
}
|
|
240
|
+
const miScore =
|
|
241
|
+
typeof report.maintainability === 'number' ? report.maintainability : 0;
|
|
242
|
+
const methods = report?.methods ?? [];
|
|
243
|
+
const crapRows = [];
|
|
244
|
+
for (const m of methods) {
|
|
245
|
+
const startLine = m?.lineStart;
|
|
246
|
+
if (typeof startLine !== 'number') continue;
|
|
247
|
+
const cyclomatic = m?.cyclomatic ?? 0;
|
|
248
|
+
const coverage = coverageForFile
|
|
249
|
+
? coverageForMethodInEntry(coverageForFile, startLine)
|
|
250
|
+
: null;
|
|
251
|
+
const crap = coverage === null ? null : crapFormula(cyclomatic, coverage);
|
|
252
|
+
crapRows.push({ method: m.name, startLine, cyclomatic, coverage, crap });
|
|
253
|
+
}
|
|
254
|
+
return { report, miScore, crapRows, parseError: false };
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Scan `targetDirs` for JS files, score each method via the CRAP kernel, and
|
|
259
|
+
* return enriched rows plus skip counters. Does not write to disk.
|
|
260
|
+
*
|
|
261
|
+
* Files without a coverage entry are skipped when `requireCoverage` is `true`
|
|
262
|
+
* (the default); methods whose coverage cannot be resolved are always
|
|
263
|
+
* skipped from the returned rows so the baseline never contains
|
|
264
|
+
* partially-scored entries. Both counters surface for reporting.
|
|
265
|
+
*
|
|
266
|
+
* When `scopeFiles` is provided (the `--changed-since` code path) files
|
|
267
|
+
* discovered via directory walking are filtered against that set before any
|
|
268
|
+
* I/O or scoring happens — so pre-push / PR-CI runs never pay the
|
|
269
|
+
* parse-and-score cost on untouched files.
|
|
270
|
+
*
|
|
271
|
+
* When `preScannedFiles` is provided (an array of absolute paths already
|
|
272
|
+
* collected by a prior `scanDirectory` pass over the same `targetDirs`), the
|
|
273
|
+
* directory walk is skipped entirely — the supplied list is used as-is.
|
|
274
|
+
* Callers that run both CRAP and MI passes over the same target dirs (e.g.
|
|
275
|
+
* `regenerateMainFromTree`) SHOULD pass the MI scan's file list here so the
|
|
276
|
+
* tree is walked only once per run.
|
|
277
|
+
*
|
|
278
|
+
* @param {{
|
|
279
|
+
* targetDirs: string[],
|
|
280
|
+
* coverage: object|null,
|
|
281
|
+
* requireCoverage?: boolean,
|
|
282
|
+
* cwd?: string,
|
|
283
|
+
* scopeFiles?: Set<string>|string[]|null,
|
|
284
|
+
* preScannedFiles?: string[]|null,
|
|
285
|
+
* }} params
|
|
286
|
+
* @returns {{
|
|
287
|
+
* rows: Array<{
|
|
288
|
+
* file: string,
|
|
289
|
+
* method: string,
|
|
290
|
+
* startLine: number,
|
|
291
|
+
* cyclomatic: number,
|
|
292
|
+
* coverage: number,
|
|
293
|
+
* crap: number,
|
|
294
|
+
* }>,
|
|
295
|
+
* scannedFiles: number,
|
|
296
|
+
* skippedFilesNoCoverage: number,
|
|
297
|
+
* skippedMethodsNoCoverage: number,
|
|
298
|
+
* }}
|
|
299
|
+
*/
|
|
300
|
+
export async function scanAndScore({
|
|
301
|
+
targetDirs,
|
|
302
|
+
coverage,
|
|
303
|
+
requireCoverage = true,
|
|
304
|
+
cwd = process.cwd(),
|
|
305
|
+
scopeFiles = null,
|
|
306
|
+
ignoreGlobs = [],
|
|
307
|
+
preScannedFiles = null,
|
|
308
|
+
}) {
|
|
309
|
+
if (!Array.isArray(targetDirs)) {
|
|
310
|
+
throw new TypeError('scanAndScore: targetDirs must be an array');
|
|
311
|
+
}
|
|
312
|
+
const scopeSet =
|
|
313
|
+
scopeFiles == null
|
|
314
|
+
? null
|
|
315
|
+
: scopeFiles instanceof Set
|
|
316
|
+
? scopeFiles
|
|
317
|
+
: new Set(scopeFiles);
|
|
318
|
+
// When the caller supplies a pre-walked file list (e.g. from a prior MI
|
|
319
|
+
// scan over the same target dirs), skip the directory walk entirely.
|
|
320
|
+
const files = preScannedFiles != null ? [...preScannedFiles] : [];
|
|
321
|
+
if (preScannedFiles == null) {
|
|
322
|
+
for (const dir of targetDirs) {
|
|
323
|
+
const abs = path.isAbsolute(dir) ? dir : path.resolve(cwd, dir);
|
|
324
|
+
scanDirectory(abs, files, { cwd, ignoreGlobs });
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
files.sort();
|
|
328
|
+
|
|
329
|
+
// Build the work-queue first so scopeFile filtering happens before
|
|
330
|
+
// any I/O / IPC. `scannedFiles` is the in-scope count.
|
|
331
|
+
// Story #2079: route every relPath through path-canon so a scan from
|
|
332
|
+
// inside `.worktrees/<workspace>/` (with cwd pointing at the main
|
|
333
|
+
// checkout) cannot leak the worktree prefix into the on-disk baseline's
|
|
334
|
+
// `file` / `path` keys downstream.
|
|
335
|
+
const queue = [];
|
|
336
|
+
for (const abs of files) {
|
|
337
|
+
const rawRel = path.relative(cwd, abs).replace(/\\/g, '/');
|
|
338
|
+
const relPath = canonicalisePath(rawRel);
|
|
339
|
+
if (scopeSet && !scopeSet.has(relPath)) continue;
|
|
340
|
+
queue.push({ abs, relPath, requireCoverage });
|
|
341
|
+
}
|
|
342
|
+
const scannedFiles = queue.length;
|
|
343
|
+
|
|
344
|
+
const perFile =
|
|
345
|
+
queue.length < SERIAL_THRESHOLD
|
|
346
|
+
? queue.map((item) => ({ item, result: scoreFileSerial(item, coverage) }))
|
|
347
|
+
: await scoreFilesViaPool(queue, coverage);
|
|
348
|
+
|
|
349
|
+
const rows = [];
|
|
350
|
+
let skippedFilesNoCoverage = 0;
|
|
351
|
+
let skippedMethodsNoCoverage = 0;
|
|
352
|
+
for (const { item, result } of perFile) {
|
|
353
|
+
if (!result) continue; // unrecoverable per-file failure: drop silently to match pre-pool semantics
|
|
354
|
+
if (result.skippedFileNoCoverage) {
|
|
355
|
+
skippedFilesNoCoverage += 1;
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
if (result.rows === null) {
|
|
359
|
+
// read/transpile/parse failure: drop and move on, but if the worker
|
|
360
|
+
// attached an error message (calculateCrapForSource throw) surface it
|
|
361
|
+
// so the run isn't silent on the ops side.
|
|
362
|
+
if (result.error) {
|
|
363
|
+
Logger.warn(
|
|
364
|
+
`[crap-utils] failed to score ${item.relPath}: ${result.error}`,
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
skippedMethodsNoCoverage += result.skippedMethodsNoCoverage ?? 0;
|
|
370
|
+
for (const mr of result.rows) {
|
|
371
|
+
rows.push({
|
|
372
|
+
file: item.relPath,
|
|
373
|
+
method: mr.method,
|
|
374
|
+
startLine: mr.startLine,
|
|
375
|
+
cyclomatic: mr.cyclomatic,
|
|
376
|
+
coverage: mr.coverage,
|
|
377
|
+
crap: mr.crap,
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
rows.sort((a, b) => {
|
|
383
|
+
if (a.file !== b.file) return a.file < b.file ? -1 : 1;
|
|
384
|
+
if (a.startLine !== b.startLine) return a.startLine - b.startLine;
|
|
385
|
+
if (a.method !== b.method) return a.method < b.method ? -1 : 1;
|
|
386
|
+
return 0;
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
return {
|
|
390
|
+
rows,
|
|
391
|
+
scannedFiles,
|
|
392
|
+
skippedFilesNoCoverage,
|
|
393
|
+
skippedMethodsNoCoverage,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* In-process scorer used by both the small-batch fast path and as the
|
|
399
|
+
* reference implementation against which the worker output is asserted
|
|
400
|
+
* byte-for-byte in the cpu-pool tests.
|
|
401
|
+
*
|
|
402
|
+
* Uses `analyzeOnce` so the source is parsed a single time and both the
|
|
403
|
+
* CRAP rows and the MI score are derived from the same escomplex report.
|
|
404
|
+
*/
|
|
405
|
+
function scoreFileSerial({ abs, relPath, requireCoverage }, coverage) {
|
|
406
|
+
const entry = findCoverageEntry(coverage, relPath);
|
|
407
|
+
if (requireCoverage && entry === null) {
|
|
408
|
+
return {
|
|
409
|
+
skippedFileNoCoverage: true,
|
|
410
|
+
rows: [],
|
|
411
|
+
skippedMethodsNoCoverage: 0,
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
let source;
|
|
415
|
+
try {
|
|
416
|
+
source = fs.readFileSync(abs, 'utf-8');
|
|
417
|
+
} catch {
|
|
418
|
+
return {
|
|
419
|
+
skippedFileNoCoverage: false,
|
|
420
|
+
rows: null,
|
|
421
|
+
skippedMethodsNoCoverage: 0,
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
const prepared = transpileIfNeeded(abs, source);
|
|
425
|
+
if (prepared === null) {
|
|
426
|
+
return {
|
|
427
|
+
skippedFileNoCoverage: false,
|
|
428
|
+
rows: null,
|
|
429
|
+
skippedMethodsNoCoverage: 0,
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
const { crapRows, parseError } = analyzeOnce(prepared, entry);
|
|
433
|
+
if (parseError) {
|
|
434
|
+
return {
|
|
435
|
+
skippedFileNoCoverage: false,
|
|
436
|
+
rows: null,
|
|
437
|
+
skippedMethodsNoCoverage: 0,
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
const rows = [];
|
|
441
|
+
let skippedMethodsNoCoverage = 0;
|
|
442
|
+
for (const mr of crapRows) {
|
|
443
|
+
if (mr.crap === null || mr.coverage === null) {
|
|
444
|
+
skippedMethodsNoCoverage += 1;
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
rows.push({
|
|
448
|
+
method: mr.method,
|
|
449
|
+
startLine: mr.startLine,
|
|
450
|
+
cyclomatic: mr.cyclomatic,
|
|
451
|
+
coverage: mr.coverage,
|
|
452
|
+
crap: mr.crap,
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
return { skippedFileNoCoverage: false, rows, skippedMethodsNoCoverage };
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
async function scoreFilesViaPool(queue, coverage) {
|
|
459
|
+
// Resolve each file's coverage entry on the host before dispatch so workers
|
|
460
|
+
// receive only their file's entry rather than the whole map. This removes the
|
|
461
|
+
// O(workers × coverageMapSize) structured-clone at spawn time.
|
|
462
|
+
const enrichedQueue = queue.map((item) => ({
|
|
463
|
+
...item,
|
|
464
|
+
coverageEntry: findCoverageEntry(coverage, item.relPath),
|
|
465
|
+
}));
|
|
466
|
+
const results = await runOnPool(CRAP_WORKER_URL, enrichedQueue, {
|
|
467
|
+
workerData: {},
|
|
468
|
+
});
|
|
469
|
+
return results.map((r, i) => {
|
|
470
|
+
const item = queue[i];
|
|
471
|
+
if (!r || r.__cpuPoolError) {
|
|
472
|
+
Logger.warn(
|
|
473
|
+
`[crap-utils] worker pool error for ${item.relPath}: ${r?.message ?? 'unknown'}`,
|
|
474
|
+
);
|
|
475
|
+
return { item, result: null };
|
|
476
|
+
}
|
|
477
|
+
return { item, result: r };
|
|
478
|
+
});
|
|
479
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helper for the explicit-degraded contract used by soft-failing gates.
|
|
3
|
+
*
|
|
4
|
+
* Tech Spec #819 §"Degraded-mode contract (Story 3)" — three soft-fail sites
|
|
5
|
+
* (select-audits diff-timeout, lint-baseline JSON-parse, baseline-refresh
|
|
6
|
+
* guardrail git-diff) historically returned a silent zero/empty result. The
|
|
7
|
+
* new contract is:
|
|
8
|
+
*
|
|
9
|
+
* { ok: false, degraded: true, reason: <code>, detail: <human> }
|
|
10
|
+
*
|
|
11
|
+
* with a non-zero CLI exit so the operator/agent has explicit visibility, OR
|
|
12
|
+
* a hard-fail closed when `--gate-mode` / `MANDREL_GATE_MODE=1` is set
|
|
13
|
+
* (CI invocations).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Build the canonical degraded envelope.
|
|
18
|
+
*
|
|
19
|
+
* @param {string} reason Machine-readable code (e.g. `GIT_DIFF_TIMEOUT`).
|
|
20
|
+
* @param {string} [detail] Human-readable explanation for operators.
|
|
21
|
+
* @returns {{ ok: false, degraded: true, reason: string, detail: string }}
|
|
22
|
+
*/
|
|
23
|
+
export function degraded(reason, detail = '') {
|
|
24
|
+
return { ok: false, degraded: true, reason, detail };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* True when `value` carries the degraded envelope shape.
|
|
29
|
+
*/
|
|
30
|
+
export function isDegraded(value) {
|
|
31
|
+
return Boolean(
|
|
32
|
+
value &&
|
|
33
|
+
typeof value === 'object' &&
|
|
34
|
+
value.ok === false &&
|
|
35
|
+
value.degraded === true &&
|
|
36
|
+
typeof value.reason === 'string',
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Decide whether the caller is running in gate-mode (hard-fail closed) based
|
|
42
|
+
* on argv and env. CI invocations set `--gate-mode` or
|
|
43
|
+
* `MANDREL_GATE_MODE=1`; local invocations leave both unset.
|
|
44
|
+
*/
|
|
45
|
+
export function isGateMode({ argv = process.argv, env = process.env } = {}) {
|
|
46
|
+
if (Array.isArray(argv) && argv.includes('--gate-mode')) return true;
|
|
47
|
+
if (env && env.MANDREL_GATE_MODE === '1') return true;
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* In gate-mode, throw a hard-fail Error keyed to `reason`. Otherwise return
|
|
53
|
+
* the degraded envelope. Centralises the if-gate-mode branch so each site has
|
|
54
|
+
* a single call site.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} reason
|
|
57
|
+
* @param {string} [detail]
|
|
58
|
+
* @param {{ argv?: string[], env?: NodeJS.ProcessEnv }} [opts]
|
|
59
|
+
* @returns {{ ok: false, degraded: true, reason: string, detail: string }}
|
|
60
|
+
*/
|
|
61
|
+
export function softFailOrThrow(reason, detail = '', opts) {
|
|
62
|
+
if (isGateMode(opts)) {
|
|
63
|
+
const err = new Error(`[gate-mode] hard-fail: ${reason}: ${detail}`);
|
|
64
|
+
err.code = reason;
|
|
65
|
+
err.degraded = true;
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
return degraded(reason, detail);
|
|
69
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dependency-parser.js — Shared Dependency & Metadata Parsing Utilities
|
|
3
|
+
*
|
|
4
|
+
* Canonical implementation of dependency-related regex parsing and
|
|
5
|
+
* ticket metadata extraction. Eliminates duplicated implementations
|
|
6
|
+
* across dispatcher.js, verify-prereqs.js, and providers/github.js.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Parse `blocked by #NNN` and `depends on #NNN` references from text.
|
|
11
|
+
* Handles case-insensitive variations.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} body - Issue body or freeform text.
|
|
14
|
+
* @returns {number[]} Array of issue numbers this text declares as blockers.
|
|
15
|
+
*/
|
|
16
|
+
export function parseBlockedBy(body) {
|
|
17
|
+
if (!body) return [];
|
|
18
|
+
const re = /(?:blocked\s+by|depends\s+on):?\s+#(\d+)/gi;
|
|
19
|
+
const ids = [...body.matchAll(re)].map((m) => Number.parseInt(m[1], 10));
|
|
20
|
+
return [...new Set(ids)];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Parse `blocks #NNN` references from text.
|
|
25
|
+
*
|
|
26
|
+
* @param {string} body - Issue body or freeform text.
|
|
27
|
+
* @returns {number[]} Array of issue numbers this text declares as blocked.
|
|
28
|
+
*/
|
|
29
|
+
export function parseBlocks(body) {
|
|
30
|
+
if (!body) return [];
|
|
31
|
+
const re = /blocks\s+#(\d+)/gi;
|
|
32
|
+
return [...body.matchAll(re)].map((m) => Number.parseInt(m[1], 10));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Extract the parent Epic id from a ticket body. Matches `Epic: #NNN`
|
|
37
|
+
* anchored to the start of a line (multiline + case-insensitive). The
|
|
38
|
+
* anchored form prevents accidental matches inside prose ("...this Epic:
|
|
39
|
+
* #...follow-on..."). Used during state-transition notification dispatch
|
|
40
|
+
* and Story-level execution planning.
|
|
41
|
+
*
|
|
42
|
+
* @param {string|null|undefined} body
|
|
43
|
+
* @returns {number|null}
|
|
44
|
+
*/
|
|
45
|
+
export function extractEpicIdFromBody(body) {
|
|
46
|
+
if (!body) return null;
|
|
47
|
+
const m = body.match(/^Epic:\s*#(\d+)/im);
|
|
48
|
+
return m ? Number.parseInt(m[1], 10) : null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Validates that a string is safe to use as a git branch name component.
|
|
53
|
+
* Rejects shell metacharacters, whitespace, and other dangerous patterns.
|
|
54
|
+
*
|
|
55
|
+
* @param {string} value - The value to validate.
|
|
56
|
+
* @returns {boolean} True if safe for use in branch names.
|
|
57
|
+
*/
|
|
58
|
+
export function isSafeBranchComponent(value) {
|
|
59
|
+
// Allow: alphanumeric, hyphens, underscores, dots, forward slashes
|
|
60
|
+
// Reject: everything else (shell metacharacters, spaces, etc.)
|
|
61
|
+
return /^[a-zA-Z0-9._\-/]+$/.test(value);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Pre-compiled `**Key**: value` matchers for every metadata key we extract.
|
|
66
|
+
* Construction cost is paid once at module load rather than per task.
|
|
67
|
+
*/
|
|
68
|
+
const METADATA_FIELD_KEYS = [
|
|
69
|
+
'Persona',
|
|
70
|
+
'Mode',
|
|
71
|
+
'Skills',
|
|
72
|
+
'Focus Areas',
|
|
73
|
+
'Protocol Version',
|
|
74
|
+
];
|
|
75
|
+
const METADATA_FIELD_RES = new Map(
|
|
76
|
+
METADATA_FIELD_KEYS.map((k) => [
|
|
77
|
+
k,
|
|
78
|
+
new RegExp(`\\*\\*${k}\\*\\*\\s*:?\\s*(.+)`, 'i'),
|
|
79
|
+
]),
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Parse task execution metadata from the `## Metadata` section of a ticket body.
|
|
84
|
+
* Returns a plain object with `persona`, `mode`, `skills`, `focusAreas`,
|
|
85
|
+
* and `protocolVersion`.
|
|
86
|
+
*
|
|
87
|
+
* @param {string} body - Issue body text.
|
|
88
|
+
* @returns {{ persona: string, mode: string, skills: string[], focusAreas: string[], protocolVersion: string }}
|
|
89
|
+
*/
|
|
90
|
+
export function parseTaskMetadata(body) {
|
|
91
|
+
const defaults = {
|
|
92
|
+
persona: 'engineer',
|
|
93
|
+
mode: 'fast',
|
|
94
|
+
skills: [],
|
|
95
|
+
focusAreas: [],
|
|
96
|
+
protocolVersion: '',
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
if (!body) return defaults;
|
|
100
|
+
|
|
101
|
+
const metaMatch = body.match(/##\s*Metadata\s*([\s\S]*?)(?=\n##|$)/i);
|
|
102
|
+
if (!metaMatch) return defaults;
|
|
103
|
+
|
|
104
|
+
const block = metaMatch[1];
|
|
105
|
+
|
|
106
|
+
function extractField(key) {
|
|
107
|
+
const re = METADATA_FIELD_RES.get(key);
|
|
108
|
+
const m = re ? block.match(re) : null;
|
|
109
|
+
return m ? m[1].trim() : null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function extractList(key) {
|
|
113
|
+
const raw = extractField(key);
|
|
114
|
+
if (!raw) return [];
|
|
115
|
+
return raw
|
|
116
|
+
.split(',')
|
|
117
|
+
.map((s) => s.trim())
|
|
118
|
+
.filter(Boolean);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
persona: extractField('Persona') || defaults.persona,
|
|
123
|
+
mode: extractField('Mode') || defaults.mode,
|
|
124
|
+
skills: extractList('Skills'),
|
|
125
|
+
focusAreas: extractList('Focus Areas'),
|
|
126
|
+
protocolVersion:
|
|
127
|
+
extractField('Protocol Version') || defaults.protocolVersion,
|
|
128
|
+
};
|
|
129
|
+
}
|