--- id: DEC-0021 ticket: studio-play-stop-cartridge-flow title: Decision for Play/Stop runtime execution from build through external run process status: accepted created: 2026-04-06 accepted: 2026-04-06 agenda: AGD-0024 plans: [PLN-0042, PLN-0044, PLN-0045] tags: [studio, runtime, play-stop, build, process, debugger, project-setup, logs] --- ## Decision Domain owner: `studio`. Referenced subdomains: `runtime`. This decision defines the runtime-execution contract that follows the preparation contract already described in `DEC-0020`. The decision is: 1. `Play` MUST execute the configured runtime as an external process. 2. The runtime executable path MUST come from `ProjectLocalStudioSetup.prometeuRuntimePath`. 3. The external command for this wave MUST be exactly `"" run build`. 4. The process MUST run with the project root as its current working directory. 5. `Play` MUST rely on the successful completion of the preparation pipeline and MUST NOT add a redundant manifest-existence preflight in this wave. 6. `Play` MUST fail explicitly when the configured runtime path is missing, invalid, nonexistent, non-executable, or cannot be spawned. 7. `Play` MUST own exactly one active runtime-process handle for the current project shell. 8. While that process is active, additional `Play` actions MUST be ignored. 9. `Stop` in this wave MUST kill the active runtime process directly. 10. The future `DebuggerWorkspace` SHALL be the canonical destination of execution and logs. 11. Until that workspace exists, runtime logs and shipper-provided preparation logs MUST flow to a temporary surface, while the Activity Feed only receives summarized lifecycle events. 12. The shipper service remains the owner of preparation orchestration and aggregated preparation output. 13. The `pack` step used by `Play` MUST preserve validation before packing, and runtime execution MUST NOT start if validation blocks the pack. 14. Additional pre-build editor preflight checks, including unsaved-file detection, are explicitly deferred to a future wave. 15. No cancellation of the preparation phase is supported in this wave. 16. The future debugger wave MAY replace `run` with `debug`, but that is not authorized by this decision. ## Rationale `Play/Stop` only becomes semantically real if the shell owns the runtime process it claims to start and stop. After `DEC-0020`, the runnable artifact root for this wave is `build/`, and the preparation flow already owns generation of `manifest.json`. This means the runtime-execution wave does not need another packaging boundary and does not need redundant manifest-existence checks before spawn. The narrowest correct contract is therefore: - prepare through `build -> validate pack -> pack -> manifest`, - treat shipper as the owner of preparation output and aggregated preparation logs, - spawn the configured runtime externally with `run build`, - keep a single process handle, - and surface logs in the future debugger destination. This keeps responsibility boundaries clear: - preparation remains owned by the earlier preparation decision, - runtime-process ownership belongs to the shell, - and future debugger behavior remains a later wave rather than being guessed now. ## Technical Specification ### 1. Runtime Command For this wave, the Studio shell MUST construct and execute the runtime command as: `"" run build` Rules: - `runtimePath` MUST be read from `ProjectLocalStudioSetup.prometeuRuntimePath`; - the process MUST execute with `cwd` equal to the project root; - no wrapper command is introduced in this wave; - no `debug` subcommand is introduced in this wave. ### 2. Execution Order `Play` preparation and execution MUST follow this order: 1. `build` 2. `pack` validation 3. `pack` only if validation allows it 4. runtime spawn with `run build` The shell MUST stop on first failure. If `build` fails, no pack validation, pack, or runtime spawn occurs. If pack validation blocks, no pack or runtime spawn occurs. If pack fails, runtime spawn does not occur. If preparation fails, no cancellation path is offered in this wave; the flow simply terminates in failure. ### 3. Preparation Contract Reliance This decision depends on `DEC-0020`. Rules: - the shell MUST rely on the success of the earlier preparation pipeline; - the shell MUST NOT add a redundant check for `build/manifest.json` existence before spawn in this wave; - a missing manifest after successful preparation is a violation of the earlier preparation contract, not a new runtime-execution rule. ### 4. Runtime Preflight Before spawning the external process, the shell MUST treat the following conditions as explicit preflight failures: - missing `prometeuRuntimePath`, - blank `prometeuRuntimePath`, - nonexistent runtime path, - non-executable runtime path, - spawn failure. This wave does not yet define a broader runtime repair flow. ### 5. Process Ownership and Stop Semantics The shell MUST own exactly one active runtime-process handle per active project shell. Rules: - `Play` while the process is active MUST be ignored; - `Stop` MUST target only the process started by the current `Play` flow; - `Stop` in this wave MUST kill that process directly; - `Stop` has no effect during `preparing` because preparation cancellation is not defined in this wave; - graceful debugger-oriented stop commands are deferred to a future debugger wave. ### 6. Logging and Debugger Destination The canonical destination for execution-session logs SHALL be the future `DebuggerWorkspace`. For this wave: - the shell MUST navigate toward that execution destination when `Play` starts, before runtime spawn is attempted; - logs from `build`, pack validation, `pack`, and runtime stdout/stderr MUST converge on that execution-log destination; - preparation logs arrive there through shipper-owned aggregated output; - until the `DebuggerWorkspace` exists, those logs MUST use a temporary/transitional surface; - the Activity Feed MUST remain a summary surface and MUST NOT become the primary full-log destination. ### 7. Shared Session State The Studio shell and debugger destination require shared execution state that exists independently of the visual lifecycle of the workspace. For this wave, the minimum state machine SHALL distinguish at least: - `idle` - `preparing` - `prepare_failed` - `connecting` - `running` - `runtime_failed` - `stopped` This state is not owned solely by the visual workspace. ### 8. Deferred Checks This decision explicitly defers: - unsaved-editor-file checks before `build`, - broader build preflight policy, - graceful runtime stop commands, - debugger-specific execution semantics, - and any redundant manifest-presence preflight beyond the contract already owned by `DEC-0020`. When introduced later, those concerns MUST be handled in a separate discussion wave or explicit revision. ## Constraints 1. This decision covers external runtime execution through `run`, not debugger execution through `debug`. 2. This decision assumes the preparation contract of `DEC-0020` without reopening it. 3. This decision does not yet define the concrete temporary UI surface that will host execution logs before the `DebuggerWorkspace` exists. 4. This decision does not yet define richer exit-code UX beyond success/failure lifecycle handling. 5. This decision does not yet define restart semantics beyond ignoring repeated `Play` while active. ## Revision Log - 2026-04-06: Initial draft from AGD-0024.