Skip to content

fix(goals): wake agent panes on inbox mail, canonicalize pane ids, make impl workers visible - #29

Merged
Eyalm321 merged 1 commit into
mainfrom
fix/goals-inbox-nudge-worker-visibility
Jul 24, 2026
Merged

fix(goals): wake agent panes on inbox mail, canonicalize pane ids, make impl workers visible#29
Eyalm321 merged 1 commit into
mainfrom
fix/goals-inbox-nudge-worker-visibility

Conversation

@Eyalm321

Copy link
Copy Markdown
Owner

Three failures found driving a live goals org (canora-sync, goals gp6/gp7) — all in the plumbing around the org, not the org itself.

1. Reports reach the parent's inbox but it never acts on them

The message bus is pull-only: POST /panes/:id/messages stores the message and pings WS clients, but nothing writes to the pane. An interactive claude orchestrator blocks on stdin the moment its turn ends, so mail sat unread (88 messages, latest seq 121) until a human typed into the pane.

New control/nudge.rs + arm_inbox_nudge in routes.rs: when mail lands for an opted-in pane (meta.role in goals-orch/spec, or hp.nudge=on), wait for the pane to leave Busy, then type ONE line naming the read cursor, using the same cadence as goal/resume delivery.

  • Never mid-turn — gated on compute_activity() != Busy.
  • Coalesced — one waiter per pane; a burst becomes one line.
  • Rate-limited — 60s per pane; gives up after 30min (pending survives, next message re-arms).
  • Opt-outhp.nudge=off meta, or HYPERPANES_MSG_NUDGE=0.

The inbox stays the source of truth; this is only the wake-up.

2. Replies to a spec agent 404'd (no such pane)

Two pane-id spellings coexist: app-created panes are pane-<uuid>, control-created ones bare <uuid>. An agent handed one form and reconstructing the other addressed a queue nobody reads — the reverse direction of the bus (orchestrator to spec answers, impl advisor consults) was silently dead.

ReadModel::resolve_pane_id canonicalizes either spelling (and a session uid); find_pane_scoped returns the canonical id, so post and read land on the same inbox.

3. Impl-agent work is invisible

spawn_workers put N agents in one pane (interleaved output), claude -p prints nothing until it exits, and the runner exits on drain -> pane_exited -> the pane auto-closes with its scrollback.

hyperpanes worker gains three flags, all default off = frozen behaviour:

  • --stream — renders Claude --output-format stream-json events as progress; non-JSON output passes through unchanged.
  • --log-dir <dir> — tees each child's raw output to <dir>/<queue>-<taskId>.log, which outlives the pane.
  • --linger <secs> — holds the process open after the drain so the pane stays readable.

Personas now pass --output-format stream-json --verbose + stream:true, lingerSecs:120. The matching MCP change (spawn_workers defaults to one pane per worker, exposes stream/logDir/lingerSecs) is in Eyalm321/hyperpanes-mcp.

Verification

  • cargo test -p hyperpanes-core — 600 pass (new: nudge policy unit tests, resolve_pane_id, alias route roundtrip).
  • cargo test in crates/app — 150 pass (new: flag parsing, stream rendering, log paths).
  • cargo clippy --all-targets clean on both crates.
  • Live (headless instance): an alias-addressed post landed in the canonical inbox and read back under either spelling; the nudge line typed itself into a quiet pane; a streamed worker run rendered progress per event and wrote per-task logs.

🤖 Generated with Claude Code

…ke impl workers visible

Three failures found driving a live goals org (canora-sync gp6/gp7):

1. Reports reached the orchestrator's inbox (88 unread) but it never acted:
   the bus is pull-only and an interactive `claude` blocks on stdin once its
   turn ends. New control/nudge.rs + arm_inbox_nudge: when mail lands for an
   opted-in pane (meta.role goals-orch|spec, or hp.nudge=on) wait for it to
   leave Busy, then type ONE coalesced, rate-limited line naming the read
   cursor. HYPERPANES_MSG_NUDGE=0 disables.

2. Replies to a spec agent 404'd: app-created panes are `pane-<uuid>`,
   control-created ones bare `<uuid>`, and an agent handed one spelling
   reconstructed the other. ReadModel::resolve_pane_id canonicalizes either
   form (and a session uid); find_pane_scoped returns the canonical id so
   post and read hit the same inbox.

3. Impl-agent work was invisible: spawn_workers put N agents in one pane,
   `claude -p` prints nothing until it exits, and the runner's exit on drain
   auto-closed the pane with its scrollback. `hyperpanes worker` gains
   --stream (render Claude stream-json as progress), --log-dir (per-task raw
   transcript that outlives the pane) and --linger; personas pass
   --output-format stream-json --verbose and spawn one pane per worker.

All new flags default off = frozen behaviour. Verified live: alias-addressed
post lands in the canonical inbox, the nudge line types into a quiet pane, and
a streamed worker run renders + logs per task.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Eyalm321
Eyalm321 merged commit 59b2ac1 into main Jul 24, 2026
27 checks passed
@Eyalm321
Eyalm321 deleted the fix/goals-inbox-nudge-worker-visibility branch July 24, 2026 23:08
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