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
- Canonical types carry no presentation state.
Scp.Domainentity/assertion/agent-work types have no position, rotation, scale, color, visibility, or layout fields. Ever. WorkspaceStateis 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.- 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 apinned: trueplacement to the workspace. Re-layout never moves pinned placements. - Persistence for POC is a local JSON
WorkspaceStatefile on-device viaIWorkspaceStore(contract-shaped, ADR-SCP-004). A workspace service (S4+) replaces the adapter, not the model. - Enforcement:
Scp.Domain/Scp.Contractsexpose no vector/quaternion types except insideWorkspaceStateDTOs; a rung-1 architecture test asserts canonical DTOs contain nopos|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
ViewModeljoin step inScp.Appkeeps 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.
Related
- [[ADR-SCP-004-Contract-First-Projection-Wire-Format]] —
WorkspaceStatedocument shape - [[ADR-SCP-002-Engine-As-Adapter-Unity-Client]] — where the enforcement lives