commit 2a2d6e11bba8e328eb4b1f84c555a832ad5303cb
parent 51444d2cf7bb7e0e63ba73087788e52f9fa6202a
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Sat, 26 Sep 2026 04:20:56 -0400
plans: release 10 slice L1 re-read — a subs failure never fails an archive (C2's settled rule restored), the NO_ARCHIVES_IN_SCOPE draft with its front-page link, two new lows (/ask on an empty hub; the missing live chat on the chip)
Gates on 51444d2c:
- tsc clean.
- Unit tests: common 1,923, editor unit 79.
- Build: export hub ok.
- e2e: hub 24, export full 204, 2origin 3 (links in place, no swap).
- The primary's eight export/public files were byte-identical throughout.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
| M | plans/release-10.md | | | 74 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ |
1 file changed, 62 insertions(+), 12 deletions(-)
diff --git a/plans/release-10.md b/plans/release-10.md
@@ -278,7 +278,7 @@ alphabetical (below).
| `90ec10a1` | `hub:` `useHubSites` / `useFederatedSites`; `ArchiveShelf`, `HubHome`, `HubStats`, `AskHub` read it; `useHubSummary` `settled`; e2e for order + colour (items 3–4) |
| `21be8700` | `hub: /ask` honours the scope chips; e2e (item 2) |
| `86d686fb` | `export: [Unreleased]` (a new section above `[0.9.0]`) |
-| _this_ | `plans:` this record |
+| `a9d31063` | `plans:` this record |
**Gates**
- **tsc:** clean before every code commit. Five runs, 37–91 s (`l1-tsc-1..5.log`). `cf5455c0` was
@@ -357,9 +357,11 @@ item-5 harness fix is not in the public changelog.
- **The line.** `AskChat` shows one line in the composer when the hub has archives and every one
is off: `NO_ARCHIVES_IN_SCOPE`, `role="status"`, `data-testid="ask-blocked"`. It replaces the
placeholder and the key hint. The box and the Ask button are disabled.
- - **The copy** is a single exported constant in `export/app/ask/hubScopeCopy.ts`, draft text "No
- archives selected. Turn one on above to ask.", for the operator. **Copy note:** `/ask` shows no
- chips, since they are on the hub's front page, so "above" does not match the page yet.
+ - **The copy** is a single exported constant in `export/app/ask/hubScopeCopy.ts`, for the
+ operator. The draft is now "No archives selected. Choose some on the [hub's front page] to ask."
+ (re-read, `0fc63ed7`). The first draft said "Turn one on above", but `/ask` shows no chips.
+ The [bracketed] words render as a link to `/`, where the chips are; dropping the brackets
+ drops the link.
- **A hub with no archives at all** now reads "Loading transcripts…" on `/ask`, instead of being
ready over nothing. `ask.spec` accepts either.
2. **Should-fix: the compose scripts wrote through the worktree links** (`1203f4a6`).
@@ -379,24 +381,26 @@ item-5 harness fix is not in the public changelog.
- **Proof:** below.
3. **Nit** (`609a7fe1`): `useHubSummary` runs with `networkMode: "always"`, so a first mount
after an `offline` event settles as "no summary" instead of pausing.
-4. **Nit: the subs query** (`78e837f1`, replacing `cf5455c0`'s `retry: false`).
+4. **Nit: the subs query** (`78e837f1`, replacing `cf5455c0`'s `retry: false`; its failure rule
+ was corrected in the re-read, `d0fa13ae`).
- **A 404** resolves to an empty manifest at once, the way posts does. It is one request.
- - **Any other error** keeps one retry (explicit on this query) and then fails the archive like a
- failed manifest or page: the chip reads failed with Retry, and the "N of M archives answered"
- line names it.
+ - **Any other error** keeps one retry (explicit on this query). If it still errors, the query
+ counts as SETTLED: the archive is ready, its videos are searched, and only its live chat is
+ missing. This is C2's rule. `78e837f1` had instead made such an archive `failed`, which the
+ re-read reverted (below).
- **Why a 404 is readable.** A member's `/subs/*` carries CORS on 404s too: checked live,
`https://jeralyzer.pages.dev/subs/<missing>.json` → `404` + `access-control-allow-origin: *`.
- So a missing file reads as a 404, not as a network error. An added archive on a host that
- sends no CORS header on a 404 would read as failed.
+ So a missing file reads as a 404, not as a network error. `serve`, which self-hosted docker
+ archives use, sends a 404 with no CORS header, and that is the case the settled rule covers.
| sha | what |
|---|---|
-| `78e837f1` | `hub:` subs: a 404 is an empty manifest; a real error is retried once, then fails its archive with Retry; e2e (finding 4) |
+| `78e837f1` | `hub:` subs: a 404 is an empty manifest; a real error is retried once, then failed its archive (reverted by `d0fa13ae`); e2e (finding 4) |
| `efe6e48f` | `hub: /ask` with every archive off is not ready and says why (`NO_ARCHIVES_IN_SCOPE`); an empty scope is never ready when not progressive; e2e (finding 1) |
| `609a7fe1` | `hub: useHubSummary` `networkMode: "always"` (finding 3) |
| `1203f4a6` | `common:` `_publicFile.ts`; compose-hub and compose-site never write through a link; 6 unit tests (finding 2) |
| `323c878f` | `export: [Unreleased]` — the two reader-visible fixes |
-| _this_ | `plans:` these review fixes |
+| `5304ce2d` | `plans:` these review fixes |
**Gates on `323c878f`**
- **tsc:** clean before every code commit (`l1-tsc-6..8`). `78e837f1` was staged as a subset of the
@@ -461,6 +465,52 @@ item-5 harness fix is not in the public changelog.
The seed (per-path links from the primary) stays as it is. A worktree run now replaces a link with
its own file, and the next seed relinks it.
+**Re-read of the fixes** (`l1-review.md`, "## Re-read of fixes"; SHIP AFTER FIXES).
+- **R1, must-fix: a subs failure must never fail an archive** (`d0fa13ae`). After `78e837f1`, a
+ non-404 subs error, after its retry, made the archive `failed`. Its already-loaded videos then left
+ the search and `/ask`, and the line said it "did not answer". This was reachable on a self-hosted
+ archive with no subs manifest, where `serve` sends a 404 without CORS. C2's rule is restored: a
+ subs query that still errors after its retry counts as settled, so the archive is `ready` without
+ its live chat. The 404 → empty manifest and the one retry are kept. The e2e is inverted: a 500
+ gives 2 subs requests, the chip reads `ready` with no Retry, Origin B's result is present, and
+ there is no status line. The changelog sentence now says what a reader sees: the archive is
+ searched without its live chat, and its chip reads ready.
+- **The copy** (`0fc63ed7`). The new draft, with its front-page link, is described under finding 1
+ above. `copyWithLink` / `copyText` split and flatten the one constant. The e2e takes the link text
+ from the constant and checks that it points to `/`.
+- **R2** (`ownDir` is safe) and **R4** (the non-progressive rule is confined to `/ask`) were verified
+ by the re-read. No change.
+
+| sha | what |
+|---|---|
+| `d0fa13ae` | `hub:` a subs manifest that still fails after its retry never fails its archive (C2's settled rule); e2e inverted; changelog sentence |
+| `0fc63ed7` | `hub: NO_ARCHIVES_IN_SCOPE` draft "No archives selected. Choose some on the [hub's front page] to ask.", the phrase a link to `/` |
+| _this_ | `plans:` this re-read record |
+
+**Gates on `0fc63ed7`** (`l1-fix2.log`)
+- **tsc:** clean (`l1-tsc-9`, on this tree; `d0fa13ae` is a subset of it).
+- **Unit tests:** common **1,923**, editor unit **79**.
+- **Build:** export hub ok (26 s), `out/ask/index.html` present.
+- **e2e:**
+ - `e2e:hub` **24 passed**, 51.1 s;
+ - export full **204 passed**, 6.7 min, `sw.js` a link at the start;
+ - `e2e:2origin` (`TWO_ORIGIN_REBUILD=1`, the seven composed entries links in place, no swap)
+ **3 passed**, 36.3 s.
+- **The primary's eight `export/public` files** kept the size, mtime and md5 in the table above
+ through all three runs (`l1-fix2-primary-before.txt` vs `-after.txt`, `diff` empty). The worktree
+ again held its own `hub-sites.json` (2 B), `corpus.json`, `llms.txt`, `robots.txt` and `_headers`
+ after 2origin.
+
+**Found and left (new lows, both need copy):**
+- **`/ask` waits forever on a hub with no archives.** When `hub-sites.json` is `[]` (a fresh
+ self-hosted hub) or failed (`loadBuiltins` never retries), and the reader has added none, `/ask`
+ reads "Loading transcripts…" forever. The fix is a "built-ins loaded" flag from `siteRegistry.ts`
+ plus a blocked line for "this hub has no archives", whose copy goes to the operator. The production
+ hub (five members) never reaches this state online.
+- **Show a member's missing live chat.** A subs manifest that settled in error leaves its archive
+ `ready` with no sign that its live chat is missing. A chip note with a subs-only Retry would show
+ it.
+
## Rollout
Nothing is rolled out. The live :3001 editor still runs `0213f6c8` (the pre-brand build); the five