Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit 15300ae7349e3d6a313ced7d35c4a2b5f12aab75
parent b29e34ccb4e9dce6bbf6bc9375357833e7700e4d
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Wed, 23 Sep 2026 20:20:01 -0400

plans: phase 3 release 2026-09-23 (slices 2 + 4a) and the next release

A release head above the slice records (merge order, gates on a7501cb3,
two e2e placeholders), a next-release section for slices 3 and 4b with the
deferred follow-ups checked open, and the two slice records corrected
against the branches (6c11b094 and b5094303 were missing; line and test
counts updated to the tips).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Diffstat:
Mplans/one-core-phase-3.md | 118++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 108 insertions(+), 10 deletions(-)

diff --git a/plans/one-core-phase-3.md b/plans/one-core-phase-3.md @@ -478,16 +478,109 @@ claimed fixed; the reads are in-memory). > ONCE via `Promise.all` and hands the same pair to all four lanes. `getAutoRunnerStatus` is > still called per lane and is genuinely in-memory. +## Release 2026-09-23 — slices 2 and 4a + +`main` `54cf1b31` → **`ae2fa5a9`**. Two branches, both off `54cf1b31`, merged in this order: + +1. **`one-core/phase-3-s2` → `8d6e84f6`** — one polling route. Five commits, `5397f83c` + `074f09a2` `edf56370` `4288009b` `c205b270`. +2. **`one-core/phase-3-s4a` → `ae2fa5a9`** — one zod schema for `settings.json`, one editor + writer, the example and the key table generated. Seven commits, `50215ab5` `e120a2a5` + `f1abe024` `85478527` `0316e988` `5b43dc8d` `81deae69`, then `main` merged in as + `7035316c`. + +**Why that order:** slice 2 first, so a rewrite sits in front of every polling request on a +green `main` *before* the settings reader underneath those views changes. Had the order been +reversed, a regression in the schema would have surfaced through eight route files that were +about to be deleted, and slice 2's before/after numbers would have been measured across two +changes at once. + +**Scope, decided with the operator 2026-09-23.** This release is slice 2 and slice 4a only. +Slice 4a is `settings.json` alone — `site.json`, channel `config.json` and the sidecars are +slice 4b. Slice 3 and slice 4b are the next release. zod is adopted (one dependency, in +`common/`), which spends the veto `one-core.md` left open. Gate B from Phase 1 rode along as a +prelude — a settings change through the existing surface plus a record, no code +([`one-core-phase-1.md`](one-core-phase-1.md#gate-b--passed-2026-09-23)). + +**Gates on merged `main` `ae2fa5a9`:** `tsc --noEmit` clean across the workspace; common +**1663** (1625 + 13 from slice 2 + 25 from slice 4a); editor unit **67** (59 + 4 + 4); +`pnpm run test:scripts` **156 + 1 skip**; mcp **219**; editor and export `next build` +green, with `ƒ /api/view/[name]` in the route table and no zod in any client chunk. + +Full editor suite on `ae2fa5a9`: <<E2E-FINAL>> +Export suite: <<E2E-FINAL>> + +**Record corrections made while checking the two records below against the branches** +(2026-09-23; where a record and the code disagreed, the code won): slice 2 is five commits, +not four — the review fix `c205b270` came after the record was written, and it moved the +`widgetActionable` row mapping out of `views.ts`, so the replacement is 176 lines + an 84-line +test at the tip, not 185 + 66; editor unit is 63 at that tip, not 61. Slice 4a's table did not +list its own record (`5b43dc8d`) or the review fix (`81deae69`), and the review fix added two +settingsDocs wiring tests, so common on that tip is 1650, not 1648. Both records said +"unmerged"; both are merged. + +## Next release — slice 3 and slice 4b + +Not started. The facts below were checked against `ae2fa5a9` on 2026-09-23. + +**Slice 3 — one drawing per noun.** + +- *Channel row.* Two `ChannelsTable`s — `editor/app/channels/components/ChannelsTable.tsx` + (966 lines, the rack) and `editor/app/components/dashboard/ChannelsTable.tsx` (192) — plus + `editor/app/components/channelWork/ChannelWorkTable.tsx` (178). One table with a column set. +- *Job in flight.* `jobs/components/RunningJobsList.tsx` (158), `jobs/components/LaneStrip.tsx` + (88), `operations/components/InFlightList.tsx` (85) and the widget's own + `ActiveJobsStrip`/`JobRow` (`widget/components/MonitorWidget.tsx:989,1033`) onto the + `JobRowView` renderer with a `variant`. **`InFlightList` does not draw `JobRowView` today**: + it draws `AutoQueueKindStatus.runner.inFlight` (`InFlightList.tsx:16,20`), so it needs a + mapping to the row, not just a re-skin. +- *Channel pipeline.* The status logic in the nine files under + `channels/[slug]/components/stages/` (eight `*Stage.tsx` cards plus `OperationWork.tsx`); + each stage keeps its body. `one-core.md` said eight. +- *Video page.* `channels/[slug]/videos/[id]/components/VideoPanel.tsx` is **1,839 lines** + (`one-core.md` said 1,586), with download, transcode and transcription still inline; + `videoOperationPanels.ts` (`…/videos/[id]/lib/`) is the enumeration to split along. + +**Slice 4b — the rest of the schemas.** `site.json`; channel `config.json`, with its mutable +sync state (`lastSyncedAt`, `lastFullSweepAt`, …) declared as such and the file NOT split; +the sidecar `X.ts` / `X-server.ts` pairs → one `sidecar(name, schema)` each (read, atomic +write, mtime freshness, the `transcript.<x>.<y>` naming guard). Slice 4a's pattern is the +template: `settingsField(coerce)` over the existing sanitizer, no `.default()`, no +`.passthrough()`, zod kept out of `"use client"` import graphs. + +**Deferred follow-ups, each checked still open on `ae2fa5a9`:** + +- The backfill lane form's hint text still says *"836 videos still have media on disk and + ~76,270 would need re-downloading"* (`operations/components/settings/LaneSettingsForm.tsx:101-102`); + the page measured 679 reachable / 74,046 no media at gate B. A stale measured figure in + copy — fix the copy or derive it, in a code slice. +- `plans/tools/phase1-numbers.ts` sums `missingInput` straight from the snapshot + (`COUNT_FIELDS`, `:57-65`) and never filters `handling: "youtube"`, so its `missingInput` + is the whole bucket, not what a backfill pass could reach. +- `usePolledPayload`'s hang recovery is not unit-tested: the editor unit suite has no React + harness, so `lib/usePolledPayload.test.ts` pins `pollTimeoutMs` only (one test). +- The nested settings blocks (`DigestSettings`, `DiarizationSettings`, …) are each one + sanitizer-backed `settingsField`, not zod objects; their docs are the `*_FIELD_DOCS` + records. Converting them is optional work, not a bug. +- `editor/scripts/measure-nav.mjs:64-69` still requests the eight OLD API paths. They answer + through the rewrites, so it measures rewrite + view; say so if its numbers are compared + with an older run. +- Accepted, not owed: nothing prunes stale per-app entries from the `transcriptionApps` + shadow any more (slice 4a, behaviour changes). + ## Slice 2, as shipped — one polling route (2026-09-23) -Branch `one-core/phase-3-s2` off `54cf1b31`, four commits, not merged: +Branch `one-core/phase-3-s2` off `54cf1b31`, five commits, merged to `main` as `8d6e84f6` +(2026-09-23). *Checked against the branch 2026-09-23: the table, the line counts and the +editor-unit count were corrected for the review-fix commit `c205b270`.* | commit | what | |---|---| | `5397f83c` | `common/views/{cleanable,widgetActionable}.ts` + tests; the two widget routes call them; seven type importers repointed off `api/widget/*/route` | | `074f09a2` | `common/views/names.ts` (`VIEW_NAMES`, `ViewName`, `VIEW_CONTRACT`) + test; `editor/app/api/view/{[name]/route.ts,views.ts,pulseView.ts,views.test.ts}`; eight route files deleted; eight `rewrites()`; `e2e/view-route.spec.ts` | | `edf56370` | `usePolledPayload` `git mv` to `editor/app/lib/`; JobsTable, useOperationsStatus, SyncConsole folded onto it; every client poll URL is `/api/view/<name>` | -| (this commit) | `plans/tools/phase3-view-numbers.ts`, two stale comments, this record | +| `4288009b` | `plans/tools/phase3-view-numbers.ts`, two stale comments, this record | +| `c205b270` | review fixes — deviation 7 below | **One route, eight rewrites, no redirect.** `/api/view/[name]` is `force-dynamic`, checks the name against `VIEW_NAMES` before any handler runs (unknown ⇒ 404), and dispatches into @@ -504,7 +597,7 @@ Gates: |---|---| | `pnpm -r exec tsc --noEmit` | clean after every commit | | common tests | **1638/1638** (was 1625; +13: cleanable 3, widgetActionable 6, names 4) | -| editor unit (`tsx --test "app/**/*.test.ts"`) | **61/61** (was 59; +2: pulse textual guard, cleanable assignability) | +| editor unit (`tsx --test "app/**/*.test.ts"`) | **61/61** at `4288009b` (was 59; +2: pulse textual guard, cleanable assignability); **63** after `c205b270` (+1 dispatcher ban, +1 `pollTimeoutMs`) | | `pnpm run test:scripts` | 156 pass / 1 skip / 0 fail | | `next build` (editor) | clean; `├ ƒ /api/view/[name]` (dynamic), `├ ƒ /api/widget/presets` kept | | e2e subset, 20 specs (`pulse`, `auto-refresh`, `dashboard`, `dashboard-paths`, `widget`, `jobs`, `jobs-active-order`, `jobs-channel`, `workers`, `worker-remote`, `auto-queue`, `lane-runner`, `scheduler`, `ops-api`, `disk-space`, `perf-budget`, `backfill`, `channel-storage`, `channel-rename`, `view-route`) | **174 passed, 0 failed, exit 0**, 8.0 min, one run, nothing re-run | @@ -517,8 +610,9 @@ main, route bodies copied into a temporary variant of the script, since the view exist yet) vs after (the committed script, importing the views): **diff empty**, 4,574 bytes each. -Line counts: the eight deleted routes were 190 lines; their replacement is 185 (route 41, -`views.ts` 87, `pulseView.ts` 57) + a 66-line test. `common/views/` gains 144 non-test +Line counts: the eight deleted routes were 190 lines; their replacement is 176 at the branch +tip (route 41, `views.ts` 78, `pulseView.ts` 57) + an 84-line test — 185 + 66 at `074f09a2`, +before `c205b270` moved the row mapping out of `views.ts` and added the dispatcher ban. `common/views/` gains 144 non-test lines (`names` 55, `cleanable` 42, `widgetActionable` 47) and 129 test lines. `editor/app` over commits 1–3, `--no-renames`: +421 / −345. @@ -556,7 +650,7 @@ Deviations: never-nulled `data` are unchanged. 6. **Two comments named deleted routes**: `PipelineBand.tsx:140` and the `widget/lib/syncInputs.ts` header now say the old path is rewritten to `/api/view/…`. -7. **Review fixes (one commit after `4288009b`)**: the hook timeout above; the +7. **Review fixes (`c205b270`, one commit after `4288009b`)**: the hook timeout above; the `CONSTRUCTORS` text ban now also covers `api/view/[name]/route.ts`, so a hoisted constructor in the dispatcher fails a test; `view-route.spec.ts` also strips `disk.freeBytes` from the activeJobs comparison (a live statfs, equal only while the @@ -580,8 +674,10 @@ the 20-spec subset above. ## Slice 4a, as shipped — one settings schema (2026-09-23) -Branch `one-core/phase-3-s4a` off `main` `54cf1b31`, unmerged. Commits (shas after the -trailer rewrite; this record is `plans:` commit 6 on top): +Branch `one-core/phase-3-s4a` off `main` `54cf1b31`, seven commits; `main` (slice 2) merged in +as `7035316c`, then merged to `main` as `ae2fa5a9` (2026-09-23). Shas are after the trailer +rewrite. *Checked against the branch 2026-09-23: the last two rows and the post-review common +count were added.* | sha | what | |---|---| @@ -590,6 +686,8 @@ trailer rewrite; this record is `plans:` commit 6 on top): | `f1abe024` | `lib/settingsSchema.ts`: `siteSettingsSchema` (31 fields, `.describe()` on each), `SiteSettings = z.infer`, `defaults()` = `defaultSiteSettings()` = `parse({})`; `lib/settings.ts` reduced to I/O (1,783 → 250 lines) and `export *`s the schema module; `settingsSchema.test.ts` | | `85478527` | `editor/app/settings/saveSettings.ts` + unit test; 19 call sites in 11 files converted to patches; `writeSettings` is imported by one editor file | | `0316e988` | `common/bin/settings-example.ts` (+`--check`), `lib/settingsDocs.ts`, generated `settings.json.example` + `SETTINGS.md`, `settingsDocs.test.ts`; SETUP.md points at SETTINGS.md | +| `5b43dc8d` | this record; changelog entry | +| `81deae69` | review fixes — every nested key documented (`lib/fieldDocs.ts`, 24 `*_FIELD_DOCS` records), see below | **What moved.** Every type, constant, clamp and block sanitizer that was in `lib/settings.ts` is in `lib/settingsSchema.ts` and re-exported, so no importer changed. `getSettings` = @@ -659,7 +757,7 @@ differently from the old one (no legacy `whisper-cli`/`firefox` keys) — by des `parallelTranscriptions: 1`) parse to byte-identical settings through main and through the schema (included in the numbers above). The entrypoint does not read the example. -**Review fix (one commit after commit 6).** SETTINGS.md now documents every +**Review fix (`81deae69`, one commit after the record).** SETTINGS.md now documents every NESTED key, not only the 31 top-level ones: each block type carries a `<TYPE>_FIELD_DOCS: FieldDocs<Type>` record beside it (`lib/fieldDocs.ts`; the mapped type requires one entry per key, optional keys and every union member's keys included, so an @@ -678,7 +776,7 @@ copied example pins every default, `held` included. **Gates.** tsc (`pnpm -r --workspace-concurrency=1 exec tsc --noEmit`; the parallel `-r` form was OOM-killed, exit 137) clean after every commit. common **1625 → 1648** (+20 schema, +3 -docs); `test:scripts` 156 pass + 1 skip of 157 (unchanged); mcp 219/219; editor unit **59 → 63**; +docs) at `5b43dc8d`, **1650** after `81deae69` (+2 docs wiring tests); `test:scripts` 156 pass + 1 skip of 157 (unchanged); mcp 219/219; editor unit **59 → 63**; `next build` editor and export clean. **e2e** (from the worktree root, detached, ports 3311/3310): auto-queue, backfill, digest, diarization, attribution, scheduler, cadence-ui, storage-locations, channel-storage, workers,