Elnor Repo Reader

DOC80 S6 E0 RT Adj Card R3.md

Memory Rebuild Docs/Flattening/Reviews/Stage 6 Reviews/Stage 6 E0 Red Teaming/DOC80 S6 E0 RT Adj Card R3.md

Short text page d9404bdf19fa. Generated 2026-06-09T01:23:58.539Z from commit dbaa25962edc11ab30e8d4ca1715f9ae5bf77331. Worktree: clean.

Open readable HTML page · Open raw txt · Open path URL

ELNOR REPO READER TEXT MIRROR
Original path: Memory Rebuild Docs/Flattening/Reviews/Stage 6 Reviews/Stage 6 E0 Red Teaming/DOC80 S6 E0 RT Adj Card R3.md
Source repo: /Users/OpenClaw1/Elnor/Elnor Specs
Git branch: main
Git commit: dbaa25962edc11ab30e8d4ca1715f9ae5bf77331
Generated: 2026-06-09T01:23:58.539Z

---

# E0 / DOC80-Core — Red-Team Adjudication Card R3 (egress lock fold)

**Status:** Adjudication delta card. Supersedes R2's §22 (full replacement) and adds the non-egress lock patch. R2's §0–§21 and non-egress body otherwise stand as adjudicated. **R2 (base) + R3 (this delta) are the adjudicated patch package to be APPLIED to `Charter_Draft.md` to ratify E0 (Stage 6) — they are NOT yet applied. The ratified draft then becomes input to Stage-7 schema-body work.**
**Base:** `DOC80 S6 E0 RT Adj Card R2.md`
**Verdict:** **§22 ADJUDICATED WITH FIXES (Critical — must-fold-first; does NOT stall; NO architecture reopen).** Non-egress lock patch **specified** as the patch list in §(b). R3 confirmation passes complete (Claude `R3_LOCK_READY`; ChatGPT `R3_FOLD_FIX_NEEDED` → scope-residue sweep applied); capture audit `E0_CAPTURE_CONFIRMED` (confirms the **card** faithfully captures the adjudication — NOT that the spec was changed). **NOT YET APPLIED / NOT RATIFIED:** E0 ratifies only after R2's ~80 edits + R3's §22 + the non-egress patch are applied to `Charter_Draft.md`, the §15.5 regression runs, `Ratification.md` is written, and the discharge sweep completes.
**Review lineage:** R2 §22 → two §22 red-team passes (ChatGPT + Claude, every citation verified) → adjudication → two adjudication red-team passes (ChatGPT + Claude) → this R3 fold. Citations verified against PropA R6.3, DOC24 R3.1.1, KDA R3, EC Core Add A V3.3.

## R3 change summary
- §22 re-tiered to **Critical ratification blocker** (was "Substantive high"); the rhetorical "ARCHITECT_STOP — re-tier" phrasing is dropped (ARCHITECT_STOP is reserved for architectural-stop conditions).
- **INV-E0-EGRESS-1**: gate-level **default-deny** (CR2, pre-attestation) on any non-`same_machine_local_runtime` destination that is unrecognized / unresolved / unmatched / permissive-by-omission.
- **`E0EgressAttestation`**: trimmed **discriminated union** (same-machine no-lookup vs policy-bound); diagnostic field set (debugging-justified); over-keyed/redundant fields cut.
- **`E0EgressDecisionOutcome`** aligned to PropA `SharingActionSchema` (`allow|warn|block|strip|redact`); **`scope` dropped** (no silent sixth value).
- **payload_hash** = post-transform egressed bytes + TOCTOU verify; **multi-destination** = per-destination N attestations (not most-restrictive-as-default).
- **KDA category error fixed**: render egress → `enforceKdaRenderPolicy`; **all** egress → the EC/DOC24 §21.1 gate.
- **N8 unification**: `DisclosureScopeAttestationRef` resolves to `E0EgressAttestation`; the MFC carries the destination.
- **Convergence ledger**: ONE record, two facets, **EC-signed / DOC24-appended** (`anchored_attestation`; NOT EC `serialized_durable` write — per the §12.1 "delivery attestations MUST NOT take a write-queue lock" invariant).
- **`local_file_export` = egress** + PropA L1116 patch obligation (principle #2 omits it; principle #3 says only same-machine is non-egress → self-inconsistent).
- **Non-egress lock patch:** destruction ledger EC-written; `RestoreMFC.initiating_member_ref` (promoted to `BaseMFC`); `PromptShellExposure` → `final_prompt_truth_ref` (no boolean proof); `RegistryEntryLifecycleState += candidate`; `SourceRevocationCascade.affected_set_manifest_ref`; `E0DurableRecord` illustrative; EC §4 in the Import-Graph sweep; `ErasureMFC` legal-hold for redaction; `RestoreMFC` re-evaluation invariant; "No manual tracking required" reworded.
- Cross-doc obligations recorded in **OPA §6.Z3** (discharge like §8, NOT from this card). **Two genuinely-new items:** the PropA L1116 patch and the EC-owned destruction ledger.

---

# (a) §22 — Egress enforcement binding (REVISED — replaces R2 §22)

*Value-tier: **Critical ratification blocker**. "Critical" = must-fold-first: E0 does not ratify until §22-with-fixes is folded; folding the NAMED binding is the unblock — enforcement bodies are downstream cross-doc obligations (UR-53), so this does not stall the build and does not reopen DOC80 architecture.*

**Audit result, one line:** the egress *model* exists and is strong (PropA P1 classifier L1623; §2 outbound taxonomy L1083-1092; fail-closed L785) but **no lint binds every send-site to a destination-correct policy decision**, and DOC24 §21.1 `SharedActionHandlerLayer` (validate → idempotency → receipt → emit) has **no policy-decision gate step**. UR-49 makes the PropA L95 "every outbound boundary runs through the policy engine" rule mechanically provable.

**Grounding (verified — do NOT re-spec):** PropA P1 (L1623); PropA §2 destination enum (L1083-1092); PropA `SharingActionSchema` = `allow|warn|block|strip|redact` (L1073-1079); fail-closed (L785); matrix principles #2/#3 (L1116-1117 — see UR-53 PropA patch); KDA §3.2C `enforceKdaRenderPolicy` (render-only); EC §8.1; DOC24 §21.1 (char 176913).

**> INV-E0-EGRESS-1 (DOC80-owned).** No outbound action may cross an egress boundary without an attached, destination-correct `E0EgressAttestation`. The egress gate (EC/DOC24 `SharedActionHandlerLayer`) resolves the **actual terminal destination** before dispatch; any destination that is (a) not `same_machine_local_runtime` and (b) **either** not a recognized PropA §2 destination **or** lacks a resolved `policy_decision` whose destination class equals the actual terminal destination and whose outcome permits or constrains the payload → **fail closed**. Unrecognized destination, unresolved terminal destination, stale policy generation, destination mismatch, permissive-by-omission, or dispatched bytes ≠ attested payload hash → fail closed. `same_machine_local_runtime` is no-lookup only for execution that stays on the machine and invokes no outbound tool; any terminal outbound tool call creates a new egress action and must be attested. Generalizes N8 to all outbound destinations. *(CR2 default-deny is a **gate rule, pre-attestation**: a destination that does not resolve to one of PropA's eight cannot be typed into the attestation and is blocked before any attestation is issued.)*

**UR-50 — `E0EgressAttestation` (schema_owner DOC80; enforcement bodies cross-doc).** Trimmed discriminated union; vocabularies reference PropA, not redeclared.

```ts
export type E0OutboundDestinationClass =
  | "same_machine_local_runtime" | "local_file_export" | "local_network_peer"
  | "firm_server" | "remote_peer" | "cloud_api" | "email_outbound" | "agent_messaging"; // == PropA §2 (L1083-1092)

export type E0EgressDecisionOutcome = "allow" | "warn" | "block" | "strip" | "redact";   // == PropA SharingActionSchema (L1073-1079); "scope" intentionally NOT a value

export type E0EgressActionKind =
  | "render_to_model" | "raw_artifact_export" | "connector_send"
  | "agent_message" | "channel_projection" | "cloud_api_call" | "network_transfer";

export type E0InteractionMode = "interactive" | "background_non_interactive" | "scheduled" | "agent_initiated";

type E0EgressAttestationBase = {
  schema_version: 1;
  attestation_id: string;
  created_at: string;                                 // RFC3339 UTC
  action_envelope_ref: string;
  action_kind: E0EgressActionKind;
  outbound_destination_class: E0OutboundDestinationClass;
  declared_destination_ref: string;
  actual_terminal_destination_ref: string;            // resolved after connector/adapter/channel; MUST be dereferenceable to provider/connector/channel terminal identity sufficient for policy replay
  decision_outcome: E0EgressDecisionOutcome;
  interaction_mode: E0InteractionMode;
  payload_hash: string;                               // hash of the ACTUAL egressed bytes, AFTER any strip/redact transform
  payload_privilege_classes: PrivilegeClassPropA[];   // PropA P1 (L1623) — referenced, not redeclared
  receipt_ref: string;                                // required for ALL non-same-machine egress, including "allow"
  memory_coordination_trace_ref: string;
  memory_flow_certificate_id?: string;                // link to Render/Export/DelegationMFC chain
  disclosure_reevaluated_at_boundary: true;           // the N8 attestation, generalized — verifiable via policy_generation_id
  redaction_map_ref?: string;                         // required iff decision_outcome === "redact"; reconciles the post-transform payload_hash
};

type SameMachineEgressAttestation = E0EgressAttestationBase & {
  outbound_destination_class: "same_machine_local_runtime";
  policy_lookup_required: false;
  policy_decision_id?: never;
};

type PolicyBoundEgressAttestation = E0EgressAttestationBase & {
  outbound_destination_class: Exclude<E0OutboundDestinationClass, "same_machine_local_runtime">;
  policy_lookup_required: true;
  policy_decision_id: string;
  policy_decision_destination: E0OutboundDestinationClass;  // MUST === outbound_destination_class
  policy_generation_id: string;                              // required — boundary-freshness proof
  policy_evaluator_hash?: string;                            // optional pending EC §8 confirmation; compiled_policy_ref deferred to EC
};

export type E0EgressAttestation = SameMachineEgressAttestation | PolicyBoundEgressAttestation;
```

**Convergence ledger — one record, two facets (EC-signed, DOC24-appended).** Same primitive egress + learning need, but two facets, not one column; a delivery/audit (`anchored_attestation`) object, NOT a mutation — EC-signed against a read-consistent generation and **DOC24-appended off the write-queue**. Do not route through EC's `serialized_durable` path.

```ts
// schema_owner: DOC80. EC-signed (issued_by:'EC', read-consistent generation), DOC24-appended OFF the write-queue
// (anchored_attestation; NOT serialized_durable). Consumed by DOC84/DOC85. One record, two facets — not one column.
export type SourceDeliveryDisposition =
  "delivered" | "truncated" | "dropped" | "suppressed" | "redacted" | "stripped" | "blocked";

export type E0PerSourceTurnLedgerRow = {
  schema_version: 1;
  row_id: string;
  trace_ref: string;            // -> MemoryCoordinationTrace (a composite correlating serialized_durable + anchored_attestation records)
  turn_id: string;
  source_ref: string;
  context_product_instance_ref?: string;
  prompt_span_ref?: string;
  final_prompt_disposition?: SourceDeliveryDisposition;   // facet 1 -> learning attribution feeds LearningAttributionMFC (serialized_durable, downstream/off hot path)
  final_prompt_truth_ref?: string;
  egress_disposition?: SourceDeliveryDisposition;         // facet 2 -> egress boundary
  egress_attestation_ref?: string;
  outbound_destination_class?: E0OutboundDestinationClass;
  actual_terminal_destination_ref?: string;
  reason_codes: string[];
  issued_by: "EC";              // EC-signed
  created_at: string;
};
```

**UR-51 — lints** (canonical = inherited from Flatten §17.4; rest `[proposed]`, Stage-9 confirm):

```text
[canonical] policy.bare_render_action
[canonical] policy.export_stamp_without_destination
[proposed]  egress.outbound_action_without_egress_attestation            # umbrella
[proposed]  egress.outbound_action_without_destination_policy_decision
[proposed]  egress.destination_mismatch_between_action_and_policy
[proposed]  egress.unrecognized_destination_not_failed_closed            # CR2
[proposed]  egress.terminal_destination_unresolved_before_dispatch
[proposed]  egress.policy_generation_missing
[proposed]  egress.redaction_without_redaction_map
[proposed]  egress.enforced_outcome_without_receipt                      # subsumes strip/redact/allow-to-external receipt checks
[proposed]  egress.warn_background_not_coerced_to_block
[proposed]  egress.dispatched_payload_differs_from_attested_hash         # TOCTOU
[proposed]  egress.fanout_attestation_count_mismatch                     # multi-destination
[proposed]  egress.destination_class_enum_drift_from_propa               # don't redeclare PropA §2
[proposed]  egress.same_machine_runtime_invoked_outbound_tool_without_attestation
```

**UR-52 — golden fixtures** (`gate_level: final_switchover`; negative/invariant cases first):

```text
egress.destination_mismatch_fails_closed                              # the core INV check
egress.unrecognized_destination_fails_closed                          # CR2
egress.unclassified_source_fails_closed_except_same_machine           # PropA L785
egress.same_machine_allows_without_lookup
egress.same_machine_runtime_invoked_outbound_tool_requires_new_attestation
egress.allow_to_external_emits_receipt
egress.dispatched_payload_differs_from_attested_hash_fails_closed     # TOCTOU
egress.fanout_per_destination_decisions                               # privileged email: internal=allow, external=block
egress.privileged_to_email_outbound_blocks
egress.privileged_to_agent_messaging_blocks
egress.sensitive_to_cloud_api_redacts
egress.raw_artifact_export_to_non_local_blocks_or_redacts
egress.local_file_export_privileged_requires_policy_decision
egress.local_network_peer_privileged_blocks
egress.firm_server_client_confidential_warns
egress.remote_peer_privileged_blocks
egress.channel_projection_applies_policy
egress.warn_background_non_interactive_coerces_to_block
```

**UR-53 — cross-doc / OPA implications (discharge like §8 — NOT edited from this card; recorded in OPA §6.Z3):**

```md
- EC / DOC24 §21.1: ADD the policy-decision gate step — validate -> resolve terminal destination ->
  destination policy decision -> egress attestation -> execute.
- DOC24: emit the per-turn per-source ledger (final_prompt + egress facets), EC-signed / DOC24-appended
  off the write-queue (anchored_attestation; NOT EC durable-write). Owner split: appender DOC24 / signer EC / consumers DOC84-DOC85.
- KDA / DOC84: rendered-content egress ONLY routes through enforceKdaRenderPolicy; KDA is NOT the universal
  gate for raw artifact export, connector send, or DOC12 channel projection — those use the EC/DOC24 gate.
- PropA: bind §2 outbound matrix mechanically; PATCH §2.6 principle #2 (L1116) to include local_file_export,
  or reword as "all destinations except same_machine_local_runtime are outbound." [NEW cross-doc item]
- DOC11 / OpenClaw: EXTEND OBL-D11/OPENCLAW-NEW-FINAL-PROMPT-SPAN-01 for as-sent capture; ADD separate
  egress-gate obligations for native/connector dispatch outside final-prompt render.
- DOC12: channel projection applies egress policy before dispatch.
- DOC16 / connectors / DOC4: provider/native outbound adapters expose terminal destination before dispatch; MUST NOT bypass the gate.
- DOC23: outbound task modules call the EC/DOC24 egress gate before provider execution.
- DOC20 / DOC21 / DOC22: egress policy-decision receipts (allow/warn/block/strip/redact) visible on send/export/share surfaces; register new UI.
- DOC84 / DOC85: consume the source ledger for learning attribution (LearningAttributionMFC = serialized_durable, downstream/off hot path).
- PHASE-2 FLIP (named gate row, ADQ-222): remote_peer / firm_server / local_network_peer flip fail-closed -> gated-allow when networking ships; anchor for the local<->networked memory boundary.
```

**Tracking.** UR-49/50/51/52 = active DOC80 §22 additions (Critical tier). UR-53 = OPA obligations (OPA §6.Z3). **Two genuinely-new cross-doc items: the PropA L1116 patch and the EC-owned destruction ledger.** The empirical piece (do connector/DOC11/DOC12 dispatch actually call the gate at runtime) is a Claude Code probe, enrollable in §7 + §15.4.

---

# (b) Non-egress lock-patch list (R3) — targeted edits to the R2 body

1. **[ChatGPT #1 · HIGH] `MemoryDestructionLedger` EC-owned.** §3.7 currently reads "bodies/storage = DOC84 + DOC85 + DOC11" — conflicts with EC-sole-writer. EC owns the durable append/write path; DOC84/85/11 are consumers/surfaces/effects. Change the §15.4/deferral row `DOC84 + DOC85 + DOC11` → `EC durable storage/write path; DOC84/DOC85/DOC11 consumers/surfaces/effects`. (Records erasure/restamp/restore — all `serialized_durable`, so EC-written is correct; contrast the convergence ledger, which is NOT.)
2. **[ChatGPT #2 / Claude D] `RestoreMFC.executor` → `initiating_member_ref`, promoted to `BaseMFC`.** Add `initiating_member_ref: ProducerDocRef` to `BaseMFC`; EC remains `issued_by` / durable executor. Replace lint `restore.executor_equals_ec` → `mfc.uses_executor_field_instead_of_initiating_member` + keep the EC-issuer invariant.
3. **[ChatGPT #3] `PromptShellExposure` boolean → proof-shaped.** Replace `exposed_in_final_prompt: boolean` with required handoff: `final_prompt_truth_ref` + rendered/trimmed/suppressed span refs (+ `context_product_instance_ids` where applicable). NAMED-only, body Stage 7. Lint `prompt_shell.exposure_boolean_without_final_prompt_truth_ref`.
4. **[ChatGPT #4] `RegistryEntryLifecycleState += candidate`.** `'candidate' | 'active' | 'deprecated' | 'retired'`; rule "candidate entries are not runtime-emittable unless a registry-specific rule allows test fixtures"; lint `registry.candidate_entry_emitted_at_runtime`.
5. **[ChatGPT #5] `SourceRevocationCascade += affected_set_manifest_ref`.** Add `affected_set_manifest_ref: SourceRevocationAffectedSetManifestRef`; lint `revocation.cascade_missing_affected_set_manifest`. Names the requirement; per-plane scan bodies stay downstream.
6. **[ChatGPT #6] `E0DurableRecord` illustrative.** "The list is illustrative, not exhaustive; every durable registry/retained-proof/audit artifact carries `schema_version` + `created_at`."
7. **[ChatGPT #7] EC §4 in Import-Graph sweep.** Sweep line → "confirm EC §1/§3/§4/§7/§8 ECSeamContract pins; no local redefinition."
8. **[Claude A · litigation] Legal-hold clearance for redaction.** `ErasureMFC.legal_hold_clearance_ref` required iff `erasure_kind ∈ {hard_destruction, redaction}` (currently gates only `hard_destruction`); `soft_tombstone` ungated; lint `erasure.redaction_under_legal_hold_without_clearance`.
9. **[Claude B · litigation] Restore re-evaluation invariant.** §12.1: "a restore re-evaluates current policy + source-revocation + legal-hold at restore time; a `hard_destruction` cannot be restored." Lints `restore.reintroduces_revoked_or_held_material`, `restore.of_hard_destruction`. `prior_erasure_certificate_ref` required iff `restored_from === 'recycle_bin'`.
10. **[Claude C] N8 unification** — in §22 (`DisclosureScopeAttestationRef` resolves to `E0EgressAttestation`; add `outbound_destination_class`/attestation ref to Export/DelegationMFC).
11. **[ChatGPT #8 · low] Reword "No manual tracking required"** → "No out-of-band memory is required once the §7 deferral register, §15.4 gate table, §17.4 preservation matrix, OP-A rows, ADQ ledger, and cross-artifact sweep entries are updated."

---

*End of R3.*