Skip to content

fix(board): unwrap Hermes kanban task-detail envelope so the drawer renders#1014

Merged
thinmintdev merged 3 commits into
mainfrom
fix/board-drawer-wire-shape
Jul 4, 2026
Merged

fix(board): unwrap Hermes kanban task-detail envelope so the drawer renders#1014
thinmintdev merged 3 commits into
mainfrom
fix/board-drawer-wire-shape

Conversation

@thinmintdev

Copy link
Copy Markdown
Contributor

Problem

The hal0 operator-board task drawer shows a blank / mis-populated detail view while the Hermes dashboard shows the same task in full. Reported against t_37a898aa:

Field Hermes hal0 (before)
status done triage (default)
assignee / priority / workspace / created-by populated blank / 0 / unassigned
description full text blank
events kind + time + payload JSON kind label only
worker log 2.3 KB of run output "no worker log yet"
run history state + dur + msg @homelab only

Root cause

A wire-shape mismatch in the UI normaliser, not the proxy — hal0-api forwards /tasks/{id} verbatim (board.py), so both UIs read the same store.

The Hermes kanban plugin returns two shapes:

  • GET /board → a flat task row per column
  • GET /tasks/{id} → an envelope: {task, comments, events, attachments, links, runs} with snake_case item fields (created_at, payload, outcome, summary) and epoch-second timestamps

normaliseTask() read scalars off the top level, so everything under .task fell to its default (hence status → "triage") and only the top-level arrays survived — with the wrong per-item field names (created_atat, payloadjson, outcomestate, summarymsg). The worker-log hook only understood array / {entries}, never the {content} shape the plugin actually returns.

Fix (ui/src/api/hooks/useBoard.ts + task-drawer.jsx)

  • normaliseTask — unwrap raw.task for scalars; pull comments/events/runs and links → deps off the envelope. Falls back to the flat row and to already-normalised camelCase objects (the optimistic-update path re-feeds them), so it's backward-compatible and idempotent.
  • normaliseEvent / normaliseRun / normaliseComment + relTime / durLabel helpers remap the item fields (created_at → at as "20m ago", payload → json, outcome/status → state, started/ended → dur, summary → msg, workspace_path → workspace).
  • useBoardTaskLog — accept {content: "<text>"} (split into per-line entries).
  • task-drawer.jsx — read t.body (the normaliser never emitted t.desc).

Tests

  • Added an e2e regression test that drives the drawer with the real envelope wire shape and asserts desc / event payload / run state / worker-log all render. The pre-existing fixtures encode the flat shape the plugin never emits for detail — which is why CI stayed green while production was blank.
  • npm run typecheck ✅ · playwright test board-drawer-v3.spec.ts22 passed (all prior flat-fixture tests still green, proving no regression).

🤖 Generated with Claude Code

thinmintdev and others added 2 commits July 3, 2026 05:31
…enders

The operator-board task drawer showed a blank/mis-populated detail view
(status defaulting to "triage", no description/assignee, event rows with no
timestamp or payload, empty worker log, bare run rows) while the Hermes
dashboard showed the same task in full.

Root cause is a wire-shape mismatch in the UI normaliser, not the proxy
(hal0-api forwards /tasks/{id} verbatim). The Hermes kanban plugin returns
TWO shapes: GET /board embeds a flat task row per column, but GET /tasks/{id}
WRAPS the row in an envelope `{task, comments, events, attachments, links,
runs}` with snake_case item fields (created_at/payload/outcome/summary) and
epoch-second timestamps. normaliseTask() read scalars off the top level, so
every field under `.task` fell to its default and only the top-level arrays
survived — with the wrong per-item field names.

- normaliseTask: unwrap `raw.task` for scalars; pull comments/events/runs and
  `links`→deps off the envelope (falling back to the flat row + already-
  normalised camelCase objects the optimistic-update path re-feeds).
- Add normaliseEvent/normaliseRun/normaliseComment + relTime/durLabel helpers:
  created_at→at (as "20m ago"), payload→json, outcome/status→state,
  started/ended→dur, summary→msg, workspace_path→workspace, created_at→created.
- useBoardTaskLog: accept the `{content: "<text>"}` log shape (split into
  per-line entries), not just array/`{entries}` — this is why the worker log
  was always "no worker log yet".
- task-drawer: read `t.body` (the normaliser never emitted `t.desc`).
- e2e: add a regression test that drives the drawer with the REAL envelope
  wire shape (the existing fixtures encode the flat shape the plugin never
  emits, which is why CI stayed green while production was blank).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@thinmintdev thinmintdev enabled auto-merge (squash) July 3, 2026 09:39
@thinmintdev thinmintdev merged commit ec2a498 into main Jul 4, 2026
3 checks passed
@thinmintdev thinmintdev deleted the fix/board-drawer-wire-shape branch July 4, 2026 08:30
thinmintdev added a commit that referenced this pull request Jul 4, 2026
…ce + logs/memory fixes

Bumps version 0.8.3b1 → 0.8.4b1 and folds the [Unreleased] CHANGELOG into the
v0.8.4b1 section covering everything since the v0.8.3b1 tag: model preferred
profiles, ComfyUI/image-gen model surface, persistent slot context, unified
logs/events, memory audit trail + console shape guards (#1024/#1026/#1028/#1030),
stack edit drawer (#1023), board kanban drawer (#1014), and optional-cosign
installer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant