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,489 @@
|
|
|
1
|
+
// .agents/scripts/lib/orchestration/finalize/post-handoff-comment.js
|
|
2
|
+
/**
|
|
3
|
+
* post-handoff-comment.js — finalize helper that upserts the
|
|
4
|
+
* `epic-handoff` structured comment on the Epic at the end of the
|
|
5
|
+
* bus-owned finalize flow.
|
|
6
|
+
*
|
|
7
|
+
* The Phase 7.1 prose previously asked operators to leave a free-form
|
|
8
|
+
* "PR opened, see #N" comment after `gh pr create`. Lifting that
|
|
9
|
+
* into a structured-marker upsert means the comment is:
|
|
10
|
+
*
|
|
11
|
+
* - addressable by the `epic-handoff` marker (operators and tooling
|
|
12
|
+
* can find the canonical PR pointer without scrolling);
|
|
13
|
+
* - idempotent under finalize replay (re-invoking the helper edits
|
|
14
|
+
* the existing comment rather than fanning out duplicates).
|
|
15
|
+
*
|
|
16
|
+
* Story #2894 / Task #2909 (Epic #2880).
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import fs from 'node:fs/promises';
|
|
20
|
+
import path from 'node:path';
|
|
21
|
+
import {
|
|
22
|
+
epicLedgerPath,
|
|
23
|
+
epicPerfReportJsonPath,
|
|
24
|
+
} from '../../config/temp-paths.js';
|
|
25
|
+
import { Logger } from '../../Logger.js';
|
|
26
|
+
import { render as renderLifecycleTrace } from '../lifecycle/trace-logger.js';
|
|
27
|
+
import { upsertStructuredComment as defaultUpsertStructuredComment } from '../ticketing.js';
|
|
28
|
+
|
|
29
|
+
export const EPIC_HANDOFF_MARKER = 'epic-handoff';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Byte budget for the embedded run-trace digest. The digest is the
|
|
33
|
+
* `TraceLogger` Summary block only (phase list + per-phase durations +
|
|
34
|
+
* event/completed/failed counts), so it is small by construction — but we
|
|
35
|
+
* cap it well under GitHub's ~64KB comment limit so a pathological ledger
|
|
36
|
+
* with a huge phase list still degrades to a truncated note + the
|
|
37
|
+
* relative-path link rather than blowing the comment budget. Story #3669.
|
|
38
|
+
*/
|
|
39
|
+
export const RUN_TRACE_MAX_BYTES = 8000;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Format a millisecond duration as a compact wall-clock string for the
|
|
43
|
+
* per-wave perf summary lines. Sub-second values render as `<n>ms`;
|
|
44
|
+
* second-scale values as `<n.n>s`; minute-scale values as `<m>m<ss>s`.
|
|
45
|
+
* Story #3029 / Task #3041.
|
|
46
|
+
*
|
|
47
|
+
* @param {number} ms
|
|
48
|
+
* @returns {string}
|
|
49
|
+
*/
|
|
50
|
+
function formatDurationMs(ms) {
|
|
51
|
+
const n = Number.isFinite(ms) ? Math.max(0, Math.floor(ms)) : 0;
|
|
52
|
+
if (n < 1000) return `${n}ms`;
|
|
53
|
+
if (n < 60000) return `${(n / 1000).toFixed(1)}s`;
|
|
54
|
+
const minutes = Math.floor(n / 60000);
|
|
55
|
+
const seconds = Math.floor((n % 60000) / 1000);
|
|
56
|
+
return `${minutes}m${seconds.toString().padStart(2, '0')}s`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Render the Performance Report section appended to the `epic-handoff`
|
|
61
|
+
* comment body. Returns an empty string when `perfReport` is null /
|
|
62
|
+
* undefined (no JSON on disk → section omitted) so callers can splice
|
|
63
|
+
* the result in unconditionally.
|
|
64
|
+
*
|
|
65
|
+
* Output contract (Story #3029 / Task #3041):
|
|
66
|
+
* - `## Performance Report` heading
|
|
67
|
+
* - One relative link line to `temp/epic-<id>/epic-perf-report.json`
|
|
68
|
+
* - One bullet per wave: `Wave N: <wall> wall / <story> story / util <pct>% [cap binding]`
|
|
69
|
+
*
|
|
70
|
+
* @param {{
|
|
71
|
+
* relativePath: string,
|
|
72
|
+
* waveParallelism: Array<{ waveIndex: number, wallClockMs: number, summedStoryMs: number, utilisation: number, capBinding: boolean, verifyConcurrencyCap?: number }>,
|
|
73
|
+
* } | null | undefined} perfReport
|
|
74
|
+
* @returns {string}
|
|
75
|
+
*/
|
|
76
|
+
export function renderPerfReportSection(perfReport) {
|
|
77
|
+
if (!perfReport || typeof perfReport.relativePath !== 'string') return '';
|
|
78
|
+
const waves = Array.isArray(perfReport.waveParallelism)
|
|
79
|
+
? perfReport.waveParallelism
|
|
80
|
+
: [];
|
|
81
|
+
const lines = [];
|
|
82
|
+
lines.push('');
|
|
83
|
+
lines.push('## Performance Report');
|
|
84
|
+
lines.push('');
|
|
85
|
+
lines.push(
|
|
86
|
+
`Persisted to [\`${perfReport.relativePath}\`](${perfReport.relativePath}).`,
|
|
87
|
+
);
|
|
88
|
+
lines.push('');
|
|
89
|
+
if (waves.length === 0) {
|
|
90
|
+
lines.push('No wave-parallelism rows recorded.');
|
|
91
|
+
} else {
|
|
92
|
+
for (const wave of waves) {
|
|
93
|
+
const wall = formatDurationMs(wave.wallClockMs);
|
|
94
|
+
const story = formatDurationMs(wave.summedStoryMs);
|
|
95
|
+
const util = Number.isFinite(wave.utilisation)
|
|
96
|
+
? (wave.utilisation * 100).toFixed(0)
|
|
97
|
+
: '0';
|
|
98
|
+
const capLabel = wave.capBinding ? 'cap binding' : 'cap not binding';
|
|
99
|
+
lines.push(
|
|
100
|
+
`- Wave ${wave.waveIndex}: ${wall} wall / ${story} story / util ${util}% [${capLabel}]`,
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return lines.join('\n');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Slice the `## Summary` block out of the full `lifecycle.md` projection.
|
|
109
|
+
* The TraceLogger `render()` output ends with a `## Summary` section (phase
|
|
110
|
+
* list, per-phase durations, event/completed/failed counts); everything
|
|
111
|
+
* before it is the per-event trace, which the Story explicitly excludes
|
|
112
|
+
* from the embedded digest. Returns the Summary body (the lines *after* the
|
|
113
|
+
* `## Summary` heading, trimmed) or `''` when no Summary heading is present.
|
|
114
|
+
*
|
|
115
|
+
* @param {string} fullMarkdown
|
|
116
|
+
* @returns {string}
|
|
117
|
+
*/
|
|
118
|
+
function summaryBlockFrom(fullMarkdown) {
|
|
119
|
+
const marker = '## Summary';
|
|
120
|
+
const idx = fullMarkdown.indexOf(marker);
|
|
121
|
+
if (idx < 0) return '';
|
|
122
|
+
return fullMarkdown.slice(idx + marker.length).trim();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Project the canonical lifecycle ledger NDJSON into the compact run-trace
|
|
127
|
+
* digest embedded in the handoff comment. Reuses the pure `TraceLogger`
|
|
128
|
+
* `render()` projection and keeps only its Summary rollup — never the full
|
|
129
|
+
* per-event trace (Story #3669 acceptance).
|
|
130
|
+
*
|
|
131
|
+
* Pure + read-only: it parses the supplied ledger text and never touches
|
|
132
|
+
* the filesystem or mutates the ledger. Returns `null` on:
|
|
133
|
+
* - a missing / empty ledger (no emitted records → empty Summary), or
|
|
134
|
+
* - a malformed ledger (the underlying `render` throws on bad JSON; we
|
|
135
|
+
* swallow it so the section degrades gracefully instead of blocking
|
|
136
|
+
* the PR open).
|
|
137
|
+
*
|
|
138
|
+
* When the projected Summary exceeds `maxBytes`, the digest is truncated on
|
|
139
|
+
* a UTF-8-safe boundary and `truncated: true` is set so the renderer can
|
|
140
|
+
* append a note and keep the relative-path link to the full `lifecycle.md`.
|
|
141
|
+
*
|
|
142
|
+
* @param {{
|
|
143
|
+
* ledgerText: string,
|
|
144
|
+
* epicId: number,
|
|
145
|
+
* relativePath: string,
|
|
146
|
+
* maxBytes?: number,
|
|
147
|
+
* }} args
|
|
148
|
+
* @returns {{ digest: string, relativePath: string, truncated: boolean } | null}
|
|
149
|
+
*/
|
|
150
|
+
export function extractRunTraceDigest({
|
|
151
|
+
ledgerText,
|
|
152
|
+
epicId,
|
|
153
|
+
relativePath,
|
|
154
|
+
maxBytes = RUN_TRACE_MAX_BYTES,
|
|
155
|
+
} = {}) {
|
|
156
|
+
if (typeof ledgerText !== 'string' || ledgerText.trim().length === 0) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
let fullMarkdown;
|
|
160
|
+
try {
|
|
161
|
+
fullMarkdown = renderLifecycleTrace(ledgerText, { epicId });
|
|
162
|
+
} catch {
|
|
163
|
+
// Malformed ledger (parseLedger throws on bad JSON). Degrade to no
|
|
164
|
+
// section rather than propagating and blocking the handoff comment.
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
const summary = summaryBlockFrom(fullMarkdown);
|
|
168
|
+
if (summary.length === 0) return null;
|
|
169
|
+
|
|
170
|
+
const budget =
|
|
171
|
+
Number.isInteger(maxBytes) && maxBytes > 0 ? maxBytes : RUN_TRACE_MAX_BYTES;
|
|
172
|
+
if (Buffer.byteLength(summary, 'utf8') <= budget) {
|
|
173
|
+
return { digest: summary, relativePath, truncated: false };
|
|
174
|
+
}
|
|
175
|
+
// Truncate on a UTF-8-safe boundary: take a byte slice, then drop any
|
|
176
|
+
// trailing partial multibyte sequence by decoding with replacement and
|
|
177
|
+
// stripping the U+FFFD tail.
|
|
178
|
+
const sliced = Buffer.from(summary, 'utf8')
|
|
179
|
+
.subarray(0, budget)
|
|
180
|
+
.toString('utf8')
|
|
181
|
+
.replace(/�+$/u, '');
|
|
182
|
+
return { digest: sliced, relativePath, truncated: true };
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Render the "Run trace" digest section appended to the `epic-handoff`
|
|
187
|
+
* comment. Returns `''` when `runTrace` is null / malformed so callers can
|
|
188
|
+
* splice the result in unconditionally — mirrors `renderPerfReportSection`.
|
|
189
|
+
*
|
|
190
|
+
* Output contract (Story #3669):
|
|
191
|
+
* - `## Run trace` heading
|
|
192
|
+
* - One relative link line to `temp/epic-<id>/lifecycle.md`
|
|
193
|
+
* - The TraceLogger Summary rollup (phase durations + counts)
|
|
194
|
+
* - A truncation note when the projection overflowed the byte budget
|
|
195
|
+
*
|
|
196
|
+
* @param {{ digest: string, relativePath: string, truncated?: boolean } | null | undefined} runTrace
|
|
197
|
+
* @returns {string}
|
|
198
|
+
*/
|
|
199
|
+
export function renderRunTraceSection(runTrace) {
|
|
200
|
+
if (
|
|
201
|
+
!runTrace ||
|
|
202
|
+
typeof runTrace.digest !== 'string' ||
|
|
203
|
+
runTrace.digest.length === 0 ||
|
|
204
|
+
typeof runTrace.relativePath !== 'string'
|
|
205
|
+
) {
|
|
206
|
+
return '';
|
|
207
|
+
}
|
|
208
|
+
const lines = [];
|
|
209
|
+
lines.push('');
|
|
210
|
+
lines.push('## Run trace');
|
|
211
|
+
lines.push('');
|
|
212
|
+
lines.push(
|
|
213
|
+
`Full lifecycle companion: [\`${runTrace.relativePath}\`](${runTrace.relativePath}).`,
|
|
214
|
+
);
|
|
215
|
+
lines.push('');
|
|
216
|
+
lines.push(runTrace.digest);
|
|
217
|
+
if (runTrace.truncated) {
|
|
218
|
+
lines.push('');
|
|
219
|
+
lines.push(
|
|
220
|
+
`_Digest truncated to fit the comment budget — see [\`${runTrace.relativePath}\`](${runTrace.relativePath}) for the full trace._`,
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
return lines.join('\n');
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Default loader: read the canonical `temp/epic-<id>/lifecycle.ndjson`
|
|
228
|
+
* ledger from disk and project it into the run-trace digest envelope
|
|
229
|
+
* `renderRunTraceSection` expects. Returns `null` on any failure (missing
|
|
230
|
+
* file, malformed JSON, empty ledger) so the handoff comment degrades
|
|
231
|
+
* gracefully — mirrors `loadPerfReportFromDisk`.
|
|
232
|
+
*
|
|
233
|
+
* `relativePath` points at the rendered `lifecycle.md` companion (the same
|
|
234
|
+
* directory as the ledger), computed relative to `cwd` so consumers can
|
|
235
|
+
* follow the link from the rendered comment. Falls back to the absolute
|
|
236
|
+
* path when the companion resolves outside `cwd`.
|
|
237
|
+
*
|
|
238
|
+
* @param {{ epicId: number, config?: object, cwd?: string }} args
|
|
239
|
+
* @returns {Promise<{ digest: string, relativePath: string, truncated: boolean } | null>}
|
|
240
|
+
*/
|
|
241
|
+
export async function loadRunTraceFromDisk({
|
|
242
|
+
epicId,
|
|
243
|
+
config,
|
|
244
|
+
cwd = process.cwd(),
|
|
245
|
+
} = {}) {
|
|
246
|
+
if (!Number.isInteger(epicId) || epicId < 1) return null;
|
|
247
|
+
let ledgerAbsPath;
|
|
248
|
+
try {
|
|
249
|
+
ledgerAbsPath = epicLedgerPath(epicId, config);
|
|
250
|
+
} catch {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
let ledgerText;
|
|
254
|
+
try {
|
|
255
|
+
ledgerText = await fs.readFile(ledgerAbsPath, 'utf8');
|
|
256
|
+
} catch {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
const companionAbsPath = path.join(
|
|
260
|
+
path.dirname(ledgerAbsPath),
|
|
261
|
+
'lifecycle.md',
|
|
262
|
+
);
|
|
263
|
+
let relativePath;
|
|
264
|
+
try {
|
|
265
|
+
const rel = path.relative(cwd, companionAbsPath);
|
|
266
|
+
relativePath =
|
|
267
|
+
rel && !rel.startsWith('..') && !path.isAbsolute(rel)
|
|
268
|
+
? rel
|
|
269
|
+
: companionAbsPath;
|
|
270
|
+
relativePath = relativePath.split(path.sep).join('/');
|
|
271
|
+
} catch {
|
|
272
|
+
relativePath = companionAbsPath;
|
|
273
|
+
}
|
|
274
|
+
return extractRunTraceDigest({ ledgerText, epicId, relativePath });
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Render the `epic-handoff` comment body. Pure helper — exported so the
|
|
279
|
+
* contract tests can assert the rendered shape without standing up a
|
|
280
|
+
* provider.
|
|
281
|
+
*
|
|
282
|
+
* @param {{ epicId: number, prNumber: number, prUrl?: string|null }} input
|
|
283
|
+
* @returns {string} markdown body (without the structured-comment marker
|
|
284
|
+
* prefix — the marker is prepended by `upsertStructuredComment`).
|
|
285
|
+
*/
|
|
286
|
+
export function renderHandoffBody({
|
|
287
|
+
epicId,
|
|
288
|
+
prNumber,
|
|
289
|
+
prUrl = null,
|
|
290
|
+
perfReport = null,
|
|
291
|
+
runTrace = null,
|
|
292
|
+
} = {}) {
|
|
293
|
+
const lines = [];
|
|
294
|
+
lines.push('### 🤝 Epic handoff — PR opened');
|
|
295
|
+
lines.push('');
|
|
296
|
+
lines.push(`Epic: #${epicId}`);
|
|
297
|
+
if (typeof prUrl === 'string' && prUrl.length > 0) {
|
|
298
|
+
lines.push(`Pull request: [#${prNumber}](${prUrl})`);
|
|
299
|
+
} else {
|
|
300
|
+
lines.push(`Pull request: #${prNumber}`);
|
|
301
|
+
}
|
|
302
|
+
lines.push('');
|
|
303
|
+
lines.push(
|
|
304
|
+
'Auto-merge will arm once the watch-and-iterate gate (Phase 8) confirms required checks are green.',
|
|
305
|
+
);
|
|
306
|
+
// Story #3029 / Task #3041 — Performance Report section. Empty string
|
|
307
|
+
// is returned when no perf report is available, so the existing body
|
|
308
|
+
// shape is preserved for handoffs that fire before the close tail has
|
|
309
|
+
// emitted a report (e.g. legacy replays).
|
|
310
|
+
const perfSection = renderPerfReportSection(perfReport);
|
|
311
|
+
if (perfSection.length > 0) {
|
|
312
|
+
lines.push(perfSection);
|
|
313
|
+
}
|
|
314
|
+
// Story #3669 — Run trace digest section. Empty string is returned when
|
|
315
|
+
// no ledger digest is available (missing/malformed ledger → section
|
|
316
|
+
// omitted), so the body shape is preserved for handoffs that fire before
|
|
317
|
+
// a ledger exists.
|
|
318
|
+
const runTraceSection = renderRunTraceSection(runTrace);
|
|
319
|
+
if (runTraceSection.length > 0) {
|
|
320
|
+
lines.push(runTraceSection);
|
|
321
|
+
}
|
|
322
|
+
lines.push('');
|
|
323
|
+
lines.push('```json');
|
|
324
|
+
lines.push(
|
|
325
|
+
JSON.stringify(
|
|
326
|
+
{ kind: 'epic-handoff', epicId, prNumber, prUrl: prUrl ?? null },
|
|
327
|
+
null,
|
|
328
|
+
2,
|
|
329
|
+
),
|
|
330
|
+
);
|
|
331
|
+
lines.push('```');
|
|
332
|
+
return lines.join('\n');
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Default loader: read the canonical `epic-perf-report.json` snapshot
|
|
337
|
+
* from disk (when present) and shape it into the
|
|
338
|
+
* `{ relativePath, waveParallelism }` envelope `renderPerfReportSection`
|
|
339
|
+
* expects. Returns `null` on any failure (missing file, malformed JSON,
|
|
340
|
+
* unreadable directory) so the handoff comment degrades gracefully to
|
|
341
|
+
* the pre-Story-#3029 body shape rather than blocking the PR open.
|
|
342
|
+
*
|
|
343
|
+
* `relativePath` is computed relative to `cwd` so consumers cloning the
|
|
344
|
+
* repo can follow the link from the rendered comment. When the report
|
|
345
|
+
* path resolves outside `cwd`, falls back to the absolute path (rare —
|
|
346
|
+
* happens only for callers that point `tempRoot` outside the repo).
|
|
347
|
+
*
|
|
348
|
+
* @param {{ epicId: number, config?: object, cwd?: string }} args
|
|
349
|
+
* @returns {Promise<{ relativePath: string, waveParallelism: Array<object> } | null>}
|
|
350
|
+
*/
|
|
351
|
+
export async function loadPerfReportFromDisk({
|
|
352
|
+
epicId,
|
|
353
|
+
config,
|
|
354
|
+
cwd = process.cwd(),
|
|
355
|
+
} = {}) {
|
|
356
|
+
if (!Number.isInteger(epicId) || epicId < 1) return null;
|
|
357
|
+
let absPath;
|
|
358
|
+
try {
|
|
359
|
+
absPath = epicPerfReportJsonPath(epicId, config);
|
|
360
|
+
} catch {
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
let raw;
|
|
364
|
+
try {
|
|
365
|
+
raw = await fs.readFile(absPath, 'utf8');
|
|
366
|
+
} catch {
|
|
367
|
+
return null;
|
|
368
|
+
}
|
|
369
|
+
let payload;
|
|
370
|
+
try {
|
|
371
|
+
payload = JSON.parse(raw);
|
|
372
|
+
} catch {
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
if (!payload || typeof payload !== 'object') return null;
|
|
376
|
+
let relativePath;
|
|
377
|
+
try {
|
|
378
|
+
const rel = path.relative(cwd, absPath);
|
|
379
|
+
relativePath =
|
|
380
|
+
rel && !rel.startsWith('..') && !path.isAbsolute(rel) ? rel : absPath;
|
|
381
|
+
// Normalize Windows backslashes so the rendered Markdown link works
|
|
382
|
+
// on both POSIX consumers and Windows operators.
|
|
383
|
+
relativePath = relativePath.split(path.sep).join('/');
|
|
384
|
+
} catch {
|
|
385
|
+
relativePath = absPath;
|
|
386
|
+
}
|
|
387
|
+
return {
|
|
388
|
+
relativePath,
|
|
389
|
+
waveParallelism: Array.isArray(payload.waveParallelism)
|
|
390
|
+
? payload.waveParallelism
|
|
391
|
+
: [],
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Upsert the `epic-handoff` structured comment on the Epic ticket.
|
|
397
|
+
*
|
|
398
|
+
* @param {object} args
|
|
399
|
+
* @param {number} args.epicId
|
|
400
|
+
* @param {number} args.prNumber
|
|
401
|
+
* @param {string} [args.prUrl]
|
|
402
|
+
* @param {object} args.provider — ITicketingProvider used by
|
|
403
|
+
* `upsertStructuredComment`.
|
|
404
|
+
* @param {Function} [args.upsertStructuredCommentFn] — override for
|
|
405
|
+
* tests.
|
|
406
|
+
* @param {object} [args.logger]
|
|
407
|
+
* @returns {Promise<{ marker: string, commentId: number|null }>}
|
|
408
|
+
*/
|
|
409
|
+
export async function postHandoffComment({
|
|
410
|
+
epicId,
|
|
411
|
+
prNumber,
|
|
412
|
+
prUrl,
|
|
413
|
+
provider,
|
|
414
|
+
config,
|
|
415
|
+
cwd,
|
|
416
|
+
perfReport,
|
|
417
|
+
runTrace,
|
|
418
|
+
loadPerfReportFn = loadPerfReportFromDisk,
|
|
419
|
+
loadRunTraceFn = loadRunTraceFromDisk,
|
|
420
|
+
upsertStructuredCommentFn = defaultUpsertStructuredComment,
|
|
421
|
+
logger = Logger,
|
|
422
|
+
} = {}) {
|
|
423
|
+
if (!Number.isInteger(epicId) || epicId < 1) {
|
|
424
|
+
throw new TypeError(
|
|
425
|
+
'postHandoffComment: epicId must be a positive integer',
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
if (!Number.isInteger(prNumber) || prNumber < 1) {
|
|
429
|
+
throw new TypeError(
|
|
430
|
+
'postHandoffComment: prNumber must be a positive integer',
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
if (!provider) {
|
|
434
|
+
throw new TypeError('postHandoffComment: provider is required');
|
|
435
|
+
}
|
|
436
|
+
// Story #3029 / Task #3041 — if an explicit `perfReport` envelope is
|
|
437
|
+
// not supplied, fall back to reading the persisted JSON written by
|
|
438
|
+
// the close-tail. Any loader failure resolves to `null` and the
|
|
439
|
+
// Performance Report section is silently omitted.
|
|
440
|
+
let resolvedPerfReport = perfReport;
|
|
441
|
+
if (resolvedPerfReport === undefined) {
|
|
442
|
+
try {
|
|
443
|
+
resolvedPerfReport = await loadPerfReportFn({ epicId, config, cwd });
|
|
444
|
+
} catch (err) {
|
|
445
|
+
logger.warn?.(
|
|
446
|
+
`[finalize/post-handoff-comment] perf-report load failed for Epic #${epicId} (non-fatal): ${err?.message ?? err}`,
|
|
447
|
+
);
|
|
448
|
+
resolvedPerfReport = null;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
// Story #3669 — if an explicit `runTrace` envelope is not supplied, fall
|
|
452
|
+
// back to projecting the canonical lifecycle ledger from disk. Any loader
|
|
453
|
+
// failure resolves to `null` and the Run trace section is silently
|
|
454
|
+
// omitted, never blocking the handoff comment / PR open.
|
|
455
|
+
let resolvedRunTrace = runTrace;
|
|
456
|
+
if (resolvedRunTrace === undefined) {
|
|
457
|
+
try {
|
|
458
|
+
resolvedRunTrace = await loadRunTraceFn({ epicId, config, cwd });
|
|
459
|
+
} catch (err) {
|
|
460
|
+
logger.warn?.(
|
|
461
|
+
`[finalize/post-handoff-comment] run-trace load failed for Epic #${epicId} (non-fatal): ${err?.message ?? err}`,
|
|
462
|
+
);
|
|
463
|
+
resolvedRunTrace = null;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
const body = renderHandoffBody({
|
|
467
|
+
epicId,
|
|
468
|
+
prNumber,
|
|
469
|
+
prUrl: prUrl ?? null,
|
|
470
|
+
perfReport: resolvedPerfReport,
|
|
471
|
+
runTrace: resolvedRunTrace,
|
|
472
|
+
});
|
|
473
|
+
try {
|
|
474
|
+
const result = await upsertStructuredCommentFn(
|
|
475
|
+
provider,
|
|
476
|
+
epicId,
|
|
477
|
+
EPIC_HANDOFF_MARKER,
|
|
478
|
+
body,
|
|
479
|
+
);
|
|
480
|
+
const commentId =
|
|
481
|
+
typeof result?.commentId === 'number' ? result.commentId : null;
|
|
482
|
+
return { marker: EPIC_HANDOFF_MARKER, commentId };
|
|
483
|
+
} catch (err) {
|
|
484
|
+
logger.warn?.(
|
|
485
|
+
`[finalize/post-handoff-comment] upsert failed for Epic #${epicId}: ${err?.message ?? err}`,
|
|
486
|
+
);
|
|
487
|
+
throw err;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// .agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js
|
|
2
|
+
/**
|
|
3
|
+
* sanitize-skip-ci.js — pure helper that strips GitHub Actions
|
|
4
|
+
* `[skip ci]` markers (and the four variant spellings GitHub honours)
|
|
5
|
+
* from a text payload.
|
|
6
|
+
*
|
|
7
|
+
* Story #3165: `/epic-deliver` Phase 7 opens a PR squashed into `main`
|
|
8
|
+
* via `gh pr merge --squash`. Story commits legitimately carry
|
|
9
|
+
* `[skip ci]` markers under `delivery.ci.skipForStoryPushes: true` to
|
|
10
|
+
* keep CI from firing on the wave's intermediate pushes. When GitHub
|
|
11
|
+
* composes the squash commit body by concatenating constituent commit
|
|
12
|
+
* messages, those markers propagate into the squash body and suppress
|
|
13
|
+
* `ci.yml` + `release-please.yml` on `main` — even though the squash
|
|
14
|
+
* subject is just `Epic #<id> (#<pr>)`.
|
|
15
|
+
*
|
|
16
|
+
* The first defence is to ensure the PR body (assembled by
|
|
17
|
+
* `openOrLocatePr` and handed to `gh pr create`) carries no raw
|
|
18
|
+
* skip-ci markers, so any tooling that derives the squash body from
|
|
19
|
+
* the PR body (or from text that flows through this helper) cannot
|
|
20
|
+
* re-introduce the suppression.
|
|
21
|
+
*
|
|
22
|
+
* Markers stripped (case-insensitive, optional inner spaces, optional
|
|
23
|
+
* brackets per GitHub's documented contract — only the bracketed
|
|
24
|
+
* forms actually suppress CI, so those are the only forms removed):
|
|
25
|
+
*
|
|
26
|
+
* - `[skip ci]` / `[ci skip]`
|
|
27
|
+
* - `[no ci]`
|
|
28
|
+
* - `[skip actions]` / `[actions skip]`
|
|
29
|
+
*
|
|
30
|
+
* Reference: GitHub Actions docs, "Skipping workflow runs":
|
|
31
|
+
* https://docs.github.com/en/actions/managing-workflow-runs/skipping-workflow-runs
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Canonical regex list. Frozen so callers can introspect (e.g. a
|
|
36
|
+
* contract test that asserts the documented marker set is what the
|
|
37
|
+
* sanitizer actually matches) without mutating the SSOT.
|
|
38
|
+
*
|
|
39
|
+
* Each pattern matches the bracketed form only — bare `skip ci`
|
|
40
|
+
* without brackets does NOT suppress CI on GitHub and is left
|
|
41
|
+
* untouched.
|
|
42
|
+
*/
|
|
43
|
+
export const SKIP_CI_PATTERNS = Object.freeze([
|
|
44
|
+
/\[\s*skip\s+ci\s*\]/gi,
|
|
45
|
+
/\[\s*ci\s+skip\s*\]/gi,
|
|
46
|
+
/\[\s*no\s+ci\s*\]/gi,
|
|
47
|
+
/\[\s*skip\s+actions\s*\]/gi,
|
|
48
|
+
/\[\s*actions\s+skip\s*\]/gi,
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Strip every GitHub-recognised `[skip ci]` variant from `text`.
|
|
53
|
+
*
|
|
54
|
+
* Non-string input (null / undefined / number) is returned unchanged
|
|
55
|
+
* so the helper can be folded into an optional-body assembly chain
|
|
56
|
+
* without forcing the caller to guard.
|
|
57
|
+
*
|
|
58
|
+
* Multiple consecutive matches collapse cleanly:
|
|
59
|
+
* - Each matched marker is replaced with the empty string.
|
|
60
|
+
* - Runs of whitespace that the deletion leaves behind on the same
|
|
61
|
+
* line collapse to a single space.
|
|
62
|
+
* - Trailing whitespace on each line is trimmed.
|
|
63
|
+
* - Runs of three or more blank lines collapse to a single blank
|
|
64
|
+
* line (so a body that was nothing but markers doesn't leave a
|
|
65
|
+
* gaping vertical gap).
|
|
66
|
+
*
|
|
67
|
+
* The helper is intentionally idempotent: `sanitize(sanitize(x)) ===
|
|
68
|
+
* sanitize(x)` for every input.
|
|
69
|
+
*
|
|
70
|
+
* @param {string} text
|
|
71
|
+
* @returns {string}
|
|
72
|
+
*/
|
|
73
|
+
export function sanitizeSkipCiMarkers(text) {
|
|
74
|
+
if (typeof text !== 'string') return text;
|
|
75
|
+
let out = text;
|
|
76
|
+
for (const pattern of SKIP_CI_PATTERNS) {
|
|
77
|
+
out = out.replace(pattern, '');
|
|
78
|
+
}
|
|
79
|
+
// Collapse intra-line whitespace runs left behind by deletions, but
|
|
80
|
+
// preserve line boundaries so paragraph structure survives.
|
|
81
|
+
out = out
|
|
82
|
+
.split('\n')
|
|
83
|
+
.map((line) => line.replace(/[ \t]{2,}/g, ' ').replace(/[ \t]+$/g, ''))
|
|
84
|
+
.join('\n');
|
|
85
|
+
// Collapse runs of 3+ blank lines down to one blank line.
|
|
86
|
+
out = out.replace(/\n{3,}/g, '\n\n');
|
|
87
|
+
return out;
|
|
88
|
+
}
|