commit ba41b56d6e7f6a9b815923102d283bbf7208d651
parent c6fce8148e47f3f5a3b1b22feabc89f536f16bde
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Wed, 23 Sep 2026 20:22:27 -0400
plans: STATE — Phase 3 slices 2 + 4a on main @ a7501cb3, gate B done
New head (what shipped, gates, next release, what is still owed), a
one-core phase-status table, six 2026-09-23 decisions, gate B struck
through with a pointer to its record, and the stale release-worktree
sentence corrected (they are gone).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat:
| M | plans/STATE.md | | | 86 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- |
1 file changed, 81 insertions(+), 5 deletions(-)
diff --git a/plans/STATE.md b/plans/STATE.md
@@ -3,7 +3,42 @@
The working memory for the local-AI derived-corpus work. Rewritten at the end of every
session, before context is cleared. See [`README.md`](README.md) for the protocol.
-**Last updated:** 2026-09-22 — **the release *curated-tags follow-ups + debts sweep* is on
+**Last updated:** 2026-09-23 — **one-core Phase 3 slices 2 and 4a are on `main` @
+`ae2fa5a9`, and gate B is done.** Base `54cf1b31`; two branches merged in the order
+`one-core/phase-3-s2` → `8d6e84f6`, then `one-core/phase-3-s4a` → `ae2fa5a9` (with `main`
+merged into it as `7035316c`). Release record, gates and the next release's inventory:
+[`one-core-phase-3.md`](one-core-phase-3.md#release-2026-09-23--slices-2-and-4a); anchors:
+[`FACTS.md`](FACTS.md#one-core-phase-3-slices-2--4a-verified-2026-09-23-main--ae2fa5a9).
+
+- **Slice 2 — one polling route.** `/api/view/[name]` serves eight named views from one total
+ handler table; the eight old API paths are `rewrites()` (not redirects), so pinned widgets
+ and scripts keep working; one client poller, `editor/app/lib/usePolledPayload.ts` (serial,
+ abort + timeout). No number moved (`plans/tools/phase3-view-numbers.ts`, empty diff).
+- **Slice 4a — one settings schema.** zod joins `common`; `common/lib/settingsSchema.ts` is
+ every key, default and clamp; `lib/settings.ts` is I/O (1,783 → 250 lines); every editor
+ save goes through `saveSettings(patch)`; `SETTINGS.md` + `settings.json.example` are
+ generated by `common/bin/settings-example.ts` and pinned by a test. Allow-list 10 → 9.
+ Read AND write of every real settings file diff-empty
+ (`plans/tools/phase3-settings-numbers.ts`). One fix: saving a storage location no longer
+ erases `storage.savedVideosLocationId`.
+- **Gate B — done 2026-09-23**, reachable media only: `backfill.allowRedownload: false`,
+ `autoQueue.backfill.held: true`, lane still `enabled: false`, set through the lane form on
+ `/operations/diarization`. Record:
+ [`one-core-phase-1.md`](one-core-phase-1.md#gate-b--passed-2026-09-23). Arming the lane is a
+ later, separate act; expected work then is the ~679 reachable.
+
+**Gates on `ae2fa5a9`:** tsc clean; common 1663; editor unit 67; scripts 156 + 1 skip; mcp
+219; editor and export builds green. Full e2e: see the release record.
+
+**Next release:** Phase 3 slice 3 (one drawing per noun) and slice 4b (`site.json`, channel
+`config.json`, sidecars) — inventory in the release record.
+
+**Still owed (operator):** the Anilyzer **production** deploy (preview is up, see below); the
+other five sites to corpus spec 4; the LM chat-only tier (shipped, unconfigured). **Owed
+(code):** the backfill lane form's hint text still says 836 reachable (gate B measured 679) —
+`LaneSettingsForm.tsx:101`.
+
+**Previously:** 2026-09-22 — **the release *curated-tags follow-ups + debts sweep* is on
`main` @ `766e0873`.** Base `4ac8ceda`; three branches merged in the order
`1a011d96` alone → `tags/rules-and-ops` (`9837f066`) → `export/tags-followups` (`cb254919`)
→ `editor/debts` (`766e0873`). Anchors for every seam are in
@@ -120,7 +155,8 @@ Worktrees `storage-locations-s0..s4` and `s0-pause` removed. Branches deleted:
`one-core/phase-1`, the seven `umtool/*`, `one-core/s0-pause`. **Kept:**
`parked/download-filter-preview`, `p1-e2e`, `worktree-duplicates-page`, `diet-series`. The
three release worktrees and branches (`tags/rules-and-ops`, `export/tags-followups`,
-`editor/debts`) go once the final gates are in. Nothing unmerged was deleted.
+`editor/debts`) are gone — checked 2026-09-23, neither `git worktree list` nor `git branch`
+shows them. Nothing unmerged was deleted.
### Post-release operator steps — done 2026-09-22 evening except the deploy
@@ -260,10 +296,12 @@ scopes migrating into lane trees, both `enabled: false`.
left it; the step-by-step runbook, including the exact `settings.json` block and the
channel to point it at, is in `one-core-phase-1.md`'s "Operator gate A" section. It gates
the MERGE of 1.3 onward, not their authorship, which is why the branch exists.
-- **Gate B** — before the backfill lane is ever `enabled` in production, decide
+- ~~**Gate B** — before the backfill lane is ever `enabled` in production, decide
`backfill.allowRedownload` and the channel scope. As configured today it would re-fetch
audio for ~66,540 videos. The migration left the lane disabled; the tree's channel leaves
- are the scope from now on.
+ are the scope from now on.~~ — **DONE 2026-09-23: reachable media only**
+ (`allowRedownload: false`, lane held, still disabled). Record:
+ [`one-core-phase-1.md`](one-core-phase-1.md#gate-b--passed-2026-09-23).
- ~~**The four legacy pause fields go only once the live `settings.json` carries all four
`held` keys**~~ — **DONE 2026-09-22 (S0-pause, in `editor/debts`).** The four fields
(`transcriptionsPaused`, `downloadsPaused`, `digest.digestsPaused`, and the inverted
@@ -537,7 +575,8 @@ held. Boot this release once, confirm all four `held` keys are in the live `sett
then take it.
**Then the rest of one-core Phase 3** — views in the core, editor as shell, four slices
-([`one-core.md`](one-core.md) §Phase 3); slice 1 shipped (above), slices 2–4 unplanned. Read `common/architecture.test.ts`'s allow-list
+([`one-core.md`](one-core.md) §Phase 3); slice 1 shipped (above), **slices 2 and 4a shipped
+2026-09-23** (see the head of this file), slices 3 and 4b are the next release. Read `common/architecture.test.ts`'s allow-list
first: it is the shortest accurate statement of what is still tangled. Phase 2 left it at
**eleven entries, byte-identical to the base**, while ADDING `"components"` to
`FORBIDDEN.lib` — the forbidden list grew and the debt ledger did not.
@@ -1381,6 +1420,17 @@ again — server modules hot-reload under `next dev`, but a job in flight holds
| 11a · Review queue | **minimum landed** | Total failures now persist warnings (they used to persist none), `buckets.digestWarnings` + a `digest_warnings` filter + an /actionable section, and duplicate-cluster confirm/reject. Approve/dismiss state deferred — needs new persistence. |
| 11b · Viewer feedback | not started | |
+**One-core phases** (the umbrella is [`one-core.md`](one-core.md); this table is the status
+of THAT plan, not of PLAN.md's phases above):
+
+| One-core phase | Status | Notes |
+| --- | --- | --- |
+| 0 · Guardrails | **shipped** 2026-09-07 | |
+| 1 · One scheduler | **shipped**; gate A passed 2026-09-13, **gate B done 2026-09-23** | Records in `one-core-phase-1.md`. |
+| 2 · One `ArchiveReader` | **shipped** (on `main` since 2026-09-13) | |
+| 3 · Views in the core | **slices 1, 2, 4a shipped** (2026-09-15, 2026-09-23, 2026-09-23) | Slice 3 and slice 4b are the next release. `one-core-phase-3.md`. |
+| 4–6 | not started | Phase 4's `settings example` already exists (`common/bin/settings-example.ts`). |
+
**Three corrections to this document's own claims, verified against the code 2026-07-29.**
Exploration for Phase 2 found the planning docs describing more unbuilt work than exists:
@@ -1455,6 +1505,32 @@ parallel task), Phase 0 transcription benchmark (a separate bottleneck).
## Decisions log
+**One-core Phase 3 is the direction (2026-09-23).** Not PLAN.md's derived-corpus phases and
+not the umtool backlog. Operator, via the question tool.
+
+**This release is Phase 3 slices 2 and 4a, nothing else (2026-09-23).** Slice 2 = one polling
+route; slice 4a = one zod schema for `settings.json` only, one `saveSettings` writer, the
+example and the key table generated. Slice 3 and slice 4b (`site.json`, channel
+`config.json`, sidecars) are the NEXT release. Not folded in: the Anilyzer production deploy,
+the other five sites to spec 4, the LM chat-only tier.
+
+**zod is adopted (2026-09-23).** One dependency, in `common/`; the veto point `one-core.md`
+left open is spent. It must stay out of client bundles, which is why the zod seams live in
+`lib/settingsFieldSchemas.ts` and not beside the sanitizers the forms import.
+
+**Gate B: reachable media only (2026-09-23).** `backfill.allowRedownload` false, the lane
+held, scope every channel. Folded into this release as a prelude — a settings change through
+the existing surface plus a runbook record, no code. Arming the lane stays a separate act.
+
+**Old API paths are `rewrites()`, not redirects; no batch route (2026-09-23).** A rewrite keeps
+method, body and `?rev=` and the client never learns the path moved, so pinned widgets keep
+working. No `names=a,b` batch route: cadences stay per call site, and Phase 6's SSE is the
+batch.
+
+**`saveSettings(patch: Partial<SiteSettings>)`, not `saveSettingsBlock(block, patch)`
+(2026-09-23).** One-level-deep merge. `channels/actions.ts` writes `channelPriority` and the
+four `autoQueue` roots atomically; a one-block signature would split that write in two.
+
**S0-pause ships in this release rather than waiting for the live file (2026-09-22).** The
standing condition was "the four legacy pause fields go only once the live `settings.json`
carries all four `held` keys". Waiting bought nothing a default could not: `sanitizeAutoQueue`