Build ErsatzTV Image / Delimiter ban (release path) (push) Successful in 26s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 9m34s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 6m35s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 6m22s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Skipped
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 5m12s
Both C#/TS language servers and the csharp-lsp MCP server were dead; all three are fixed and each demonstrated with a real find-all-references call in this repo. Root causes were one shape — a config naming a path this machine does not have, with nothing checking. None returned a wrong answer; each refused to start: - csharp-ls: MSBuildLocator needs a dotnet root owning host/fxr; Homebrew's bin has none, libexec does. - typescript-language-server: the LSP workspace root is the repo root but `typescript` lives in web/node_modules, and the plugin cannot pass a tsserver path (v5 dropped --tsserver-path; lspServers cannot set initializationOptions). - the csharp-lsp MCP server: .mcp.json named a dotnet install that no longer existed, while ~/.codex/config.toml's copy of the same server had been migrated. Both files are gitignored, so nothing could compare them. Corrects defect-shapes-773.md §5.1: the "workflow agents must use csharp-lsp" note names the MCP server's tools, which subagents DO reach — it was dead because the server could not start, not because agents cannot call it. The LSP tool is the one no subagent has been observed to resolve. Six cold review rounds. Five false greens were found in this PR's own verification code, each introduced by the fix for the previous one — extracted as #796. fixes #777 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Timothy <timothy@noreply.gitea.tblindustries.be>
126 lines
10 KiB
Markdown
126 lines
10 KiB
Markdown
# docs/ — task-signal map
|
|
|
|
Purpose: route a fresh contributor/agent to the minimal set of docs for the task at hand, instead of
|
|
a mandatory front-to-back read. **Update this doc in the same PR that adds, removes, or retitles a
|
|
doc below, or that changes which sections a task signal points to.**
|
|
|
|
## Start here, always
|
|
|
|
- **`CLAUDE.md`** (repo root) — project intro: architecture, layout, dev commands, conventions,
|
|
Task Completion Protocol.
|
|
- **`docs/contributing.md`** — established code patterns (CQRS/MediatR, LanguageExt, the ChicoryTV
|
|
SPA, EF Core dual-provider migrations, FFmpeg pipeline, analyzers, testing). Read before any
|
|
non-trivial change.
|
|
|
|
## Task signal → minimal sections
|
|
|
|
| Signal | Read |
|
|
| --- | --- |
|
|
| Session startup / "what's next" (no issue named) | `docs/handoffs/chicorytv-issue-queue.md` (standing kickoff — two concurrent tracks: orientation ‖ `scripts/select-queue.sh 5`) |
|
|
| Named-issue pickup | Skip queue selection; go straight to focused retrieval — see "Knowledge retrieval" below, then the issue body |
|
|
| Adding/changing a `/api/*` endpoint | `docs/api-conventions.md` checklist + `docs/endpoint-index.md` |
|
|
| Adding a ChicoryTV SPA screen | `docs/spa-conventions.md` |
|
|
| Scheduling / playout engine work | `docs/domain-model.md` + decisions catalog rows keyed `sched.*` (`docs/decisions/README.md`) |
|
|
| Concurrency / optimistic-locking work | `docs/api-conventions.md` §7a/b/c + `docs/decisions/optimistic-concurrency.md` |
|
|
| Auth / security-surface work | `docs/decisions/api-auth-security.md` |
|
|
| CI / release pipeline work | `docs/ci-cd.md` + `docs/decisions/release-ci-governance.md` |
|
|
| Proposing a new guard / CI check / regression test convention | `docs/defect-shapes-773.md` §4 (detector menu + the classes where no detector is plausible), then the two rules every guard must satisfy: `docs/decisions/records/testing/guard-derives-population-from-source.md` and `…/guard-ships-with-mutation-proof.md` |
|
|
| Adding / changing / deleting a guard file | `docs/guard-inventory.md` — every guard's row is machine-checked by `scripts/tests/test_guard_inventory.py`, so a new guard must acquire a row before the suite goes green |
|
|
| Finding every site that references a symbol (multi-site fix/sweep) | `docs/local-lsp-tooling.md` — which surface answers, and why a delegated agent must be pointed at the `csharp-lsp` MCP tools rather than the `LSP` tool |
|
|
| Live local run / Playwright-MCP verification | `docs/e2e-local.md` + `scripts/e2e-local.sh` |
|
|
| Adding/changing a UI-E2E browser flow | `docs/e2e-local.md` → "UI-E2E harness" + `scripts/e2e-ui.sh` |
|
|
| What does a test suite cover | `docs/testing.md` |
|
|
| Legacy Blazor route lookup | `docs/blazor-route-parity.md` (historical #91 phase (b) inventory) |
|
|
| "Why do we do X this way" / challenging a convention | **Catalog-first**: `docs/decisions/README.md` (active rows) → follow the row's link to `docs/decisions/records/<area>/<topic>.md` for full rationale. `docs/decisions/archive/<area>/` only for "what did the rule used to be." |
|
|
|
|
## Knowledge retrieval (MemPalace + catalog + Gitea)
|
|
|
|
These four rules are the seam agreed with server-management#642 (the Gitea→MemPalace exporter).
|
|
They apply whether the question comes up via MemPalace, a grep, or a stale comment:
|
|
|
|
1. **Current conventions/decisions → catalog-first.** Start at `docs/decisions/README.md`; discover
|
|
via the `ErsatzTV-Decisions` wing (active) / `ErsatzTV-Decisions-Archive` (superseded/retired).
|
|
**Resolve by topic/key, never by chasing a file path.**
|
|
2. **Issue history → evidence, not authority.** The `Gitea-ErsatzTV` wing is historical narrative
|
|
that may be stale; it never overrides current Markdown.
|
|
3. **The breadcrumb rule (the crux behavior change).** A file path named inside a *historical issue
|
|
comment* (e.g. "grep `docs/decisions.md` 2026-07-17", "see …") is a **breadcrumb, not a live
|
|
pointer.** Find the current rule via the catalog / active wing **by concept**; do not treat the
|
|
named path as current. (Why it's safe: still-current → in the active wing, breadcrumb resolves;
|
|
superseded → the active wing returns the *successor* and a literal follow lands on a record that
|
|
announces its own `status: superseded`; retired → the active wing returns nothing, which is
|
|
itself the signal. The validator-enforced move-to-`archive/` is what prevents the catastrophic
|
|
"superseded rule read as current" case.)
|
|
4. **Fallback when MemPalace is stale/down:** `docs/decisions/README.md` catalog, then
|
|
`` rg '^`key: <dotted.key>`' docs/decisions/ ``. MemPalace is never authority nor sole fallback.
|
|
|
|
MemPalace is candidate discovery only — every passage is verified against its cited Markdown/Gitea
|
|
source before use. Never derive live queue state from MemPalace, #237, or historical comments; queue
|
|
state is live Gitea state, retrieved via `scripts/select-queue.sh` (see
|
|
`docs/handoffs/chicorytv-issue-queue.md`). Full retrieval contract (altitude/precedence, staleness
|
|
bounds, what's mined per issue): `docs/handoffs/chicorytv-issue-queue.md` → "Knowledge retrieval".
|
|
|
|
## Also present in `docs/`
|
|
|
|
- **`docs/domain-model.md`** — what the app IS: entity glossary, channel→playout→schedule/block
|
|
concept map, where each concept is edited in the SPA.
|
|
- **`docs/api-conventions.md`** — checklist for adding/changing a `/api/*` endpoint (controllers,
|
|
DTOs, error mapping, auth, OpenAPI regen, tests).
|
|
- **`docs/spa-conventions.md`** — playbook for adding a screen to the ChicoryTV React SPA.
|
|
- **`docs/e2e-local.md`** (+ `scripts/e2e-local.sh`) — how to run a live local instance for manual
|
|
or Playwright-MCP verification.
|
|
- **`docs/local-lsp-tooling.md`** — the code-intelligence surfaces (the `LSP` tool's three servers and
|
|
the `csharp-lsp` MCP server): how each is configured, which one a **subagent** can actually reach,
|
|
the traps (a cold server answers the first query with a confidently partial result), and
|
|
`scripts/check-local-lsp.sh` to verify the preconditions. Read before briefing an agent to find
|
|
every site referencing a symbol.
|
|
- **`docs/testing.md`** — testing map: what each `*.Tests` project / `web` suite covers,
|
|
golden-file nets, the timezone-independence rule, how to run subsets, the per-PR verification
|
|
gate.
|
|
- **`docs/blazor-route-parity.md`** — historical record of the completed #91 phase (b) cutover:
|
|
the Blazor Server UI is removed and every legacy route now 302-redirects to its SPA equivalent
|
|
(or falls through to the catch-all → `/app`). Read it for the full legacy→SPA route inventory.
|
|
- **`docs/decisions/records/<area>/<topic>.md`** — one active decision record per file, YAML
|
|
frontmatter (`key`/`title`/`status`/`since`/`supersedes`/`superseded-by`, plus optional
|
|
`stale-after`/`sources` — ersatztv#603), rationale prose in the body. The **filename is the key**,
|
|
so one-active-record-per-key is a filesystem property (ersatztv#610). `docs/decisions.md` and the
|
|
topic files remain as the lifecycle-schema narrative plus a "Records formerly in this file" index,
|
|
which is what keeps older date-based pointers resolvable. **Generated active view**:
|
|
`docs/decisions/README.md`
|
|
(catalog / task router) — start there. Superseded/retired records live in
|
|
`docs/decisions/archive/` and are read only for history, never for "what is the current rule."
|
|
- **`docs/ci-cd.md`** — build/test/release pipeline, versioning, dependency management.
|
|
- **`docs/rest-api.md`** — REST API design doc for ersatztv#2 (goals, conventions, per-slice plan).
|
|
Largely superseded day-to-day by `docs/api-conventions.md`; read this for the original rationale.
|
|
- **`docs/mcp.md`** — the `ErsatzTV.Mcp` stdio JSON-RPC MCP server (#58): how it wraps `/api/v1` as
|
|
read + cautious-write tools, its config/env vars, auth, security posture, and the tool catalog.
|
|
- **`docs/channels.md`** — Channel entity field reference.
|
|
- **`docs/m3u-xmltv.md`** — M3U/XMLTV generation overview (`ChannelPlaylist`, `GetChannelGuideHandler`).
|
|
- **`docs/fork-strategy.md`** — divergence policy vs upstream ErsatzTV.
|
|
- **`docs/design-sync.md`** — Claude Design ↔ repo screen workflow (#92).
|
|
- **`docs/endpoint-index.md`** — generated REST endpoint index (method/path/operationId/summary per
|
|
OpenAPI tag). Do not edit by hand; regenerated by `scripts/generate-endpoint-index.py` /
|
|
`scripts/update-openapi.sh`.
|
|
- **`docs/handoffs/chicorytv-issue-queue.md`** — static session kickoff prompt + workflow lore.
|
|
Queue state is **live Gitea state**, retrieved each session via `scripts/select-queue.sh` — see
|
|
that file's standing kickoff for the two concurrent tracks (orientation ‖ selection). ersatztv#237
|
|
is a closed, archival historical tracker (superseded by `startup.parallel-orientation` in
|
|
`docs/decisions.md`) — not a live pointer.
|
|
- **`docs/defect-shapes-773.md`** — root-cause analysis of the recurring defect shapes across the
|
|
whole closed-issue corpus (#773): the measured class ranking, the four families they consolidate
|
|
into, the cheapest mechanical detector per class, the classes where **no** detector is plausible,
|
|
and an audit of which configured hooks/MCP servers/LSPs are actually invoked. Read it before
|
|
proposing a new guard or CI check — §4 is the detector menu, and it argues against enumerating
|
|
cases one incident at a time.
|
|
- **`docs/guard-inventory.md`** — every executable guard file, what it blocks, whether it is a
|
|
`GUARD` or `TOOLING`, and whether it ships a mutation proof (`MUTATION` / `BEHAVIOUR-ONLY` /
|
|
`NONE`) with a `file::function` ref. The population is derived from the filesystem and the
|
|
workflow/hook call sites and compared for set equality by `scripts/tests/test_guard_inventory.py`,
|
|
so a new guard cannot ship unclassified and a renamed test cannot leave a row claiming coverage it
|
|
has lost. Guards implemented inline in workflow YAML are deliberately outside that population —
|
|
the doc states the limit rather than implying coverage.
|
|
- **`docs/tracker-retrofit-triage-237.md`** — audit trail for the #524 triage of ersatztv#237's 111
|
|
comments (method, per-comment classification, totals). Evidence for the
|
|
`docs.tracker-comment-retrofit` decision; read it only when triaging another over-cap tracker.
|
|
- **`docs/handoffs/rest-api.md`** — original handoff prompt for kicking off the REST API work (#2).
|