From db71b4fffb45253d6a13cccbc48877c5dfc2bb0b Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Fri, 31 Jul 2026 06:55:03 -0700 Subject: [PATCH] =?UTF-8?q?docs(core):=20scope=20the=20archived=20three-en?= =?UTF-8?q?coding=20decision=20=E2=80=94=20it=20is=20not=2052-or-nothing?= =?UTF-8?q?=20(#3147)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `archived` family is the largest unclaimed cluster (52 sites) and its blocker is that **nobody has scoped it**. This scopes it. It converts nothing. ## The two options both read as enormous because 52 sites are counted as one lump They are not one lump. The sites answer **two different questions**: | question | renameable? | |---|---| | **LANE** — "is this row resting in the board's archive lane?" | yes — must resolve | | **STATE** — "did Fusion archive this row?" (the marker `archiveTask` writes) | **no** | `async-maintenance.ts` already draws that line and marks its own site DELIBERATE-LITERAL: > `'archived'` is the STATE marker here, not a lane. This sweep collects rows Fusion itself archived or soft-deleted; a card merely sitting in a workflow's archived-TRAIT lane is live work and must not be collected. Widening to the resolved archived set would pull real cards into a cleanup pass. **Converting that site would be a bug, not progress.** `async-archive-lineage.ts`'s soft-delete path is the same shape — `column = 'archived', deleted_at IS NOT NULL` is the storage state it has just written. So the first question is a **triage**, not a conversion: which of the 52 are lane questions? Nobody has answered it, which is exactly why the cost reads as unbounded. ## Measured: the SQL half, which the existing note calls the hard part 8 Drizzle sites across 7 files. **Four already have `store` in scope** — they could take a resolved set today with no signature change: - `branch-group-ops.ts` — `clearNearDuplicateReferencesToImpl(store, ...)` - `branch-and-pr-entities.ts` — `findRecentTasksByContentFingerprintImpl(store, ...)` (2 sites) - `task-mutation-ops.ts` — `cleanupArchivedTasksImpl(store)` **Four need one parameter each**, the same optional-lane-set shape used throughout this program: - `async-lifecycle.ts` — `liveLineageChildFilter(parentId, projectId?)` - `async-search.ts` — `liveSearchPredicate(includeArchived, projectId?)` - `async-self-healing.ts` — `listSoftDeletedColumnDriftCandidates(db, ...)` - `store.ts` — the revert-lookup conditions (already holds `this.asyncLayer`) That is not *"threading a resolver into the persistence layer"*. It is four call sites that already have what they need, plus four one-parameter widenings — **before** any triage removes the STATE sites from the count entirely. ## What I did not do, and why The triage itself: a per-site judgement about what each guard *means*. That belongs to whoever owns this gate, not to a passing fleet lane — and getting it wrong in the STATE direction pulls live cards into a cleanup sweep, which is the one failure mode here that destroys work rather than hiding an affordance. What was cheap and missing was the **shape** of the problem. ## Measured - Comment-only; parity test **2/2**. - `tsc --noEmit -p packages/core` clean; census `--strict` clean. - `check-fnxc-future-dates` is red from `main`'s own #3128 stamps — **#3139** fixes that; this branch inherits and does not add to it. ## Census No movement. Co-authored-by: Claude Opus 5 (1M context) --- .../archived-column-gate-parity.test.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/packages/core/src/__tests__/archived-column-gate-parity.test.ts b/packages/core/src/__tests__/archived-column-gate-parity.test.ts index e02205c233..7269e1254c 100644 --- a/packages/core/src/__tests__/archived-column-gate-parity.test.ts +++ b/packages/core/src/__tests__/archived-column-gate-parity.test.ts @@ -113,6 +113,34 @@ NOT CONVERTED HERE, and deliberately: the gate requires all three encodings to m conversion is one coordinated change with its inventories updated in the same commit. This supplies the classification that change needs; it does not pre-empt it. +FNXC:WorkflowResolvedColumns 2026-07-31-23:55 (SCOPING — the choice is not 52-or-nothing): +"Convert all three encodings" and "declare `archived` non-renameable" are the two options offered, and +both sound enormous because 52 sites are counted as one lump. They are not one lump: the sites answer +TWO DIFFERENT QUESTIONS, and only one of them is a lane question. + + LANE: "is this row resting in the board's archive lane?" — renameable, must resolve. + STATE: "did Fusion archive this row?" — the marker `archiveTask` writes, NOT renameable. + +`async-maintenance.ts` already draws that line and marks its site DELIBERATE-LITERAL: "the STATE +marker here, not a lane... a card merely sitting in a workflow's archived-TRAIT lane is live work and +must not be collected." Converting that site would be a BUG, not progress. + +MEASURED, on the SQL half this file calls the hard part — 8 Drizzle sites across 7 files: + FOUR already have a `store` in scope and could take a resolved set with no signature change: + branch-group-ops.ts clearNearDuplicateReferencesToImpl(store, ...) + branch-and-pr-entities.ts findRecentTasksByContentFingerprintImpl(store, ...) [2 sites] + task-mutation-ops.ts cleanupArchivedTasksImpl(store) + FOUR need one parameter each, the optional-lane-set shape used throughout this program: + async-lifecycle.ts liveLineageChildFilter(parentId, projectId?) + async-search.ts liveSearchPredicate(includeArchived, projectId?) + async-self-healing.ts listSoftDeletedColumnDriftCandidates(db, ...) + store.ts the revert-lookup conditions (already holds `this.asyncLayer`) + +That is not "threading a resolver into the persistence layer". It is four call sites that already have +what they need plus four one-parameter widenings — before the triage above removes the STATE sites +from the count. (Two of the four "already have a store" sites turned out to be STATE on inspection; +the triage note above is the authority, this is the reachability survey that preceded it.) + FNXC:WorkflowResolvedColumns 2026-07-31-23:50 (one wrong reason for picking the cheap option, removed): The second option looks like it has already been taken — `trait-types.ts` annotates the flag "RESTRICTED (built-in only)", which reads as "a custom board cannot have its own archive lane". It does