Files
ersatztv/docs/handoffs
timothy fe6e2722f8
Build ErsatzTV Image / CI image pin matches docker/ci (pull_request) Successful in 6s
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 5s
Build ErsatzTV Image / decisions.md append-only (pull_request) Successful in 4s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 7m1s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 19s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 16s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m54s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 14m5s
docs(lore): batching, no "main checkout", trust the queue, killed≠failed
Operator-requested after PR #405 pushed 5 times, orphaning live runs the
operator had to cancel by hand. Batches every standing-lore correction this
session produced into one commit (per the batching rule it adds).

New HARD CONSTRAINTS:
- BATCH PUSHES. Cancellation is impossible from the agent side on Gitea 1.25.4
  — REST .../runs/{id}/cancel and MCP cancel_run both 404, and the web-UI route
  needs a session+CSRF that doesn't script. Only the operator can cancel, so an
  orphaned run holds a runner slot until it finishes. If you must supersede a
  live run, SAY SO.
- TRUST THE GITEA BUILD QUEUE. Do not gate/throttle a push on host health; the
  runners were retuned for stability. Batch because you can't cancel what you
  orphan, not to protect the host.
- BOM-CHECK touched .cs before pushing. The #311 gate is fix-as-you-touch, and
  it bit two sessions the same day (PR #405 ×6; #70/PR #402 ×19 via Python
  utf-8-sig writing BOMs back). Verify your detector — an od-based grep reported
  all-clean while 19 files were dirty.
  Corrects a claim I nearly published: `dotnet format --include` DOES work here.
  The apparent no-op was the SHELL — CI's mapfile is bash-only, zsh has no
  mapfile → empty array → zero files → exit 0. Run it under bash -c.

THERE IS NO "main checkout" — the biggest correction here.
/Users/timothy/ersatztv is a shared mutable working tree whose HEAD is whatever
the last session left there. Its name lies, and it bit TWO sessions on
2026-07-17, both doing the obvious thing: one assumed main and committed onto
the #604/CI session's branch 24s after that session's own commit; another read
git log there and concluded main was "4 behind origin" — a phantom. Framed as a
design flaw, not a discipline failure: "check git status first" appears to
confirm the false assumption and then goes stale (it WAS on main at 12:46 and
wasn't by 14:17). Worktree discipline itself is healthy — 10 feature worktrees.

Diagnosing CI reds — three ways to misread one, all hit this session:
- A KILLED job reports conclusion=failure, not cancelled. The tell is a log that
  stops mid-step with NO error and NO failure marker. A runner retune killed run
  1006's migration + E2E on a BOM-only diff that couldn't break them. Log
  timestamps are UTC, host is UTC+2 — convert before correlating.
- cancelled ≠ failure: a cancel is NO verdict, and a run marked failure may hold
  a genuine job failure from BEFORE the cancel. Monitors must count FAILED and
  CANCELLED separately.
- "Unable to pull refs/heads/v4" is act refreshing its action cache and is
  followed by "Cloned …" — noise, not a cause. Grep the failure marker, not
  the word "error". An infra-shaped red (setup/cache step, before your code
  compiles) is not a code failure; don't file a CI bug off one sample.

Also: the cheap selector's failure modes are wider than deps+priority — it also
misses in-progress claim state and umbrella-vs-child.

Docs-only.
2026-07-17 18:15:32 +02:00
..