Skip to content

Tool execution boundary — tools never participate in logical or simulation time #38

Description

@jBernavaPrah

Tool execution boundary — tools never participate in logical or simulation time

Status

Candidate for Ready pending independent cross-review and transfer to
phoxal/.github.

Problem

Phoxal tools represent external devices, operator actions, engineering controls,
networking, recording, and host diagnostics. They currently share the generic
participant runner with robot services, drivers, and simulators. That makes it
possible for an orchestrator or a tool to select the robot's simulation clock
even though the tool does not own a robot state transition.

The concrete current violation is tool-joypad: its 50 Hz Tokio polling loop is
host-driven, but it obtains ctx.clock() for publish timestamps, and
phoxal-cli launches it with PHOXAL_CLOCK=simulation in Webots. This couples
external controller output and lifecycle timestamps to a clock that stops while
simulation is paused. The active joypad is already a #[phoxal::tool] using a
managed async task; it does not implement Runtime, use RuntimeProcess, or
have separate runtime.rs / args.rs modules.

service/motion compounds the mismatch by applying manual-command freshness to
the producer's logical envelope timestamp with a fixed 500 ms window. It does
not retain consumer-local monotonic arrival time. Although the bus subscription
continues receiving during a logical pause and its bounded ring drops the
oldest sample, motion drains it only at logical steps.

Without a structural boundary, future tools can repeat the same mistake:
simulation pause can freeze timestamps or tool work, slow/faster-than-real-time
execution can distort host I/O, and a tool can accidentally enter a logical
clock or barrier path it does not own.

Desired outcome

Establish and enforce one suite-wide invariant:

A tool may observe or affect a robot through typed contracts, but it never
joins the robot's clock.

Tools run from host-monotonic timers, wall time where dates are semantically
required, or external events. Robot services, drivers, and simulators remain the
only participants that may execute state transitions on logical time. The
logical-time consumer owns asynchronous-input retention, freshness,
authorization, arbitration, and sampling at the step boundary.

The same tool contracts and loop semantics must work in Run, Webots, and Deploy.

Scope and ownership

Primary owner: phoxal/framework.

Affected repositories:

  • phoxal/framework: participant/tool boundary, official tools,
    service/motion, documentation, compile/source guards, and the framework-owned
    example/test surface.
  • phoxal/phoxal-cli: site-tool launch environment, launch-graph assertions,
    mode-parity tests, and clean-room integration.
  • phoxal/organization: reconcile canonical architecture/process wording after
    the implementation lands.
  • phoxal/operator: audit-only for this tracker. The current Rerun proxy is
    event-driven and has no logical-clock scheduling dependency; its migration is
    owned by phoxal/organization#904.

This cross-repository tracker lives in phoxal/.github. Contract and framework
enforcement land first, followed by the required framework release and catalog,
then the CLI consumer cleanup, then canonical documentation reconciliation.

Verified current inventory

Process/surface Classification Current scheduling/time behavior Required change
framework/tool/router tool / required site transport Zenoh events plus a host one-second metrics interval; wall-time envelope stamp; no simulation clock Keep host/event driven; ensure periodic work never uses catch-up bursts; retain the router transport exception without making diagnostics a tick barrier.
framework/tool/joypad tool / external continuous input Managed 50 Hz Tokio interval with MissedTickBehavior::Delay; publishes using ctx.clock(); CLI selects simulation clock in Webots Remove tool clock access and Webots clock selection; use host interval with Skip; publish zero immediately on selected-device disconnect.
framework/tool/telemetry tool / host observation Managed host one-second interval; wall-time envelope stamp; Tokio default missed-tick behavior Set explicit MissedTickBehavior::Skip; retain host/event timing in every mode.
planned framework/tool/rerun tool / engineering recorder Not implemented; phoxal/organization#904 still mentions “simulation clock when present” Preserve generic envelope/timeline metadata only; never subscribe to or schedule from a simulator clock.
phoxal/operator Rerun proxy external observation client Event-driven typed subscriptions and host-time retry sleeps No code change in this tracker; keep the replacement in phoxal/organization#904 clock-independent.
phoxal-cli orchestrator Host/event driven; observes simulation clock for TUI display; launches joypad with simulation clock in Webots; standard tools are outside the checked robot participant graph Preserve display-only observation; make all standard tools real/host-time launches and prove they never enter the logical participant set.
service/motion robot service / logical-time consumer Steps at 20 Hz; bounded async subscribers keep receiving during pause; manual freshness uses producer logical timestamp and a fixed 500 ms window Retain latest input plus consumer-local monotonic arrival time; apply a fixed 150 ms initial timeout; sample only at logical steps.
framework/service/* robot services Checked participant kind; scheduled steps follow logical time in Webots where declared No classification change.
framework/component/* robot drivers Checked driver kind; physical or simulator-substituted device integration No classification change. A process that needs logical device/world state remains a driver or simulator, not a tool.
Webots supervisor/controller simulators World/clock authorities running from Webots/host scheduling; supervisor publishes and controller may observe simulation clock No classification change. Simulator clock ownership remains here.

Locked decisions

  1. #[phoxal::tool] always uses host-time/event-driven execution. A tool cannot
    select or inherit ClockMode::Simulation, even through the generic
    participant launch contract.
  2. Remove SetupContextToolExt::clock(). A tool that publishes uses a
    host-safe timestamp path for generic envelope metadata; add a small reusable
    helper only if the existing router, joypad, and telemetry code demonstrates
    real duplication.
  3. Existing macro enforcement that prevents #[phoxal::tool] from declaring
    #[step], #[server], or #[server_snapshot] remains the structural
    lifecycle guard.
  4. Add a lightweight repository guard preventing framework/tool/** from
    importing simulation clock contracts, ClockSource, StepContext, clock
    barriers, or equivalent logical scheduling APIs.
  5. Tools may preserve and render generic envelope timestamps or timeline IDs as
    opaque diagnostic data. phoxal-cli may observe the simulation clock for
    its title bar. Neither case may schedule work, decide freshness, or join a
    barrier from that data.
  6. External continuous state is keep-latest with bounded memory. No queued
    pre-pause backlog is replayed. A controller that remains connected and keeps
    publishing during pause remains current external authority; after resume the
    consumer samples only the latest locally fresh state.
  7. service/motion records consumer-local monotonic arrival time independently
    from producer envelope time and applies an initial fixed 150 ms manual-input
    timeout. Configurability is deferred until a robot demonstrates a real need.
  8. A detected selected-device disconnect publishes zero manual intent
    immediately. Process or transport loss independently reaches zero through
    the motion timeout.
  9. Joypad disconnect does not publish or synthesize an emergency-stop release.
    The current joypad does not own the emergency-stop contract; this work must
    not add one. Existing software and component emergency-stop ownership in
    service/motion is preserved independently from the parked safety-service
    direction in phoxal/organization#906.
  10. Periodic tool loops use MissedTickBehavior::Skip (or equivalent
    event-driven newest-wins behavior), never catch-up bursts.
  11. Tool lifecycle policy is unchanged: the CLI may still require and supervise
    standard site tools, and a required tool failure may fail the session.
    This issue guarantees only that tool readiness/failure never becomes a
    logical-step completion dependency. Making tools optional is out of scope.
  12. No generic ToolProcess abstraction and no compatibility clock mode are
    introduced. Make the direct boundary correction.

Implementation plan

1. Framework owner and enforcement

  • Document the tool/runtime/simulator boundary in active framework architecture
    and authoring documentation.
  • Make the runner structurally select host time for IsTool participants,
    regardless of a generic launch clock value.
  • Remove the tool clock accessor.
  • Retain the existing macro compile guard against scheduled/server lifecycle
    methods on tools.
  • Add source/compile tests for forbidden logical/simulation clock dependencies.
  • Add a graph-level test proving tools cannot become logical-clock/barrier
    participants.

2. Official tool correction

  • Change joypad polling to MissedTickBehavior::Skip.
  • Stamp joypad publications through the host-safe tool path.
  • Publish one zero manual command immediately when the selected controller is
    detected as disconnected, then stop publishing movement until a controller is
    selected again.
  • Keep device management, manual motion, and all typed contracts identical in
    Run, Webots, and Deploy.
  • Give telemetry an explicit skipped-missed-tick policy.
  • Audit router timing and keep its metrics window host-driven and bounded.

3. Motion asynchronous-input boundary

  • Receive manual commands independently of the logical step loop.
  • Retain only the newest accepted command plus its consumer-local monotonic
    arrival instant.
  • Apply the fixed 150 ms local timeout, finite-value checks, robot limits,
    emergency-stop state, safety constraints where present, and manual/navigation
    arbitration before producing drive/target at the logical step.
  • Ensure a pause cannot accumulate a replay backlog and process/transport loss
    reaches zero without waiting for producer logical time.
  • Keep emergency-stop latching/source ownership separate from manual command
    freshness and from phoxal/organization#906.

4. CLI orchestration cleanup

  • Remove the Webots-specific simulation clock selection for joypad.
  • Launch every STANDARD_SITE_TOOLS entry with real/host clock behavior in Run,
    Webots, and Deploy.
  • Keep the CLI's simulation-clock feed observational and TUI-only.
  • Add mode-parity and graph tests proving tools never enter the robot logical
    participant/barrier set.
  • Preserve current standard-tool readiness and session supervision policy.

5. Planning and canonical docs

  • Amend phoxal/organization#904
    so Rerun profiles preserve generic envelope/timeline metadata but
    do not subscribe to “simulation clock when present”; duration/size limits use
    host monotonic time and measured bytes.
  • Reconcile canonical organization architecture wording to the landed boundary
    and final repository ownership names.

6. Framework-owned validation surface

  • Extend framework/examples/hello-rover with one minimal Webots world suitable
    for tool/runtime boundary checks; do not use robot-v1 as the test harness.
  • Use framework runner/test-clock coverage to hold logical execution paused while
    proving tool host loops and subscriptions continue.
  • Use the hello-rover world for clean Run/Webots mode-parity and launch-graph
    validation.

Acceptance criteria

Architecture and enforcement

  • Active framework documentation defines tools as external asynchronous
    processes that never participate in logical or simulation time.
  • #[phoxal::tool] cannot select simulation scheduling, expose a tool clock
    accessor, declare a scheduled step, import simulator-clock contracts, or join
    a logical clock/barrier graph.
  • Services, drivers, simulators, tools, and the CLI orchestrator remain
    explicitly classified by responsibility.
  • Opaque timeline display/recording remains allowed without scheduling or
    freshness decisions based on simulator time.

Joypad and motion

  • Joypad uses a host interval/event loop with skipped missed ticks and no
    logical/simulation clock dependency.
  • Joypad contracts and behavior are identical in Run, Webots, and Deploy.
  • Selected-device disconnect publishes zero manual intent immediately and
    never synthesizes emergency-stop release.
  • Motion retains newest manual state with consumer-local monotonic arrival
    time and rejects it after 150 ms without a fresh receipt.
  • Motion samples the latest accepted state at the logical step; it never
    replays a queued pause backlog.
  • Joypad process/transport loss reaches zero through the independent motion
    timeout.
  • Existing finite-value, robot-limit, arbitration, safety-constraint, and
    emergency-stop protections remain covered.

Other tools and orchestration

  • Router, telemetry, and planned Rerun have no logical-time scheduling or
    simulator-clock subscription.
  • Periodic tool work never emits catch-up bursts after host delay.
  • All standard tools receive real/host clock launch behavior in Run,
    Webots, and Deploy.
  • CLI simulation-clock observation remains display-only and is not a
    lifecycle or step authority.
  • Tool startup/readiness/failure may affect session supervision but never
    gates completion of a robot logical step.
  • phoxal/organization#904
    contains no requirement for Rerun to subscribe to a simulation clock.

Validation

  • A paused logical clock does not stop joypad polling, telemetry sampling,
    tool request handling, or async subscription receipt.
  • Slow and faster-than-real-time logical execution does not change tool poll
    cadence or cause catch-up bursts.
  • Tests cover selected-device disconnect, tool crash/transport silence,
    consumer-local timeout, stale input, bounded newest-wins receipt, and no pause
    backlog replay.
  • framework/examples/hello-rover contains and runs a minimal Webots world
    for this boundary; no private robot is the only validation harness.
  • Clean-room doctor -> update -> check --strict -> simulation run succeeds
    with the released framework/catalog and CLI consumer.

Required checks

Framework PR:

  • cargo test --workspace
  • targeted tool/motion/runner/graph tests added by this issue
  • framework-owned hello-rover Webots boundary test

Framework release between owner and consumer:

  • publish any changed shared crates
  • publish changed official tool artifacts
  • produce and validate one coherent catalog/build snapshot

CLI PR:

  • cargo check --workspace
  • cargo test --workspace
  • targeted launch-plan, environment, graph, and mode-parity tests
  • clean-room phoxal-cli doctor -> update -> check --strict -> simulation run <world>

Organization documentation PR:

  • git diff --check
  • local Markdown-link verification

Delivery and land order

  1. phoxal/framework PR: architecture, enforcement, tool correction, motion
    boundary, example, and tests.
  2. Human approval and framework release/catalog completion.
  3. phoxal/phoxal-cli PR: consume the released framework/catalog, remove the
    invalid tool clock launch configuration, and add mode-parity/clean-room
    evidence.
  4. phoxal/organization PR: reconcile canonical architecture and runbook
    wording to the landed implementation.

Each repository gets one coherent final PR for this tracker. Every PR links this
issue, names the land/release order, and reports its health-check evidence.

Non-goals

  • Removing logical time from robot services, component drivers, Webots
    simulators, or the framework scheduler.
  • Making standard tools optional or changing current session supervision policy.
  • Adding simulation-specific copies of tool contracts.
  • Making live human/device input deterministic before the robot authority accepts
    it.
  • Requiring a controller release/re-press gesture across pause; continuously
    refreshed, locally fresh latest state remains valid.
  • Making the 150 ms manual timeout configurable before evidence requires it.
  • Redesigning emergency stop or the parked future safety service in
    phoxal/organization#906.
  • Implementing Rerun; this tracker only corrects
    phoxal/organization#904's
    timing requirement.
  • Implementing generic deterministic replay.
  • Creating a generic ToolProcess abstraction or a compatibility clock mode.

Related work

  • phoxal/organization#904
    — Tool Rerun recording POC; must preserve generic timeline metadata
    without simulation-clock scheduling.
  • phoxal/organization#906
    — parked safety-service direction; independent from manual freshness and
    existing emergency-stop preservation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    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