From bb45afef3386a1e0d1b20fe1a55f97aab1f6db0e Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 26 Jul 2026 10:25:46 +0200 Subject: [PATCH] docs(runtime): plan simulation ownership Inventory the present selection, interaction, combat, movement, physics, and projectile owners; pin named-retail ordering; and define independently reversible J5.1-J5.7 gates without moving presentation into Runtime. Co-authored-by: Codex --- .../2026-07-25-modern-runtime-slice-j.md | 3 + .../2026-07-26-modern-runtime-slice-j5.md | 378 ++++++++++++++++++ ...ice-j5-owner-and-retail-order-inventory.md | 207 ++++++++++ 3 files changed, 588 insertions(+) create mode 100644 docs/plans/2026-07-26-modern-runtime-slice-j5.md create mode 100644 docs/research/2026-07-26-slice-j5-owner-and-retail-order-inventory.md diff --git a/docs/plans/2026-07-25-modern-runtime-slice-j.md b/docs/plans/2026-07-25-modern-runtime-slice-j.md index 3addd7f7..5c710afa 100644 --- a/docs/plans/2026-07-25-modern-runtime-slice-j.md +++ b/docs/plans/2026-07-25-modern-runtime-slice-j.md @@ -280,6 +280,9 @@ J4 must borrow it rather than create another inventory model. **Active 2026-07-26.** Detailed execution begins with a source/owner inventory and a named-retail ordering matrix. Each coherent move must preserve the accepted connected interaction, facing, projectile, and collision behavior. +The executable sub-slice ledger, presentation boundary, acceptance gates, and +rollback discipline live in +[`2026-07-26-modern-runtime-slice-j5.md`](2026-07-26-modern-runtime-slice-j5.md). - Move presentation-free movement interpretation, authoritative/predicted physics state, selection identity, approach/use transactions, combat intent, diff --git a/docs/plans/2026-07-26-modern-runtime-slice-j5.md b/docs/plans/2026-07-26-modern-runtime-slice-j5.md new file mode 100644 index 00000000..7ff4cb48 --- /dev/null +++ b/docs/plans/2026-07-26-modern-runtime-slice-j5.md @@ -0,0 +1,378 @@ +# Modern runtime Slice J5 — movement, physics, interaction, and combat + +**Status:** ACTIVE — J5.1 next +**Parent:** `2026-07-25-modern-runtime-slice-j.md`, J5 +**Production base:** `2c67a2c3` +**Authorization:** the user approved Slices F–L, including the Slice J +gameplay-owner gates, on 2026-07-24 + +## Objective + +Move the complete presentation-independent action and simulation graph into +`AcDream.Runtime` while preserving retail behavior and the accepted graphical +feel. + +At completion: + +- Runtime owns selection, interaction mode/transactions, combat and spell-cast + intent, local/remote movement, outbound cadence, per-session physics, and + projectile simulation; +- App converts physical input into typed commands and projects committed state + into cameras, retained UI, animation, sound, particles, markers, and meshes; +- graphical and future no-window hosts borrow the same owners and observe the + same ordered state; +- no render callback, UI element, or camera object is gameplay authority. + +## Presentation boundary + +### Moves to Runtime + +- selected/previous object identity; +- temporary use/examine/use-item-on-target mode; +- appraisal/use/pickup/approach transaction identity; +- combat mode, attack build/request/repeat intent, target identity; +- spell-cast request intent; +- `PlayerMovementController` state, movement interpretation, canonical local + body, object clock, movement managers, and outbound cadence; +- per-session `PhysicsEngine`, transition scratch, shadow/collision gameplay + state; +- remote canonical body/movement state; +- projectile component state and simulation; +- typed views, commands, ordered events, reset, disposal, and ownership + ledgers for all of the above. + +### Remains in App + +- Silk input sources and configurable key/chord mapping; +- camera orbit, mouse cursor capture, and device-delta filtering; +- world ray construction/picking; +- selection lighting pulse, vivid markers, and selected-object HUD; +- combat/spell bars and retained target-mode cursor images; +- animated part/root pose composition; +- meshes, terrain/EnvCell streaming publication, sounds, particles, lights, + translucency, and debug drawing; +- UI text, toasts, drag/drop visuals, pending-slot mesh, and appraisals' + retained window. + +The camera's instant mouse-look mode still emits typed retail turn/sidestep +commands to Runtime. The camera may not write the player heading directly. + +## Fixed invariants + +1. Retail algorithms and branch/order semantics do not change during the move. +2. One mutable owner exists for every state class. +3. Runtime has no App/UI/backend dependency. +4. `RuntimeEntityRecord` remains canonical entity identity and physics + authority; App `LiveEntityRecord` remains a projection sidecar. +5. `RuntimeInventoryState` remains the only busy/inventory-transaction owner. +6. Core flat collision data is immutable/shareable. Each runtime/session owns + its `PhysicsEngine`, transition scratch, bodies, shadows, interpolation, and + projectile state. +7. All mutation stays on the existing update thread. Network workers enqueue + immutable messages only. +8. App input-to-Runtime commands are synchronous; no extra frame, polling + mirror, or background queue is introduced. +9. App presentation callbacks may re-enter/delete/replace entities. Every + continuation revalidates exact record, incarnation, authority version, and + object-clock epoch before commit. +10. Reset/disposal executes every suffix after an observer failure and refuses + a new session until the complete ownership ledger converges. +11. Every sub-slice is independently buildable, tested, connected-gated where + behavior can change, documented, committed, and given an exact rollback. + +## Execution ledger + +| Sub-slice | Status | Result/evidence | +|---|---|---| +| J5.0 owner/retail inventory | complete | `docs/research/2026-07-26-slice-j5-owner-and-retail-order-inventory.md` | +| J5.1 canonical action state | next | selection, combat state, target-mode owner | +| J5.2 interaction transactions | pending | use/appraisal/pickup/approach state and transport ordering | +| J5.3 combat and magic intent | pending | attack/mode/target/cast owners and typed input | +| J5.4 local movement and outbound cadence | pending | controller, body, movement managers, MTS/AP/jump cadence | +| J5.5 per-session physics and remote simulation | pending | engine/scratch/shadows/remote canonical body | +| J5.6 projectile runtime | pending | canonical component/simulation plus App projection acknowledgements | +| J5.7 combined cleanup and closeout | pending | no mirrors, no-window parity, teardown, connected and visual gates | + +## J5.1 — canonical action state + +Create one Runtime owner for: + +- `SelectionState`; +- `CombatState`; +- presentation-free interaction/target-mode state. + +Actions: + +1. Move interaction-mode types/state from App UI into Runtime gameplay. +2. Make Runtime construct all three exact owners. +3. Remove Program's selection construction and GameWindow's direct combat + construction. +4. Make App composition, session routing, retained UI, plugins, and current + Runtime commands/views borrow the exact Runtime instances. +5. Remove `ItemInteractionController`'s optional private + `InteractionState` fallback; production and tests must pass the exact owner. +6. Add a combined ownership/revision snapshot and failure-safe reset/disposal. +7. Add Runtime views for selection, combat mode/known health, and interaction + mode without exposing mutable collections. + +Gate: + +- named-retail selection order and deduplication; +- combat Begin/reset defaults; +- target-mode enter/acquire/cancel/reset; +- UI/plugin observer failure isolation; +- two Runtime instances in one process; +- exact graphical/direct owner identity; +- source guard proving App cannot construct a production owner; +- Runtime dependency and assembly-load closure; +- focused Runtime/App tests, Release build, full Release suite, connected + lifecycle/reconnect route. + +## J5.2 — interaction transactions + +Split App orchestration into: + +- App `WorldSelectionQuery`/picker/lighting/drag presentation; +- Runtime interaction transaction owner; +- typed query, movement, inventory-policy, transport, and presentation + acknowledgement seams. + +Runtime owns: + +- use throttle and source/target identity; +- appraisal request/current identity; +- ordinary use reservation transfer to authoritative UseDone; +- pickup request and exact post-arrival identity/token; +- ordered outbound interaction queue; +- entity-hidden/deleted cancellation; +- reset/disposal convergence. + +App retains: + +- cursor position and world ray; +- lighting pulse; +- toasts/text rendering; +- retained drag/drop and pending-slot drawing. + +Ordering: + +- ordinary Use sends immediately, then transfers its busy reservation to + UseDone; +- targeted Use enters mode until a compatible target is acquired; +- pickup's same-frame send drains after local movement output and before + inbound dispatch; +- post-arrival pickup sends once only on natural completion; +- stale/replaced object identities never execute queued work. + +Gate: + +- current connected near/far door/NPC/corpse use; +- item-on-target, appraisal, pickup, pending-slot accept/failure; +- same-frame W-release plus R; +- delete/GUID reuse, hidden target, cancellation, transport failure, callback + reentrancy, reset/disposal; +- normalized graphical/direct ordered traces and no duplicate busy owner. + +## J5.3 — combat and magic intent + +Move: + +- `CombatAttackController`'s presentation-free build/request/repeat state; +- combat-mode selection/default policy; +- target death/auto-target identity transitions; +- `SpellCastingController` intent and last-request state. + +Replace `InputAction` dependencies with Runtime-specific typed commands. +App maps configured actions and bar/button presses onto those commands and +projects Runtime snapshots. + +Keep App-only: + +- combat/spell bar widgets; +- camera target tracking; +- animation, sound, particles, and response text layout; +- DAT catalog/icon/formula presentation. + +Ordering: + +- movement aborts repeat attack at the existing retail input boundary; +- targeted attack/cast turns through the shared movement owner before + release; +- cast stops movement, emits exactly one targeted/untargeted request, then + increments the shared busy reference; +- server attack/cast completion remains authoritative. + +Gate: + +- power-bar cadence and height selection; +- repeat start/abort/movement cancellation; +- combat-mode equipment defaults; +- 180-degree bow/spell target facing; +- hostile-only auto-target after death; +- self/untargeted/targeted spell requests, component failure, busy completion; +- graphical bar parity and direct typed-command parity. + +## J5.4 — local movement and outbound cadence + +Move `PlayerMovementController`, its data types, and +`LocalPlayerOutboundController` into Runtime. Replace test-era environment +reads with typed construction options and the Runtime character movement-skill +projection. + +App provides: + +- current typed movement snapshot from the input dispatcher; +- filtered mouse-look turn adjustment; +- animation root-motion frame and completion acknowledgements; +- optional diagnostic sink. + +Runtime owns: + +- canonical local `PhysicsBody`, `MotionInterpreter`, `MovementManager`, + `MoveToManager`, `PositionManager`, and object clock; +- local input edge interpretation; +- run lock, jump charge/launch, movement/contact state; +- target-facing movement; +- pre-inbound MTS/jump and post-inbound autonomous-position send cadence; +- complete canonical `Position`, contact-plane, timestamps, and sent baselines. + +Gate: + +- bit-exact `RawMotionState`, MTS, jump, and autonomous-position fixtures; +- strict cadence/equality boundaries; +- complete quaternion/cell-local frame; +- short-tap animation-owned start; +- run/walk/back/strafe/turn/mouse-look/jump/land; +- portal/focus/reset teardown; +- target-facing and movement-aborts-repeat ordering; +- zero added per-frame allocations after warmup. + +## J5.5 — per-session physics and remote simulation + +Add a Runtime physics owner that constructs one `PhysicsEngine` per runtime +instance. App streaming publishes immutable prepared collision assets through +typed admission/withdrawal acknowledgements. + +Move canonical remote simulation state and component indexes from App sidecars +to `RuntimeEntityRecord`/Runtime owners: + +- remote body/interpolation/movement-manager state; +- canonical cell/rebucket writes; +- physics-host lookup; +- shadow/collision gameplay membership; +- ordinary-object update workset. + +App consumes committed snapshots/events to: + +- update `WorldEntity`; +- rebucket render projections; +- publish current root/part/equipped-child poses; +- refresh graphical collision/debug views. + +Gate: + +- complete flat collision conformance corpus remains bit-identical; +- fresh/reused engine parity and zero-allocation resolve profiles; +- player and remote position/cell/orientation parity; +- crowd de-overlap, doors, stairs, dungeon/cell seams, login placement; +- hidden/pending/rehydration, teleport correction, delete/GUID reuse; +- two concurrent Runtime instances prove scratch/shadow isolation. + +## J5.6 — projectile runtime + +Move projectile component identity, prediction versions, and simulation into +Runtime. Store the canonical component on `RuntimeEntityRecord`, not the App +sidecar. + +Runtime uses: + +- existing Core `ProjectilePhysicsStepper`; +- canonical body/cell/state/timestamp authority; +- strict prepared collision shapes; +- existing split Begin/Complete prediction with exact-version revalidation. + +App acknowledges successful commits by: + +- updating/rebucketing the render projection; +- synchronizing graphical shadow representation; +- publishing effect root/pose. + +App does not decide collision outcome, impact, damage, effect, or deletion. + +Gate: + +- existing clamp/gravity/AlignPath/angular/collision/thin-wall fixtures; +- designated-target exclusion semantics; +- loaded/pending/cross-landblock/correction/delete/GUID-reuse; +- 96-owner lifetime/effect stress; +- no duplicated mesh, effect, shadow, body, or script owner; +- arrow, bolt, and representative spell projectile connected route. + +## J5.7 — combined cleanup and closeout + +Delete: + +- temporary App owner fields and construction fallbacks; +- App simulation component dictionaries; +- current-runtime adapters that reconstruct moved snapshots; +- reset/disposal branches replaced by Runtime; +- compatibility aliases after all consumers borrow Runtime. + +Add: + +- one J5 ownership ledger; +- failure injection at every construction, subscription, command, projection + acknowledgement, reset, and disposal boundary; +- graphical/direct normalized traces; +- Runtime-only movement/use/combat/cast/projectile fixture host; +- source/dependency guards against App/backend leakage and duplicate owners. + +Run: + +1. focused Core physics/selection/combat tests; +2. Runtime state/command/event/teardown tests; +3. App input/interaction/combat/magic/physics/projectile tests; +4. Release build and complete Release suite; +5. exact-binary lifecycle/reconnect route; +6. canonical nine-stop movement/combat/jump route; +7. connected interaction, casting, projectile, portal, and reconnect route; +8. user graphical feel gate for movement, facing, use, combat/cast bars, and + visible missiles; +9. architecture, divergence, issue, roadmap, AGENTS/CLAUDE, and durable-memory + reconciliation. + +## Commit and rollback discipline + +Each sub-slice lands as one independently reversible production commit followed +by a documentation/evidence checkpoint where needed. + +Planned production commit sequence: + +1. `refactor(runtime): own canonical action state` +2. `refactor(runtime): own interaction transactions` +3. `refactor(runtime): own combat and magic intent` +4. `refactor(runtime): own local movement and outbound cadence` +5. `refactor(runtime): own per-session physics simulation` +6. `refactor(runtime): own projectile simulation` +7. `refactor(runtime): close simulation ownership` + +Record each full SHA and exact `git revert ` command in this file before +running its connected gate. Revert J5 groups in reverse order. Do not revert +J4 or the flat-collision Slice I cutover to mask a J5 ownership failure. + +## Acceptance + +J5 is complete only when: + +- every listed presentation-free owner is constructed by Runtime; +- App owns presentation only and borrows exact Runtime state; +- graphical and no-window commands produce the same ordered state and packets; +- collision and trajectory fixtures remain bit-identical; +- reset, reconnect, same-process multiple-instance, GUID reuse, and failure + injection converge every owner; +- no extra frame or per-frame allocation regression exists; +- complete Release and connected gates pass; +- the user accepts graphical movement, facing, interaction, combat/casting, + and projectile behavior; +- architecture, roadmap, milestones, issues/divergences, AGENTS/CLAUDE, + evidence, memory, and rollback instructions are synchronized. diff --git a/docs/research/2026-07-26-slice-j5-owner-and-retail-order-inventory.md b/docs/research/2026-07-26-slice-j5-owner-and-retail-order-inventory.md new file mode 100644 index 00000000..be9c37c4 --- /dev/null +++ b/docs/research/2026-07-26-slice-j5-owner-and-retail-order-inventory.md @@ -0,0 +1,207 @@ +# Slice J5 owner and retail-order inventory + +**Date:** 2026-07-26 +**Scope:** presentation-free selection, interaction, combat/magic intent, +movement/outbound cadence, physics, and projectile ownership +**Parent plan:** `docs/plans/2026-07-26-modern-runtime-slice-j5.md` + +## Purpose + +Slice J5 moves gameplay simulation and intent out of the graphical App and into +`AcDream.Runtime`. This note pins the current production owners and the retail +ordering that cannot change while those owners move. + +This is an ownership refactor, not a new movement, combat, interaction, or +projectile implementation. Existing retail ports remain the behavioral oracle. + +## Current source ownership + +| Concern | Current canonical state | Construction/root | Presentation coupling to split | +|---|---|---|---| +| Selection identity | `AcDream.Core.Selection.SelectionState` | `Program` constructs; `GameWindow` retains | world ray picking, lighting pulse, vivid markers, status/UI projections | +| Combat notifications/mode | `AcDream.Core.Combat.CombatState` | `GameWindow` constructs | combat/spell bars, camera target tracking, feedback | +| Pointer target mode | `AcDream.App.UI.InteractionState` | optional private construction inside `ItemInteractionController` | cursor image only; state itself is presentation-free | +| Item-use/appraisal/pickup intent | `ItemInteractionController`, `SelectionInteractionController`, `InventoryTransactionState` | App retained-UI and live-presentation composition | world picking, retained drag/drop, toasts, pending-slot mesh | +| Combat attack intent | `CombatAttackController`, `LiveCombatModeCommandController` | App retained-UI/session composition | input action mapping and combat-bar projection | +| Spell-cast intent | `SpellCastingController` inside App `MagicRuntime` | App content/UI composition | DAT catalog loading, component icons/text, spell bar | +| Local movement | `PlayerMovementController` plus Core `PhysicsBody`, `MotionInterpreter`, `MovementManager` | App player-mode composition | Silk/input sampling, camera/mouse-look device state, animated pose publication | +| Outbound movement cadence | `LocalPlayerOutboundController` | `GameWindow` constructs | App diagnostic sink only | +| Per-session collision | Core `PhysicsEngine`, `ShadowObjectRegistry`, transition scratch | `GameWindow` constructs | streaming publishers and debug visualization | +| Remote movement/physics | App `RemotePhysicsUpdater`, `RemoteInboundMotionDispatcher`, live sidecars | App composition | `WorldEntity`, render projection, animation pose/effect publication | +| Projectile simulation | Core `ProjectilePhysicsStepper` plus App `ProjectileController.Runtime` | App live-presentation composition | `WorldEntity`, effect pose, shadow publication | + +`RuntimeEntityRecord` already owns canonical accepted identity, timestamps, +full cell, raw/final physics state, object clock, `PhysicsBody`, and +`IPhysicsObjHost`. The App `LiveEntityRecord` is a projection sidecar. J5 must +extend the canonical record rather than add another entity or physics model. + +`RuntimeInventoryState` already owns the exact inventory transaction/busy/use +reservation state. J5 interaction work must borrow that owner and must not +recreate a busy counter or pending inventory request. + +## Current reset ordering + +`LiveSessionResetManifest` currently performs the relevant stages in this +order: + +1. mouse/input capture; +2. player presentation and teleport transit; +3. dialogs/chat/settings; +4. equipped children and external container; +5. interaction plus selection; +6. inventory transactions; +7. selection presentation and object table; +8. spellbook/magic; +9. combat attack and combat state; +10. local-player and remaining session state; +11. live entity teardown; +12. render projection drain and session identity; +13. network effects/presentation tails. + +Runtime ownership may combine internal stages, but App acknowledgements must +retain the same dependency order: presentation releases references before the +canonical owner is destroyed, while old session identity remains available +until exact-incarnation teardown converges. + +## Named-retail ordering matrix + +### Selection + +`ACCWeenieObject::SetSelectedObject @ 0x0058C2E0` + +1. If forced or changed, clear the old object's selected flag. +2. Commit the new selected ID. +3. Set the new object's selected flag. +4. If the ID changed, commit previous and previous-valid IDs. +5. Publish the UI selection notice. +6. Publish the shared item-holder selection change. +7. Notify the plugin API. + +The state commit precedes every observer. Deduplicated selection does not +publish the changed notice. + +### Session combat initialization + +`ClientCombatSystem::Begin @ 0x0056A460` + +1. Commit NonCombat and clear pending mode. +2. Clear jump, build, response, attack, repeat, and tracking transients. +3. Restore medium attack height and UI requested power `0.5`. +4. Register the global notice handler. + +Runtime combat reset must clear the complete intent transaction before App +projects the peace-mode UI. + +### Ordinary use and target mode + +`ItemHolder::UseObject @ 0x00588A80` + +1. Enforce the strict 0.2-second local use gate. +2. Verify inventory-request readiness and vendor restrictions. +3. Resolve automatic wield/use policy and targeted-use policy. +4. For ordinary use, emit `CM_Inventory::Event_UseEvent`. +5. Increment the shared UI busy reference. +6. Invoke `CPlayerSystem::UsingItem` and publish local text. +7. For a targeted item without an acquired target, store the source object and + enter `TARGET_MODE_USE_TARGET`; do not emit the use-with-target packet yet. +8. Once a compatible target is acquired, emit + `Event_UseWithTargetEvent`, increment busy, then invoke `UsingItem`. + +`ClientUISystem::Handle_Item__UseDone @ 0x00564900` + +1. Decrement exactly one busy reference. +2. Refresh cursor state only when the count reaches zero. +3. Present a nonzero server error afterward. + +The current production correction remains authoritative for local ACE: +ordinary Use is sent immediately and ACE owns spatial approach. Pickup retains +the existing ordered local approach transaction and post-arrival send. + +### Local movement output + +`CommandInterpreter::SendMovementEvent @ 0x006B4680` + +1. Require player, SmartBox, raw motion state, and nonzero autonomy. +2. Read the player's current raw state, canonical `Position`, contact state, + long-jump state, and four retail timestamps. +3. build/send `MoveToStatePack`. +4. Stamp `last_sent_position_time` only after send. + +`CommandInterpreter::SendPositionEvent @ 0x006B4770` + +1. Require SmartBox, player, active/in-world transient state, and valid + canonical `Position`. +2. Read current contact and timestamps. +3. build/send `AutonomousPositionPack`. +4. After send, stamp time and copy the complete sent `Position` and contact + plane as the next comparison baseline. + +The existing pre-inbound movement/jump and post-inbound autonomous-position +slots remain unchanged. + +### Object physics + +`CPhysicsObj::UpdatePositionInternal @ 0x00512C30`, +`CPhysicsObj::transition @ 0x00512DC0`, +`CPhysicsObj::SetPositionInternal(CTransition const*) @ 0x00515330`, +and the ordered object tail recorded in +`docs/research/2026-07-19-r6-update-object-order-pseudocode.md` remain the +simulation oracle. + +Runtime owns the canonical body and simulation. App may publish the final +accepted root/part poses only after that simulation result commits. A render +callback must never become position, cell, velocity, or collision authority. + +### Projectile collision exclusion + +`OBJECTINFO::missile_ignore @ 0x0050CEB0` + +The existing Core `ProjectilePhysicsStepper` port remains unchanged: + +- ignore other missiles; +- ignore ethereal weenies unless they are the designated target; +- with a nonzero designated target, ignore other creatures; +- do not infer a designated target from UI selection. + +## Fixed dependency direction + +```text +Silk / retained UI / camera + | + v +App typed input + presentation adapters + | + v +AcDream.Runtime intent/simulation owners + | + v +Core algorithms + Core.Net transport/content seams +``` + +Runtime never references App, Silk, OpenGL, OpenAL, ImGui, Arch, or retained +UI. App may synchronously acknowledge a committed runtime mutation and project +it; it may not keep a second mutable copy. + +## Source hazards + +1. `ItemInteractionController` can currently create a private + `InteractionState`; this is a duplicate-owner seam and must be removed when + J5.1 lands. +2. `Program` currently constructs selection while `GameWindow` constructs + combat. Both must move under one Runtime owner before higher-level + controllers move. +3. `PlayerMovementController` contains environment reads for test-era default + skills. A Runtime move must use typed construction options and the existing + Runtime character skill projection. +4. `LocalPlayerOutboundController` directly accepts `WorldSession` and an App + diagnostic sink. Runtime may use Core.Net, but diagnostics must cross a + narrow optional interface. +5. App `LiveEntityRecord` still stores remote/projectile component interfaces. + Simulation components must migrate to `RuntimeEntityRecord`; only + animation/effect/render projection belongs in the App sidecar. +6. Remote/projectile callbacks can synchronously delete or replace a GUID. + Every split-phase commit must retain the existing exact-record, + incarnation, authority-version, and object-clock-epoch revalidation. +7. `PhysicsEngine` transition scratch is per engine and same-thread LIFO. + Immutable prepared collision content may be shared; the engine and scratch + may not be shared by concurrent sessions.