# 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.