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,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/mutation/survivor-report.js — enumerate actionable surviving mutants
|
|
3
|
+
* from a Stryker JSON report (Story #3428).
|
|
4
|
+
*
|
|
5
|
+
* The mutation gate (`stryker-runner.js` → `summariseReport`) collapses the
|
|
6
|
+
* report into a single score. That score tells you *whether* the suite is
|
|
7
|
+
* leaky, not *where*. This helper does the complementary job: it walks the
|
|
8
|
+
* same `files[].mutants[].status` surface and enumerates the mutants that
|
|
9
|
+
* the suite failed to kill — `Survived` (a mutation that the tests ran over
|
|
10
|
+
* but never caught) and `NoCoverage` (a mutation in a line no test exercises
|
|
11
|
+
* at all) — grouped per file so the survivor-kill loop has concrete targets.
|
|
12
|
+
*
|
|
13
|
+
* It is **pure**: no network, no child process, no filesystem reads. The
|
|
14
|
+
* caller hands in an already-parsed report object (the same JSON that
|
|
15
|
+
* `stryker-runner.js` reads from `reports/mutation/mutation.json`). This
|
|
16
|
+
* keeps the helper trivially unit-testable with inline fixtures and lets
|
|
17
|
+
* remediation tooling reuse a report it already loaded for scoring.
|
|
18
|
+
*
|
|
19
|
+
* Output contract:
|
|
20
|
+
*
|
|
21
|
+
* {
|
|
22
|
+
* ok: true,
|
|
23
|
+
* totals: { survived, noCoverage, actionable, files },
|
|
24
|
+
* files: [
|
|
25
|
+
* {
|
|
26
|
+
* file: "src/a.js",
|
|
27
|
+
* survived: [{ id, line, mutatorName, status, ... }],
|
|
28
|
+
* noCoverage: [{ ... }],
|
|
29
|
+
* count: <survived.length + noCoverage.length>,
|
|
30
|
+
* },
|
|
31
|
+
* ...
|
|
32
|
+
* ],
|
|
33
|
+
* }
|
|
34
|
+
* { ok: false, error: <string> }
|
|
35
|
+
*
|
|
36
|
+
* Files with no actionable survivors are omitted from `files`. The `files`
|
|
37
|
+
* array is sorted by descending actionable count (worst offenders first),
|
|
38
|
+
* ties broken by file path for stable output.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
/** Mutant statuses this helper treats as actionable survivors. */
|
|
42
|
+
export const ACTIONABLE_STATUSES = Object.freeze(['Survived', 'NoCoverage']);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Fields copied verbatim from each Stryker mutant onto the enumerated
|
|
46
|
+
* survivor record. We deliberately keep a fixed allowlist (rather than
|
|
47
|
+
* spreading the raw mutant) so the output shape is stable and never leaks
|
|
48
|
+
* unexpected report internals.
|
|
49
|
+
*/
|
|
50
|
+
const MUTANT_FIELDS = Object.freeze([
|
|
51
|
+
'id',
|
|
52
|
+
'mutatorName',
|
|
53
|
+
'status',
|
|
54
|
+
'location',
|
|
55
|
+
'replacement',
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Pure: enumerate `Survived` and `NoCoverage` mutants per file from a
|
|
60
|
+
* parsed Stryker mutation report.
|
|
61
|
+
*
|
|
62
|
+
* @param {unknown} report Parsed Stryker JSON report (an object with a
|
|
63
|
+
* top-level `files` map). Passing the raw JSON string is **not**
|
|
64
|
+
* supported — parse it first (mirrors `summariseReport`).
|
|
65
|
+
* @returns {(
|
|
66
|
+
* { ok: true, totals: { survived: number, noCoverage: number, actionable: number, files: number }, files: Array<{ file: string, survived: object[], noCoverage: object[], count: number }> }
|
|
67
|
+
* | { ok: false, error: string }
|
|
68
|
+
* )}
|
|
69
|
+
*/
|
|
70
|
+
export function enumerateSurvivors(report) {
|
|
71
|
+
if (!report || typeof report !== 'object' || Array.isArray(report)) {
|
|
72
|
+
return { ok: false, error: 'Stryker report must be a JSON object' };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const files = /** @type {Record<string, unknown> | undefined} */ (
|
|
76
|
+
/** @type {Record<string, unknown>} */ (report).files
|
|
77
|
+
);
|
|
78
|
+
if (!files || typeof files !== 'object' || Array.isArray(files)) {
|
|
79
|
+
return { ok: false, error: "Stryker report missing 'files' map" };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const perFile = [];
|
|
83
|
+
let survivedTotal = 0;
|
|
84
|
+
let noCoverageTotal = 0;
|
|
85
|
+
|
|
86
|
+
for (const [filePath, entry] of Object.entries(files)) {
|
|
87
|
+
if (!entry || typeof entry !== 'object') continue;
|
|
88
|
+
const mutants = /** @type {{ mutants?: unknown }} */ (entry).mutants;
|
|
89
|
+
if (!Array.isArray(mutants)) continue;
|
|
90
|
+
|
|
91
|
+
const survived = [];
|
|
92
|
+
const noCoverage = [];
|
|
93
|
+
for (const mutant of mutants) {
|
|
94
|
+
if (!mutant || typeof mutant !== 'object') continue;
|
|
95
|
+
const status = /** @type {{ status?: unknown }} */ (mutant).status;
|
|
96
|
+
if (status === 'Survived') {
|
|
97
|
+
survived.push(pickMutant(mutant));
|
|
98
|
+
} else if (status === 'NoCoverage') {
|
|
99
|
+
noCoverage.push(pickMutant(mutant));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (survived.length === 0 && noCoverage.length === 0) continue;
|
|
104
|
+
|
|
105
|
+
survivedTotal += survived.length;
|
|
106
|
+
noCoverageTotal += noCoverage.length;
|
|
107
|
+
perFile.push({
|
|
108
|
+
file: filePath,
|
|
109
|
+
survived,
|
|
110
|
+
noCoverage,
|
|
111
|
+
count: survived.length + noCoverage.length,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
perFile.sort((a, b) => b.count - a.count || a.file.localeCompare(b.file));
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
ok: true,
|
|
119
|
+
totals: {
|
|
120
|
+
survived: survivedTotal,
|
|
121
|
+
noCoverage: noCoverageTotal,
|
|
122
|
+
actionable: survivedTotal + noCoverageTotal,
|
|
123
|
+
files: perFile.length,
|
|
124
|
+
},
|
|
125
|
+
files: perFile,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Copy the stable allowlist of fields off a raw Stryker mutant. The `line`
|
|
131
|
+
* convenience field is derived from `location.start.line` when present so
|
|
132
|
+
* callers can sort/print without re-walking the nested location shape.
|
|
133
|
+
*
|
|
134
|
+
* @param {Record<string, unknown>} mutant
|
|
135
|
+
* @returns {Record<string, unknown>}
|
|
136
|
+
*/
|
|
137
|
+
function pickMutant(mutant) {
|
|
138
|
+
const out = {};
|
|
139
|
+
for (const field of MUTANT_FIELDS) {
|
|
140
|
+
if (mutant[field] !== undefined) out[field] = mutant[field];
|
|
141
|
+
}
|
|
142
|
+
const line = extractLine(mutant.location);
|
|
143
|
+
if (line !== null) out.line = line;
|
|
144
|
+
return out;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Pull the 1-based start line out of a Stryker `location` object, or null
|
|
149
|
+
* when the shape is missing or malformed.
|
|
150
|
+
*
|
|
151
|
+
* @param {unknown} location
|
|
152
|
+
* @returns {number | null}
|
|
153
|
+
*/
|
|
154
|
+
function extractLine(location) {
|
|
155
|
+
if (!location || typeof location !== 'object') return null;
|
|
156
|
+
const start = /** @type {{ start?: unknown }} */ (location).start;
|
|
157
|
+
if (!start || typeof start !== 'object') return null;
|
|
158
|
+
const line = /** @type {{ line?: unknown }} */ (start).line;
|
|
159
|
+
return typeof line === 'number' && Number.isFinite(line) ? line : null;
|
|
160
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notification helpers — shared severity vocabulary and webhook URL resolver.
|
|
3
|
+
*
|
|
4
|
+
* The unified `notify()` API in `notify.js` is the single dispatch entry
|
|
5
|
+
* point for two event-allowlist-gated channels: GitHub comments
|
|
6
|
+
* (`notifications.commentEvents`) and the Slack webhook
|
|
7
|
+
* (`notifications.webhookEvents`). Both channels filter independently by
|
|
8
|
+
* event-name membership — there is no fallback chain and severity is no
|
|
9
|
+
* longer a routing factor for either channel.
|
|
10
|
+
*
|
|
11
|
+
* Severity vocabulary: low | medium | high. Severity is carried as
|
|
12
|
+
* envelope metadata so Slack consumers can color-code by it and so
|
|
13
|
+
* high-severity comments still `@mention` the operator, but it does not
|
|
14
|
+
* gate channel delivery.
|
|
15
|
+
* - low — routine pipeline progress: task transitions, story-run
|
|
16
|
+
* progress upserts. `transitionTicketState` skips the
|
|
17
|
+
* `notify()` dispatch entirely for these so the comment
|
|
18
|
+
* channel never sees them.
|
|
19
|
+
* - medium — operator-visible milestones: story / epic → done
|
|
20
|
+
* transitions, story-merged, epic milestones.
|
|
21
|
+
* - high — operator must act: epic blockers, HITL gates,
|
|
22
|
+
* autonomous-chain failures. Webhook envelope prefix is
|
|
23
|
+
* `[Action Required]`; high-severity comments always
|
|
24
|
+
* `@mention` the operator.
|
|
25
|
+
*
|
|
26
|
+
* Webhook URL resolution: `process.env.NOTIFICATION_WEBHOOK_URL` only —
|
|
27
|
+
* loaded from `.env` locally, the Claude Code web environment-variables UI,
|
|
28
|
+
* or `ENV_FILE` on GitHub Actions. The webhook URL is never read from
|
|
29
|
+
* `.agentrc.json` and (as of Epic #702) is no longer sourced from
|
|
30
|
+
* `.mcp.json`.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { AGENT_LABELS } from '../label-constants.js';
|
|
34
|
+
|
|
35
|
+
export const SEVERITY_RANK = Object.freeze({ low: 0, medium: 1, high: 2 });
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Compute the severity of a ticket-state-transition event.
|
|
39
|
+
*
|
|
40
|
+
* Today only Story or Epic tickets reaching `agent::done` rate `medium`;
|
|
41
|
+
* every other transition (intermediate or task-level) is `low`. State-
|
|
42
|
+
* transition events never reach `high` — that level is reserved for
|
|
43
|
+
* explicit `notify()` calls signalling operator action is required.
|
|
44
|
+
*
|
|
45
|
+
* @param {{ kind?: string, ticket?: { type?: string }, toState?: string|null }} event
|
|
46
|
+
*/
|
|
47
|
+
export function eventSeverity(event) {
|
|
48
|
+
if (event?.kind === 'state-transition') {
|
|
49
|
+
const type = event.ticket?.type;
|
|
50
|
+
const isStoryOrEpic = type === 'story' || type === 'epic';
|
|
51
|
+
if (isStoryOrEpic && event.toState === AGENT_LABELS.DONE) return 'medium';
|
|
52
|
+
}
|
|
53
|
+
return 'low';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Render a state-transition event into a human-readable summary line used
|
|
58
|
+
* as both the GitHub comment body and the webhook message text.
|
|
59
|
+
*/
|
|
60
|
+
export function renderTransitionMessage(event) {
|
|
61
|
+
const type = event.ticket?.type ?? 'ticket';
|
|
62
|
+
const id = event.ticket?.id;
|
|
63
|
+
const title = event.ticket?.title ?? '';
|
|
64
|
+
const toState = event.toState ?? '';
|
|
65
|
+
const fromState = event.fromState ?? '';
|
|
66
|
+
let summary = fromState
|
|
67
|
+
? `${type} #${id} · \`${fromState}\` → \`${toState}\``
|
|
68
|
+
: `${type} #${id} · → \`${toState}\``;
|
|
69
|
+
if (title) summary += ` — ${title.slice(0, 80)}`;
|
|
70
|
+
return summary;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function resolveWebhookUrl() {
|
|
74
|
+
return process.env.NOTIFICATION_WEBHOOK_URL?.trim() || null;
|
|
75
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Active-Story env-var propagation (Epic #1030 Story #1043 / Task #1061).
|
|
3
|
+
*
|
|
4
|
+
* The PreToolUse / PostToolUse trace hook in
|
|
5
|
+
* `lib/observability/tool-trace-hook.js` resolves the active Epic +
|
|
6
|
+
* Story from `process.env.CC_EPIC_ID` and `process.env.CC_STORY_ID`.
|
|
7
|
+
* This module is the single writer/clearer of those vars:
|
|
8
|
+
*
|
|
9
|
+
* - `setActiveStoryEnv({ epicId, storyId, workCwd })` is called from
|
|
10
|
+
* `story-init.js` after the worktree is materialised. It sets the
|
|
11
|
+
* vars on the current `process.env` (so any child commands the
|
|
12
|
+
* orchestrator spawns inherit them) and exports them to a sibling
|
|
13
|
+
* `.env.local` inside the worktree. The harness re-spawns the
|
|
14
|
+
* agent with that file's contents loaded, so the trace hook fires
|
|
15
|
+
* with the right ids on the *next* tool call after init returns.
|
|
16
|
+
*
|
|
17
|
+
* - `clearActiveStoryEnv({ workCwd })` is called from
|
|
18
|
+
* `story-close/post-merge-close.js` after the merge lands. It
|
|
19
|
+
* deletes the env vars from `process.env` and removes the
|
|
20
|
+
* `.env.local` file. Tooling invoked outside an active Story —
|
|
21
|
+
* planning, dispatch, ad-hoc CLI — must NOT pollute random
|
|
22
|
+
* `traces.ndjson` files; the hook's no-op contract relies on the
|
|
23
|
+
* vars being absent at that point.
|
|
24
|
+
*
|
|
25
|
+
* Both functions are best-effort and never throw on fs failures. The
|
|
26
|
+
* trace hook is itself best-effort, so a stale `.env.local` would at
|
|
27
|
+
* worst cause one extra trace line to land in a stale `temp/.../`
|
|
28
|
+
* directory — annoying but not a correctness bug. We log warnings via
|
|
29
|
+
* the caller's logger when provided.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import nodeFs from 'node:fs';
|
|
33
|
+
import nodePath from 'node:path';
|
|
34
|
+
|
|
35
|
+
const ENV_LOCAL_BASENAME = '.env.local';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Names of the env vars we own. Keeping the list central makes the
|
|
39
|
+
* round-trip (set on init, clear on close) trivially auditable —
|
|
40
|
+
* grep `CC_EPIC_ID` / `CC_STORY_ID` to find every read site.
|
|
41
|
+
*/
|
|
42
|
+
export const ACTIVE_STORY_ENV_KEYS = ['CC_EPIC_ID', 'CC_STORY_ID'];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Render the `.env.local` body. One `KEY=value` line per var, LF
|
|
46
|
+
* line endings (the harness's dotenv parser tolerates CRLF too but LF
|
|
47
|
+
* keeps the file deterministic across Windows / macOS / Linux).
|
|
48
|
+
*
|
|
49
|
+
* Story #2874 — when `epicId === null` (standalone Story, no parent
|
|
50
|
+
* Epic), the `CC_EPIC_ID=` line is omitted entirely. The trace
|
|
51
|
+
* hook's no-op contract reads "var absent from env" as the signal,
|
|
52
|
+
* so emitting an empty `CC_EPIC_ID=` line would set the var to the
|
|
53
|
+
* empty string and change the contract.
|
|
54
|
+
*
|
|
55
|
+
* Exported for testing.
|
|
56
|
+
*
|
|
57
|
+
* @param {{ epicId: number|null, storyId: number }} input
|
|
58
|
+
* @returns {string}
|
|
59
|
+
*/
|
|
60
|
+
export function renderActiveStoryEnvFile({ epicId, storyId }) {
|
|
61
|
+
const lines = [
|
|
62
|
+
'# Auto-managed by .agents/scripts/lib/observability/active-story-env.js',
|
|
63
|
+
'# Re-generated on every story-init; deleted on story-close.',
|
|
64
|
+
];
|
|
65
|
+
if (epicId !== null) lines.push(`CC_EPIC_ID=${epicId}`);
|
|
66
|
+
lines.push(`CC_STORY_ID=${storyId}`, '');
|
|
67
|
+
return lines.join('\n');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Set `CC_EPIC_ID` / `CC_STORY_ID` on the current process and (when
|
|
72
|
+
* `workCwd` is provided) export them to `<workCwd>/.env.local`.
|
|
73
|
+
*
|
|
74
|
+
* Idempotent: re-running with the same ids is a no-op on disk; with
|
|
75
|
+
* different ids the `.env.local` is overwritten.
|
|
76
|
+
*
|
|
77
|
+
* Story #2874 — `epicId: null` is the standalone-Story sentinel.
|
|
78
|
+
* When passed:
|
|
79
|
+
* - `CC_EPIC_ID` is removed from `env` (the var MUST NOT be set
|
|
80
|
+
* to an empty string — the trace hook's `resolveActiveStory`
|
|
81
|
+
* no-op contract is keyed on the var's absence).
|
|
82
|
+
* - The rendered `.env.local` omits the `CC_EPIC_ID=` line.
|
|
83
|
+
* - `CC_STORY_ID` behaviour is unchanged.
|
|
84
|
+
* All other invalid `epicId` values (`0`, negative, NaN, non-integer)
|
|
85
|
+
* still throw — `null` is the only standalone signal.
|
|
86
|
+
*
|
|
87
|
+
* @param {{ epicId: number|null, storyId: number, workCwd?: string,
|
|
88
|
+
* env?: NodeJS.ProcessEnv, fs?: typeof nodeFs,
|
|
89
|
+
* logger?: { warn?: (m: string) => void } }} args
|
|
90
|
+
* @returns {{ envSet: boolean, fileWritten: boolean, filePath: string|null }}
|
|
91
|
+
*/
|
|
92
|
+
export function setActiveStoryEnv({
|
|
93
|
+
epicId,
|
|
94
|
+
storyId,
|
|
95
|
+
workCwd,
|
|
96
|
+
env = process.env,
|
|
97
|
+
fs = nodeFs,
|
|
98
|
+
logger,
|
|
99
|
+
} = {}) {
|
|
100
|
+
if (epicId !== null && (!Number.isInteger(epicId) || epicId <= 0)) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
`[active-story-env] epicId must be a positive integer or null; got ${epicId}`,
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
if (!Number.isInteger(storyId) || storyId <= 0) {
|
|
106
|
+
throw new Error(
|
|
107
|
+
`[active-story-env] storyId must be a positive integer; got ${storyId}`,
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (epicId === null) {
|
|
112
|
+
// Standalone Story — ensure CC_EPIC_ID is absent so the trace
|
|
113
|
+
// hook's no-op contract sees "no epic" rather than "epic=''".
|
|
114
|
+
if ('CC_EPIC_ID' in env) delete env.CC_EPIC_ID;
|
|
115
|
+
} else {
|
|
116
|
+
env.CC_EPIC_ID = String(epicId);
|
|
117
|
+
}
|
|
118
|
+
env.CC_STORY_ID = String(storyId);
|
|
119
|
+
|
|
120
|
+
let fileWritten = false;
|
|
121
|
+
let filePath = null;
|
|
122
|
+
if (typeof workCwd === 'string' && workCwd.length > 0) {
|
|
123
|
+
filePath = nodePath.join(workCwd, ENV_LOCAL_BASENAME);
|
|
124
|
+
try {
|
|
125
|
+
fs.writeFileSync(
|
|
126
|
+
filePath,
|
|
127
|
+
renderActiveStoryEnvFile({ epicId, storyId }),
|
|
128
|
+
{
|
|
129
|
+
encoding: 'utf8',
|
|
130
|
+
},
|
|
131
|
+
);
|
|
132
|
+
fileWritten = true;
|
|
133
|
+
} catch (err) {
|
|
134
|
+
logger?.warn?.(
|
|
135
|
+
`[active-story-env] Failed to write ${filePath}: ${
|
|
136
|
+
err instanceof Error ? err.message : String(err)
|
|
137
|
+
}`,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return { envSet: true, fileWritten, filePath };
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Delete `CC_EPIC_ID` / `CC_STORY_ID` from the current process env and
|
|
146
|
+
* remove `<workCwd>/.env.local` when present. Best-effort; a missing
|
|
147
|
+
* file is not an error.
|
|
148
|
+
*
|
|
149
|
+
* @param {{ workCwd?: string, env?: NodeJS.ProcessEnv,
|
|
150
|
+
* fs?: typeof nodeFs,
|
|
151
|
+
* logger?: { warn?: (m: string) => void } }} args
|
|
152
|
+
* @returns {{ envCleared: boolean, fileRemoved: boolean, filePath: string|null }}
|
|
153
|
+
*/
|
|
154
|
+
export function clearActiveStoryEnv({
|
|
155
|
+
workCwd,
|
|
156
|
+
env = process.env,
|
|
157
|
+
fs = nodeFs,
|
|
158
|
+
logger,
|
|
159
|
+
} = {}) {
|
|
160
|
+
for (const k of ACTIVE_STORY_ENV_KEYS) {
|
|
161
|
+
if (k in env) delete env[k];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let fileRemoved = false;
|
|
165
|
+
let filePath = null;
|
|
166
|
+
if (typeof workCwd === 'string' && workCwd.length > 0) {
|
|
167
|
+
filePath = nodePath.join(workCwd, ENV_LOCAL_BASENAME);
|
|
168
|
+
try {
|
|
169
|
+
if (fs.existsSync(filePath)) {
|
|
170
|
+
fs.unlinkSync(filePath);
|
|
171
|
+
fileRemoved = true;
|
|
172
|
+
}
|
|
173
|
+
} catch (err) {
|
|
174
|
+
logger?.warn?.(
|
|
175
|
+
`[active-story-env] Failed to remove ${filePath}: ${
|
|
176
|
+
err instanceof Error ? err.message : String(err)
|
|
177
|
+
}`,
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return { envCleared: true, fileRemoved, filePath };
|
|
182
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* baseline-refresh-rate.js — pure reporter for the per-Epic baseline-refresh
|
|
3
|
+
* commit rate (Epic #1386, Story #1400).
|
|
4
|
+
*
|
|
5
|
+
* The "baseline-refresh discipline" (Story #1124, Tech Spec #902) requires
|
|
6
|
+
* that every Story whose merge introduces baseline drift land an explicit
|
|
7
|
+
* `baseline-refresh:` commit in the same close PR (or, post Story #1398,
|
|
8
|
+
* fold the refresh into the close commit itself). The 90% target — that
|
|
9
|
+
* at least 90% of merged Stories per Epic land without leaving baseline
|
|
10
|
+
* drift behind — needs a measurable signal so retros can spot regressions
|
|
11
|
+
* before they leak into `main`.
|
|
12
|
+
*
|
|
13
|
+
* This module exports a single pure function that takes a fixture of
|
|
14
|
+
* commit records (one per Story-attributable commit on `epic/<id>` over
|
|
15
|
+
* the trailing window) and returns:
|
|
16
|
+
*
|
|
17
|
+
* - per-Epic counts of `baseline-refresh:` commits
|
|
18
|
+
* - per-Epic counts of merged Stories
|
|
19
|
+
* - per-Epic percentage of merged Stories that did NOT land a
|
|
20
|
+
* baseline-refresh commit (the "clean-merge" rate)
|
|
21
|
+
*
|
|
22
|
+
* The caller (analyze-execution.js) is responsible for shelling out to
|
|
23
|
+
* `git log` and resolving each commit to its parent Epic ID — this
|
|
24
|
+
* module touches no I/O so the test fixture can pin behavior without a
|
|
25
|
+
* temp git repo or stubbed spawn.
|
|
26
|
+
*
|
|
27
|
+
* Default window is 4 weeks (28 days). Pass `windowDays` to override
|
|
28
|
+
* (e.g., `windowDays: 14` for a fortnightly retro).
|
|
29
|
+
*
|
|
30
|
+
* Aligned with `perf-aggregator.js`: empty input yields a well-formed
|
|
31
|
+
* empty payload, malformed records are silently skipped, the function
|
|
32
|
+
* never throws on bad data.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import { isObject } from '../json-utils.js';
|
|
36
|
+
import { RESOLVES_TRAILER_RE } from '../orchestration/resolves-token.js';
|
|
37
|
+
|
|
38
|
+
const BASELINE_REFRESH_PREFIX = 'baseline-refresh:';
|
|
39
|
+
const DEFAULT_WINDOW_DAYS = 28;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Coerce an ISO-8601 date string to epoch ms. Returns NaN for malformed
|
|
43
|
+
* input so the caller's window filter drops the record.
|
|
44
|
+
*/
|
|
45
|
+
function toEpochMs(iso) {
|
|
46
|
+
if (typeof iso !== 'string' || iso.length === 0) return Number.NaN;
|
|
47
|
+
const ms = Date.parse(iso);
|
|
48
|
+
return Number.isFinite(ms) ? ms : Number.NaN;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Classify a commit by its subject line.
|
|
53
|
+
*
|
|
54
|
+
* - `baseline-refresh:` prefix → refresh commit
|
|
55
|
+
* - subject containing `(resolves #N)` → Story-merge commit
|
|
56
|
+
* - everything else → ignored (chore commits, baseline-only fixes, etc.)
|
|
57
|
+
*
|
|
58
|
+
* The classification is deliberately disjoint: a `baseline-refresh:`
|
|
59
|
+
* commit is never counted as a Story merge, and a Story merge is never
|
|
60
|
+
* counted as a baseline-refresh — even if the subject happens to mention
|
|
61
|
+
* both keywords. This matches the on-the-ground convention: refreshes
|
|
62
|
+
* land as their own commit (or amended into the close), Stories land as
|
|
63
|
+
* `feat: ... (resolves #N)`.
|
|
64
|
+
*/
|
|
65
|
+
function classifySubject(subject) {
|
|
66
|
+
if (typeof subject !== 'string' || subject.length === 0) return 'other';
|
|
67
|
+
if (subject.startsWith(BASELINE_REFRESH_PREFIX)) return 'refresh';
|
|
68
|
+
if (RESOLVES_TRAILER_RE.test(subject)) return 'story';
|
|
69
|
+
return 'other';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Compute the trailing-window cutoff in epoch ms. Exported on the
|
|
74
|
+
* exported function via the `now` option so tests can pin the clock.
|
|
75
|
+
*/
|
|
76
|
+
function computeCutoffMs(nowMs, windowDays) {
|
|
77
|
+
const days =
|
|
78
|
+
Number.isFinite(windowDays) && windowDays > 0
|
|
79
|
+
? windowDays
|
|
80
|
+
: DEFAULT_WINDOW_DAYS;
|
|
81
|
+
return nowMs - days * 24 * 60 * 60 * 1000;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Pure reporter for the per-Epic baseline-refresh commit rate.
|
|
86
|
+
*
|
|
87
|
+
* @param {Iterable<{
|
|
88
|
+
* sha?: string,
|
|
89
|
+
* isoDate: string,
|
|
90
|
+
* subject: string,
|
|
91
|
+
* epicId: number | string | null,
|
|
92
|
+
* }>} commits
|
|
93
|
+
* Commit records from the caller. Records missing `epicId` (the commit
|
|
94
|
+
* isn't on any Epic branch) are dropped. Records older than the window
|
|
95
|
+
* are also dropped. Order does not matter — the function aggregates by
|
|
96
|
+
* Epic regardless of input ordering.
|
|
97
|
+
*
|
|
98
|
+
* @param {object} [opts]
|
|
99
|
+
* @param {number} [opts.windowDays] — trailing window in days (default 28).
|
|
100
|
+
* @param {() => Date | number} [opts.now] — clock injector for tests.
|
|
101
|
+
* Accepts either a Date or epoch-ms; defaults to `() => Date.now()`.
|
|
102
|
+
*
|
|
103
|
+
* @returns {{
|
|
104
|
+
* kind: 'baseline-refresh-rate',
|
|
105
|
+
* windowDays: number,
|
|
106
|
+
* generatedAt: string,
|
|
107
|
+
* cutoffAt: string,
|
|
108
|
+
* perEpic: Array<{
|
|
109
|
+
* epicId: number | string,
|
|
110
|
+
* storyMerges: number,
|
|
111
|
+
* baselineRefreshes: number,
|
|
112
|
+
* cleanMergeRate: number,
|
|
113
|
+
* }>,
|
|
114
|
+
* totals: {
|
|
115
|
+
* storyMerges: number,
|
|
116
|
+
* baselineRefreshes: number,
|
|
117
|
+
* cleanMergeRate: number,
|
|
118
|
+
* },
|
|
119
|
+
* }}
|
|
120
|
+
*
|
|
121
|
+
* `cleanMergeRate` is the fraction of merged Stories that did NOT need a
|
|
122
|
+
* baseline-refresh commit follow-up (or amend), in `[0, 1]` rounded to
|
|
123
|
+
* 4 decimal places. The 90% target is `cleanMergeRate >= 0.9`. When
|
|
124
|
+
* `storyMerges === 0`, the rate is `1` (vacuously clean — no Stories,
|
|
125
|
+
* no drift) so a quiet Epic doesn't show up as red.
|
|
126
|
+
*/
|
|
127
|
+
export function computeBaselineRefreshRate(commits, opts = {}) {
|
|
128
|
+
const nowFn = opts.now ?? (() => Date.now());
|
|
129
|
+
const nowVal = nowFn();
|
|
130
|
+
const nowMs = nowVal instanceof Date ? nowVal.getTime() : Number(nowVal);
|
|
131
|
+
const windowDays =
|
|
132
|
+
Number.isFinite(opts.windowDays) && opts.windowDays > 0
|
|
133
|
+
? Math.floor(opts.windowDays)
|
|
134
|
+
: DEFAULT_WINDOW_DAYS;
|
|
135
|
+
const cutoffMs = computeCutoffMs(nowMs, windowDays);
|
|
136
|
+
|
|
137
|
+
// Map<epicId, { storyMerges, baselineRefreshes }>. Insertion order is
|
|
138
|
+
// preserved so the output array is stable for snapshot-style assertions.
|
|
139
|
+
const perEpic = new Map();
|
|
140
|
+
const ensureBucket = (epicId) => {
|
|
141
|
+
if (!perEpic.has(epicId)) {
|
|
142
|
+
perEpic.set(epicId, { storyMerges: 0, baselineRefreshes: 0 });
|
|
143
|
+
}
|
|
144
|
+
return perEpic.get(epicId);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
for (const raw of commits ?? []) {
|
|
148
|
+
if (!isObject(raw)) continue;
|
|
149
|
+
const epicId = raw.epicId;
|
|
150
|
+
if (epicId == null || epicId === '') continue;
|
|
151
|
+
const ts = toEpochMs(raw.isoDate);
|
|
152
|
+
if (!Number.isFinite(ts)) continue;
|
|
153
|
+
if (ts < cutoffMs) continue;
|
|
154
|
+
|
|
155
|
+
const klass = classifySubject(raw.subject);
|
|
156
|
+
if (klass === 'other') continue;
|
|
157
|
+
|
|
158
|
+
const bucket = ensureBucket(epicId);
|
|
159
|
+
if (klass === 'refresh') bucket.baselineRefreshes += 1;
|
|
160
|
+
else if (klass === 'story') bucket.storyMerges += 1;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const perEpicRows = [];
|
|
164
|
+
let totalStories = 0;
|
|
165
|
+
let totalRefreshes = 0;
|
|
166
|
+
for (const [epicId, counts] of perEpic) {
|
|
167
|
+
const cleanMergeRate =
|
|
168
|
+
counts.storyMerges === 0
|
|
169
|
+
? 1
|
|
170
|
+
: Math.max(
|
|
171
|
+
0,
|
|
172
|
+
Math.min(
|
|
173
|
+
1,
|
|
174
|
+
(counts.storyMerges - counts.baselineRefreshes) /
|
|
175
|
+
counts.storyMerges,
|
|
176
|
+
),
|
|
177
|
+
);
|
|
178
|
+
perEpicRows.push({
|
|
179
|
+
epicId,
|
|
180
|
+
storyMerges: counts.storyMerges,
|
|
181
|
+
baselineRefreshes: counts.baselineRefreshes,
|
|
182
|
+
cleanMergeRate: roundRate(cleanMergeRate),
|
|
183
|
+
});
|
|
184
|
+
totalStories += counts.storyMerges;
|
|
185
|
+
totalRefreshes += counts.baselineRefreshes;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const totalsClean =
|
|
189
|
+
totalStories === 0
|
|
190
|
+
? 1
|
|
191
|
+
: Math.max(
|
|
192
|
+
0,
|
|
193
|
+
Math.min(1, (totalStories - totalRefreshes) / totalStories),
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
return {
|
|
197
|
+
kind: 'baseline-refresh-rate',
|
|
198
|
+
windowDays,
|
|
199
|
+
generatedAt: new Date(nowMs).toISOString(),
|
|
200
|
+
cutoffAt: new Date(cutoffMs).toISOString(),
|
|
201
|
+
perEpic: perEpicRows,
|
|
202
|
+
totals: {
|
|
203
|
+
storyMerges: totalStories,
|
|
204
|
+
baselineRefreshes: totalRefreshes,
|
|
205
|
+
cleanMergeRate: roundRate(totalsClean),
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function roundRate(rate) {
|
|
211
|
+
if (!Number.isFinite(rate)) return 0;
|
|
212
|
+
return Math.round(rate * 10000) / 10000;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Exported for unit tests that want to assert the classifier directly
|
|
216
|
+
// without round-tripping through the aggregator.
|
|
217
|
+
export const __test__ = {
|
|
218
|
+
classifySubject,
|
|
219
|
+
computeCutoffMs,
|
|
220
|
+
DEFAULT_WINDOW_DAYS,
|
|
221
|
+
};
|