Files
browser/openspec/changes/make-run-runtime-state-authoritative/design.md
T

2.5 KiB

Context

Platform currently stores serverInstances.state as both desired state and observed runtime state. CompleteRunJob projects successful lifecycle jobs directly into that field, so a previous process.start success can leave a server as running even after the actual Run-managed process is gone. A manually started generated Run can register and heartbeat, but platform will not dispatch another start job because it trusts the stale stored state.

Run already has the safer primitive: it owns the generated package startup path and can report redacted processState facts from inside the generated Run workspace. This change uses Run reports as the observed runtime source and avoids Platform registration-time probes.

Goals / Non-Goals

Goals:

  • Stop generated Run startup from relying on a platform-dispatched registration-time process.status job.
  • Project server state from Run processState for status/start/stop lifecycle results.
  • Preserve Platform ownership of authorization, leases, and audit for explicit operator requests while treating generated Run bootstrap as Run-owned.

Non-Goals:

  • Add a new live telemetry protocol or raw process list to heartbeat.
  • Hardcode SCUM-specific executable names, Steam app IDs, paths, ports, or health checks in platform or Run.
  • Change plugin create wizard requirements or distribution-build ownership.

Decisions

  • Do not queue status reconciliation on generated Run registration. Registration confirms identity and session only; Run-owned lifecycle/status reports correct stale Platform projections.
  • Keep explicit process.status result projection for operator-requested or Run-reported status flows that are not registration bootstrap side effects.
  • Project process.status into lifecycle state with conservative mapping: running => running, stopped/not-started => stopped, unexpected exited => failed, operator-stopped exited => stopped.

Risks / Trade-offs

  • A plugin start wrapper can be running while still installing dependencies. This change does not solve game readiness; it only prevents platform from preserving stale process state when Run reports no managed process.
  • Status reconciliation is asynchronous. A manual Run may briefly appear with stale state until it claims and completes the status job.
  • If a server process was started outside the active generated Run workspace, the registering Run will report not-started and platform will mark stopped. That is intentional: unmanaged external processes are not authoritative for platform lifecycle.