Skip to content

Refactor web-react: replace useExecution polling with runtime SSE state subscription #43

Description

@enricopiovesan

Summary

The current web-react client manages its own idle → loading → polling → succeeded/failed state machine in useExecution.ts. Once the Traverse runtime ships the app state machine (Traverse #525), SSE endpoint (Traverse #526), and command dispatch (Traverse #527), this local state machine must be removed and replaced with a pure subscription to runtime state events.

This makes web-react the reference implementation for the SSE client pattern — all other platform clients will follow the same shape.

Blocked on

Status (2026-07-06): Traverse #525 and #526 are done. Remaining blocker is #527 only.

  • Traverse #525 — app state machine spec + runtime done
  • Traverse #526 — SSE state subscription endpoint done
  • Traverse #527 — command dispatch endpoint (remaining blocker)

What changes

Remove:

  • src/hooks/useExecution.ts — local polling state machine
  • src/client/traverseClient.ts pollExecution() — no longer needed, state arrives via SSE

Add:

  • src/hooks/useAppState.ts — subscribes to GET /v1/workspaces/{workspace}/apps/traverse-starter/events via EventSource
  • src/client/traverseClient.ts sendCommand() — POSTs to /v1/workspaces/{workspace}/apps/traverse-starter/commands
  • State shape driven entirely by runtime event payloads — no local transition logic

App.tsx becomes:

const { state, context, output } = useAppState(client, workspaceId)
// state: 'idle' | 'processing' | 'results' | 'error'  — from runtime
// output: runtime-provided fields when state === 'results'

<button onClick={() => client.sendCommand('submit', { note })}>Start</button>

Architecture constraint

The hook must contain zero transition logic. It maps runtime state names to render states only. No if (state === 'processing') startPolling().

Definition of Done

  • useExecution.ts deleted
  • useAppState.ts implemented — connects via EventSource, dispatches state updates on events
  • sendCommand() added to traverseClient.ts
  • App.tsx updated — submits via sendCommand, renders from useAppState
  • Unit tests updated: mock SSE events instead of mock HTTP polling
  • phase1_smoke.sh updated if endpoint paths change
  • All existing CI gates pass: lint, typecheck, tests, coverage

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions