Two executor conversions with real operator consequences, one census false positive, and three sites deliberately left with their reasons recorded. ## Census | file | main | here | | --- | ---: | ---: | | `packages/engine/src/executor.ts` | 12 | **8** | Of the 4: three genuine conversions, one reclassification. ## What was broken **`resetMergeStateIfNeeded` — cards re-entered execution carrying stale merge evidence.** Merge state is cleared when a card *leaves* a lane where a merge could have been recorded. Keyed on `in-review`/`done`, a renamed board matched neither, so a card bouncing back into execution kept `mergeDetails` — including a **commit sha from its previous pass** — into its next run. `review` is not a trait, so this resolves through the same five flags (`complete`, `mergeOrchestration`, `mergeBlocker`, `humanReview`) the dependency gates in this file already use; two gates answering "is this a merge-bearing lane?" differently would be a split brain. **The worktree-owner scan — a live checkout read as unowned.** `findActiveWorktreeOwner` asks "is anyone else working in this checkout?". Its in-memory `activeWorktrees` leg is vocabulary-independent, but the **durable** leg — the one that answers after an engine restart, when the in-memory map is empty — filtered with `t.column !== "in-progress"`. On a renamed board that matched nobody, so the worktree read as free and a second task could be handed a checkout another task is live in. Post-restart is exactly when this function matters. Not the query-filter class: that `listTasks` call passes no `column`, so the predicate is the only lane gate on the path. ## A third census false positive in this package Line 16094's `to` is a **review-addressing record status** — the method signature is `to: "queued" | "in-progress" | "addressed" | "failed"`, and the next two lines test it against `"addressed"` and `"failed"`, which are not columns at all. Marked `DELIBERATE-LITERAL`. That is the third in `packages/engine` after the two `cli-agent` `CliMachineState` ones (#2797). The backlog total includes non-columns; a sweep that "converts" them turns a status machine into a workflow role. ## Revert results (measured, each run independently) | conversion | reverted → | | --- | --- | | worktree-owner wip predicate | RENAMED case fails — checkout reads as **free** while another task is live in it | | `resetMergeStateIfNeeded` lanes | RENAMED case fails — card keeps `commitSha: "abc123"` from its previous pass | Both DEFAULT cases pass before and after, which is why both vocabularies run. Each has a non-vacuous companion (holder sitting in the complete lane; a return from the hold lane) so a predicate matching every column would not pass. **Both reach their seam directly through a cast.** The public routes are `handleBranchConflict` (needs a real `BranchConflictError` plus a git repo) and the `task:moved` listener (drags in the whole `execute()` path); going through either would make these tests about a git fixture rather than about the lane predicate. The alternative was the status quo — all 91 `executor-worktree*.test.ts` cases seed `column: "in-progress"`, so they assert the legacy fallback and pass either way. I shipped the conversions in one commit *stating* they were unproven, then closed that gap in the next; the history shows both. ### Two fake defects found while writing those tests Worth naming, because both are the documented green-for-the-wrong-reason shape: 1. The first fake had no `updateTask`, so the cleanup **threw** rather than asserting anything. 2. The second returned a new object without persisting — and `cleanupMergeStateForReverification` **re-reads through `getTask`**. The re-read handed back the stale row, so *both* vocabularies reported "nothing changed" and it would have read as a passing negative test. ## Deliberately NOT converted, with reasons - **The `task:moved` listener cluster** (`3521`/`3545`/`3596`/`3606`), including the AGENTS Move-Task hard-cancel contract `userCanceled: source === "user" && to === "todo"`. Its prologue is synchronous (`userCanceledTaskIds.delete`, watchdog clear) and deferring it to a microtask changes hard-cancel ordering. The sync IR reader is not an option — it returns the DEFAULT workflow for every task in production. A safe conversion needs lanes resolved on an earlier async boundary: new machinery plus an ordering change, which is out of fleet scope and not a guess worth making on a hard-cancel path. - **`17081`** pairs `latestColumn === "in-progress"` with a **hardcoded** `moveTask(taskId, "in-progress")` two lines above — census-invisible, the same shape as the branch-worktree requeue bug in #2797. They have to convert together, and the move needs the same rejection guard. - **`5903`** is the query-filter class: `listTasks({ column: "in-progress" })` followed by a re-assertion of the same literal. Converting it drops a count and changes nothing — see `docs/solutions/architecture-patterns/self-healing-sweeps-are-blind-on-a-renamed-board.md` (#2800). ## Verification - `pnpm test:gate` — 161 + 487 + 13 + 71, green - `npx tsc -p packages/engine/tsconfig.json --noEmit` — clean - `pnpm lint` — clean - `--strict` exits 0 --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
183 lines
10 KiB
JSON
183 lines
10 KiB
JSON
{
|
|
"generatedFrom": "node scripts/lifecycle-column-census.mjs --strict --update-baseline",
|
|
"byFile": {
|
|
"packages/engine/src/self-healing.ts": 97,
|
|
"packages/engine/src/scheduler.ts": 12,
|
|
"packages/core/src/task-store/async-comments-attachments.ts": 9,
|
|
"packages/dashboard/app/components/TaskContextMenu.tsx": 9,
|
|
"packages/engine/src/executor.ts": 8,
|
|
"packages/dashboard/app/components/Column.tsx": 7,
|
|
"packages/dashboard/app/components/ListView.tsx": 6,
|
|
"packages/engine/src/notification/notification-service.ts": 5,
|
|
"packages/engine/src/restart-recovery-coordinator.ts": 5,
|
|
"packages/dashboard/app/components/TaskDetailModal.tsx": 4,
|
|
"packages/engine/src/replan-target.ts": 4,
|
|
"packages/core/src/async-mission-store-queries.ts": 3,
|
|
"packages/core/src/task-store/async-merge-coordination.ts": 3,
|
|
"packages/core/src/task-store/task-artifacts-ops.ts": 3,
|
|
"packages/dashboard/app/components/DockTaskList.tsx": 3,
|
|
"packages/dashboard/app/components/TaskCard.tsx": 3,
|
|
"packages/dashboard/app/components/TaskChangesTab.tsx": 3,
|
|
"packages/dashboard/app/components/TaskChatTab.tsx": 3,
|
|
"packages/dashboard/app/hooks/useTaskDiffStats.ts": 3,
|
|
"packages/dashboard/app/utils/taskActivity.ts": 3,
|
|
"packages/dashboard/app/utils/worktreeGrouping.ts": 3,
|
|
"packages/dashboard/src/chat.ts": 3,
|
|
"packages/dashboard/src/routes/register-task-workflow-routes.ts": 3,
|
|
"packages/engine/src/planner-overseer.ts": 3,
|
|
"packages/core/src/agent-store.ts": 2,
|
|
"packages/core/src/async-mission-store.ts": 2,
|
|
"packages/core/src/node-override-guard.ts": 2,
|
|
"packages/core/src/task-move-disposer.ts": 2,
|
|
"packages/core/src/task-store/archive-lifecycle-2.ts": 2,
|
|
"packages/core/src/task-store/audit-ops.ts": 2,
|
|
"packages/core/src/task-store/comments-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/symbol-locks.ts": 2,
|
|
"packages/core/src/task-store/task-id-integrity.ts": 2,
|
|
"packages/dashboard/app/components/Board.tsx": 2,
|
|
"packages/dashboard/app/components/DocumentsView.tsx": 2,
|
|
"packages/dashboard/app/components/effective-model-resolution.ts": 2,
|
|
"packages/dashboard/app/components/WorkflowResultsTab.tsx": 2,
|
|
"packages/dashboard/app/utils/taskRevert.ts": 2,
|
|
"packages/dashboard/app/utils/taskTiming.ts": 2,
|
|
"packages/dashboard/src/github-tracking-state.ts": 2,
|
|
"packages/dashboard/src/server.ts": 2,
|
|
"packages/engine/src/auto-merge-finalization.ts": 2,
|
|
"packages/core/src/eval-automation.ts": 1,
|
|
"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/branch-and-pr-entities.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/ChangesDiffModal.tsx": 1,
|
|
"packages/dashboard/app/components/command-center/liveSnapshotMetrics.ts": 1,
|
|
"packages/dashboard/app/components/DevServerView.tsx": 1,
|
|
"packages/dashboard/app/components/MergeDetails.tsx": 1,
|
|
"packages/dashboard/app/components/PrPanel.tsx": 1,
|
|
"packages/dashboard/app/components/ResearchTaskActionModal.tsx": 1,
|
|
"packages/dashboard/app/components/RoutingTab.tsx": 1,
|
|
"packages/dashboard/app/components/TaskPlannerChatTab.tsx": 1,
|
|
"packages/dashboard/app/hooks/useExecutorStats.ts": 1,
|
|
"packages/dashboard/app/hooks/useTasks.ts": 1,
|
|
"packages/dashboard/app/utils/inReviewStallCopy.ts": 1,
|
|
"packages/dashboard/app/utils/quickAddStart.ts": 1,
|
|
"packages/dashboard/app/utils/stalePausedReviewCopy.ts": 1,
|
|
"packages/dashboard/app/utils/taskStuck.ts": 1,
|
|
"packages/dashboard/src/github-issue-comment.ts": 1,
|
|
"packages/dashboard/src/github-tracking-comments.ts": 1,
|
|
"packages/dashboard/src/gitlab-issue-comment.ts": 1,
|
|
"packages/dashboard/src/gitlab-source-issue-reconciler.ts": 1,
|
|
"packages/dashboard/src/gitlab-tracking-comments.ts": 1,
|
|
"packages/dashboard/src/knowledge-index-refresh.ts": 1,
|
|
"packages/dashboard/src/planning-board-tools.ts": 1,
|
|
"packages/dashboard/src/research-routes.ts": 1,
|
|
"packages/dashboard/src/routes/register-agent-core-routes.ts": 1,
|
|
"packages/dashboard/src/routes/register-chat-routes.ts": 1,
|
|
"packages/dashboard/src/task-planner-chat-context.ts": 1,
|
|
"packages/dashboard/src/task-planner-chat-metrics.ts": 1,
|
|
"packages/dashboard/src/test/mockCoreEngine.ts": 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/pr-comment-handler.ts": 1,
|
|
"packages/engine/src/runtimes/in-process-runtime.ts": 1,
|
|
"packages/engine/src/triage.ts": 1
|
|
},
|
|
"deliberateByFile": {
|
|
"packages/dashboard/src/reliability-metrics.ts\u0000in-review": 4,
|
|
"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\u0000triage": 2,
|
|
"packages/dashboard/app/components/TaskDetailModal.tsx\u0000triage": 2,
|
|
"packages/engine/src/cli-agent/state-machine.ts\u0000done": 2,
|
|
"packages/engine/src/scheduler.ts\u0000in-progress": 2,
|
|
"packages/engine/src/scheduler.ts\u0000in-review": 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-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/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/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\u0000todo": 1,
|
|
"packages/dashboard/app/components/TaskContextMenu.tsx\u0000triage": 1,
|
|
"packages/dashboard/app/components/TaskDetailModal.tsx\u0000todo": 1,
|
|
"packages/dashboard/app/utils/columnRoles.ts\u0000todo": 1,
|
|
"packages/dashboard/src/github-tracking-state.ts\u0000archived": 1,
|
|
"packages/dashboard/src/github-tracking-state.ts\u0000done": 1,
|
|
"packages/dashboard/src/reliability-metrics.ts\u0000done": 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/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\u0000archived": 1,
|
|
"packages/engine/src/scheduler.ts\u0000done": 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/engine/src/self-healing.ts": 48,
|
|
"packages/engine/src/project-engine.ts": 7,
|
|
"packages/engine/src/backlog-pressure-reporter.ts": 3,
|
|
"packages/core/src/task-store/async-persistence.ts": 2,
|
|
"packages/core/src/task-store/merge-queue-ops.ts": 2,
|
|
"packages/core/src/task-store/moves.ts": 2,
|
|
"packages/engine/src/executor.ts": 2,
|
|
"packages/engine/src/stale-task-reporter.ts": 2,
|
|
"packages/cli/src/extension.ts": 1,
|
|
"packages/core/src/async-mission-store.ts": 1,
|
|
"packages/core/src/eval-automation.ts": 1,
|
|
"packages/core/src/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/core/src/task-store/task-artifacts-ops.ts": 1,
|
|
"packages/core/src/task-store/task-store-helpers.ts": 1,
|
|
"packages/dashboard/src/routes/register-gitlab.ts": 1,
|
|
"packages/engine/src/agent-tools.ts": 1,
|
|
"packages/engine/src/auto-merge-finalization.ts": 1,
|
|
"packages/engine/src/restart-recovery-coordinator.ts": 1,
|
|
"packages/engine/src/scheduler.ts": 1,
|
|
"packages/engine/src/workflow-node-handlers.ts": 1
|
|
}
|
|
}
|