Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H7LwYgJfpkbLCTeiAf8U4A
82 lines
9.1 KiB
Markdown
82 lines
9.1 KiB
Markdown
This file captures tasks which derive from roadmap tasks (unfinished, deferred), bugs encountered during usage and feature requests/improvements which are not fitting directly in the roadmap.
|
||
Always sort by priority and put tasks blocked by other tasks/features at the dedicated section.
|
||
When working on a task, check for other, similar tasks that could be resolved on the way.
|
||
Use following pattern to classify tasks: TYPE/SCOPE
|
||
Where TYPE could be BUG, FEAT, PERF, CHORE and SCOPE could be UX, UI, FLOW, NODE, API, INFRA, DOCS appended by MOBILE if only for mobile use case.
|
||
Don't write temporary reasons for deferring a task in the task description (only strategical reasons should be noted).
|
||
Deferring because out of scope is fine, but don't mention deferring than.
|
||
|
||
`Deferred` holds what stays open on purpose, each with the condition that
|
||
should reopen it.
|
||
|
||
## Open
|
||
|
||
### Connector write paths
|
||
|
||
Needs someone watching the real hardware, so it is not a background task. This
|
||
is what M4 still waits on, together with porting the flows.
|
||
|
||
- FEAT/NODE: the connectors only read. Enable the write paths with someone watching: WF-RAC `setAirconStat` (needs an operatorId registered with the unit first, which is itself a write) and Art-Net `transmit`.
|
||
- FEAT/NODE: the second WF-RAC unit (the one Node-RED addresses with operatorId "0") closes the connection on an anonymous read. It likely wants an account registered; the first unit answers without one.
|
||
- CHORE/NODE: `wfrac` reports `mode` as "unknown" while the unit is off, because the mode bits hold a value outside the known set. Faithful to the reference decoder, but "off" would read better.
|
||
|
||
### Bugs found while building the screens
|
||
|
||
- BUG/API: `POST /alerts/test/{channel}` always answers 200. `AlertManager.send()` catches and logs every delivery failure, so the alerts screen's Test button cannot tell a working channel from a broken one — the one thing it exists for. Let `send()` raise or return a result on the test path.
|
||
- BUG/API: `RedisWorkQueue.stats()` hard-codes `"parked": 0`, so held or stranded work never shows on the health endpoint. This is why a rebuild stranding parked items went unnoticed until it was looked for.
|
||
- BUG/FLOW: deleting a flow leaves its `pipeline:{flow}.*` Redis keys behind, and renaming one does not migrate them — the live instance carries `pipeline:__history__:dashboar.test` beside the correct `dashboard.test`. One cleanup on the delete/rename path covers both.
|
||
- CHORE/API: revoking an OAuth client does not invalidate access tokens already issued; they are stateless JWTs valid up to `MCP_TOKEN_EXPIRE_MINUTES`. Immediate revocation means `app/mcp/http.py` checking the client row still exists.
|
||
- CHORE/FLOW: `Pipeline.trigger`'s docstring says a paused flow still publishes so the value shows on the canvas. True only without a queue; with one the item parks before `apply_outputs` and nothing shows. Docstring and behaviour disagree.
|
||
- CHORE/FLOW: `_to_messages` keeps its `if not retval: return None` guard ahead of the new type check, so a falsy non-dict return (`0`, `""`, `[]`) is still silently "no output" rather than the named error. Deliberate for now; worth a decision.
|
||
- CHORE/FLOW: `WorkItem.kind == "node"` ("executes exactly one node") was documented but never implemented. If a run-one-node item is wanted, it still needs writing.
|
||
|
||
### Dashboard follow-ups
|
||
|
||
- BUG/UI: ensure dashboard wallpanel (read-only) links hot reload automatically on dashboard changes
|
||
- BUG/UI: shrinking the canvas silently clips whatever now falls past its bottom edge. `maxRows` only constrains a new drag, not a stored placement, so nothing warns and nothing offers to reflow.
|
||
- CHORE/UX: dropping a widget also selects it, which opens its panel — which rescales the canvas the instant you let go. Correct, but it lurches; either leave the panel closed on a drag-release or animate the scale.
|
||
- CHORE/UI: `ROW_HEIGHT` is a fixed 80px while column width follows the canvas, so a 1920-wide panel at 12 columns has 160×80 cells. If that reads too wide, the row height could derive from the canvas too.
|
||
- FEAT/UI: multi-page and multi-section dashboards have no UI. The backend has `PageDef`/`SectionDef` and rename; the editor only ever edits `sectionsOf(page)[0]`, so nothing can create a second page.
|
||
- FEAT/UI: only `layout.lg` is ever written. Below `lg` the view stacks widgets full width in CSS, so `md`/`sm` stay unused until a per-breakpoint editor exists.
|
||
- PERF/UI: `ChartWidget` re-joins the whole table on every live value. Fine at IoT rates; at `HISTORY_CAP` × 5 series it should append into a ring buffer.
|
||
- CHORE/UI: opening edit mode on a dashboard whose widgets predate placement writes the migrated positions immediately, bumping the version once.
|
||
- CHORE/API: no backend test for the `WidgetDef` dtype validator or `columns`.
|
||
|
||
### Flow editor follow-ups
|
||
|
||
- PERF/FLOW: every save rebuilds the whole pipeline. Fine at the current flow count; rebuild only the touched flow when it starts to show.
|
||
- CHORE/API: `POST /flows/{name}/rename` is no longer reachable from the UI. A flow's title is what the panel edits, matching how nodes work; the canonical name is fixed at creation, so either the endpoint goes or renaming comes back deliberately.
|
||
- BUG/UI: `renderedNodes` overwrites xyflow's own `selected` flag with `id === selectedId`, so a box-selection of several nodes is invisible even though delete and copy act on all of them.
|
||
- CHORE/UI: ⌘C/⌘V `preventDefault` on the canvas blocks the native clipboard there (fields are guarded). The node clipboard is `localStorage`, so it does not cross browsers or profiles.
|
||
- PERF/UI: `useParamSuggestions` fetches every flow's detail to build the suggestion list. An aggregate endpoint if an installation ever has many flows.
|
||
- CHORE/UX: the derived-cron chip also appears on the delay node, where `interval` is a rate limit rather than a schedule. May want it inject-only.
|
||
- CHORE/UX: free-form params (python nodes) get no suggestions, since there is no schema to key them off.
|
||
|
||
### Infrastructure
|
||
|
||
- CHORE/INFRA: the `playwright` compose service cannot reach `api.localhost`, so `make verify-docker` is the only containerised route. (Native Playwright now works: the headless-shell libs are installed. Only the headless shell is downloaded — `--headed` still needs `bunx playwright install chromium`, and there is no emoji font, so 👋 renders as tofu in screenshots.)
|
||
- CHORE/DOCS: `app/development.md` still presents `docker compose watch` as the dev flow; it and the Makefile targets disagree about how the stack is started.
|
||
- CHORE/UI: `make lint-frontend` is `biome check --write --unsafe ./` — a lint target that rewrites the whole tree rather than checking it. A checking target plus a separate `format` would be safer.
|
||
- CHORE/UI: `routeTree.gen.ts` was generated by an older router version than the installed one; the next build reorders ~130 lines regardless of who touched it.
|
||
- CHORE/UI: the alerts screen duplicates the backend's `ALERTING_EVENTS`; the chooser drifts if the backend set grows. A rule with nothing ticked covers everything, so it fails soft.
|
||
- CHORE/UI: `tests/runtime.spec.ts` still calls the home page "the dashboard" (`dashboard-flow-row`), which now collides with the dashboards feature.
|
||
|
||
## Deferred
|
||
|
||
Open on purpose. Each names what should bring it back.
|
||
|
||
- PERF/UI: the app's entry chunk exceeds the warning threshold. React Flow and Monaco are already lazy; a manualChunks split measured no better, so this needs route-level work on the shell rather than chunking config.
|
||
- PERF/UI: the Monaco chunk is 2.6 MB. It only loads when a node panel opens, but the editor could be trimmed further or swapped for CodeMirror if that becomes a problem.
|
||
- CHORE/API: node source saves carry no version precondition, so two clients editing the same node's code are last-writer-wins. The flow document is what the optimistic lock protects; code files would need their own, and an exact-match one produces false conflicts against a single client's own interleaved flow and source saves. Revisit with the M5 multi-user work.
|
||
- CHORE/FLOW: shared node sources bypass the draft/publish split. Editing one writes the library copy and reloads immediately, since the code is not any single flow's to hold back. Deliberate, but it means a shared node is the one thing publish does not gate.
|
||
- CHORE/INFRA: `requires-python` is capped below 3.14 because the MCP SDK wants a newer starlette there than the pinned `sentry-sdk<2` allows. Lift the cap when sentry-sdk moves to 2.x.
|
||
- CHORE/INFRA: `bun run --filter frontend build` fails on this workspace with `crypto.hash is not a function` — Vite 7 wants Node 20.12+ and the host has 18. The Docker image builds fine, so it only bites local bundling; `bunx tsc` still type-checks.
|
||
- FEAT/UI: an endpoint's edge routes straight across the graph, so it can pass behind a node that sits between the lane and the node it wires to. Readable, but a routed edge would be tidier.
|
||
|
||
## Blocked
|
||
|
||
- CHORE/INFRA: `bun install` inside the frontend Docker build intermittently fails with
|
||
"Fail extracting tarball" for several packages at once, and succeeds on a plain rebuild.
|
||
It looks like concurrent extraction under memory pressure. Pin down or retry in the
|
||
Dockerfile if it starts costing CI time.
|