fleet: resolve the pre-archive unarchive target (census 69 → 68) (#3091)
## Census
| | column guards |
|---|---|
| before | **69** |
| after | **68** |
## How this was found
By finishing a triage I'd left incomplete. Of the 19 single-guard files,
I had actually examined six and flagged the rest partly on assumption —
so I went back and read them.
Five of the remaining ones turned out to be `archived` comparisons
**pinned by `archived-column-gate-parity.test.ts`** (`audit-ops`,
`task-id-integrity`, `mission-store`, `async-comments-attachments`, plus
`merge-queue-ops-2` for review). Converting any of those moves one of
three encodings that must move together.
**This one isn't pinned**, and that difference is the whole PR.
## What changed
```ts
if (!declaresPreArchiveColumn || preArchiveColumn === archivedColumn
|| preArchiveColumn === "archived")
```
Belt-and-braces: the condition already accepted the resolved lane **or**
the legacy id, stated twice. A set says it once, so the two halves can't
drift apart — the real risk with a duplicated condition, rather than the
census count.
## Why this isn't the split brain
The parity guard pins comparisons of a **task's column** — one of three
encodings of *"an archived task is not live."* This compares a **stored
`preArchiveColumn` value** against the board's archive lane: a different
question, about where to send a card on unarchive.
Verified rather than argued — that suite runs **green** here, and it
went **red** the last time I touched a pinned site (#3076, where I named
an arm and immediately reverted). It's a live check, not an assumption.
## Measured
| check | result |
|---|---|
| archive / artifact / unarchive suites | 7 files, **27 tests green** |
| `archived-column-gate-parity` | **2 passed** |
| five gates + strict census | green |
| core `tsc` | clean |
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -35,6 +35,9 @@ import { join } from "node:path";
|
||||
import { storeLog } from "../store.js";
|
||||
import { resolveArchivedLanes } from "../project-lane-vocabulary.js";
|
||||
|
||||
/* DELIBERATE-LITERAL — the no-resolution fallback for the archive lane above. */
|
||||
const LEGACY_ARCHIVE_LANES: readonly string[] = ["archived"];
|
||||
|
||||
export function listWorkflowWorkItemsForTaskSyncImpl(store: TaskStore, taskId: string, opts: { kinds?: WorkflowWorkItemKind[] } = {}): WorkflowWorkItem[] {
|
||||
const conditions = ["taskId = ?"];
|
||||
const params: unknown[] = [taskId];
|
||||
@@ -433,7 +436,21 @@ export async function resolveUnarchiveTargetColumnImpl(
|
||||
&& (lifecycle !== undefined
|
||||
? declaredColumnIds.has(preArchiveColumn)
|
||||
: isColumn(preArchiveColumn));
|
||||
if (!declaresPreArchiveColumn || preArchiveColumn === archivedColumn || preArchiveColumn === "archived") {
|
||||
/*
|
||||
FNXC:WorkflowResolvedColumns 2026-07-31-18:20 (fleet — the pre-archive unarchive target):
|
||||
RESOLVED archive lane UNION the legacy id, stated once instead of twice.
|
||||
|
||||
The condition already accepted either — `archivedColumn` when the workflow resolved, and the
|
||||
literal as a belt-and-braces second arm. A set says that once, so the two halves cannot drift
|
||||
apart, which is the real risk with a duplicated condition rather than the census count.
|
||||
|
||||
NOT the same as the sites `archived-column-gate-parity.test.ts` pins: those compare a TASK's
|
||||
column and are one of three encodings that must move together. This compares a stored
|
||||
`preArchiveColumn` VALUE against the board's archive lane, so it is not part of that gate —
|
||||
verified by running that suite, which stays green.
|
||||
*/
|
||||
const archiveLanes = new Set<string>([archivedColumn, ...LEGACY_ARCHIVE_LANES].filter((c): c is string => c !== undefined));
|
||||
if (!declaresPreArchiveColumn || archiveLanes.has(preArchiveColumn)) {
|
||||
if (completeColumn === undefined) {
|
||||
throw new Error(`Cannot resolve an unarchive target${taskId ? ` for ${taskId}` : ""}: its workflow declares no complete column`);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
"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/moves.ts": 1,
|
||||
"packages/core/src/task-store/task-artifacts-ops.ts": 1,
|
||||
"packages/core/src/task-store/task-id-integrity.ts": 1,
|
||||
"packages/dashboard/app/components/ResearchTaskActionModal.tsx": 1,
|
||||
"packages/dashboard/app/components/TaskCard.tsx": 1,
|
||||
|
||||
Reference in New Issue
Block a user