**Consolidation of 23 open PRs into one.** Every one shared a single root cause and mostly touched a single file; 23 CI runs for that was indefensible. Folds and supersedes: #2867 #2869 #2876 #2879 #2883 #2891 #2899 #2901 #2902 #2905 #2906 #2914 #2916 #2918 #2919 #2920 #2922 #2927 #2929 #2932 #2934 #2937 #2939. (#2865, #2882, #2897, #2909, #2912 already merged and are not re-folded.) ## The root cause A self-healing sweep selects its work with `listTasks({ column: "in-review" })`. On a board whose lanes are renamed that returns **nothing**, so the sweep never runs — no error, no log line, no failed task. Several sweeps had already had their *predicates* converted to resolved lanes, which dropped a census count and changed nothing, because the query above the loop had already returned an empty list. **26 sweeps converted.** Each one: read the project's columns for the role, then decide each card against **its own** workflow, with the legacy ids unioned so a board mid-rename is never skipped. ## What each sweep stops silently failing to do | | | | --- | --- | | stale merger status | one finished card held the **merge queue** for everything behind it | | stale `blockedBy` / completed-task release | dependents stayed blocked on work that had already finished — the board stops moving | | workspace partial lands | a task left with **some repos merged and some not** | | mid-merge retry stamp | the card stalled *and* the operator's manual Retry was gated by the same stamp | | in-progress limbo / no-progress failures | dead cards held a work slot forever | | partial-progress retry | real work parked failed with its **retry budget unspent** | | orphaned-execution signal | visibility only — the one signal pointing at an orphan went silent | | zero-commit audit | went **half-blind**: the error arm kept working, the lane arm did not | Plus: ghost review cards, transient merge failures, misclassified failures, branch misbinding, missing-worktree failures, merged-but-unfinished finalization, done-metadata repair, self-owned branch conflicts, orphan-only scope violations, post-done wedges, idle assigned agents, PR-conflict worktree ownership, and orphaned workspace worktrees. ## Two defects the conversion itself introduced, both caught and fixed 1. **Missed pairs.** Widening a read without converting the guards beneath it is *worse than not converting*: the sweep starts admitting renamed-board cards and then mis-decides every one. Review caught a second guard on a re-read row; the audit that triggered found **five more**, one of which gates the `reviewProof` triple-proof — a renamed review card would have been moved backward with the safety check silently skipped. Column guards 86 → 81. 2. **Duplicate processing.** The literal reads were disjoint by construction; resolved reads are not, so a column carrying two role flags put one card in two buckets — duplicate moves, duplicate audit rows, inflated counts. Both now have ratchets. `self-healing-converted-sweeps-have-no-literal-lane-guards.test.ts` **derives** its sweep list (a sweep counts as converted when its body calls `resolveProjectColumnsForRoles`), so it cannot go stale, and it carries two positive controls because a broken regex finds no offenders and a broken derivation iterates nothing — an empty loop registers no tests and reads green. ## Deliberately unchanged - 22 `moveTask` destinations carrying `recoveryRehome: true` — `moves.ts` exempts these so a card stranded in an undeclared column stays rescuable. - One literal in `clearStaleBlockedBy`'s log-dedup closure (allowed by name in the ratchet, with the reason). - `surfaceInReviewStalls` — hot list-read path, needs a batched prefetch; that is a performance design decision, not a conversion. - `scheduler.ts` and `replan-target.ts` — built on `resolveTaskWorkflowIrSync`, which returns the default IR for every task in production. Converting there produces inert code. ## The fold itself is worth one note All 23 branches appended to the **same test file at the same anchor**, so every automatic strategy — git 3-way, `merge-file --union`, and three hand-written resolvers — interleaved them mid-block. Two attempts committed conflict markers before I caught it. The file is therefore **reconstructed**: head authored once, body assembled as the union of each branch's own intact top-level segments keyed by test title, with the nested `already-merged hard blocker` describe appended whole (flattening it orphaned its helper). Verified by *parsing after every step* rather than trusting the merge — which is how each interleaving was caught. ## Verification `pnpm test:gate` 161 + 487 + 13 + 71. Scoped suites 592 passed (self-healing, the blindness suite at 68 cases, the ratchet, and the notification suite). `tsc` engine clean; `pnpm lint`, `check:changesets`, `lifecycle-column-census --strict` and `check-sql-column-literals` all clean, each run explicitly. Each folded conversion was individually revert-proven on its original branch — the read reverted alone, and the per-card verdict reverted alone — and those measurements are recorded in the commit messages carried into this branch. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
143 lines
8.4 KiB
JSON
143 lines
8.4 KiB
JSON
{
|
|
"generatedFrom": "node scripts/lifecycle-column-census.mjs --strict --update-baseline",
|
|
"byFile": {
|
|
"packages/engine/src/self-healing.ts": 56,
|
|
"packages/engine/src/scheduler.ts": 12,
|
|
"packages/engine/src/executor.ts": 8,
|
|
"packages/core/src/task-store/async-comments-attachments.ts": 6,
|
|
"packages/engine/src/notification/notification-service.ts": 5,
|
|
"packages/engine/src/replan-target.ts": 4,
|
|
"packages/engine/src/restart-recovery-coordinator.ts": 4,
|
|
"packages/core/src/task-store/task-artifacts-ops.ts": 3,
|
|
"packages/core/src/agent-store.ts": 2,
|
|
"packages/core/src/async-mission-store-queries.ts": 2,
|
|
"packages/core/src/task-store/audit-ops.ts": 2,
|
|
"packages/core/src/task-store/moves.ts": 2,
|
|
"packages/core/src/task-store/project-store-ops.ts": 2,
|
|
"packages/core/src/task-store/reads.ts": 2,
|
|
"packages/core/src/task-store/task-id-integrity.ts": 2,
|
|
"packages/dashboard/app/utils/taskRevert.ts": 2,
|
|
"packages/dashboard/src/github-tracking-state.ts": 2,
|
|
"packages/dashboard/src/routes/register-task-workflow-routes.ts": 2,
|
|
"packages/engine/src/auto-merge-finalization.ts": 2,
|
|
"packages/engine/src/planner-overseer.ts": 2,
|
|
"packages/core/src/eval-signal-collector.ts": 1,
|
|
"packages/core/src/in-review-stall.ts": 1,
|
|
"packages/core/src/mission-store.ts": 1,
|
|
"packages/core/src/plugin-store.ts": 1,
|
|
"packages/core/src/stalled-review-detector.ts": 1,
|
|
"packages/core/src/task-store/comments-ops.ts": 1,
|
|
"packages/core/src/task-store/lifecycle-ops.ts": 1,
|
|
"packages/core/src/task-store/merge-queue-ops-2.ts": 1,
|
|
"packages/core/src/task-store/merge-queue-ops.ts": 1,
|
|
"packages/dashboard/app/components/ResearchTaskActionModal.tsx": 1,
|
|
"packages/dashboard/app/components/TaskCard.tsx": 1,
|
|
"packages/engine/src/backlog-pressure-reporter.ts": 1,
|
|
"packages/engine/src/ephemeral-worker-manager.ts": 1,
|
|
"packages/engine/src/merger.ts": 1,
|
|
"packages/engine/src/runtimes/in-process-runtime.ts": 1,
|
|
"packages/engine/src/triage.ts": 1
|
|
},
|
|
"deliberateByFile": {
|
|
"packages/dashboard/app/components/TaskContextMenu.tsx\u0000in-review": 3,
|
|
"packages/engine/src/self-healing.ts\u0000in-review": 3,
|
|
"packages/core/src/live-agent-count.ts\u0000in-progress": 2,
|
|
"packages/core/src/live-agent-count.ts\u0000in-review": 2,
|
|
"packages/core/src/store.ts\u0000in-review": 2,
|
|
"packages/core/src/task-merge.ts\u0000archived": 2,
|
|
"packages/core/src/task-merge.ts\u0000done": 2,
|
|
"packages/core/src/task-merge.ts\u0000in-review": 2,
|
|
"packages/dashboard/app/components/TaskCard.tsx\u0000todo": 2,
|
|
"packages/dashboard/app/components/TaskCard.tsx\u0000triage": 2,
|
|
"packages/dashboard/app/components/TaskContextMenu.tsx\u0000archived": 2,
|
|
"packages/dashboard/app/components/TaskContextMenu.tsx\u0000done": 2,
|
|
"packages/dashboard/app/components/TaskDetailModal.tsx\u0000triage": 2,
|
|
"packages/dashboard/app/hooks/useTaskDiffStats.ts\u0000done": 2,
|
|
"packages/dashboard/src/reliability-metrics.ts\u0000in-review": 2,
|
|
"packages/engine/src/cli-agent/state-machine.ts\u0000done": 2,
|
|
"packages/engine/src/scheduler.ts\u0000archived": 2,
|
|
"packages/engine/src/scheduler.ts\u0000done": 2,
|
|
"packages/engine/src/scheduler.ts\u0000in-progress": 2,
|
|
"packages/engine/src/scheduler.ts\u0000in-review": 2,
|
|
"packages/engine/src/self-healing.ts\u0000done": 2,
|
|
"packages/engine/src/usage-limit-detector.ts\u0000archived": 2,
|
|
"packages/engine/src/usage-limit-detector.ts\u0000done": 2,
|
|
"plugins/fusion-plugin-reports/src/store/report-store.ts\u0000archived": 2,
|
|
"packages/cli/src/commands/task.ts\u0000archived": 1,
|
|
"packages/cli/src/commands/task.ts\u0000done": 1,
|
|
"packages/cli/src/extension.ts\u0000archived": 1,
|
|
"packages/cli/src/extension.ts\u0000done": 1,
|
|
"packages/core/src/live-agent-count.ts\u0000archived": 1,
|
|
"packages/core/src/live-agent-count.ts\u0000done": 1,
|
|
"packages/core/src/store.ts\u0000archived": 1,
|
|
"packages/core/src/store.ts\u0000done": 1,
|
|
"packages/core/src/store.ts\u0000in-progress": 1,
|
|
"packages/core/src/store.ts\u0000todo": 1,
|
|
"packages/core/src/task-move-disposer.ts\u0000in-progress": 1,
|
|
"packages/core/src/task-move-disposer.ts\u0000todo": 1,
|
|
"packages/core/src/task-store/archive-lifecycle-2.ts\u0000archived": 1,
|
|
"packages/core/src/task-store/branch-and-pr-entities.ts\u0000archived": 1,
|
|
"packages/core/src/task-store/task-store-helpers.ts\u0000in-progress": 1,
|
|
"packages/core/src/task-store/task-store-helpers.ts\u0000todo": 1,
|
|
"packages/core/src/task-store/task-update.ts\u0000in-progress": 1,
|
|
"packages/core/src/task-store/task-update.ts\u0000in-review": 1,
|
|
"packages/core/src/task-store/update-task-deps.ts\u0000archived": 1,
|
|
"packages/core/src/task-store/update-task-deps.ts\u0000done": 1,
|
|
"packages/dashboard/app/components/command-center/liveSnapshotMetrics.ts\u0000in-progress": 1,
|
|
"packages/dashboard/app/components/command-center/MissionControlPanel.tsx\u0000done": 1,
|
|
"packages/dashboard/app/components/command-center/MissionControlPanel.tsx\u0000in-review": 1,
|
|
"packages/dashboard/app/components/command-center/MissionControlPanel.tsx\u0000todo": 1,
|
|
"packages/dashboard/app/components/DocumentsView.tsx\u0000archived": 1,
|
|
"packages/dashboard/app/components/DocumentsView.tsx\u0000done": 1,
|
|
"packages/dashboard/app/components/RoutineEditor.tsx\u0000triage": 1,
|
|
"packages/dashboard/app/components/ScheduleForm.tsx\u0000triage": 1,
|
|
"packages/dashboard/app/components/ScheduleStepsEditor.tsx\u0000triage": 1,
|
|
"packages/dashboard/app/components/TaskCard.tsx\u0000done": 1,
|
|
"packages/dashboard/app/components/TaskContextMenu.tsx\u0000in-progress": 1,
|
|
"packages/dashboard/app/components/TaskContextMenu.tsx\u0000triage": 1,
|
|
"packages/dashboard/app/components/TaskDetailModal.tsx\u0000archived": 1,
|
|
"packages/dashboard/app/components/TaskDetailModal.tsx\u0000done": 1,
|
|
"packages/dashboard/app/components/TaskDetailModal.tsx\u0000in-progress": 1,
|
|
"packages/dashboard/app/components/TaskDetailModal.tsx\u0000in-review": 1,
|
|
"packages/dashboard/app/components/TaskDetailModal.tsx\u0000todo": 1,
|
|
"packages/dashboard/app/utils/columnRoles.ts\u0000todo": 1,
|
|
"packages/dashboard/app/utils/quickAddStart.ts\u0000todo": 1,
|
|
"packages/dashboard/src/github-tracking-comments.ts\u0000done": 1,
|
|
"packages/dashboard/src/github-tracking-state.ts\u0000archived": 1,
|
|
"packages/dashboard/src/github-tracking-state.ts\u0000done": 1,
|
|
"packages/dashboard/src/gitlab-tracking-comments.ts\u0000in-progress": 1,
|
|
"packages/dashboard/src/reliability-metrics.ts\u0000in-progress": 1,
|
|
"packages/dashboard/src/routes/register-task-workflow-routes.ts\u0000todo": 1,
|
|
"packages/dashboard/src/routes/register-task-workflow-routes.ts\u0000triage": 1,
|
|
"packages/dashboard/src/server.ts\u0000archived": 1,
|
|
"packages/dashboard/src/task-planner-chat-context.ts\u0000done": 1,
|
|
"packages/dashboard/src/test/mockCoreEngine.ts\u0000in-review": 1,
|
|
"packages/engine/src/agent-heartbeat.ts\u0000archived": 1,
|
|
"packages/engine/src/agent-heartbeat.ts\u0000done": 1,
|
|
"packages/engine/src/cli-agent/task-session.ts\u0000done": 1,
|
|
"packages/engine/src/executor.ts\u0000in-progress": 1,
|
|
"packages/engine/src/hold-release.ts\u0000archived": 1,
|
|
"packages/engine/src/hold-release.ts\u0000done": 1,
|
|
"packages/engine/src/hold-release.ts\u0000in-review": 1,
|
|
"packages/engine/src/project-engine.ts\u0000in-review": 1,
|
|
"packages/engine/src/scheduler.ts\u0000todo": 1,
|
|
"packages/engine/src/self-healing.ts\u0000archived": 1,
|
|
"packages/engine/src/triage.ts\u0000triage": 1,
|
|
"plugins/fusion-plugin-even-cards/src/cards/board-cards.ts\u0000archived": 1,
|
|
"plugins/fusion-plugin-even-cards/src/cards/board-cards.ts\u0000done": 1,
|
|
"plugins/fusion-plugin-even-realities-glasses/src/notifications/diff.ts\u0000done": 1,
|
|
"plugins/fusion-plugin-reports/src/store/report-types.ts\u0000archived": 1
|
|
},
|
|
"queryByFile": {
|
|
"packages/core/src/task-store/async-persistence.ts": 2,
|
|
"packages/core/src/task-store/merge-queue-ops.ts": 2,
|
|
"packages/engine/src/self-healing.ts": 2,
|
|
"packages/core/src/async-mission-store.ts": 1,
|
|
"packages/core/src/task-store/archive-lifecycle-2.ts": 1,
|
|
"packages/core/src/task-store/async-archive-lineage.ts": 1,
|
|
"packages/core/src/task-store/async-self-healing.ts": 1,
|
|
"packages/engine/src/agent-tools.ts": 1,
|
|
"packages/engine/src/auto-merge-finalization.ts": 1
|
|
}
|
|
}
|