mandrel 1.93.0 → 2.0.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 +59 -73
- package/.agents/agents/acceptance-critic.md +129 -0
- package/.agents/agents/story-worker.md +161 -0
- package/.agents/docs/SDLC.md +489 -1285
- package/.agents/docs/agentrc-reference.json +177 -67
- package/.agents/docs/configuration.md +108 -136
- package/.agents/docs/execution-reference.md +44 -22
- package/.agents/docs/quality-gates.md +13 -19
- package/.agents/docs/workflows.md +3 -3
- package/.agents/instructions.md +107 -108
- package/.agents/rules/ci-remediation.md +8 -12
- package/.agents/rules/git-conventions-reference.md +224 -0
- package/.agents/rules/git-conventions.md +42 -223
- package/.agents/rules/security-baseline.md +5 -0
- package/.agents/rules/testing-standards.md +106 -13
- package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
- package/.agents/schemas/agentrc.schema.json +71 -201
- package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
- package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
- package/.agents/schemas/risk-verdict.schema.json +0 -13
- package/.agents/scripts/acceptance-eval.js +62 -18
- package/.agents/scripts/agents-bootstrap-github.js +1 -1
- package/.agents/scripts/analyze-execution.js +1 -1
- package/.agents/scripts/audit-to-stories.js +7 -7
- package/.agents/scripts/boot-sweep.js +1 -1
- package/.agents/scripts/check-context-budget.js +62 -5
- package/.agents/scripts/check-lifecycle-lint.js +6 -9
- package/.agents/scripts/check-prepush-recovery.js +1 -1
- package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
- package/.agents/scripts/diagnose-friction.js +0 -6
- package/.agents/scripts/lib/Logger.js +6 -10
- package/.agents/scripts/lib/audit-suite/runner.js +2 -2
- package/.agents/scripts/lib/audit-suite/selector.js +5 -5
- package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
- package/.agents/scripts/lib/baselines/kernel.js +206 -18
- package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -4
- package/.agents/scripts/lib/baselines/reader.js +1 -6
- package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
- package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +56 -18
- package/.agents/scripts/lib/checks/core-bare-clean.js +2 -2
- package/.agents/scripts/lib/checks/index.js +2 -1
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +23 -21
- package/.agents/scripts/lib/cli/standard-args.js +13 -22
- package/.agents/scripts/lib/cli-args.js +16 -7
- package/.agents/scripts/lib/close-validation/gates.js +160 -22
- package/.agents/scripts/lib/config/acceptance-eval.js +52 -5
- package/.agents/scripts/lib/config/ci.js +6 -31
- package/.agents/scripts/lib/config/delivery-routing.js +103 -0
- package/.agents/scripts/lib/config/explain.js +57 -36
- package/.agents/scripts/lib/config/limits.js +17 -58
- package/.agents/scripts/lib/config/paths.js +0 -2
- package/.agents/scripts/lib/config/quality.js +1 -1
- package/.agents/scripts/lib/config/runners.js +17 -50
- package/.agents/scripts/lib/config/temp-paths.js +19 -14
- package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
- package/.agents/scripts/lib/config-resolver.js +3 -8
- package/.agents/scripts/lib/config-settings-schema-delivery.js +46 -136
- package/.agents/scripts/lib/config-settings-schema-quality.js +17 -14
- package/.agents/scripts/lib/config-settings-schema.js +52 -38
- package/.agents/scripts/lib/dependency-parser.js +3 -2
- package/.agents/scripts/lib/doc-tiers.js +39 -4
- package/.agents/scripts/lib/duplicate-search.js +211 -41
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
- package/.agents/scripts/lib/findings/promote-finding.js +5 -5
- package/.agents/scripts/lib/framework-version.js +2 -3
- package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
- package/.agents/scripts/lib/git-branch-lifecycle.js +17 -22
- package/.agents/scripts/lib/git-utils.js +32 -6
- package/.agents/scripts/lib/github/framework-repo.js +6 -0
- package/.agents/scripts/lib/label-constants.js +10 -23
- package/.agents/scripts/lib/label-taxonomy.js +9 -43
- package/.agents/scripts/lib/observability/active-story-env.js +112 -3
- package/.agents/scripts/lib/observability/hook-heartbeat.js +187 -0
- package/.agents/scripts/lib/observability/source-classifier.js +3 -3
- package/.agents/scripts/lib/observability/tool-trace-hook.js +15 -4
- package/.agents/scripts/lib/onboard/init-tail.js +1 -3
- package/.agents/scripts/lib/orchestration/acceptance-clusters.js +111 -0
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +32 -4
- package/.agents/scripts/lib/orchestration/audit-lens-routing.js +128 -0
- package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +273 -0
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +204 -0
- package/.agents/scripts/lib/orchestration/code-review.js +20 -268
- package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
- package/.agents/scripts/lib/orchestration/consolidation-precondition.js +1 -1
- package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
- package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
- package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +8 -8
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +2 -2
- package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +17 -43
- package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
- package/.agents/scripts/lib/orchestration/merge-block-class.js +1 -1
- package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
- package/.agents/scripts/lib/orchestration/plan-context.js +248 -266
- package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +3 -2
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +1 -1
- package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
- package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +61 -0
- package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +97 -0
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +223 -854
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +361 -0
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +35 -108
- package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
- package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
- package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +14 -14
- package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
- package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/risk-verdict.js +3 -4
- package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +2 -2
- package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +8 -20
- package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +3 -2
- package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
- package/.agents/scripts/lib/orchestration/preflight-cache.js +5 -5
- package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
- package/.agents/scripts/lib/orchestration/resolve-plan-run.js +155 -0
- package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
- package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +8 -8
- package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
- package/.agents/scripts/lib/orchestration/review-depth.js +26 -12
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
- package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
- package/.agents/scripts/lib/orchestration/run-epilogue.js +426 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +1 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +95 -41
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +16 -13
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +40 -0
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +11 -3
- package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
- package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
- package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
- package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
- package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +15 -12
- package/.agents/scripts/lib/orchestration/story-follow-ups.js +237 -0
- package/.agents/scripts/lib/orchestration/story-init-remote.js +47 -0
- package/.agents/scripts/lib/orchestration/story-plan-state.js +48 -0
- package/.agents/scripts/lib/orchestration/{epic-runner → story-progress}/story-run-progress-writer.js +3 -3
- package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
- package/.agents/scripts/lib/orchestration/task-body-validator.js +8 -18
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +11 -61
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +189 -373
- package/.agents/scripts/lib/orchestration/ticket-validator.js +3 -8
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +0 -25
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +29 -26
- package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -5
- package/.agents/scripts/lib/planning-corpus.js +16 -11
- package/.agents/scripts/lib/preflight-runner.js +2 -2
- package/.agents/scripts/lib/provider-factory.js +1 -1
- package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
- package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +36 -0
- package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
- package/.agents/scripts/lib/story-adjacency.js +11 -14
- package/.agents/scripts/lib/story-body/story-body.js +124 -70
- package/.agents/scripts/lib/story-plan.js +2 -4
- package/.agents/scripts/lib/templates/decomposer-prompts.js +46 -45
- package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
- package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +26 -26
- package/.agents/scripts/lib/validation-evidence.js +1 -1
- package/.agents/scripts/lib/wave-runner/ready-set.js +6 -6
- package/.agents/scripts/lib/workspace-provisioner.js +1 -1
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +5 -7
- package/.agents/scripts/lint-issue-body.js +71 -40
- package/.agents/scripts/mandrel-update-preflight.js +1 -1
- package/.agents/scripts/notify.js +4 -3
- package/.agents/scripts/plan-context.js +64 -74
- package/.agents/scripts/plan-persist.js +121 -280
- package/.agents/scripts/plan-run-epilogue.js +97 -0
- package/.agents/scripts/post-structured-comment.js +38 -0
- package/.agents/scripts/providers/github/issues.js +17 -33
- package/.agents/scripts/providers/github/mappers.js +0 -12
- package/.agents/scripts/providers/github/tickets.js +2 -5
- package/.agents/scripts/resolve-plan-run.js +117 -0
- package/.agents/scripts/signals-view.js +24 -19
- package/.agents/scripts/single-story-close.js +11 -14
- package/.agents/scripts/single-story-confirm-merge.js +39 -23
- package/.agents/scripts/single-story-init.js +29 -20
- package/.agents/scripts/stories-wave-tick.js +6 -6
- package/.agents/scripts/story-plan.js +26 -47
- package/.agents/scripts/sync-claude-agents.js +165 -0
- package/.agents/scripts/update-ticket-state.js +37 -15
- package/.agents/skills/core/analyze-execution/SKILL.md +21 -18
- package/.agents/skills/core/api-and-interface-design/SKILL.md +5 -3
- package/.agents/skills/core/code-review-and-quality/SKILL.md +63 -7
- package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +1 -1
- package/.agents/skills/core/gates-and-baselines/SKILL.md +149 -0
- package/.agents/skills/core/idea-refinement/SKILL.md +8 -14
- package/.agents/skills/core/qa-coverage-mapping/SKILL.md +7 -7
- package/.agents/skills/core/scope-triage/SKILL.md +28 -172
- package/.agents/skills/skills.index.json +8 -418
- package/.agents/starter-agentrc.json +0 -5
- package/.agents/templates/agent-protocol.md +9 -10
- package/.agents/workflows/audit-architecture.md +3 -3
- package/.agents/workflows/audit-clean-code.md +3 -3
- package/.agents/workflows/audit-dependencies.md +3 -3
- package/.agents/workflows/audit-devops.md +3 -3
- package/.agents/workflows/audit-documentation.md +5 -5
- package/.agents/workflows/audit-lighthouse.md +3 -3
- package/.agents/workflows/audit-navigability.md +3 -2
- package/.agents/workflows/audit-performance.md +3 -3
- package/.agents/workflows/audit-privacy.md +3 -3
- package/.agents/workflows/audit-quality.md +3 -3
- package/.agents/workflows/audit-security.md +3 -3
- package/.agents/workflows/audit-seo.md +3 -3
- package/.agents/workflows/audit-sre.md +3 -3
- package/.agents/workflows/audit-to-stories.md +20 -20
- package/.agents/workflows/audit-ux-ui.md +3 -3
- package/.agents/workflows/deliver.md +122 -131
- package/.agents/workflows/git-cleanup.md +3 -4
- package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
- package/.agents/workflows/helpers/acceptance-self-eval.md +52 -40
- package/.agents/workflows/helpers/code-review.md +70 -193
- package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +12 -14
- package/.agents/workflows/helpers/{single-story-deliver.md → deliver-story.md} +113 -139
- package/.agents/workflows/helpers/diagnose.md +10 -10
- package/.agents/workflows/helpers/mandrel-sync-config.md +1 -1
- package/.agents/workflows/helpers/parallel-tooling.md +1 -1
- package/.agents/workflows/helpers/signals.md +16 -16
- package/.agents/workflows/helpers/worktree-lifecycle.md +48 -64
- package/.agents/workflows/mandrel-update.md +3 -2
- package/.agents/workflows/plan.md +112 -145
- package/.agents/workflows/qa-assist.md +24 -30
- package/.agents/workflows/qa-explore.md +29 -38
- package/.agents/workflows/qa-run.md +2 -2
- package/README.md +9 -8
- package/docs/CHANGELOG.md +46 -0
- package/lib/cli/registry.js +95 -0
- package/lib/migrations/index.js +6 -5
- package/package.json +5 -3
- package/.agents/personas/architect.md +0 -113
- package/.agents/personas/devops-engineer.md +0 -38
- package/.agents/personas/engineer-mobile.md +0 -120
- package/.agents/personas/engineer-web.md +0 -111
- package/.agents/personas/engineer.md +0 -119
- package/.agents/personas/product.md +0 -94
- package/.agents/personas/project-manager.md +0 -114
- package/.agents/personas/qa-engineer.md +0 -95
- package/.agents/personas/refactorer.md +0 -113
- package/.agents/personas/security-engineer.md +0 -112
- package/.agents/personas/sre.md +0 -86
- package/.agents/personas/technical-writer.md +0 -101
- package/.agents/personas/ux-designer.md +0 -95
- package/.agents/schemas/dispatch-manifest.json +0 -232
- package/.agents/schemas/epic-spec.schema.json +0 -153
- package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
- package/.agents/scripts/dispatcher.js +0 -295
- package/.agents/scripts/epic-audit-prepare.js +0 -497
- package/.agents/scripts/epic-audit-recheck.js +0 -274
- package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
- package/.agents/scripts/epic-deliver-preflight.js +0 -462
- package/.agents/scripts/epic-deliver-prepare.js +0 -590
- package/.agents/scripts/epic-execute-record-wave.js +0 -449
- package/.agents/scripts/epic-plan-clarity.js +0 -211
- package/.agents/scripts/epic-plan-decompose.js +0 -54
- package/.agents/scripts/epic-plan-healthcheck.js +0 -581
- package/.agents/scripts/epic-plan-spec.js +0 -64
- package/.agents/scripts/epic-reconcile.js +0 -625
- package/.agents/scripts/lib/baseline-snapshot.js +0 -979
- package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
- package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
- package/.agents/scripts/lib/config/lifecycle.js +0 -40
- package/.agents/scripts/lib/config/preflight.js +0 -58
- package/.agents/scripts/lib/config/retro.js +0 -77
- package/.agents/scripts/lib/epic-merge-lock.js +0 -322
- package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
- package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
- package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -660
- package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
- package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
- package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
- package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
- package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
- package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
- package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -388
- package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
- package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
- package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
- package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
- package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
- package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
- package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
- package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
- package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
- package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -384
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -278
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
- package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
- package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
- package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
- package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
- package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
- package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
- package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
- package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
- package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
- package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
- package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
- package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +0 -109
- package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
- package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
- package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
- package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
- package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
- package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
- package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
- package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
- package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
- package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
- package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
- package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
- package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
- package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
- package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
- package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
- package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
- package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
- package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -301
- package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
- package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
- package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
- package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
- package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
- package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
- package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
- package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
- package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
- package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
- package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
- package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
- package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
- package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
- package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
- package/.agents/scripts/lib/push-epic-retry.js +0 -209
- package/.agents/scripts/lib/spec/index.js +0 -36
- package/.agents/scripts/lib/spec/loader.js +0 -425
- package/.agents/scripts/lib/spec/state.js +0 -208
- package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
- package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
- package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
- package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
- package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
- package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
- package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
- package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
- package/.agents/scripts/lib/wave-runner/tick.js +0 -754
- package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
- package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
- package/.agents/scripts/lifecycle-emit.js +0 -510
- package/.agents/scripts/plan-critics.js +0 -199
- package/.agents/scripts/retro-run.js +0 -218
- package/.agents/scripts/standalone-feedback-rollup.js +0 -188
- package/.agents/scripts/story-close.js +0 -294
- package/.agents/scripts/story-init.js +0 -599
- package/.agents/scripts/story-phase.js +0 -369
- package/.agents/scripts/wave-tick.js +0 -335
- package/.agents/skills/core/baseline-refresh/SKILL.md +0 -181
- package/.agents/skills/core/ci-cd-and-automation/SKILL.md +0 -274
- package/.agents/skills/core/ci-cd-and-automation/examples.md +0 -211
- package/.agents/skills/core/code-simplification/SKILL.md +0 -389
- package/.agents/skills/core/context-engineering/SKILL.md +0 -309
- package/.agents/skills/core/context-engineering/examples.md +0 -58
- package/.agents/skills/core/deprecation-and-migration/SKILL.md +0 -250
- package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
- package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
- package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
- package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
- package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
- package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
- package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -413
- package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
- package/.agents/skills/core/frontend-ui-engineering/SKILL.md +0 -357
- package/.agents/skills/core/hydrate-context/SKILL.md +0 -123
- package/.agents/skills/core/idea-refinement/examples.md +0 -437
- package/.agents/skills/core/idea-refinement/frameworks.md +0 -135
- package/.agents/skills/core/incremental-implementation/SKILL.md +0 -271
- package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +0 -213
- package/.agents/skills/core/knowledge-transfer/SKILL.md +0 -180
- package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +0 -117
- package/.agents/skills/core/performance-optimization/SKILL.md +0 -314
- package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +0 -277
- package/.agents/skills/core/property-based-testing/SKILL.md +0 -148
- package/.agents/skills/core/refactoring-discipline/SKILL.md +0 -111
- package/.agents/skills/core/shipping-and-launch/SKILL.md +0 -328
- package/.agents/skills/core/spec-driven-development/SKILL.md +0 -252
- package/.agents/skills/core/test-driven-development/SKILL.md +0 -475
- package/.agents/skills/core/using-agent-skills/SKILL.md +0 -232
- package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +0 -31
- package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +0 -51
- package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +0 -76
- package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +0 -31
- package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +0 -33
- package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +0 -31
- package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +0 -51
- package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +0 -54
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +0 -29
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +0 -30
- package/.agents/skills/stack/backend/stripe-integration/SKILL.md +0 -57
- package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +0 -9
- package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +0 -48
- package/.agents/skills/stack/frontend/astro/SKILL.md +0 -62
- package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +0 -30
- package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +0 -29
- package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +0 -50
- package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +0 -58
- package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +0 -34
- package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +0 -51
- package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +0 -199
- package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +0 -68
- package/.agents/workflows/helpers/deliver-epic-reference.md +0 -534
- package/.agents/workflows/helpers/deliver-epic.md +0 -955
- package/.agents/workflows/helpers/deliver-stories.md +0 -440
- package/.agents/workflows/helpers/epic-audit.md +0 -189
- package/.agents/workflows/helpers/epic-deliver-story.md +0 -427
- package/.agents/workflows/helpers/epic-testing.md +0 -125
- package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
- package/.agents/workflows/helpers/plan-epic.md +0 -351
- package/.agents/workflows/helpers/plan-story.md +0 -251
- package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
- /package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +0 -0
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* duplicate-search.js — Cross-
|
|
2
|
+
* duplicate-search.js — Cross-Story Duplicate Detection
|
|
3
3
|
*
|
|
4
|
-
* Used by `/plan`
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Used by `/plan` to surface open Stories whose scope overlaps with a
|
|
5
|
+
* seed / seed-file / tickets corpus before new Stories are created.
|
|
6
|
+
* Returns ranked candidates with an overlap score and URL so the host
|
|
7
|
+
* LLM can pause for HITL confirmation.
|
|
8
8
|
*
|
|
9
9
|
* Design notes:
|
|
10
|
-
* -
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
10
|
+
* - Prefer `provider.searchIssues` to narrow open Stories server-side
|
|
11
|
+
* (`label:"type::story" state:open` + top seed tokens), capped at
|
|
12
|
+
* ~100 hits, then rank that set. Fall back to `listIssuesByLabel`
|
|
13
|
+
* when search errors or is unavailable (same try/catch pattern as
|
|
14
|
+
* `TicketGateway.getTickets`).
|
|
15
|
+
* - Scoring is intentionally simple (token Jaccard over title + body).
|
|
16
|
+
* It is a triage signal, not a semantic-search replacement.
|
|
17
|
+
* - Provider errors on the list fallback propagate verbatim — the
|
|
18
|
+
* caller is responsible for translating them into a friction comment
|
|
19
|
+
* or operator-visible failure.
|
|
19
20
|
*/
|
|
20
21
|
|
|
22
|
+
import { Logger } from './Logger.js';
|
|
23
|
+
import { TYPE_LABELS } from './label-constants.js';
|
|
24
|
+
|
|
21
25
|
const STOPWORDS = new Set([
|
|
22
26
|
'a',
|
|
23
27
|
'an',
|
|
@@ -75,6 +79,10 @@ const STOPWORDS = new Set([
|
|
|
75
79
|
|
|
76
80
|
const DEFAULT_MIN_SCORE = 0.15;
|
|
77
81
|
const DEFAULT_MAX_RESULTS = 5;
|
|
82
|
+
/** How many seed tokens to pass as free-text search terms. */
|
|
83
|
+
const DEFAULT_SEARCH_TOKEN_CAP = 8;
|
|
84
|
+
/** Hard cap on search hits ranked client-side (~one Search API page). */
|
|
85
|
+
const SEARCH_RESULT_CAP = 100;
|
|
78
86
|
|
|
79
87
|
/**
|
|
80
88
|
* Tokenize freeform text into a deduplicated set of meaningful words.
|
|
@@ -92,6 +100,33 @@ export function tokenize(text) {
|
|
|
92
100
|
return new Set(tokens);
|
|
93
101
|
}
|
|
94
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Pick the highest-signal seed tokens for a Search API free-text query.
|
|
105
|
+
* Longer tokens first (specificity proxy), then alphabetical for stability.
|
|
106
|
+
*
|
|
107
|
+
* @param {string} seed
|
|
108
|
+
* @param {number} [maxTokens]
|
|
109
|
+
* @returns {string[]}
|
|
110
|
+
*/
|
|
111
|
+
export function pickSearchTokens(seed, maxTokens = DEFAULT_SEARCH_TOKEN_CAP) {
|
|
112
|
+
const tokens = tokenize(seed);
|
|
113
|
+
return [...tokens]
|
|
114
|
+
.sort((a, b) => b.length - a.length || a.localeCompare(b))
|
|
115
|
+
.slice(0, maxTokens);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Build the `/search/issues` query for open Stories overlapping a seed.
|
|
120
|
+
* Repo scoping is left to `provider.searchIssues`.
|
|
121
|
+
*
|
|
122
|
+
* @param {string} seed
|
|
123
|
+
* @returns {string}
|
|
124
|
+
*/
|
|
125
|
+
export function buildOpenStorySearchQuery(seed) {
|
|
126
|
+
const tokens = pickSearchTokens(seed);
|
|
127
|
+
return [`label:"${TYPE_LABELS.STORY}"`, 'state:open', ...tokens].join(' ');
|
|
128
|
+
}
|
|
129
|
+
|
|
95
130
|
/**
|
|
96
131
|
* Compute the Jaccard overlap between two token sets.
|
|
97
132
|
*
|
|
@@ -108,14 +143,14 @@ export function overlapScore(a, b) {
|
|
|
108
143
|
}
|
|
109
144
|
|
|
110
145
|
/**
|
|
111
|
-
* Build the
|
|
112
|
-
*
|
|
146
|
+
* Build the issue URL for an id. The candidate exposes the URL so the
|
|
147
|
+
* HITL pause can render clickable links without a second round-trip.
|
|
113
148
|
*
|
|
114
149
|
* @param {number|string} id
|
|
115
150
|
* @param {{ owner?: string, repo?: string }} [opts]
|
|
116
151
|
* @returns {string}
|
|
117
152
|
*/
|
|
118
|
-
function
|
|
153
|
+
function buildIssueUrl(id, opts = {}) {
|
|
119
154
|
const owner = opts.owner || process.env.GITHUB_OWNER;
|
|
120
155
|
const repo = opts.repo || process.env.GITHUB_REPO;
|
|
121
156
|
if (owner && repo) {
|
|
@@ -125,54 +160,72 @@ function buildEpicUrl(id, opts = {}) {
|
|
|
125
160
|
}
|
|
126
161
|
|
|
127
162
|
/**
|
|
128
|
-
*
|
|
129
|
-
*
|
|
163
|
+
* Normalize a provider issue (list or search hit) into the ranking shape.
|
|
164
|
+
*
|
|
165
|
+
* @param {object} issue
|
|
166
|
+
* @returns {{ id: number, title: string, body: string, url?: string }}
|
|
167
|
+
*/
|
|
168
|
+
function normalizeIssue(issue) {
|
|
169
|
+
return {
|
|
170
|
+
id: Number(issue.number ?? issue.id),
|
|
171
|
+
title: issue.title ?? '',
|
|
172
|
+
body: issue.body ?? '',
|
|
173
|
+
url: issue.html_url ?? issue.url ?? undefined,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Rank a pre-fetched open-Story list against a seed corpus.
|
|
179
|
+
* Pure helper shared by the provider-backed search and tests.
|
|
130
180
|
*
|
|
131
181
|
* @param {{
|
|
132
|
-
*
|
|
133
|
-
*
|
|
182
|
+
* seed: string,
|
|
183
|
+
* openStories: Array<{ id:number, title?:string, body?:string, url?:string }>,
|
|
134
184
|
* minScore?: number,
|
|
135
185
|
* maxResults?: number,
|
|
136
186
|
* owner?: string,
|
|
137
187
|
* repo?: string,
|
|
188
|
+
* excludeIds?: Iterable<number|string>,
|
|
138
189
|
* }} args
|
|
139
|
-
* @returns {
|
|
190
|
+
* @returns {Array<{ id: number, title: string, score: number, url: string }>}
|
|
140
191
|
*/
|
|
141
|
-
export
|
|
142
|
-
|
|
143
|
-
|
|
192
|
+
export function rankOpenStoryDuplicates({
|
|
193
|
+
seed,
|
|
194
|
+
openStories,
|
|
144
195
|
minScore = DEFAULT_MIN_SCORE,
|
|
145
196
|
maxResults = DEFAULT_MAX_RESULTS,
|
|
146
197
|
owner,
|
|
147
198
|
repo,
|
|
199
|
+
excludeIds = [],
|
|
148
200
|
}) {
|
|
149
|
-
if (!
|
|
150
|
-
throw new Error(
|
|
151
|
-
'findSimilarOpenEpics: onePager must be a non-empty string',
|
|
152
|
-
);
|
|
201
|
+
if (!seed || typeof seed !== 'string') {
|
|
202
|
+
throw new Error('rankOpenStoryDuplicates: seed must be a non-empty string');
|
|
153
203
|
}
|
|
154
|
-
if (!
|
|
155
|
-
throw new Error('
|
|
204
|
+
if (!Array.isArray(openStories)) {
|
|
205
|
+
throw new Error('rankOpenStoryDuplicates: openStories must be an array');
|
|
156
206
|
}
|
|
157
207
|
|
|
158
|
-
const seedTokens = tokenize(
|
|
208
|
+
const seedTokens = tokenize(seed);
|
|
159
209
|
if (seedTokens.size === 0) return [];
|
|
160
210
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
211
|
+
const excluded = new Set(
|
|
212
|
+
[...excludeIds].map((id) => Number(id)).filter((n) => Number.isFinite(n)),
|
|
213
|
+
);
|
|
164
214
|
|
|
165
215
|
const ranked = [];
|
|
166
|
-
for (const
|
|
167
|
-
const
|
|
216
|
+
for (const story of openStories) {
|
|
217
|
+
const id = Number(story?.id ?? story?.number);
|
|
218
|
+
if (!Number.isFinite(id) || excluded.has(id)) continue;
|
|
219
|
+
const title = story.title || '';
|
|
220
|
+
const corpus = `${title}\n${story.body || ''}`;
|
|
168
221
|
const candidateTokens = tokenize(corpus);
|
|
169
222
|
const score = overlapScore(seedTokens, candidateTokens);
|
|
170
223
|
if (score >= minScore) {
|
|
171
224
|
ranked.push({
|
|
172
|
-
id
|
|
173
|
-
title
|
|
225
|
+
id,
|
|
226
|
+
title,
|
|
174
227
|
score: Number(score.toFixed(4)),
|
|
175
|
-
url:
|
|
228
|
+
url: story.url || buildIssueUrl(id, { owner, repo }),
|
|
176
229
|
});
|
|
177
230
|
}
|
|
178
231
|
}
|
|
@@ -181,9 +234,126 @@ export async function findSimilarOpenEpics({
|
|
|
181
234
|
return ranked.slice(0, maxResults);
|
|
182
235
|
}
|
|
183
236
|
|
|
237
|
+
/**
|
|
238
|
+
* Server-narrowed open-Story fetch via `/search/issues`.
|
|
239
|
+
*
|
|
240
|
+
* @param {object} provider
|
|
241
|
+
* @param {string} seed
|
|
242
|
+
* @returns {Promise<Array<{ id:number, title:string, body:string, url?:string }>>}
|
|
243
|
+
*/
|
|
244
|
+
async function fetchOpenStoriesViaSearch(provider, seed) {
|
|
245
|
+
const query = buildOpenStorySearchQuery(seed);
|
|
246
|
+
const hits = await provider.searchIssues({ query });
|
|
247
|
+
if (!Array.isArray(hits)) return [];
|
|
248
|
+
return hits.slice(0, SEARCH_RESULT_CAP).map(normalizeIssue);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Full open-Story backlog via label listing (fallback path).
|
|
253
|
+
*
|
|
254
|
+
* @param {object} provider
|
|
255
|
+
* @returns {Promise<Array<{ id:number, title:string, body:string, url?:string }>>}
|
|
256
|
+
*/
|
|
257
|
+
async function fetchOpenStoriesViaList(provider) {
|
|
258
|
+
if (typeof provider.listIssuesByLabel !== 'function') {
|
|
259
|
+
throw new Error(
|
|
260
|
+
'findSimilarOpenStories: provider must implement listIssuesByLabel()',
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
const issues = await provider.listIssuesByLabel({
|
|
264
|
+
state: 'open',
|
|
265
|
+
labels: TYPE_LABELS.STORY,
|
|
266
|
+
});
|
|
267
|
+
if (!Array.isArray(issues)) return [];
|
|
268
|
+
return issues.map(normalizeIssue);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Fetch open-Story candidates: prefer Search API narrowing, fall back to
|
|
273
|
+
* `listIssuesByLabel` when search errors or is unavailable.
|
|
274
|
+
*
|
|
275
|
+
* @param {object} provider
|
|
276
|
+
* @param {string} seed
|
|
277
|
+
* @returns {Promise<Array<{ id:number, title:string, body:string, url?:string }>>}
|
|
278
|
+
*/
|
|
279
|
+
async function fetchOpenStoryCandidates(provider, seed) {
|
|
280
|
+
if (!provider || typeof provider !== 'object') {
|
|
281
|
+
throw new Error('findSimilarOpenStories: provider is required');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const hasSearch = typeof provider.searchIssues === 'function';
|
|
285
|
+
const hasList = typeof provider.listIssuesByLabel === 'function';
|
|
286
|
+
if (!hasSearch && !hasList) {
|
|
287
|
+
throw new Error(
|
|
288
|
+
'findSimilarOpenStories: provider must implement searchIssues() or listIssuesByLabel()',
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (hasSearch) {
|
|
293
|
+
try {
|
|
294
|
+
return await fetchOpenStoriesViaSearch(provider, seed);
|
|
295
|
+
} catch (err) {
|
|
296
|
+
if (!hasList) throw err;
|
|
297
|
+
const msg = typeof err?.message === 'string' ? err.message : String(err);
|
|
298
|
+
Logger.warn(
|
|
299
|
+
`[duplicate-search] search-based candidate fetch failed (${msg}); ` +
|
|
300
|
+
'falling back to listIssuesByLabel',
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return fetchOpenStoriesViaList(provider);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Find open Stories whose title + body overlap with the supplied seed
|
|
310
|
+
* above a configurable threshold.
|
|
311
|
+
*
|
|
312
|
+
* @param {{
|
|
313
|
+
* seed: string,
|
|
314
|
+
* provider: import('./ITicketingProvider.js').ITicketingProvider,
|
|
315
|
+
* minScore?: number,
|
|
316
|
+
* maxResults?: number,
|
|
317
|
+
* owner?: string,
|
|
318
|
+
* repo?: string,
|
|
319
|
+
* excludeIds?: Iterable<number|string>,
|
|
320
|
+
* }} args
|
|
321
|
+
* @returns {Promise<Array<{ id: number, title: string, score: number, url: string }>>}
|
|
322
|
+
*/
|
|
323
|
+
export async function findSimilarOpenStories({
|
|
324
|
+
seed,
|
|
325
|
+
provider,
|
|
326
|
+
minScore = DEFAULT_MIN_SCORE,
|
|
327
|
+
maxResults = DEFAULT_MAX_RESULTS,
|
|
328
|
+
owner,
|
|
329
|
+
repo,
|
|
330
|
+
excludeIds = [],
|
|
331
|
+
}) {
|
|
332
|
+
if (!seed || typeof seed !== 'string') {
|
|
333
|
+
throw new Error('findSimilarOpenStories: seed must be a non-empty string');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Avoid a network round-trip when the seed cannot produce a score.
|
|
337
|
+
if (tokenize(seed).size === 0) return [];
|
|
338
|
+
|
|
339
|
+
const openStories = await fetchOpenStoryCandidates(provider, seed);
|
|
340
|
+
return rankOpenStoryDuplicates({
|
|
341
|
+
seed,
|
|
342
|
+
openStories,
|
|
343
|
+
minScore,
|
|
344
|
+
maxResults,
|
|
345
|
+
owner,
|
|
346
|
+
repo,
|
|
347
|
+
excludeIds,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
|
|
184
351
|
export const __test = {
|
|
185
352
|
STOPWORDS,
|
|
186
353
|
DEFAULT_MIN_SCORE,
|
|
187
354
|
DEFAULT_MAX_RESULTS,
|
|
188
|
-
|
|
355
|
+
DEFAULT_SEARCH_TOKEN_CAP,
|
|
356
|
+
SEARCH_RESULT_CAP,
|
|
357
|
+
buildIssueUrl,
|
|
358
|
+
buildEpicUrl: buildIssueUrl,
|
|
189
359
|
};
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
* failure path is captured in `errors[]`.
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
|
+
import { DEFAULT_FRAMEWORK_REPO } from '../github/framework-repo.js';
|
|
33
34
|
import { META_LABELS } from '../label-constants.js';
|
|
34
|
-
import { DEFAULT_FRAMEWORK_REPO } from '../orchestration/retro/phases/gather-signals.js';
|
|
35
35
|
import {
|
|
36
36
|
contentFingerprint,
|
|
37
37
|
DEFAULT_MAX_FILINGS_PER_RUN,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* session's ledger items (see `.agents/schemas/qa-ledger.schema.json` and
|
|
7
7
|
* `lib/qa/qa-session.js`), the still-untriaged backlog is clustered and each
|
|
8
8
|
* cluster is promoted to a follow-up ticket — a single Story (via `/plan`)
|
|
9
|
-
* for a tight, one-deliverable cluster, or an Epic (via `/plan --
|
|
9
|
+
* for a tight, one-deliverable cluster, or an Epic (via `/plan --seed`) for
|
|
10
10
|
* a broad cluster that spans multiple coverage surfaces. Each contributing
|
|
11
11
|
* ledger item then has the resulting `routedTo` issue link written back onto it
|
|
12
12
|
* so a resume run sees the item as filed rather than re-promoting it.
|
|
@@ -40,7 +40,7 @@ export const PROMOTION_TARGETS = Object.freeze({
|
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* A cluster of more than this many distinct coverage surfaces is broad enough
|
|
43
|
-
* to warrant an Epic (`/plan --
|
|
43
|
+
* to warrant an Epic (`/plan --seed`) rather than a single Story
|
|
44
44
|
* (`/plan`). One or two surfaces is a tight, single-deliverable cluster.
|
|
45
45
|
*/
|
|
46
46
|
const EPIC_COVERAGE_THRESHOLD = 2;
|
|
@@ -159,7 +159,7 @@ export function clusterLedgerItems(items) {
|
|
|
159
159
|
/**
|
|
160
160
|
* Decide a cluster's promotion target. A cluster that spans more than
|
|
161
161
|
* {@link EPIC_COVERAGE_THRESHOLD} distinct coverage surfaces is broad enough to
|
|
162
|
-
* warrant an Epic (`/plan --
|
|
162
|
+
* warrant an Epic (`/plan --seed`); otherwise it is a single-deliverable
|
|
163
163
|
* Story (`/plan`).
|
|
164
164
|
*
|
|
165
165
|
* @param {{ coverages: string[] }} cluster
|
|
@@ -233,7 +233,7 @@ function routedToLink(issue, kind) {
|
|
|
233
233
|
* shared `routeFinding` against existing Issues (via the injected search
|
|
234
234
|
* port). This dedups against work already filed.
|
|
235
235
|
* 2. On a `new` decision, open the follow-up ticket through the injected
|
|
236
|
-
* `createStory` (`/plan`) or `createEpic` (`/plan --
|
|
236
|
+
* `createStory` (`/plan`) or `createEpic` (`/plan --seed`) port,
|
|
237
237
|
* chosen by {@link targetForCluster}. On any other decision, link back to
|
|
238
238
|
* the matched Issue rather than creating a duplicate.
|
|
239
239
|
* 3. Stamp the resolved `routedTo` link onto every contributing ledger item
|
|
@@ -252,7 +252,7 @@ function routedToLink(issue, kind) {
|
|
|
252
252
|
* @param {(cluster: object) => Promise<{ number: number, url?: string }>} ports.createStory
|
|
253
253
|
* Opens a single Story (`/plan`) for a tight cluster.
|
|
254
254
|
* @param {(cluster: object) => Promise<{ number: number, url?: string }>} ports.createEpic
|
|
255
|
-
* Opens an Epic (`/plan --
|
|
255
|
+
* Opens an Epic (`/plan --seed`) for a broad cluster.
|
|
256
256
|
* @returns {Promise<{
|
|
257
257
|
* promotions: Array<{
|
|
258
258
|
* clusterKey: string,
|
|
@@ -8,9 +8,8 @@
|
|
|
8
8
|
* 1. **Version resolution.** Under npm distribution the root `package.json`
|
|
9
9
|
* is the canonical version marker. {@link resolveFrameworkVersion} reads it
|
|
10
10
|
* and degrades to `'unknown'` (never throws) so a missing/unreadable
|
|
11
|
-
* manifest can never crash an authoring
|
|
12
|
-
*
|
|
13
|
-
* delegates here (DRY — one manifest reader).
|
|
11
|
+
* manifest can never crash an authoring path. All ticket-body stamp
|
|
12
|
+
* producers delegate here (DRY — one manifest reader).
|
|
14
13
|
*
|
|
15
14
|
* 2. **Ticket-body stamp.** Epics and Stories are stamped **once at authoring
|
|
16
15
|
* time** with the running version and the authoring date, via a hybrid
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* git-branch-cleanup.js — Shared branch deletion helpers (local + remote).
|
|
3
3
|
*
|
|
4
4
|
* Consolidates the "delete this branch from local and/or origin" pattern
|
|
5
|
-
* used by `story-close.js` and other branch-reaping flows. Originally
|
|
5
|
+
* used by `single-story-close.js` and other branch-reaping flows. Originally
|
|
6
6
|
* carved out when more than one caller re-implemented the same idempotency
|
|
7
7
|
* rules with subtle drift.
|
|
8
8
|
*
|
|
@@ -117,15 +117,6 @@ export function deleteBranchEverywhere(name, opts = {}) {
|
|
|
117
117
|
return { deleted: bothOk, reason, local, remote };
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
/**
|
|
121
|
-
* Backwards-compatible alias for `deleteBranchEverywhere`. Older call
|
|
122
|
-
* sites and tests imported this name; keeping the alias avoids touching
|
|
123
|
-
* them in the migration.
|
|
124
|
-
*
|
|
125
|
-
* @deprecated prefer `deleteBranchEverywhere`.
|
|
126
|
-
*/
|
|
127
|
-
export const deleteBranchBoth = deleteBranchEverywhere;
|
|
128
|
-
|
|
129
120
|
/**
|
|
130
121
|
* Delete N branches in a single batched git call (push --delete X Y Z, or
|
|
131
122
|
* branch -D X Y Z), falling back to per-ref delete via
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Consolidates the "does this branch exist locally / remotely?" and
|
|
5
5
|
* "ensure this branch exists and is checked out" logic that
|
|
6
|
-
* `story-init.js`
|
|
6
|
+
* `single-story-init.js` centralizes (formerly duplicated across the deleted
|
|
7
|
+
* `story-init.js` and `dispatch-engine.js` entry seams).
|
|
7
8
|
*
|
|
8
9
|
* All helpers take an explicit `cwd`. Callers with worktree isolation
|
|
9
10
|
* enabled pass the worktree path; single-tree callers pass `PROJECT_ROOT`.
|
|
@@ -87,18 +88,16 @@ export function branchExistsViaTrackingRef(branch, cwd) {
|
|
|
87
88
|
|
|
88
89
|
/**
|
|
89
90
|
* Pure: classify how a `story-<id>` branch should be seeded from the (local,
|
|
90
|
-
* remote) ref-presence matrix. This is the single source of truth
|
|
91
|
-
*
|
|
92
|
-
* - `single-story-init.js#decideStoryBranchSeed` (standalone path)
|
|
93
|
-
* - `story-init/branch-initializer.js#planStoryBranchSeed` (Epic path)
|
|
91
|
+
* remote) ref-presence matrix. This is the single source of truth for
|
|
92
|
+
* `single-story-init.js#decideStoryBranchSeed` (v2 `/deliver` path).
|
|
94
93
|
*
|
|
95
|
-
*
|
|
96
|
-
* fetch, else create` decision tree;
|
|
97
|
-
* logic lives in exactly one place. The
|
|
94
|
+
* The init path previously re-implemented the same `local → no-op, remote →
|
|
95
|
+
* fetch, else create` decision tree; it now delegates here so the branching
|
|
96
|
+
* logic lives in exactly one place. The caller keeps its own keyword for
|
|
98
97
|
* the "local ref already exists" outcome (`reuse` vs `none`) — synonyms for
|
|
99
|
-
* "do not re-create / do not re-seed" preserved for
|
|
100
|
-
*
|
|
101
|
-
*
|
|
98
|
+
* "do not re-create / do not re-seed" preserved for its existing public/test
|
|
99
|
+
* contract — so this classifier returns the neutral `'local'` keyword and
|
|
100
|
+
* the caller maps it onto its own vocabulary.
|
|
102
101
|
*
|
|
103
102
|
* @param {{ localHas: boolean, remoteHas: boolean }} presence
|
|
104
103
|
* @returns {'local'|'fetch'|'create'}
|
|
@@ -116,22 +115,18 @@ export function classifyBranchSeed({ localHas, remoteHas }) {
|
|
|
116
115
|
|
|
117
116
|
/**
|
|
118
117
|
* Single-home for the story-branch seed-action *switch shell* that
|
|
119
|
-
* `single-story-init.js#seedStoryBranch` (
|
|
120
|
-
* `story-init/branch-initializer.js
|
|
121
|
-
*
|
|
122
|
-
* remote) decision to `classifyBranchSeed`; only the act-on-the-decision
|
|
123
|
-
* shell (reuse / fetch / create) was duplicated, and that shell was the
|
|
124
|
-
* drift surface for the seed-decision contract.
|
|
118
|
+
* `single-story-init.js#seedStoryBranch` owns (Story #4255). The deleted
|
|
119
|
+
* Epic `story-init/branch-initializer.js` path had duplicated the same
|
|
120
|
+
* shell before v2 cutover.
|
|
125
121
|
*
|
|
126
122
|
* The two callers differ in exactly two behavioural axes, both of which are
|
|
127
123
|
* parameters here — no other conditional branching is introduced:
|
|
128
|
-
* - **`baseRef`** — the ref to branch from on `create` (`main` for
|
|
129
|
-
*
|
|
124
|
+
* - **`baseRef`** — the ref to branch from on `create` (`main` for v2
|
|
125
|
+
* `/deliver`; pre-v2 Epic close used the Epic branch).
|
|
130
126
|
* - **`swallowCreateRace`** — when `true`, a `git branch` that exits
|
|
131
127
|
* non-zero with an "already exists" stderr is treated as reuse rather
|
|
132
|
-
* than a fatal error (
|
|
133
|
-
*
|
|
134
|
-
* throws (the standalone path has no concurrent creator to race).
|
|
128
|
+
* than a fatal error (pre-v2 concurrent wave dispatch). When `false`, any create failure
|
|
129
|
+
* throws (the v2 standalone path has no concurrent creator to race).
|
|
135
130
|
*
|
|
136
131
|
* The asymmetric surrounding wrappers (merged-sweep, fast-forward,
|
|
137
132
|
* donor-prime, workspace-verify, phase-timer) are deliberately NOT folded
|
|
@@ -43,6 +43,18 @@ import { execFileSync, spawnSync } from 'node:child_process';
|
|
|
43
43
|
let _execFileSync = execFileSync;
|
|
44
44
|
let _spawnSync = spawnSync;
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Memoized cleaned env shared by every `gitSync` / `gitSpawn` /
|
|
48
|
+
* `createGitInterface` invocation in this process. Built lazily on first
|
|
49
|
+
* use so cold imports pay nothing. Call sites pass the object through to
|
|
50
|
+
* `child_process` only — none mutate `GIT_*` (or any other key) between
|
|
51
|
+
* git calls, so reuse is safe. Tests that mutate `process.env` and need
|
|
52
|
+
* a fresh snapshot must call {@link __resetCleanGitEnv}.
|
|
53
|
+
*
|
|
54
|
+
* @type {NodeJS.ProcessEnv | null}
|
|
55
|
+
*/
|
|
56
|
+
let _cleanGitEnv = null;
|
|
57
|
+
|
|
46
58
|
/**
|
|
47
59
|
* Build a child-process env that drops every `GIT_*` variable inherited from
|
|
48
60
|
* the parent. When this module's helpers run inside a git hook (e.g. husky
|
|
@@ -53,13 +65,28 @@ let _spawnSync = spawnSync;
|
|
|
53
65
|
* that spin up real git fixtures break reproducibly under that shape.
|
|
54
66
|
*
|
|
55
67
|
* Stripping every `GIT_*` is broader than strictly necessary but cheap and
|
|
56
|
-
* impossible to drift out of sync with future git releases.
|
|
57
|
-
*
|
|
68
|
+
* impossible to drift out of sync with future git releases. The result is
|
|
69
|
+
* memoized per process (see `_cleanGitEnv`); author/committer identity is
|
|
70
|
+
* restored via per-call `env:` overrides where required.
|
|
71
|
+
*
|
|
72
|
+
* @returns {NodeJS.ProcessEnv}
|
|
58
73
|
*/
|
|
59
74
|
function cleanGitEnv() {
|
|
60
|
-
return
|
|
61
|
-
|
|
75
|
+
if (_cleanGitEnv) return _cleanGitEnv;
|
|
76
|
+
_cleanGitEnv = Object.freeze(
|
|
77
|
+
Object.fromEntries(
|
|
78
|
+
Object.entries(process.env).filter(([k]) => !k.startsWith('GIT_')),
|
|
79
|
+
),
|
|
62
80
|
);
|
|
81
|
+
return _cleanGitEnv;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Drop the memoized cleaned env so the next git call rebuilds from
|
|
86
|
+
* `process.env`. Testing-only seam — not part of the stable API.
|
|
87
|
+
*/
|
|
88
|
+
export function __resetCleanGitEnv() {
|
|
89
|
+
_cleanGitEnv = null;
|
|
63
90
|
}
|
|
64
91
|
|
|
65
92
|
/**
|
|
@@ -321,11 +348,10 @@ export function slugify(text) {
|
|
|
321
348
|
/**
|
|
322
349
|
* Resolves the canonical branch name for a Story.
|
|
323
350
|
* v5 Standard: story-[STORY_ID]
|
|
324
|
-
* @param {string|number} _epicId - Unused; retained for back-compat call sites.
|
|
325
351
|
* @param {string|number} storyId
|
|
326
352
|
* @returns {string}
|
|
327
353
|
*/
|
|
328
|
-
export function getStoryBranch(
|
|
354
|
+
export function getStoryBranch(storyId) {
|
|
329
355
|
const id =
|
|
330
356
|
typeof storyId === 'number' ? storyId : Number.parseInt(storyId, 10);
|
|
331
357
|
if (!Number.isFinite(id) || id <= 0) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Central source of truth for all GitHub label names used by the orchestrator.
|
|
3
3
|
*
|
|
4
|
-
* Every other module (label-taxonomy,
|
|
5
|
-
* etc.) should import from here rather than using string literals. Renames
|
|
4
|
+
* Every other module (label-taxonomy, single-story-close.js,
|
|
5
|
+
* stories-wave-tick.js, etc.) should import from here rather than using string literals. Renames
|
|
6
6
|
* land in one place.
|
|
7
7
|
*/
|
|
8
8
|
|
|
@@ -10,12 +10,12 @@ export const AGENT_LABELS = {
|
|
|
10
10
|
REVIEW_SPEC: 'agent::review-spec',
|
|
11
11
|
READY: 'agent::ready',
|
|
12
12
|
EXECUTING: 'agent::executing',
|
|
13
|
-
// Story #2144 — intermediate state owned by `story-close.js`. A Story
|
|
13
|
+
// Story #2144 — intermediate state owned by `single-story-close.js`. A Story
|
|
14
14
|
// flips to `agent::closing` after preflight validation succeeds and
|
|
15
|
-
//
|
|
16
|
-
// `agent::done` only after the
|
|
15
|
+
// the Story PR is opened against `main`. It flips to
|
|
16
|
+
// `agent::done` only after the close pipeline confirms the PR merge
|
|
17
17
|
// landed; if the close is killed mid-flight, the Story remains at
|
|
18
|
-
// `agent::closing` so
|
|
18
|
+
// `agent::closing` so `/deliver` can pick up at the
|
|
19
19
|
// post-merge phase rather than re-running preflight. The label is the
|
|
20
20
|
// distinguishing signal between "hung close" and "finished work".
|
|
21
21
|
CLOSING: 'agent::closing',
|
|
@@ -75,7 +75,6 @@ export function isValidTransition(fromState, toState) {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
export const TYPE_LABELS = {
|
|
78
|
-
EPIC: 'type::epic',
|
|
79
78
|
STORY: 'type::story',
|
|
80
79
|
};
|
|
81
80
|
|
|
@@ -83,14 +82,6 @@ export const STATUS_LABELS = {
|
|
|
83
82
|
BLOCKED: 'status::blocked',
|
|
84
83
|
};
|
|
85
84
|
|
|
86
|
-
/**
|
|
87
|
-
* Persona labels are derived at bootstrap time from `.agents/personas/*.md`
|
|
88
|
-
* (see `label-taxonomy.js`), not hard-coded here — the persona file is the
|
|
89
|
-
* source of truth, and ticket hydration resolves the label value to the
|
|
90
|
-
* matching filename.
|
|
91
|
-
*/
|
|
92
|
-
export const PERSONA_LABEL_PREFIX = 'persona::';
|
|
93
|
-
|
|
94
85
|
/**
|
|
95
86
|
* Acceptance-axis labels for opt-out signalling on Epics that
|
|
96
87
|
* intentionally have no acceptance-table coverage. (Story #4324 retired
|
|
@@ -122,13 +113,10 @@ export const META_LABELS = {
|
|
|
122
113
|
|
|
123
114
|
/**
|
|
124
115
|
* Planning-axis labels (Epic #2880 F7). Currently scoped to the
|
|
125
|
-
* `planning::healthcheck-waived` operator-applied waiver
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
* when the healthcheck returned `ok: false` unless this label is
|
|
130
|
-
* present — see `.agents/docs/SDLC.md` § "`agent::ready` exit conditions"
|
|
131
|
-
* for the full handoff contract.
|
|
116
|
+
* `planning::healthcheck-waived` operator-applied waiver — a historical
|
|
117
|
+
* escape hatch for the retired post-plan readiness healthcheck. The
|
|
118
|
+
* label remains in the taxonomy for tickets that still carry it; the
|
|
119
|
+
* healthcheck CLI itself was deleted in the v2 epic-scripts sweep.
|
|
132
120
|
*
|
|
133
121
|
* Future planning-axis waivers (one per failing exit condition) extend
|
|
134
122
|
* this enum so consumers can reference them by symbol.
|
|
@@ -166,7 +154,6 @@ export const LABEL_COLORS = {
|
|
|
166
154
|
TYPE: '#7057FF',
|
|
167
155
|
AGENT: '#0E8A16',
|
|
168
156
|
STATUS_BLOCKED: '#D93F0B',
|
|
169
|
-
PERSONA: '#C5DEF5',
|
|
170
157
|
ACCEPTANCE: '#FBCA04',
|
|
171
158
|
PLANNING: '#FEF2C0',
|
|
172
159
|
DELIVERY: '#BFD4F2',
|