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,45 @@
|
||||
# Phase 66 — History Tab Copy: Auto-Save, No Save Button
|
||||
|
||||
**Source:** `TODO.md` L4 — "Update the history tab - the text still reads like there's a save button. There isn't anymore, every chat is saved."
|
||||
**Story:** n/a (TODO-derived — owner roadmap confirmation 2026-09-01)
|
||||
**Context:** Verified copy inventory (audited 2026-09-01, line numbers as of this writing):
|
||||
- `frontend/history.html` L6 — `<meta name="description" content="Saved chats — every conversation you saved, one click back.">` ("you saved" implies the manual action).
|
||||
- `frontend/history.html` L106–109 — the `.page-sub`: "Every conversation you pressed <strong>Save</strong> on — newest activity first. Click a title to return to that chat." — the primary offender: it names a Save button that has not existed since phase 55 (owner-locked A2, 2026-08-31: every conversation auto-saves via `app.js` `persistConversation`; pinned by `test_save_share_ux.py::test_anonymous_auto_save`).
|
||||
- `frontend/history.html` L163 — the empty-table row (inside `#history-empty-row`, `hidden` until `frontend/assets/history.js` reveals it on a 0-row fetch): "No saved chats yet — finish a conversation and press <strong>Save</strong> in the chat."
|
||||
- STAYS AS-IS (verified accurate — "saved" as a STATE, not a button): the `<h1>Saved chats</h1>` (L105), the anonymous gate copy (L123–128: "Sign in to view your saved chats" / "Saved conversations are admin-only…"), the table caption, and the `history.js` aria-labels ("Delete saved chat: …", "Unshare saved chat: …").
|
||||
- No existing test pins any of the three offending strings (verified: "pressed Save" / "press Save" / "every conversation you saved" appear nowhere in `tests/`).
|
||||
- `.agents/` is tracked and committed (AGENTS.md rule 8) — the phase commit stages `.agents/` + `frontend/` + `tests/`.
|
||||
|
||||
## Objective
|
||||
Every user-visible string on the History tab describes the app as it works TODAY: conversations save themselves automatically — there is no Save button to press. The exact replacement copy is locked below.
|
||||
|
||||
## Dependencies
|
||||
- `65_bottom_chat_actions` (todo, preceding — no functional dependency; ordering by number)
|
||||
|
||||
## Tasks
|
||||
1. `01_history_page_copy.md` — rewrite the three strings in `frontend/history.html` (meta description, page-sub, empty row) to the locked auto-save copy.
|
||||
2. `02_tests_and_commit.md` — unit text pins + dedicated E2E `tests/e2e/test_history_copy.py` (run in isolation) + regression pass + one atomic commit.
|
||||
|
||||
## Testing & Quality
|
||||
- Unit pins (house style, `tests/unit/test_stale_ui_copy.py` pattern — read `frontend/history.html` as text): the old literals are GONE, the locked replacements are present.
|
||||
- E2E (mandatory, house rule): `tests/e2e/test_history_copy.py`, run in isolation against the shared conftest server (DB up) — an admin sees the ACTUAL page (gate hidden, table rendered): the rendered page-sub and empty-row texts match the locked copy, and no rendered page text reads like a Save button exists.
|
||||
- Coverage: **>90%** on `app/` (validate.sh gate — no `app/` change, the gate stays green at its current level).
|
||||
|
||||
## Completion Criteria
|
||||
- [ ] `frontend/history.html` contains none of: "you pressed <strong>Save</strong>", "press <strong>Save</strong>", "every conversation you saved" — and carries the three locked (A3) strings.
|
||||
- [ ] The rendered History page (admin, empty table) shows the locked page-sub and empty-row text; the `<h1>Saved chats</h1>` and the gate copy are untouched.
|
||||
- [ ] `uv run pytest` green; coverage TOTAL >90%; `uv run ruff check . && uv run pyright` clean.
|
||||
- [ ] `uv run pytest tests/e2e/test_history_copy.py -v --no-cov` green in isolation (DB up).
|
||||
- [ ] Regression E2E suites green in isolation: `test_chat_history.py`, `test_stale_saved_chats.py`.
|
||||
- [ ] One `--no-gpg-sign` commit; phase dir moved to `.agents/phases/complete/`.
|
||||
|
||||
## Locked decisions
|
||||
- **Owner-locked (2026-09-01, roadmap confirmation, A3):** exact replacement copy —
|
||||
- meta description (`history.html` L6): `Saved chats — every conversation is saved automatically, one click back.`
|
||||
- page-sub (`history.html` L106–109): `Every conversation is saved automatically — newest activity first. Click a title to return to that chat.` (the `<strong>Save</strong>` emphasis is retired with the button — no inline emphasis in the replacement)
|
||||
- empty row (`history.html` L163): `No saved chats yet — start a conversation and it will be saved automatically.`
|
||||
|
||||
## Commit
|
||||
```bash
|
||||
git add .agents/ frontend/ tests/ && git commit --no-gpg-sign -m "fix(web): history tab copy — every chat saves automatically, there is no Save button"
|
||||
```
|
||||
@@ -0,0 +1,30 @@
|
||||
# Task 01 — Rewrite the History-tab copy to the auto-save model
|
||||
|
||||
**Phase:** `66_history_auto_save_copy` · **Source:** `TODO.md:4` — "Update the history tab - the text still reads like there's a save button. There isn't anymore, every chat is saved."
|
||||
**Story:** n/a (TODO-derived)
|
||||
|
||||
## Objective
|
||||
The three offending strings in `frontend/history.html` describe how BOR used to work (a Save button the visitor pressed). They become the locked (A3) auto-save copy — accurate, same house voice, no new markup.
|
||||
|
||||
## Work
|
||||
1. `frontend/history.html` — three exact replacements (markup otherwise byte-identical):
|
||||
- L6 — the meta description content becomes exactly (A3):
|
||||
`Saved chats — every conversation is saved automatically, one click back.`
|
||||
- L106–109 — the `.page-sub` becomes exactly (A3) — the `<strong>Save</strong>` emphasis is retired with the button; keep the `<p class="page-sub">` element, the indentation, and the single paragraph:
|
||||
`Every conversation is saved automatically — newest activity first. Click a title to return to that chat.`
|
||||
- L163 — the `#history-empty-row` cell text becomes exactly (A3):
|
||||
`No saved chats yet — start a conversation and it will be saved automatically.`
|
||||
(the `colspan="6"`, the `hidden` attribute, and the row's id are untouched — `history.js` reveals this exact row on a 0-row fetch).
|
||||
2. Leave UNTOUCHED (verified accurate — "saved" as a state, not a button): the `<h1>Saved chats</h1>` (L105), the anonymous gate copy (L123–128), the table caption, every other row/cell in `history.html`, and everything in `frontend/assets/history.js` (its "saved chat" aria-labels are state language).
|
||||
3. No CSS, no JS, no other page — the TODO scopes this to the history tab; any OTHER page found to name a Save button is noted in the commit body as follow-up material, not fixed here.
|
||||
|
||||
## Testing & Quality
|
||||
- `uv run pytest` green (unit + integration — no Python changed); `uv run ruff check . && uv run pyright` clean.
|
||||
- Coverage TOTAL **>90%** (validate.sh gate — unchanged, no `app/` code).
|
||||
- Quick manual sanity (optional, before the pins land in task 02): `grep -n "Save" frontend/history.html` — the only remaining case-sensitive "Save" hits are the retired-comment-free state strings ("Saved chats" h1, "Saved conversations are admin-only", "saved chats" table aria-label/caption).
|
||||
|
||||
## Completion Criteria
|
||||
- [ ] `grep -c "pressed <strong>Save</strong>\|press <strong>Save</strong>\|every conversation you saved" frontend/history.html` → 0.
|
||||
- [ ] The three locked (A3) strings are present in `frontend/history.html` (meta, page-sub, empty row), each exactly once.
|
||||
- [ ] The h1, the gate section (L119–129), and `history.js` are byte-identical to before this task.
|
||||
- [ ] `uv run pytest` green; lint + types clean; coverage >90%.
|
||||
@@ -0,0 +1,41 @@
|
||||
# Task 02 — Unit pins + dedicated E2E + regression pass + atomic commit
|
||||
|
||||
**Phase:** `66_history_auto_save_copy` · **Source:** `TODO.md:4` — "Update the history tab - the text still reads like there's a save button. There isn't anymore, every chat is saved."
|
||||
**Story:** n/a (TODO-derived)
|
||||
|
||||
## Objective
|
||||
The new auto-save copy is pinned at two layers so it can never silently regress — unit text pins (no browser, house style) and one dedicated Playwright suite asserting what a signed-in admin actually SEES on the History tab — then one atomic commit.
|
||||
|
||||
## Work
|
||||
1. `tests/unit/test_history_copy.py` (NEW — house pattern `tests/unit/test_stale_ui_copy.py`: read `frontend/history.html` as text, assert substrings):
|
||||
- Negative pins (GONE): `"you pressed <strong>Save</strong>"`, `"press <strong>Save</strong> in the chat"`, `"every conversation you saved"`.
|
||||
- Positive pins (PRESENT, exactly once each): the three locked (A3) strings — `Saved chats — every conversation is saved automatically, one click back.`, `Every conversation is saved automatically — newest activity first. Click a title to return to that chat.`, `No saved chats yet — start a conversation and it will be saved automatically.`
|
||||
- State-language survivors (PRESENT, proving no over-deletion): `<h1>Saved chats</h1>`, `Sign in to view your saved chats`, `Saved conversations are admin-only`.
|
||||
2. `tests/e2e/test_history_copy.py` (NEW — one phase, one file, run in isolation, DB up; shared conftest server, default env):
|
||||
- Setup (house patterns from `tests/e2e/test_chat_history.py`): `_reset_db` with the TRUNCATE extended to include `saved_chats` (so the table is genuinely empty), `login(page, app_url, next="/history.html")` from `tests/e2e/auth_helpers.py`.
|
||||
- Admin view of an empty History tab:
|
||||
- the anonymous gate is hidden (`#history-gate` hidden — the login worked);
|
||||
- `#history-empty-row` is revealed (visible) and its textContent == the locked (A3) empty-row string;
|
||||
- the `.page-sub` innerText == the locked (A3) page-sub string (whitespace-normalized compare);
|
||||
- `document.querySelector('meta[name="description"]').content` == the locked (A3) meta string;
|
||||
- the no-button contract: `document.body.innerText` matches NEITHER `/press(ed)?\s+save/i` NOR `/save\s+button/i` — while the `<h1>` still reads "Saved chats" (asserted present, so the scan cannot pass by deleting the heading);
|
||||
- no `#save-chat-btn` anywhere (phase 55 A2 — the control is gone from the app, not just the copy).
|
||||
- Determinism: all assertions are settled-state (static HTML + the one 0-row fetch); Playwright `expect` retries ride out the table load.
|
||||
3. Regression E2E (each in isolation, DB up): `test_chat_history.py` (the row actions + restore flow on this page), `test_stale_saved_chats.py` (the stale pills + regenerate flow).
|
||||
4. One atomic commit (`.agents/` tracked — AGENTS.md rule 8):
|
||||
```bash
|
||||
git add .agents/ frontend/ tests/ && git commit --no-gpg-sign -m "fix(web): history tab copy — every chat saves automatically, there is no Save button"
|
||||
```
|
||||
Commit body: the verification read-through outcome from task 01 (the three replacements; h1/gate/history.js untouched) — one line each.
|
||||
|
||||
## Testing & Quality
|
||||
- `uv run pytest` green (unit + integration); coverage TOTAL **>90%** (validate.sh gate — no `app/` change).
|
||||
- `uv run pytest tests/e2e/test_history_copy.py -v --no-cov` green in isolation (DB up) — run it after the unit pins pass.
|
||||
- `uv run ruff check . && uv run pyright` clean (the new test files included).
|
||||
|
||||
## Completion Criteria
|
||||
- [ ] `tests/unit/test_history_copy.py` + `tests/e2e/test_history_copy.py` exist and are green (E2E in isolation, DB up).
|
||||
- [ ] The two regression E2E suites are green in isolation.
|
||||
- [ ] Full suite green, coverage >90%, lint + types clean.
|
||||
- [ ] Exactly one new commit on `main`, staging `.agents/ frontend/ tests/` only, `--no-gpg-sign`.
|
||||
- [ ] Phase dir moved to `.agents/phases/complete/66_history_auto_save_copy/` (`.agents/` stays tracked and committed).
|
||||
Reference in New Issue
Block a user