Files
fusion/scripts/lib/lifecycle-column-census-baseline.json
gsxdsm c143327d4b fix(core): the archived-document guards failed in OPPOSITE directions on a renamed lane (#2886)
Two of the four convertible sites my own learnings doc **miscounted as
sentinels** — the #2877 review corrected "8 of 9 must not be converted"
to "5 of 9", and these are two of the three that correction freed.

They read `task.column` straight off a row `select`, so they are board
lanes by exactly the test that document gives, and a renamed archived
column is simply not seen. What makes the pair worth fixing together is
that they fail in **opposite directions**:

| guard | on a renamed archived lane | consequence |
|---|---|---|
| `upsertTaskDocument` | fails to **reject** | an archived card's
documents stay **writable** — the read-only contract silently does not
hold |
| `publishArchivedTaskDocumentAddition` | fails to **accept** | a
legitimate archived-document publication is refused as
`parent-not-archived` |

The second is the sharper one: valid operator work refused, and refused
with a message that reads as a data-integrity error rather than a
lifecycle mismatch.

## Shape

Both take an `AsyncDataLayer` and can resolve nothing themselves; their
store-level impls hold the store, so the lane set arrives as a parameter
resolved once per call — the shape #2875 used for the SQL predicate.

**One shared `resolveArchivedLanes` for both paths**, deliberately: if
the write guard and the publication guard could disagree about whether a
card is archived, a card ends up both read-only *and* un-publishable.

## The revert proof caught my own fixture first

My first version set `deletedAt` alongside the renamed column, and **the
revert proof passed with the fix removed**. Both guards are
`column-is-archived || deletedAt != null`, so a soft-deleted fixture
short-circuits the exact comparison under test — the assertion was
holding for an unrelated reason.

Dropping `deletedAt` isolates it, and is also the *real* shape: a live
row in a workflow-declared archived lane is what a renamed board
produces, and what `getLiveTaskColumn` was written to catch.

Revert proof, measured honestly the second time: restore `task.column
=== "archived"` and the renamed-lane case fails — the upsert resolves
instead of rejecting.

## Real PostgreSQL, deliberately

These are row predicates inside a transaction. A mocked store would
assert the arguments and prove nothing about the comparison that runs —
the same reasoning as #2875.

Three cases: the renamed lane rejects, the **legacy** `archived` id
still rejects (most boards never rename anything), and a live card is
still allowed through (a guard that rejects everything is its own bug).

## Verification

- `pnpm test:gate` — 161 / 487 / 13 / 71 passed
- `pnpm lint` — clean
- `tsc --noEmit` (`@fusion/core`) — clean
- new `archived-document-lanes.pg.test.ts` + existing
`artifacts-documents-evals.pg.test.ts` — 12 passed against real
PostgreSQL

Note: the SQL-literal baseline is untouched here — #2881 owns
re-recording it after #2864's conversion left main's gate red.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 17:40:30 -07:00

144 lines
8.5 KiB
JSON

{
"generatedFrom": "node scripts/lifecycle-column-census.mjs --strict --update-baseline",
"byFile": {
"packages/engine/src/self-healing.ts": 87,
"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/async-mission-store-queries.ts": 3,
"packages/core/src/task-store/task-artifacts-ops.ts": 3,
"packages/engine/src/planner-overseer.ts": 3,
"packages/core/src/agent-store.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/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/src/reliability-metrics.ts\u0000in-review": 4,
"packages/dashboard/app/components/TaskContextMenu.tsx\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/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\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-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\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/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\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": 35,
"packages/core/src/task-store/async-persistence.ts": 2,
"packages/core/src/task-store/merge-queue-ops.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,
"packages/engine/src/workflow-node-handlers.ts": 1
}
}