commit 05e0cba726da093a9883b1e49a722a89b29ad99c
parent 2a3042656300eda15f8fdd46671460bc343710c9
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Wed, 30 Sep 2026 01:15:02 -0400
plans: releases 14 and 15 merged — release 15's Rollout (the homepage live from 2ad584c0, the runbook, the order, what the reviews left for the operator); the two SS decisions ruled; STATE; the implementer rules' corpus link is ln -sT
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat:
3 files changed, 71 insertions(+), 4 deletions(-)
diff --git a/plans/STATE.md b/plans/STATE.md
@@ -3,6 +3,26 @@
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.
+**Now (2026-09-30): releases 14 and 15 are merged to `main` `b154a9d9`; the homepage is in
+production; the editor, umtool, the index and stats, the hub and the sites are owed.** The records
+are [`release-14.md`](release-14.md) (HS hidden sites, S1 a clear screen until the first Search, CF
+the chart's Other band — each reviewed SHIP) and [`release-15.md`](release-15.md) (IG the index
+build's hold, UT umtool's build trace, DS a stalled drive, SS the editor's site scope — each
+reviewed SHIP). The operator's runbook is `~/reports/release-15/RUNBOOK.html`.
+- **Live (2026-09-30):** `https://archilyzer.pages.dev` from `main` `bab894db`, source mirror
+ `880936b5`, every live check OK. Nothing else of this round is live: :3001 still serves the
+ pre-release build; the hub and the six sites are at their last deploys.
+- **Owed, in the runbook's order:** editor rebuild + restart; umtool rebuild then `test:scripts`
+ then restart; index + stats with every drive mounted (`Held: 0`); the hub; the six sites; then
+ this file and memory.
+- **Candidate, awaiting the operator's word:** history and diffs of the source on the homepage
+ under `/source/git/` — stagit at homepage build (research in the job's scratch: a static
+ renderer inside the homepage is the alternative; Sendforge is out: it needs JS for history and
+ cannot live under a sub-path).
+- **Follow-ups the reviews named:** the editor's and export's build traces list dot-directories
+ (cosmetic while `standalone` is off); `REQUIRED_TOKENS` lacks `--chart-other` (the e2e pins it);
+ `export`'s `WorkspaceView` `splitOn` has a one-paint flash from a localStorage restore.
+
**Now (2026-09-28, night): the stats cache key fix — built, reviewed (SHIP AFTER FIXES, then SHIP
on re-review; every touch-up done), not merged.** The branch is `fix/stats-cache-key`, and [`stats-cache-key.md`](stats-cache-key.md)
holds the record, the review and the rollout. FACTS has "The stats cache key".
diff --git a/plans/release-15.md b/plans/release-15.md
@@ -1064,8 +1064,8 @@ it polls until the value is right and passes.
| Choosing on a `?site=` link's page drops the param and stores the choice. **Ruled at review: it stays.** | Keep the param and store nothing, as a link's page is "just that page"; the picker and the page would then disagree |
| On a site's pages, the cookie is written before the push. **Ruled at review: the round trip is accepted.** | Push first and write after: faster, but a page opened right after the URL moves could read the old value, and a navigation started while an action is pending discards the action's re-render |
| The migration writes without an optimistic update, so its one flash lasts until the write's re-render | Update at once: a shorter flash, but a state change during hydration (see above) |
-| A new channel starts checked on the active site as the picker resolves it, so an editor with one site and nothing stored starts it checked on that site | Only a stored choice or a `?site=` link; the lone site would then need a click |
-| The new-channel pre-check is the form's initial state, so a pick made in another tab while the form is open does not change its boxes | Follow the active site while the form is untouched |
+| A new channel starts checked on the active site as the picker resolves it, so an editor with one site and nothing stored starts it checked on that site. **Ruled at re-review: it stays.** | Only a stored choice or a `?site=` link; the lone site would then need a click |
+| The new-channel pre-check is the form's initial state, so a pick made in another tab while the form is open does not change its boxes. **Ruled at re-review: it stays.** | Follow the active site while the form is untouched |
#### Review
@@ -1089,3 +1089,48 @@ editor's built bundle, so all of it takes effect only after the editor is rebuil
After that, each browser's first visit migrates its localStorage selection once.
## Rollout
+
+Release 15 is slices IG (`r15/index-hold`, merged `ccf90892`), UT (`r15/umtool-trace`, `07c991be`),
+DS (`r15/drive-stall`, `ef4f1d7c`) and SS (`r15/site-scope`, `b154a9d9`). It rolls out together
+with release 14 (HS `69e058d6`, S1 `721ed0eb`, CF `bab894db`) and the stats recount. The operator's
+runbook is `~/reports/release-15/RUNBOOK.html`, generated by `make-runbook.py` beside it, with the
+scripts in `~/reports/release-15/scripts/` (`r15-*.sh`, derived from release 12's). Every command is
+typed from the primary checkout's root.
+
+**Done before this record (2026-09-30).** The homepage is in production: `main` `bab894db`,
+source `880936b5` (2,509 files, audit clean against the denylist), deployment `2bbb46d0`; the live
+checks all passed (clone HEAD = manifest, tarball hashes equal, 0 user/host matches over 1,834
+revisions; Gumroad link, the chart's Other band, `homepage-summary.json` version 6 with 77,547
+transcripts). A live check run within five minutes of a deploy can fail its clone-HEAD line:
+`info/refs` is served with `max-age=300`; wait and run it again.
+
+**The order.**
+1. Preconditions: the primary clean at or after `b154a9d9`; `pnpm -s archilyzer source publish
+ --check` passes; `/jobs` shows nothing running; `/storage` shows every location mounted and no
+ channel `inconsistent` or `in-transition` (the index build now HOLDS those: IG).
+2. The editor: capped build, restart (the start script sets `UV_THREADPOOL_SIZE=16`), smoke. Then
+ umtool: capped rebuild in the primary FIRST, then `pnpm run test:scripts` — its post-build trace
+ check skips a build older than the config and that run is the only proof on the real fixture (UT)
+ — then restart umtool the way it was last started.
+3. Index, then stats, with every drive mounted. The `Diff:` line must end `Held: 0`; thousands
+ removed means a drive was missing. `ARCHILYZER_INDEX_ALLOW_HELD=1` is the override, on the
+ command line for a CLI run or in the editor's environment (and a restart) for the job.
+4. The homepage again only if the source mirror should carry the final `main` (it was published
+ from `bab894db`).
+5. The hub, then the six sites, each build → preview → production, with the checks the release 14
+ record lists (the name and the marked link at 360 px; S1's three; HS's member count = public
+ LISTED sites; `homepage-summary.json` version 6).
+6. Editor live checks after the restart: pick a site and walk Dashboard → Channels → Jobs →
+ Settings — the select never reads "All sites" (the first visit may flash once while the old
+ localStorage choice migrates to the cookie: SS); `/storage` shows each location's detector
+ (`counters` for a mounted drive; `stat` is the fallback) (DS).
+
+**Left for the operator, from the reviews.**
+- Does the external drive spin down when idle? A spin-up longer than 3 s completes nothing, so the
+ watchdog marks the drive "not answering" for 15–30 s after idle and job starts on it are refused
+ in that window (DS, L6).
+- A root typed by hand on a channel's Storage panel is capped at four calls in flight but is never
+ marked; naming it as a location on `/storage` gives it the full treatment (DS).
+- The editor's and the export's own build traces list dot-directories (`.env`, `.claude`,
+ `test-transcripts/.jobs`; `.export-index`) — cosmetic while `standalone` output is off; a later
+ slice (UT review).
diff --git a/plans/tools/implementer-rules.md b/plans/tools/implementer-rules.md
@@ -82,10 +82,12 @@ the Next.js reference for this version.
the primary, and the build was OOM-killed (FACTS, "A path joined from `process.cwd()` …"). From
the worktree root:
```
- ln -s <primary>/transcripts transcripts && timeout -s KILL 240 systemd-run --user --scope -q -p MemoryMax=5G -p MemorySwapMax=0 pnpm --filter umtool exec next build; rm transcripts
+ ln -sT <primary>/transcripts transcripts && timeout -s KILL 240 systemd-run --user --scope -q -p MemoryMax=5G -p MemorySwapMax=0 pnpm --filter umtool exec next build; rm transcripts
```
It is for the BUILD only. Always remove the link, never commit it, and never run an app, an index
- or a fixture builder through it. It should take about 25 s at under 1 GB, the same as without
+ or a fixture builder through it. `-T` matters: a worktree that already has a `transcripts/`
+ directory (an old `index.mdb`) would otherwise get `transcripts/transcripts`, and the build
+ would run without the corpus and pass for the wrong reason (slice UT, release 15). It should take about 25 s at under 1 GB, the same as without
the corpus.
- The slice's e2e spec list (in the prompt), detached and waited on as above.
- The numbers tool the prompt names, diff-empty (or "none", stated).