Cory Policht
← All references
REF · ADR-SCP-005-WORKSPACE-STATE-SEPARATION · ADR

Adr Scp 005 Workspace State Separation

source: Spatial-Cognition-Platform/ADR/ADR-SCP-005-Workspace-State-Separation.mdscrubbed extract

Scrubbed extract of Spatial-Cognition-Platform/ADR/ADR-SCP-005-Workspace-State-Separation.md — cited by the Chronicle (06-extraction-and-divergence). Redactions: phone / service detail / secrets / clearance / personal / internal hosts.


type: project project: Spatial-Cognition-Platform status: accepted created: 2026-08-27 tags:

  • adr
  • experience-plane
  • workspace

ADR-SCP-005: Presentation state lives only in the Workspace plane

Status: Accepted Date: 2026-08-27 Deciders: Solo (Cory) Context Project: [[Spatial-Cognition-Platform]] · [[Concept-Layered-Planes-Architecture]] §6

Context

The concept is explicit: never put XYZ coordinates onto canonical software entities — the same service sits at different positions in different workspaces. In a Unity codebase the gravitational pull is the opposite: transforms are ambient, and “just store the position on the node” is always one lazy commit away. This boundary will erode unless mechanically enforced from day one.

Decision

  1. Canonical types carry no presentation state. Scp.Domain entity/assertion/agent-work types have no position, rotation, scale, color, visibility, or layout fields. Ever.
  2. WorkspaceState is the only home for spatial/visual state (views[].placements[], grouping, visibility, pinning), keyed by canonical id — a placement references an entity; an entity never knows its placements.
  3. Layout is a pure derivation, user movement is an override. Scp.Projection.Layout(snapshot, viewRules, seed) deterministically produces initial placements; when the user grabs and moves an object, the adapter writes a pinned: true placement to the workspace. Re-layout never moves pinned placements.
  4. Persistence for POC is a local JSON WorkspaceState file on-device via IWorkspaceStore (contract-shaped, ADR-SCP-004). A workspace service (S4+) replaces the adapter, not the model.
  5. Enforcement: Scp.Domain/Scp.Contracts expose no vector/quaternion types except inside WorkspaceState DTOs; a rung-1 architecture test asserts canonical DTOs contain no pos|rot|scale-named members. Code review treats a violation as a contract break, not a style nit.

Consequences

Positive

  • Radically different projections (architecture / security / runtime / agent views, S7) of the same truth become data, not refactors.
  • Multi-workspace and future multi-user collaboration need zero canonical-model change.
  • Deterministic layout is golden-file tested by agents headlessly.

Negative / Risks

  • Every render pass joins snapshot × workspace; a ViewModel join step in Scp.App keeps this out of Unity adapters.
  • Pinned placements can go stale when entities disappear from newer snapshots; v0 rule: orphaned placements are dropped at load and logged.

Alternatives Considered

Alternative 1 — Positions on graph nodes (the default temptation)

Rejected because: collapses Experience into Truth; breaks multi-view/multi-workspace permanently; the concept names this the cardinal sin.

Alternative 2 — Unity scene as the persistence layer (serialize the scene)

Rejected because: scene files are engine-locked, unreviewable, agent-hostile, and conflate view instantiation with state.

Alternative 3 — Physics/force simulation owning positions at runtime

Rejected because: non-deterministic, untestable headless, fights user pinning. Force-directed math is welcome inside the pure layout function where it stays seeded and reproducible.

  • [[ADR-SCP-004-Contract-First-Projection-Wire-Format]] — WorkspaceState document shape
  • [[ADR-SCP-002-Engine-As-Adapter-Unity-Client]] — where the enforcement lives