← docs · ADR

Install identity — who am I AND where I read — resolves at one fail-loud seam; the genotype carries no install literals

Everything install-specific (the group, the transcript store, any display name) resolves through one seam, tools/_identity.py, in fail-loud mode: absent identity raises or runs explicitly anonymous — never a silent default, never a baked-in literal. The transcript store joins the identity contract: it derives from the running install's $HOME (or EDGE_PROJECT_DIR explicitly), and a store directory that does not exist is an error, not "nothing new." The grep-gate — zero install-identity literals in tools/ — becomes the seam's conformance test.

Status

proposed (2026-06-10; Voz ratifies — "next steps" session). Inscribes the Direction steers from the-genotype-still-wears-the-devs-name (proposed since 06-08) as architecture. Pairs with ADR-0016 (pre-dispatch enforcement — the other half of the same incident).

Context

transcript store to ~/.claude/projects/-home-vboxuser — the developer's host path baked into the genotype. On roberto (deployed 06-09, 294 session files in -home-roberto*), the sweep scans a nonexistent directory and reports "nothing new (cursor up to date)" — a silent success. Result: cursor {} since deploy, zero episodes ever extracted, no Direction/wiki projections on disk. Roberto produced two Artefatos briefed from an empty memory, and nothing ever errored.

or "edge" display default (wiki_render), the stale lucasrp/edge-of-chaos source key (now also found as a placeholder in roberto's agent.yaml).

resolution (briefing.py:419, recall.py:115, wiki_render.py:50-52), and sweep.py:34 caches the group at import time (stale-copy risk). The fail-loud rule the glossary ratified ("an install that has not declared who it is must not write as anyone") lives nowhere in code — every caller silently accepts None and degrades.

contamination risk, not hygiene.

Considered options

callers' inline resolutions). Rejected: the next literal lands the same way — the disease is the absence of a deep seam, not any one literal. Per-caller fixes also leave the fail-loud rule unenforceable (each caller decides its own degrade).

the read-side silent degrade ("nothing new") is exactly what hid a 294-session amnesia for two days. Reads that orient the edge are load-bearing; lying quietly is worse than stopping.

make one call and carry no fallback of their own.

Decision

the house two-function shape: require_group() raises (RuntimeError naming the gap — the install/write posture), group() returns None and the caller labels its degrade honestly (the runtime/read posture). (Amended 2026-06-10 review: originally drafted as group(require=True) + IdentityError; the shipped two-function form is the pre-existing house API and the tests pin it — same substance, one seam, two postures.) No caller re-implements the precedence; no module caches the result at import time.

running $HOME (-home-<user> per the Claude store convention); raises when the resolved directory does not exist. "Nothing new" is reserved for a real store with no new lines.

fallbacks. The grep-gate runs as a test (test_identity_blinding) and as the pre-propagate acceptance check in the genotype→clone→PR→merge→propagate flow.

sweep.py resolves at call time.

Consequences

write** instead of producing plausible work from an empty or foreign state.

~294-session backlog (cursor-guarded, resumable).

hold (the proxy-harness hosts write transcripts under the harness home).

multi-mentee groups) — one file to change.