Files
fusion/packages/core
gsxdsm f7a7347e1b test(core): cover #3057's cold-storage conversion; audit two archived literals as dead sync (#3089)
**Replaces #3085, which I am closing.** #3057 landed the same
cold-storage conversion while that PR was open. Rather than argue about
which spelling wins, this keeps only what `main` does not have: the
coverage, and two audits.

## #3057 converted this and shipped no test

`listTasksImpl`'s `columnFilterIsArchive` replaced `columnFilter ===
"archived"`. Correct change — and the kind that needs a test more than
most, because of how it fails.

Archived rows do not live in `tasks`; `archiveTask` copies them into the
archive store and removes them. This decision is whether that second
store is read **at all**. Against the literal, a caller naming a renamed
archive lane — `listTasks({ column: "filed", includeArchived: true })`,
which is what an archive view does — got an empty page from the only API
that can reach those rows.

Note the shape: the **unfiltered** read (`!columnFilter`) was always
correct. It fails only for the caller that names the lane, so it
survives any board-level smoke test and presents as *"the archive is
empty"* rather than as a bug. That is precisely the class that regresses
quietly once the conversion that fixed it has nothing holding it.

Three cases, and each earns its place:

| case | what it stops |
|---|---|
| renamed archive lane | the regression itself |
| legacy `archived` id (**control**) | a future conversion that resolves
the renamed lane and *drops* the legacy seed — the seeding hazard in its
other direction |
| non-archive lane (**negative**) | the widening turning every filtered
board read into a second-store round-trip |

**MUTATION**: restoring `columnFilter === "archived"` fails **only** the
renamed case.

**A trap worth recording.** My first version left the LIVE read real
against a fake `layer.db`. It threw, the `.catch` swallowed it, and all
three cases passed the negative — *including the legacy control*, which
is what exposed it. A test whose subject is never reached looks
identical to one whose subject answered no. `readLiveTaskRows` is mocked
now, and the control is what made it detectable.

## Audited, not converted — two dead sync paths

Both would be real defects if they ran. Neither runs.

| site | why it is dead |
|---|---|
| `mission-store.ts` (feature-delete link check) | `getMissionStoreImpl`
returns the AsyncDataLayer-backed `AsyncMissionStore` under PostgreSQL;
the sync `MissionStore` reached via `this.db.prepare` is legacy SQLite
only |
| `lifecycle-ops.ts` (polling-replica archive emit) |
`checkForChangesImpl` opens with `store.db.getLastModified()` /
`store.db.prepare`, which throw in backend mode |

The second is the sharper one: **both** its guard and the `to:
"archived"` it emits are literals, so a polling replica on a renamed
board would emit a move to a column the board does not declare.

Recorded in place — the treatment `project-store-ops.ts`'s dequeue twin
already has — so the census entries are not mistaken for unconverted
debt, and whoever deletes the sync SQLite residue takes these with it.

**They stay COUNTED.** Marking them DELIBERATE-LITERAL would buy a
smaller number by asserting the code is *correct*. It is not correct; it
is unreachable. Those are different claims with different expiries, and
the census should keep pointing here until the code is gone.

## Census

No movement — by design. This PR adds coverage and audits; it converts
nothing that was not already converted on `main`.

## Measured

- 3 new cases pass; `src/__tests__/{cold-storage,archive,unarchive}*` —
**6 files / 21 tests pass**
- `tsc --noEmit -p packages/core` clean; census `--strict` clean

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 04:06:40 -07:00
..
2026-07-26 18:11:47 -07:00