diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 36948f8..98c5ad1 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,2 +1,2 @@ {"type":"meta","next_id":{"DSC":2,"AGD":2,"DEC":2,"PLN":5,"LSN":1,"CLSN":1}} -{"type":"discussion","id":"DSC-0001","status":"accepted","ticket":"world-editor-journey-spec","title":"World Editor / Journey Spec","created_at":"2026-06-19","updated_at":"2026-06-19","tags":["world-editor","journey","stage-contract","architecture"],"agendas":[{"id":"AGD-0001","file":"AGD-0001-world-editor-journey-spec.md","status":"accepted","created_at":"2026-06-19","updated_at":"2026-06-19"}],"decisions":[{"id":"DEC-0001","file":"DEC-0001-world-editor-journey-v1.md","status":"accepted","created_at":"2026-06-19","updated_at":"2026-06-19","ref_agenda":"AGD-0001"}],"plans":[{"id":"PLN-0001","file":"PLN-0001-world-journey-spec.md","status":"review","created_at":"2026-06-19","updated_at":"2026-06-19","ref_decisions":["DEC-0001"]},{"id":"PLN-0002","file":"PLN-0002-journey-runtime-model.md","status":"review","created_at":"2026-06-19","updated_at":"2026-06-19","ref_decisions":["DEC-0001"]},{"id":"PLN-0003","file":"PLN-0003-world-editor-authoring.md","status":"review","created_at":"2026-06-19","updated_at":"2026-06-19","ref_decisions":["DEC-0001"]},{"id":"PLN-0004","file":"PLN-0004-journey-commit-validation.md","status":"review","created_at":"2026-06-19","updated_at":"2026-06-19","ref_decisions":["DEC-0001"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0001","status":"accepted","ticket":"world-editor-journey-spec","title":"World Editor / Journey Spec","created_at":"2026-06-19","updated_at":"2026-06-19","tags":["world-editor","journey","stage-contract","architecture"],"agendas":[{"id":"AGD-0001","file":"AGD-0001-world-editor-journey-spec.md","status":"accepted","created_at":"2026-06-19","updated_at":"2026-06-19"}],"decisions":[{"id":"DEC-0001","file":"DEC-0001-world-editor-journey-v1.md","status":"accepted","created_at":"2026-06-19","updated_at":"2026-06-19","ref_agenda":"AGD-0001"}],"plans":[{"id":"PLN-0001","file":"PLN-0001-world-journey-spec.md","status":"done","created_at":"2026-06-19","updated_at":"2026-06-19","ref_decisions":["DEC-0001"]},{"id":"PLN-0002","file":"PLN-0002-journey-runtime-model.md","status":"review","created_at":"2026-06-19","updated_at":"2026-06-19","ref_decisions":["DEC-0001"]},{"id":"PLN-0003","file":"PLN-0003-world-editor-authoring.md","status":"review","created_at":"2026-06-19","updated_at":"2026-06-19","ref_decisions":["DEC-0001"]},{"id":"PLN-0004","file":"PLN-0004-journey-commit-validation.md","status":"review","created_at":"2026-06-19","updated_at":"2026-06-19","ref_decisions":["DEC-0001"]}],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0001-world-journey-spec.md b/discussion/workflow/plans/PLN-0001-world-journey-spec.md index 63b48aa..462d05e 100644 --- a/discussion/workflow/plans/PLN-0001-world-journey-spec.md +++ b/discussion/workflow/plans/PLN-0001-world-journey-spec.md @@ -2,7 +2,7 @@ id: PLN-0001 ticket: world-editor-journey-spec title: World Editor / Journey V1 Spec -status: review +status: done created: 2026-06-19 decisions: - DEC-0001 diff --git a/specs/world-editor-journey-v1.md b/specs/world-editor-journey-v1.md new file mode 100644 index 0000000..c669dc8 --- /dev/null +++ b/specs/world-editor-journey-v1.md @@ -0,0 +1,229 @@ +# World Editor / Journey V1 Specification + +Source decision: `discussion/workflow/decisions/DEC-0001-world-editor-journey-v1.md` + +## Purpose + +The World Editor defines the macro-world contract for Gardens of Nil. It does not edit internal Stage content. Journey is the runtime-readable logical graph published from the World Editor. + +This specification defines the V1 authoring and runtime boundary. + +## Ownership Boundary + +The World Editor SHALL own: + +- macro WorldLayers; +- WorldTile occupancy; +- logical Stage placement; +- Journey endpoints; +- Journey connections; +- commit-time validation; +- publication of logical Journey data. + +The Stage Editor SHALL own: + +- internal Stage geometry; +- floors inside a Stage; +- Stage props; +- Stage objects; +- Stage scene generation; +- Stage bake. + +The World Editor commit MUST NOT create Stage scenes, Stage geometry, internal Stage objects, or baked Stage content. + +## Authoring Asset + +`WorldLayoutSO` is the editor-only authoring ScriptableObject for the World Editor. + +`WorldLayoutSO` MUST contain: + +- a stable layout id; +- `worldTileSize`, defaulting to `24m`; +- `worldLayerHeight`, defaulting to `24m`; +- authoring Stage records; +- occupied WorldTiles per Stage; +- authoring endpoint records; +- authoring connection records; +- editor metadata. + +`worldTileSize` and `worldLayerHeight` MUST be configurable. V1 defaults are `24m`. + +`WorldLayoutSO` MAY reference editor-only Stage authoring data, including `StageDefinition`, but runtime code MUST NOT consume `WorldLayoutSO`. + +## Runtime Asset + +`JGraphSO` is the runtime Journey ScriptableObject. + +Journey elements MUST use the `J` prefix. Journey ScriptableObjects MUST also use the `SO` suffix. + +`JGraphSO` MUST contain: + +- `sourceWorldLayoutId`; +- `publishedAt`; +- `schemaVersion`; +- optional `contentHash`; +- `JStage` records; +- `JEndpoint` records; +- `JConnection` records. + +Runtime Journey code MUST consume `JGraphSO`. Runtime Journey code MUST NOT depend on `WorldLayoutSO`, `StageDefinition`, or any type under `Assets/Scripts/Editor`. + +## World Model + +The World Editor is 2D per `WorldLayer`. + +A Stage: + +- belongs to exactly one `WorldLayer`; +- occupies a set of WorldTiles; +- MUST NOT overlap another Stage on the same WorldLayer tile. + +A WorldTile can be occupied by at most one Stage within a WorldLayer. + +All physical space MUST belong to a Stage. `JConnection` MUST NOT own physical space. If a corridor, transition room, long lift, loading mask, or similar physical traversal space is needed, it MUST be represented as a Stage. + +## JStage + +`JStage` is the runtime logical representation of a Stage inside `JGraphSO`. + +`JStage` MUST have a stable GUID/string id. Tags MAY be used for classification and lookup, but tags MUST NOT replace stable identity. + +`JStage` is not Stage scene generation data and is not Stage bake data. + +## Endpoints + +Initial endpoint types are: + +- `JEndpointSocket`; +- `JEndpointAnchor`; +- `JEndpointLift`. + +Every endpoint MUST have: + +- a stable GUID/string id; +- an owning `JStage` id; +- a WorldTile coordinate; +- an endpoint type; +- a required/optional flag. + +### JEndpointSocket + +`JEndpointSocket` represents a physical side connection on a free tile face. + +It MUST: + +- exist only on a free face of a Stage WorldTile; +- use one of `North`, `South`, `East`, or `West`; +- accept at most one `JConnection`; +- connect only to another `JEndpointSocket`. + +Socket-to-socket physical connections MUST connect opposite faces on adjacent WorldTiles. + +### JEndpointAnchor + +`JEndpointAnchor` represents an abstract travel point such as a portal, hub, or fast-travel anchor. + +It MAY have multiple `JConnections`. Runtime destination selection for multi-connection anchors is outside V1. + +### JEndpointLift + +`JEndpointLift` represents macro vertical travel between WorldLayers. + +It MUST: + +- accept exactly one `JConnection` in V1; +- connect only to another `JEndpointLift`; +- align on the same 2D WorldTile coordinate as its paired lift; +- connect across different WorldLayers. + +## Endpoint Coexistence + +A WorldTile MAY contain sockets and one non-socket endpoint. + +`JEndpointAnchor` and `JEndpointLift` MUST NOT coexist on the same WorldTile. + +Sockets MAY coexist with anchors or lifts. + +## Connections + +`JConnection` is a logical edge between exactly two endpoints. + +`JConnection` MUST: + +- have a stable GUID/string id; +- reference endpoint A by id; +- reference endpoint B by id; +- connect endpoints of compatible type; +- not own physical space. + +Endpoint compatibility in V1 is same-type only: + +- socket to socket; +- anchor to anchor; +- lift to lift. + +Directionality MAY be represented in V1. Concrete requirement modeling and loading hints are outside V1, but `JConnection` SHOULD remain extensible so those fields can be added later. + +## Commit Flow + +The World Editor SHALL publish Journey data through an explicit commit action. + +The commit action MUST: + +- validate `WorldLayoutSO`; +- abort if commit-blocking errors exist; +- allow publication when only warnings exist; +- create or update `JGraphSO`; +- write `JStage`, `JEndpoint`, and `JConnection` records; +- write publication metadata. + +The commit action MUST NOT: + +- generate Stage scenes; +- generate Stage geometry; +- generate internal Stage objects; +- run Stage bake; +- write Stage Editor content. + +## Validation + +Commit-blocking errors include: + +- same-layer WorldTile overlap between Stages; +- connection referencing a missing endpoint; +- connection linking an endpoint to itself; +- incompatible endpoint types; +- socket with more than one connection; +- socket on an internal Stage face; +- socket connected to a non-opposite or non-adjacent socket; +- anchor and lift on the same WorldTile; +- lift connected to a lift with a different 2D coordinate; +- required endpoint without connection. + +Warnings include: + +- optional endpoint without connection; +- Stage without endpoints; +- authoring metadata missing from non-critical fields. + +## Editor Technology + +World Editor V1 SHALL use the same window technology as the existing Stage Editor: + +- `EditorWindow`; +- UI Toolkit via `UnityEngine.UIElements` and `UnityEditor.UIElements`; +- custom canvas based on `VisualElement.generateVisualContent`. + +Stage Editor integration remains manual in V1. + +## V1 Non-Goals + +V1 does not include: + +- loading hints; +- streaming policies; +- concrete `JRequirement` structures; +- runtime destination selection UI or logic for multi-connection anchors; +- deep Stage Editor marker sync; +- automatic Stage Editor opening from the World Editor; +- unified World/Stage Editor shell.