galaxyproject / galaxyproject/loom

Orbit: make the "Galaxy job finished — ask me to verify" message actionable with a one-click button

Open
#451 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
TypeScript
Stars
14
Forks
12
Avg merge
6d 5h
Merged PRs (30d)
17

Description

The Galaxy completion messages are working well -- a beta tester called out that "Galaxy job finished, ask me to analyze" is a genuinely useful nudge. The gap is that it *tells* you to ask instead of letting you just do it. You have to type the follow-up yourself, which is friction on the exact action the message is already recommending.

### Where this lives today

`jobFinishedToast()` in `extensions/loom/galaxy-poller.ts` builds the text per terminal state:

- completed -> `✅ Galaxy: "" finished — ask me to verify the outputs.`
- failed -> `❌ Galaxy: "" failed () — ask me to investigate.`
- cancelled / skipped -> informational, no follow-up implied

There's a second, invocation-level completion notify further down the same file. Both reach the shell through the notifier wired in `extensions/loom/session-lifecycle.ts`, which calls `ctx.ui.notify(text, level)`. Orbit renders that as an inline info message (`chat.addInfoMessage`) in the `method === "notify"` branch of `app/src/renderer/app.ts`.

### What would need to change

Rendering a button is not the hard part -- info messages already carry interactive elements. The "Don't show again" anchors on the cheaper-model and compact nudges use exactly this pattern with a delegated click handler.

The constraint is the transport. pi's RPC `ui.notify` carries only `message` and `notifyType`; there is no structured field an action could ride on. That leaves two shapes:

1. **Renderer pattern-matches the notify text.** Cheap, but couples Orbit's UI to the brain's exact toast prose -- any wording change silently drops the button.
2. **Structured channel.** The brain emits the completion as an intent (status, label, suggested prompt) over a channel that survives RPC -- `ctx.ui.setWidget` with a new `LoomWidgetKey` is the one Orbit already consumes for the notebook -- and Orbit decides whether to render it as a button.

Option 2 is the one that keeps the brain shell-neutral: the CLI has no button concept, so the brain should describe the suggested action and let each shell decide how (or whether) to surface it.

### Behavior worth pinning down

- Per-status action: completed -> "Verify outputs"; failed -> "Investigate". Cancelled/skipped get no button.
- Clicking submits the follow-up as a normal user turn, so it's visible in the transcript rather than happening invisibly.
- A turn may already be in flight when the poller fires -- the button needs to either disable itself or queue.
- Consume the button after one click so a scrolled-back message can't re-fire an old job's analysis.

Related: #400 is the same family of problem on a different surface (agent asks "Shall I proceed?" instead of pointing at the plan card's existing Approve/Edit/Reject buttons).

Contributor guide

No contributing guide indexed for this repository

Research direction

Read extensions/loom/galaxy-poller.ts and extensions/loom/session-lifecycle.ts first, then trace the notify branch in app/src/renderer/app.ts and the existing interactive-element handlers. Confirm how a structured completion intent can cross RPC and be rendered per status. Done means completed and failed jobs expose one-use Verify or Investigate actions, while cancelled and skipped jobs do not, and clicks submit visible user turns safely during an in-flight turn.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
full-stack
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.