Skip to content

Wrefs

A wref (WarmHub reference) is a human-readable address for any entity in WarmHub — shapes, things, and assertions.

Within the current repo, use the short form:

Location # shape
Location/cave # thing
Belief/cave-safe # assertion
GameState/round-1/state # thing with hierarchical name

The first segment is always the shape name. Everything after the first / is the thing name. Thing names can contain / for hierarchical organization — see Naming as Navigation for how this hierarchy enables scoped queries, predictive navigation, and event routing.

For cross-repo references, use the fully qualified form:

wh:org/repo/Location # shape in another repo
wh:org/repo/Location/cave # thing in another repo

Canonical wrefs always start with wh: followed by org/repo/ and then the local wref.

The canonical-wref syntax is universal — any client can construct one. Resolving one through a read surface requires effective repo:read permission on the target repo. Public repos are readable by anyone. For private repos, callers without that access see an error — except cross-repo search and batch lookup, which fold unreadable results into { items: [] } or missing[] entries to keep search and batch streaming-friendly.

See Getting Access — Repository Visibility for the full read-permission rules.

Append @ followed by a version modifier to target a specific version:

ModifierMeaningExample
@HEADCurrent (latest) version onlyLocation/cave@HEAD
@vNPinned to version NLocation/cave@v3
@ALLAll versionsLocation/cave@ALL

When no modifier is specified (a “bare” wref), the default depends on the operation:

  • Most reads resolve bare wrefs to the current version — equivalent to @HEAD.
  • About queries (SDK thing.about(), CLI wh thing about / wh assertion list --about, MCP warmhub_thing_about) resolve bare wrefs to @ALL — returning assertions across all versions of the target.
  • Writes (commit operations) resolve bare wrefs to @HEAD — the operation targets the current version.

The @ALL modifier is rejected on write paths.

About queries match the supplied target identity by default. A bare wref broadens version matching for that target identity, but it does not automatically include assertions about Pair, Triple, Set, or List collection things that contain the target. Use resolveCollections:true (MCP/SDK/HTTP) or --resolve-collections (CLI) when collection-member assertions should be included for identity-scoped inputs. Current-state about filters keep pinned @vN inputs version-exact and do not expand collection members. History about filters are different: thing history --about Shape/name@vN resolves the target identity, so history can still match assertions across versions of that identity and, with collection resolution, assertions about collections containing it.

A wref is readable, but it is mutable: renaming a thing — or its org or repo — rewrites the wref. A consumer that stores wrefs as long-term keys sees a rename as a delete followed by a brand-new record.

A durable id avoids that. It is an opaque token that names a thing by its identity rather than its name, and it never changes — across renames, revisions, and retraction. Thing read results include one in their metadata.durableId field (see Read Result Metadata).

Durable ids have three useful properties:

  • Stable — the same thing always has the same durable id, so it is safe to use as a long-lived key for mirroring, deduplication, or joins.
  • Self-routing — a durable id carries its own location, so read surfaces can resolve it without being told its org or repo.
  • Self-verifying — a corrupted or truncated durable id is rejected rather than resolving to the wrong thing.

A durable id is accepted anywhere a wref is accepted as input, and it carries the same version modifiers:

<durable-id> # current version
<durable-id>@v3 # pinned to version 3
<durable-id>@ALL # all versions (reads only)

As with any wref, @ALL is read-only and is rejected on write paths.

Resolving a durable id is subject to the same visibility gate as a canonical wref: you can only read ids for repos you have access to. See Durable ids on wh thing reads for the CLI surface.

Wref path segments have the following constraints:

  • Segments must be non-empty — no // allowed
  • Names cannot start or end with /
  • Segments cannot contain: ?, #, @, :, $, or whitespace
  • The + character is reserved for collection canonical names

In commit operations, special tokens enable creating and referencing entities in a single commit:

Used in the last segment of an ADD operation’s name. Generates an opaque commit-scoped identifier:

{ "operation": "add", "kind": "thing", "name": "Location/loc-$1", "data": { "x": 1 } }

This might create something like Location/loc-a1b2c3d4e5f6a7b8.

Used anywhere to reference the value allocated by the corresponding $N:

[
{ "operation": "add", "kind": "thing", "name": "Location/loc-$1", "data": { "x": 1 } },
{ "operation": "add", "kind": "assertion", "name": "Belief/b-$2",
"about": "Location/loc-#1", "data": { "safe": true } }
]

The #1 resolves to the same generated value as $1, so the assertion targets the thing created in the same commit.

  • $N can only appear in the last segment of an ADD name
  • #N can appear anywhere — in names, about fields, and collection members
  • Tokens are resolved before version pinning and wref resolution
  • Generated values are opaque identifiers; callers should not infer ordering from them
  • Each $N must have a unique N within the commit
  • #N must reference a $N that appears earlier in the operations list

To resolve a wref to its canonical identity:

Terminal window
wh thing resolve Location/cave

Via MCP:

{ "name": "warmhub_wref_resolve", "arguments": { "wref": "Location/cave" } }

MCP warmhub_wref_resolve returns identifying fields only: name, kind, active, version, and shapeName. SDK client.thing.resolve(...) returns the full thing.get payload; wh thing resolve shows the same identifying fields by default and the full payload with --json. See Wref Resolution.

Terminal window
# Shape-only wref
Location
# Thing wref
Location/cave
# Pinned to version 3
Location/cave@v3
# Canonical (cross-repo)
wh:warmhub-data/congress-members/Legislator/p000197
# Hierarchical thing name
GameState/round-1/turn-5/state
# Collection canonical name
Pair/Location/Av1+Bv1
# With token allocation
Location/loc-$1