Skip to content

UI Addressing

Purpose

This document fixes the target addressing model for AdaOS browser-facing UI, runtime manifests, projections, and domain-facing operator surfaces.

The goal is not to replace every existing path or identifier with one universal string format. The goal is to define one coherent vocabulary so that:

  • skills and scenarios can be authored by humans and LLMs without guessing
  • browser-facing manifests can bind data and actions safely
  • runtime services can preserve scope and ownership across Yjs, streams, and projections
  • domain-specific surfaces such as device access can reuse the same model

This is a target-state architecture document. Current implementation details remain documented in:

Governing Rules

  1. Do not expose raw storage topology as the primary authoring contract.
  2. Keep logical authoring addresses separate from runtime materialization refs.
  3. Keep domain identity refs separate from state refs and action refs.
  4. Keep scope explicit whenever state may be shared, node-owned, or local.
  5. When skill-owned browser state must stay shared, declare ownership explicitly in the skill manifest rather than relying on client-side exceptions.
  6. Prefer deterministic, typed refs over ad hoc string conventions.
  7. LLM-oriented authoring should use a compact, repetitive vocabulary.

Non-Goals

This document does not require:

  • one URI syntax for every internal AdaOS concept
  • immediate replacement of existing ctx.*, data_projections, or webio.stream.* contracts
  • direct skill authoring against Yjs paths
  • a hard mandate that every ref becomes browser-visible

Addressing Layers

AdaOS now needs one model with several layers, not one flat namespace.

1. Logical authoring layer

This is the layer skills and scenarios should reason about first.

Examples:

  • ctx.user.profile
  • ctx.state.review.selection
  • logical projection slots declared through data_projections

This layer is stable for authoring and should remain storage-agnostic.

2. Projection-routing layer

This is the layer that maps logical state to runtime backends.

Examples:

  • (scope, slot) pairs in data_projections
  • scenario- or skill-owned mapping into Yjs, KV, SQL, or future backends

This layer is authoritative for data placement decisions.

3. Runtime UI binding layer

This is the layer browser-facing manifests and runtime adapters bind to.

Examples:

  • Yjs-backed state refs
  • browser stream receiver refs
  • local view-state refs
  • action refs
  • projection refs

This layer is where semantic UI manifests should live.

4. Domain identity layer

This layer identifies real entities and reusable domain objects.

Examples:

  • device:browser:<device_id>
  • device:member:<node_id>
  • webspace:<webspace_id>

Human-facing names and aliases for these refs are governed by the named-entity layer described in Named Entities and Canonical Naming. The domain ref stays stable when a label changes.

This layer is shared across UI, SDK, runtime, and operator tooling.

Canonical Ref Classes

The target model uses a small typed vocabulary.

Logical refs

Logical refs are authoring-level and storage-agnostic.

Examples:

  • ctx.user.profile
  • ctx.ui.web.desktop
  • ctx.voice.morning.current_step

Runtime state refs

Runtime state refs bind browser-visible state to a concrete runtime-backed state family.

Examples:

  • y:data/reviews/current
  • y:data/nodes/member-01/infrastate/summary
  • y:ui/application

Stream refs

Stream refs identify transport-independent live browser receiver families.

Examples:

  • stream:chat.live
  • stream:infrastate.operations.active

Stream refs identify the semantic receiver family. Webspace targeting, node ownership, and transport preference remain binding properties rather than part of the ref identity itself.

View-state refs

View-state refs identify client-owned interaction state.

Examples:

  • view:filters.status
  • view:columns.enabled
  • view:review.selection

Projection refs

Projection refs identify demanded materialized UI views.

Examples:

  • projection:overview
  • projection:inventory:members
  • projection:modal:workspace-manager

projection_key remains the canonical key within projection payloads. This document treats projection:<projection_key> as the addressing form used when projection identity must participate in a broader ref vocabulary.

Action refs

Action refs identify typed browser-visible or runtime-visible operations.

Examples:

  • action:skill.chat.send
  • action:device_access.rename
  • action:webspace.open

For current compatibility work, one action ref may still resolve through existing callSkill, callHost, or modal-opening behavior. The important boundary is to keep the browser-facing action identity stable even while the underlying compatibility bridge evolves.

Domain refs

Domain refs identify reusable domain entities rather than UI state.

Examples:

  • device:browser:abc123
  • device:member:member-01
  • webspace:desktop

Human names are not refs

Human-facing names such as Kitchen display, ZVERZVE-A1BNQF7, Edge on Windows, or Node 0 are labels, not addressing refs. They may resolve to a domain ref through the named-entity layer. Localized labels and aliases follow the same rule: the active language can change which text is displayed or matched, but it must not change the target domain ref.

Addressing contracts should not encode these labels as routing keys.

Correct shape:

{
  "target": {
    "ref": "device:member:8db40740-b3ff-44bf-baf5-9fb013b35b01",
    "label": "ZVERZVE-A1BNQF7"
  }
}

Avoid:

{
  "target": "ZVERZVE-A1BNQF7"
}

The label is display-only and may change without invalidating the ref.

Scope Model

Addressing is not complete without scope.

The target scope vocabulary is:

  • shared: collaborative state shared within one webspace
  • node: state owned by one node inside a shared webspace
  • local: browser-local state not synchronized through shared runtime state
  • workspace: durable or logical scenario/workspace scope outside a browser local session

The preferred semantic binding shape is an object, not only a string:

{
  "kind": "y",
  "path": "data/infrastate/summary",
  "scope": "node",
  "nodeRef": "$context.nodeId"
}

This avoids encoding too much meaning into one ad hoc path string.

Canonical vs Derived State

The model must distinguish canonical truth from browser-facing derived state.

Canonical examples

  • logical state behind ctx.*
  • durable workspace metadata
  • shipped scenario content
  • shipped skill webui.json
  • access-link policy records

Derived examples

  • ui.application
  • demanded projection payloads
  • grouped or filtered client view state
  • browser stream buffers

Yjs may contain both live collaborative truth and derived materialization, but the addressing model must not blur those ownership boundaries.

Relationship to Existing Contracts

ctx.*

ctx.* remains the primary logical authoring contract for skills and scenarios. It is not replaced by browser-visible Yjs or stream refs.

data_projections

data_projections remain the canonical routing layer between logical state and physical backend placement. This document does not replace (scope, slot) pairs. It makes clear how browser-facing refs relate to that routing layer.

webio.receivers

webio.receivers remain the canonical declaration mechanism for transport-independent browser stream families. This document treats each receiver family as a stream:<receiver> ref at the addressing level.

projection_key

projection_key remains the canonical deterministic identity for demanded materialized UI views. This document only gives it a consistent typed-ref role in the wider vocabulary.

DeviceRef

Device-facing refs such as browser:<device_id> and member:<node_id> should evolve toward an explicitly typed domain-ref vocabulary:

  • device:browser:<device_id>
  • device:member:<node_id>
  • hub:<subnet_id> for the local hub settings target

Device-facing architecture may continue to document the shorter browser:<device_id> and member:<node_id> forms during migration, but the target vocabulary should be explicit about the domain class. If a local hub is observed through the legacy member:<local_node_id> form, the device-access layer must normalize it to hub:<subnet_id> before exposing settings or command availability.

Use subnet endpoint for the software participant attached to the subnet. browser and member are endpoint kinds; device and client are operator-facing access classes.

The naming layer should resolve user-facing labels and aliases into these refs before actions are dispatched. UI manifests should bind to refs, not to mutable display strings.

Named Entities

Named entities are the bridge from human language to addressing.

The boundary is:

  • UI Addressing defines stable typed refs and binding shapes.
  • Named Entities define display names, observed names, aliases, ambiguity, and locale-aware text-to-ref resolution.
  • NLU and operator tooling should resolve labels to refs before dispatching action:* commands.
  • Manifests may include display labels for readability, but action payloads, projection demand, and state binding should use typed refs.

Examples:

  • "show logs for kitchen display" resolves kitchen display to device:member:<node_id>, then dispatches an action with that ref.
  • A device settings form displays ZVERZVE-A1BNQF7, but the save action targets device:member:<node_id>.
  • A browser settings modal may show Edge on Windows, but modal addressing should still use the modal/action ref plus device:browser:<device_id>.
  • A Russian alias such as рабочий браузер and an English alias such as work browser may resolve to the same device:browser:<device_id>; neither alias becomes an addressing key.

The direction must stay one-way:

  1. user phrase or UI label
  2. named-entity resolution
  3. typed domain ref
  4. action, projection, or state binding

Typed refs should never be derived by parsing display strings.

Priority Slice for Web UI

The first addressing slice needed by the browser runtime is intentionally small.

Required first

  • Yjs state refs
  • stream refs
  • local view-state refs
  • typed action refs
  • projection refs
  • webspace:<id> and device:* domain refs where browser surfaces need them

Deferred

  • broad generalized URI layers for non-UI backends
  • a universal cross-plane query language
  • automatic ref rewriting across all historical contracts
  • per-user projection payload forks

Semantic UI manifests should bind through typed objects rather than opaque renderer-specific strings.

Example:

{
  "source": {
    "kind": "stream",
    "ref": "stream:chat.live",
    "scope": "shared"
  },
  "viewState": {
    "ref": "view:chat.input"
  },
  "actions": [
    {
      "ref": "action:skill.chat.send",
      "trigger": "submit"
    }
  ]
}

For chart-like views, a compatible semantic binding should follow the same shape and only vary by semantic kind and source contract, not by introducing a second addressing model for time-series data.

LLM Authoring Guidance

For the current skill-level implementation checklist, use LLM-Safe Skill Development Guide.

LLM-authored skills and scenarios should follow these rules:

  • prefer declared logical paths and typed refs over inventing new branches
  • do not write directly to arbitrary Yjs paths unless the runtime contract explicitly exposes them
  • keep business truth out of view:*
  • keep renderer decisions out of addressing
  • keep node ownership explicit instead of implied
  • prefer one of the documented ref classes before introducing a new one

Roadmap

Status note:

  • the typed ref vocabulary is now documented and used by the draft semantic Web UI ABI
  • demo skill and scenario manifests already use y:, stream:, view:, and action: refs
  • desktop and modal runtime adapters now preserve the same binding vocabulary during compatibility rendering
  • the first Taiga-backed collection_grid renderer consumes the same y: and view: refs without introducing renderer-specific addressing
  • the Taiga-backed metric_chart renderer consumes the same y: and view: refs without introducing chart-specific addressing
  • the semantic chat_panel now consumes the same typed y: bindings without introducing a separate chat-only addressing model
  • the widget host now resolves Taiga-backed semantic renderers through lazy registry entries, while keeping the same typed binding refs on the manifest side
  • the demo slice now uses action:-backed open_modal, call_host, and invoke_skill_action flows against the same shared view: and stream: refs
  • broader cross-document harmonization is still in progress
  • the demo metrics table and chart now share the same view: selection ref on both semantic and compatibility paths
  • desktop and modal runtime adapters now preserve the same node-scoped y: binding behavior for the demo slice
  • the demo package now reuses the same typed refs across both workspace and operations surface classes
  • semantic workspace metadata is now mirrored into runtime.surface.* browser state so typed actions can carry stable surface context without inventing a second addressing model
  • typed open_workspace actions can now target a first-class shell route (workspace) in addition to modal and webspace-switch flows

0. Vocabulary Fixation

  • [x] publish this addressing vocabulary as the canonical browser/runtime reference model
  • [x] freeze the distinction between logical, routing, runtime, projection, action, and domain refs
  • [ ] align naming guidance across ctx.*, data_projections, webio.receivers, and projection_key

1. Cross-Document Harmonization

  • [ ] update scenario and skill architecture docs so ctx.* is explicitly the logical authoring layer
  • [ ] update projection docs so projection_key is explicitly the projection ref identity
  • [ ] update device-access docs so DeviceRef is documented as a domain-ref slice
  • [ ] keep named-entity docs aligned so human-facing labels resolve into domain refs but never become addressing refs themselves
  • [ ] keep localization guidance aligned so localized labels affect display and resolution priority, not addressing identity
  • [ ] update browser/runtime docs so Yjs, streams, and local view state are described through the same scope vocabulary

2. Web UI Priority Slice

  • [x] define the first browser-facing binding object shape for y, stream, and view refs
  • [x] define typed browser action refs for the first semantic UI actions
  • [ ] define the first canonical webspace:<id> and device:* refs needed by workspace and device surfaces
  • [ ] define the first projection-ref usage rules for pages, widgets, modals, and platform-emitted projections
  • [x] define the first shared binding pattern that both table-like and chart-like semantic views can reuse

3. Runtime and ABI Alignment

  • [x] teach runtime manifest and semantic UI ABI docs to use the same ref vocabulary
  • [x] align browser adapters with explicit scope handling instead of implicit path conventions alone
  • [x] preserve compatibility for current webui.json, Yjs, and stream contracts during migration

4. Authoring and Tooling

  • [ ] publish LLM-oriented authoring examples using the finalized ref classes
  • [ ] validate manifests against allowed ref kinds and scope combinations
  • [ ] validate that action targets, projection demand, and state bindings do not use mutable display labels as routing keys
  • [x] add repository examples covering shared, node-scoped, and local browser state

4a. Stand-Oriented Demo Readiness

  • [x] repository demo manifests use y:, stream:, view:, and action: refs together
  • [x] one shared view: ref links table selection to chart rendering
  • [x] the same addressing slice is used in both desktop and modal demo surfaces
  • [x] desktop and modal runtime adapters scope node-owned y: refs consistently for the same demo bindings
  • [x] repository demo manifests reuse the same typed refs across both workspace and operations surface classes
  • [x] typed host and skill action envelopes now inherit runtime.surface.* context from semantic workspace metadata
  • [x] typed open_workspace actions can target an explicit browser workspace shell surface
  • [ ] manual verification on the target stand

5. Deferred Generalization

  • [ ] decide whether a generalized non-UI data URI layer is still needed after browser/runtime addressing stabilizes
  • [ ] if kept, position that layer as a facade over the canonical addressing model rather than as a competing architecture