chore(541): fast-forward the shared checkout at session end (H13)
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 10s
PR Gates / Docs update reminder (pull_request) Successful in 14s
PR Gates / decisions lifecycle (pull_request) Successful in 17s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 1m22s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m23s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 7m34s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 15m8s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 19m55s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 10s
PR Gates / Docs update reminder (pull_request) Successful in 14s
PR Gates / decisions lifecycle (pull_request) Successful in 17s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 1m22s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m23s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 7m34s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 15m8s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 19m55s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
A session was handed docs/handoffs/chicorytv-issue-queue.md pasted out of /Users/timothy/ersatztv while that tree was 81 commits behind, so it still described the queue protocol #520 retired the day before (read tracker command was ever run against that tree, so every existing "never read its HEAD" guard was irrelevant: a stale checkout serves stale FILES, and docs are what a kickoff depends on. Nothing broke only because selection went through scripts/select-queue.sh. The lore bullet on that tree already prescribed the shape of the fix for its earlier failure modes — "a design flaw, not a discipline failure; a check does not stay true" — so this removes the stale condition instead of adding another check. scripts/refresh-shared-checkout.sh fast-forwards the tree to origin/main and reinstalls web/node_modules when the lockfile moved. It is deliberately timid: it refuses and changes nothing when the tree is not on main, is dirty, is ahead, or is mid-rebase/merge, and it never switches branches, stashes or discards. A NO-OP is a normal outcome. Uses npm ci rather than npm install — the first version used install, which rewrote package-lock.json and left the tree dirty, i.e. the exact state the next run refuses on, so it would have disabled itself after one use. Asserts the tree is clean at exit. refs #541
This commit is contained in:
@@ -133,6 +133,7 @@ in-file entries.
|
||||
- [2026-07-21 — External channel-logo URLs are downloaded and cached at save time; the render path never fetches a logo (#525)](#2026-07-21--external-channel-logo-urls-are-downloaded-and-cached-at-save-time-the-render-path-never-fetches-a-logo-525)
|
||||
- [2026-07-21 — Check the worked issue before the decision corpus; a closed tracker's comments need no retrofit (#524)](#2026-07-21--check-the-worked-issue-before-the-decision-corpus-a-closed-trackers-comments-need-no-retrofit-524)
|
||||
- [2026-07-21 — Work-ahead slots are claimed atomically by the caller, released by the transcode it hands them to (#536)](#2026-07-21--work-ahead-slots-are-claimed-atomically-by-the-caller-released-by-the-transcode-it-hands-them-to-536)
|
||||
- [2026-07-21 — Session end fast-forwards the shared checkout; a stale tree serves stale FILES (#541)](#2026-07-21--session-end-fast-forwards-the-shared-checkout-a-stale-tree-serves-stale-files-541)
|
||||
|
||||
---
|
||||
|
||||
@@ -3377,3 +3378,33 @@ pre-fix shape, 15 912 of 20 000 rounds over-claimed.
|
||||
**Why the return-value plumbing rather than enqueuing inside the shifter.** `PlayoutTimeShifter` lives in `ErsatzTV.Infrastructure`, which cannot reference the `RefreshChannelData` request type (an `ErsatzTV.Application` type), so the enqueue must happen in the Application-layer handler. `TimeShift` therefore returns `Option<string>` — `Some(channelNumber)` only when a non-zero offset was actually persisted, `None` on every early-out (wrong mode, active-and-unforced, empty playout) and on a zero-offset re-tune — so a guide rebuild fires exactly once per real thaw, never on a no-op. The zero-offset `None` gate is covered by a dedicated non-vacuous test.
|
||||
|
||||
**Per-viewer resume was deliberately not built.** `OnDemandCheckpoint` is a single value on the playout, so resume is per-channel, not per-viewer. #68 states per-channel suffices for a single household; multi-viewer identity would diverge from this model and is out of scope.
|
||||
|
||||
## 2026-07-21 — Session end fast-forwards the shared checkout; a stale tree serves stale FILES (#541)
|
||||
|
||||
`key: session.shared-checkout-refresh` · `status: active` · `since: 2026-07-21` · `supersedes: none` · `superseded-by: none`
|
||||
**Rule:** Session end runs `scripts/refresh-shared-checkout.sh`, which fast-forwards `/Users/timothy/ersatztv` to `origin/main` (and reinstalls `web/node_modules` when the lockfile moved), refusing to touch anything unless that tree is on a clean, non-ahead `main`.
|
||||
**Signals:** shared checkout, stale kickoff paste, `/Users/timothy/ersatztv`, session-end protocol, H13 · paths: `scripts/refresh-shared-checkout.sh`, `docs/handoffs/chicorytv-issue-queue.md` · issues: #541, #520, #311, #312
|
||||
**Mechanics:** `docs/handoffs/chicorytv-issue-queue.md` → session-end step 6 + the shared-tree lore bullet
|
||||
|
||||
**The existing rule had a hole, and it is a hole no rule can close.** The standing guidance — never
|
||||
commit in the shared tree, never read its `HEAD`/`git log`/`git status` as truth about `main` — is
|
||||
written entirely around a session **reading git state**. On 2026-07-21 the trap arrived as a **file**:
|
||||
the kickoff prompt was pasted out of that tree while it was 81 commits behind, and the handoff doc it
|
||||
carried still described the queue protocol #520 had retired the previous day (read tracker #237, which
|
||||
`main` now says must *not* be read for queue state). No `git` command touched that tree all session, so
|
||||
no discipline check could have fired. Selection happened to go through `scripts/select-queue.sh`, which
|
||||
is why nothing broke — routing luck, not a control.
|
||||
|
||||
**So the fix removes the stale condition rather than adding a check**, which is what the shared-tree
|
||||
lore bullet already prescribed for its first two failure modes: *"a check does not stay true."*
|
||||
|
||||
**The script is deliberately timid, because the tree is shared.** It refuses — loudly, exit 0,
|
||||
changing nothing — when the tree is not on `main`, is dirty, has local commits, or is mid-rebase or
|
||||
mid-merge. It never switches branches, never stashes, never discards. A refusal is a normal outcome,
|
||||
not a failure, because the common reason for one is that another session is legitimately mid-flight.
|
||||
|
||||
**Two details that testing forced.** The first version used `npm install`, which **rewrote
|
||||
`package-lock.json`** and left the shared tree dirty — the exact state the next run refuses on, so the
|
||||
tool would have disabled itself after one use. It uses `npm ci`, which installs strictly from the
|
||||
lockfile and never writes it. And it asserts the tree is clean at exit, reporting loudly if not:
|
||||
leaving the shared tree dirty is the one outcome that would make this script a net negative.
|
||||
|
||||
Reference in New Issue
Block a user