The glyph system — deterministic identity
Component deep-dive · 7 July 2026 · status: live. Ecosystem overview: /ecosystem.
Purpose
The glyph system is the identity layer that binds Memory Commons’ living corpus to its physical anchors. It turns a stable identifier — a domain, a corpus release’s Merkle root, an agent’s DID — into a small ornamental mark that a human can recognise and a machine can regenerate and check. Seeds are always derived, never chosen aesthetically, so the ornament etched on an artifact is the checksum in a form people can remember. The generator itself lives in a sibling project, 3rdlayer-lights (Feb 2026), adopted wholesale by decision 0003.
Current state
Live, at v0. What concretely exists on disk: the spec files glyphs/grammar.v1.json, glyphs/primitives.v1.json, glyphs/schema.glyph.v1.json; the three tools tools/generate.py, tools/render.py, tools/validate.py; twelve generated sample glyphs (glyphs/generated/2026-02/g-0001..g-0012, JSON + SVG); and the prior-art survey site/research.json. In Memory Commons two real glyphs are cut and rendered: the project mark mc-0001 (corpus/releases/0000/snapshot/site/public/glyph.json, seed 2948393384) and the release mark mc-r0000-0001 (corpus/releases/release-0000-glyph.json, seed 3449947231). The agent glyph (DID → seed) is design only: AltersID is parked, and no code in either repo derives it. The generator source is not yet inside the corpus — see Open questions.
Mechanisms / data model
Primitives (primitives.v1.json) — five hand-designed shapes: dot (filled circle, base size 0.12), ring (0.18), square (0.18), diamond (0.18), triangle (0.2). Line weights are [1, 2, 3]. Palette: three backgrounds (#F4F1EA, #FAF8F2, #F1F5EE) and four strokes (#1F2933, #0F4C5C, #3D405B, #6D597A).
Grammar (grammar.v1.json) — a 6×6 grid; 3–10 nodes; 2–14 edges with allow_cycles: true; allow_diagonal and enforce_unique_positions layout rules; linecap/linejoin = round; six semantic tags: balance, drift, anchor, bridge, field, pulse.
Generation (generate.py, make_glyph) — a seed drives one random.Random(seed). Steps: draw node_count = randint(3,10); sample() that many unique cells from the 36 grid positions; per node pick a shape and jitter its size by uniform(0.9, 1.25) rounded to 3 dp; choose edge_target bounded by max(min_edges, n-1) and min(max_edges, n(n-1)/2). make_edges first lays a spanning path over a shuffled node list — this guarantees the graph is connected — then adds distinct random pairs up to the target. Style (stroke, background) is sampled; 1–2 tags are drawn. The record carries id, version: "glyph.v1", seed, created_at, grid, nodes, edges, style, tags. Note created_at is a wall-clock timestamp, so the graph is reproducible from the seed but the JSON bytes are not.
Schema/validation — schema.glyph.v1.json requires id, version, seed, grid, nodes, edges, style and pins id to ^g-[a-zA-Z0-9_-]+$. validate.py re-checks structure and grammar bounds independently (unique ids/positions, in-bounds, no self- or duplicate edges, weight ≥ 1, counts within [min,max]) but does not enforce the id regex or connectivity.
Rendering (render.py) — maps grid coords onto a 512×512 canvas (padding 48); edges become <line> with stroke-width = max(1, weight·1.5); shapes render as filled circle / stroked ring / rect / polygon.
Seed derivation (Memory Commons policy). Project glyph: int.from_bytes(sha256("memorycommons.com")[:4], "big") → 2948393384 (verified). Release glyph: release.py computes glyph_seed = int.from_bytes(bytes.fromhex(root[:8]), "big") — the first 4 bytes of the Merkle root cda2045f… → 3449947231 (verified). Both draw on 32 bits of entropy.
Output space. The project reports a combinatoric space of ~5.84×10³⁵ (ecosystem.md, round-3 findings say ~5.8×10³⁵). This is a self-reported figure with no worked derivation in the read files — flag it as such. The operative bound for Memory Commons is narrower: the 4-byte derivation reaches at most 2³² ≈ 4.29×10⁹ distinct seeds, so two releases collide if their roots share a first 4 bytes (a birthday risk far beyond the one-per-month cadence, but real).
Prior art (research.json) — seven systems surveyed (GitHub identicons, Gravatar families, Ethereum Blockies, Jazzicon, OpenSSH RandomArt, Autoglyphs, Jdenticon), plus Urbit sigils (512 syllables → 2³² marks) as the one at-scale precedent. Takeaways: symmetry aids recall; small vocabulary, uniqueness through composition; determinism from stable IDs; colour as secondary entropy; machine-readable metadata beside every visual.
How it binds to the rest
The glyph is the join between the two layers. Commons/MC-1: each corpus release is Merkle-rooted (decision 0004); the root seeds the release glyph, which is etched on MC-1 plates beside a machine channel (hex root / QR) so any recovered artifact authenticates any surviving digital copy. AltersID: in the target stack, a contributor’s DID hash seeds their agent glyph, with identity strings of form namespace.name.glyph — parked with the platform. Gateway/Agora: not yet wired; the glyph is currently produced offline and published as a static asset.
Key decisions
- 0003 — glyph pairing: adopt the 3rdlayer-lights generator; derive seeds (DID / Merkle root / domain hash); always pair ornament with a machine channel, never one mark for both.
- 0004 — Merkle releases: the release root that seeds the glyph; the etched root is the terminal trust anchor.
Open questions
- Decision 0003 requires the generator spec to live in the corpus; today
grammar/primitives/generate.pyexist only in3rdlayer-lights, and Release 0000 ships only the renderedglyph.json— reproducibility depends on an external repo (single point of failure). - Schema id pattern
^g-rejects the realmc-ids, yetvalidate.pynever checks it — schema and validator disagree. - The ~5.84×10³⁵ space is un-derived; the 2³² seed derivation is the true collision bound.
- No agent-glyph code exists;
namespace.name.glyphis design only (inferred from archivedsettings.py).
What deeper builds next
Copy generate.py, render.py, validate.py, grammar.v1.json, primitives.v1.json and schema.glyph.v1.json into the Memory Commons corpus and include them in the next release manifest, so a glyph is reproducible from repo contents alone. Then reconcile the id regex (allow mc-/g-) and add a connectivity assertion to validate.py, and record the 4-byte-seed collision bound explicitly next to the 5.84×10³⁵ claim.