# AGENTS — how to work in this repo
This file is auto-read at the start of every session. The project keeps its
memory as a linked map of markdown files — read it before doing anything.
## ⚠️ CRITICAL: The Good Dog Rule
BEFORE any planning or coding, follow this rule:
> ONE integration test per change.
When the user asks for changes that would involve multiple integration tests:
1. Identify the ONE specific use case/test they want to work on
2. Focus ONLY on the single use case until it's complete and tests pass
> *A good dog learns one trick perfectly before learning the next.*
**No feature branches pre-1.0 (decided 2026-08-24):** solo dev, pre-1.0 — all
work lands directly on `main`, committed and pushed per work unit. No
`taskNN-*` branches, no PRs. The scope discipline above is about test focus,
not git mechanics.
**Commit / push policy (2026-08-30, user directive):** commit every work unit —
committing is expected and never needs extra permission. Pushing is different:
push ONLY at sub-milestones and milestones. During a multi-commit refactor,
that means commits land locally every partial; `git push` happens at the
session's agreed checkpoint(s), not per-commit. When a milestone warrants a
push the user will say so (or say "push it").
MUST read the architecture guide before planning or modifying the codebase:
[`ai.md`](ai.md) (+ [`schema.md`](schema.md) for the memory-map conventions).
MUST read the coding guide before writing tests or code: the [Working
rules](#working-rules) in this file — this repo has no `CODING.md`;
conventions live here and in `ai.md`.
## Onboarding (in order)
1. [`schema.md`](schema.md) — the memory-map conventions (what lives where, how to keep it true).
2. [`ai.md`](ai.md) — the AI guide: architecture, patterns, decisions, current state.
3. [`TASKS.md`](TASKS.md) — the task catalog (index + queue state); open items and API research facts are in [`TASKS/`](TASKS/).
4. [`HANDOFF.md`](HANDOFF.md) — current operational state: what's in flight, landmines, next step.
5. `
/index.md` — the index for any directory you're about to touch.
**If `HANDOFF.md` exists, trust it as current state** — no `fsck`, no branch
hunting, no file-scanning to re-derive what it already states, unless it points
at a problem.
## Working rules
- **Never work without the map.** If the map contradicts the code, the code wins
and the map gets fixed in the same change (stale facts are corrected, not appended).
- **Every feature change ships with its memory update in the SAME commit:**
`ai.md` for architecture/patterns, `TASKS.md` for status, index files when
layout changes. No code commit without its docs — a follow-up "docs backfill"
commit is a broken rule, not a style.
- **Rewrite `HANDOFF.md` at session end, compaction, or any interruption.**
Never end a session with uncommitted work unrecorded — the handoff names the
branch, the dirty files, and why it stopped.
- **The first time a fact costs a hunt (secrets path, DB path, port, recovery
source), record it** in `ai.md`/indexes/`HANDOFF.md` so the next session never
re-hunts it.
- **Derived-solution rule (record once, then grep):** the moment you work out a
reusable solution — a recipe, workaround, or how-to (e.g. how to shrink and
re-encode an image for the README) — write it into `MyMistakes.md` **in the same
session**, before you finish the task. And always **grep `MyMistakes.md` first**
when you hit a "I've done this before but have to figure it out again" wall. A
solution recorded once ends the re-derivation loop; an un-recorded solution is a
guarantee you will re-derive it and make the user sit through it again. This is
the fix for the image-shrink incident (2026-08-29): the recipe was never written
down, so it had to be worked out from scratch a second time.
- **Follow existing conventions** — MVVM, `RelayCommand` for actions,
`ViewModelBase.SetProperty()`, all styles in `Themes/Controls.xaml`
(merged once in `App.xaml`; never duplicate per-window).
- **Do not add comments unless the code needs them; do not expand the task queue
on your own** — work only what the user queues.
- **Derivative work / spin guard.** Every problem here is derivative — OBS, other
overlay tools, and the WPF/WebView2 ecosystems already solved it. Both sides are
mandatory, not advisory:
- **Proactive (new features):** before writing code, do a quick external scan
(websearch: how do OBS/CEV/overlay tools do this?) and cite the reference in the
commit message.
- **Spin guard (objectively triggered):** a SECOND failed remedy for the same
symptom = STOP. No third guess over the same code. Research the established
answer externally, cite its URL in the commit message AND in `MyMistakes.md`,
then code it. You do not know everything — repeated failure is a research
trigger, not a persistence trigger.
- **Response style: no default planning template.** Do the work, then report
what changed and what's next. No "Plans & Pitfalls", pros/cons tables, or
step-by-step plans unless the user asks for a plan first (see `ai.md`).
- **No-Fluff Mode is available on request** — unpadded, ruthless review that
argues rather than reassures (see `ai.md`). Optional, never the default.
## Scope Lock
BEFORE editing any file, declare the exact file list for the task. Every file you
touch must be either in that list OR you must state the specific dependency that
requires it (e.g. "method X's signature changed, callers must update"). No "while
I'm here" edits. No refactoring. No style tweaks. If you spot a problem in a file
you're already editing, note it in HANDOFF.md as a follow-up — do not fix it in
this change.
> *The commit `d2114c7` touched 11 files across 4 layers because the AI decided
> to refactor the world. This rule exists because of that incident.*
### Before editing a file — git history scan
```
git log --oneline -5 --
```
If the file hasn't been touched in many commits and the current task doesn't
directly require changing it, that is a red flag — stop and justify the edit or
don't make it. A stable file touched by an unrelated task is a bug, not a feature.
### Pre-commit audit
Before every commit, run `scripts/scope-check.sh` with the declared file list.
If any file appears in `git diff` but not in the declared scope, either justify
it or revert the change. The script enforces what the rule demands.
```bash
./scripts/scope-check.sh "Models/Scene.cs" "ViewModels/MainViewModel.cs" "MainWindow.xaml"
```
## Build
From WSL, ALWAYS use the Windows dotnet host — Linux `dotnet` re-downloads the
`windowsdesktop.app.*` packs over the slow 9p bridge and re-restores twice (WPF
`_wpftmp`), and `--no-restore` right after an interrupted restore produces bogus
`NETSDK1064` errors. See `ai.md` → Run for the exact commands and why.
```bash
"/mnt/c/Program Files/dotnet/dotnet.exe" build "C:\Users\gramp\Documents\Code\projects\ytLive\ytLive.csproj"
"/mnt/c/Program Files/dotnet/dotnet.exe" vstest "C:\Users\gramp\Documents\Code\projects\ytLive\ytLive.Tests\bin\Debug\net8.0-windows10.0.19041.0\ytLive.Tests.dll"
```
Keep it at **0 warnings**. Running requires Windows. On a silent startup crash,
read `%APPDATA%\ytLlive\startup.log` (`Helpers/AppLog.cs` writes checkpoints and
unhandled exceptions there).