E1_E2_R3_Delta_Review_Claude_Opus_4.8.md
Memory Rebuild Docs/Stage_6_Charters/E1_E2_DOC81_Scope_Policy/Reviews/E1_E2_R3_Delta_Review_Claude_Opus_4.8.md
# DOC81 (E1/E2) — R3 Delta Design Re-Review (SCOPED, final pre-ratification gate)
**Reviewer model:** Claude Opus 4.8 · **Date:** 2026-06-08 · **Target:** `DOC81_Scope_Policy_Charter_Draft.md` **R3** (2,682 lines), repo `wbrody/Elnor-Specs@main` HEAD `48e795d`.
**Repo access:** confirmed (Composio GitHub connector; archive fetched + read directly — §3.0, §3.2, §3.3, §3.4, §4.2, §4.6.1–.4, §4.7, §5.x cascade, §6.6, §13.6/§13.7/§14.3, plus every named pipeline op grepped for a definition).
**Method:** delta only. R1/R2 cards, forks, declines (D1–D12, D-R1–D-R6), and rulings R-1…R-5 treated as CLOSED; no re-litigation. Judged as engineering.
---
## VERDICT: `MINOR_FIXES_THEN_RATIFY`
**Bottom line:** R3's unified-state rebuild is correct and closes the entire R2 Blocking/Substantive set — all four cases pass, the point+vector algebra is airtight, and the QF pack is genuinely formula-backed (meta-test PASS). Two real localized fixes stand between R3 and ratification: a **render-may-leave egress-floor skip** (step-3 gate doesn't match the 0c crosswalk trigger; `isEgressAction` is undefined) and a **seed contradiction** (§4.6.4 still says `local_file_export → reference_only_candidate` while §13.6 correctly says `normal_policy_check`). Both are one-line, paste-ready. Everything else is minor.
**Is R3 ratifiable?** Yes — after landing the two SUBSTANTIVE fixes (S1, S2). The minors (M1–M7) can ride the same commit or be deferred; none gates. Architecture and adjudication are untouched, so this does not reopen design. Recommend the NI-1 property-fixture gate (§11, disclosure-axis extension) as the delta re-check after the fixes land.
---
## 1. The four walked cases — all PASS (against the R3 text, L884–969)
**(a) cross-matter internal `retrieve` → full content (R-1).** PASS.
A cross-matter internal retrieve carries a raised scope floor (e.g. `reference_only_candidate` from §4.6 rule-3 cross_scope) but `conservatism_floor_basis.r1_qualifying = false`. Step 0c does not fire (no destination, not a `render*`), so `destination_floor` stays `normal_policy_check`. At step 3 (L937–940) `floorEff` is computed but its application is gated by `isEgressAction(retrieve) OR r1_qualifying` — **both false** ⇒ the floor is NOT applied ⇒ full content survives. Cross-matter relevance is handled by DAMS contamination ranking (§4.4), never a floor. Matches `fixture.policy.cross_matter_internal_retrieve_not_floored` (L982). This is exactly R-1: privilege/matter is an egress concern, not an internal gate.
**(b) empty-applicable internal → domain baseline, not block.** PASS.
Step 1c (L918–921): `applicable` empty AND `isInternalAction(action)` AND `request.principal == scopeResolution.object_owner_principal` AND `not r1_qualifying` ⇒ `applicable = [domainBaselineDecision(request)]`; the meet then proceeds on the always-present domain contribution. The else-branch hard-blocks (`policy.no_applicable_decision`) for egress / `write_durable` / `learn_*` / `delegate` / `carryover` / cross-principal (L917). Matches `fixture.policy.empty_applicable_internal_uses_domain_baseline_not_block` (L982). Correct: usability cliff removed for internal reads; fail-closed retained for everything that leaves or mutates. (See M2 re: `domainBaselineDecision` being undefined.)
**(c) `restamp_reeval` restore-up-to-ceiling reachable (R-2).** PASS.
Step 4 (L944–948): the sticky branch is `mode=='ordinary'` only; `mode=='restamp_reeval'` SKIPS sticky and instead clamps `eff.point`/`eff.disclosure_vector` to `MIN(current meet, rootCeilingItems)`. Because step 3's floor is mode-agnostic, the result is bounded by `MIN(root ceiling, current scope floor)` — so a lifted transient floor genuinely restores up to ceiling, while a still-present permanent restriction stays applied. Matches `fixture.policy.autonomous_restamp_restores_up_to_ceiling_after_floor_lift` (L982). Lint `policy.restamp_reeval_applied_sticky_restrictive` (L980) guards the inverse.
**(d) scope-floor disclosure ceiling survives to the final scalar — A-B1 class now structurally impossible.** PASS (structural, not patched).
`PolicyPoint` is 4 capability axes only (L622–624); `disclosure_class` is off the point, off `BOTTOM`/`TOP`/`meetPoints`/`leqPoint`. Disclosure travels solely in `DisclosurePermissionVector`, met by `meetDisclosureVectors` at every step. The floor (L939 meets `floorEff.max_disclosure_vector`), the domain (L1762 `contribution_disclosure_vector`), and the sticky prior all meet their disclosure **vectors** into the one `eff.disclosure_vector`. The scalar is derived **once** at `finalizeDisclosureAndCoherence` (L686–689) from that final vector, then `makeCoherent` caps content LAST. There is no scalar-disclosure write path to overwrite ⇒ the A-B1/Q4 bug class is unrepresentable, not merely fixed. Matches `fixture.policy.scope_floor_disclosure_ceiling_survives_scalar_derivation` (L982) + the V1 lints (L747: `policy.disclosure_class_present_on_policy_point`, `policy.policy_state_point_and_vector_met_separately`).
### Break attempts on the 0→7 order — one real hole (S1), the rest hold
- **Disclosure rises without a restamp →** blocked. Every meet (steps 2–5) is AND/MIN (removes only). The only widening is step-4 `restamp_reeval` (sticky skipped, ceiling-clamped) — the sanctioned, ceiling-bounded declassification path (L4). *Defense-in-depth note, non-gating:* `meet_v2`'s `mode='restamp_reeval'` carries no in-algorithm assertion that it was invoked under an authorized `RestampAuthority`; the authority gate lives in §3.4. Clean separation, and the ceiling clamp bounds it regardless — but confirm §3.4 is the **sole** caller that can pass `restamp_reeval`.
- **A floor undone at finalize →** impossible. `finalizeDisclosureAndCoherence` only derives the scalar and coheres content DOWN; it raises nothing.
- **Crosswalk floor skipped →** **REAL on the render-may-leave path (S1).** 0c computes `destination_floor` for `{export,delegate,carryover}` **or** `render* with destination` (L899), but step 3 applies it only `if isEgressAction OR r1_qualifying` (L938). For a render whose content leaves to an *allowed* external class, 0c does not block (disposition `policy_bound_egress`, L1817/1821) and sets `destination_floor=fail_closed_candidate` + `egress_attestation_required` — then step 3 skips the floor (a render-may-leave is not in the natural `isEgressAction` set, and need not be `r1_qualifying`). Result: full content renders to an external destination, attested but **not** floored. The hard block / disallowed-class is still enforced at 0c; only the content/disclosure **floor degradation** is dropped. See S1.
- **sticky/ceiling cross-mode →** holds. Ordinary is bounded by the prior (transitively ≤ ceiling); `restamp_reeval` is bounded by `MIN(root ceiling, current floor)`; obligations (step 5) and finalize (step 6) run after in both modes and only tighten.
---
## 2. New-defect findings (value-tiered; §+line; paste-ready)
### S1 — SUBSTANTIVE (must-fix): render-may-leave egress-floor skip + `isEgressAction` undefined
**§3.2 step 3, L935–940 (with 0c, L897–904).** The step-3 floor-application predicate is narrower than the 0c crosswalk-consultation predicate, and `isEgressAction` has **no definition anywhere** (grep: sole occurrence is its use at L938). A `render_*` action carrying a destination that resolves to an allowed external class consults the crosswalk (computing a restrictive `destination_floor`, e.g. `fail_closed_candidate`) but never applies it — an egress content/disclosure floor-skip in the same family as the A-B1/A-S3 leaks R3 was built to close.
**Fix (two parts):**
1. Make step-3's gate mirror 0c's trigger so any action that *consulted* the crosswalk also *applies* its floor:
```text
# L938 — was: if isEgressAction(request.action) OR scopeResolution.conservatism_floor_basis.r1_qualifying:
if isEgressAction(request.action) \
OR (request.action startsWith 'render' AND request.destination present) \
OR scopeResolution.conservatism_floor_basis.r1_qualifying:
```
2. Define the action partition once (closes M2's `isEgressAction`/`isInternalAction` too), so a Stage-7 implementer cannot guess:
```text
isEgressAction(a) := a in { export, delegate, carryover }
isInternalAction(a) := a in { retrieve, render_inline, render_*_without_destination, classify, inspect, ui_disclose, collect, extract }
# exhaustive + mutually exclusive over MemoryPolicyAction; a render_* WITH a destination is egress-for-floor (handled by the step-3 clause above).
```
Add lint `egress.render_with_destination_floor_not_applied` (V6 family) + fixture `fixture.egress.render_may_leave_applies_crosswalk_floor`.
### S2 — SUBSTANTIVE (must-fix): `local_file_export` floor — §4.6.4 contradicts §13.6 (workflow-damaging)
**§4.6.4 L1820 vs §13.6 L2604.** §13.6 correctly seeds the floor as `normal_policy_check` **with `E0EgressAttestation` retained (NOT a hard floor)**. The §4.6.4 inline seed comment still says `same_machine_local → local_file_export, floor reference_only_candidate`. A Stage-7 implementer following §4.6.4 content-floors a litigator saving their own full-content work product to local disk — the exact over-protection C4 is meant to catch.
**Fix (align the stale inline seed to the operative §13.6 value):**
```text
# §4.6.4 seed comment L1820 — was: same_machine_local → local_file_export, floor reference_only_candidate, attestation REQUIRED
same_machine_local → local_file_export, floor normal_policy_check, attestation REQUIRED # §7.4 / §13.6 — treat as egress + attest; do NOT content-floor routine local exports
```
(No code change beyond the seed table; the crosswalk schema already carries `policy_floor`.)
### M1 — MINOR: `FLOOR_EFFECT` return shape vs `ConservatismFloorEffect` fields
**§3.2 L939 vs §4.6.1 L1717–1724.** Step 3 reads `floorEff.point` and `floorEff.max_disclosure_vector`, but `ConservatismFloorEffect` exposes the four capability maxima as separate `max_content_fidelity` / `max_locality` / `max_learning_scope` / `max_mutation_authority` (plus `max_disclosure_vector`, `effect_id`) — there is no `.point`. Specify `FLOOR_EFFECT`'s projection:
```text
FLOOR_EFFECT(floor) := { point: { content_fidelity: e.max_content_fidelity, locality: e.max_locality,
learning_scope: e.max_learning_scope, mutation_authority: e.max_mutation_authority },
max_disclosure_vector: e.max_disclosure_vector, effect_id: e.effect_id } # e = the §4.6.1 row for `floor`
```
### M2 — MINOR (C3 overlap): load-bearing pipeline ops referenced but undefined
**§3.2.** Beyond `isEgressAction`/`isInternalAction` (defined in S1) and `domainBaselineDecision`, three are trivial lifts that should still be one line each so nothing is guessed:
```text
domainBaselineDecision(req) := domainContribution(req) wrapped as a synthetic MemoryPolicyDecision
(same 4-axis point + disclosure_vector; reason_code policy.domain_profile_only_internal_baseline) — idempotent with the step-2 domain input.
toPolicyPoint(d) := { content_fidelity: d.content_fidelity, locality: d.locality, learning_scope: d.learning_scope, mutation_authority: d.mutation_authority } # drops disclosure_class (vector-carried)
priorState(p) := { point: { p.effective_content_fidelity, p.effective_locality, p.effective_learning_scope, p.effective_mutation_authority },
disclosure_vector: p.effective_disclosure_vector, obligations:[], required_attestations:[], applied_floor_refs:[] }
clampPointDown(p,c) := { axis: LAT[axis].clampDown(p[axis], c[axis]) for axis in FOUR_CAPABILITY_AXES } # per-axis lift of Chain.clampDown (L608)
```
(`domainBaselineDecision` is the only one of these that is genuinely load-bearing — it is the entire content of case (b).) All other named ops resolve: `meetFloors` L1715, `FLOOR_EFFECT` L1708, `object_owner_principal` L386, `rootCeilingItems`→§3.4 `PolicyCeilingSnapshot`, `resolveDestinationPolicyCrosswalk`→§4.6.4 table lookup (row shape complete L1812–1819), `obligationDisclosureVectorCeilings` L1122, `evaluateActionPredicate` L1863, `bottomDisclosureVector` L1444, `DISCLOSURE_ALLOWS` L1482.
### M3 — MINOR: `meetPolicyState` accumulator fields break literal NI-1
**§3.0 L658–668.** `obligations` and `applied_floor_refs` use array CONCAT (L662, L664), while `required_attestations` uses Set-union (L663). So the point (`meetPoints`, MIN) and disclosure (`meetDisclosureVectors`, verified pure MIN/AND/Set at L1453–1467) are idempotent/commutative/associative — but the raw `PolicyEffectiveState` is **not** literally idempotent/commutative (concat duplicates/reorders). The laws hold only after obligation-resolution (§3.3, order-independent) + ref-set semantics. Also `destination_crosswalk_ref`/`sticky_prior_effective_policy_ref` use `b ?? a` (last-wins) — order-independent only under the (correct but unstated) invariant that ≤1 input carries each. **Fix:** either Set-union (dedupe by ref) for `obligations` + `applied_floor_refs` (mirrors attestations, makes the state literally lawful), OR have the NI-1 property fixtures compare **finalized + set-normalized** results rather than raw-object equality. Pick one and state it where `fixture.property.*` is defined (§11).
### M4 — MINOR: `meetAllStates` not empty-safe
**§3.0 L669.** `ss.reduce(meetPolicyState)` throws a raw `TypeError` on an empty array, unlike `meetAllPoints` which returns `⊥` on empty (L632). The caller guarantees ≥1 (domain always present), so it is safe in practice — but mirror the fail-closed guard for defense-in-depth:
```text
meetAllStates(ss) := ss.length ? ss.reduce(meetPolicyState) : { point: {...BOTTOM}, disclosure_vector: bottomDisclosureVector(), obligations:[], required_attestations:[], applied_floor_refs:[] }
```
(or throw `PolicyLatticeError` so it lands in the step-`catch` fail-closed path, not an unhandled `TypeError`).
### M5 — MINOR (architect-confirm posture): V10 `forceBottomDisclosure` bottoms the whole vector
**§3.2 L912, L933.** A single applicable decision whose `disclosure_class != deriveDisclosureClass(disclosure_vector)` sets `forceBottomDisclosure`, which bottoms the **entire** `eff.disclosure_vector` (⇒ `not_disclosable` ⇒ content coheres to `none` ⇒ object effectively blocked). F1 (L911) by contrast floors only the **one** malformed capability axis, explicitly to avoid one corrupt record DoS-ing a request (L694). The asymmetry is deliberate and fixture-locked (`fixture.policy.decision_scalar_vector_mismatch_bottoms_disclosure`, L982) and is fail-closed-safe — but it does let one self-contradictory decision DoS an object's disclosure. **Confirm the posture**, or align with F1 by *excluding* the mismatched decision (`continue` at L912, as stale/incompatible decisions already do) and letting the meet proceed on the valid inputs (domain always present).
### M6 — MINOR: stale "step order 0→6" prose
**§3.2 L881** ("The step order 0→6 is normative") predates the step-7 action-closure/predicate gate (L963–966, V23). Update to **0→7**. (Cosmetic; the code and lint `policy.action_predicate_not_evaluated` are correct.)
### M7 — MINOR (C2 nit, Phase-2): `principal_ref?` optional in `ScopeResolutionCacheKey`
**§6.6 L2167.** Optional ⇒ two distinct principals could both hash to the principal-absent key. For R-5, make `principal_ref` **required** in `ScopeResolutionCacheKey` (or treat absent as a distinct, non-colliding sentinel). `EffectivePolicyCacheKey` is already safe (principal arrives transitively via the required `principal_ref` inside `policy_evaluation_context_ref`, L720/L2175).
---
## 3. The four residual confirms (C1–C4)
**C1 — V13 derived/durable: COHERENT (no required fix).** The six objects — `ScopeResolutionResult`, `ScopeBoundary`, `EffectiveMemoryPolicy`, `PolicyMembraneDecision`, `PolicyCappedDAMSInput`, `PolicyEvaluationContext` — carry `persistence_kind:'derived_projection'` + `canonical_source_refs` + `rebuild_key` and still `extends E0DurableRecord` (D-R2 compromise; confirmed L729, L874, and the classification note L2674). `extends` supplies the structural envelope; the marker + `freshness_key` + the §6.6 cache keys + their lints (`cache.policy_reused_across_effective_state_generation`, `policy.artifact_missing_effective_state_generation`) enforce "rebuilt on generation change, never reused as truth across generations." That is exactly "rebuildable, not durable truth" on the EC side. **Optional one-line hardening (belt-and-suspenders, not required):** lint `classification.derived_projection_persisted_as_durable_truth` (a `derived_projection` consumed past its `freshness_key` generation without a rebuild). Existing freshness/cache lints already cover the failure.
**C2 — `principal_scope` placement (R-5): PRESENT in both keys; one Phase-2 nit (M7).** The field on `ScopeResolutionResult` is `principal_scope: PrincipalScope` (requesting-principal sentinel, L385) + `object_owner_principal: PrincipalScope` (the owner, L386 — the field step-1c compares). The cache keys use `principal_ref`: `ScopeResolutionCacheKey` carries it directly (L2167, optional — see M7); `EffectivePolicyCacheKey` carries it transitively via the required `principal_ref` inside `policy_evaluation_context_ref` (L2175 → L720). A cache cannot bleed across principals. The `principal_scope`/`principal_ref` name difference is intentional (sentinel vs identifier), not a defect.
**C3 — pseudocode boundary: mostly clean; the undefined cluster is M2 (+ S1's `isEgressAction`, M1's `FLOOR_EFFECT`).** Referenced-but-nowhere-defined: `isEgressAction` (L938 — S1), `isInternalAction` (L919 — S1), `domainBaselineDecision` (L920 — load-bearing, M2), `toPolicyPoint` (L930 — M2), `priorState` (L945 — M2), `clampPointDown` (L948 — M2); plus `FLOOR_EFFECT`'s return shape (M1). All other named ops have real definitions or unambiguous table-lookups (enumerated in M2). `rootCeilingItems` returns the §3.4 `PolicyCeilingSnapshot`; confirm that snapshot exposes both `.point` and `.max_disclosure_vector` (L948 consumes both) — it should, given the restamp `original_ceiling_ref` machinery, but it is the one accessor I could not pin to an explicit field list and is worth a glance at ratification.
**C4 — seeds: one real contradiction (S2); the rest are sound for a securities-litigation-first user.**
- `local_file_export` floor → **S2** (must be `normal_policy_check` per §13.6 L2604; §4.6.4 L1820 still says `reference_only_candidate`). This is the workflow-damage seed.
- `THRESHOLD_SHIPPED_DEFAULT_PROFILE = {0.85, 0.70}` (L1783/L2600) — usable out-of-box; `THRESHOLD_FALLBACK_NO_PROFILE = {1.0, 0.0}` (L1782/L2599) correctly no-profile-only. Good.
- `MAX_SCOPE_TRAVERSAL_DEPTH = 16` (L2598, D-R3) — fine for the local single-principal graph.
- contamination `minimum_measurement_confidence = 0.60` (L1618/L2601), topic band `0.20` / admit `0.70` (L2602) — reasonable, fail-closed below.
---
## 4. Meta-test — PASS (every table a consumer, every metric a formula, every hash a canonicalization, every stateful object transition rules, every optional field a presence condition)
No schema-without-formula found in the QF pack. Verified against source:
- **`deriveDisclosureClass`** (L1469–1477) — decision tree, **no fall-through to `full`**; `generic_reason_only`/`redacted_reason` → `redacted_summary` (CL A-B2), source-title/exact-count/full-reason → `full` (GPT №7). Monotone, consistent with `DISCLOSURE_ALLOWS`.
- **`meetDisclosureVectors`** (L1453–1467) — pure MIN/AND/Set; preserves rendering refs, conflict ⇒ drop-to-`none` (V11). NI-1-clean.
- **`evaluateThreshold` polarity model** (L1798–1804) — `higher/lower/range_is_safer`; `range_is_safer` throws (never silent pass); NaN/missing ⇒ fail-closed family.
- **`domainContribution` 9→5 crosswalk** (L1746–1765) — concrete `LVL_*` maps, per-action axis selection, emits point + disclosure **vector** (V2/A2-B5).
- **`computeCoverage`** (L554–560) — dedup + `searched ⊆ required`, zero-denominator guard, `may_emit_not_found` formula; `required_scope_refs` excludes walled/other-principal scopes (L546, closes A2-S10).
- **`topicMatchAmbiguity`** (L2275–2280) + **`evaluateCollectionDisposition`** (L2283) — real formula + governance/EC/ambiguity gate (V18, `defer_review_fail_closed` on unresolved governance).
- **`ContaminationRiskThresholdRule`** (L1614–1624) — `minimum_measurement_confidence` gate (QF4), `gte`/`block_on_equal`, `lower_is_safer`.
- **`cascadeComplete`** (L1937–1943) — freeze-gate-first (TOCTOU) + all-planes-done; **`lastActiveSupportEdgeLost`** (L1957–1961) — tri-state, `indeterminate ⇒ fail_closed`.
- **`ScopeEquivalenceCluster`** (L234–245) — `cluster_confidence = min_edge_confidence_over_selected_spanning_tree` + `lifecycle_state` + `equivalence_generation_id` (deterministic; closes A2-S8).
- **`DisclosureVectorCeilingComparison`** (L1228–1234) — explicit partial order (V19/QF13).
- **`validateQuotaEnvelope`** (L2213–2219) — non-negative-integer + `estimate ≤ max` + R-2 manual-approval guard.
- **`CanonicalHashSpec` `doc81.canonical_hash.v1`** (L2186–2191) — complete canonicalization (lexicographic keys, omit-absent, set ordering, NFC, RFC3339Z, sha256); every `ContentHash` defers to it.
- **Optional-field presence conditions** present where it matters: `binding_constraint` (L869), `action_permission_result` (L871), `issued_memory_flow_certificate_ref?` post-issuance + invariant (L1240/L1244, D-R1 form — correct), conditional `safe_label_vocabulary_version` (L2181), `user_visible_summary_ref` forbidden on `no_notice` (L1260/L1263).
**NI-1 / algebra assessment:** the lattice core (point MIN via `meetPoints`; disclosure via `meetDisclosureVectors`) is idempotent/commutative/associative — the laws hold over the *meet semantics*. The only gap is bookkeeping (M3): `meetPolicyState`'s `obligations`/`applied_floor_refs` arrays aren't set-normalized, so the laws don't hold on the **raw** state object, only on the finalized/set-normalized result. Fix M3 (set-union or fixture normalization) and the NI-1 property family is literally true over `PolicyEffectiveState`.
---
## 5. Subtractive note (standing pass)
Nothing in the R3 delta is good-but-redundant enough to cut — R3 *removed* the redundant scalar-disclosure representation (the V1 win) and the wall items are already explicitly non-gating (D-R5). The only "extra" is the deliberate belt-and-suspenders `require_safe_label` vector ceiling (L1120) duplicating the downstream render discharge; it is cheap and defensible, leave it. No strip recommended.
---
*Scope honored: depth on the R3 delta (§3.0/§3.2/§3.3/§3.4/§4.6 + QF pack), no re-review of settled material, no re-litigation of D1–D12/D-R1–D-R6/R-1…R-5. Two SUBSTANTIVE fixes (S1, S2) + seven MINORs; C1 coherent, C2 present (+M7 nit), C3 = M1/M2 cluster, C4 = S2 + sound seeds; meta-test PASS. R3 is ratifiable after S1+S2.*