Skip to content

id: design: semantic cell/tag presentation model — one tagged state, many renderers #6010

Open

Description

@dezren39

Part of the worlds design program: #5955. Wave-2 follow-up from the prior-art research (Lane B item 37); parent topic issue: #5970. Research source: workspace/scratch/worlds-capabilities-brief-2026-11-04/prior-art-research.md.

The Dwarf Fortress rule

DF's presentation history is the canonical capability-tier story: ASCII glyphs (CP437) → community tilesets replacing glyphs 1:1 → full graphical tiles — the simulation never changed, only the presentation mapping, and the ASCII tier remains a complete, playable representation. The design rule: world state must be expressible as a grid of typed cells with semantic tags (creature/material/state), and each client tier renders tags at its fidelity. Drew's "blue cape with sparkles → blue letter C / cape emoji" is exactly a tag→glyph fallback rule.

Scope

Done looks like

A tagged-state spec (cell fields, tag vocabulary v1, per-tier rendering obligations) that #5970's fallback chain can reference.

Activity

  1. added
    priority/normalOrdinary priority (the default)
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    on Nov 5, 2026
  2. developing-today commented on Nov 5, 2026

    @developing-today
    Contributor
  3. added
    kind/designA design proposal (design-architect): multi-step, phased, decision-bearing
    queue/queuedHas a queued task in the Supabase agent queue
    task/triageQueue packet kind: verify, reproduce, and route this item
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 5, 2026
  4. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  5. developing-today commented on Nov 5, 2026

    @developing-today
    Contributor

    🤖 Agent note · done

    Triage verdict — LIVE, premise holds, spec routed

    Verified fresh 2026-11-05: issue #6010 is OPEN, no hard-stop labels, no other holder. The ticket's load-bearing premise — presentation-is-data already shipped — holds at current main: the module is live in (e.g. consumes ; guests supply legacy UTF-8 text or the versioned Screen cell buffer, never raw escapes/HTML/CSS). So the tagged-state model is an extension of a shipped surface, not greenfield.

    Dependency map (all verified OPEN just now): parent program issue #5955; parent topic issue #5970 (user presentation assets — the fallback chain this spec feeds); capability tiers issue #786 (Phase 13 F13.4, in-band terminal detection). Sibling issue #6011 (terminal rendering ladder) is the per-tier rendering-obligation consumer — the tag vocabulary v1 and the ladder should be specified against each other, vocabulary first or together.

    Execution shape (for the follow-up task)

    Write the tagged-state spec per the ticket's Done-looks-like: cell fields (kind, owner-visible identity, state flags), tag vocabulary v1, and per-tier rendering obligations — with the Dwarf Fortress rule as the invariant: every tier (ASCII → tiles → rich) is a COMPLETE representation of the same tagged state; world code declares tags, the fallback mapping lives in the presentation layer, never in world code. Name the oracle: a worked example cell set (including Drew's blue-cape-with-sparkles case) rendered at every tier with no information loss at the lowest tier. Land as a design record on the issue or a docs PR under the standing rules.

  6. 8 remaining items

  7. developing-today commented on Nov 5, 2026

    @developing-today
    Contributor

    Correction to the triage note above (task 10376): several code identifiers were stripped from that comment in posting. Restored verbatim:

    • The shipped module is world_presentation, live in pkgs/id.
    • The consumer example is world_session/types.rs, which uses crate::world_presentation::ScreenPatch.

    All other statements in the note above stand as written.

  8. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  9. added
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 5, 2026
  10. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · state: handed off

  11. added
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 5, 2026
  12. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  13. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    Tagged-state spec v1 (task 10548)

    Design boundary. The world owns one canonical tagged state; renderers are projections of it, not sources of game semantics. Changing from ASCII to tiles or rich graphics must not change simulation state. The world declares semantic tags; the trusted presentation layer owns tag-to-glyph/asset mappings and authored fallbacks. This is a proposed logical model, not a silent wire-format change.

    Cell model and vocabulary

    A cell is a row-major grid position containing zero or more ordered layers (back to front), so terrain, an entity, and an effect can coexist. Each layer has:

    kind: terrain | entity | item | effect | marker
    primary_tag: namespaced semantic tag
     tags: set of additional semantic/appearance tags
    identity?: { world_local_id, owner_label? }
    state_flags: set of positive state-tag IDs
    

    kind is the stable cross-world role; primary_tag gives its concrete meaning. identity is optional for non-identifiable layers. IDs are scoped to a world instance (not global account IDs); owner_label is a viewer-specific, plain-text projection. The host must redact labels before sending a view to anyone not entitled to see them. State flags are affirmative facts: absence means “not asserted/unknown,” not false.

    The v1 core vocabulary reserves these roles/tags:

    • kind: terrain, entity, item, effect, marker.
    • Primary tags: core.terrain.floor|wall|water; core.entity.player|creature|npc; core.item.wearable|tool|consumable; core.effect.sparkle|fire|poison; core.marker.goal|cursor.
    • Appearance/composition tags include core.appearance.cape, core.color.blue, and core.effect.sparkle (an effect may also be a separate layer when it needs its own position/lifetime).
    • Common state flags: core.state.alive, dead, hostile, wounded, selected, concealed (all fully qualified as core.state.*). Worlds may add stable world.<world-id>.* tags; they may not redefine a core.* meaning.

    Tags are inert identifiers, never CSS, HTML, ANSI, shader source, or executable code. A client that does not recognize a tag must retain it in a safe textual fallback/description rather than silently dropping it. The world/presentation registry supplies a plain-text meaning for display; unknown namespaced IDs remain inspectable.

    Rendering obligations and composition

    For a recipient, first form the authorized tagged-state projection (including identity redaction), then resolve it through the presentation/asset layer, then emit through the selected client tier. Every tier must be a total mapping for the tags it receives. It may reduce visual fidelity, but it must preserve the recipient-visible kind, identity, tags, and state flags in the rendered view or a deterministic legend/accessible text description. If glyphs collide, layers overlap, or a feature has no asset, use a declared secondary mark, legend, or text description; do not guess from pixels or omit the fact.

    This composes with the sibling designs rather than duplicating them: #5970 owns asset IDs, capability policy, and the authored rich → static/substitute → sprite/glyph fallback (per-world-disabled filters use their declared fallback); #6011/#786 select the client/protocol capability rung. That rung changes how pixels are transported, not what a tag means. ASCII and symbols receive the same semantic mapping effort as image tiers. The deterministic text projection is the lowest-tier escape hatch; labels and descriptions must be escaped as plain text by trusted presentation code.

    Worked example and oracle

    At (2,2), define one layer with kind=entity, primary_tag=core.entity.player, owner-view identity {world_local_id: p-1, owner_label: You}, tags {core.appearance.cape, core.color.blue, core.effect.sparkle}, and state {core.state.alive}; surround it with floor and wall cells. Render that same cell set as:

    • Rich: player sprite, blue-cape asset, sparkle effect; accessible description says “You, player; blue cape; sparkle; alive.”
    • Tiles: the corresponding Dwarf-Fortress-style player/cape tile and sparkle mark; legend/description retains the same facts.
    • Symbols: blue C plus * where color/symbols are supported; legend identifies C as You/player with blue cape and * as sparkle.
    • ASCII-only: map glyph C plus a plain-ASCII legend such as C at 2,2 = You / player; blue cape; sparkle; alive (no reliance on color or emoji).

    The oracle is equality of the normalized recipient-visible semantic projection before rendering and after decoding the rendered view plus its legend/description: same kind, entitled identity, all tags, and all state flags at every tier. A test must fail if the lowest tier only emits C and loses cape/sparkle/identity, even though the glyph itself is drawable.

    Fit with the shipped presentation DTO

    On current main, WorldSurface is Screen or Text. ScreenSurface is version/dimensions plus row-major cells; ScreenCell currently contains only symbol, fg, bg, bold, and columns. ScreenPatch/CellRun are deltas over those concrete visual cells. Therefore the tagged model belongs upstream of the presenter that produces WorldSurface; do not pretend these existing cells already carry semantic tags or overload patches with them. Any future wire representation for tagged state needs an explicit versioned protocol decision. The existing safe text projection can carry the lowest-tier legend.

    Acceptance check: a shared example fixture is rendered through each tier and the semantic-projection oracle above passes, including for an unknown tag and a viewer who is not entitled to an identity label. This makes “one tagged state, many renderers” executable without requiring every tier to use the same glyph or asset.

  14. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/idPackage/app: id (pkgs/ or apps/ in this repo)kind/designA design proposal (design-architect): multi-step, phased, decision-bearingpriority/normalOrdinary priority (the default)task/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions