Skip to content

Spec + runtime: app-level state machine definition in app manifest #525

Description

@enricopiovesan

Summary

Add a state_machine block to the app manifest schema. The Traverse runtime reads this at app registration time and owns the application state machine for that app. Clients never manage their own state machines — they subscribe to runtime state events and send commands.

This is the primitive that makes multi-platform clients architecture-clean: every platform (web, iOS, Android, macOS, Windows, Linux, CLI) becomes a pure rendering layer.

Motivation

Without a runtime-owned state machine:

  • Every client duplicates the same idle → loading → polling → succeeded/failed logic
  • State divergence bugs appear between platforms
  • Business rules about when to retry, when to fail, and what to invoke are spread across every client codebase

With a runtime-owned state machine:

  • State logic lives once, in the manifest
  • All clients receive the same state events
  • Adding a new client is pure UI work — zero business logic to port

Proposed manifest schema addition

{
  "kind": "app_manifest",
  "app_id": "traverse-starter",
  "state_machine": {
    "initial_state": "idle",
    "states": [
      {
        "id": "idle",
        "transitions": [
          { "on": "submit", "to": "processing" }
        ]
      },
      {
        "id": "processing",
        "invoke": {
          "capability_id": "traverse-starter.process",
          "input_from": "command.payload"
        },
        "transitions": [
          { "on": "capability_succeeded", "to": "results" },
          { "on": "capability_failed", "to": "error" }
        ]
      },
      {
        "id": "results",
        "transitions": [
          { "on": "reset", "to": "idle" }
        ]
      },
      {
        "id": "error",
        "transitions": [
          { "on": "retry", "to": "processing", "with_last_payload": true },
          { "on": "reset", "to": "idle" }
        ]
      }
    ]
  }
}

Runtime behavior

  1. On traverse-cli app register, the runtime parses and validates the state_machine block
  2. The runtime instantiates one state machine per app session (or per workspace — TBD)
  3. When a client sends a command, the runtime evaluates the transition, updates state, and broadcasts an event
  4. If a state has an invoke block, the runtime calls the named WASM capability and auto-transitions on result
  5. State events are broadcast to all subscribed clients

Definition of Done

  • New spec: 047-app-state-machine — defines the manifest schema, state/transition semantics, invoke block, and event payload shape
  • Manifest validator (traverse-cli app validate) accepts and validates state_machine blocks
  • Runtime instantiates and executes state machines for registered apps
  • State machine persists across client disconnects (runtime owns it, not the client)
  • traverse-cli app validate rejects invalid state machines: unreachable states, missing initial_state, undefined capability refs
  • Integration test: register traverse-starter manifest, send submit command, observe processing → results transition in state event stream

New spec number

Suggest: 047-app-state-machine

Downstream unblocked

  • traverse-framework/App-References: all platform clients (web, iOS, macOS, Android, Windows, Linux)
  • traverse-framework/App-References #AR3: refactor web-react to use runtime state subscription

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent:codexClaimed by CodexenhancementNew feature or requestspecSpec and planning related work

    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