Skip to content

feat: exec channel-relay parity + dashboard daemon UX#3

Merged
lespaceman merged 10 commits into
mainfrom
feat/exec-parity-daemon-ux
May 9, 2026
Merged

feat: exec channel-relay parity + dashboard daemon UX#3
lespaceman merged 10 commits into
mainfrom
feat/exec-parity-daemon-ux

Conversation

@lespaceman
Copy link
Copy Markdown
Member

Summary

Two related lines of work, rebased cleanly on top of main (currently at 0.4.1):

1. exec channel-relay parity

Makes drisp exec functionally identical to interactive mode minus the Ink UI. Permission/question requests now route through --channel (relayed to telegram etc.) just like interactive; with no channel attached they block until --timeout-ms fires.

  • Removes --on-permission / --on-question policy flags and EXEC_EXIT_CODE.POLICY (slot kept as numeric gap for backward compat).
  • New shared modules src/app/channels/relayAdapter.ts and sessionBridgeLifecycle.ts extracted from RuntimeProvider so exec and interactive share the same channel-relay machinery.
  • Deletes src/app/exec/policies.{ts,test.ts}.

2. Dashboard daemon UX (Pair Once)

Implements docs/plans/2026-05-09-remote-runtime-daemon-ux.md — closes the gaps left by the prior "committed prototype" (fd71141) so a single drisp dashboard pair <token> leaves the machine ready for dashboard-driven remote runs.

  • New src/infra/daemon/: PID lock, log file rotation, UDS IPC, state-dir, launchd/systemd service-unit install.
  • New src/app/entry/dashboardDaemon.ts entry + expanded runtimeDaemon.ts (long-lived InstanceSocket, proactive token refresh, per-run abort).
  • dashboard subcommand surface: status, logs, runs, refresh, daemon foreground|start|stop|install, console enable.

Other

  • feat(telemetry): workflow / dashboard / setup / exec events + exception autocapture.
  • feat(processRegistry): async cleanup hooks with 2s timeout.
  • refactor(gateway/console): drop conversationId mirror on outbound and remove debug trace.
  • fix(workflow): treat untouched tracker skeleton as a clean completion.
  • feat(dashboard): wire connect to remote run executor + add doctor / console link.
  • test(cli): drop stale dashboard doctor --runner forwarding test.
  • Adds posthog-setup-report.md documenting the wizard run that produced the telemetry events.

Test plan

  • npm run typecheck clean
  • npm test — 273 files, 3142/3142 passing
  • Manual smoke: drisp exec --channel telegram "..." relays permission to telegram
  • Manual smoke: drisp dashboard pair <token> leaves a running daemon and dashboard-triggered runs work
  • Verify drisp dashboard daemon install produces a working launchd plist on macOS

🤖 Generated with Claude Code

lespaceman and others added 10 commits May 9, 2026 16:09
…onsole link

- connect now dispatches job_assignment frames to executeRemoteAssignment,
  drains in-flight runs before disconnecting, and streams events back via
  the new sendRunEvent on InstanceSocketClient
- doctor verifies pairing health and (with --runner) confirms the runner is
  bound to this instance via GET /api/runners/<id>; only refreshes the
  access token when the runner check actually needs it
- console link <runnerId> writes ~/.config/athena/channels/console.json
  (mode 0600) with a derived ws/wss broker_url and reloads gateway channels
- send() warns once per close transition when frames are dropped

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously a workflow that ran without engaging the tracker was marked
failed with a verbose stop reason. That penalised single-turn workflows
where the agent legitimately had nothing to track. Now the loop ends
in 'completed' with no stop reason.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…on autocapture

- enableExceptionAutocapture so PostHog catches uncaught errors without
  manual trackError calls at every boundary
- new helpers: trackWorkflowCommand, trackDashboardPaired,
  trackDashboardUnpaired, trackSetupCompleted, trackExecCompleted
- SetupWizard fires trackSetupCompleted alongside the existing
  writeGlobalConfig

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… remove debug trace

Outbound console.message.out now carries threadId only; the dashboard
side stopped reading conversationId from outbound replies, and mirroring
both fields was dead-weight. Also removes the writeGatewayTrace call
that was left over from earlier debugging.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
registerAsyncCleanup() lets long-lived resources (sockets, daemons, file
locks) flush before the process exits via SIGINT, SIGTERM, or an
unhandled error. Hooks race against a 2s timeout so a hung cleanup can't
block exit, and re-entrant signals are de-duplicated via an `exiting`
guard. beforeExit still runs sync-only cleanup since it can't await.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Implements the "Pair Once, Dashboard-Spawned Headless Sessions" plan
(docs/plans/2026-05-09-remote-runtime-daemon-ux.md). Closes the gaps
left by the prior committed prototype (fd71141) so a single
`drisp dashboard pair <token>` leaves the machine ready for
dashboard-driven remote runs without keeping a foreground TUI alive.

- New `src/infra/daemon/` substrate: PID lock, log file rotation,
  UDS IPC server/client, state-dir resolution, and launchd/systemd
  service-unit install/uninstall helpers (all with tests).
- New `dashboardDaemon.ts` entry point and expanded `runtimeDaemon`
  to host long-lived InstanceSocket connection, proactive token
  refresh, and per-run abort handling.
- `dashboard` subcommand expansion: `status`, `logs`, `runs`,
  `refresh`, `daemon foreground|start|stop|install`, and
  `console enable`. Status reports merge daemon UDS state with
  dashboard-side instance metadata.
- Tests cover the new infra modules, daemon lifecycle, and the
  expanded command surface (3142 total, +46).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
One-shot report from the PostHog setup wizard documenting the new
events (workflow/dashboard/setup/exec) and exception autocapture
shipped in commit ac2b1db.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The test asserted the old subcommand-arg shape for `dashboard doctor`
that no longer matches how `--runner` is forwarded.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@lespaceman lespaceman merged commit d4beb7b into main May 9, 2026
2 checks passed
lespaceman added a commit that referenced this pull request May 10, 2026
Extract seams, remove duplication, and sharpen module ownership across
six areas of the codebase. All 3258 tests pass.

**#4 RelayCoordinator**: extract generic PendingBroadcast<T> internal
type; requestPermission/requestQuestion become thin wrappers.

**#6 UDS IPC**: extract tryReadFrame/writeFrame codec to udsFrameCodec.ts;
both server handleConnection and client sendUdsRequest consume it.

**#5 Exec runner**: extract FailureLatch (registerFailure/hasFailure) and
exitCodeFromFailure; finalMessage test coverage expanded to 11 tests.

**#1+#2 Gateway binding + dispatch turn**: extract RuntimeBindingStore
(binding state machine, grace timer, epoch, observer callbacks) from
DispatchPipeline + SessionRegistry; delete dispatcher.ts; SessionRegistry
shrinks to dispatch correlation directory.

**#3 Plugin source resolution**: create workflowResolver.ts as the single
home for workflow manifest traversal, ref-shape detection, version
pinning, and ambiguity detection; strip workflow-specific code from
marketplaceShared.ts; delete workflowSourceResolution.ts.

**#7 Session persistence**: extract SessionRow type and rowToAthenaSession
mapper to types.ts; remove identical duplicate definitions from store.ts
and registry.ts.

Co-Authored-By: Claude Sonnet 4.6 <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.

2 participants