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,663 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// .agents/scripts/check-gherkin-placeholders.js
|
|
4
|
+
//
|
|
5
|
+
// Story #3426 (Epic #3418) — Gherkin placeholder-reference lint validator.
|
|
6
|
+
//
|
|
7
|
+
// Scans every `*.feature` file under the canonical BDD roots
|
|
8
|
+
// (`tests/features/**` by default) and validates that every
|
|
9
|
+
// `Scenario Outline` `<placeholder>` is actually consumed by the
|
|
10
|
+
// assertion of the step definition it binds to. A placeholder that is
|
|
11
|
+
// declared in the Examples header and threaded through a step's prose but
|
|
12
|
+
// whose bound step definition never references the captured parameter is a
|
|
13
|
+
// tautological test — the Examples column varies but the assertion ignores
|
|
14
|
+
// it, so every row passes vacuously. This validator flags that gap.
|
|
15
|
+
//
|
|
16
|
+
// The detection model:
|
|
17
|
+
//
|
|
18
|
+
// 1. Parse each `.feature` file into Scenario Outline blocks. For each
|
|
19
|
+
// Outline, collect the set of `<placeholder>` tokens that appear in
|
|
20
|
+
// its steps and the column headers declared in its `Examples` table.
|
|
21
|
+
// Only placeholders that are BOTH used in a step and declared as an
|
|
22
|
+
// Examples column are in scope (a `<placeholder>` with no Examples
|
|
23
|
+
// column is a separate authoring error out of this check's lane).
|
|
24
|
+
//
|
|
25
|
+
// 2. For each Outline step containing a placeholder, resolve the bound
|
|
26
|
+
// step definition by matching the step text (with `<placeholder>`
|
|
27
|
+
// tokens collapsed to a sentinel) against the step-definition patterns
|
|
28
|
+
// discovered in the steps tree (`tests/steps/**` by default). The step
|
|
29
|
+
// definition's named parameters are the channel through which an
|
|
30
|
+
// Examples value reaches an assertion.
|
|
31
|
+
//
|
|
32
|
+
// 3. A placeholder is "consumed" when its bound step definition's body
|
|
33
|
+
// references the parameter that carries it — i.e. the step-def
|
|
34
|
+
// function reads the captured argument inside an assertion (and is not
|
|
35
|
+
// a tautological no-op such as `expect(true).toBe(true)`). A
|
|
36
|
+
// placeholder that threads only into a step whose definition ignores
|
|
37
|
+
// the captured value is flagged.
|
|
38
|
+
//
|
|
39
|
+
// This mirrors `.agents/scripts/check-doc-links.js`: same fence-masking of
|
|
40
|
+
// non-Gherkin regions, same per-file violation-collecting shape
|
|
41
|
+
// (`{ file, line, kind, message }`), same `{ exitCode, violations,
|
|
42
|
+
// scanned }` programmatic return, and the same CLI exit-code contract.
|
|
43
|
+
//
|
|
44
|
+
// Exit codes:
|
|
45
|
+
// 0 every Scenario-Outline placeholder is consumed by its bound step
|
|
46
|
+
// definition's assertion.
|
|
47
|
+
// 1 at least one placeholder is unconsumed (tautological); details are
|
|
48
|
+
// written to stderr (file:line).
|
|
49
|
+
//
|
|
50
|
+
// Helpers are intentionally inlined per the sibling validator's design
|
|
51
|
+
// constraint.
|
|
52
|
+
|
|
53
|
+
import fs from 'node:fs';
|
|
54
|
+
import path from 'node:path';
|
|
55
|
+
import { fileURLToPath } from 'node:url';
|
|
56
|
+
import { runAsCli } from './lib/cli-utils.js';
|
|
57
|
+
import { Logger } from './lib/Logger.js';
|
|
58
|
+
|
|
59
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
60
|
+
const __dirname = path.dirname(__filename);
|
|
61
|
+
const REPO_ROOT = path.resolve(__dirname, '..', '..');
|
|
62
|
+
|
|
63
|
+
// --- Static config ---------------------------------------------------------
|
|
64
|
+
|
|
65
|
+
// Canonical BDD roots, repo-root-relative. `tests/features` holds the
|
|
66
|
+
// `.feature` scenarios; `tests/steps` holds the step-definition library.
|
|
67
|
+
// Mirrors the layout in `.agents/rules/testing-standards.md` and the
|
|
68
|
+
// `gherkin-authoring` skill.
|
|
69
|
+
export const DEFAULT_FEATURE_ROOTS = ['tests/features'];
|
|
70
|
+
export const DEFAULT_STEP_ROOTS = ['tests/steps'];
|
|
71
|
+
|
|
72
|
+
// Step-definition source extensions to scan.
|
|
73
|
+
const STEP_DEF_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs']);
|
|
74
|
+
|
|
75
|
+
// --- File discovery --------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
function walkFiles(dirAbs, predicate, out) {
|
|
78
|
+
let entries;
|
|
79
|
+
try {
|
|
80
|
+
entries = fs.readdirSync(dirAbs, { withFileTypes: true });
|
|
81
|
+
} catch (_err) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
for (const entry of entries) {
|
|
85
|
+
const abs = path.join(dirAbs, entry.name);
|
|
86
|
+
if (entry.isDirectory()) {
|
|
87
|
+
if (entry.name === 'node_modules' || entry.name === '.git') continue;
|
|
88
|
+
walkFiles(abs, predicate, out);
|
|
89
|
+
} else if (entry.isFile() && predicate(entry.name)) {
|
|
90
|
+
out.push(abs);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function discoverFeatures(rootAbs, featureRoots) {
|
|
96
|
+
const out = [];
|
|
97
|
+
for (const sub of featureRoots) {
|
|
98
|
+
const subAbs = path.join(rootAbs, sub);
|
|
99
|
+
if (fs.existsSync(subAbs)) {
|
|
100
|
+
walkFiles(subAbs, (name) => name.endsWith('.feature'), out);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
out.sort();
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function discoverStepDefs(rootAbs, stepRoots) {
|
|
108
|
+
const out = [];
|
|
109
|
+
for (const sub of stepRoots) {
|
|
110
|
+
const subAbs = path.join(rootAbs, sub);
|
|
111
|
+
if (fs.existsSync(subAbs)) {
|
|
112
|
+
walkFiles(
|
|
113
|
+
subAbs,
|
|
114
|
+
(name) => STEP_DEF_EXTENSIONS.has(path.extname(name)),
|
|
115
|
+
out,
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
out.sort();
|
|
120
|
+
return out;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// --- Region masking --------------------------------------------------------
|
|
124
|
+
|
|
125
|
+
// Returns a copy of `source` where the contents of every fenced doc-string
|
|
126
|
+
// region (Gherkin triple-quote or triple-backtick) are replaced by blank
|
|
127
|
+
// lines. Newlines are preserved so downstream line numbers stay aligned.
|
|
128
|
+
// This prevents prose inside a doc-string argument from being parsed as
|
|
129
|
+
// steps or placeholders.
|
|
130
|
+
export function maskDocStrings(source) {
|
|
131
|
+
const lines = source.split('\n');
|
|
132
|
+
const out = new Array(lines.length);
|
|
133
|
+
let inDoc = false;
|
|
134
|
+
let marker = '';
|
|
135
|
+
for (let i = 0; i < lines.length; i++) {
|
|
136
|
+
const line = lines[i];
|
|
137
|
+
const fenceMatch = line.match(/^(\s*)("""|```|~~~)/);
|
|
138
|
+
if (inDoc) {
|
|
139
|
+
out[i] = '';
|
|
140
|
+
if (fenceMatch && fenceMatch[2] === marker) {
|
|
141
|
+
inDoc = false;
|
|
142
|
+
marker = '';
|
|
143
|
+
}
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (fenceMatch) {
|
|
147
|
+
inDoc = true;
|
|
148
|
+
marker = fenceMatch[2];
|
|
149
|
+
out[i] = '';
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
out[i] = line;
|
|
153
|
+
}
|
|
154
|
+
return out.join('\n');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// --- Feature parsing -------------------------------------------------------
|
|
158
|
+
|
|
159
|
+
const PLACEHOLDER_RE = /<([^<>]+)>/g;
|
|
160
|
+
|
|
161
|
+
export function extractPlaceholders(text) {
|
|
162
|
+
const out = [];
|
|
163
|
+
PLACEHOLDER_RE.lastIndex = 0;
|
|
164
|
+
let m;
|
|
165
|
+
// biome-ignore lint/suspicious/noAssignInExpressions: idiomatic regex loop
|
|
166
|
+
while ((m = PLACEHOLDER_RE.exec(text)) !== null) {
|
|
167
|
+
out.push(m[1].trim());
|
|
168
|
+
}
|
|
169
|
+
return out;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// A step keyword line: Given / When / Then / And / But / *.
|
|
173
|
+
const STEP_LINE_RE = /^\s*(Given|When|Then|And|But|\*)\s+(.*\S)\s*$/;
|
|
174
|
+
|
|
175
|
+
// Parse a masked `.feature` source into an array of Scenario Outline blocks.
|
|
176
|
+
// Each block: { line, steps: [{ line, text }], exampleHeaders: Set<string> }.
|
|
177
|
+
// Only `Scenario Outline:` blocks are returned; plain `Scenario:` blocks are
|
|
178
|
+
// ignored because they cannot carry `<placeholders>`.
|
|
179
|
+
export function parseOutlines(masked) {
|
|
180
|
+
const lines = masked.split('\n');
|
|
181
|
+
const outlines = [];
|
|
182
|
+
let current = null;
|
|
183
|
+
let inExamples = false;
|
|
184
|
+
|
|
185
|
+
for (let i = 0; i < lines.length; i++) {
|
|
186
|
+
const raw = lines[i];
|
|
187
|
+
const lineNo = i + 1;
|
|
188
|
+
const trimmed = raw.trim();
|
|
189
|
+
|
|
190
|
+
if (/^Scenario Outline:/i.test(trimmed)) {
|
|
191
|
+
current = { line: lineNo, steps: [], exampleHeaders: new Set() };
|
|
192
|
+
outlines.push(current);
|
|
193
|
+
inExamples = false;
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// A new Scenario / Feature / Background / Rule ends the current outline's
|
|
198
|
+
// step-collection scope.
|
|
199
|
+
if (
|
|
200
|
+
/^(Scenario:|Feature:|Background:|Rule:|Scenario Template:)/i.test(
|
|
201
|
+
trimmed,
|
|
202
|
+
)
|
|
203
|
+
) {
|
|
204
|
+
current = null;
|
|
205
|
+
inExamples = false;
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (!current) continue;
|
|
210
|
+
|
|
211
|
+
if (/^(Examples|Scenarios):/i.test(trimmed)) {
|
|
212
|
+
inExamples = true;
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (inExamples) {
|
|
217
|
+
// The first non-blank table row inside an Examples block is the header.
|
|
218
|
+
if (trimmed.startsWith('|') && current.exampleHeaders.size === 0) {
|
|
219
|
+
const cells = trimmed
|
|
220
|
+
.split('|')
|
|
221
|
+
.map((c) => c.trim())
|
|
222
|
+
.filter((c) => c.length > 0);
|
|
223
|
+
for (const cell of cells) current.exampleHeaders.add(cell);
|
|
224
|
+
}
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const stepMatch = raw.match(STEP_LINE_RE);
|
|
229
|
+
if (stepMatch) {
|
|
230
|
+
current.steps.push({ line: lineNo, text: stepMatch[2].trim() });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return outlines;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// --- Step-definition indexing ----------------------------------------------
|
|
238
|
+
|
|
239
|
+
// Extract step-definition entries from a step-def source file. Each entry:
|
|
240
|
+
// { pattern: RegExp, paramNames: string[], body: string }
|
|
241
|
+
//
|
|
242
|
+
// We support the two dominant authoring styles:
|
|
243
|
+
// - Cucumber-expression strings: Given('the {actor} has {int} invoices', fn)
|
|
244
|
+
// {name} tokens become capture groups; `paramNames` records the names.
|
|
245
|
+
// - Regular-expression literals: Given(/^the (.+) has (\d+)/, fn)
|
|
246
|
+
// numbered capture groups; `paramNames` records `$1`, `$2`, ... markers.
|
|
247
|
+
//
|
|
248
|
+
// The body is the text of the handler function (best-effort), used to decide
|
|
249
|
+
// whether a captured parameter is referenced by the assertion.
|
|
250
|
+
export function parseStepDefs(source) {
|
|
251
|
+
const defs = [];
|
|
252
|
+
const callRe =
|
|
253
|
+
/\b(Given|When|Then|And|But|defineStep|Step)\s*\(\s*(['"`]|\/)/g;
|
|
254
|
+
let m;
|
|
255
|
+
// biome-ignore lint/suspicious/noAssignInExpressions: idiomatic regex loop
|
|
256
|
+
while ((m = callRe.exec(source)) !== null) {
|
|
257
|
+
const opener = m[2];
|
|
258
|
+
const patStart = m.index + m[0].length - opener.length;
|
|
259
|
+
const parsed =
|
|
260
|
+
opener === '/'
|
|
261
|
+
? readRegexLiteral(source, patStart)
|
|
262
|
+
: readStringLiteral(source, patStart, opener);
|
|
263
|
+
if (!parsed) continue;
|
|
264
|
+
|
|
265
|
+
const { raw: patternRaw, end: patternEnd } = parsed;
|
|
266
|
+
const handlerParams = readHandlerParams(source, patternEnd);
|
|
267
|
+
const body = readHandlerBody(source, patternEnd);
|
|
268
|
+
const built =
|
|
269
|
+
opener === '/'
|
|
270
|
+
? buildFromRegex(patternRaw)
|
|
271
|
+
: buildFromExpression(patternRaw);
|
|
272
|
+
if (!built) continue;
|
|
273
|
+
defs.push({ ...built, handlerParams, body });
|
|
274
|
+
}
|
|
275
|
+
return defs;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Read the handler's formal parameter names from the function expression that
|
|
279
|
+
// follows the step pattern. Supports arrow functions (`(a, b) => {`,
|
|
280
|
+
// `a => {`) and classic functions (`function (a, b) {`). Returns the ordered
|
|
281
|
+
// list of bare identifier parameter names (skipping destructured/rest forms
|
|
282
|
+
// we cannot map positionally). Capture group N binds to handler param N, so
|
|
283
|
+
// this list is the channel from an Examples value to an assertion.
|
|
284
|
+
function readHandlerParams(source, patternEnd) {
|
|
285
|
+
// Skip the comma + whitespace separating the pattern from the handler.
|
|
286
|
+
const rest = source.slice(patternEnd, patternEnd + 400);
|
|
287
|
+
// `function name? ( ... )` or `( ... ) =>` or `singleArg =>`.
|
|
288
|
+
let sigMatch = rest.match(
|
|
289
|
+
/^\s*,\s*(?:async\s+)?function\s*\w*\s*\(([^)]*)\)/,
|
|
290
|
+
);
|
|
291
|
+
if (!sigMatch) sigMatch = rest.match(/^\s*,\s*(?:async\s+)?\(([^)]*)\)\s*=>/);
|
|
292
|
+
if (!sigMatch) {
|
|
293
|
+
const single = rest.match(/^\s*,\s*(?:async\s+)?([A-Za-z_$][\w$]*)\s*=>/);
|
|
294
|
+
if (single) return [single[1]];
|
|
295
|
+
return [];
|
|
296
|
+
}
|
|
297
|
+
return sigMatch[1]
|
|
298
|
+
.split(',')
|
|
299
|
+
.map((p) => p.trim())
|
|
300
|
+
.filter((p) => /^[A-Za-z_$][\w$]*$/.test(p));
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Read a quoted string literal starting at `start` (pointing at the opening
|
|
304
|
+
// quote). Returns { raw, end } where `raw` excludes the quotes and `end` is
|
|
305
|
+
// the index just past the closing quote.
|
|
306
|
+
function readStringLiteral(source, start, quote) {
|
|
307
|
+
let i = start + 1;
|
|
308
|
+
let out = '';
|
|
309
|
+
while (i < source.length) {
|
|
310
|
+
const ch = source[i];
|
|
311
|
+
if (ch === '\\') {
|
|
312
|
+
out += source[i + 1] ?? '';
|
|
313
|
+
i += 2;
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
if (ch === quote) return { raw: out, end: i + 1 };
|
|
317
|
+
out += ch;
|
|
318
|
+
i++;
|
|
319
|
+
}
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Read a regex literal starting at `start` (pointing at the opening slash).
|
|
324
|
+
function readRegexLiteral(source, start) {
|
|
325
|
+
let i = start + 1;
|
|
326
|
+
let out = '';
|
|
327
|
+
let inClass = false;
|
|
328
|
+
while (i < source.length) {
|
|
329
|
+
const ch = source[i];
|
|
330
|
+
if (ch === '\\') {
|
|
331
|
+
out += ch + (source[i + 1] ?? '');
|
|
332
|
+
i += 2;
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
if (ch === '[') inClass = true;
|
|
336
|
+
else if (ch === ']') inClass = false;
|
|
337
|
+
else if (ch === '/' && !inClass) return { raw: out, end: i + 1 };
|
|
338
|
+
else if (ch === '\n') return null;
|
|
339
|
+
out += ch;
|
|
340
|
+
i++;
|
|
341
|
+
}
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Read the handler body text following the pattern. Best-effort: from the
|
|
346
|
+
// first `{` after the pattern to its matching `}`. Falls back to a bounded
|
|
347
|
+
// window when no brace block is found (e.g. arrow shorthand).
|
|
348
|
+
function readHandlerBody(source, patternEnd) {
|
|
349
|
+
const braceIdx = source.indexOf('{', patternEnd);
|
|
350
|
+
const window = source.slice(patternEnd, patternEnd + 4000);
|
|
351
|
+
if (braceIdx === -1 || braceIdx > patternEnd + 400) {
|
|
352
|
+
// Arrow shorthand `(...) => expr` — return the bounded window.
|
|
353
|
+
return window;
|
|
354
|
+
}
|
|
355
|
+
let depth = 0;
|
|
356
|
+
for (let i = braceIdx; i < source.length; i++) {
|
|
357
|
+
const ch = source[i];
|
|
358
|
+
if (ch === '{') depth++;
|
|
359
|
+
else if (ch === '}') {
|
|
360
|
+
depth--;
|
|
361
|
+
if (depth === 0) return source.slice(braceIdx, i + 1);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return source.slice(braceIdx);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Build a matcher from a Cucumber-expression string. {name} parameter tokens
|
|
368
|
+
// become capture groups; the surrounding literal text is escaped.
|
|
369
|
+
function buildFromExpression(expr) {
|
|
370
|
+
const paramNames = [];
|
|
371
|
+
let pattern = '^';
|
|
372
|
+
let i = 0;
|
|
373
|
+
while (i < expr.length) {
|
|
374
|
+
const ch = expr[i];
|
|
375
|
+
if (ch === '{') {
|
|
376
|
+
const close = expr.indexOf('}', i);
|
|
377
|
+
if (close === -1) {
|
|
378
|
+
pattern += escapeRegex(ch);
|
|
379
|
+
i++;
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
const name = expr.slice(i + 1, close).trim();
|
|
383
|
+
paramNames.push(name || `arg${paramNames.length + 1}`);
|
|
384
|
+
pattern += '(.+?)';
|
|
385
|
+
i = close + 1;
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
if (ch === '(' && expr[i + 1] === ')') {
|
|
389
|
+
// Optional-text cucumber syntax `text(s)` — make the preceding char
|
|
390
|
+
// optional.
|
|
391
|
+
i += 2;
|
|
392
|
+
pattern += '?';
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
pattern += escapeRegex(ch);
|
|
396
|
+
i++;
|
|
397
|
+
}
|
|
398
|
+
pattern += '$';
|
|
399
|
+
let re;
|
|
400
|
+
try {
|
|
401
|
+
re = new RegExp(pattern);
|
|
402
|
+
} catch (_err) {
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
return { pattern: re, paramNames };
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Build a matcher from a regex-literal step. Numbered capture groups map to
|
|
409
|
+
// positional parameter markers `$1`, `$2`, ...
|
|
410
|
+
function buildFromRegex(regexSrc) {
|
|
411
|
+
let re;
|
|
412
|
+
try {
|
|
413
|
+
re = new RegExp(regexSrc);
|
|
414
|
+
} catch (_err) {
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
const groupCount = countCaptureGroups(regexSrc);
|
|
418
|
+
const paramNames = [];
|
|
419
|
+
for (let n = 1; n <= groupCount; n++) paramNames.push(`$${n}`);
|
|
420
|
+
return { pattern: re, paramNames };
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function countCaptureGroups(regexSrc) {
|
|
424
|
+
let count = 0;
|
|
425
|
+
let inClass = false;
|
|
426
|
+
for (let i = 0; i < regexSrc.length; i++) {
|
|
427
|
+
const ch = regexSrc[i];
|
|
428
|
+
if (ch === '\\') {
|
|
429
|
+
i++;
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
if (ch === '[') inClass = true;
|
|
433
|
+
else if (ch === ']') inClass = false;
|
|
434
|
+
else if (ch === '(' && !inClass) {
|
|
435
|
+
// Skip non-capturing `(?:` and lookarounds `(?=` `(?!` `(?<=` `(?<!`.
|
|
436
|
+
if (regexSrc[i + 1] === '?' && regexSrc[i + 2] !== '<') continue;
|
|
437
|
+
if (
|
|
438
|
+
regexSrc[i + 1] === '?' &&
|
|
439
|
+
regexSrc[i + 2] === '<' &&
|
|
440
|
+
(regexSrc[i + 3] === '=' || regexSrc[i + 3] === '!')
|
|
441
|
+
) {
|
|
442
|
+
continue;
|
|
443
|
+
}
|
|
444
|
+
count++;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
return count;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function escapeRegex(s) {
|
|
451
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// --- Step binding ----------------------------------------------------------
|
|
455
|
+
|
|
456
|
+
// Build the literal step text a step definition would see at runtime, with
|
|
457
|
+
// each `<placeholder>` substituted by a unique alphanumeric sentinel token.
|
|
458
|
+
// Returns the substituted text plus the ordered placeholder names so we can
|
|
459
|
+
// recover which placeholder fell into which capture group. The sentinel is a
|
|
460
|
+
// bare word chosen to survive cucumber-expression and regex-literal matching
|
|
461
|
+
// without introducing characters a pattern might treat specially.
|
|
462
|
+
const STANDIN_PREFIX = 'zphz';
|
|
463
|
+
const STANDIN_SUFFIX = 'zqz';
|
|
464
|
+
const STANDIN_RECOVER_RE = new RegExp(
|
|
465
|
+
`${STANDIN_PREFIX}(\\d+)${STANDIN_SUFFIX}`,
|
|
466
|
+
);
|
|
467
|
+
|
|
468
|
+
export function substitutePlaceholders(stepText) {
|
|
469
|
+
const order = [];
|
|
470
|
+
const substituted = stepText.replace(PLACEHOLDER_RE, (_full, name) => {
|
|
471
|
+
const token = `${STANDIN_PREFIX}${order.length}${STANDIN_SUFFIX}`;
|
|
472
|
+
order.push(name.trim());
|
|
473
|
+
return token;
|
|
474
|
+
});
|
|
475
|
+
return { substituted, order };
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Detect whether a step-definition body references a given parameter name —
|
|
479
|
+
// i.e. whether the captured Examples value reaches an assertion at all.
|
|
480
|
+
//
|
|
481
|
+
// The signal is deliberately simple and conservative: the parameter
|
|
482
|
+
// identifier (named cucumber parameter, e.g. `expectedOutcome`) or the
|
|
483
|
+
// positional capture marker (regex capture, e.g. `$1`) must appear as a
|
|
484
|
+
// referenced identifier inside the handler body. A tautological step
|
|
485
|
+
// definition — `() => { expect(true).toBe(true); }` or
|
|
486
|
+
// `(role) => { /* no-op */ }` — never references its captured parameter, so
|
|
487
|
+
// it is flagged. A genuine assertion that compares the captured value
|
|
488
|
+
// against observed state references the parameter and passes.
|
|
489
|
+
//
|
|
490
|
+
// For positional regex captures the handler's formal parameter name is not
|
|
491
|
+
// recoverable from the pattern alone, so we instead require that the handler
|
|
492
|
+
// reads SOME argument value in an assertion (`bodyReadsAnyArgument`).
|
|
493
|
+
export function bodyReferencesParam(body, paramName) {
|
|
494
|
+
if (!body) return false;
|
|
495
|
+
if (paramName.startsWith('$')) {
|
|
496
|
+
return bodyReadsAnyArgument(body);
|
|
497
|
+
}
|
|
498
|
+
const re = new RegExp(`(?<![\\w$])${escapeRegex(paramName)}(?![\\w$])`);
|
|
499
|
+
return re.test(body);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Heuristic for positional (regex) captures: does the handler read any
|
|
503
|
+
// non-constant value inside an assertion? A tautological body asserts only
|
|
504
|
+
// over literals (`true`, numbers, strings), so stripping those and finding a
|
|
505
|
+
// remaining identifier inside an `expect(...)` / `assert(...)` call proves
|
|
506
|
+
// the handler consumes an argument.
|
|
507
|
+
export function bodyReadsAnyArgument(body) {
|
|
508
|
+
if (!body) return false;
|
|
509
|
+
// Strip literal arguments so a tautology over constants leaves empty call
|
|
510
|
+
// parentheses.
|
|
511
|
+
const stripped = body
|
|
512
|
+
.replace(/\b(true|false|null|undefined)\b/g, '')
|
|
513
|
+
.replace(/\b\d+(\.\d+)?\b/g, '')
|
|
514
|
+
.replace(/(['"`])(?:\\.|(?!\1).)*\1/g, '');
|
|
515
|
+
// Find each `expect(...)` / `assert*(...)` call and look for an identifier
|
|
516
|
+
// INSIDE its argument list (not the matcher method name itself).
|
|
517
|
+
const callRe = /(expect|assert(?:\.\w+)?)\s*\(([^)]*)\)/g;
|
|
518
|
+
let m;
|
|
519
|
+
// biome-ignore lint/suspicious/noAssignInExpressions: idiomatic regex loop
|
|
520
|
+
while ((m = callRe.exec(stripped)) !== null) {
|
|
521
|
+
if (/[A-Za-z_$][\w$]*/.test(m[2])) return true;
|
|
522
|
+
}
|
|
523
|
+
return false;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// --- Step binding resolution -----------------------------------------------
|
|
527
|
+
|
|
528
|
+
// Resolve a single Outline step to its bound step definition and map each
|
|
529
|
+
// placeholder to the capture-group parameter it lands in. Returns
|
|
530
|
+
// { def, captures: [{ placeholder, paramName }] } or null when unresolved.
|
|
531
|
+
export function resolveBinding(stepText, stepDefs) {
|
|
532
|
+
const { substituted, order } = substitutePlaceholders(stepText);
|
|
533
|
+
if (order.length === 0) return null;
|
|
534
|
+
|
|
535
|
+
for (const def of stepDefs) {
|
|
536
|
+
const m = def.pattern.exec(substituted);
|
|
537
|
+
if (!m) continue;
|
|
538
|
+
const captures = [];
|
|
539
|
+
for (let g = 1; g < m.length; g++) {
|
|
540
|
+
const groupText = m[g] ?? '';
|
|
541
|
+
const phMatch = groupText.match(STANDIN_RECOVER_RE);
|
|
542
|
+
if (!phMatch) continue;
|
|
543
|
+
const placeholder = order[Number(phMatch[1])];
|
|
544
|
+
// The handler's positional formal parameter is the channel a captured
|
|
545
|
+
// Examples value reaches an assertion through. Prefer it; fall back to
|
|
546
|
+
// the pattern's positional marker when the signature is unreadable.
|
|
547
|
+
const handlerParam = def.handlerParams?.[g - 1];
|
|
548
|
+
const paramName = handlerParam ?? def.paramNames[g - 1] ?? `$${g}`;
|
|
549
|
+
captures.push({ placeholder, paramName });
|
|
550
|
+
}
|
|
551
|
+
if (captures.length > 0) return { def, captures };
|
|
552
|
+
}
|
|
553
|
+
return null;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// --- Per-file check --------------------------------------------------------
|
|
557
|
+
|
|
558
|
+
export function checkFile(absPath, repoRoot, stepDefs) {
|
|
559
|
+
const violations = [];
|
|
560
|
+
const source = fs.readFileSync(absPath, 'utf8');
|
|
561
|
+
const masked = maskDocStrings(source);
|
|
562
|
+
const relFile = path.relative(repoRoot, absPath).split(path.sep).join('/');
|
|
563
|
+
const outlines = parseOutlines(masked);
|
|
564
|
+
|
|
565
|
+
for (const outline of outlines) {
|
|
566
|
+
const consumed = new Map(); // placeholder -> boolean
|
|
567
|
+
const firstSeenLine = new Map(); // placeholder -> line
|
|
568
|
+
|
|
569
|
+
for (const step of outline.steps) {
|
|
570
|
+
const used = extractPlaceholders(step.text);
|
|
571
|
+
if (used.length === 0) continue;
|
|
572
|
+
for (const ph of used) {
|
|
573
|
+
if (!firstSeenLine.has(ph)) firstSeenLine.set(ph, step.line);
|
|
574
|
+
if (!consumed.has(ph)) consumed.set(ph, false);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
const binding = resolveBinding(step.text, stepDefs);
|
|
578
|
+
if (!binding) continue;
|
|
579
|
+
|
|
580
|
+
for (const { placeholder, paramName } of binding.captures) {
|
|
581
|
+
if (paramName && bodyReferencesParam(binding.def.body, paramName)) {
|
|
582
|
+
consumed.set(placeholder, true);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
for (const [ph, isConsumed] of consumed) {
|
|
588
|
+
// Only flag placeholders that are real Examples columns. A
|
|
589
|
+
// `<placeholder>` with no matching Examples column is malformed in a
|
|
590
|
+
// different way and out of this validator's lane.
|
|
591
|
+
if (!outline.exampleHeaders.has(ph)) continue;
|
|
592
|
+
if (!isConsumed) {
|
|
593
|
+
violations.push({
|
|
594
|
+
file: relFile,
|
|
595
|
+
line: firstSeenLine.get(ph) ?? outline.line,
|
|
596
|
+
kind: 'unconsumed-placeholder',
|
|
597
|
+
message: `Scenario Outline placeholder <${ph}> is never asserted by its bound step definition`,
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
return violations;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// --- Public entry point ----------------------------------------------------
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Run the checker programmatically. Returns `{ exitCode, violations, scanned }`.
|
|
610
|
+
*
|
|
611
|
+
* @param {object} [options]
|
|
612
|
+
* @param {string} [options.repoRoot] Defaults to the framework repo root.
|
|
613
|
+
* @param {string[]} [options.featureRoots] Defaults to `['tests/features']`.
|
|
614
|
+
* @param {string[]} [options.stepRoots] Defaults to `['tests/steps']`.
|
|
615
|
+
*/
|
|
616
|
+
export function runCheck(options = {}) {
|
|
617
|
+
const repoRoot = options.repoRoot ?? REPO_ROOT;
|
|
618
|
+
const featureRoots = options.featureRoots ?? DEFAULT_FEATURE_ROOTS;
|
|
619
|
+
const stepRoots = options.stepRoots ?? DEFAULT_STEP_ROOTS;
|
|
620
|
+
|
|
621
|
+
const stepDefFiles = discoverStepDefs(repoRoot, stepRoots);
|
|
622
|
+
const stepDefs = [];
|
|
623
|
+
for (const abs of stepDefFiles) {
|
|
624
|
+
const src = fs.readFileSync(abs, 'utf8');
|
|
625
|
+
stepDefs.push(...parseStepDefs(src));
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
const featureFiles = discoverFeatures(repoRoot, featureRoots);
|
|
629
|
+
const violations = [];
|
|
630
|
+
for (const abs of featureFiles) {
|
|
631
|
+
violations.push(...checkFile(abs, repoRoot, stepDefs));
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
return {
|
|
635
|
+
exitCode: violations.length === 0 ? 0 : 1,
|
|
636
|
+
violations,
|
|
637
|
+
scanned: featureFiles.length,
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
function formatViolation(v) {
|
|
642
|
+
return `${v.file}:${v.line}: [${v.kind}] ${v.message}`;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
async function main() {
|
|
646
|
+
const result = runCheck();
|
|
647
|
+
if (result.violations.length === 0) {
|
|
648
|
+
Logger.info(
|
|
649
|
+
`[check-gherkin-placeholders] OK — scanned ${result.scanned} feature file(s); no unconsumed placeholders.`,
|
|
650
|
+
);
|
|
651
|
+
process.exit(0);
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
for (const v of result.violations) {
|
|
655
|
+
process.stderr.write(`${formatViolation(v)}\n`);
|
|
656
|
+
}
|
|
657
|
+
process.stderr.write(
|
|
658
|
+
`\n[check-gherkin-placeholders] FAILED — ${result.violations.length} violation(s) across ${result.scanned} file(s).\n`,
|
|
659
|
+
);
|
|
660
|
+
process.exit(1);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
runAsCli(import.meta.url, main, { source: 'check-gherkin-placeholders' });
|