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:
@@ -0,0 +1,51 @@
|
||||
# Story: Configurable app name
|
||||
|
||||
**Phase:** `39_configurable_brand` · **E2E:** `tests/e2e/test_configurable_brand.py`
|
||||
|
||||
## Narrative
|
||||
|
||||
As **the owner**, the app is "Brain of Reese" because that's what I named
|
||||
it — but the name is hard-coded across every template and JS string. I want
|
||||
to be able to **rename the app with one env var** (`BOR_APP_NAME`) so every
|
||||
page title, the header brand, the status labels, and the aria text carry
|
||||
the new name without touching code.
|
||||
|
||||
- **Given** the app is running with `BOR_APP_NAME="Brain of Testy"`
|
||||
- **When** I open any page (chat, sources, tuning, login, document viewer)
|
||||
- **Then** the title, the header brand, the status labels
|
||||
("Brain of Testy is thinking"), the empty-state greeting, and the
|
||||
document-viewer titles all say "Brain of Testy" — and with the variable
|
||||
unset the app is byte-identical to today ("Brain of Reese").
|
||||
|
||||
## Acceptance criteria
|
||||
1. `GET /api/config` (public, stateless) → `{app_name, version}` from
|
||||
settings — exactly those two keys (no secrets, no other settings);
|
||||
unit + integration tested.
|
||||
2. `frontend/assets/brand.js` (classic script, loaded first on all five
|
||||
pages): sets `window.BOR_BRAND` synchronously (default "Brain of
|
||||
Reese"), fetches `/api/config` (`cache: "no-store"`), and applies the
|
||||
name — `document.title` (global replace of the literal), every
|
||||
`.brand-text` (bold split: a name starting "Brain of " bolds the
|
||||
remainder, else plain; the name is HTML-escaped), every text node and
|
||||
the `aria-label` / `placeholder` / meta-`content` attributes containing
|
||||
the literal; a fetch failure falls back to the default (console.warn,
|
||||
the page never breaks).
|
||||
3. The JS hard-codes move off the literal: `app.js` (status labels, the
|
||||
typing label, the elapsed-hint aria) + `document.js` (page titles) read
|
||||
`window.BOR_BRAND` (default "Brain of Reese" if unset).
|
||||
4. `Containerfile`: an esbuild line for brand.js next to the others.
|
||||
5. The story E2E boots its **own** app instance with `BOR_APP_NAME`
|
||||
overridden (distinct port; the shared conftest server keeps the default
|
||||
name so the existing title assertions stay green) and asserts
|
||||
title/brand/greeting/aria/label.
|
||||
6. `.env.example` + README document `BOR_APP_NAME` (what it affects, the
|
||||
default, the bold-split rule).
|
||||
7. Unit + integration green, `app/` coverage >90%, story E2E green in
|
||||
isolation, ruff + pyright clean, one `--no-gpg-sign` commit.
|
||||
|
||||
## Playwright Mapping Rule
|
||||
`tests/e2e/test_configurable_brand.py` — one story, one file, run in
|
||||
isolation: the overridden-name instance shows the new brand in the title,
|
||||
the header `.brand-text` (with the bold split), the empty-state greeting,
|
||||
the messages aria-label, and the chat status label; the default-name
|
||||
shared server still renders "Brain of Reese" (the no-op regression).
|
||||
Reference in New Issue
Block a user