First implementation slice: run lifetime¶
Status: This is the historical specification and evidence for an isolated run-lifetime slice. It is not the current project-wide work queue; see the roadmap for integration priorities.
2026-10-26, batch 34. This is the bounded implementation specification under the sole rebuild plan, not another work queue. It specifies R1a only, the first coding batch. The specification was implemented in batch 35: nine focused Editor groups pass with exit0. Existing gameplay remains unmodified; batch 36 now integrates the lifetime into the new shared scene/Editor development entry at F0 no-actor scope. The rest of this page records the reviewed scope and behavior. The wider run contract remains authoritative; a small lifetime owner is one part of F0, not a playable arena or a completed foundation.
Design review and admission¶
The core workstreams now have source-backed ownership, comparison cases, migration direction and explicit follow-ups. The gate register connects the R0 checklist and every CA/SE/RP/PS follow-up to its affected phase and required evidence. The architecture pass is sufficient to begin the isolated R1a boundary. It does not certify all 227 files as deeply reviewed, imported scene overrides, a concrete Input System wire format or an entire gameplay rebuild.
| R0 planning requirement | Evidence and conclusion |
|---|---|
| Whole-file inventory and honest review depth | Cleanup audit: all 227 project scripts inventoried; focused source maps extend coverage without retroactively upgrading inventory-only rows. |
| Core owners and dispositions | Input, run, player, combat, stage/enemy, reward, persistence/UI/services identify retained content/behavior, replacement owners, bridges and removal conditions. Unreviewed secondary APIs/imported overrides are gates before their own migration. |
| Identity, state and lifetime | Slot/device lifetime differs from actor/run lifetime. Definitions, runtime, profile and presentation have separate owners. R1a introduces lifetime only, with no roster or player identity fabricated to satisfy a test. |
| Fixture and authoring | F0–F5 and character/enemy/stage recipes have declared capabilities and acceptance. R1a covers lifecycle checks; the shared scene follows at R1b, real player at R2 and passive damage target at R3. |
| Compatibility and source baseline | Existing 608 gameplay pins and later maps preserve the current source; no shipped Steam commit is claimed. Profile identity/legacy conversion/write rules are designed. Concrete new input serialization and IO changes are gated before production use. R1a cannot access those services. |
| Shared scene/events | Scene differences, stage/environment ownership and scoped event contracts are recorded. R1a creates no scene, global event bus or existing GameEvents bridge. Exact bindings and scoped phase notifications are reviewed at their first consumer in R1b. |
| First slice and verification | Exact new files, public responsibilities, lifecycle/failure rules, test groups, rollback and production isolation are specified below. No unresolved payout/scarcity/backend/device choice changes this code path. |
This closes the architecture-planning gate for starting R1a, with the explicit phase gates retained. It does not waive those gates or authorize broad replacement of existing owners. If implementation requires an old script, serialized asset, service or package outside the manifest below, stop that expansion, trace its callers/bindings and amend the slice before touching it. Ordinary internal method choices within the stated behavior do not require another approval.
Exact file and asset boundary¶
Implemented namespace: TinyChaos.Gameplay.Lifecycle; no existing type with that namespace/name was found in the inspected project. Keep the project's default runtime/Editor assemblies; no new package or assembly definitions.
| Implementation path | Responsibility |
|---|---|
Assets/Script/Game/GameSystem/Run/RunContext.cs |
Immutable lifetime identity and cancellation token. A unique RunId for each new lifetime; no stage/character assets, profile fields, roster, Unity singleton or input device references. This is lifetime context, not the complete future validated run request. |
Assets/Script/Game/GameSystem/Run/IRunParticipant.cs |
Narrow participant contract: stable non-empty Id; asynchronous PrepareAsync(context); synchronous Activate(context); synchronous Release(context). Preparation includes participant-owned cancellable work. Release accepts partial preparation and must finish its owned synchronous cleanup. Asynchronous cleanup requires an explicit contract amendment before a caller needs it. |
Assets/Script/Game/GameSystem/Run/RunLifetime.cs |
Own the copied participant list, RunContext, phase, one preparation/stop operation, activation admission, cancellation, reverse cleanup and explicit failure result. Associated small phase types can live here; no framework, service locator, simulation, pool, score, audio or navigation logic. |
Assets/Script/External/Editor/RunLifecycleChecks.cs |
Focused checks against those actual runtime classes, using controlled in-memory participants and completion sources. Entry TinyChaos.EditorTools.RunLifecycleChecks.RunBatch35. No gameplay MonoBehaviours instantiated, Play Mode, scene loads, normal saves, Steam/Discord or HTTP. |
| Metadata only for those additions | New .meta for the Run folder and four new C# files, preserving all existing GUIDs. Obtain/import valid metadata through the matching Editor; do not reuse existing GUIDs or reserialize unrelated assets. |
No existing C# file changes are needed for R1a. In particular, AppInitiator, ServicesRoot, GameInitialization (declared in GameInitializer.cs), GameSession, GameManager, GameStateService, GameEvents, Player, AbilityHolder and InputManager retain their existing behavior and bindings. No scene/prefab/SO, production build list/profile, manifest, package lock, project setting or normal profile changes are part of this slice. Documentation updates record actual evidence after implementation.
The new core is production code awaiting integration; the Editor participants are verification collaborators, not another player, ability, damage system or game loop. The old production path never discovers it through Awake, static initialization, Resources, reflection or an automatic scene entry.
Lifecycle behavior¶
The coordinator runs on its owning thread; it creates no background Unity work and uses no blocking waits. Constructor validation copies a non-empty ordered list of non-null participants, rejects blank/duplicate IDs and duplicate participant instances, and starts no participant work. Participants cannot be swapped into a live preparation.
The phase sequence is Created → Preparing → Ready → Running → Stopping → Stopped. Stopping can begin from any nonterminal phase. A prepare/activation failure records its cause and follows the same cleanup path to Stopped. This is lifecycle phase, not the menu/reward/death/pause simulation state; do not set Time.timeScale or adapt GameStateService in this slice.
| Operation | Required behavior |
|---|---|
| PrepareAsync | Store operation ownership before entering participant code. Visit participants in declared order; await each actual preparation. Track a participant as entered before calling it so partial failure is released too. Return the same owned preparation work to duplicate callers; never start another sequence. No automatic activation. |
| Readiness | Reach Ready only after all entered participants succeeded and the lifetime still accepts work. After each await check ending/cancellation before advancing. A participant returning successfully after ignoring cancellation cannot make an ended lifetime Ready or invoke later participants. |
| TryActivate | Return false outside Ready; a duplicate call in Running has no effects. Activate prepared participants in order exactly once. Reach Running only after every activation succeeds. If one fails, record failure, request stop and release all entered participants through the one cleanup path. No partial-running success. |
| RequestStop | Synchronously close new-work/activation admission and request cancellation once, without joining pending work. Safe when called during preparation, activation or another stop request. A participant requesting cancellation must not await a join on its own unfinished PrepareAsync. |
| StopAsync | Request stop and return the shared join/cleanup operation. Wait for entered preparation to finish/acknowledge cancellation before releasing that participant. Do not destroy/reuse its resources while it can still write them. Concurrent/repeated stop callers share the operation. |
| Release | Release entered participants in reverse order exactly once, including the partially prepared or activation-failing participant. Skip participants never entered. Continue remaining cleanup after a Release throws and report accumulated failures. Never claim successful cleanup when releases failed. |
| End state | Stopped means no owned preparation remains and every entered participant has had its Release attempt. Preserve explicit failure information for the caller; cancellation is not success or a completed-game result. Dispose owned cancellation resources after joins/cleanup, keeping read-only final identity/outcome usable. |
| Restart/retry | Create a new RunLifetime and fresh RunId/context. Never clear flags to reactivate a disposed instance. Old context tokens are cancelled and old activation calls remain rejected; a new lifetime cannot mutate the previous one. |
Re-entrancy matters even on one thread: participant callbacks may request stop or invoke duplicate admission. Install operation ownership before callbacks; after each synchronous activation also check stop admission before activating the next participant or declaring Running. Reject unsupported attempts predictably rather than recursively starting work.
If a participant never completes after cancellation, stopping remains pending. Surface the outstanding participant in the checking/adapter diagnostics; a watchdog can fail verification, but cannot pretend the owned work was safely stopped. No forced timeout-completion or resource reuse in the core. This is the conservative lifecycle choice, not an indefinite gameplay loading policy; real participant integrations must supply cancellable work and an explicit failure/recovery path.
R1a exposes current phase/context and explicit outcome to the owner. It adds no phase notification API until R1b has a real presentation/scene consumer. That later scoped notification must follow the event contract; it cannot become a global bus or an alternate command path.
Focused verification¶
These requirements were executed in batch 35: all nine groups passed in the required Editor. The batch records exact evidence/limits; this table remains the regression specification. Use controlled completion sources and ordered effect logs rather than real-time sleeps. An Editor check runner must finish with a nonzero exit on any failed check and distinguish a runner timeout from a passing case.
| Group | Scenario and pass condition |
|---|---|
| L01 · Validation | Null/empty collection, null participant, blank/duplicate IDs and duplicate object references are rejected before any participant call. A valid caller-owned collection cannot change the coordinator's copied sequence afterward. |
| L02 · Readiness and order | Hold the first/last Prepare task pending. No Ready, activation or later preparation occurs early; successful completion yields one Ready transition. Explicit activation occurs in declared order once. |
| L03 · Duplicate/re-entrant admission | Call Prepare twice while pending and after completion; attempt activation before Ready and twice after Ready. One preparation/activation effect per participant. RequestStop from a prepare/activate callback cannot start another participant or produce Running. |
| L04 · Cancel before/during preparation | Stop Created and at each pending preparation boundary. Token cancellation is immediate; late successful preparation cannot set Ready. Entered participants release once in reverse order; never-entered participants are untouched. |
| L05 · Failure rollback | Inject a synchronous Prepare throw, faulted Prepare task and activation throw after a prior successful participant. Every entered participant receives one release attempt; no Running success or dangling owned task, and the original failure remains visible. |
| L06 · Cleanup and joining | Call stop repeatedly while preparation remains pending. No early release or false Stopped. Complete it, then inject release failures: remaining releases still occur, terminal outcome reports failures and no release is repeated. |
| L07 · Non-cooperative work | Ignore cancellation in a controlled pending Prepare. Stop remains pending until that task completes; the harness reports pending owner. After completion, no Ready/activation/next participant, then proper cleanup. No sleeping or pretending a timed-out operation was released. |
| L08 · New lifetime isolation | Construct and stop at least three independent lifetimes, then complete work from an old cancelled lifetime. RunIds differ, old activation stays rejected, and a new lifetime's phase/effect log remains unchanged. |
| L09 · Production isolation and compilation | Compile using the required Editor. Existing source/content/settings/package hashes and production scene list remain unchanged; no references from existing runtime scripts/assets to the new owner, no old GameEvents/static service access or Unity Time mutation in the new core. Runtime scripts have no UnityEditor reference. This is isolation evidence, not a gameplay/IL2CPP pass. |
Use the current Unity CLI workflow and its preservation procedure. Before any Editor invocation inspect the active Editor/project ownership and preserve pre-run bytes, dirty state and normal profile/preferences; Editor tooling may update engine preferences even though the checks use no game IO. Do not launch a second Editor against a checkout held by another Editor. Do not print token-bearing process arguments.
Run the matching 6000.2.8f1 Editor with -batchmode -nographics -projectPath and the check entry above, explicit temporary -logFile, when project ownership permits. If the entry uses async continuation/update scheduling, let it own EditorApplication.Exit; do not combine an immediate -quit with unfinished work or block the Unity synchronization context. Use a bounded runner watchdog and preserve its actual handle/exit status/log. No full player build is needed for this plain lifecycle slice; Linux player/IL2CPP and physical-input evidence belong to later integrated slices.
Record actual group outcomes and any excluded fixture failures in batch 35, along with new source/meta hashes. Restore only attributed generated package/settings/preferences changes to captured pre-run bytes. Do not restore HEAD over preexisting user work. No new gameplay performance or full-playthrough claim follows from these checks.
Compatibility, rollout and rollback¶
There is no bridge or serialized call to migrate in R1a: no existing object references the new classes. The compatibility seam is the future explicit run entry; existing production initialization remains authoritative until that adapter is introduced and its affected scenes are verified. Do not redirect GameInitialization to a half-built coordinator or install a second authority beside GameManager.
Rollback before integration removes only the four new files and their new folder/file metadata, using an exact added-file manifest and verifying no references were introduced. Preserve all preexisting source/assets, batches 30–34, unresolved audio deletions, generated Linux metadata and local recovery data. If already committed by later explicit request, revert only the scoped addition normally; do not reset or rewrite shared history. No commit/push is implied by implementation or verification.
Batch 36 now implements/verifies that R1b integration: the shared Assets/Scenes/Gameplay.unity, RunSceneHost/RunSceneBindings, Editor-only development window and seven passing import/PlayMode groups. It has no dummy assets, legacy service/bootstrap entry or production build-list change. F0's no-actor scene/lifecycle scenarios are verified, including reload and stale work. Batch 37 now verifies R2a roster/device ownership; per-slot action/session/context work is next, with the existing production entry still unchanged.
This verifies F0 only for its declared scene/lifecycle scope; full gameplay acceptance remains pending. R2 then adds the approved roster/input/production-player assembly, R3 the motor/vitals/passive target, R4 ability/weapon ownership and later effects, then stages/rewards/UI as the main dependency plan states. No dummy motor, copied Tutorial player, second test-game loop or speculative services are needed to demonstrate R1a.