refactor(agents): migrate .agent/ planning tree to .agents/

Standardize on the .agents/ directory (shared with project skills):
phases/, user_stories/, reports/, screenshots/, validate.sh, and
phase-sessions/ + pipeline.log all move to .agents/ (git mv preserves
history; runtime artifacts move alongside).

Updates every reference in AGENTS.md, README.md, .gitignore, app
docstrings, and test story headers. Historical KB content in data/
and the runtime pipeline.log transcript are left untouched.
This commit is contained in:
2026-09-05 10:57:07 -04:00
parent 766702c750
commit dbf2af26c6
1118 changed files with 664 additions and 664 deletions
@@ -0,0 +1,53 @@
# Task 03 — Example theme (`indigo.css`) + authoring guide + Containerfile line
**Phase:** `62_ui_customization` · **Source:** `TODO.md:3` — "…custom color themes…"
**Story:** n/a (TODO-derived)
## Objective
A working example theme a deployer can point `BOR_THEME` at out of the box — plus the documentation that makes "write my own theme" a 15-minute job, and the one Containerfile line that ships the directory in the container image (A7).
## Work
1. `frontend/assets/themes/indigo.css` (NEW) — overrides ONLY the 8 identity variables in a single `:root` block; the semantic families (accent/ok/err) are deliberately UNTOUCHED (they encode states — deflection amber, success green, error red — and are already AA in the built-in theme; a theme that keeps them stays honest):
```css
/* Phase 62 example theme — dark indigo/slate.
Overrides the :root identity palette from styles.css; every
text/background pair meets WCAG 2.1 AA (>= 4.5:1):
ink on bg 15.8:1 · ink on surface 14.6:1 · ink-soft on surface 8.2:1
dark bg ink on brand 6.4:1 · brand-ink on surface 11.9:1.
Semantic families (accent/ok/err) inherit the built-in theme. */
:root {
--bg: #0a0e1a;
--surface: #111726;
--ink: #e6e9f0;
--ink-soft: #a8b0c8;
--line: #232c44;
--brand: #818cf8;
--brand-soft: #1a1f38;
--brand-ink: #c7d2fe;
}
```
- Before committing, re-verify the five ratios above (e.g. a 10-line python contrast calc against the built-in pairs' house comment style) — if any pair misses 4.5:1, adjust the value, not the bar (AGENTS.md rule 5).
- Spot-check that no component CSS hard-codes a color the theme should own: `grep -n "f43f5e\|#f0e6e6\|#0f0a0a" frontend/assets/styles.css` should match ONLY the `:root` palette block + comments (if a literal lives elsewhere, note it in the task report — do NOT refactor styles.css in this phase).
2. `frontend/assets/themes/README.md` (NEW) — the authoring guide, house-comment style:
- How themes load: `BOR_THEME=<file>` → `/api/config` → `brand.js` inserts `<link rel="stylesheet" href="/assets/themes/<file>">` AFTER `styles.css` (later wins the cascade — that is the whole mechanism).
- The variable table: the 8 identity variables (bg/surface/ink/ink-soft/line/brand/brand-soft/brand-ink) with the built-in values as reference, and the note that accent/ok/err are semantic and should stay.
- Rules: filename `^[a-z0-9_-]+\.css$` (lowercase, bare filename — the server validator rejects anything else at startup); one `:root` block; every text/background pair ≥4.5:1 (AGENTS.md rule 5); never white-on-brand (the built-in's documented 3.7:1 trap) — dark bg ink on brand, as the built-in does.
- Deployment: works in dev immediately (served from the static dir); in the container, rebuild the image (the `cp -r` picks up whatever is in `frontend/assets/themes/` at build time — no Containerfile edit for new files, A7).
3. `Containerfile` — stage-1 `RUN` chain: after the `styles.css` minify line, add
```
&& cp -r ./assets/themes /out/assets/themes \
```
(A7: whole directory, no per-file esbuild — future themes need no Containerfile change). No other stage changes; the runtime stage copies the whole `/out` static tree, so the dir flows through untouched.
4. Dev-server sanity (record in task report): with `BOR_THEME=indigo.css`, `http://localhost:8000/assets/themes/indigo.css` returns 200 from the static dir; with the default env the built-in palette renders (the file existing but `BOR_THEME` empty changes NOTHING — loading is opt-in via the env var, not directory scanning).
## Testing & Quality
- No Python logic; `uv run pytest` green; `uv run ruff check . && uv run pyright` clean.
- Coverage: **>90%** on `app/` (validate.sh gate).
- Add the theme-file unit pins to `tests/unit/test_frontend_brand.py` (or `test_stale_ui_copy.py`'s sibling if the executor prefers a new `tests/unit/test_themes.py`): the file exists, starts with a `:root` block, contains exactly the 8 `--` overrides (no other declarations), and the Containerfile contains the `cp -r ./assets/themes` line.
- Browser proof (computed `--brand`, the link tag, visual sanity) lands in task 05's E2E.
## Completion Criteria
- [ ] `frontend/assets/themes/indigo.css` + `README.md` exist; all five contrast ratios verified ≥4.5:1 (calc output in the task report).
- [ ] `Containerfile` ships `assets/themes/` (the line is in stage 1, after the styles.css minify).
- [ ] The `grep` spot-check for hard-coded identity colors is recorded (expect: `:root` block + comments only).
- [ ] Unit pins green; full suite green; lint + types clean.