RelayCTX Creative briefsBRIEF.code-presence.md
RelayCTX Creative · Document

BRIEF.code-presence.md — Code presence as display state (DEC-025)

1,661 words · 8 min View raw Source History

BRIEF.code-presence.md — Code presence as display state (DEC-025)

Project: relay-creative / display direction for DEC-025 identity-and-codes Status: direction proposal — nothing here binds app work until EC ratifies Live concepts: /concepts/code-presence-v1.html (app surfaces) · /mcp/code-presence-display.html (MCP rich + plain tiers) Upstream decision: relay-platform docs/DESIGN-NOTE.identity-and-codes.md, docs/GUIDE.identity-and-codes-rollout.md (branch claude/relay-code-access-control-ydwgbj) · Linear RCTX-1066 · relay AJA9TN Date: 2026-08-01 · v3.5 neutral-first


Why

Today every object mints a Code at creation, shared or not. That makes the Code wallpaper — the most distinctive thing in the product, rendered on things nobody ever handed to anyone.

DEC-025 fixes it: a Code exists if and only if an actor deliberately elevated context for handoff — human, agent, or system alike. Presence of a Code is evidence of that act. Absence means the object never left.

The consequence for design is blunt: most objects will have no Code. Every surface built on the assumption that a Code is always there now has a second state it was never drawn for.

The question this brief answers

Not "what replaces the Code." That was tried and rejected — see Rejected drafts.

How does a surface look when the hero artifact is legitimately absent, without the absence reading as an error or a missing field?

The answer the design must express, in one line a person could say out loud:

A Code means someone chose to share this. No Code means it never left.

Both states are correct and normal. The difference should be readable at a glance, and neither should look like the other one broken.

The four laws

L1 · Mark presence, never absence

No placeholder. No em-dash in the Code slot. No dashed outline, no ghost lozenge, no "Not shared" stamp on the row. **A symbol that stands for nothing happened is exactly what reads as an error** — a person scanning a list cannot tell your deliberate em-dash from a failed fetch, and neither can a screen reader.

Shared objects are marked. Unshared objects are simply quiet.

L2 · One teal moment per object

The accent tracks where the intent lives:

StateThe one teal moment
Sharedthe Code--accent-text, mono, the brightest thing in the card
Unsharedthe invitation — the share action, --accent-fill + --on-accent

So the surface never loses its accent and never doubles it. On an unshared object the brightest element is the act that would create a Code — which is the honest hierarchy, because that act is the only thing of consequence available on that object.

This also gives the two states a shape-level difference (a mono token vs. a filled button) rather than a colour-level one, which survives greyscale, low-vision, and the plain-text MCP tier.

L3 · The title never changes rank

Same slot, same size, same weight, same colour in both states. Nothing is promoted to fill the gap.

The title's job is recall — finding your own work again. The Code's job is sharing. Different jobs; they do not compete and they do not substitute. On an unshared object the title is simply a label, which is what it always was.

This law is the direct lesson of the rejected draft, and it is the one most likely to be violated by accident: a designer sees empty space where the Code was and reaches for the nearest text field.

L4 · Absence is addressable, not annotated

On list surfaces, "never shared" is a filter you can select, not a badge stamped on every row. Make the set selectable and absence becomes legible as a population — "41 of 68 never left this workspace" — instead of a mark repeated 41 times that each individually looks like missing data.

This is what satisfies "absence of a Code is information and should be legible in the UI" without violating L1.

Surface-by-surface

SurfaceSharedUnshared
Relay detailCode in the hero slot (.relay-code-hero), copy affordance, provenance lineHero slot absent — the layout closes up, it is not left empty. Title in its normal label slot. Share is the primary action.
Share / elevationCode hero at full weight; this is the surface the Code was designed forThe panel is the act — the Code slot is occupied by the invitation until the moment of elevation, then by the Code, arriving once
List / inboxCode in the leading rail, mono, --accent-textRail carries nothing. Row is otherwise identical. Segment control (All · In circulation · Never shared) carries the state
Claim / notification / onboardingunchanged — sharing is the subject on these surfaces, the Code stays heron/a — a codeless object cannot reach these surfaces

The old canon line — "the Code is the product — hero artifact on every relay surface" — is narrowed, not replaced:

The Code is the hero artifact on every surface where sharing is the subject: share panel, handoff, claim, notifications, onboarding.

The elevation moment

This is where the Code is most hero, and lazy mint makes it better: minting on every object makes the Code wallpaper; minting on intent makes it earned. The Code's first appearance is now an event with a cause, so it gets the one event animation on the surface — .rly-materialize (pulse family #7, characters land top-down, 55ms stagger, once, system teal) and nothing else moving.

Copy stays at capability level, never mechanism — RCTX-1073. "A Code means someone chose to share this" clears the gate. Describing how minting works does not. UI labels name the act ("Share this relay"), never the machinery.

Rejected drafts

Kept here so they are not re-proposed.

#DraftWhy it fails
1Title as hero on codeless objectsRejected by EC. Title is the most generic field in the schema — every competing tool has one. It cannot carry a verb surface, and promoting it teaches that the hero slot is a container for whatever is available rather than a claim about identity.
2Title in Code costume — mono, uppercase, letterspaced in the Code slotA costume. It fakes the artifact with a field that has none of its properties: not short, not shareable, not unique, not speakable over a phone. Worse than #1 because it is #1 wearing a disguise.
3Show the ID (r7f3a91c…) where the Code would beIDs are lowercase hex machine identifiers and are not a display surface (invariant C2). Their narrow alphabet is deliberate — it keeps them shape-disjoint from uppercase Codes, which is what lets one resolver dispatch on shape alone. Rendering one to a person leaks a machine handle and invites the demand to prettify it, which is identity churn.
4Em-dash / "—" or "Not shared" chip in the Code slotViolates L1. Indistinguishable from a failure state at a glance, and it spends the row's attention budget on a non-event.

Accessibility (non-negotiable)

MCP tiers

Per-harness rich/plain — relay-platform docs/DESIGN-NOTE.mcp-rich-display.md, rui-* kit in src/relay/mcp/ui/.

What ratification unblocks

relay-app REFERENCE.product.md:47 and REFERENCE.screens.md:19 both still carry the old "hero artifact on every relay surface" line. Rewriting them is gated on this direction, and they in turn gate all Train 3 app work.

Note for sizing: the rollout guide's touchpoint #1 counts 52 code references in relay-detail.ts. That is the mechanical part. The real work is the visual hierarchy of every relay surface, and it is not counted anywhere yet.

Open questions → EC

  1. Ratify the four laws (or amend). L3 is the load-bearing one.
  2. List default filter — proposed All. Alternative: default to In circulation on the inbox surface, where the shared set is the subject.
  3. Does an unshared object show any provenance at all (created-by, stream, time), or is the quiet state fully quiet? Proposed: yes, provenance stays — it is recall metadata, and recall is the unshared object's whole job.