ui: lead task detail with diagnosis

This commit is contained in:
kami
2026-07-29 23:31:25 +04:00
parent 1ca9d64e89
commit f7027cb9a7
8 changed files with 134 additions and 117 deletions
+53 -45
View File
@@ -28,22 +28,23 @@ is not an operationally useful control plane yet.
- One `workpc-opencode` worker is heartbeating and reports capacity 1. Its
Unix-socket herdr path is the meaningful reachability signal; legacy
coordinator TCP probes are not.
coordinator TCP probes are not. The coordinator now skips remote herdr
protocol probes entirely and logs them as worker-owned; local herdr probes
remain separate.
- The API reports 28 tasks: **22 blocked, 5 completed, 1 failed, and no
queued, leased, approval-pending, or captured sessions**. The visible queue
is therefore historical E2E residue, not current work.
- A real browser loaded the deployed SPA with a valid Web session and crashed
before painting: `overview.sessions` is JSON `null`, while the bundle calls
`sessions.length`. Task detail has the same fault for `events: null`.
Source now emits empty arrays and the frontend is defensive; the current
local build renders the live board and task record. **The deployment still
needs a rebuild/redeploy.**
- The API and SPA were rebuilt/redeployed on 2026-07-29. API health and the
browser shell returned `200`; the deployed logout endpoint returns `204`.
This ships the empty-collection fixes that prevent the prior
`sessions.length`/`events` null crashes. A real authenticated browser smoke
is still outstanding.
- The task record for a blocked task and the failed E2E task had no retained
session and no lifecycle events. Every lifecycle control was correctly
disabled, but neither record could explain its state.
- The live image predates the source session/logout work: `DELETE
/v1/ui/session` returns `405`. Do not treat token rotation as session
revocation until that endpoint is deployed.
- ntfy delivery now has a configured publisher token. A read-only
authenticated account check returned `200`, resolving the prior publish
`403 Forbidden`; no test notification was sent.
Earlier successful OpenCode approval and worker-flow checks remain useful
historical evidence, but they do not prove the current deployment or a
@@ -56,21 +57,25 @@ checkout.
The current UI should become a diagnosis surface, not a five-column task
catalogue.
1. **Persist and show a blocked diagnosis.** Project the structured blocking
reason/error into the task read model. Group the board by reason and age
(for example: lease failure, worker offline, expired lease, approval,
handoff validation, operator block) rather than rendering a giant generic
“Blocked” lane.
2. **Persist last-session and pane evidence.** Before a worker/coordinator
drops a terminal session mapping, retain harness, pane ID, last successful
capture/check, and a pane status of `open`, `closed`, `unreachable`, or
`unknown`. The UI must show the source and timestamp. For old records that
lack this evidence, say **unknown — legacy record has no retained
blocker/pane evidence**, never imply a live or closed pane.
3. **Make the task page lead with the diagnosis.** Put reason, last activity,
pane state, and next safe action first. Hide unavailable lifecycle forms
behind an “Unavailable actions” disclosure; an empty session must not
consume most of the page with disabled controls.
1. ~~**Persist and show a blocked diagnosis.**~~ **Closed in code,
deployment verification outstanding (2026-07-29).** `TaskBlocked` now
carries a validated `block_reason`; coordinator and browser-created blocks
set it, while older events receive a deterministic projection fallback.
The board groups blocked tasks by diagnosis and orders each group oldest
first instead of rendering one generic “Blocked” lane.
2. ~~**Persist last-session and pane evidence.**~~ **Closed in code,
deployment verification outstanding (2026-07-29).** Before worker
completion/release cleanup, the worker captures a `session_evidence`
snapshot (harness, pane, observed pane status, capture/check timestamps,
and source); coordinator blocks record their own check snapshot. The task
projection retains it and blocked cards state the source and timestamp.
Legacy records still say **unknown — legacy record has no retained
blocker/pane evidence**, never implying a live or closed pane.
3. ~~**Make the task page lead with the diagnosis.**~~ **Closed in code,
deployment verification outstanding (2026-07-29).** The task detail now
leads with reason, last activity, pane state, retained evidence, and the
next safe action. Only server-enabled lifecycle actions are shown directly;
unavailable actions are kept in an “Unavailable actions” disclosure.
4. **Separate active work from history.** Default the board to active,
waiting, and needs-attention work; move completed/failed/test residue to
filters or a compact history view. Add search, project filtering, and an
@@ -334,7 +339,7 @@ Delivery` asserting the prompt target is the unique name. Nothing yet starts
two same-harness sessions in distinct panes and verifies both attach, so the
`agent_name_taken` failure mode itself is untested end-to-end.
### B17 — opaque harnesses must not author canonical handoff anchors (found live 2026-07-28) — closed in code; live success still unproven
### B17 — opaque harnesses must not author canonical handoff anchors (found live 2026-07-28) — closed; worker path live-verified
The real OpenCode healthcheck run showed that prompting an opaque agent to
write the full `continuity.Handoff` schema is the wrong ownership boundary.
@@ -401,22 +406,32 @@ correction documented at the end of this file supplies the parsing and
validation half.
The coordinator no longer accepts a non-local herdr operation; the standing
rule is enforced rather than advisory. A successful live worker handoff,
release, and pickup remains the required operational proof.
rule is enforced rather than advisory.
**QA attempt (2026-07-29):** the bounded disposable task
**Failed QA fixture (2026-07-29):** the bounded disposable task
`06FTSHBPYHQXN8MM849PFA1V6M` reached the worker and wrote its semantic
report, but publication correctly refused it. Its prescribed fields combined
to the canonical action `inspect the marker file — verify worker-owned
handoff construction`; the circular-action guard rejects that word even when
it occurs in the explanatory `WHY` text. This is an invalid QA fixture, not a
successful handoff or a release-path regression. The worker must be given a
fresh fixture whose combined `NEXT`/`WHY` action does not mention a handoff
(for example, `WHY: verify canonical artifact construction`), then the
release and successor pickup must be observed. The coordinator is token-gated
and this host cannot read the protected worker credential, so this session
could not enqueue that replacement task. The failed disposable pane was left
untouched; no destructive herdr calls were issued.
release-path regression.
**Live success (2026-07-29):** after configuring `test-e2e` on the
`workpc-opencode` worker, disposable task `06FTY8ZA45CCZZHQ7H44SMQG14`
completed the full path. Its first pane (`w1B:p1`) created the marker and the
bounded semantic report. The worker, not the harness, published canonical
handoff `5e9e942f269f6d6394896186377e35d596d403bd04a58f0c307818af0499b208`:
its anchor was worker-derived (`git_sha`
`d73b576882b07bac34abaf2beabeacfaa8f79529`, branch
`orchestra/scratch/oc-06fty8za45cczzhq7h44smqg14`) and its semantic action
was `Verify the B17 probe marker file contents. — Verify canonical artifact
construction.` The worker recorded `TaskReleased`, routed a successor lease
with that handoff reference to a new pane (`w1C:p1`), and the successor
verified the marker through the scratch checkpoint. It then completed the
task with report artifact
`9a41950548118a47232747ff57fb7ac109dbdb2e45e0b8a8141d4828a6351f18`.
After `TaskCompleted`, the worker state had no sessions or leases. The
disposable worktree was intentionally retained; pane/session cleanup passed.
### B13 — `agent.start` silently no-ops under back-to-back leases (found live 2026-07-28) — closed (code fix; not yet re-verified live)
@@ -745,16 +760,9 @@ bypass is closed by construction rather than by the header check alone.
In dependency order, not importance order:
1. **Prove a successful B17 worker handoff.** Use a bounded disposable task
with a concrete next action and verify canonical report upload, release,
follow-up pickup, and cleanup. The rejection path is proven; success is
not.
2. **Fix health semantics and ntfy.** Report worker/local-herdr health
separately from legacy TCP registry probes, and correct the ntfy server
credential causing `403 Forbidden`.
3. **Address the Web UI backlog above**, starting with queue explanations,
1. **Address the Web UI backlog above**, starting with queue explanations,
actionable worker health, and a usable approval/recovery workflow.
4. **Record a browser smoke.** Confirm login, refresh, invalid token, and
2. **Record a browser smoke.** Confirm login, refresh, invalid token, and
expired-session behavior in an actual browser after the deployed assets
settle.