fix(520,521): clear stale migration-map + narrow convention-docs-session-start rule to the task-map protocol [decisions-edit]
Build ErsatzTV Image / CI image pin matches docker/ci (pull_request) Successful in 13s
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 16s
Build ErsatzTV Image / decisions lifecycle (pull_request) Successful in 37s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m22s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 1m20s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 7m19s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 14m47s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 18m22s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Build ErsatzTV Image / CI image pin matches docker/ci (pull_request) Successful in 13s
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 16s
Build ErsatzTV Image / decisions lifecycle (pull_request) Successful in 37s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 1m22s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 1m20s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 7m19s
Build ErsatzTV Image / Functional E2E (curl contracts) (pull_request) Successful in 14m47s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 18m22s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+2
-2
@@ -244,8 +244,8 @@ per-kind child endpoints.
|
||||
|
||||
## 2026-07-07 — Convention docs read at session start, updated in-PR
|
||||
`key: docs.convention-docs-session-start` · `status: active` · `since: 2026-07-07` · `supersedes: none` · `superseded-by: none`
|
||||
**Rule:** The standing convention-doc set (api-conventions, spa-conventions, e2e-local, blazor-route-parity, domain-model, decisions, README) is read at session start and updated in the same PR that changes what it documents, replacing per-session recon.
|
||||
**Signals:** `docs/README.md` index, `ApiControllerSecurityTests` drift · paths: `docs/README.md`, `docs/api-conventions.md` §6 · issues: #184, #185
|
||||
**Rule:** Docs-first, not source-first: conventions (api-conventions, spa-conventions, e2e-local, blazor-route-parity, domain-model, decisions, README) are read from docs, not reverse-engineered from code, via `docs/README.md`'s task-signal map — only the sections it points to for the task at hand, not the whole set. Each doc is updated in the same PR that changes what it documents, replacing deferred/follow-up doc updates.
|
||||
**Signals:** `docs/README.md` index, `ApiControllerSecurityTests` drift · paths: `docs/README.md`, `docs/api-conventions.md` §6 · issues: #184, #185. Session-start *reading order* is now the task-signal map — see `startup.parallel-orientation`.
|
||||
**Mechanics:** `docs/README.md`
|
||||
|
||||
`docs/api-conventions.md`, `docs/spa-conventions.md`, `docs/e2e-local.md`,
|
||||
|
||||
@@ -45,7 +45,7 @@ the link for rationale. Superseded/retired history lives in `archive/`. Regenera
|
||||
| `concurrency.ifmatch-rfc7232` | `ConcurrencyHeaders.ParseIfMatch` is a real RFC 7232 entity-tag/list parser: a syntactically-valid tag that doesn't strong-match (weak/empty/non-canonical/out-of-range/list) returns 412, and only a genuine grammar violation returns 400. | 2026-07-12 | [link](optimistic-concurrency.md#2026-07-12--if-match-evaluates-per-rfc-7232-valid-but-non-matching--412-only-grammar-violations--400-265) |
|
||||
| `concurrency.replace-all-contract` | Replace-all aggregate PUTs carry a uniform plain `int Version` concurrency token (EF `.IsConcurrencyToken()`), checked pre-save and enforced by the EF UPDATE guard, returning 412 (not 409) on a stale `If-Match`. | 2026-07-11 | [link](optimistic-concurrency.md#2026-07-11--optimistic-concurrency-contract-for-replace-all-puts-253-pr1-infra--block-reference) |
|
||||
| `concurrency.schedule-item-child-identity` | `PUT /api/schedules/{id}/items` reconciles by an optional round-tripped child `Id` (null/absent/0 ⇒ new item), never by array position, so fill-group/shuffle state follows the logical item across reorders; an unknown or duplicate id is rejected 422 (checked after the §7a `CheckVersion`, so 412 precedes 422). | 2026-07-11 | [link](optimistic-concurrency.md#2026-07-11--stable-child-identity-for-schedule-item-replace-259-split-from-252253) |
|
||||
| `docs.convention-docs-session-start` | The standing convention-doc set (api-conventions, spa-conventions, e2e-local, blazor-route-parity, domain-model, decisions, README) is read at session start and updated in the same PR that changes what it documents, replacing per-session recon. | 2026-07-07 | [link](../decisions.md#2026-07-07--convention-docs-read-at-session-start-updated-in-pr) |
|
||||
| `docs.convention-docs-session-start` | Docs-first, not source-first: conventions (api-conventions, spa-conventions, e2e-local, blazor-route-parity, domain-model, decisions, README) are read from docs, not reverse-engineered from code, via `docs/README.md`'s task-signal map — only the sections it points to for the task at hand, not the whole set. Each doc is updated in the same PR that changes what it documents, replacing deferred/follow-up doc updates. | 2026-07-07 | [link](../decisions.md#2026-07-07--convention-docs-read-at-session-start-updated-in-pr) |
|
||||
| `docs.decision-lifecycle` | every decision `##` record (active or archived) carries a 5-field metadata block (`key`, `status`, `since`, `supersedes`, `superseded-by`) checked by `scripts/decisions_validate.py`; a record is never deleted or line-edited to reverse a call — it is moved to `docs/decisions/archive/` with `status: superseded`/`retired` and a reciprocal `superseded-by`/`supersedes` key pair to its replacement. | 2026-07-21 | [link](../decisions.md#2026-07-21--decision-records-carry-a-lifecycle-schema-validated-by-a-script-append-only-by-diff-is-retired-521) |
|
||||
| `ffmpeg.external-logo-graphics-engine` | External-URL channel logos pass through to the graphics engine like any other watermark source; `WatermarkSelector` must never gate them on `File.Exists` (always false for a URL) and never route them through the ffmpeg-native overlay shortcut. | 2026-07-20 | [link](../decisions.md#2026-07-20--external-url-channel-logos-pass-through-to-the-graphics-engine-never-fileexists-gated-never-ffmpeg-native-502) |
|
||||
| `ffmpeg.hls-cold-start-burst` | HLS cold-start latency is fixed with a bounded `-readrate_initial_burst` (gated on FFmpeg ≥6.1 capability detection), not by raising `work_ahead_limit`, which would remove the concurrency guarantee it exists for. | 2026-07-20 | [link](../decisions.md#2026-07-20--hls-cold-start-is-fixed-with--readrate_initial_burst-not-by-raising-the-work-ahead-limit-350) |
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
# Decision migration map (legacy heading → active record / archive)
|
||||
|
||||
Auditable mapping produced during the #521 lifecycle migration. Every legacy H2 heading maps to
|
||||
either an active record (key) or an archive location. Most headings in `docs/decisions.md` and the
|
||||
`docs/decisions/*.md` topic files are still `status: legacy-unmigrated` (no metadata block yet) — this
|
||||
table only covers records touched so far. `PYTHONPATH=. python3 scripts/decisions_validate.py` prints
|
||||
the running legacy-unmigrated count; it must trend to 0 over the arc, not drop to 0 in one PR.
|
||||
The full corpus (`docs/decisions.md` and the `docs/decisions/*.md` topic files) was **fully migrated
|
||||
to the lifecycle schema on 2026-07-21 (#520/#521)**: `PYTHONPATH=. python3 scripts/decisions_validate.py`
|
||||
reports 0 `legacy-unmigrated` headings, and the catalog (`docs/decisions/README.md`, built by
|
||||
`scripts/build_decisions_catalog.py`) lists 108 active records. Every active decision heading now
|
||||
carries a metadata block (`key:`/`status:`/`since:`/`supersedes:`/`superseded-by:`). Most headings were
|
||||
migrated **in place** — the heading text is unchanged, only the metadata block was added — so their key
|
||||
is discoverable via the catalog or `rg '^\`key:\`' docs/decisions/`, not via this file. This table
|
||||
records only the **non-trivial** mappings produced during the migration: splits, supersessions, and
|
||||
prose-only reversal notes. It is not, and was never meant to be, a 1:1 index of all 108 records.
|
||||
|
||||
| Legacy heading | Key | Status | Location |
|
||||
| --- | --- | --- | --- |
|
||||
@@ -49,10 +53,10 @@ sibling.
|
||||
and is very much active, so this is a straightforward **supersession of an unnamed predecessor**, not
|
||||
a retirement — there's no case to make for `retired` here since the surface it measures is live.
|
||||
|
||||
## Still open (tracked for later migration passes, not this PR)
|
||||
## Still open
|
||||
|
||||
- The remaining ~90 headings in `docs/decisions.md` and the other three `docs/decisions/*.md` topic
|
||||
files (`optimistic-concurrency.md`, `api-auth-security.md`, `spa-modularization.md`, and the rest of
|
||||
`release-ci-governance.md`) are unmigrated (`status: legacy-unmigrated`, no metadata block). They are
|
||||
valid under the schema as-is (the validator treats an unmigrated H2 as a migration target, not an
|
||||
error) and migrate incrementally as each is next touched, per the arc's design.
|
||||
- **DONE**: `docs.queue-state-gitea-tracker` (#237) — superseded by `startup.parallel-orientation`
|
||||
(2026-07-21, #520), archived at `docs/decisions/archive/startup.md`. See the table above.
|
||||
- Nothing else is open from this migration — the corpus is fully migrated (0 legacy-unmigrated). Future
|
||||
new decisions are simply added directly in the lifecycle schema; there is no further migration pass
|
||||
to track here.
|
||||
|
||||
@@ -135,8 +135,8 @@ orchestrator and pass in its packet. **Do not fall back to inline sorting or an
|
||||
selector.** If no cheaper route or session is available, pause and request the selector packet rather
|
||||
than consuming orchestrator tokens on queue ranking.
|
||||
|
||||
FIRST read `AGENTS.md` and `CLAUDE.md` when present, then `docs/README.md`, the convention docs it
|
||||
indexes, and the Lessons below. Apply both client instruction files; where they differ, follow the
|
||||
FIRST read `AGENTS.md` and `CLAUDE.md` when present, then `docs/README.md` and the sections its
|
||||
task-signal map points to for your task, plus the Lessons below. Apply both client instruction files; where they differ, follow the
|
||||
stricter safety/completion requirement unless a higher-priority instruction resolves the conflict.
|
||||
|
||||
FRONTIER ESCALATION — these moments go to the strongest available reasoning model. In Claude Code,
|
||||
|
||||
Reference in New Issue
Block a user