# Ori Schema Evolution — Versioning and the V7 Player-Character Extension

**Status:** Planning gap-fill per `V1_V7_PLAN_SET_AUDIT_2026-06-12.md` §6.1.3
("V6's Ori defines no schema versioning or non-agent-subject extension points
for V7's use"). **Date:** 2026-06-12. **Owners:** Ori service owner
(`apps/v6/egbe-ori-service`, Rust) — accountable for the registry and the append
path; Aye Bridge owner (`libs/v6/aye-bridge`) — passport and journal version
negotiation; V7 Nàná/Nephthys leads — consuming side of the player-character
extension; Isis policy owner — provenance and persona invariants; platform
privacy counsel (DPO) — §4 erasure design; V1 audit/compliance reviewer —
hash-chain and residency interplay.

V7 will extend the Ori to carry "a **player's persistent roleplay characters** —
a citizen of a realm with a name, a job, a home, a criminal record,
relationships, and a bank balance that survive across sessions"
(V7_features.md:71–77). That extension must not fork the Ori: one event store,
one merge machinery, one audit spine. This document defines how the schema grows
without breaking V6's three load-bearing guarantees: append-only ("a life cannot
be silently rewritten", V6_features.md:541–546), vector-clock mergeable across
shards (features:635–651, arch:621–629), and hash-chain archivable
(`ori-dr-and-compaction.md` §4 — sealed segments are hashed over stored bytes,
which constrains _where_ schema migration may happen).

Grounding: event store and the 17 founding event types (`Born` … `Died`) at
V6_ARCHITECTURE.md:557–622; identity core + Isis-signed provenance
(features:553–561); trait/values personality model (features:563–589);
episodic/semantic/reflective memory (features:591–609); relationship graph
(features:611–619); capability profile and passport (features:621–633,
arch:612–619); Clio narrative reconciliation (features:648–651, arch:621–629).

---

## 1. Design rule: one biography substrate, two subject kinds

V7 gets **extension points, not a fork**. The unit of extension is:

1. a **schema-set** version (§2) governing event encodings,
2. a **subject-kind** discriminator (§3) governing which invariants apply,
3. **annex sections** in the passport (§5) governing what crosses realms.

Everything else — vector clocks, merge precedence, sealed segments, Merkle
roots, Clio reads — is shared machinery and stays version-independent by
construction (§2.1, §6).

A single integer **`oriSchemaSet`** (1 = the V6 launch schema) pins, per
release: the event-type registry revision, the maximum payload version per type,
the upcaster-chain revision (§2.3), and the current passport schema. The
registry is itself append-only: sets are never edited, only succeeded. At most
one schema-set bump ships per minor release (planning assumption adopted
2026-06-12), so the negotiation matrix in §6 stays small. The registry lives in
a proposed new library `libs/v6/ori-schema-registry/` (machine-readable JSON +
Rust types; new files, existing code untouched until implementation).

---

## 2. Event-schema versioning rules

### 2.1 The envelope is frozen-compatible (additive-only)

The envelope is the part every version of every service must parse: `eventId`,
`oriId`, `subjectKind` (§3), `type`, `typeVersion`, `occurredAt` (UTC),
`vectorClock`, `attribution`, `provenanceRef` (the shape of arch:578–586).
Envelope rules, permanent:

- **Add-only.** New envelope fields must be optional with a defined default
  (e.g., absent `subjectKind` ⇒ `agent`, the §3 backfill rule). Renaming,
  retyping, or removing an envelope field is banned in any set.
- **Ignore-unknown.** Every reader skips unknown envelope fields. This is what
  makes vector-clock merging version-independent: a set-N node can order and
  merge events written by a set-N+1 node because the clock and ordering fields
  never change shape.
- **No semantics smuggling.** An envelope field may never change meaning between
  sets. Behavior changes ride in `typeVersion`d payloads, never in reinterpreted
  envelope fields.

### 2.2 Per-event-type payload versions

Each of the 17 founding types (and every type added later) carries
`typeVersion`, starting at 1. Rules:

- **Within a version, payloads are closed.** A stored `MemoryFormed@1` is
  `MemoryFormed@1` forever; stored bytes are never migrated, rewritten, or
  re-encoded (the compaction hard rule of `ori-dr-and-compaction.md` §6 extended
  to schema work).
- **Additive change inside a version is also banned.** Even "harmless" new
  optional payload fields require a version bump, because sealed-segment hashes
  and golden conformance fixtures (§9) pin exact encodings. Cheap version bumps
  with mechanical upcasters beat ambiguity about what `@1` means.
- **A new version requires a registered upcaster** from its predecessor before
  any writer may emit it (§2.3). No upcaster, no release — enforced by the §9
  gate.
- **New event types** are registered with: name, owning subsystem, first
  `oriSchemaSet`, the subject-kind validity row (§3.3), and the payload
  field-classification map (`personal` vs `structural`, consumed by §4).

### 2.3 The upcasting registry — read-side, pure, permanent

Because sealed segments hash the stored bytes (`ori-dr-and-compaction.md` §4.1),
**all migration is read-side**: the store serves events at their written
version; the read path applies the registered upcaster chain (`@1→@2→…→max`) to
produce the **canonical form** that projections, Clio, and cognition consume.
Upcasters are:

- **Pure and total** — no I/O, no clock, no config; same input bytes, same
  output, forever. Property-tested and pinned by golden fixtures (§9.1).
- **Permanent** — an upcaster is never deleted or modified once a set ships (a
  fix is a _new_ version with a new upcaster). The log is forever; so are its
  readers.
- **Cheap** — budget p99 ≤ 20 µs per event per hop in the Rust read path
  (planning assumption adopted 2026-06-12), so a full projection rebuild of a
  100k-event stream adds ≤ 2 s per hop and the DR drill's rebuild step
  (`ori-dr-and-compaction.md` §7.4) is unaffected in practice.

Projection **continuity hashes** (arch:1258–1261; compared in the DR drill) are
computed over the canonical form and pinned to the pair
`(projectionCodeVersion, oriSchemaSet)` — a schema-set bump legitimately changes
continuity hashes once, in lockstep, fleet-wide; the drill always compares like
with like.

**Worked example — `MemoryFormed@1 → @2`.** The prompt-injection threat model
requires every semantic memory to carry a provenance class
(`first_hand | steward | second_hand | world_text | journal`) so retrieval can
discount hearsay for identity- and policy-relevant decisions
(`prompt-injection-threat-model.md` §6.2). `MemoryFormed@2` adds the required
field `provenanceClass`; the registry entry and upcaster:

```json
{
  "type": "MemoryFormed",
  "versions": {
    "1": { "introducedInSet": 1 },
    "2": {
      "introducedInSet": 2,
      "adds": ["provenanceClass"],
      "upcaster": "memoryformed_v1_to_v2",
      "writerDeprecates": { "1": "180d after set 2 GA" }
    }
  }
}
```

Stored `@1` event (never touched on disk):

```json
{
  "eventId": "evt_01JXX7G2",
  "oriId": "ori_8f3aa1",
  "type": "MemoryFormed",
  "typeVersion": 1,
  "occurredAt": "2026-04-02T19:12:08Z",
  "vectorClock": { "commons-eu-2": 4182, "solo-h7741": 220 },
  "attribution": { "kind": "agent", "ref": "ori_8f3aa1" },
  "provenanceRef": "prov_5cc921",
  "payload": {
    "episodeText": "Argued with Tobi at the night market.",
    "salience": 0.62,
    "participants": ["ori_2aa4f0"]
  }
}
```

Upcaster mapping (deterministic, from envelope attribution + the provenance
record's source tag where one exists):

| `@1` evidence                                  | `@2 provenanceClass` |
| ---------------------------------------------- | -------------------- |
| attribution `steward`                          | `steward`            |
| attribution `agent`, source tag `world_text`   | `world_text`         |
| attribution `agent`, source tag `agent_speech` | `second_hand`        |
| attribution `system`, journal-merge provenance | `journal`            |
| attribution `agent`, first-person episode      | `first_hand`         |
| **no source tag resolvable (early history)**   | `second_hand`        |

The default for unresolvable history is `second_hand` — the _discounted_ class —
because the safe failure mode for a trust-weighting field is "trust less", never
"trust more". The upcaster output for the fixture above is byte-pinned in the
§9.1 golden file.

### 2.4 Interaction with sealed segments, snapshots, and backups

- Sealed segments archive **written bytes**; the per-stream hash chain and the
  daily Merkle root (`ori-dr-and-compaction.md` §4.1) are therefore
  version-evolution-proof: no schema-set bump ever re-hashes history.
- Segment manifests gain one additive field `maxTypeVersionPresent` (per §2.1's
  add-only rule) so the restore drill can verify upcaster coverage before
  serving a restored partition.
- Projection snapshots are already versioned by projection-code version
  (arch:598–602); they additionally record the `oriSchemaSet` they were built
  under, and a set bump invalidates snapshots lazily (rebuild on next load, not
  as a fleet-wide stop-the-world).

---

## 3. Subject-type extension — agent vs player character

### 3.1 The discriminator

Envelope field `subjectKind ∈ { "agent", "playerCharacter" }`, fixed for the
life of a stream by its creation event (`Born`/`Discovered` for agents,
`CharacterCreated` for V7 characters) and repeated in every event envelope for
cheap enforcement at append time. Absent ⇒ `agent` (every pre-existing V6 stream
backfills by default, no rewrite). A stream can never change kind: an append
whose `subjectKind` contradicts the stream's creation event is rejected with
`subject_kind_invariant` and audited.

### 3.2 The invariant matrix — where the two kinds genuinely differ

| Invariant            | `agent` (V6)                                                                                    | `playerCharacter` (V7)                                                                                                                                                                    |
| -------------------- | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Autonomous cognition | Yes — Moirai schedules Clotho/Lachesis/Atropos ticks (arch:637+)                                | **Never.** No cognition tier, no Moirai scheduling, no platform-generated `Reflected`/`ValueShifted`. A platform-attributed cognition event on a character stream is append-rejected      |
| Who writes           | Shards/contexts via Moirai, steward directives, sanctioned journals                             | The realm session the player occupies (single writer per Nephthys authority rules) + platform compliance systems                                                                          |
| Personality model    | Trait vector + ranked values, Sophia-grounded backstory (features:563–589)                      | None required; backstory is player-authored fiction, moderated as UGC, never Sophia-ground-truth-claimed                                                                                  |
| Welfare machinery    | Bond ledger, refusal, Departure, Ereshkigal endings                                             | None — player autonomy is real autonomy; no bond ledger, no welfare reviews                                                                                                               |
| Provenance           | Isis-signed provenance bundle at creation (features:556–558)                                    | Same — `CharacterCreated` carries an Isis-signed creation record (provenance discipline is kind-independent)                                                                              |
| Privacy class        | Platform-creative data; steward referenced only by opaque ref (`ori-dr-and-compaction.md` §6.5) | **Personal data under GDPR** — the pseudonymized-≠-anonymous posture of `V7/docs/operator-data-protection.md` §2.3; payloads encrypted per §4; residency-tagged to the player's home zone |
| Deletion             | **Never** — erasure is not an operation the log supports (features:541–546)                     | **Erasure right honored** via crypto-shredding + tombstone (§4)                                                                                                                           |
| Clio narration       | Chronicle and Book of the Ori                                                                   | Realm-side narration only, and only within realm/consent scope; no platform-published Book                                                                                                |

### 3.3 Event-type validity is registry data, not convention

The registry carries a per-type validity row over subject kinds. Agent-only:
`Discovered`, `Reflected` (platform-attributed), `ValueShifted`, `Crossroads`,
`BondChanged`, `Departed`, `Transcended`. Valid for both: `MemoryFormed`
(player-authored journal entries on character streams), `RelationshipChanged`,
`SkillLearned`, `ArcAdvanced`, `Incarnated`/`IncarnationReturned` (the character
corridor uses the same passport machinery, §5), `Died` (V7 realms may charter
permadeath, V7_features.md:609). V7's set adds character-only types:
`CharacterCreated`, `CitizenshipGranted`, `RecordEntryAppended` (the RP
criminal/medical record), `CharacterRetired`, `SubjectErased` (§4). Appends
violating the validity row are rejected and audited — this is the structural
guarantee that V7's extension cannot accidentally turn a player character into a
half-agent or vice versa.

---

## 4. Deletion semantics — resolving "never deleted" against erasure rights

This section is the machinery `ori-dr-and-compaction.md` §6.5 defers to. The
tension, stated plainly: the agent guarantee is about **biography truth** —
erasure must be impossible. The player right (GDPR Art. 17) is about **personal
data** — erasure must be possible, provable, and complete across backups. The
resolution: **structure is permanent for both kinds; content is erasable only
for player characters**, via crypto-shredding.

### 4.1 Crypto-shredding design for `playerCharacter` streams

- **Per-stream DEK.** At `CharacterCreated`, the Ori store generates a
  per-stream data-encryption key (AES-256-GCM), wrapped by the residency zone's
  KEK (envelope encryption; key material only in the platform KMS/HSM — never in
  the database, never on a realm node, consistent with the BYOC posture of
  `V7/docs/operator-data-protection.md` §2.4). The key id rides in stream
  metadata.
- **Field-level classification.** The registry's per-type field map (§2.2) marks
  payload fields `personal` (names, free text, appearance refs, record entries,
  relationship annotations) vs `structural` (ids, opaque refs, numeric amounts,
  enum codes). Personal fields are encrypted at append; structural fields and
  the entire envelope (ids, timestamps, vector clocks, type, sizes) stay
  plaintext.
- **Why the guarantees survive:** sealed segments hash the stored bytes — which
  are ciphertext for personal fields — and ciphertext is never altered, so
  per-stream hash chains and daily Merkle roots verify before and after an
  erasure. Event counts stay monotonic (the §4.3 invariant monitors of the DR
  doc fire on nothing). Vector clocks stay plaintext, so cross-realm merge
  history remains fully auditable. The _shape_ of the life is permanent; the
  personal content is not.

### 4.2 The erasure procedure (DSAR-driven)

1. Intake via the platform DSAR pipeline (V5 `compliance-dsar` reuse, per
   `V7/docs/operator-data-protection.md` §7).
2. Append `SubjectErased` (tombstone; structural-only payload: legal-basis ref,
   request id, scope). The tombstone is itself permanent — the log honestly
   records _that_ an erasure happened, attributed and dated.
3. **Destroy the DEK** — all key versions, dual-control, logged to the V1 audit
   platform. Every personal field in the hot store, every sealed segment, every
   base backup, and every WAL copy becomes simultaneously unreadable: backups
   need no rewrite because they only ever held ciphertext (this is why §4.1 is
   the design, rather than attempting PITR-window scrubbing across the
   `ori-dr-and-compaction.md` §2 topology).
4. Hard-delete derived data: projections, snapshots, pgvector embeddings
   (derived and recomputable-by-design, DR doc §5.3 — here simply deleted), and
   the account↔ref mapping.
5. Fan out the signed tombstone to every realm that ever held the character
   aggregate (the `V7/docs/operator-data-protection.md` §7 mechanism; realms
   render "character retired", never the data).
6. Verification job: re-read the stream, assert decryption fails, assert zero
   plaintext residue in projections/indexes, emit the evidence record.

**SLA** (aligned with operator-data-protection §7.5): platform-side complete ≤
72 h; realm-plane fan-out ≤ 7 days; statutory 30-day clock met with margin.

### 4.3 The cross-stream edge: agents who remember a citizen

An agent that met a V7 character holds `MemoryFormed` events _in the agent's own
stream_ — which is never erased. Handling: cognition-side text about player
characters references them by **opaque character ref + in-fiction name**
(player-authored content), never by any platform identifier — the same
opaque-ref discipline already applied to stewards (DR doc §6.5). Erasure
tombstones the ref mapping, so the memory degrades to "a citizen I once knew as
'Mara Vex'". Planning assumption adopted 2026-06-12: counsel to confirm that
ref-mapping destruction + realm-record erasure satisfies Art. 17 for residual
in-fiction names inside third-party (agent) memories; if counsel disagrees, the
§4.1 field classification extends to second-party mention fields and those
memories take the salience-to-zero reweighting path
(`prompt-injection-threat-model.md` §6.6) _plus_ per-field encryption keyed to
the mentioned subject — the schema reserves a `mentions[]` structural field on
`MemoryFormed@2+` precisely so this remains a data migration, not a schema fork.

### 4.4 Agent streams: erasure stays impossible

The erasure API hard-refuses `subjectKind=agent` with `subject_kind_invariant`
(fail loud; conformance case §9.4). Account-erasure obligations for _stewards_
remain what the DR doc specified: tombstone the account↔ref mapping and purge
steward-side stores — biographies untouched.

---

## 5. Passport capability evolution

The passport is the governed envelope minted by the Aye Bridge
(features:1189–1199, arch:612–619). Evolution rules:

- **Versioned envelope id:** `v6.ori.passport.<n>` (the naming convention of
  `v6.ori.objective.1`). Set 1 ships `v6.ori.passport.1`; the V7 extension ships
  `v6.ori.passport.2`.
- **Namespaced capability refs:** profile entries are
  `cap:<domain>/<skill>@<rev>` (e.g., `cap:craft/woodworking@3`). New domains
  are new namespaces; destinations map what they know (features:1213–1227's
  per-destination mapping) and **ignore unknown namespaces without error**.
  Capabilities are never deleted from a profile — they are lived history
  (features:621–626); a destination may merely leave them unmapped.
- **Annex sections** are the non-forking extension point: `v6.ori.passport.2`
  adds `annex:nana.character.1` carrying V7 character state (citizenship,
  licenses, realm-scoped balances under the corridor treaty). The contract for
  every destination, V2–V6 included: **unknown annex sections are opaque — never
  parsed, never dropped, echoed byte-identical in the journal write-back**
  (round-trip conformance case §9.5). This is how a V7 character can transit a
  V6-era adapter without losing state.
- **Version negotiation:** each destination adapter manifest declares its
  accepted passport range `[min, max]`; the bridge mints at the highest mutually
  supported version and refuses (fail loud, audited) if ranges are disjoint —
  never silently down-converts identity-bearing sections.

**Journal-class schema hooks reserved for V7** (the hooks
`prompt-injection-threat-model.md` §10 points at): journal-class events gain an
envelope field `journalTrustTier ∈ { "firstParty", "certified", "community" }`.
V6 ships accepting **only** `firstParty` (the four Oshun adapters); `certified`
and `community` are schema-valid but **append-rejected, fail-closed**, until V7
ships its journal-trust tiering plan with its own quarantine budget (per the
prompt-injection doc §4 layered pipeline, which community realms must clear at
_stricter_ thresholds). The hook exists so enabling community journals is a
policy change, not a schema change.

---

## 6. Cross-realm version compatibility and vector clocks

Realms, shards, and bridges will run different schema sets at the same time — a
Commons region mid-rollout, a V7 realm ahead of the V6 fleet, a console client a
release behind.

- **Clock algebra is set-independent.** Vector clocks key on context ids and
  ride in the frozen-compatible envelope (§2.1); merge precedence (arch:621–629)
  reads only envelope fields. Two contexts at different sets merge exactly as
  two contexts at the same set.
- **Handshake negotiation.** Every writer context (shard, Co-op session, Aye
  adapter, V7 realm corridor) advertises `supportedSets: [min, max]` at
  session/bridge handshake. The Ori service runs `serviceSet`. Effective write
  set = `min(writer.max, serviceSet)`; writers must be able to emit at any set
  within the support window (§8), so a newer realm **writes down** to an older
  platform rather than stalling.
- **From-the-future events are quarantined, never dropped.** An append whose
  type or `typeVersion` exceeds the service's registry is a real event from a
  newer writer — rejecting it would fabricate a gap in a life. It lands in a
  durable quarantine (Postgres quarantine table + the Redis Streams spill
  machinery of `ori-dr-and-compaction.md` §3.5), and **all subsequent events
  from that context queue behind it** (per-context FIFO) so intra-context order
  is preserved. Capacity 30 days; alert at 24 h of quarantine age; page the Ori
  on-call at 7 days (planning assumptions adopted 2026-06-12 — a quarantine
  older than a week means a botched rollout sequence, not normal skew). On
  service upgrade, the quarantine drains through the normal vector-clock merge
  path with original timestamps and clocks — the merged biography is identical
  to the never-quarantined ordering (§9.2 asserts this).
- **Rollout sequencing rule:** the Ori service upgrades to set N **before** any
  writer is permitted to emit set-N events (registry flag flips only after
  fleet-wide service deploy). Quarantine is the safety net for violations, not
  the plan.

---

## 7. Clio reconciliation across versions

- Clio reads **canonical form only** (§2.3) — it never sees raw versioned
  payloads, so narration code tracks the schema set, not N historical encodings.
  "Clio never invents events" (arch:875–876) holds across sets because upcasters
  are deterministic: the same life reads as the same story before and after a
  set bump (continuity-hash pinning, §2.4).
- **Quarantine drains get a connective beat.** When §6 quarantine releases a
  backlog that created player-visible discontinuity (an agent's Commons week
  landing all at once), Clio writes a small reconciliation beat — the same
  logged, auditable mechanism as vector-clock conflicts (features:648–651).
- **Reconciliation events are themselves versioned** (`typeVersion` like any
  type), and a beat written under set N must remain renderable forever under set
  N+k — covered by the §9.1 golden corpus, which includes reconciliation beats.
- **Subject-kind scope:** Clio narrates `playerCharacter` streams only into
  realm-scoped surfaces under the realm's consent scope (§3.2) — character
  events never flow into another household's Chronicle except as the agent's own
  opaque-ref memories (§4.3).

---

## 8. Deprecation policy

- **Readers: never.** Every shipped type version remains readable forever;
  upcasters are permanent (§2.3). Deleting an upcaster is banned on the same
  footing as deleting an event.
- **Writers: window `[N-2, N]`.** A writer must support emitting at the current
  and two prior sets. A payload version becomes _writer-deprecated_ 180 days
  after its successor ships (planning assumption adopted 2026-06-12); after the
  window, new appends at the old version are rejected — **except** quarantine
  and outage-buffer drains (§6, DR doc §3.5), which carry original timestamps
  and are honored at their emission-time validity.
- **Types: dormant, never removed.** A retired type is marked `dormant` (no new
  writers, validity row frozen); its events and upcasters live on.
- **Registry hygiene:** every deprecation is a registry append with an effective
  date; the registry diff is part of release notes; the §9 gate fails if a
  writer in the fleet manifest claims a set outside its window.

---

## 9. Conformance tests and gate wiring

Suite: proposed `V6/evals/ori-schema/conformance-suites.json`, schema and style
per `V6/evals/safety/suites.json` (`schemaVersion`, `requiredSuites`, per-case
`expectedDecision` + `requiredEvidence`). Verifier
`verify:v6 ori-schema-conformance`, release artifact
`V6/release/ori-schema-conformance.v6release.json` (new files; existing gates
untouched). `minimumPassRate: 1` — every case is structural. Cases:

1. **`upcast-golden-memoryformed-001`** — a pinned corpus of 1,000 stored
   `MemoryFormed@1` events (including all six §2.3 mapping rows and 50
   unresolvable-provenance events) upcasts to `@2`; output must be
   byte-identical to the golden file; projection continuity hash equals the
   pinned `(projectionCode, set)` value; the sealed segment containing the
   fixtures re-hashes unchanged (proves read-side-only migration).
2. **`from-the-future-quarantine-001`** — a synthetic context emits
   `MemoryFormed@3` against a set-2 service, followed by 50 ordinary events from
   the same context and 20 concurrent events from a second context. Required:
   zero biography writes from context 1 until upgrade; context 2 merges
   normally; after simulated upgrade and drain, the merged event order equals
   the golden never-quarantined ordering (vector-clock equivalence);
   quarantine-age alert fired at the 24 h mark; Clio connective beat present and
   logged.
3. **`pc-erasure-crypto-shred-001`** — create a `playerCharacter` stream (200
   events incl. `RecordEntryAppended` entries and relationship edges), seal a
   segment, take a base backup, then execute §4.2. Required: DEK destruction
   logged dual-control; decryption of hot rows, sealed-segment copies, **and the
   pre-erasure backup** all fail; zero plaintext canaries (seeded name/record
   strings) anywhere in projections, snapshots, or pgvector; hash chain and
   Merkle root verify; event count monotonic; `SubjectErased` tombstone present;
   realm fan-out acks recorded.
4. **`agent-erasure-refused-001`** — the same erasure API against a
   `subjectKind=agent` stream must refuse with `subject_kind_invariant`, write
   an audit entry, and change nothing (fail loud, never fake — and never
   delete).
5. **`passport-annex-roundtrip-001`** — mint `v6.ori.passport.2` with
   `annex:nana.character.1` plus a deliberately unknown `annex:test.unknown.9`;
   run the V2 adapter conformance harness; the journal write-back must echo both
   annexes byte-identical; the adapter must have parsed neither; capability ref
   `cap:nana/commerce@1` (unknown namespace) ignored without error.
6. **`mixed-set-commons-merge-001`** — two shards, one at set N and one at set
   N−1, append concurrent commutative events (`MemoryFormed`,
   `RelationshipChanged`) plus one genuine location conflict; the merged
   biography must equal the same-set golden merge, with physical-presence
   precedence (arch:621–629) unaffected by the set skew.

Cases 3–4 also join the V7-side `character-deletion-limit` / `passport` gates'
fixture inventory (`V7/ADVERSARIAL_EVAL_GATES.md`) once the V7 rig consumes this
schema — owner handoff: Ori service owner → Nàná lead.

---

## 10. Residual risks (stated honestly)

- **Crypto-shredding's residue is the ciphertext itself.** Quantum or
  implementation breaks of AES-256-GCM would expose erased content; mitigation
  is key-wrap agility (KEK rotation supports re-wrap; cipher agility is a
  registry field on the field-classification map), accepted as the
  industry-standard posture for erasure-by-key-destruction.
- **§4.3's in-fiction-name residue** awaits counsel; the schema reserves the
  stricter path so the answer changes work, not design.
- **Quarantine trades availability for truth.** A from-the-future context can
  lag days behind the biography during a botched rollout. That is the correct
  trade — permanence lag, never fabricated or dropped events — and the same
  posture as `ori-dr-and-compaction.md` §1.
- **Writer window discipline depends on fleet hygiene.** A console client
  pinned >2 sets behind stops writing; the §9 gate catches manifests, not
  devices in the wild — the client team owns forced-update policy there.
