commit 253305dfafb76663c43502d8f9780d96319491be
parent 35d1a420b0aca46a79269c44dd3aafd52c47a8a2
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Mon, 28 Sep 2026 13:41:14 -0400
plans: slice W1's fix round — the queued-cancel symptom corrected, the meta chain called defensive, review L2/L3 and the nits as found-and-left, the stray common/node_modules
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
| M | plans/release-13.md | | | 72 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- |
1 file changed, 69 insertions(+), 3 deletions(-)
diff --git a/plans/release-13.md b/plans/release-13.md
@@ -144,9 +144,12 @@ job's `tmp/overnight`.
and nothing is written. **`shutdownCancel.ts` is outside the prompt's Owns list** (no other slice
owns it); the change is three lines. The call is optional (`?.()`), because under `next dev` the
registry on `globalThis` can predate the method.
-- **Meta writes are chained** (`metaWriter`). The enqueue's write and the terminal one used to be
- two unordered `writeFile`s, so a cancel landing within milliseconds could leave `queued` on disk,
- or a shorter JSON over a longer one's tail.
+- **Meta writes are chained** (`metaWriter`, over `serialWriter` since the fix round). This is
+ **defensive, not a fix for an observed race**:
+ - `writeJobMeta` snapshots the record before its first `await`, so two writes are issued in
+ order, and only the fs threadpool could complete them out of order;
+ - the review's probe cancelled 300 jobs in the same tick as their enqueue, and all 300 ended
+ `cancelled` with or without the chain.
- **Tests.** `registry.test.ts` +1: `onCancel` sees the record already `cancelled`, with `endedAt`.
`streamCommand.test.ts` (new, 3): a function job and a command job queued behind a holder,
cancelled, end `cancelled` on disk with no `startedAt`; after `beginShutdown()` the sidecar stays
@@ -237,5 +240,68 @@ is W2's, so the gate-list line is in the report for the parent to join.
`deploy-export`, `build-index`, `build-stats`, `archive-*`).
- **Run A's OOM:** the machine has 15 GB, and the live parakeet worker plus several worktrees'
servers crowd it. A full-suite gate tonight may meet the same killer.
+- **`shuttingDown` is one-way and process-wide** (review L2; the gaps predate this slice):
+ - Once `beginShutdown()` has run, no queued cancel writes a sidecar. That includes an operator's,
+ or a remote worker requester's, landing during Next's graceful close (`server.close` waits for
+ in-flight requests). This is the old behaviour.
+ - A job enqueued in that window is never reaped. If it starts, its child can outlive the exit,
+ and its meta stays `running`, which the boot pass leaves alone.
+ - The flag is the natural hook for a follow-up in which `enqueue` refuses, or at least does not
+ start, a job once `shuttingDown` is set. It was not considered for this slice (the review's
+ question), and it is not done.
+- **A job RUNNING at a graceful restart ends `cancelled` on disk, with no `cancelReason`** (review
+ L3). Its `.finally` still writes while Next closes, so on `/jobs` a restart reads like an
+ operator's cancel. This is unchanged by this slice, whose "nothing is written" is about queued
+ jobs only.
+- **`onSettled` does not fire for a lane a newer launch replaced** (review nit). Build homepage
+ followed at once by Deploy homepage: the build ends unseen, and "built <when>" stays stale until
+ AutoRefresh (5 s by default) or a reload. The prop's comment says so.
+- **The e2e harness reset now writes `cancelled` metas** (review nit). `invalidate-cache` cancels
+ queued jobs, which write their sidecar asynchronously during `resetData`'s `rm`. It is the same
+ class as a running job's terminal write, and `rm`'s `maxRetries` already absorbs it.
+
+### Slice W1, fix round (2026-09-28)
+
+Review: **SHIP AFTER FIXES** (`w1-review.md`). One should-fix, L1 taken, L2, L3 and the two nits
+recorded above. `main` was not merged.
+
+- **Should-fix:** the item-5 changelog bullet claimed `/jobs` listed an evicted, cancelled job as
+ queued again. It never did: such a job opened no log, so once evicted it is not listed, and a
+ non-terminal meta reads "archived".
+ - The real consequences were the boot pass re-queueing it, and `/api/media/fetch-window/<id>`
+ (MCP `fetch_clip`) reporting a cancelled fetch as still `queued`.
+ - The bullet now says that. So do this record's item 5 and the `sites-homepage.spec` comment.
+ - `cd0781f5`'s commit message repeats the old claim, and it is left as it is.
+- **L1:** the chain is `serialWriter(write)`, exported for its test. It is
+ `last = last.then(write, write)` plus a no-op `last.catch`:
+ - a writer that rejects no longer stalls every later write;
+ - the last write rejecting is not an unhandled rejection.
+ - `writeJobMeta` never rejects, so this is defence only.
+ - `streamCommand.test.ts` +1: four writes, the first slow and the second and fourth rejecting,
+ must run one at a time, in order, with no unhandled rejection.
+ - The test fails on each of three weaker variants: `.then(write)` stops after write 2; without
+ the catch, the runner reports an `unhandledRejection`; unchained writes interleave.
+- **Found while re-gating: `common/node_modules` had been replaced** at 13:25:02, after the
+ hand-back and not by this slice, with a standalone (non-workspace) install carrying
+ `@types/react` 19.3.0.
+ - `tsc` then failed in `export` (`PlayerProvider.tsx:1186`: two unrelated `Ref` types).
+ - The stray tree was moved to `$T/w1-stray-common-node_modules-1325` (530 MB, not deleted), and
+ `pnpm install --frozen-lockfile --offline` relinked the workspace ("Already up to date",
+ 3.4 s).
+ - The sibling worktrees' `common/node_modules` are workspace symlinks, as this one is again.
+
+| sha | what |
+|---|---|
+| `60ac51a7` | `changelog:` the item-5 bullet, the record's item 5 and the spec comment say what the stale `queued` actually did |
+| `c3afe68d` | `jobs:` `serialWriter`: `then(write, write)` plus a no-op catch; `streamCommand.test.ts` +1 |
+| _this_ | `plans:` this fix round; the chain described as defensive; L2, L3 and the nits recorded |
+
+**Gates** (`w1-fix-gates2.log`, on the relinked tree):
+- tsc clean.
+- **common 2,120/2,120** (+1, the serialWriter test) and **editor unit 85/85**.
+- The first attempt (`w1-fix-gates.log`) ran on the stray tree: tsc failed. Its common run was
+ stopped after the tree moved out from under it, and it has no result.
+- No e2e and no build: the changed spec's diff is a comment, and the rest is common code under unit
+ tests, plus docs.
## Rollout