# Task 04 — Frontend Tool-Line Rendering for the New Names **Phase:** `70_harness_aligned_tools` · **Story:** `.agents/user_stories/agent-document-tools.md` ## Objective Point the tool-line rendering at the new `ls`/`read`/`grep` names while keeping **legacy saved chats** (persisted with the old `list_documents` / `read_document` / `search_documents` names, phase 14 persistence) rendering exactly as before — no migration. ## Work 1. `frontend/assets/app.js` — `appendToolLine(wrap, name, argument)`: - New branches: `read` + argument → `📄 Reading argument`; `grep` + argument → `🔎 Searching for argument`; `ls` + argument (scoped) → `🔎 Listing documents in argument`; `ls` unscoped → `🔎 Listing documents`. - **Legacy branches stay**: `read_document` (Reading), `search_documents` (Searching for), everything else (Listing documents) — persisted turns from before this phase must render unchanged. (Implementation: a name→kind map covering both generations, or explicit if-chains — executor's choice; the pins below define the contract.) - All arguments through `textContent` only (the existing "path/pattern is data, never markup" discipline). - Update the section docstring (phase 37 reference + a phase-70 note: names remapped to the harness surface; legacy names still render). 2. `frontend/assets/shared.js` — the shared-chat tool-line helper (currently `read_document` + argument → `📄 Reading …`, else `🔎 Listing documents`): add the new names (`read` → Reading, `grep` → Searching for with `` argument, `ls` → Listing documents, `ls` + argument → Listing documents in `…`), keep the legacy `read_document` branch, keep `textContent`-only population. Update its docstring comment. 3. `tests/unit/test_frontend_tool_states.py` — update/add pins (the source-string house pattern): - `app.js` carries branches for `read`, `grep`, `ls` (with/without argument) and still carries `read_document` / `search_documents` (legacy render). - `shared.js` carries the `read` / `grep` / `ls` handling and the legacy `read_document` branch. - Every argument population goes through `textContent` (no `innerHTML` on tool lines). - The old-only copy pins (e.g. exact "Listing documents" string for the default case) stay green. ## Testing & Quality - Unit: `tests/unit/test_frontend_tool_states.py` pins above. - Coverage: no `app/` code in this task — the **>90%** gate stays green as part of the full suite run. ## Completion Criteria - [ ] `uv run pytest tests/unit/test_frontend_tool_states.py -v --no-cov` green. - [ ] A persisted chat containing old tool names renders Reading/Searching/Listing lines exactly as before (legacy branches pinned). - [ ] `uv run ruff check . && uv run pyright` clean.