chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-03-29: - T01: todo → done
This commit is contained in:
180
workplans/CUST-WP-0030-dashboard-entity-list-ux.md
Normal file
180
workplans/CUST-WP-0030-dashboard-entity-list-ux.md
Normal file
@@ -0,0 +1,180 @@
|
||||
---
|
||||
id: CUST-WP-0030
|
||||
type: workplan
|
||||
title: "Dashboard Entity List UX"
|
||||
domain: custodian
|
||||
repo: the-custodian
|
||||
status: todo
|
||||
owner: custodian
|
||||
topic_slug: custodian
|
||||
created: "2026-03-29"
|
||||
updated: "2026-03-29"
|
||||
state_hub_workstream_id: "9d8e1c33-2067-4593-a5d8-d28dda3b1d21"
|
||||
---
|
||||
|
||||
# Dashboard Entity List UX
|
||||
|
||||
## Goal
|
||||
|
||||
Make every entity table in the dashboard navigable and self-documenting.
|
||||
Two new UI primitives:
|
||||
|
||||
1. **REF cell** — running row number (1-based); click copies a deep-link
|
||||
(`<origin>/data/<recordtype>/<id>`) to the clipboard; double-click opens
|
||||
the link in a new tab.
|
||||
2. **Name cell** — second column, titled after the record type; shows the
|
||||
entity name truncated at 80 chars with full-name tooltip on hover.
|
||||
|
||||
Support these cells with a landing page (`/data/[type]/[id]`) that renders
|
||||
a key-value view of every field in the record, each key decorated with a
|
||||
`<help-tip>` (one-sentence description + link to the relevant help-doc
|
||||
section).
|
||||
|
||||
Pilot all three features on the **Token Cost** page, then extend to other
|
||||
entity tables in later workplans.
|
||||
|
||||
## Background
|
||||
|
||||
Current entity tables show only IDs (often truncated UUIDs) with no way to
|
||||
navigate to a record detail view or discover what a field means. For a
|
||||
person reviewing agent activity the tables are hard to parse. Providing a
|
||||
running reference number, an entity name column, and a click-through detail
|
||||
page substantially lowers the cognitive load.
|
||||
|
||||
The `<help-tip>` custom element already exists in
|
||||
`src/components/help-tip.js` and is used on several pages — the field-help
|
||||
registry will reuse it as the rendering layer.
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
The pilot targets the Token Cost page. Observable Framework supports
|
||||
parameterised pages via `[param].md` file naming. The API already exposes
|
||||
`GET /token-events/?task_id=…` and `GET /token-events/summary/`; a
|
||||
per-record GET endpoint is needed before the landing page can work.
|
||||
|
||||
### Component layer
|
||||
- `src/components/ref-cell.js` — exports `refCell(index, type, id)` that
|
||||
returns an `HTMLElement` with click/dblclick handlers.
|
||||
- `src/components/field-help.js` — exports `FIELD_HELP` map and
|
||||
`fieldRow(key, value)` helper that wraps the key in `<help-tip>`.
|
||||
|
||||
### API layer
|
||||
- `GET /token-events/{event_id}` — returns `TokenEventRead` for a single
|
||||
event; needed by the landing page data loader.
|
||||
|
||||
### Dashboard pages
|
||||
- `src/data/token-events/[id].json.py` — data loader that calls the new
|
||||
single-event endpoint; returns JSON for the landing page.
|
||||
- `src/data/token-events/[id].md` — landing page: key-value table, each
|
||||
row built with `fieldRow()`.
|
||||
- `src/token-cost.md` — updated: REF column (refCell) and Name column
|
||||
added to By Repo, By Workplan, and Top Tasks tables.
|
||||
|
||||
## Tasks
|
||||
|
||||
```task
|
||||
id: T01
|
||||
title: "REF cell component"
|
||||
status: done
|
||||
priority: high
|
||||
description: >
|
||||
Create src/components/ref-cell.js.
|
||||
Export refCell(index, recordType, id) → HTMLElement.
|
||||
- Displays 1-based index as monospace text, cursor:pointer.
|
||||
- Single click: copies `${location.origin}/data/${recordType}/${id}` to
|
||||
clipboard; briefly flashes "Copied!" as a transient tooltip using the
|
||||
existing help-tip positioning pattern.
|
||||
- Double click: window.open(deeplink, '_blank').
|
||||
- No external dependencies; plain DOM.
|
||||
state_hub_task_id: "8ee527cf-436b-4bab-bdb8-406314a38d99"
|
||||
```
|
||||
|
||||
```task
|
||||
id: T02
|
||||
title: "GET /token-events/{event_id} endpoint"
|
||||
status: todo
|
||||
priority: high
|
||||
description: >
|
||||
Add GET /token-events/{event_id} to api/routers/token_events.py.
|
||||
Returns TokenEventRead (already defined in schemas/token_event.py).
|
||||
404 if not found.
|
||||
No migration needed.
|
||||
Add a test in tests/test_token_events.py: get by id → 200, unknown id → 404.
|
||||
state_hub_task_id: "02c27d25-d744-4da0-9bcb-b40ada54d5a5"
|
||||
```
|
||||
|
||||
```task
|
||||
id: T03
|
||||
title: "Field-help registry"
|
||||
status: todo
|
||||
priority: medium
|
||||
description: >
|
||||
Create src/components/field-help.js.
|
||||
Export FIELD_HELP: a plain object keyed by field name.
|
||||
Each entry: { label, description, doc } — matches help-tip attributes.
|
||||
Cover at minimum all TokenEventRead fields:
|
||||
id, tokens_in, tokens_out, tokens_total, task_id, workstream_id,
|
||||
repo_id, session_id, model, agent, ref_type, ref_id, note, created_at.
|
||||
Export fieldRow(key, value) → HTMLElement (<tr>) that wraps key in a
|
||||
<help-tip> (or plain <td> if key is not in FIELD_HELP) and value in a
|
||||
second <td>.
|
||||
Import HelpTip from ./help-tip.js to ensure the custom element is
|
||||
registered.
|
||||
state_hub_task_id: "7721d884-bd70-459f-b36d-450d69aac549"
|
||||
```
|
||||
|
||||
```task
|
||||
id: T04
|
||||
title: "Token-event landing page"
|
||||
status: todo
|
||||
priority: medium
|
||||
description: >
|
||||
Create two files:
|
||||
1. src/data/token-events/[id].json.py — data loader.
|
||||
Reads `id` from argv[1]; calls GET /token-events/{id};
|
||||
exits 1 if 404 so Observable renders an error page.
|
||||
2. src/data/token-events/[id].md — landing page.
|
||||
Imports fieldRow from components/field-help.js.
|
||||
Fetches FileAttachment("token-events/{id}.json").json().
|
||||
Renders an HTML <table> with one row per field using fieldRow().
|
||||
Title: "Token Event · {id.slice(0,8)}…".
|
||||
Back link: "<a href='/token-cost'>← Token Cost</a>".
|
||||
state_hub_task_id: "dc63746d-74b3-434a-925c-1cead480198f"
|
||||
```
|
||||
|
||||
```task
|
||||
id: T05
|
||||
title: "Apply REF and Name columns to Token Cost page"
|
||||
status: todo
|
||||
priority: high
|
||||
description: >
|
||||
Update src/token-cost.md.
|
||||
Import refCell from ./components/ref-cell.js.
|
||||
For each of the three entity tables (By Repo, By Workplan, Top Tasks):
|
||||
- Prepend a "REF" column using refCell(i+1, recordType, row.id).
|
||||
Record types: "repos" for By Repo (using repo_id), "workstreams" for
|
||||
By Workplan (using scope_id), "token-events" for Top Tasks (using
|
||||
task_id — note: links to the task landing page, not a token event page,
|
||||
until T04 is done; use recordType "tasks").
|
||||
- Add a Name column as the second data column:
|
||||
- By Repo: repo_slug (no truncation needed, slugs are short)
|
||||
- By Workplan: scope_id displayed as first 8 chars + "…" (unchanged)
|
||||
→ replace with workstream title if available; for now show scope_id
|
||||
truncated to 36 chars with full UUID tooltip.
|
||||
- Top Tasks: task_id truncated to 80 chars with full-id tooltip.
|
||||
Keep all existing columns unchanged.
|
||||
state_hub_task_id: "3225cc6c-2574-41e9-b8fd-e5e703a9dd7c"
|
||||
```
|
||||
|
||||
```task
|
||||
id: T06
|
||||
title: "Consistency gate and docs update"
|
||||
status: todo
|
||||
priority: low
|
||||
description: >
|
||||
1. Run `cd state-hub && make test` — all token_events tests must pass.
|
||||
2. Run `make fix-consistency REPO=the-custodian`.
|
||||
3. Add a one-paragraph entry to src/docs/reference.md describing the
|
||||
/data/<type>/<id> URL scheme and the REF column convention.
|
||||
state_hub_task_id: "107cb5bb-ff0c-4c97-af04-2cdeff11f0b2"
|
||||
```
|
||||
Reference in New Issue
Block a user