Files
brain-of-reese/.agent/user_stories/steering-notes.md
T
ducoterra 4971e2859d
Build and Push Containers / build-and-push-app (push) Successful in 12s
Build and Push Containers / build-and-push-db (push) Successful in 10s
chore(agent): track .agent/ planning tree in git
Remove the blanket .agent/ gitignore so the phase roadmap, user
stories, reports, and PLAN.md are versioned with the code. Only
runtime artifacts (.agent/phase-sessions/, .agent/pipeline.log)
remain ignored. Update AGENTS.md git protocol rule to match.
2026-09-01 10:18:22 -04:00

50 lines
2.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Story: Tune How Brain Answers (Steering Notes)
**Phase:** `15_steering_notes.md` · **E2E:** `tests/e2e/test_steering.py`
## Narrative
As **a user**, when an answer **isn't quite right** (too chatty, wrong
assumption, missing context), I want to **tune** Brain right there: a
short instruction ("be more concise", "assume I'm on NixOS") that is
**stored in the database** and **read into the system prompt** so every
future reply follows it.
- **Given** an answer I don't like
- **When** I click "Tune" under it and save an instruction
- **Then** the note is persisted in Postgres, shown in the tuning
panel (where it can be removed), and injected into the system prompt
of every subsequent turn — verifiable in the answer.
## Acceptance criteria
1. New `steering_notes` table (id, note, created_at) via Alembic
migration 0003.
2. Stateless API: `GET /api/steering` (newest first),
`POST /api/steering` (1–2000 chars, 201 / 422),
`DELETE /api/steering/{id}` (204 / 404).
3. System prompt: when notes exist, a `<tuning>` section (numbered notes,
char-budgeted) is appended to **both** HIGH and DEFLECT prompts; when
none exist, the prompt is byte-identical to today's.
4. Per-turn log line gains `tuning=N`.
5. UI: "Tune" button under every completed brain answer (deflected too)
→ inline form → save → confirmation; header "Tuning" toggle lists
notes with per-note delete; all labeled, live regions, ≥44px targets,
Phase-08 tokens.
6. Notes render as text (XSS-safe).
7. Unit + integration green, `app/` coverage >90%, story E2E green in
isolation, one `--no-gpg-sign` commit.
## Playwright Mapping Rule
**Test Scenario → `tests/e2e/test_steering.py`** (mock LLM, seeded KB —
the mock echoes the first tuning note into its answer when `<tuning>` is
present, so prompt injection is observable in the UI):
1. `test_tune_under_answer_persists_and_steers` — answer → Tune → note
"STEEER-MARKER be concise" → saved → next answer contains the marker
(note reached the system prompt) → note visible in panel with count.
2. `test_delete_note_stops_steering` — delete from panel → count 0 →
next answer has no marker.
3. `test_note_rendered_as_text_xss_safe` — note with `<script>` renders
as visible escaped text, never executes.
4. `test_tuning_panel_a11y` — toggle aria-expanded, region label,
delete buttons labeled, live region announces save/delete.