fix(core): mark the two archived STATE sites at the site — converting them destroys live work (#3157)
The LANE/STATE triage (#3154) found that **two of the eight** Drizzle `archived` sites are STATE markers that must never be resolved. That classification lived only in `archived-column-gate-parity.test.ts`. A coordinated three-encoding conversion **edits these files**. A converter working file-by-file sees the same `eq(column, "archived")` shape as the six LANE sites, with nothing in front of them to tell the two apart. So the markers go at the sites. ## `task-mutation-ops.ts` — `cleanupArchivedTasksImpl` Enumerates rows Fusion itself archived, then **removes their directories**. Widening it to the resolved archived-lane set would feed cards **merely resting in a board's archived-trait lane** into a filesystem delete. This is the only site in this family where a wrong conversion **destroys work** rather than hiding an affordance. ## `async-self-healing.ts` — `listSoftDeletedColumnDriftCandidates` Finds soft-deleted rows whose column **drifted** from the marker they are supposed to carry. Resolving it would classify a soft-deleted row in a renamed archive lane as drift and "repair" a row that is already correct. ## Why this is defensive rather than cosmetic The triage exists to make the conversion safe. A classification the converter **cannot see while editing the file** does not do that — it only helps someone who happens to read the gate's test file first, which is not how a file-by-file sweep proceeds. Both are marked DELIBERATE-LITERAL with the reason and a pointer to the parity test holding the full eight-site split. ## Measured - Comment-only. - Parity test **2/2**; archive + soft-delete suites — **5 files / 15 tests pass**. - `tsc --noEmit -p packages/core` clean; census `--strict` and `check-sql-column-literals` clean. - **No census movement** — a DELIBERATE-LITERAL marker on a STATE site is a classification, and these were never counted as lane debt. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -55,6 +55,17 @@ interface SoftDeletedColumnDriftCandidate {
|
||||
export async function listSoftDeletedColumnDriftCandidates(
|
||||
db: AsyncDataLayer["db"],
|
||||
): Promise<SoftDeletedColumnDriftCandidate[]> {
|
||||
/*
|
||||
FNXC:WorkflowResolvedColumns 2026-07-31-23:59 DELIBERATE-LITERAL — STATE MARKER, DO NOT RESOLVE:
|
||||
`"archived"` is the marker a soft-deleted row is SUPPOSED to carry, and this query finds rows whose
|
||||
column DRIFTED away from it. Resolving it to the board's archived-lane set would classify a
|
||||
soft-deleted row sitting in a renamed archive lane as drift and "repair" a row that is already
|
||||
correct.
|
||||
|
||||
Marked at the site for the same reason as `task-mutation-ops.ts`'s cleanup sweep: the LANE/STATE
|
||||
classification lived only in `archived-column-gate-parity.test.ts`, and a coordinated conversion
|
||||
edits this file. The shape here is indistinguishable from the six LANE sites without it.
|
||||
*/
|
||||
const rows = await db
|
||||
.select({ id: schema.project.tasks.id, column: schema.project.tasks.column })
|
||||
.from(schema.project.tasks)
|
||||
|
||||
@@ -1066,6 +1066,21 @@ export async function cleanupArchivedTasksImpl(store: TaskStore): Promise<string
|
||||
quarantine partition.
|
||||
*/
|
||||
const projectId = layer.projectId?.trim() || "__legacy_unscoped__";
|
||||
/*
|
||||
FNXC:WorkflowResolvedColumns 2026-07-31-23:59 DELIBERATE-LITERAL — STATE MARKER, DO NOT RESOLVE:
|
||||
`"archived"` here is the marker `archiveTask` WROTE, not a board lane. This sweep enumerates rows
|
||||
Fusion itself archived and then REMOVES THEIR DIRECTORIES (`rm` below). Widening it to the
|
||||
resolved archived-lane set would feed cards merely RESTING in a board's archived-trait lane into
|
||||
a filesystem delete — live work, destroyed.
|
||||
|
||||
Marked at the site because the classification previously lived only in
|
||||
`archived-column-gate-parity.test.ts`, and a coordinated three-encoding conversion edits THIS
|
||||
file. A converter working file-by-file would see the same `eq(column, "archived")` shape as the
|
||||
six LANE sites and have nothing here telling them apart.
|
||||
|
||||
The sibling STATE site is `async-self-healing.ts`'s soft-deleted column-drift query; the LANE/
|
||||
STATE split for all eight Drizzle sites is recorded in that parity test.
|
||||
*/
|
||||
const archivedRows = await layer.db
|
||||
.select()
|
||||
.from(schema.project.tasks)
|
||||
|
||||
Reference in New Issue
Block a user