Skip to content

Add inline task status update control to web dashboard#229

Merged
danieljhkim merged 1 commit into
agent-mainfrom
orbit/ORB-00025-6a0682a8
May 15, 2026
Merged

Add inline task status update control to web dashboard#229
danieljhkim merged 1 commit into
agent-mainfrom
orbit/ORB-00025-6a0682a8

Conversation

@danieljhkim
Copy link
Copy Markdown
Owner

Task

ORB-00025 — Add inline task status update control to web dashboard

Description

Problem

The web dashboard's per-task actions row (buildActionsRow() at crates/orbit-cli/assets/dashboard/app.js:404–433) exposes three mutation paths: approve, reject, archive. There is no way to move a task between lifecycle-internal statuses (e.g. proposed → in-progress, in-progress → blocked, blocked → review) from the UI. Today the only options are the CLI (orbit task update) or the MCP (orbit.task.update).

The backend already supports it. PATCH /tasks/:id (crates/orbit-cli/src/command/web/api/tasks.rs:88–112, wired at crates/orbit-cli/src/command/web/api/mod.rs:286) accepts a partial UpdateTaskBody whose status: Option<TaskStatus> field already routes through runtime.update_task_with_identity(...). The work is frontend-only.

Why It Matters

Dashboard users (humans, not agents) currently context-switch to a terminal to do something as basic as "move this task from proposed to in-progress so I can start it." That breaks the dashboard's promise as a control surface and pushes users toward the CLI for routine state changes. Adding an inline status control closes the gap without touching backend code paths that are already in production.

Scope

Exposed statuses (lifecycle-internal): proposed, backlog, someday, in-progress, review, blocked, done.

Explicitly excluded — dedicated flows already exist:

  • rejected — keep going through POST /tasks/:id/reject, which requires a note (RejectBody.note: String at tasks.rs:36–41). The new control must not offer this status, otherwise it bypasses the note requirement.
  • archived — keep going through POST /tasks/:id/archive plus the existing window.confirm() at app.js:426. archived is also not part of the TaskStatus enum accepted by PATCH.
  • friction — deprecated from the lifecycle (see ORB-00024).

Backend changes — none. PATCH /tasks/:id already accepts { "status": "..." } and writes history via update_task_with_identity. Do not add a new endpoint, do not change the routing in mod.rs, do not modify UpdateTaskBody.

Known Consequence

DASHBOARD_TASK_STATUSES at tasks.rs:17–26 does not include TaskStatus::Done. Tasks transitioned to done via the new control will disappear from the dashboard's task list immediately after refresh. This is accepted for this task — expanding the dashboard's visibility set is a separate decision and a separate task. The control should still expose done as a target; the implementer should add a post-action toast or inline note clarifying the disappearance ("task marked done — no longer shown in dashboard list") so users aren't confused.

Constraints / Notes

  • UX: add the control to buildActionsRow() next to the existing approve/reject/archive buttons, OR as a dedicated control adjacent to the status pill in the detail view — implementer's call, but it must not visually displace the existing three buttons.
  • Current status omitted: the control must not offer the task's current status as a target.
  • Status order: when offering options, follow the dashboard's STATUS_ORDER ordering (app.js:4–13, post-ORB-00024) for in-set statuses, then done last.
  • In-flight behavior: mirror runAction() at app.js:464–499 — disable the control while the PATCH is in flight, surface backend errors via the same .action-error element pattern, and call refreshDashboard() on success.
  • No authz changes. The dashboard already permits unauthenticated POSTs to /approve, /reject, /archive. The new control inherits the same trust model; if that's wrong, it's wrong for everything and needs its own task.
  • No new test harness. If JS-side tests exist for buildActionsRow or runAction, extend them. Otherwise, smoke-test manually and document the steps in execution_summary (open dashboard, transition proposed → in-progress, observe history reflects the change, verify error path on a forced 4xx).

Acceptance Criteria

(captured in the acceptance_criteria field)

Acceptance Criteria

  • A status update control is rendered for every task in the dashboard, sourced from the same code path as the existing action buttons (i.e. added inside or adjacent to buildActionsRow() in crates/orbit-cli/assets/dashboard/app.js).
  • The control exposes exactly this status set: proposed, backlog, someday, in-progress, review, blocked, done. It does NOT expose friction, rejected, or archived.
  • The task's current status is not offered as a target in the control (no-op transitions are not selectable).
  • Selecting a target status issues a PATCH /tasks/:id request with body { "status": "<target>" } and no other fields. The existing runAction() helper is reused or extended — do not duplicate its disable/error/refresh logic.
  • On success: the dashboard refreshes via refreshDashboard(), the task's status pill reflects the new value, and the task's history (visible in the detail expansion) shows the transition.
  • On failure (e.g. server returns 4xx/5xx): the control is re-enabled, an .action-error element is prepended to the task detail with the server's error message, and the task's status pill remains unchanged.
  • When a task is transitioned to done, the UI surfaces a user-visible cue (toast, inline note, or post-refresh message) that the task is no longer shown in the default dashboard list. The cue must be testable — it appears in the DOM after a successful done-transition.
  • The existing approve, reject, and archive buttons render and function exactly as before. The reject flow still requires a note via showRejectForm() at app.js:435. The archive flow still confirms via window.confirm() at app.js:426.
  • No backend changes: crates/orbit-cli/src/command/web/api/tasks.rs and crates/orbit-cli/src/command/web/api/mod.rs are unchanged. DASHBOARD_TASK_STATUSES is unchanged. UpdateTaskBody is unchanged.
  • make ci passes.

Execution Summary

Click to expand

Outcome: success

Changes:

  • Added a per-task status update select in the dashboard action row, ordered by STATUS_ORDER with done last, omitting the current status and excluding friction/rejected/archived.
  • Extended runAction to support PATCH /api/tasks/:id while preserving shared disable/error/refresh handling for approve, reject, and archive.
  • Added a DOM-visible done-transition notice and styling for the status control and success cue.
  • Bumped docs/design/activity-job/4_decisions.md Last updated to satisfy the design decay check for the already-landed ORB-00027 macOS sandbox changes.

Validation:

  • node --check crates/orbit-cli/assets/dashboard/app.js
  • git diff --quiet -- crates/orbit-cli/src/command/web/api/tasks.rs crates/orbit-cli/src/command/web/api/mod.rs
  • ./target/debug/orbit web serve --host 127.0.0.1 --port 8787 --no-open, then curl-verified updated /static/app.js and CSS assets
  • make ci

Assessment: Frontend-only task status transitions are implemented through the existing dashboard action path; backend task API files remain unchanged.

Deviations from original plan:

  • Updated an unrelated stale design-doc date because make ci's design_check failed on docs/design/activity-job/4_decisions.md before the dashboard change could satisfy the required validation gate.

Validation

  • Not reported

Branch Freshness

  • Base ref: origin/agent-main
  • Head ref: orbit/ORB-00025-6a0682a8
  • Behind base: 0
  • Ahead of base: 1

authored by: claude-opus-4-7

Tasks:
- ORB-00025: Add inline task status update control to web dashboard
@danieljhkim danieljhkim merged commit 5d2be71 into agent-main May 15, 2026
2 of 3 checks passed
@danieljhkim danieljhkim deleted the orbit/ORB-00025-6a0682a8 branch May 15, 2026 02:30
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