Elnor Repo Reader

Doc23 Add B FULL Adj RT Reviews.md

Active Working and Red Team/DOC23 Working/DOC23 Red Teaming/Add B Adj Card Review 5.29/Doc23 Add B FULL Adj RT Reviews.md

Short text page a00418e95c25. 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: Active Working and Red Team/DOC23 Working/DOC23 Red Teaming/Add B Adj Card Review 5.29/Doc23 Add B FULL Adj RT Reviews.md
Source repo: /Users/OpenClaw1/Elnor/Elnor Specs
Git branch: main
Git commit: dbaa25962edc11ab30e8d4ca1715f9ae5bf77331
Generated: 2026-06-09T01:23:58.539Z

---

# Claude

# DOC23 Addenda B — Consolidated Independent Review of the Adjudication Card (Final)

**What this is.** A single, self-contained independent review of `DOC23_ADDENDA_B_RT_ADJUDICATION_CARD_CONSOLIDATED.md` (126 adjudicated items deduped from ~228 raw reviewer assertions). It is my **final** view, consolidating a per-row correctness pass, a dedup-completeness coverage matrix, a cross-row interaction/redundancy pass, and a reconciliation with a second reviewer's (ChatGPT's) assessment of this review. Where my position changed across passes, this document states only the final position in the analysis sections; the explicit "what changed and why" mapping lives in §7 so nothing is lost but nothing stale is left in the per-row analysis.

**Verified against (GitHub `wbrody/Elnor-Specs@main`, `Current Specs/DOC23/DOC23 Addenda B/`):** Outcome Evaluator+Revisor V3.3.1; Feedback Delivery V1.0.1; Source Workspace V1.0.1; Task Forum + Run Board V1.0.1; Evaluation Common Contracts V1.1.1; Addenda B Core R0.7.1; base Task System Modular Architecture R3.1. Source review cross-walked: `Active Working and Red Team/DOC23 Working/DOC23 Red Teaming/DOC 23 Add B RT Reviews 1 (5.28).md`. Findings are verified against the live text, not the card's line anchors.

**Conventions.** `§x` = section in the operative specs unless prefixed "card." or "RT." `[CARD BUG]` = defect in a proposed fix; `[SPEC BUG]` = confirmed defect in an operative spec; `[CHATGPT FORK]` = a defect introduced by the second reviewer's schema. Structural types (`StorageRef`, `OwnerDoc`, `ISO8601`, `ArtifactScopeRef`, `PolicyEvaluationRef`, `CapabilityRef`, `ClaimRef`, `TaintClass`, `CalibratedScore`, `RepairStrategyKind`, `HardRevisionCallKind`, `OutcomeEvaluationDisposition`, `SourceRecordRef`, `ArtifactVersionState`) are assumed to exist in their owner docs and are referenced, not redefined. Canonical schemas are defined once in §6/§8/§10; analysis sections reference them.

------

## 0. Executive summary

The package is fundamentally sound and worth shipping into an R0.4 amendment — but verification flips several dispositions, the strongest fixes need rewrites, and the amendment should be **staged**, not applied as a flat pile of 126 rows.

The organizing conclusion: do not "apply 126 rows + a hardening package." Apply a **structural layer first** (one governance envelope, one type-owner sweep, one phantom-field lint, one finding event/record/view model, one termination ledger, scoped derivation receipts, one read-model invalidation discipline), then the row fixes. Otherwise the amendment fixes local bugs while preserving the pattern that produced them. And — critically — the structural layer must itself pass a **strip/type-owner pass before adoption (Step 0)**, because as currently drafted across this review and the second reviewer's pass it carries new forks and duplicate stores that the discipline is meant to forbid.

**Treat as build-blockers:**

- **A-01 / A-05 — lossy basis collapse.** Folding `authority_basis` into `assurance_basis` silently loses the `user_instruction` and `saved_criteria` blocking bases (neither exists in `AssuranceBasis`). Keep both arrays, using the **verified** FD authority enum.
- **A-01 — the projection strips governance.** The view that reaches UI/forum/delivery must carry `taint_class`/`matter_id`/`privileged`/`data_class`, or it re-opens the laundering paths D-01 and D-24 close.
- **A-01 — migration unspecified** for a `schema_version 1 → "2.0"` change (basis singular→array, confidence string→numeric, new required `finding_kind`); with the event/record split (§6.3) it must populate both objects.

**Dispositions that flip:**

- **A-11 → DECLINE** — the enum already exists (§6.16.1: `production | signal_generation | calibration`); the card's `cross_calibration` is wrong.
- **B-25 → DECLINE** — `depends_on_step_ids` already exists on `RevisionPlanStepBase` (§7.5) and §6.11.1 already does cycle detection; the proposed minimal base would delete ~8 real fields.
- **B-15 → DECLINE / OP-A-only** — `RoomKind.plan_review` is registered by **DOC12** (`OBL-DOC12-FORUM-01`); the fix targets the wrong registry.
- **D-04 (tier-0 sub-fix) → DECLINE** — "remove tier 0" deletes the load-bearing `lookup_receipt` tier; reconcile the contradiction instead.

**Partial misreads (real but mis-scoped):** **B-03** (the artifact path is already protected by `ArtifactMutationPrecondition` + §11.20; the real gap is the Source Workspace write path), **B-24** (a loop breaker already exists at §6.7.3; this is a refinement, not a void).

**Dedup completeness:** essentially complete (~227 → 126); the three named likely-miss areas (ChatGPT Audit Addendum, Grok §4/§5, Gemini memory) are all covered. One true orphan (**Claude D19**), one cited-but-unaddressed (**Claude D20**), three thin spots (**Grok §3.3 / §5.7 / §5.9**), one citation typo (**B-24 is Grok §4.9, not §4.10**). These are promoted to rows in §5/§10.

------

## 1. The amendment plan (staged)

**Step 0 — Strip/type-owner pass on the structural layer itself.** Before writing any of the §6 structural objects, run the TypeOwnerRegistry sweep and the object-admission criterion (a new object enters only if it has a producer, a consumer, a durable artifact, and a declared owner) over the proposed structural schemas. This catches the forks/dupes resolved in §6/§7 (the forked authority enum, the duplicate blocking-basis enum, the un-collapsed `NoVerdictReason`, the duplicate attempt-store).

**Layer 1 — Structural hardening (§6).** GovernanceEnvelope → exhaustive TypeOwnerRegistry → phantom-field lint → finding event/record/view (architect-gated, §6.3) → `FindingMatchKey` + single `RevisorTerminationLedger` → scoped formula receipts/observations/rollups → read-model invalidation.

**Layer 2 — Disposition flips.** A-11, B-15, B-25 decline; D-04 tier-0 sub-fix decline.

**Layer 3 — Critical row fixes (§4).** A-01/A-05, A-02, A-16, B-03/D-16, B-24, C-03, D-01, D-24.

**Layer 4 — §G hardening (§8).** Derivation + invalidation + degraded modes + surface contracts + reliance-decay + delegation.

Order matters: if §G ships before the derivation/governance/invalidation layer, it builds polished read-models over unstable truth.

------

## 2. Disposition changes at a glance

The card's default is "accept all except where marked." This is the exception list — every row where I recommend a change to the disposition or the fix. Rows not listed are confirmed sound as written. (The "why my view moved" deltas from earlier passes are in §7.)

| Row  | Card disposition  | Final recommendation                | Why (one line)                                               |
| ---- | ----------------- | ----------------------------------- | ------------------------------------------------------------ |
| A-01 | ACCEPT            | ACCEPT W/ MODS                      | Event/record/view split (§6.3); keep both `assurance_basis` + `authority_basis` (verified FD enum); governance on all three; migration; name `FindingKind`. |
| A-02 | ACCEPT            | ACCEPT → **elevate CRITICAL**       | Breaks Pattern C read path; reuse bundle's `EvaluatedTarget`/`EvaluationBasis`; make old `target_*` projections. |
| A-04 | ACCEPT            | ACCEPT W/ MODS                      | Default policy self-contradictory (`judge_can_override:false` + an override allowlist) → one allowlist. |
| A-05 | ACCEPT W/ MODS    | (reinforced)                        | Compute `blocking_authority_satisfied` from `authority_basis`; keep typed `BlockingAuthorityEvaluation` (§6.3). |
| A-07 | ACCEPT            | ACCEPT W/ MODS + architect decision | Import `IndeterminateCause` (Addenda-A R203); reuse §5.4.2 `EvaluationLimitationKind`; build ONE deduped `NoVerdictReason` (§6.6). |
| A-11 | ACCEPT            | **DECLINE**                         | Enum exists (§6.16.1); `cross_calibration` wrong.            |
| A-12 | ACCEPT (authored) | ACCEPT W/ MODS                      | Use named `OutcomeVerdict`, not §5.13 per-lane `EvaluationVerdict`; `defer`/`request_changes` don't force a verdict. |
| A-16 | ACCEPT (CRITICAL) | (keep) + fix                        | Whitelist sanctioned `DirectFixStep`; advisory context still taint-checked before injection. |
| A-21 | ACCEPT            | (refine)                            | Validation needs a `finding_kind → targets_artifact` map to be decidable. |
| A-23 | ACCEPT W/ MODS    | re-anchor                           | Fields are **Source Workspace §4.2/§4**, not FD; rename the payload field. |
| A-26 | ACCEPT            | (refine)                            | Pin `FindingMatchKey` to a stable artifact id (reconcile with D-18); reuse §6.2 `FailureKind`. |
| B-02 | ACCEPT            | (refine)                            | Idempotency key collides with B-27 regenerate loop; add `attempt_seq`/`prior_output_hash`. |
| B-03 | ACCEPT ⚠verify    | re-scope                            | Artifact path already protected (§11.20 + `ArtifactMutationPrecondition`); real gap is SW write API (→ D-16). |
| B-08 | ACCEPT            | rename                              | `ExecutionFailureKind` collides with §6.2 `FailureKind` and §11.17 `WorkspaceWriteFailureKind` → `StepExecutionFailureKind`. |
| B-15 | ACCEPT ⚠verify    | **DECLINE / OP-A-only**             | DOC12 owns `plan_review` (`OBL-DOC12-FORUM-01`).             |
| B-16 | ACCEPT-AS-FIX     | ACCEPT W/ MODS                      | Configurable tiebreaker policy with required total-order `final_tiebreaker`; drop `created_at`; use `total_tokens` not `estimated_lock_duration_ms`. |
| B-24 | ACCEPT (CRITICAL) | (re-frame)                          | Refinement of existing §6.7.1/§6.7.3 (not a void); richer trigger taxonomy but thin detector (accounting on the ledger). |
| B-25 | ACCEPT (CRITICAL) | **DECLINE**                         | `depends_on_step_ids` exists (§7.5); §6.11.1 cycle detection exists; proposed base deletes fields → B-25R (rename, not replace). |
| C-01 | ACCEPT            | ACCEPT + scoped receipts            | Add `FormulaEvaluationReceipt`/`MetricObservation`/`MetricRollup`, scoped to durable/reliance/learning metrics (§6.5). |
| C-03 | ACCEPT-AS-FIX     | (complete)                          | Remove **both** `predicted_pre_hash` and `predicted_post_hash`; patch §11.20 RULE + prose. |
| D-01 | ACCEPT            | ACCEPT W/ MODS                      | Complete the map (4 missing kinds) **and** route trust through `SourceTrustBasis` (conservative for `expert_report`/`technical_doc`), reconciled with SW Retrieval lineage (§6.7-D01). |
| D-04 | ACCEPT            | ACCEPT W/ MODS                      | Keep tier 0 (`lookup_receipt`); forbid downstream claim dependence; reconcile the actual contradiction. |
| D-13 | ACCEPT            | **elevate**                         | Cross-run guidance is an injection-into-prompts path; route through governance + the contested check. |
| D-16 | ACCEPT ⚠verify    | (confirmed)                         | Real gap; reference `OBL-ADDB-SW-V12-WORKSPACE-API-01`; home for B-03's precondition. |
| D-24 | ACCEPT            | (confirmed)                         | Real privilege gap; matter firewall precedes visibility; anchor Task Forum §5.3/§5.4. |

**New rows to add** (§6/§10): `GovernanceEnvelope` (X-01), `RevisorTerminationLedger`, phantom-field lint, exhaustive `TypeOwnerRegistry`, read-model invalidation, `RelianceDecayMonitor`, `DelegationEnvelope`, Task-agent forum-surface ownership (D19), task-scoped forum (D20), feedback→prompt responsibility matrix (Grok §3.3), sub-agent metric observation (Grok §5.7), BoardDigest ResearchNeed import (Grok §5.9).

------

## 3. The nine ⚠verify rows — verification results

| Row      | Claim                                                        | Result                                                       |
| -------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| **A-02** | target/basis fields live on the bundle, not the envelope     | **CONFIRMED.** On `EvaluationFeedbackBundle` (FD §2: `evaluated_target: EvaluatedTarget`, `evaluation_basis: EvaluationBasis`); the envelope (COMMON §3.1) has `target_artifact_ref`/`target_artifact_version_ref`/`target_scope_ref`/`evaluation_snapshot_ref`/`criterion_lineage`. V3.3.1 §5.18 has the Pattern C Judge read the missing names off the envelope. |
| **A-05** | FD `authority_basis: EvaluationAuthorityBasis[]`; §3.4 r2 makes it the blocker test | **CONFIRMED.** §3.3 carries it (9 values, see §6.3); §3.4 r2: a `severity:"blocking"` finding needs ≥1 of `{deterministic_check, source_reference, tool_verification, user_instruction, saved_criteria}`. |
| **A-11** | `LearningMode` referenced, never enumerated                  | **FALSE.** §6.16.1: `production | signal_generation | calibration`. `cross_calibration` is wrong. → DECLINE. |
| **A-23** | conflict in FD                                               | **WRONG ANCHOR.** Both fields are **Source Workspace §4.2/§4** (`ApplicabilityScope.authority_level: "binding"|"persuasive"|"advisory"|"unknown"`; `domain_payload.authority_level`). A third `authority_level` (directive strength) exists in Core. |
| **B-03** | no write precondition on SW direct fixes                     | **PARTIAL.** Artifact `direct_fix` already protected: §7.5 `preconditions[]` (incl. `live_artifact_hash_matches_snapshot`), §11.20 hash check, `ArtifactMutationPrecondition`. Real gap = the SW **record** write path. |
| **B-15** | `plan_review` never registered                               | **WRONG OWNER.** Registered by DOC12 (Forum V1.0.1; `OBL-DOC12-FORUM-01`). |
| **B-16** | §11.9 tie-breaker rule 4 = wall-clock `created_at`           | **CONFIRMED.** §11.9.4 ends `4. created_at asc; 5. plan_id lexicographic`. |
| **C-03** | §7.2.1 emits `predicted_post_hash` as LLM output             | **CONFIRMED.** §7.2.1 `rolling_hash_chain` carries `predicted_pre_hash`+`predicted_post_hash`; §11.20 RULE expects Step N+1 to validate against the predicted hash. |
| **D-16** | workspace API referenced but undefined                       | **CONFIRMED.** V3.3.1 §12 has only "basic" ops; tracked as `OBL-ADDB-SW-V12-WORKSPACE-API-01`. |

------

## 4. Per-row findings (final, with schema/anchor fixes)

Each entry is the final consolidated position. Structural objects referenced here are defined once in §6.

### A-01 — Two incompatible `EvaluationFinding` schemas — unify via event/record/view; the naive fix has three bugs

Verified incompatibility — **V3.3.1 §5.7**: `finding_text, severity(4), state: FindingState, basis: AssuranceBasis` (singular), `target_artifact_ref, taint_class, confidence: "low"|"medium"|"high"`, `schema_version: 1`. **FD §3.3**: `finding_kind(12), authority_basis: EvaluationAuthorityBasis[], lifecycle_state, target_criterion_id?, affected_claim_refs?, confidence: number, based_on_board_digest_ref?`, `schema_version: "1.0"`. Unify into the **event/record/view** model (§6.3). Three bugs to fix in the unification:

- **(a) [CARD BUG] basis collapse is lossy** — `user_instruction`/`saved_criteria` (FD §3.4 r2 blockers) have no `AssuranceBasis` member; keep both `assurance_basis[]` and `authority_basis[]` and compute the blocker boolean from `authority_basis`.
- **(b) [CARD BUG] the view strips governance** — `FeedbackFindingView` must carry the `GovernanceEnvelope` (§6.1).
- **(c) [CARD BUG] no migration / `FindingKind` unnamed** — define `FindingKind` (§6.3) and a v1→v2.0 migration populating both event and record.

Canonical schemas: §6.3. Lints: `validation.blocking_finding_without_authority`, `validation.view_drops_governance_fields`, `validation.finding_v1_unmigrated`, `validation.finding_authority_assurance_axis_collapsed`.

### A-02 — Pattern C reads fields not on the envelope — CONFIRMED; elevate to CRITICAL

The source review rates this CRITICAL; the card lists it plain ACCEPT — **elevate** (it breaks the headline read path). Reuse the bundle's existing `EvaluatedTarget`/`EvaluationBasis` types (don't mint `*Ref` variants), and define `evaluated_target`/`evaluation_basis` as typed **projections** over the envelope's existing `target_artifact_ref`+`target_scope_ref` and `evaluation_snapshot_ref`+`criterion_lineage` (or fix V3.3.1 §5.18 to read the fields that exist), to avoid a third overlapping representation.

### A-04 — Pattern C route-resolution policy — ACCEPT W/ MODS

[CARD BUG] The shipped default contradicts itself: `judge_can_override_evaluator: false` makes `override_allowed_only_for_finding_states` dead config. Collapse to one representation:

```ts
judge_override_allowed_for_finding_states: FindingState[];   // [] = never overrides; drop the boolean
// A Judge numeric pass cannot clear an Evaluator blocking finding unless that finding's state ∈ this set.
```

### A-06 — State enum count & mapping skew — CONFIRMED

`OutcomeEvaluationState` has 15 members; COMMON §3.1 calls it "14-value"; §3.2 omits `evaluating`; `max_iterations_reached` is referenced but absent from the enum. Fix (split runtime vs disposition states, add `max_iterations_reached`, one normative `OUTCOME_STATE_MATRIX`) is sound. Prune the broader enum thicket per A-07/§6.6: prefer making `SubstantiveVerdictStatus` a derived column of the matrix rather than a free-standing enum.

### A-07 — Indeterminate/limitation taxonomy — ACCEPT W/ MODS + architect decision

[CARD BUG] Both enums the card proposes to "add" already exist or are owned elsewhere: `EvaluationLimitationKind` is defined at **V3.3.1 §5.4.2** (verified 7 values) — reuse it; `IndeterminateCause` is referenced in COMMON §3.1 as **`// V4 R203` (Addenda-A-owned)** — import it. They are ~80% the same axis; collapse into one deduped `NoVerdictReason` vocabulary (§6.6) with a registry mapping old labels as aliases. This relocates a taxonomy two addenda own → **architect decision + reconciliation against the actual R203 member list** (not verifiable from the DOC23 set). `TaskReliancePacket.unresolved_limitations` (§8) consumes the canonical `NoVerdictReason`, not a locally minted enum.

### A-11 — `LearningMode` — DECLINE

Defined at §6.16.1 (`production | signal_generation | calibration`, behaviors §6.16.2). The card's `cross_calibration` is wrong; applying it verbatim corrupts the enum and §6.16.2. Residual: add a §15→§6.16.1 cross-reference if missing. E-07 behavior deferral stands. Lints: `validation.learning_mode_value_drift`, `validation.learning_mode_redeclared_outside_owner`.

### A-12 — `HumanOutcomeFeedbackEvent` (card-authored) — ACCEPT W/ MODS

[CARD BUG] References §5.13 `EvaluationVerdict` (a per-lane struct: `{verdict_id, lane_id, result:"lane_passed"|…}`) where it means the outcome-level verdict, which is currently inline-and-unnamed on the envelope. Name it and use it; don't force a verdict for routing-only decisions:

```ts
type OutcomeVerdict = "passed" | "failed" | "indeterminate" | "not_applicable";  // name COMMON §3.1's inline union
// HumanOutcomeFeedbackEvent: overridden_verdict?: OutcomeVerdict; resulting_verdict?: OutcomeVerdict;
// decision ∈ {request_changes, defer} ⇒ resulting_verdict forbidden. validation.human_feedback_verdict_misuse
```

### A-16 — Direct repair bypasses `revision_in` — CONFIRMED CRITICAL; fix has an interaction bug

FD §7.2 Channel 2 wires `repair_instruction_out → DraftRevision.instruction_in`, `format_repair_out → FormatChecker.data_in`, `feedback_bundle_out → RevisionModule.context_in`, bypassing the `ArtifactMutationPrecondition` + `revision_in` chain. [CARD BUG] The fix's "only `revision_in` or `revision_compatible`" rule forbids the **sanctioned** `DirectFixStep` path (§7.5, `target_port:"none_direct_fix"`, class-gated §10, `ArtifactMutationPrecondition`-guarded). Whitelist it:

```ts
// validation.repair_routed_to_non_revision_port (error) UNLESS the write is:
//   (a) port == "revision_in", OR
//   (b) PortRevisionEligibility.revision_compatible === true WITH module_revision_capability_ref, OR
//   (c) a DirectFixStep (target_port == "none_direct_fix") with direct_fix_class ∈ direct_fix_allowed_classes
//       AND a satisfied ArtifactMutationPrecondition (§7.5/§11.20)
// All other instruction_in/data_in/context_in wiring = ADVISORY CONTEXT ONLY (no mutation).
```

Note (→ D-01): advisory context is still **rendered into prompts** by DOC15/CIL — A-16 stops mutation, not injection; tainted advisory context must still pass the D-01 sanitization/taint rule before reaching a prompt.

### A-17 / A-18 / A-19 / A-20 / A-21 — sound (one note)

A-17 (Revisor is the planner), A-18 (bundle emission contradiction), A-19 (`proposed → dismissed` + auto-dismiss — naturally satisfied by the §6.3 record lifecycle, but the §5.7.1 transition table still needs the explicit edge), A-20 (`unanchored_llm_judgment` ack) — all sound. A-21 (optional fields required by invariants): the validation needs a `finding_kind → targets_artifact` map to fire deterministically (`validation.artifact_targeted_finding_missing_version_ref`).

### A-23 — re-anchor

Fields are **Source Workspace §4.2** (`ApplicabilityScope.authority_level`) + **§4** (`domain_payload.authority_level`), not FD. Different value vocabularies → prefer **renaming** the payload field (`domain_payload.domain_authority_level`) over asserting precedence between incomparable scales. (Third `authority_level` in Core — note in the §6.2 sweep.)

### A-26 — `FindingMatchKey` — refine (two interactions)

[CARD BUG/interaction] Reuse the existing §6.2 `FailureKind`; and key on a **stable** artifact id, not a versioned `ArtifactScopeRef`, or D-18's stability fix doesn't reach the path that consumes the match key. Canonical schema: §6.4.

### A-27 — sound

`EvaluationSnapshot.source_workspace_head_hashes: Record<ArtifactRef,string>` is genuinely wrong-typed; the `SourceWorkspaceSnapshotHashSet` replacement is correct and is the concrete type B-03's precondition compares against.

### B-01 / B-04 / B-05 / B-06 / B-07 / B-09 / B-10 / B-11 / B-12 / B-13 / B-14 — runtime cluster, sound

Unified `RevisionExecutionLifecycle` FSM (B-01); parallel rolling hash (B-04, distinct from C-03); cascade convergence (B-05) + dependency-cycle/`pending_dependency` deadlock (B-06); `ParallelBatchFinalizationReceipt` (B-07); candidate-vs-head + `SideEffectIntentCandidate` (B-09); cancel + Hard-Call blocking scope (B-10); skip protocol (B-11); policy-freshness fields (B-12); `ResearchNeedLease` (B-13); forum deadlock breaker (B-14) — all sound. B-05/B-20's counters consume the single `RevisorTerminationLedger` (§6.4). B-14 cites Claude D20 whose substance (task-scoped forum) it does not address (→ §10).

### B-02 — idempotency key — refine (B-27 collision)

[CARD BUG/interaction] `attempt_class:"regenerate"` alone doesn't distinguish successive regenerations → the second is deduplicated and B-27's loop can't progress.

```ts
interface StepIdempotencyKey {
  run_id: string; plan_id: string; step_id: string; step_kind: StepKind;
  target_ref_hash: string; input_payload_hash: string;
  attempt_class: "first"|"retry"|"regenerate";
  attempt_seq: number;            // monotonic per (step_id, attempt_class); REQUIRED for regenerate
  prior_output_hash?: string;     // the B-27 hash being escaped; folds the two fixes together
}
```

### B-03 — re-scope to the Source Workspace write API

The artifact path is already protected (§7.5 `preconditions[]` incl. `live_artifact_hash_matches_snapshot`; §11.20; `ArtifactMutationPrecondition`). The genuine gap is the SW **record** write path. Re-scope the precondition to the SW API and home it in D-16:

```ts
interface WorkspaceWritePrecondition {
  target_record_ref: StorageRef; expected_snapshot_hash: string;   // SourceWorkspaceSnapshotHashSet member (A-27)
  on_mismatch: "abort_and_reevaluate"|"queue_behind_lock"|"fail"; lock_mode: "optimistic_snapshot_hash"|"pessimistic_write_lock";
}
// validation.workspace_record_write_without_precondition. Artifact path keeps ArtifactMutationPrecondition.
```

### B-08 — rename to avoid collision

[CARD BUG] `ExecutionFailureKind` collides in name with §6.2 `FailureKind` (finding classification) and §11.17 `WorkspaceWriteFailureKind`. Rename to `StepExecutionFailureKind`; register all three (distinct scopes) in the §6.2 TypeOwnerRegistry.

### B-15 — DECLINE / OP-A-only

`plan_review` is registered by DOC12 (Forum V1.0.1; `OBL-DOC12-FORUM-01`). The Forum module correctly defers via `room_kind?: string`. Keep only the existing DOC12 obligation; add a cross-doc dependency closure record rather than a local registry entry (§10 includes `ExternalRoomKindDependency`).

### B-16 — configurable tiebreaker with guaranteed total order

[CARD BUG] §11.9.4 currently ends `4. created_at asc; 5. plan_id lexicographic`. A verbatim "risk descending (safer first)" patch is self-contradictory and dropping rule 5 removes the only total order. Final: drop wall-clock `created_at`; keep a **configurable** policy (some environments want safety-first on privileged work) **but** require a total-order `final_tiebreaker`, and use `revision_cost_total_tokens` (already computed) rather than the unestimable `estimated_lock_duration_ms`:

```ts
interface ConcurrencyTieBreakerPolicy {
  policy_id: "default.short_lock_after_priority.v1" | "safety_first_for_privileged_work.v1" | "risk_reduction_after_priority.v1";
  ordered_fields: Array<
    "required_for_overall_pass_desc" | "is_high_stakes_desc" | "outcome_priority_asc"
    | "revision_cost_total_tokens_asc" | "plan_risk_score_asc" | "plan_safety_score_desc">;
  final_tiebreaker: "plan_id_lexicographic_asc";   // REQUIRED — guarantees total order
  schema_version: "1.0";
}
// Default ordered_fields: [required_for_overall_pass_desc, is_high_stakes_desc, outcome_priority_asc,
//   revision_cost_total_tokens_asc] + final_tiebreaker.
// validation.concurrency_tie_breaker_uses_wall_clock | _not_total_order | _missing_policy_ref
```

### B-24 — Revisor sufficiency — re-frame as the predicate feeding §6.7.3, with a richer (but thin-stored) detector

[CARD BUG/framing] §6.7 already has emit-states (§6.7.1: `needs_verification|needs_information|needs_human_judgment|unable_to_evaluate`), seven success conditions (§6.7.2), and a loop breaker (§6.7.3: `repeated_insufficiency_count`, N=3), plus D16's `still_failing_same_reason`. The missing piece is the **insufficiency predicate**. Adopt a **rich trigger taxonomy** (the additional triggers map to real states — policy, budget, side-effect, identical-output, cascade-cycle, precondition), but keep the detector **thin**: all attempt/score/count accounting lives on the single `RevisorTerminationLedger` (§6.4), and the detector **observes and aggregates** the existing typed guards (B-06/B-08/B-09/B-12/B-27) rather than re-routing them. Canonical schemas: §6.4. Route to a Hard Call **only after** the §6.7.3 threshold; per-attempt, emit the §6.7.1 state; add `needs_verification` to the route.

### B-25 — DECLINE (misread + destructive); replace with B-25R dependency canonicalization

`RevisionPlanStepBase` (§7.5) already has `depends_on_step_ids`; §6.11.1 does topological sort with cycle detection; §6.11.3 states steps form a DAG. The premise is false, and the proposed minimal base would delete `step_order, affected_artifact_refs, affected_outcome_ids, source_repair_depth, idempotency_key, preconditions[], expected_output, on_failure, human_gate_recommended, goal_impact_assessment, expected_pre_hash, produced_post_hash`. Replace with **B-25R**: treat `depends_on_step_ids` as canonical, add an optional derived `DependencyEdge[]`/`RevisionPlanDependencyReadModel` (isomorphic if present), and apply B-26's `revalidation_trigger → revalidation_policy` as a **field rename on the existing base** — not a base replacement.

```ts
interface DependencyEdge {
  from_step_id: string; to_step_id: string;
  edge_kind: "requires_output" | "requires_artifact_version" | "requires_human_resolution"
           | "requires_source_answer" | "requires_verification";
  schema_version: "1.0";
}
interface RevisionPlanDependencyReadModel {
  plan_id: string; dependency_edges: DependencyEdge[];
  derived_from_step_dependency_hash: string; created_at: ISO8601; schema_version: "1.0";
}
RULE revision_plan_dependency_source_of_truth:
  RevisionPlanStepBase.depends_on_step_ids is canonical; DependencyEdge[] is a derived read model;
  if both present they MUST be isomorphic.
// validation.revision_plan_dependency_edge_drift | _cycle | _targets_missing_step | _read_model_stale
//   | revision_plan_step_dependency_undefined
```

### B-26 / B-27 — sound (with the B-02 interaction)

B-26: single `revalidation_policy` field — apply as a rename on the existing base (replaces `revalidation_trigger`). B-27: fold `previous_attempt_hashes` into the B-02 key and the §6.4 ledger.

### C-01 / C-02 / C-04 / C-05 / C-06 / C-07 / C-08 / C-09 / C-10 — math cluster, sound + scoped receipts

All dispositions sound. C-01's `FormulaRegistry` + `CalibratedScore` is the structural keystone (correctly subsumes ~15 "no formula" findings). Add the **derivation-receipt layer** — `FormulaEvaluationReceipt` + `MetricObservation` + `MetricRollup` (§6.5) — because a registry proves a formula *exists*, not that a stored number *used* it. **Scope it** (durable/reliance/learning metrics only; not transient hot-path scores) to avoid unbounded hot-path receipts. C-04's `advice_regression_rate` is also where Grok §5.7 partly lands (→ §10).

### C-03 — complete the edges

§7.2.1 carries **both** `predicted_pre_hash` and `predicted_post_hash`; remove both from the LLM output contract (the LLM may pass through a known snapshot hash but must not be contracted to *emit* a SHA), and patch the §11.20 RULE `rolling_hash_chain_valid` + prose + `validation.rolling_hash_chain_broken/mismatch` to compare the dispatcher-computed post-hash. The §7.5 base's `expected_pre_hash?/produced_post_hash?` are the runtime-populated counterparts and stay.

### D-01 — taint: complete the map AND route through trust basis

Verified: 15 `source_kind`s, 8 `TaintClass` values, no map. **Two fixes:** (1) complete the map (the original 11 + the missing 4); (2) [improvement] do **not** default `expert_report`/`technical_doc` to `external_authority_trusted` — an expert report is often party-submitted/adversarial; a technical doc may be vendor marketing. Route trust through a `SourceTrustBasis` with conservative kind-defaults, **reconciled with SW's existing "Retrieval lineage" block (§4.1)** rather than added as a parallel axis. Canonical schema: §6.7-D01. The transitive-taint rule, `SanitizationNode`, and `TaintAggregationPolicy(max_taint)` are correct and high-value.

### D-04 — keep tier 0

[CARD BUG] "Remove tier 0" deletes a load-bearing tier. Verified: tier 0 = `lookup_receipt` ("receipt records only"), a member of `SourceDocumentationMode`, `SourceRecord.tier: 0|1|2|3`, with examples ("Check today's stock price → tier 0"). Keep tier 0 but bar it from supporting downstream claims:

```ts
// KEEP tier ∈ {0,1,2,3}. tier 0 = lookup_receipt (receipt-only/ephemeral); may_support_downstream_claims: false.
// Reconcile any "tiers 1-3" prose/table to include tier 0. SourceTierTransition.from_tier/to_tier: 0|1|2|3 (not bare number).
// validation.tier0_source_record_materialized | claim_depends_on_tier0_lookup | tier0_lookup_cited_in_final_artifact
```

The rest of D-04 (persist transitions, align verification states, gate demotion) is sound.

### D-02 / D-03 / D-05 / D-06 / D-07 / D-08 / D-09 / D-10 / D-11 / D-12 / D-13 / D-14 / D-15 / D-17 / D-18 / D-19 / D-20 / D-21 / D-22 / D-23 — sound (two elevations)

All sound. **D-09** (passive board auto-publishes everything) — pair under the privilege-firewall heading with D-24 for privileged matters. **D-13** (cross-run RunGuidance) — **elevate**: it's an injection-into-future-prompts path (the never-checked `contested` state + cross-run vector); its fix must route through the governance/taint check (D-01) and the contested check, not just durable persistence. (Note: "Claude D-card" row numbers and "card D-row" numbers are different namespaces.)

### D-16 — confirmed gap

Define the full workspace API surface (V3.3.1 §12 has only "basic" ops; tracked as `OBL-ADDB-SW-V12-WORKSPACE-API-01`). This is the home for B-03's precondition.

```ts
type SourceWorkspaceOperationKind =
  | "create_workspace" | "read_workspace_snapshot" | "read_source_record" | "add_source_record"
  | "update_source_record" | "append_source_query_record" | "update_research_need" | "answer_research_need"
  | "acquire_research_need_lease" | "release_research_need_lease" | "add_verification_record"
  | "add_freshness_record" | "mark_source_stale" | "record_tier_transition" | "create_source_set"
  | "update_source_set" | "promote_library_candidate" | "export_workspace_bundle";
interface SourceWorkspaceMutationPrecondition {           // = B-03's WorkspaceWritePrecondition, workspace-scoped
  workspace_id: string; expected_workspace_head_hash: string; expected_event_seq: number;
  target_record_ref?: StorageRef; expected_target_record_hash?: string;
  lock_mode: "optimistic_event_seq" | "pessimistic_write_lock"; lock_lease_ref?: StorageRef;
  on_conflict: "abort_and_reevaluate" | "queue_behind_lock" | "fail_outcome"; schema_version: "1.0";
}
interface SourceWorkspaceOperation {
  operation_id: string; operation_kind: SourceWorkspaceOperationKind;
  task_id: string; run_id?: string; workspace_id: string;
  actor_ref: string; command_ref?: string; idempotency_key: string;     // each op → command_ref + idempotency_key (D-14)
  precondition?: SourceWorkspaceMutationPrecondition; payload_ref?: StorageRef;
  governance: GovernanceEnvelope; created_at: ISO8601; schema_version: "1.0";
}
interface SourceWorkspaceOperationReceipt {
  receipt_id: string; operation_id: string; operation_kind: SourceWorkspaceOperationKind; workspace_id: string;
  prior_workspace_head_hash?: string; new_workspace_head_hash?: string; prior_event_seq?: number; new_event_seq?: number;
  status: "applied" | "read_completed" | "conflict" | "rejected_by_policy" | "failed";
  conflict_reason?: "workspace_head_hash_mismatch" | "event_seq_mismatch" | "target_record_hash_mismatch" | "lock_unavailable";
  created_at: ISO8601; schema_version: "1.0";
}
// validation.workspace_api_operation_unregistered | workspace_mutation_without_precondition
//   | workspace_event_seq_conflict | workspace_receipt_missing_head_hash | workspace_command_missing_idempotency_key
```

### D-24 — privilege firewall

Forum §5.3 carries `matter_id?` but §5.4 visibility resolution ignores it.

```ts
// A post with matter_id == X is visible ONLY to readers under matter_id == X regardless of `visibility`;
// `visibility` scopes WITHIN the matter. privileged:true is always matter-scoped at every access tier.
// validation.forum_post_cross_matter_leak. Anchor: Task Forum §5.3/§5.4.
```

### §E (held) / §F (declined) — concur

The Phase-B deferral set and the four declines are appropriately scoped. E-13's forward-compat learning-scope fields should reuse the `GovernanceEnvelope` (§6.1) so networked-learning scope and matter/privilege travel together.

------

## 5. Coverage matrix (dedup completeness)

**Count reconciliation.** Raw ≈ **227** (Claude 63: A1-A6, B1-B12, C1-C15, D1-D24, S1-S6 · ChatGPT ~110: 89 findings + 8 IDEA + 2 CONFIRMED + 15 Audit Addendum + 7 self-learning-2 · Gemini 19 · Grok 35) ≈ the card's "~228." Adjudicated: 88 fix + 13 held + 4 declined + 21 surfaces = **126** + 5 folded notes. Arithmetic holds.

**Failure-point verdicts:** ChatGPT Audit Addendum (15) — fully covered (net-new A-26/A-27/B-26; rest reinforce B-02/B-04/B-07/C-07/B-11/A-10/D-06/D-10/D-12/D-13/D-15/D-21). Grok §4/§5 (24) — all substantively covered; three thin (§3.3/§5.7/§5.9); one citation typo (B-24 is §4.9, not §4.10). Gemini memory (5) — fully covered, all deferred (E-01..E-05); the five BUGs are live (C-02/C-03/C-04/C-05/B-16).

**Exceptions — now promoted to rows (§10):**

| #    | Finding                                                      | Status                                 | Action                                                       |
| ---- | ------------------------------------------------------------ | -------------------------------------- | ------------------------------------------------------------ |
| 1    | **Claude D19** — Task Agent appears in two forum-shaped surfaces | **ORPHAN**                             | New row + `TaskAgentForumSurfaceOwnership` (§10).            |
| 2    | **Claude D20** — Forum run-scoped only; no task-scoped forum | **THIN** (cited under B-14)            | New row + `ForumScopePolicy` (§10); must inherit the D-24 matter firewall. |
| 3    | **Grok §3.3** — one doc owns end-to-end feedback→prompt data-flow + responsibility matrix | **THIN** (B-17 fixes only port typing) | New row + `FeedbackToPromptResponsibilityMatrixRow` (§10).   |
| 4    | **Grok §5.7** — sub-agent metrics named but no recording schema | **THIN** (partly C-04)                 | New row + `SubAgentAdviceMetricObservation` (§10); state now-vs-defer. |
| 5    | **Grok §5.9** — `BoardDigest.open_research_needs` references `ResearchNeed` without SW import | **THIN** (A-09/D-11)                   | `BoardDigestResearchNeedRef` (§10) + TypeOwnerRegistry entry (`ResearchNeed`→SW §6). |
| 6    | **ChatGPT item 21** — limitation values stuffed into the state field | **MERGE?** (A-06/A-07)                 | Ensure §6.6 mapping forbids limitation values in the state field; don't double-fix §5.4.2.2. |
| 7    | **ChatGPT item 37** — declared-dependency-only revalidation too brittle (scope) | **THIN** (B-05)                        | Confirm B-05/B-26 cover revalidation *scope* or note it.     |
| 8    | **B-24** cited "Grok §4.10"                                  | **Citation typo**                      | It's Grok §4.9; §4.10 = library promotion → D-20's source.   |
| 9    | **B-03** cites "ChatGPT CG-SW9"                              | **Attribution nuance**                 | B-03 is Gemini F-01 + D-05; no ChatGPT SW finding is about concurrent-write safety. |
| 10   | **ChatGPT items 28-29** — delivery/consumption receipts (per-item status) | covered via Appendix F under A-08      | Verify Appendix F specifies *per-item* consumption status.   |

**No wrongful splits; no wrongful merges that lose a fix.** Heaviest merges are legitimate (E-10 absorbs 12 `[SELF-LEARNING]` items; C-01 absorbs ~15 "no formula" findings).

------

## 6. Canonical structural schemas (Layer 1 — defined once)

These objects are referenced throughout §4/§8/§10. They incorporate the corrections from §7. Run **Step 0** (§1) over them before writing.

### 6.1 GovernanceEnvelope (universal mixin)

```ts
interface GovernanceEnvelope {
  taint_class: TaintClass;
  data_class: "public" | "internal" | "privileged" | "local_only";
  matter_id?: string;
  principal_id?: string;
  learning_scope?: "local" | "matter" | "team" | "firm" | "networked";
  privileged: boolean;
  policy_decision_refs: PolicyEvaluationRef[];
  sanitization_required: boolean;
  export_policy: "export_allowed" | "redaction_required" | "export_blocked" | "local_only";       // can it LEAVE the system
  projection_policy: "must_preserve_governance" | "may_downgrade_only_with_sanitization_receipt"   // can a lower-gov VIEW be made
                   | "non_exportable";
  schema_version: "1.0";
}
// Required on every GovernedObjectKind (finding event/record/view, envelopes, bundles, RunGuidanceItem,
//   board posts, BoardDigest, context packets, SourceRecord, SourceQueryRecord, ResearchNeed,
//   EvidencePackage, TaskReliancePacket, LearningSignalEnvelope, MetricObservation, externalization receipts).
// Orthogonality note: export_policy answers "may it leave"; projection_policy answers "may a lower-gov view be derived".
//   non_exportable/local_only are aligned across both and must not contradict.
// validation.governed_object_without_envelope | view_drops_governance_fields | exported_object_without_governance
//   | projection_downgrades_governance_without_sanitization
type GovernedObjectKind =
  | "EvaluationFindingEvent" | "EvaluationFindingRecord" | "FeedbackFindingView"
  | "EvaluationResultEnvelope" | "EvaluationFeedbackBundle" | "RunGuidanceItem"
  | "TaskRunBoardPost" | "BoardDigest" | "TaskRunContextPacket"
  | "SourceRecord" | "SourceQueryRecord" | "ResearchNeed" | "EvidencePackage"
  | "TaskReliancePacket" | "LearningSignalEnvelope" | "MetricObservation" | "WorkspaceExternalizationReceipt";
interface GovernedObjectRegistryEntry {
  type_name: GovernedObjectKind; owner_doc: OwnerDoc;
  governance_required: boolean; governance_field_path: string;   // usually "governance"
  allowed_projection_targets: string[]; projection_must_preserve_governance: boolean;
  schema_version: "1.0";
}
// validation.governance_field_wrong_path | exported_object_without_governance
```

### 6.2 TypeOwnerRegistry + phantom-field lint (run exhaustively)

```ts
interface TypeOwnerRegistryEntry {
  type_name: string; canonical_owner_doc: OwnerDoc; canonical_section_ref: string;
  type_kind: "interface"|"enum"|"type_alias"|"schema"|"read_model"|"receipt"|"event"|"command"|"policy";
  status: "canonical"|"imported"|"deprecated"|"pending_absorption"|"projection_only";
  allowed_projection_type_names: string[];
  duplicate_type_names: Array<{ doc: OwnerDoc; section_ref: string; disposition: "delete"|"rename"|"projection"|"alias" }>;
  pending_consumer_behavior?: "persist_only"|"suppress_promotion"|"disable_ui_affordance"|"emit_validation_warning"|"block_route";
  schema_version: "1.0";
}
interface SchemaReferenceValidationRule {
  rule_id: string; owner_doc: OwnerDoc;
  reference_pattern: "reads_field"|"writes_field"|"must_carry_field"|"emits_type"|"consumes_type"|"extends_type"|"projects_type";
  source_section_ref: string; referenced_type_name: string; referenced_field_path?: string;
  expected_owner_doc?: OwnerDoc; severity: "error"|"warning"; schema_version: "1.0";
}
// Seed the registry with the known collisions: FailureKind (§6.2 finding) vs StepExecutionFailureKind (B-08)
//   vs WorkspaceWriteFailureKind (§11.17); EvaluationVerdict (§5.13 lane struct) vs OutcomeVerdict (A-12);
//   the three authority_level fields (SW §4.2, SW §4 domain_payload, Core directive); IndeterminateCause (R203)
//   vs EvaluationLimitationKind (§5.4.2). 
// validation.field_reference_not_in_schema | type_reference_not_in_owner_registry | projected_field_missing_from_source
//   | consumer_reads_field_not_emitted_by_producer | schema_reference_owner_drift
//   | type_declared_without_owner_registry_entry | duplicate_type_without_disposition
```

### 6.3 Finding event / record / view (replaces the single mutable finding) — architect-gated

**Verified** FD §3.3 authority enum (use verbatim; do not fork):

```ts
type EvaluationAuthorityBasis =
  | "deterministic_check" | "source_reference" | "tool_verification"
  | "rubric_criterion" | "user_instruction" | "saved_criteria"
  | "human_label" | "multi_reviewer_consensus" | "model_judgment_only";   // FD §3.3 — VERIFIED

type FindingKind =
  | "criterion_failed" | "missing_requirement" | "unsupported_assertion" | "source_mismatch"
  | "format_violation" | "style_violation" | "incomplete_coverage" | "research_gap"
  | "subjective_quality_issue" | "tool_verified_failure" | "process_observation" | "custom";  // = FD §3.3 set

interface BlockingAuthorityEvaluation {
  satisfied: boolean;
  basis: EvaluationAuthorityBasis[];                  // REUSE the canonical enum (NOT a separate BlockingAuthorityBasis)
  subjective_blocking_permission: "not_allowed" | "allowed_by_outcome_definition"
                                | "allowed_by_user_instruction" | "allowed_by_human_review";
  evaluated_policy_ref?: PolicyEvaluationRef; explanation: string; schema_version: "1.0";
}
const BLOCKING_BASES: EvaluationAuthorityBasis[] =
  ["deterministic_check","source_reference","tool_verification","user_instruction","saved_criteria"];
// satisfied = (severity !== "blocking") || basis.some(b => BLOCKING_BASES.includes(b));
//   model_judgment_only blocks ONLY when subjective_blocking_permission != "not_allowed".

interface EvaluationFindingEvent {              // immutable: what was emitted
  finding_event_id: string; finding_id: string; result_id: string;
  producer_kind: ProducerKind; producer_module_id: string; producer_activation_seq: number;
  finding_kind: FindingKind; finding_text: string; explanation: string;
  severity: "low"|"medium"|"high"|"blocking"; emitted_state: "proposed"|"active";
  assurance_basis: AssuranceBasis[]; authority_basis: EvaluationAuthorityBasis[];   // BOTH axes
  blocking_authority: BlockingAuthorityEvaluation;
  confidence_score: number; confidence_basis: ConfidenceBasis[]; confidence_explanation: string;
  target_artifact_ref?: StorageRef; target_artifact_version_ref?: StorageRef;
  target_scope_ref?: ArtifactScopeRef; target_criterion_id?: string; affected_claim_refs: ClaimRef[];
  evidence_refs: StorageRef[]; verification_record_refs: StorageRef[]; supporting_material_snapshot_refs: StorageRef[];
  based_on_artifact_version_ref?: StorageRef;
  based_on_artifact_version_absent_reason?: "non_artifact_target"|"human_review_no_artifact"|"process_observation";
  based_on_source_workspace_snapshot_ref?: StorageRef; based_on_board_digest_ref?: StorageRef;
  evaluation_snapshot_ref: StorageRef; match_key: FindingMatchKey;
  governance: GovernanceEnvelope;
  created_at: ISO8601; schema_version: "2.0"; migration_version: number;
}
interface EvaluationFindingRecord {             // mutable: current lifecycle state (EC-written)
  finding_id: string; canonical_event_ref: StorageRef;
  current_state: FindingState; current_severity: "low"|"medium"|"high"|"blocking";
  lifecycle_transition_refs: StorageRef[];      // §5.7.1 table re-expressed here; ADD proposed→dismissed (A-19)
  superseded_by_finding_id?: string; expires_at?: ISO8601;
  last_validated_against_artifact_version_ref?: StorageRef;
  last_validated_against_source_workspace_snapshot_ref?: StorageRef;
  governance: GovernanceEnvelope; updated_at: ISO8601; schema_version: "1.0";
}
interface FeedbackFindingView {                 // projection to UI/forum/delivery
  finding_id: string; source_finding_event_ref: StorageRef; current_finding_record_ref: StorageRef;
  display_summary: string; display_explanation: string;
  finding_kind: FindingKind; severity: "low"|"medium"|"high"|"blocking"; lifecycle_state: FindingState;
  blocking_authority_satisfied: boolean; blocking_authority_basis: EvaluationAuthorityBasis[];
  routed_action_refs: StorageRef[];
  governance: GovernanceEnvelope;               // MANDATORY passthrough, copied from source (never recomputed)
  schema_version: "1.1";
}
// Unified FindingState = the 12 V3.3.1 §5.7 values; FD's 7-value lifecycle maps onto it (no new states).
// Migration v1→v2.0 populates BOTH event and record: basis→[basis]; confidence low|med|high→0.3|0.6|0.9;
//   finding_kind←classify(finding_text) default "custom"; authority_basis←[].
// validation.blocking_finding_without_authority | view_drops_governance_fields | finding_v1_unmigrated
//   | feedback_finding_view_authority_drift | blocking_authority_basis_enum_forked
```

### 6.4 FindingMatchKey + RevisorTerminationLedger (single loop-identity + single accounting)

```ts
interface FindingMatchKey {
  failure_kind: FailureKind;                    // REUSE §6.2 FailureKind
  stable_artifact_id?: string;                  // stable id, NOT a versioned ArtifactScopeRef
  target_section_path?: string;                 // version-independent section/anchor
  finding_summary_hash: string; normalized_finding_text_hash: string;
  criterion_id?: string; evidence_signature_hash?: string; schema_version: "1.0";
}
type SufficiencyTrigger =
  | "no_capability_covers_outcome" | "capability_unavailable_or_unhealthy"
  | "policy_prohibits_required_step" | "all_policy_allowed_procedures_exhausted"
  | "max_attempts_without_material_score_improvement" | "identical_output_loop_detected"
  | "evidence_insufficient_to_proceed" | "verification_unresolvable"
  | "contradictory_requirements" | "precondition_unresolvable"
  | "budget_cap_prevents_minimal_sufficient_attempt"
  | "external_side_effect_requires_ungranted_approval" | "cascade_cycle_detected";
type SufficiencyTerminalRoute =
  | "needs_information" | "needs_verification" | "needs_human_judgment"
  | "unable_to_evaluate" | "blocked_by_policy" | "unrecoverable" | "process_gap_out";
interface SufficiencyDetectionPolicy {
  policy_id: string; min_attempts_before_no_improvement: number; no_improvement_window: number;
  improvement_metric_ref: string; epsilon: number; max_total_attempts: number;
  consecutive_insufficient_limit: number;       // mirrors §6.7.3
  procedure_universe_scope: "declared_applicable"|"policy_allowed_only"|"safe_without_human_gate"|"all_known_with_policy_labels";
  require_capability_snapshot: true; require_policy_snapshot: true; require_attempt_signature_hash: true;
  schema_version: "1.0";
}
interface CapabilityCoverageAssessment {        // makes "no_capability_covers" decidable
  assessment_id: string; outcome_id: string; capability_snapshot_ref: StorageRef;
  required_capabilities: CapabilityRef[]; available_capabilities: CapabilityRef[];
  coverage_state: "covered"|"partially_covered"|"not_covered"|"covered_but_unhealthy";
  gaps: Array<{ required_capability_ref: CapabilityRef; gap_kind: "missing"|"unhealthy"|"policy_blocked"|"version_incompatible"; evidence_ref?: StorageRef }>;
  schema_version: "1.0";
}
interface CandidateRepairProcedure {            // makes "all_procedures_exhausted" decidable
  procedure_id: string; strategy_kind: RepairStrategyKind; repair_target: RepairTarget;
  required_capabilities: CapabilityRef[]; policy_allowed: boolean;
  safety_class: "mechanical"|"meaning_bearing"|"privileged"|"external_side_effect";
  tried: boolean; exhausted: boolean;
  inapplicable_reason?: "missing_capability"|"policy_blocked"|"unsafe_without_human"|"already_failed_same_signature"|"requires_missing_evidence"|"requires_ungranted_side_effect";
  schema_version: "1.0";
}
interface SufficiencyDetectionResult {          // THIN: predicate output + refs (no embedded attempt log)
  detection_id: string; outcome_id: string; run_id: string; evaluated_at: ISO8601; policy_ref: string;
  no_sufficient_procedure: boolean; triggered_by: SufficiencyTrigger[];
  termination_ledger_ref: StorageRef;           // accounting lives on the ledger, not here
  coverage_assessment_ref: StorageRef; candidate_procedure_refs: StorageRef[];
  decisive_guard_receipt_refs: StorageRef[];    // refs into B-06/B-08/B-09/B-12/B-27 receipts (observe, don't re-route)
  terminal_route: SufficiencyTerminalRoute; hard_call_required: boolean;
  hard_call_kind?: HardRevisionCallKind | "no_sufficient_procedure" | "contradictory_requirements" | "budget_scope_decision";
  rationale: string; schema_version: "1.0";
}
interface RevisorTerminationLedger {            // SINGLE accounting object for all loop guards
  ledger_id: string; task_id: string; run_id: string; outcome_id: string;
  finding_match_key: FindingMatchKey; originating_finding_id?: string; originating_result_id?: string;
  cascade_chain_id?: string; cascade_depth: number; max_cascade_depth: number;
  attempts: Array<{
    attempt_id: string; attempt_seq: number; procedure_id?: string; strategy_kind?: RepairStrategyKind;
    input_signature_hash: string; output_signature_hash?: string;
    score_before?: CalibratedScore; score_after?: CalibratedScore; score_delta?: number;
    terminal_status: "succeeded"|"failed"|"no_material_improvement"|"policy_blocked"|"capability_failed"|"regressed"|"identical_output_rejected"|"not_attempted_missing_evidence";
    receipt_refs: StorageRef[];
  }>;
  repeated_insufficiency_count: number;         // §6.7.3 — increments on ANY insufficient plan
  still_failing_same_reason_count: number;      // D16 — increments only when FindingMatchKey unchanged
  // INVARIANT: still_failing_same_reason_count <= repeated_insufficiency_count
  previous_output_hashes: string[];
  quiescence_state: "not_started"|"in_progress"|"waiting_dependency"|"waiting_hard_call"|"quiescent"|"terminal_blocked";
  terminal_decision?: "continue"|"replan"|"needs_information"|"needs_verification"|"needs_human_judgment"|"blocked_by_policy"|"process_gap_out"|"unrecoverable"|"max_iterations_reached";
  terminal_decision_ref?: StorageRef; updated_at: ISO8601; schema_version: "1.0";
}
// validation.revisor_attempt_without_termination_ledger | repeated_failure_without_match_key
//   | revisor_loop_guard_counters_disagree (the invariant) | success_marked_before_ledger_quiescent
//   | regenerate_identical_output_not_recorded | sufficiency_result_duplicates_attempt_log
//   | sufficiency_protocol_without_predicate | hard_call_raised_when_no_human_choice_available
//   | sufficiency_retry_after_terminal_detection
```

### 6.5 Formula derivation receipts (scoped)

```ts
interface FormulaSpec {                          // C-01 registry (FULL fields per the math cluster: inputs/output,
  formula_id: string; owner_doc: OwnerDoc; semantic_version: string; purpose: string;
  expression_ref: StorageRef; expression_language: "deterministic_typescript"|"sql_read_model"|"declarative_metric_dsl"|"human_review_required";
  missing_input_policy: "fail_validation"|"return_indeterminate"|"exclude_with_recorded_omission"|"default_value_with_audit"|"block_computation";
  zero_denominator_policy?: "return_indeterminate_insufficient_data"|"return_zero"|"return_one"|"fail_validation";
  rounding_policy: "no_rounding_store_full_precision"|"round_display_only"|"round_to_6_decimal_places";
  sample_policy?: { min_sample_size: number; insufficient_sample_result: "indeterminate"|"emit_with_low_confidence"; window_required: boolean };
  confidence_interval_policy?: { required: boolean; interval_level: 0.8|0.9|0.95|0.99; method: "wilson"|"bootstrap"|"normal_approximation"|"bayesian_beta"|"not_applicable" };
  test_vectors: FormulaTestVector[]; schema_version: "1.0";
}
interface FormulaEvaluationReceipt {
  receipt_id: string; formula_id: string; formula_semantic_version: string; producer_ref: string;
  input_manifest_hash: string; input_value_hash: string; output_ref: StorageRef; output_value_hash: string;
  omitted_input_names: string[]; missing_input_policy_applied?: string; zero_denominator_policy_applied?: string;
  finite_number_check: "passed"|"failed_nan"|"failed_infinity"|"coerced_to_indeterminate";
  validation_codes: string[]; computed_at: ISO8601; schema_version: "1.0";
}
interface MetricObservation { observation_id: string; metric_id: string; formula_eval_receipt_ref: StorageRef; subject_ref: StorageRef; observed_at: ISO8601; value_ref: StorageRef; governance: GovernanceEnvelope; schema_version: "1.0"; }
interface MetricRollup { rollup_id: string; metric_id: string; subject_scope_ref: StorageRef; measurement_window: DateRange; included_observation_refs: StorageRef[]; excluded_observation_refs: Array<{ observation_ref: StorageRef; exclusion_reason: "outside_window"|"wrong_subject_scope"|"right_censored"|"policy_filtered"|"duplicate"|"invalidated" }>; formula_eval_receipt_ref: StorageRef; sample_size: number; value_ref: StorageRef; confidence_interval?: [number,number]; confidence_interval_level?: 0.8|0.9|0.95|0.99; created_at: ISO8601; schema_version: "1.0"; }
// SCOPE: FormulaEvaluationReceipt REQUIRED only when the output is (a) a durable MetricObservation/Rollup,
//   (b) input to a reliance/learning/reputation decision, or (c) surfaced in a §G certification.
//   NOT required for transient in-flight scores within a single evaluation pass.
// validation.durable_metric_without_formula_receipt | metric_value_without_formula_receipt
//   | formula_output_nan_or_infinity | formula_test_vector_missing | formula_version_drift
```

### 6.6 NoVerdictReason (deduped, label-faithful) + registry

```ts
type NoVerdictReason =
  // §5.4.2 canonical labels (VERIFIED — keep exact spelling):
  | "insufficient_evidence" | "human_judgment_needed" | "missing_capability"
  | "source_unavailable" | "policy_blocked" | "stale_evidence" | "unable_to_ground_claim"
  // genuinely new from Addenda-A R203 (ONLY those not covered above — VERIFY against R203 before finalizing):
  | "conflicting_evidence" | "tool_failure" | "timeout"
  | "unsupported_scope" | "blocked_before_substantive_verdict";
// Aliases handled by the registry, NOT added as members:
//   missing_source→source_unavailable ; stale_source→stale_evidence ; missing_information→insufficient_evidence ;
//   policy_block→policy_blocked ; human_judgment_required→human_judgment_needed
interface NoVerdictReasonRegistryEntry {
  reason: NoVerdictReason;
  canonical_owner: "AddendaA_R203_IndeterminateCause" | "DOC23_AddendaB_V3_3_1_EvaluationLimitationKind" | "CommonContracts_Alias";
  aliases: string[]; default_outcome_disposition: OutcomeEvaluationDisposition;
  default_recovery_route: "needs_information"|"needs_verification"|"needs_human_judgment"|"blocked_by_policy"|"unable_to_evaluate"|"unrecoverable";
  schema_version: "1.0";
}
// ARCHITECT DECISION: relocating these into one Common-Contracts vocabulary changes ownership of an
//   Addenda-A-owned taxonomy; requires sign-off + reconciliation against the actual R203 member list.
// validation.no_verdict_reason_label_drift | no_verdict_reason_duplicate_concept | no_verdict_reason_unmapped
//   | indeterminate_cause_redeclared_outside_owner | evaluation_limitation_kind_redeclared_outside_owner
//   | limitation_value_used_as_outcome_state
```

### 6.7 Read-model invalidation + D-01 trust basis

```ts
interface DerivedReadModelRecord {
  read_model_id: string;
  read_model_kind: "TaskReliancePacket"|"TaskHealthCard"|"FindingsInbox"|"WorkProductCertification"|"RunDiff"|"DecisionAuditView"|"EvidencePackage"|"EvaluationChainView";
  input_manifest_ref: StorageRef; derivation_policy_ref: StorageRef; formula_eval_receipt_refs: StorageRef[];
  valid_from_event_seq: number; valid_until_event_seq?: number; invalidated_by_event_ref?: StorageRef;
  governance: GovernanceEnvelope; schema_version: "1.0";
}
interface ReadModelInvalidationSpec {
  producer_event_kind: string; invalidates_read_models: DerivedReadModelRecord["read_model_kind"][];
  invalidation_scope: "same_run"|"same_task"|"same_matter"|"specific_refs"; target_refs?: StorageRef[]; schema_version: "1.0";
}
// validation.read_model_without_input_manifest | lifecycle_event_without_read_model_invalidation
//   | context_packet_valid_after_invalidation_event | reliance_packet_valid_after_source_change

// D-01 trust basis (reconciled with SW §4.1 Retrieval lineage — DERIVE from existing fields, don't add a parallel axis):
type SourceTrustBasis = "user_supplied"|"internal_library"|"official_api"|"verified_authority_database"|"court_record"
  |"regulator_record"|"issuer_filing_system"|"authenticated_connector"|"web_unverified"|"party_submitted"
  |"expert_authored_unverified"|"vendor_documentation"|"manual_override_policy"|"unknown";
interface SourceKindTaintDefault {
  source_kind: SourceRecord["source_kind"]; default_taint_class: TaintClass;
  required_trust_basis?: SourceTrustBasis[]; allow_override: boolean; override_requires_policy_decision: boolean; schema_version: "1.0";
}
// Conservative defaults (the 15 kinds): document/email/file/prior_task_output → user_trusted_bounded;
//   library_entry → internal_corpus_trusted; web_source → external_untrusted; custom → unclassified (override required);
//   api_result/database_record/case_law/statute/regulation/financial_filing → external_authority_trusted WITH required_trust_basis;
//   expert_report → user_trusted_bounded (party_submitted/expert_authored_unverified); technical_doc → external_untrusted.
// validation.source_kind_taint_unmapped | external_authority_without_trust_basis | custom_source_without_taint_override
//   | taint_override_without_policy_decision | taint_not_inherited_through_summary | source_trust_basis_duplicates_retrieval_lineage
```

### 6.8 LintRegistry (tiering + fixtures)

```ts
interface LintRegistryEntry { lint_id: string; severity: "error"|"warning"|"advisory"; owner_doc: OwnerDoc; fixture_refs: StorageRef[]; schema_version: "1.0"; }
// Every validation.* id above must have a LintRegistryEntry with ≥1 fixture, or it is unenforced.
// validation.lint_without_fixture (meta-lint)
```

------

## 7. Assessment of ChatGPT's pass (what moved my view, what I pushed back on)

ChatGPT reviewed this analysis. Its central reframe (the two-layer amendment) is correct and is folded into §1. Below: where it changed my view, and where its additions re-commit the patterns this review is removing — with verified corrections (already applied in §6).

**Where ChatGPT improved on my earlier position (adopted):**

- **D-01 trust basis.** It correctly flagged my `expert_report|technical_doc → external_authority_trusted` as too trusting for litigation. Adopted via §6.7 (`SourceTrustBasis`, conservative defaults), with the added requirement that it reconcile with SW's existing Retrieval lineage rather than add a parallel axis.
- **Finding event/record split.** Better than my single-schema fix; adopted in §6.3 (architect-gated). It naturally satisfies A-19 and matches the EC-sole-writer model.
- **Read-model invalidation** (`DerivedReadModelRecord` + `ReadModelInvalidationSpec`), **reliance-decay** and **delegation** as rows, **promotion of the coverage exceptions to rows**, and the **two-layer staging** — all adopted (§6.7, §10, §5, §1).

**Where I push back — verified, with corrections in §6:**

- **(a) [CHATGPT FORK] `EvaluationAuthorityBasis` was redefined incorrectly.** ChatGPT's version drops `human_label`/`multi_reviewer_consensus`/`model_judgment_only` and invents `human_review`/`policy_rule`/`other`. The live FD §3.3 enum (verified) is the 9 values in §6.3 — use it verbatim. Same class of error as the A-11 fork.
- **(b) Duplicate enum `BlockingAuthorityBasis`.** It's `EvaluationAuthorityBasis` minus `model_judgment_only` plus `subjective_blocking_allowed` — a near-duplicate, and `subjective_blocking_allowed` duplicates ChatGPT's own `subjective_blocking_permission` field. Keep the typed `BlockingAuthorityEvaluation` object (a boolean isn't auditable enough — a fair improvement) but reuse the canonical enum (§6.3).
- **(c) `NoVerdictReason` doesn't actually collapse the redundancy.** It carries label drift vs the verified §5.4.2 (`policy_block`≠`policy_blocked`, `human_judgment_required`≠`human_judgment_needed`, `missing_information`≠`insufficient_evidence`) and keeps internal dupes (`missing_source`+`source_unavailable`, `stale_source`+`stale_evidence`). Corrected to a deduped, label-faithful enum + alias registry (§6.6), with the R203 reconciliation flagged as an architect decision.
- **(d) Duplicate accounting store.** ChatGPT proposes both `SufficiencyDetectionResult.attempts` and `RevisorTerminationLedger.attempts`. One home: the ledger. The detector is thinned to predicate-output + refs (§6.4).
- **(e) Two ledger counters without an invariant.** Keep both `repeated_insufficiency_count` and `still_failing_same_reason_count` but define `still_failing_same_reason_count ≤ repeated_insufficiency_count` (§6.4), or the ledger re-creates the disagreeing-counters problem it exists to prevent.
- **(f) Universal formula receipts → unbounded hot path.** Scope receipts to durable/reliance/learning metrics (§6.5).
- **(g) `SourceTrustBasis` likely duplicates SW's existing Retrieval lineage (§4.1, verified present).** Derive trust from / unify with the existing fields, don't add a parallel enum (§6.7).
- **(h) `estimated_lock_duration_ms` is unestimable a priori.** Use `revision_cost_total_tokens` (already computed) in the B-16 tiebreaker (§4-B16). I do accept ChatGPT's configurable tiebreaker (I withdraw "drop risk entirely").
- **(i) Lint proliferation / object admission.** Tier every lint (`error|warning|advisory`) and map it to a fixture (§6.8); admit a new object only if it has producer + consumer + durable artifact + owner. This is **Step 0** (§1) and applies to ChatGPT's own additions first.

**Net:** I agree with ~80% of ChatGPT's pass, including two genuine improvements on my work. The disagreements are surgical — specific enum forks, duplicate enums/stores, and scoping — and they reduce to a single discipline: the structural layer ChatGPT proposes must pass its *own* type-owner/strip pass before it's written. The irony worth stating plainly: ChatGPT proposes the TypeOwnerRegistry and phantom-field lint and then violates both in its new schemas, which is exactly why Step 0 exists.

------

## 8. §G — Professional Reliance Layer (keep; harden as a derived/read-model layer)

The layer is coherent and implementable and is the deliberate 2027/2028 differentiator — keep all of it. It must be built as derived read-models (§6.7) over the canonical truth, with explicit derivation, invalidation, degraded modes, and the standard surface contract. Key hardenings:

- **G-01 `EvaluationContractReview`** — replace `criteria_summary: string[]` with typed projections of `EvaluationOutcomeDefinition.criteria`, so the pre-flight check can't drift from what is actually evaluated.

```ts
interface EvaluationContractReviewCriterionProjection {
  criterion_ref: StorageRef; criterion_id: string; criterion_label: string;
  required: boolean; weight?: number; threshold_summary?: string; scoring_basis?: string;
  user_visible_summary: string; schema_version: "1.0";
}
interface EvaluationContractReview {
  review_id: string; task_id: string; run_id?: string;
  compiled_plan_ref: StorageRef; interpreted_goal: string;
  criterion_projections: EvaluationContractReviewCriterionProjection[]; threshold_summary: string[];
  source_requirements: string[]; required_capabilities: CapabilityRef[]; hard_call_triggers: HardRevisionCallKind[];
  material_differences_from_preview?: string[];
  user_approval_required: boolean;
  approval_status: "pending" | "approved" | "rejected" | "edited" | "waived_by_policy"; approval_ref?: StorageRef;
  governance: GovernanceEnvelope; created_at: ISO8601; schema_version: "1.1";
}
// validation.evaluation_contract_review_criterion_projection_drift
```

- **G-02 `RevisionReviewPacket`** — key `finding_to_change_map` on canonical `finding_id`, reference `RevisionPlanStep.step_id`s, give `semantic_diff_ref` a declared kind, and record decisions as a separate receipt (the packet carries no current action).

```ts
type SemanticDiffArtifactKind = "text_semantic_diff" | "structured_artifact_diff" | "source_citation_diff" | "format_only_diff" | "multi_artifact_diff";
interface SemanticDiffArtifact {
  diff_id: string; diff_kind: SemanticDiffArtifactKind;
  before_artifact_version_ref: StorageRef; after_candidate_artifact_version_ref: StorageRef;
  changed_scope_refs: ArtifactScopeRef[]; summary: string;
  machine_readable_diff_ref?: StorageRef; user_visible_diff_ref: StorageRef; schema_version: "1.0";
}
interface RevisionReviewFindingChangeMapEntry {
  finding_id: string; finding_event_ref: StorageRef; revision_plan_step_ids: string[]; changed_scope_refs: ArtifactScopeRef[];
  resolution_claim: "fully_resolves" | "partially_resolves" | "does_not_resolve" | "introduces_tradeoff"; explanation: string; schema_version: "1.0";
}
interface RevisionReviewPacket {
  packet_id: string; task_id: string; run_id: string; revision_plan_ref: StorageRef;
  before_artifact_version_ref: StorageRef; candidate_artifact_version_ref: StorageRef; semantic_diff_ref: StorageRef;
  finding_to_change_map: RevisionReviewFindingChangeMapEntry[];
  preservation_constraint_result_refs: StorageRef[]; source_changes: SourceRecordRef[]; revalidation_result_refs: StorageRef[];
  regression_risk_summary: string;
  lifecycle_state: "generated" | "review_pending" | "accepted" | "rejected" | "forked" | "changes_requested" | "restored_known_good" | "superseded";
  governance: GovernanceEnvelope; created_at: ISO8601; schema_version: "1.1";
}
interface RevisionReviewDecisionReceipt {
  receipt_id: string; packet_id: string;
  action: "accept" | "reject" | "fork" | "request_changes" | "restore_known_good_state" | "no_user_review_required";
  actor_ref: string; rationale?: string; resulting_candidate_state?: ArtifactVersionState; command_ref?: string;
  created_at: ISO8601; schema_version: "1.0";
}
// validation.revision_review_packet_contains_current_action | review_decision_without_receipt
//   | revision_review_change_map_missing_finding_id | semantic_diff_artifact_kind_unregistered
```

- **G-03 `EvidencePackage`** — `claim_support_map` depends on the **Addenda-A-owned** claim extractor; declare the degraded mode.

```ts
type ClaimSupportStatus = "supported" | "partially_supported" | "unsupported" | "contradicted" | "not_checked" | "indeterminate_stale_or_unverified";
interface EvidencePackageClaimEntry {
  claim_ref: ClaimRef; supporting_anchor_refs: StorageRef[]; contradicting_anchor_refs: StorageRef[];
  support_status: ClaimSupportStatus; support_derivation_receipt_ref?: StorageRef;
  not_checked_reason?: "claim_extractor_unavailable" | "evidence_anchor_unavailable" | "policy_filtered" | "outside_scope"; schema_version: "1.0";
}
interface EvidencePackage {
  evidence_package_id: string; task_id: string; run_id: string;
  final_artifact_refs: StorageRef[]; source_workspace_snapshot_ref: StorageRef;
  source_record_refs: SourceRecordRef[]; evidence_anchor_refs: StorageRef[]; claim_support_map: EvidencePackageClaimEntry[];
  unresolved_research_need_refs: string[]; stale_or_unverified_source_refs: SourceRecordRef[];
  extractor_status: "available" | "unavailable_all_claims_not_checked" | "partial";
  governance: GovernanceEnvelope; created_at: ISO8601; schema_version: "1.1";
}
// validation.evidence_package_claim_support_underived | claim_extractor_absent_without_not_checked_status | evidence_package_without_workspace_snapshot
```

- **G-06 `TaskReliancePacket`** — give `reliance_status` an explicit derivation rule and an input manifest, and make it invalidatable:

```ts
type RelianceStatus = "safe_to_rely_within_scope"|"rely_with_limitations"|"not_safe_to_rely"|"human_review_required";
// unresolved_limitations: NoVerdictReason[] | RelianceLimitationKind[]  (reuse §6.6, NOT a local enum)
RULE task_reliance_status_derivation:
  IF pending_hard_call_refs.length > 0:                                   status = "human_review_required"
  ELSE IF open_blocking_finding_refs.length > 0:                          status = "not_safe_to_rely"
  ELSE IF unresolved_limitations ∩ {policy_blocked, unable_to_ground_claim, contradicted,
        evidence_package_missing, external_side_effect_unverified, pattern_c_chain_unresolved} ≠ ∅:
                                                                          status = "not_safe_to_rely"
  ELSE IF unresolved_limitations.length > 0:                              status = "rely_with_limitations"
  ELSE:                                                                   status = "safe_to_rely_within_scope"
// TaskReliancePacket is a DerivedReadModelRecord (§6.7): invalidated by source change / finding lifecycle / artifact version.
// validation.reliance_status_underived | reliance_packet_without_input_manifest | reliance_packet_valid_after_source_change
```

- All read-only DOC20 surfaces (G-12/13/15/20) need the standard surface contract (loading/empty/degraded/error/command/telemetry/read-model/safe-label/Inspector), even asserting "no new truth."

------

## 9. Cut / keep

**Drop or downgrade (effort/risk without payoff, or net-negative as written):**

- **A-11 → DECLINE** (enum exists; proposed value wrong).
- **B-25 → DECLINE** the schema add (field exists; proposed base destructive); keep only the B-26 rename via B-25R.
- **B-15 → DECLINE** the registry add (wrong owner); keep the DOC12 OP-A obligation + `ExternalRoomKindDependency` (§10).
- **D-04 "remove tier 0" → DECLINE** that sub-fix; keep tier 0 as receipt-only.
- **A-07 duplicate enums → DECLINE** new parallel enums; reconcile owner-owned taxonomy (§6.6).
- **From the ChatGPT pass:** `BlockingAuthorityBasis` (use canonical), the forked `EvaluationAuthorityBasis` (use FD §3.3), the duplicated `SufficiencyDetectionResult.attempts`, the un-scoped universal formula receipts, the parallel `SourceTrustBasis` axis, `estimated_lock_duration_ms`.

**Keep:** the entire §G layer; all sound rows in §4; and the load-bearing structural objects (§6).

**Add (Layer 1 + new rows):** `GovernanceEnvelope`, exhaustive `TypeOwnerRegistry`, phantom-field lint, finding event/record/view, `FindingMatchKey` + `RevisorTerminationLedger`, scoped formula receipts, read-model invalidation, `LintRegistry`; and the §10 product/coverage rows.

------

## 10. New rows (product + coverage)

Full interfaces; all carry `GovernanceEnvelope` where they hold or project governed data. The three structural rows (X-01, ledger, lint/registry) are defined in §6 and only referenced here.

- **X-01 Universal governance envelope + projection invariant** — `GovernanceEnvelope` + `GovernedObjectRegistryEntry`, §6.1.
- **RevisorTerminationLedger** — §6.4. **Phantom-field lint / exhaustive TypeOwnerRegistry** — §6.2.
- **`ExternalRoomKindDependency`** (B-15 — cross-doc closure instead of a local registry entry):

```ts
interface ExternalRoomKindDependency {
  room_kind: "plan_review"; owner_doc: "DOC12"; owner_obligation_ref: "OBL-DOC12-FORUM-01";
  consumed_by: "DOC23_AddendaB_TaskForum"; required_for_features: Array<"plan_review_room" | "high_stakes_plan_review_gate">;
  local_fallback: "block_plan_review_feature" | "degrade_to_user_hard_call" | "degrade_to_task_agent_advisory_only";
  schema_version: "1.0";
}
// validation.external_room_kind_dependency_unresolved | local_room_kind_redeclares_doc12_owned_kind
```

- **Reliance-decay monitoring** (the litigation-grade payoff of source-change detection §5.16 + reliance packets):

```ts
type RelianceDecayTriggerKind = "source_overruled" | "source_amended" | "source_superseded" | "source_verification_failed"
  | "source_freshness_expired" | "policy_decision_superseded" | "finding_lifecycle_changed" | "artifact_version_changed";
interface RelianceDecayMonitorPolicy {
  policy_id: string; monitored_source_kinds: SourceRecord["source_kind"][]; monitored_reliance_statuses: RelianceStatus[];
  trigger_kinds: RelianceDecayTriggerKind[];
  default_action: "flag_attention_ledger" | "invalidate_reliance_packet" | "require_recheck_before_reuse" | "silent_audit_only";
  notification_threshold: "any_degradation" | "safe_to_limited_or_worse" | "safe_to_not_safe" | "human_review_required"; schema_version: "1.0";
}
interface RelianceDecayEvent {
  event_id: string; task_id: string; run_id?: string; trigger_kind: RelianceDecayTriggerKind; triggering_ref: StorageRef;
  affected_reliance_packet_refs: StorageRef[]; prior_status: RelianceStatus; new_status: RelianceStatus;
  decay_reason: string; attention_ledger_item_ref?: StorageRef; created_at: ISO8601; schema_version: "1.0";
}
// validation.source_change_without_reliance_decay_check | reliance_packet_reused_after_decay_without_recheck
```

- **Delegation envelope** (scoped, revocable authorization for autonomous runs — composes EvaluationContractReview + AutonomousModePolicy + BudgetNarrative + AttentionLedger):

```ts
interface DelegationEnvelope {
  delegation_id: string; task_id?: string; run_id?: string; matter_id?: string;
  scope: "single_run" | "task" | "matter" | "template" | "timeboxed_batch";
  authorized_by_user_ref: string; authorized_at: ISO8601; expires_at?: ISO8601;
  evaluation_contract_review_ref: StorageRef; autonomous_mode_policy_ref: StorageRef;
  budget_cap_ref?: StorageRef; allowed_cost_vector_ref?: StorageRef;
  permitted_actions: Array<"evaluate" | "revise_candidate" | "source_research" | "forum_assistance" | "generate_evidence_package" | "prepare_but_not_send_external_effect">;
  prohibited_actions: Array<"external_message_send" | "filing_or_submission" | "memory_promotion" | "library_promotion" | "privileged_export">;
  escalation_triggers: Array<"hard_call" | "budget_threshold_hit" | "source_conflict" | "policy_block" | "external_side_effect_required" | "reliance_status_not_safe" | "unrecoverable_error">;
  revocation_status: "active" | "revoked" | "expired" | "superseded"; revoked_by_user_ref?: string; revoked_at?: ISO8601;
  governance: GovernanceEnvelope; schema_version: "1.0";
}
// validation.autonomous_action_without_delegation_envelope | delegation_envelope_budget_missing_for_costly_run
//   | delegation_envelope_allows_irreversible_action_without_explicit_permission | delegation_envelope_expired_but_active
```

- **D19 Task-agent forum-surface ownership** (the orphaned coverage finding):

```ts
interface TaskAgentForumSurfaceOwnership {
  surface_id: string; surface_kind: "task_forum_room" | "run_board_thread" | "module_assistance_room" | "task_agent_advisory_panel";
  canonical_owner_doc: OwnerDoc; participant_model_ref: StorageRef; post_model_ref: StorageRef;
  task_agent_role: "participant" | "moderator" | "advisory_panel" | "not_allowed";
  may_create_rooms: boolean; may_post_to_run_board: boolean; may_mutate_task_graph: false; schema_version: "1.0";
}
// validation.task_agent_forum_surface_duplicate_without_owner | task_agent_forum_surface_allows_graph_mutation
```

- **D20 Task/matter-scoped forum** (must inherit the D-24 matter firewall):

```ts
interface ForumScopePolicy {
  room_id: string; forum_scope: "run" | "task" | "matter" | "template";
  task_id?: string; run_id?: string; matter_id?: string; template_id?: string;
  persistence_policy: "run_lifetime" | "task_lifetime" | "matter_lifetime" | "template_lifetime";
  cross_run_visibility: "none" | "same_task_only" | "same_matter_only";
  governance: GovernanceEnvelope; schema_version: "1.0";
}
// validation.task_scoped_forum_without_scope_policy | run_forum_used_for_cross_run_task_memory | forum_scope_matter_mismatch
```

- **Grok §3.3 Feedback→prompt responsibility matrix** (B-17 fixes only port typing; this owns the end-to-end contract):

```ts
interface FeedbackToPromptResponsibilityMatrixRow {
  stage: "feedback_production" | "feedback_routing" | "feedback_dispatch" | "consumption_receipt"
       | "doc24_context_selection" | "doc15_prompt_rendering" | "module_prompt_consumption";
  owning_doc: OwnerDoc; owning_component: string; input_type_refs: string[]; output_type_refs: string[];
  required_receipt_or_event_type?: string;
  governance_preserved: boolean; taint_checked: boolean;
  empty_state_behavior: string; degraded_state_behavior: string; error_state_behavior: string; schema_version: "1.0";
}
// validation.feedback_to_prompt_stage_unowned | feedback_to_prompt_governance_lost | feedback_to_prompt_missing_receipt
```

- **Grok §5.7 Sub-agent metric observation** (state whether it ships now or defers vs E-06):

```ts
interface SubAgentAdviceMetricObservation {
  observation_id: string; sub_agent_ref: SubAgentRef; coordination_point: AllowedCoordinationPoint;
  advice_ref: StorageRef; accepted: boolean; outcome_delta?: CalibratedScore; attribution_lift?: number;
  regression_introduced: boolean; regression_severity?: "minor" | "major" | "critical"; false_positive?: boolean; false_negative?: boolean;
  cost_vector_ref?: StorageRef; formula_eval_receipt_refs: StorageRef[]; governance: GovernanceEnvelope; created_at: ISO8601; schema_version: "1.0";
}
// validation.sub_agent_metric_named_without_observation_schema | sub_agent_advice_regression_without_severity
```

- **Grok §5.9 BoardDigest ResearchNeed import** (+ TypeOwnerRegistry entry `ResearchNeed`→SW §6):

```ts
interface BoardDigestResearchNeedRef {
  research_need_ref: StorageRef;          // Source Workspace §6 ResearchNeed
  source_workspace_ref: string; need_status_at_digest_time: "open" | "leased" | "human_needed" | "answered" | "unresolved";
  included_reason: string; schema_version: "1.0";
}
// validation.board_digest_research_need_ref_without_source_workspace_import
```

------

## 11. Answers to the three original specific questions (final)

**(1) A-01 unification — does it work?** Yes — unify, via the event/record/view model (§6.3). It breaks a consumer as the card wrote it: collapsing `authority_basis` into `assurance_basis` loses the `user_instruction`/`saved_criteria` blockers. Keep both arrays (verified FD enum), carry `GovernanceEnvelope` on all three objects, and specify the v1→v2.0 migration. Separate schemas under one name is the worse outcome.

**(2) §G — does it work / where buggy?** Coherent and implementable; keep all of it. Build it as derived read-models (§6.7) with explicit `reliance_status` derivation (§8), typed criteria projections (G-01), typed diff + receipts (G-02), and declared degraded modes (G-03). The work is derivation/invalidation/surface-contracts, not removal.

**(3) B-24 — sound?** The trigger set must be richer than my original four (the additional triggers map to real spec states), but the detector must be **thin** (accounting on the single `RevisorTerminationLedger`, §6.4), must **feed** §6.7.3 rather than replace it, must add `needs_verification` to the route, must raise a Hard Call **only after** the §6.7.3 threshold, and must **observe** the existing typed guards (B-06/B-08/B-09/B-12/B-27) rather than re-route them.

------

## 12. Open items / next steps

1. **R0.4 package**, staged per §1 (Step 0 strip pass → Layer 1 structural → Layer 2 flips → Layer 3 critical → Layer 4 §G).
2. **Architect decisions required:** the finding event/record split (§6.3); the `NoVerdictReason` ownership relocation + R203 reconciliation (§6.6); elevating A-02/D-13.
3. **Not verifiable from the DOC23 set (confirm before finalizing):** the Addenda-A R203 `IndeterminateCause` member list (§6.6); the exact SW §4.1 Retrieval-lineage field names (§6.7-D01); the SW §4.1 region lines 296-314.
4. **Coverage:** adjudicate Claude D19/D20 and Grok §3.3/§5.7/§5.9 (now §10 rows); fix the B-24 citation label.
5. **Not yet done:** a line-level certification of all 126 card items against all 227 raw assertions (this review did section-by-section enumeration + spot-checks + the three failure-point sweeps). Available as a separate appendix if wanted.

------

## Appendix — legend

`ACCEPT` adopt as-is · `ACCEPT W/ MODS` adopt with stated change · `DECLINE` do not apply (covered/wrong) · `⚠verify` resolved in §3. `[CARD BUG]` defect in a proposed fix · `[SPEC BUG]` defect in an operative spec · `[CHATGPT FORK]` defect introduced by the second reviewer's schema. Coverage codes: ✓ covered · M merged · S split · DEF deferred · DEC declined · POS confirmed-positive · ORPH orphan · THIN partial.

*Verified against live operative specs in `wbrody/Elnor-Specs@main`. This document is the final consolidated review and supersedes all prior separate passes for active use.*



------

### Appendix B — Dense coverage crosswalk (paste before the legend appendix)

Every raw reviewer assertion → adjudicated card row. Status: ✓ covered · M merged · S split · DEF deferred-§E · DEC declined-§F · POS confirmed-positive · NOTE folded-note · ORPH orphan · THIN partial · ⚠ covered-but-row-has-a-flagged-defect (see §4).

**Claude (63):** `A1→G-08✓ · A2→G-09✓ · A3→G-10✓ · A4→G-17✓ · A5→G-11✓ · A6→E-08 DEF` `B1→A-01+A-05 S · B2→A-06✓ · B3→A-03✓ · B4→A-08✓ · B5→A-09 M · B6→A-09 M · B7→B-05 M · B8→B-05 M · B9→B-04✓ · B10→D-15 M · B11→B-17✓ · B12→D-09✓` `C1→A-04✓ · C2→A-19✓ · C3→B-18✓ · C4→B-06✓ · C5→A-11⚠DECLINE · C6→A-20✓ · C7→D-17 M · C8→D-01 M · C9→D-11✓ · C10→B-19✓ · C11→D-23✓ · C12→D-24✓ · C13→D-04⚠ · C14→A-24✓ · C15→D-14 M` `D1→D-15 M · D2→B-20✓ · D3→D-10/B-14 M · D4→E-07 DEF · D5→A-15/D-22 M · D6→D-05 M · D7→B-21✓ · D8→A-25✓ · D9→POS@A-16 · D10→POS · D11→G-19✓ · D12→C-09 M · D13→C-01 M · D14→D-17 M · D15→B-13✓ · D16→A-12⚠ · D17→B-22✓ · D18→D-08 M · D19→ORPH(§10) · D20→B-14 THIN(§10) · D21→E-07 DEF · D22→A-15/D-22/E-06 M · D23→A-23⚠ · D24→B-23✓` `S1→G-12✓ · S2→G-13✓ · S3→G-14✓ · S4→G-15✓ · S5→G-16✓ · S6→E-09 DEF`

**ChatGPT (99 main + 15 Audit Addendum + 7 self-learning-2 = 121):** IDEAs(8)→`G-06, G-01, G-02, G-07, G-04, G-03, G-05, G-21` ✓ · CONFIRMED×2→POS Seam (items 11–33)→`A-02⚠, A-03, A-04⚠, A-01⚠, A-05⚠, A-18, A-17, A-16⚠, D-05, A-06, A-06/A-07 M, A-07⚠, A-07⚠, A-07⚠, A-08, A-08, A-21, A-08·AppxF, A-08/D-23, A-14, A-13, A-10, A-22` Runtime (34–49)→`B-02⚠, B-04, B-04, B-05 THIN#37, B-05/B-06, B-07, B-07, B-12, B-08⚠, B-08⚠, B-08⚠, B-08⚠, B-09, B-09, B-10, B-10` Math (50–60)→`C-01, C-01, C-10, C-08, C-09, C-09, C-07, C-06, C-06, C-07, C-01` SW (61–71)→`D-03, D-04⚠, D-04⚠, D-05, D-05, D-04⚠, D-02, D-06, B-13, D-06, D-06` Forum (72–81)→`D-07, D-07, D-09, D-07, D-08, D-08, D-10, D-10, D-10, D-10` Core (82–88)→`D-14, D-14, D-14, A-09/A-15, D-14, D-14/A-15, A-15` Sub-agent (89–91)→`D-15, D-15, E-06 DEF` · Taint (92–93)→`D-01, D-12` · Learning (94)→`E-13 DEF` · Self-learning (95–99)→`E-10 DEF ×5` Audit Addendum (15)→`AA1→B-26 · AA2→A-27 · AA3→A-26⚠ · AA4→A-10 · AA5→B-11 · AA6→D-13 · AA7→D-10 · AA8→D-12 · AA9→B-02⚠ · AA10→B-04 · AA11→B-07 · AA12→C-07 · AA13→D-15 · AA14→D-21 · AA15→D-06` ✓ Self-learning-2 (7)→ all `E-07 / E-10 / E-06` DEF

**Gemini (19):** `F-01→B-03⚠ · F-02→B-14 · F-03→D-01` `D-01→D-13 · D-02→F-04 DEC · D-03→B-06 · D-04→B-27 · D-05→B-03/B-13` Memory(5)→`Hydration→E-01 · Precedence→E-02 · Amnesia(GM-V1)→E-03 · State/Structure→E-04 · Denominator(GM-V2)→E-05` DEF `TaskConfirmationSignal→F-02 DEC` BUGs(5)→`BUG-01→C-02 · BUG-02→C-03 · BUG-03→C-04 · BUG-04→B-16⚠ · BUG-05→C-05` ✓

**Grok (35):** §3(6)→`3.1→NOTE@A-16/G-08 · 3.2→E-11 DEF · 3.3→B-17 THIN(§10) · 3.4→B-05 · 3.5→E-08 DEF · 3.6→G-20/A-03` §4(10)→`4.1→B-01 · 4.2→D-16 · 4.3→D-08 · 4.4→NOTE@A-15 · 4.5→B-02⚠ · 4.6→NOTE@D-23 · 4.7→D-07 · 4.8→A-14 · 4.9→B-24 (card mislabels §4.10) · 4.10→D-20` §5(14)→`5.1→B-25 DECLINE · 5.2→NOTE@A-05 · 5.3→D-01 · 5.4→D-07 · 5.5→D-17 · 5.6→B-01 · 5.7→C-04 THIN(§10) · 5.8→D-13 · 5.9→A-09/D-11 THIN(§10) · 5.10→D-19 · 5.11→D-14 · 5.12→D-18 · 5.13→B-02 · 5.14→B-15 DECLINE` Ideas(5)→`N1→E-11 · N2→F-01/G-17 · N3→G-18 · N4→E-12 · N5→G-20` ✓

**Crosswalk summary:** every raw assertion resolves to a row, a deferral, a decline, a confirmed-positive, or one of the flagged exceptions in §5. The only items that don't land on a clean fix are the ones already enumerated there — `Claude D19` (ORPH), `Claude D20`/`Grok §3.3`/`§5.7`/`§5.9` (THIN, now §10 rows), and the `Grok §4.9`/`§4.10` citation typo.





**Two minor optional adds:** (1) the "resolve the owner *before* accepting an 'X is missing' add" discipline is only implicit (via Step 0 + B-15) — you may want it stated once in §1; (2) the note that ChatGPT's `CG-S#`/`GK-#.#` labels are the card's own normalization, not source labels — a useful footnote for the adjudication.





# ChatGPT

# DOC23 Addenda B — Final Consolidated Red-Team Response, Reconciliation, and Spec-Inclusion Package

**Status:** final consolidated handoff for the DOC23 Addenda B adjudication-card review round.  
**Target family:** DOC23 Addenda B: Core R0.7.1; Outcome Evaluator/Revisor V3.3.1; Evaluation Common Contracts V1.1.1; Source Workspace V1.0.1; Task Forum + Run Board V1.0.1; Feedback Delivery V1.0.1; plus base DOC23 R3.1/R3.1.1 as applicable.  
**Purpose:** provide a single self-contained document containing the final recommendations, corrected dispositions, schemas, contracts, lint rules, patch sequencing, math/formula audit, §G Professional Reliance Layer hardening, and answers to the red-team prompt and follow-up issues.

---

## 0. Source pack and scope

This document consolidates the following materials and all follow-up analysis from this red-team round:

1. The original red-team review prompt for `DOC23_ADDENDA_B_RT_ADJUDICATION_CARD_CONSOLIDATED.md`.

2. The adjudication card itself, which deduplicated roughly 228 raw assertions into 126 adjudicated items.

3. The independent Claude review of the adjudication card.

4. Claude's later response critiquing my consolidated analysis and identifying over-additive / duplicate-schema issues.

5. My deeper passes on the card, including the math/formula audit, structural-invariant analysis, and §G reliance-layer review.

6. The existing consolidated report previously produced in this conversation, now superseded where the final Claude reconciliation corrected or narrowed it.

   **This document is intended as the R0.4 handoff package.** It is not merely a review memo. It includes paste-ready TypeScript-style schemas, lint IDs, normative rules, and explicit patch sequencing so a spec-drafting or coding agent does not have to infer the intended contracts.

---

## 1. Executive top-line

The adjudication card is fundamentally worth shipping into the next Addenda B amendment, but it cannot be applied as-is. Several rows are correct as findings but broken as fixes; several accepted rows should flip to declined or be reframed; and the package needs a structural hardening layer before the local row fixes are safe.

The most important change after the follow-up reviews is **subtractive discipline**: do not just add schemas. First run a type-owner / strip pass over the proposed fixes themselves. The hardening package must not create duplicate enums, duplicate attempt stores, orphan provenance axes, or receipts with no consumer.

The five highest-priority corrections are:

1. **A-01 / A-05:** unify `EvaluationFinding`, but preserve both `assurance_basis[]` and the canonical FD `authority_basis[]`. Do not collapse authority into assurance. Use the verified nine-value `EvaluationAuthorityBasis` enum from FD. Cut the duplicate `BlockingAuthorityBasis` enum.

2. **B-24:** define a sufficiency detector, but make it a thin predicate/diagnostic object that references the single `RevisorTerminationLedger`. All attempt accounting lives on the ledger. The detector aggregates guard receipts; it does not re-decide guard outcomes or embed a second attempt log.

3. **C math cluster:** a `FormulaRegistry` is necessary but not sufficient. Durable metrics, reliance scores, learning/reputation inputs, and user-facing certifications need scoped `FormulaEvaluationReceipt`s, `MetricObservation`s, and `MetricRollup`s. Transient in-flight arithmetic should not emit unbounded hot-path receipts.

4. **D-01 / Source Workspace:** derive source authority and taint from existing retrieval-lineage/provenance fields. Do not add an orphan `SourceTrustBasis` axis. Use conservative defaults for `expert_report` and `technical_doc`.

5. **§G Professional Reliance Layer:** keep the entire layer, but make every status a derived/read-model status with input manifests, derivation policies, invalidation rules, degraded modes, and command/surface registrations. §G must not create a second truth store.

   The single most likely failure mode if the amendment is applied naively is **derived truth becoming stored truth**: `passed`, `support_status`, `reliance_status`, `task_health_status`, sub-agent reputation, source authority, and review status all look like simple fields, but they must be derivable from receipts, snapshots, formulas, and lifecycle events.

---

## 2. Final R0.4 amendment staging

Apply the changes in this order. Do not implement §G surfaces before the structural layer and derivation layer exist.

```text
Step 0 — Structural strip/admission gate
  - Run TypeOwnerRegistry and duplicate-type checks on every proposed new object.
  - Reject forked enums and duplicate stores.
  - Require owner, producer, consumer, durable-artifact class, lint severity, and fixtures.

Layer 1 — Canonical structural primitives
  - GovernanceEnvelope.
  - TypeOwnerRegistryEntry.
  - SchemaReferenceValidationRule / phantom-field lint.
  - SpecObjectAdmissionRegistryEntry.
  - LintRegistryEntry.
  - EvaluationFindingEvent + EvaluationFindingRecord + FeedbackFindingView.
  - FindingMatchKey.
  - RevisorTerminationLedger.
  - Scoped FormulaEvaluationReceipt + MetricObservation + MetricRollup.
  - DerivedReadModelRecord + ReadModelInvalidationSpec.

Layer 2 — Disposition flips and false-positive cleanup
  - A-11: decline as a fix row; LearningMode already exists and value is calibration, not cross_calibration.
  - B-15: decline local Forum registry fix; DOC12 / OP-A owns RoomKind.plan_review.
  - B-25: decline missing-dependency-field row; replace with dependency representation canonicalization.
  - D-04: decline “remove tier 0”; keep tier 0 as receipt-only.

Layer 3 — Critical row fixes
  - A-01/A-05: canonical finding with authority/assurance split.
  - A-02/A-03/A-04: Pattern C envelope fields and chain-resolution receipt.
  - A-06/A-07: state/verdict/no-verdict taxonomy cleanup.
  - A-16/A-17: repair-port closure and Revisor planner boundary.
  - B-03/D-16: Source Workspace operation API and write preconditions.
  - B-24: sufficiency detector + ledger integration.
  - C-03: remove predicted future hashes.
  - D-01/D-24: source/taint governance and matter firewall.

Layer 4 — Professional Reliance and product surfaces
  - §G reliance artifacts as derived/read models.
  - Reliance invalidation and reliance-decay monitoring.
  - DelegationEnvelope.
  - Command registry and surface-state contracts.
  - TaskReplay modes and divergence records.

Layer 5 — Conformance fixtures and OP-A / UI registry updates
  - Math fixtures.
  - Phantom-field fixtures.
  - Taint/matter-leakage fixtures.
  - Source externalization fixtures.
  - B-24 no-sufficient-procedure fixtures.
  - §G degraded/invalidation fixtures.
  - OP-A update and DOC20/DOC21/DOC22 registration work.
```

---

## 3. Master decision table — final changed rows and additions

Rows not listed here remain accepted as in the card, subject to the structural rules in this document.

| ID                  |                      Final view | Final action                                                 |
| ------------------- | ------------------------------: | ------------------------------------------------------------ |
| A-01                | Accept with major modifications | Use event/record/view split; keep `assurance_basis[]` and canonical `authority_basis[]`; add governance passthrough and migration. |
| A-02                |        Accept; elevate critical | Add `evaluated_target` and `evaluation_basis` to `EvaluationResultEnvelope`; make old target fields derived projections. |
| A-03                |       Accept with modifications | Add chain registry and chain lifecycle; include expected producers and status. |
| A-04                |       Accept with modifications | Add `EvaluationChainResolutionReceipt`; do not leave route conflict to vague consumer policy. |
| A-05                |       Accept with modifications | Cut `BlockingAuthorityBasis`; reuse canonical FD `EvaluationAuthorityBasis`; retain `BlockingAuthorityEvaluation`. |
| A-06                |       Accept with modifications | Build one state/disposition matrix; add/normalize `max_iterations_reached`; separate runtime from emitted dispositions. |
| A-07                |       Accept with modifications | Do not mint duplicate enums; reuse B-owned `EvaluationLimitationKind`; alias near-dupes; verify Addenda-A R203 before promoting a Common `NoVerdictReason`. |
| A-08 / B-23         |                           Merge | One `FeedbackRoutingResolutionPolicy` covering routing completeness, multi-fire policy, and idempotency. |
| A-09                |              Accept and elevate | Exhaustive TypeOwnerRegistry sweep, not a few local corrections. |
| A-11                |              Decline as written | Live value set is `production | signal_generation | calibration`; do not add `cross_calibration`. |
| A-12                |       Accept with modifications | Use outcome-level `OutcomeVerdict`, not lane-level `EvaluationVerdict`; `defer` / `request_changes` need not produce a verdict. |
| A-16                |                Accept; critical | Repair mutation only through `revision_in`, revision-compatible ports, or sanctioned `DirectFixStep`; advisory context remains taint-bearing. |
| A-23                |       Accept with modifications | Re-anchor to Source Workspace; split jurisdictional authority from legal treatment/adverseness. |
| A-26                |       Accept with modifications | Use stable artifact identity plus `FindingMatchKey`; avoid version-sensitive scope-only keys. |
| B-02                |       Accept with modifications | Add `attempt_seq` and `prior_output_hash`; integrate with regenerate loop guard. |
| B-03 / D-16         |                Accept; re-scope | Artifact direct-fix path already has protections; real gap is Source Workspace operation/write API. |
| B-08                |              Accept with rename | Use `StepExecutionFailureKind`; register distinct failure enums to avoid name collision. |
| B-14                |       Accept with modifications | Deadlock breaker yes; remove `task_agent_decides`; Task Agent recommends, not decides. |
| B-15                |             Decline / OP-A-only | DOC12 owns `RoomKind.plan_review`; local Task Forum registry fix is wrong-owner. |
| B-16                |       Accept with modifications | Remove wall-clock; use total deterministic policy with lock contention/cost proxy and lexicographic final tie. |
| B-20                |                          Accept | Success condition waits for cascade/ledger quiescence.       |
| B-24                |                 Accept; rewrite | Thin detector + richer triggers + single ledger; Hard Call only when the user has a meaningful choice. |
| B-25                |              Decline as written | `depends_on_step_ids` already exists; replace with dependency representation canonicalization. |
| B-26                |                          Accept | Collapse `revalidation_trigger` / `revalidation_expectation` into one `revalidation_policy`. |
| B-27                |                          Accept | Previous output hashes live in idempotency/termination ledger. |
| C-01                |                  Accept; harden | FormulaRegistry plus scoped formula receipts, observations, rollups, finite-number policy, fixtures. |
| C-02                |                  Accept; harden | Add right-censoring and terminal-class policies to revision-cycle metrics. |
| C-03                |                          Accept | Remove both predicted pre/post future hashes from LLM-authored contract. |
| C-04                |                  Accept; harden | Define sub-agent metric observations and reputation formula; include severity-weighted regression. |
| C-07                |                          Modify | Replace scalar cost estimate with `CostVector` and dimensional rollups. |
| C-08                |                          Modify | Novelty needs a discriminated union for no-neighbor cases.   |
| C-09                |                          Modify | Correct weight normalization and template-match functions; guard zero-weight/NaN/missing components. |
| D-01                |                  Accept; harden | Derive source authority from retrieval lineage; conservative defaults for expert/technical docs. |
| D-04                |                          Modify | Keep tier 0 as receipt-only; no tier-0 downstream claim support. |
| D-07/D-09/D-12/D-24 |                 Merge partially | One Run Board governance/publication/retention/matter-firewall model. |
| D-13                |                         Elevate | Cross-run RunGuidance is prompt injection; require governance, contested-state check, and read-model invalidation. |
| D-20                |                          Modify | Split library-promotion candidate from durable DOC73/library write. |
| §G                  |                    Keep, harden | Derived/read-model layer with input manifests, invalidation, degraded modes, commands, and no-new-truth rule. |
| New X-01            |                             Add | Universal `GovernanceEnvelope` and projection invariant.     |
| New X-02            |                             Add | Structural admission registry for new objects and lints.     |
| New X-03            |                             Add | `RevisorTerminationLedger` as single loop/attempt/cascade source of truth. |
| New X-04            |                             Add | Phantom-field lint and exhaustive type-owner sweep.          |
| New X-05            |                             Add | Read-model invalidation registry.                            |
| New X-06            |                             Add | Reliance-decay monitoring.                                   |
| New X-07            |                             Add | DelegationEnvelope for scoped autonomy.                      |
| New X-08            |                             Add | Feedback-to-prompt responsibility matrix.                    |
| New X-09            |                             Add | Task Agent forum-surface ownership row.                      |
| New X-10            |                             Add | Task-scoped forum policy.                                    |

---

## 4. Step 0 — structural admission and lint discipline

The proposed fix package must itself be governed. Every new type, receipt, read model, policy, command, enum, and lint needs an owner, producer, consumer, durable-artifact class, and fixture. This prevents the hardening package from creating the same duplicate/forked schema problems it is meant to fix.

### 4.1 StructuralAdmissionRecord

```ts
type StructuralAdmissionDisposition =
  | "admit"
  | "admit_with_rename"
  | "admit_as_projection"
  | "merge_with_existing_type"
  | "reject_duplicate"
  | "defer_until_owner_confirmed";

interface StructuralAdmissionRecord {
  record_id: string;

  proposed_type_name: string;
  proposed_owner_doc: OwnerDoc;
  proposed_section_ref: string;

  producer_ref: string;
  consumer_refs: string[];

  durable_artifact_kind?:
    | "event"
    | "record"
    | "receipt"
    | "read_model"
    | "policy"
    | "command"
    | "schema_only";

  canonical_owner_registry_entry_ref?: StorageRef;

  duplicate_check_result:
    | "no_duplicate_found"
    | "duplicates_existing_type"
    | "overlaps_existing_type"
    | "projection_of_existing_type"
    | "owner_unknown";

  duplicate_or_overlap_refs: StorageRef[];

  disposition: StructuralAdmissionDisposition;
  rationale: string;

  required_lint_refs: string[];
  required_fixture_refs: StorageRef[];

  admitted_at?: ISO8601;
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.structural_object_without_owner
validation.structural_object_without_producer
validation.structural_object_without_consumer
validation.structural_object_without_durable_artifact_or_projection_status
validation.structural_object_duplicate_unresolved
validation.structural_admission_missing_fixture
```

### 4.2 SpecObjectAdmissionRegistryEntry

```ts
interface SpecObjectAdmissionRegistryEntry {
  object_name: string;
  object_kind:
    | "enum"
    | "interface"
    | "receipt"
    | "event"
    | "record"
    | "read_model"
    | "policy"
    | "command"
    | "lint"
    | "surface";

  owner_doc: OwnerDoc;
  owner_section_ref: string;

  producer_refs: string[];
  consumer_refs: string[];

  durable_artifact:
    | "canonical_durable"
    | "derived_read_model"
    | "ephemeral_runtime"
    | "schema_only"
    | "projection_only";

  durable_writer:
    | "EC"
    | "OpenClaw_runtime"
    | "none_ephemeral"
    | "external_system";

  admission_status:
    | "admitted"
    | "admitted_projection_only"
    | "merged_with_existing"
    | "rejected_duplicate"
    | "pending_owner_decision";

  duplicate_check_refs: StorageRef[];

  schema_version: "1.0";
}
```

Required lints:

```ts
validation.spec_object_without_admission_entry
validation.spec_object_without_producer
validation.spec_object_without_consumer
validation.spec_object_without_durable_artifact_class
validation.spec_object_conflicts_with_ec_sole_writer
```

### 4.3 LintRegistryEntry

The package now contains many `validation.*` IDs. They are useful only if each has severity, owner, execution stage, and fixtures.

```ts
type LintSeverity = "error" | "warning" | "advisory";

type LintExecutionStage =
  | "schema_compile"
  | "plan_compile"
  | "dispatch_preflight"
  | "runtime_audit"
  | "post_run_audit"
  | "ci_fixture";

interface LintRegistryEntry {
  lint_id: string;

  severity: LintSeverity;
  owner_doc: OwnerDoc;
  owner_section_ref: string;

  execution_stage: LintExecutionStage;

  description: string;

  input_type_refs: string[];
  failure_condition: string;

  fixture_refs: StorageRef[];

  blocks_dispatch: boolean;
  blocks_durable_write: boolean;

  introduced_by_row_ids: string[];

  schema_version: "1.0";
}
```

Required meta-lints:

```ts
validation.lint_without_registry_entry
validation.lint_without_fixture
validation.lint_without_owner
validation.error_lint_does_not_block_when_required
validation.lint_references_unknown_type
```

---

## 5. Layer 1 — universal governance, type ownership, phantom-field linting

### 5.1 GovernanceEnvelope

Use one governance envelope everywhere instead of ad hoc governance fields. It travels through projections and exports.

```ts
interface GovernanceEnvelope {
  taint_class: TaintClass;
  data_class: "public" | "internal" | "privileged" | "local_only";

  matter_id?: string;
  principal_id?: string;
  learning_scope?: "local" | "matter" | "team" | "firm" | "networked";

  privileged: boolean;
  policy_decision_refs: PolicyEvaluationRef[];

  sanitization_required: boolean;

  export_policy:
    | "export_allowed"
    | "redaction_required"
    | "export_blocked"
    | "local_only";

  projection_policy:
    | "must_preserve_governance"
    | "may_downgrade_only_with_sanitization_receipt"
    | "non_exportable";

  schema_version: "1.0";
}
```

Governed object classes include at minimum:

```ts
type GovernedObjectKind =
  | "EvaluationFindingEvent"
  | "EvaluationFindingRecord"
  | "FeedbackFindingView"
  | "EvaluationResultEnvelope"
  | "EvaluationFeedbackBundle"
  | "RunGuidanceItem"
  | "TaskRunBoardPost"
  | "BoardDigest"
  | "TaskRunContextPacket"
  | "SourceRecord"
  | "SourceQueryRecord"
  | "ResearchNeed"
  | "EvidencePackage"
  | "TaskReliancePacket"
  | "LearningSignalEnvelope"
  | "MetricObservation"
  | "WorkspaceExternalizationReceipt";
```

Required lints:

```ts
validation.governed_object_without_envelope
validation.view_drops_governance_fields
validation.export_without_export_policy
validation.projection_downgrades_governance_without_sanitization
validation.exported_object_without_governance
```

### 5.2 TypeOwnerRegistryEntry

```ts
interface TypeOwnerRegistryEntry {
  type_name: string;
  canonical_owner_doc: OwnerDoc;
  canonical_section_ref: string;

  type_kind:
    | "interface"
    | "enum"
    | "type_alias"
    | "schema"
    | "read_model"
    | "receipt"
    | "event"
    | "command"
    | "policy";

  status:
    | "canonical"
    | "imported"
    | "deprecated"
    | "pending_absorption"
    | "projection_only";

  allowed_projection_type_names: string[];

  duplicate_type_names: Array<{
    doc: OwnerDoc;
    section_ref: string;
    disposition: "delete" | "rename" | "projection" | "alias";
  }>;

  pending_consumer_behavior?:
    | "persist_only"
    | "suppress_promotion"
    | "disable_ui_affordance"
    | "emit_validation_warning"
    | "block_route";

  schema_version: "1.0";
}
```

Required lints:

```ts
validation.type_owner_drift
validation.type_declared_without_owner_registry_entry
validation.duplicate_type_without_disposition
validation.pending_absorption_without_degraded_behavior
validation.projection_type_missing_source_type
```

### 5.3 SchemaReferenceValidationRule — phantom-field lint

This should be a global CI check. It parses every spec statement of the form “reads field X,” “writes field Y,” “MUST carry field Z,” etc. against the registered owner type.

```ts
interface SchemaReferenceValidationRule {
  rule_id: string;
  owner_doc: OwnerDoc;

  reference_pattern:
    | "reads_field"
    | "writes_field"
    | "must_carry_field"
    | "emits_type"
    | "consumes_type"
    | "extends_type"
    | "projects_type";

  source_section_ref: string;
  referenced_type_name: string;
  referenced_field_path?: string;

  expected_owner_doc?: OwnerDoc;
  severity: "error" | "warning";
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.field_reference_not_in_schema
validation.type_reference_not_in_owner_registry
validation.projected_field_missing_from_source
validation.consumer_reads_field_not_emitted_by_producer
validation.schema_reference_owner_drift
```

---

## 6. Layer 1 — derived read models and invalidation

§G and many DOC20 surfaces are read models. They cannot create new truth, and they must become stale when upstream truth changes.

```ts
interface DerivedReadModelRecord {
  read_model_id: string;

  read_model_kind:
    | "TaskReliancePacket"
    | "TaskHealthCard"
    | "FindingsInbox"
    | "WorkProductCertification"
    | "RunDiff"
    | "DecisionAuditView"
    | "EvidencePackage"
    | "EvaluationChainView"
    | "BoardDigest"
    | "TaskRunContextPacket";

  input_manifest_ref: StorageRef;
  derivation_policy_ref: StorageRef;

  formula_eval_receipt_refs: StorageRef[];

  valid_from_event_seq: number;
  valid_until_event_seq?: number;

  invalidated_by_event_ref?: StorageRef;

  governance: GovernanceEnvelope;

  schema_version: "1.0";
}

interface ReadModelInvalidationSpec {
  producer_event_kind: string;

  invalidates_read_models: DerivedReadModelRecord["read_model_kind"][];

  invalidation_scope:
    | "same_run"
    | "same_task"
    | "same_matter"
    | "specific_refs";

  target_refs?: StorageRef[];

  schema_version: "1.0";
}
```

Required lints:

```ts
validation.read_model_without_input_manifest
validation.lifecycle_event_without_read_model_invalidation
validation.context_packet_valid_after_invalidation_event
validation.reliance_packet_valid_after_source_change
validation.findings_inbox_valid_after_finding_lifecycle_change
```

---

## 7. §A — Cross-document contract and schema fixes

### 7.1 A-01 / A-05 — canonical EvaluationFinding package

**Final decision:** unify the incompatible finding schemas. Do not keep separate same-named `EvaluationFinding` types. But do not collapse authority into assurance. The final model is:

- immutable `EvaluationFindingEvent` emitted by evaluators;
- mutable `EvaluationFindingRecord` current-state projection;
- `FindingLifecycleTransitionReceipt` for all lifecycle changes;
- FD-owned `FeedbackFindingView` as a projection only;
- canonical FD `EvaluationAuthorityBasis` reused verbatim;
- no `BlockingAuthorityBasis` enum.

#### 7.1.1 Canonical authority enum — import, do not redefine

```ts
// Canonical owner: Feedback Delivery §3.3.
// Common Contracts imports this exact enum.
type EvaluationAuthorityBasis =
  | "deterministic_check"
  | "source_reference"
  | "tool_verification"
  | "rubric_criterion"
  | "user_instruction"
  | "saved_criteria"
  | "human_label"
  | "multi_reviewer_consensus"
  | "model_judgment_only";
```

Do **not** add:

```ts
// Do not add this enum. It is a duplicate and should be rejected by TypeOwnerRegistry.
type BlockingAuthorityBasis = never;
```

#### 7.1.2 Finding kinds and states

```ts
type FindingKind =
  | "criterion_failed"
  | "missing_requirement"
  | "unsupported_assertion"
  | "source_mismatch"
  | "format_violation"
  | "style_violation"
  | "incomplete_coverage"
  | "research_gap"
  | "subjective_quality_issue"
  | "tool_verified_failure"
  | "process_observation"
  | "custom";

type FindingState =
  | "proposed"
  | "active"
  | "contested"
  | "resolved"
  | "superseded_by_revision"
  | "superseded_by_source_change"
  | "tool_verified"
  | "human_verified"
  | "user_approved"
  | "rejected_by_user"
  | "dismissed"
  | "unrecoverable";
```

Use `expires_at` and `expired_by_policy` transition reasons; do not add a new `expired` state unless the canonical owner explicitly amends `FindingState`.

#### 7.1.3 BlockingAuthorityEvaluation

```ts
type SubjectiveBlockingPermission =
  | "not_allowed"
  | "allowed_by_outcome_definition"
  | "allowed_by_user_instruction"
  | "allowed_by_human_review";

interface BlockingAuthorityEvaluation {
  satisfied: boolean;

  // Reuse canonical FD enum. No BlockingAuthorityBasis enum.
  basis: EvaluationAuthorityBasis[];

  subjective_blocking_permission: SubjectiveBlockingPermission;

  evaluated_policy_ref?: PolicyEvaluationRef;
  explanation: string;

  schema_version: "1.0";
}

const DEFAULT_BLOCKING_BASES: EvaluationAuthorityBasis[] = [
  "deterministic_check",
  "source_reference",
  "tool_verification",
  "user_instruction",
  "saved_criteria"
];

function deriveBlockingAuthoritySatisfied(input: {
  severity: "low" | "medium" | "high" | "blocking";
  basis: EvaluationAuthorityBasis[];
  subjective_blocking_permission: SubjectiveBlockingPermission;
}): boolean {
  if (input.severity !== "blocking") return true;

  if (input.basis.some((b) => DEFAULT_BLOCKING_BASES.includes(b))) {
    return true;
  }

  return (
    input.basis.includes("model_judgment_only") &&
    input.subjective_blocking_permission !== "not_allowed"
  );
}
```

Required lints:

```ts
validation.evaluation_authority_basis_redeclared_outside_owner
validation.blocking_authority_basis_enum_forked
validation.blocking_authority_basis_contains_unknown_value
validation.model_judgment_only_blocker_without_subjective_permission
validation.blocking_authority_satisfied_derivation_drift
validation.blocking_authority_missing_explanation
```

#### 7.1.4 FindingMatchKey

```ts
interface FindingMatchKey {
  failure_kind: FailureKind;

  // Stable identity. Do not key only on versioned ArtifactScopeRef.
  stable_artifact_id?: string;
  target_section_path?: string;
  target_scope_ref?: ArtifactScopeRef | null;

  criterion_id?: string;

  finding_summary_hash: string;
  normalized_finding_text_hash: string;
  evidence_signature_hash?: string;
  source_workspace_snapshot_hash?: string;

  schema_version: "1.0";
}
```

#### 7.1.5 EvaluationFindingEvent / Record / LifecycleReceipt / View

```ts
interface EvaluationFindingEvent {
  finding_event_id: string;
  finding_id: string;
  result_id: string;

  producer_kind: ProducerKind;
  producer_module_id: string;
  producer_activation_seq: number;

  finding_kind: FindingKind;
  finding_text: string;
  explanation: string;

  severity: "low" | "medium" | "high" | "blocking";

  // Immutable initial state only.
  emitted_state: "proposed" | "active";

  // Different axes. Do not collapse.
  assurance_basis: AssuranceBasis[];
  authority_basis: EvaluationAuthorityBasis[];
  blocking_authority: BlockingAuthorityEvaluation;

  confidence_score: number; // 0..1
  confidence_basis: ConfidenceBasis[];
  confidence_explanation: string;

  target_artifact_ref?: StorageRef;
  target_artifact_version_ref?: StorageRef;
  target_scope_ref?: ArtifactScopeRef;
  target_criterion_id?: string;
  affected_claim_refs: ClaimRef[];

  evidence_refs: StorageRef[];
  verification_record_refs: StorageRef[];
  supporting_material_snapshot_refs: StorageRef[];

  based_on_artifact_version_ref?: StorageRef;
  based_on_artifact_version_absent_reason?:
    | "non_artifact_target"
    | "human_review_no_artifact"
    | "process_observation";

  based_on_source_workspace_snapshot_ref?: StorageRef;
  based_on_board_digest_ref?: StorageRef;

  evaluation_snapshot_ref: StorageRef;
  match_key: FindingMatchKey;

  governance: GovernanceEnvelope;

  created_at: ISO8601;
  schema_version: "2.0";
  migration_version: number;
}

interface EvaluationFindingRecord {
  finding_id: string;
  canonical_event_ref: StorageRef;

  current_state: FindingState;
  current_severity: "low" | "medium" | "high" | "blocking";

  lifecycle_transition_refs: StorageRef[];

  superseded_by_finding_id?: string;
  expires_at?: ISO8601;

  last_validated_against_artifact_version_ref?: StorageRef;
  last_validated_against_source_workspace_snapshot_ref?: StorageRef;

  governance: GovernanceEnvelope;

  updated_at: ISO8601;
  schema_version: "1.0";
}

interface FindingLifecycleTransitionReceipt {
  receipt_id: string;
  finding_id: string;

  from_state: FindingState;
  to_state: FindingState;

  transition_reason:
    | "router_admitted"
    | "user_contested"
    | "user_confirmed"
    | "tool_verified"
    | "human_verified"
    | "revision_resolved"
    | "source_changed"
    | "target_version_changed"
    | "expired_by_policy"
    | "dismissed_duplicate"
    | "not_confirmed_at_activation_termination"
    | "rejected_by_user"
    | "marked_unrecoverable";

  actor_ref: string;
  evidence_refs: StorageRef[];

  created_at: ISO8601;
  schema_version: "1.0";
}

interface FeedbackFindingView {
  finding_id: string;
  source_finding_event_ref: StorageRef;
  current_finding_record_ref: StorageRef;

  display_summary: string;
  display_explanation: string;

  finding_kind: FindingKind;
  severity: "low" | "medium" | "high" | "blocking";
  lifecycle_state: FindingState;

  blocking_authority_satisfied: boolean;
  blocking_authority_basis: EvaluationAuthorityBasis[];

  routed_action_refs: StorageRef[];

  // Mandatory passthrough. Never recompute or drop.
  governance: GovernanceEnvelope;

  schema_version: "1.1";
}
```

Required lints:

```ts
validation.finding_state_mutated_inside_immutable_event
validation.finding_current_projection_without_event
validation.finding_lifecycle_transition_missing_receipt
validation.finding_proposed_without_terminal_exit
validation.finding_v1_unmigrated
validation.view_drops_governance_fields
validation.feedback_finding_view_authority_drift
validation.finding_authority_assurance_axis_collapsed
validation.progress_signal_match_key_drift
validation.artifact_targeted_finding_missing_version_ref
```

#### 7.1.6 Migration from legacy findings

```ts
interface EvaluationFindingMigrationV1ToV2 {
  legacy_finding_ref: StorageRef;
  generated_event_ref: StorageRef;
  generated_record_ref: StorageRef;

  basis_mapping:
    | "legacy_basis_to_assurance_basis"
    | "legacy_authority_basis_preserved"
    | "legacy_authority_basis_absent";

  confidence_mapping:
    | "low_to_0_3"
    | "medium_to_0_6"
    | "high_to_0_9"
    | "numeric_preserved";

  finding_kind_mapping:
    | "legacy_finding_kind_preserved"
    | "classified_from_text"
    | "default_custom";

  migration_lossiness:
    | "lossless"
    | "lossy_authority_basis_absent"
    | "lossy_kind_inferred";

  migrated_at: ISO8601;
  schema_version: "1.0";
}
```

### 7.2 A-02 / A-03 / A-04 — Pattern C envelope and chain resolution

Pattern C cannot depend on fields that live only on `EvaluationFeedbackBundle`. Put the target and basis fields on the envelope and emit a chain-resolution receipt.

#### 7.2.1 Envelope fields

```ts
interface EvaluationResultEnvelope {
  result_id: string;
  producer_kind: ProducerKind;
  outcome_id: string;
  run_id: string;

  evaluated_target: EvaluatedTarget;
  evaluation_basis: EvaluationBasis;

  // Migration window only; derived from evaluated_target.
  target_artifact_ref: StorageRef | null;
  target_artifact_version_ref: StorageRef | null;
  target_scope_ref: ArtifactScopeRef | null;

  evaluation_snapshot_ref: StorageRef;
  target_evaluation_chain_id?: string;

  governance: GovernanceEnvelope;

  schema_version: string;
}
```

Required lints:

```ts
validation.envelope_target_projection_drift
validation.envelope_basis_missing
validation.envelope_basis_missing_for_pattern_c
```

#### 7.2.2 Chain registry and resolution receipt

```ts
type EvaluationChainStatus =
  | "open"
  | "complete"
  | "partial_timeout"
  | "conflicted"
  | "superseded";

type EvaluationChainKind =
  | "pattern_c_evaluator_then_judge"
  | "experiment_internal"
  | "multi_producer";

interface EvaluationChainRegistryRecord {
  chain_id: string;
  chain_kind: EvaluationChainKind;

  task_id: string;
  run_id: string;

  target_artifact_ref: StorageRef | null;
  target_artifact_version_ref: StorageRef | null;
  target_scope_ref: ArtifactScopeRef | null;
  evaluation_snapshot_ref: StorageRef;

  expected_producers: ProducerKind[];
  received_result_ids: string[];

  status: EvaluationChainStatus;

  created_at: ISO8601;
  completed_at?: ISO8601;
  superseded_by_chain_id?: string;

  validation_failures: Array<
    | "chain_id_missing"
    | "chain_target_mismatch"
    | "chain_stale_snapshot"
    | "chain_ambiguous"
    | "chain_consumer_timeout"
  >;

  schema_version: "1.0";
}

interface EvaluationChainResolutionReceipt {
  receipt_id: string;
  chain_id: string;
  chain_kind: EvaluationChainKind;
  result_ids_considered: string[];

  resolved_verdict: "passed" | "failed" | "indeterminate" | "not_applicable";
  resolved_route:
    | "pass_path"
    | "fail_path"
    | "human_review_path"
    | "retry_path"
    | "block_until_resolved";

  decisive_result_id?: string;
  qualitative_blockers_preserved: boolean;
  quantitative_pass_overridden_by_blocker: boolean;

  conflict_type?:
    | "none"
    | "qualitative_fail_quantitative_pass"
    | "qualitative_pass_quantitative_fail"
    | "indeterminate_mismatch"
    | "missing_expected_producer"
    | "snapshot_mismatch";

  policy_ref: string;
  explanation: string;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.pattern_c_chain_without_resolution_receipt
validation.pattern_c_route_conflict_unresolved
validation.pattern_c_snapshot_mismatch
validation.pattern_c_chain_id_mismatch
validation.chain_id_name_drift
```

### 7.3 A-06 / A-07 — outcome state, disposition, verdict, limitation taxonomy

#### 7.3.1 State/disposition split

```ts
type OutcomeEvaluationRuntimeState =
  | "pending"
  | "pending_dependency"
  | "evaluating"
  | "dirty";

type OutcomeEvaluationDisposition =
  | "satisfied"
  | "needs_revision"
  | "needs_information"
  | "needs_verification"
  | "needs_human_judgment"
  | "unable_to_evaluate"
  | "blocked_by_policy"
  | "regressed"
  | "upstream_failure"
  | "unrecoverable"
  | "superseded"
  | "max_iterations_reached";

type OutcomeEvaluationState = OutcomeEvaluationRuntimeState | OutcomeEvaluationDisposition;

type OutcomeVerdict =
  | "passed"
  | "failed"
  | "indeterminate"
  | "not_applicable";
```

Add a normative `OUTCOME_STATE_MATRIX` rather than scattering verdict/route/terminal mapping across prose:

```ts
interface OutcomeStateMatrixEntry {
  state: OutcomeEvaluationState;
  state_class: "runtime" | "disposition";
  emitted_to_envelope: boolean;
  terminal: boolean;
  verdict_mapping?: OutcomeVerdict;
  feedback_branch: FeedbackBranch;
  blocks_downstream_default: boolean;
  revisor_default_action:
    | "none"
    | "revise"
    | "research"
    | "verify"
    | "hard_call"
    | "process_gap"
    | "stop";
  ui_label: string;
  learning_eligibility:
    | "eligible"
    | "diagnostic_only"
    | "not_eligible";
  schema_version: "1.0";
}
```

#### 7.3.2 No-verdict taxonomy — do not duplicate Addenda A or B-owned enums

Final recommendation: **do not promote a Common `NoVerdictReason` enum until Addenda-A R203 is checked.** For Addenda B, use the verified B-owned limitation labels. Use an alias registry for near-duplicates.

```ts
// Canonical B-side labels from V3.3.1 §5.4.2.
type EvaluationLimitationKind =
  | "insufficient_evidence"
  | "human_judgment_needed"
  | "missing_capability"
  | "source_unavailable"
  | "policy_blocked"
  | "stale_evidence"
  | "unable_to_ground_claim";

// Optional Common read-model vocabulary, adopt only after Addenda-A R203 verification.
type NoVerdictReason =
  | "insufficient_evidence"
  | "human_judgment_needed"
  | "missing_capability"
  | "source_unavailable"
  | "policy_blocked"
  | "stale_evidence"
  | "unable_to_ground_claim"
  | "conflicting_evidence"
  | "tool_failure"
  | "timeout"
  | "unsupported_scope"
  | "blocked_before_substantive_verdict";

interface NoVerdictReasonAliasRegistryEntry {
  alias_value: string;

  canonical_reason: NoVerdictReason;

  source_owner:
    | "DOC23_AddendaB_EvaluationLimitationKind"
    | "DOC23_AddendaA_R203_IndeterminateCause"
    | "legacy_or_review_term";

  source_enum_name?: string;
  source_section_ref?: string;

  mapping_status:
    | "verified"
    | "pending_r203_verification"
    | "legacy_alias"
    | "deprecated";

  schema_version: "1.0";
}

const DEFAULT_NO_VERDICT_ALIAS_MAP: NoVerdictReasonAliasRegistryEntry[] = [
  {
    alias_value: "missing_source",
    canonical_reason: "source_unavailable",
    source_owner: "legacy_or_review_term",
    mapping_status: "legacy_alias",
    schema_version: "1.0"
  },
  {
    alias_value: "stale_source",
    canonical_reason: "stale_evidence",
    source_owner: "legacy_or_review_term",
    mapping_status: "legacy_alias",
    schema_version: "1.0"
  },
  {
    alias_value: "missing_information",
    canonical_reason: "insufficient_evidence",
    source_owner: "legacy_or_review_term",
    mapping_status: "legacy_alias",
    schema_version: "1.0"
  },
  {
    alias_value: "policy_block",
    canonical_reason: "policy_blocked",
    source_owner: "legacy_or_review_term",
    mapping_status: "legacy_alias",
    schema_version: "1.0"
  },
  {
    alias_value: "human_judgment_required",
    canonical_reason: "human_judgment_needed",
    source_owner: "legacy_or_review_term",
    mapping_status: "legacy_alias",
    schema_version: "1.0"
  }
];
```

Required lints:

```ts
validation.no_verdict_reason_label_drift
validation.no_verdict_reason_duplicate_concept
validation.no_verdict_reason_alias_unregistered
validation.indeterminate_cause_redeclared_without_owner_approval
validation.evaluation_limitation_kind_redeclared_outside_owner
validation.limitation_value_used_as_outcome_state
```

### 7.4 A-08 / B-23 — feedback routing resolution and idempotency

Routing completeness and multiple simultaneous branch firing are one problem.

```ts
type FeedbackBranch =
  | "on_satisfied"
  | "on_needs_revision"
  | "on_needs_more_sources"
  | "on_needs_source_verification"
  | "on_needs_human_judgment"
  | "on_blocked_by_policy"
  | "on_upstream_failure"
  | "on_unrecoverable"
  | "on_repeated_failure"
  | "none";

type RoutingFirePolicy =
  | "first_match_only"
  | "all_matching_with_idempotency";

interface FeedbackRoutingResolutionPolicy {
  policy_id: string;
  fire_policy: RoutingFirePolicy;
  state_to_branch_matrix_ref: StorageRef; // OUTCOME_STATE_MATRIX
  delivery_idempotency_key_formula:
    | "hash_run_result_branch"
    | "custom_formula_ref";
  on_conflict:
    | "prefer_blocking"
    | "human_review"
    | "emit_all_with_idempotency"
    | "fail_validation";
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.feedback_branch_unmapped
validation.feedback_branch_multi_fire_without_policy
validation.feedback_delivery_without_idempotency_key
validation.feedback_to_prompt_governance_lost
```

### 7.5 A-09 / A-15 / A-22 — build-ready gate and pending consumer behavior

A sub-addendum surface is not build-ready until owning-doc registries and pending absorption behavior exist.

```ts
interface BuildReadyGateRecord {
  gate_id: string;
  target_doc_family: "DOC23_Addenda_B";
  required_type_owner_registry_pass: boolean;
  required_phantom_field_lint_pass: boolean;
  required_cross_doc_obligation_closure_refs: StorageRef[];
  pending_absorption_entries: TypeOwnerRegistryEntry[];
  pending_absorption_allowed: boolean;
  rationale: string;
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.build_ready_claim_with_pending_unowned_type
validation.pending_consumer_behavior_missing
validation.command_registry_required_but_missing
validation.unstable_section_cross_ref
```

### 7.6 A-11 — LearningMode correction

```ts
// Canonical owner: V3.3.1 §6.16.1.
type LearningMode =
  | "production"
  | "signal_generation"
  | "calibration";
```

Do not add `cross_calibration`.

Required lints:

```ts
validation.learning_mode_value_drift
validation.learning_mode_redeclared_outside_owner
```

### 7.7 A-12 — HumanOutcomeFeedbackEvent

```ts
interface HumanOutcomeFeedbackEvent {
  event_id: string;
  result_id: string;
  outcome_id: string;
  run_id: string;

  human_actor_ref: string;
  occurred_at: ISO8601;

  decision:
    | "override_to_pass"
    | "override_to_fail"
    | "confirm"
    | "request_changes"
    | "defer";

  overridden_verdict?: OutcomeVerdict;
  resulting_verdict?: OutcomeVerdict;

  rationale_text: string;
  target_scope_ref?: ArtifactScopeRef;

  governance: GovernanceEnvelope;

  schema_version: "1.0";
}
```

Rules:

```ts
RULE human_feedback_verdict_fields:
  decision in {"request_changes", "defer"} forbids resulting_verdict.
  decision in {"override_to_pass", "override_to_fail", "confirm"} requires resulting_verdict.
```

Required lint:

```ts
validation.human_feedback_verdict_misuse
```

### 7.8 A-16 / A-17 — direct repair wiring and Revisor planner boundary

```ts
interface PortRevisionEligibility {
  port_id: string;
  module_id: string;
  revision_compatible: boolean; // default false
  module_revision_capability_ref?: StorageRef;
}
```

Rule:

```ts
RULE repair_mutation_port_boundary:
  A meaning-bearing OutcomeRepairInstruction may execute an artifact mutation only through:
    (a) a port named revision_in;
    (b) a port with revision_compatible = true and ModuleRevisionCapability coverage; or
    (c) a sanctioned DirectFixStep whose target_port == "none_direct_fix",
        whose direct_fix_class is allowed, and whose ArtifactMutationPrecondition is satisfied.

  instruction_in, data_in, and context_in may carry advisory context only.
  Advisory context remains taint-bearing and subject to GovernanceEnvelope projection rules.
```

Required lints:

```ts
validation.repair_routed_to_non_revision_port
validation.revisor_declares_revision_in
validation.advisory_repair_context_used_as_mutation_authority
```

### 7.9 A-23 — authority terminology split

```ts
type CoreAuthorityLevel =
  | "binding"
  | "persuasive"
  | "advisory"
  | "unknown";

type LegalTreatmentStatus =
  | "current"
  | "negative_treatment"
  | "overruled"
  | "limited"
  | "distinguished"
  | "adverse"
  | "unknown";

interface ApplicabilityScope {
  scope_kind:
    | "legal_jurisdiction"
    | "regulatory_domain"
    | "business_unit"
    | "technical_platform"
    | "time_period"
    | "geography"
    | "audience"
    | "matter"
    | "custom";
  scope_value: string;
  authority_level?: CoreAuthorityLevel;
  domain_specific_payload?: Record<string, unknown>;
  schema_version: "1.1";
}

interface LegalSourcePayload {
  court?: string;
  jurisdiction?: string;
  date?: string;
  source_authority_level?: CoreAuthorityLevel;
  treatment_status?: LegalTreatmentStatus;
  holdings?: string[];
  useful_propositions?: string[];
  pincite_refs?: StorageRef[];
  schema_version: "1.1";
}
```

Required lints:

```ts
validation.legal_payload_authority_level_legacy
validation.authority_level_projection_drift
validation.authority_level_field_used_for_treatment_status
```

---

## 8. §B — Runtime, concurrency, and distributed-system fixes

### 8.1 RevisorTerminationLedger — one source of loop/attempt/cascade truth

Do not store attempts on both `SufficiencyDetectionResult` and a ledger. The ledger is canonical.

```ts
interface RevisorAttemptLedgerEntry {
  attempt_id: string;
  attempt_seq: number;

  procedure_id?: string;
  strategy_kind?: RepairStrategyKind;

  input_signature_hash: string;
  output_signature_hash?: string;

  score_before?: CalibratedScore;
  score_after?: CalibratedScore;
  score_delta?: number;

  terminal_status:
    | "succeeded"
    | "failed"
    | "no_material_improvement"
    | "policy_blocked"
    | "capability_failed"
    | "regressed"
    | "identical_output_rejected"
    | "not_attempted_missing_evidence"
    | "blocked_by_side_effect_policy"
    | "blocked_by_budget"
    | "blocked_by_precondition";

  receipt_refs: StorageRef[];
  created_at: ISO8601;

  schema_version: "1.0";
}

interface RevisorTerminationLedger {
  ledger_id: string;

  task_id: string;
  run_id: string;
  outcome_id: string;

  finding_match_key: FindingMatchKey;

  originating_finding_id?: string;
  originating_result_id?: string;

  cascade_chain_id?: string;
  cascade_depth: number;
  max_cascade_depth: number;

  attempts: RevisorAttemptLedgerEntry[];

  repeated_insufficiency_count: number;
  still_failing_same_reason_count: number;

  previous_output_hashes: string[];

  quiescence_state:
    | "not_started"
    | "in_progress"
    | "waiting_dependency"
    | "waiting_hard_call"
    | "quiescent"
    | "terminal_blocked";

  terminal_decision?:
    | "continue"
    | "replan"
    | "needs_information"
    | "needs_verification"
    | "needs_human_judgment"
    | "blocked_by_policy"
    | "process_gap_out"
    | "unrecoverable"
    | "max_iterations_reached";

  terminal_decision_ref?: StorageRef;

  updated_at: ISO8601;
  schema_version: "1.0";
}
```

Invariant:

```ts
RULE revisor_loop_counter_invariant:
  still_failing_same_reason_count <= repeated_insufficiency_count.

  repeated_insufficiency_count increments on any insufficient plan.

  still_failing_same_reason_count increments only when the new insufficient
  attempt has the same FindingMatchKey as the prior insufficient attempt.

  If an attempt is insufficient for a new FindingMatchKey:
    repeated_insufficiency_count increments;
    still_failing_same_reason_count resets to 1 or remains scoped to
    the prior key in a separate ledger.
```

Required lints:

```ts
validation.revisor_attempt_without_termination_ledger
validation.repeated_failure_without_match_key
validation.revisor_loop_guard_counters_disagree
validation.success_marked_before_ledger_quiescent
validation.regenerate_identical_output_not_recorded
```

### 8.2 B-24 — sufficiency detection contract

The detector is a predicate/diagnostic object. It may aggregate existing guard receipts into a terminal route. It may not overwrite those underlying guard outcomes. It references the ledger for attempts/counts; it does not embed a second attempt log.

```ts
type SufficiencyTrigger =
  | "no_capability_covers_outcome"
  | "capability_unavailable_or_unhealthy"
  | "policy_prohibits_required_step"
  | "all_policy_allowed_procedures_exhausted"
  | "max_attempts_without_material_score_improvement"
  | "identical_output_loop_detected"
  | "evidence_insufficient_to_proceed"
  | "verification_unresolvable"
  | "contradictory_requirements"
  | "precondition_unresolvable"
  | "budget_cap_prevents_minimal_sufficient_attempt"
  | "external_side_effect_requires_ungranted_approval"
  | "cascade_cycle_detected";

type SufficiencyTerminalRoute =
  | "needs_information"
  | "needs_verification"
  | "needs_human_judgment"
  | "unable_to_evaluate"
  | "blocked_by_policy"
  | "unrecoverable"
  | "process_gap_out";

interface SufficiencyDetectionPolicy {
  policy_id: string;

  min_attempts_before_no_improvement: number; // default 2
  no_improvement_window: number;              // default 2
  improvement_metric_ref: string;             // FormulaSpec ID
  epsilon: number;                            // default 0.03 on 0..1 calibrated score

  max_total_attempts: number;
  consecutive_insufficient_limit: number;

  procedure_universe_scope:
    | "declared_applicable"
    | "policy_allowed_only"
    | "safe_without_human_gate"
    | "all_known_with_policy_labels";

  require_capability_snapshot: true;
  require_policy_snapshot: true;
  require_attempt_signature_hash: true;

  schema_version: "1.0";
}

interface CapabilityCoverageAssessment {
  assessment_id: string;
  outcome_id: string;
  capability_snapshot_ref: StorageRef;

  required_capabilities: CapabilityRef[];
  available_capabilities: CapabilityRef[];

  coverage_state:
    | "covered"
    | "partially_covered"
    | "not_covered"
    | "covered_but_unhealthy";

  gaps: Array<{
    required_capability_ref: CapabilityRef;
    gap_kind:
      | "missing"
      | "unhealthy"
      | "policy_blocked"
      | "version_incompatible";
    evidence_ref?: StorageRef;
  }>;

  schema_version: "1.0";
}

interface CandidateRepairProcedure {
  procedure_id: string;
  strategy_kind: RepairStrategyKind;
  repair_target: RepairTarget;

  required_capabilities: CapabilityRef[];
  policy_allowed: boolean;

  safety_class:
    | "mechanical"
    | "meaning_bearing"
    | "privileged"
    | "external_side_effect";

  tried: boolean;
  exhausted: boolean;

  inapplicable_reason?:
    | "missing_capability"
    | "policy_blocked"
    | "unsafe_without_human"
    | "already_failed_same_signature"
    | "requires_missing_evidence"
    | "requires_ungranted_side_effect";

  schema_version: "1.0";
}

interface SufficiencyDetectionResult {
  detection_id: string;
  outcome_id: string;
  run_id: string;
  evaluated_at: ISO8601;

  policy_ref: string;

  no_sufficient_procedure: boolean;
  triggered_by: SufficiencyTrigger[];

  // Single source of attempt/count truth.
  termination_ledger_ref: StorageRef;

  coverage_assessment_ref: StorageRef;
  candidate_procedure_refs: StorageRef[];

  // Existing typed guard receipts that caused or supported the diagnosis.
  decisive_guard_receipt_refs: StorageRef[];

  terminal_route: SufficiencyTerminalRoute;
  hard_call_required: boolean;

  hard_call_kind?:
    | HardRevisionCallKind
    | "no_sufficient_procedure"
    | "contradictory_requirements"
    | "budget_scope_decision";

  rationale: string;

  schema_version: "1.0";
}
```

Authority boundary:

```ts
RULE sufficiency_detector_authority_boundary:
  SufficiencyDetectionResult may aggregate existing typed guard receipts
  into a terminal_route.

  It may not reinterpret or overwrite the underlying guard dispositions.

  If terminal_route differs from any decisive guard's native disposition,
  SufficiencyDetectionResult MUST explain the aggregation basis and cite
  all decisive_guard_receipt_refs.
```

Routing:

```ts
RULE sufficiency_terminal_route:
  IF terminal_route == "needs_information":
    emit OutcomeEvaluationDisposition.needs_information + ResearchNeed.

  IF terminal_route == "needs_verification":
    emit OutcomeEvaluationDisposition.needs_verification + VerificationRequestStep.

  IF terminal_route == "blocked_by_policy":
    emit OutcomeEvaluationDisposition.blocked_by_policy using the decisive PolicyDecisionRef.
    Hard Call only if the user can alter the policy boundary.

  IF terminal_route == "process_gap_out":
    emit OutcomeEvaluationDisposition.unable_to_evaluate + TaskProcessGapSignal.
    Task Agent may propose a graph patch; it cannot mutate the graph.

  IF terminal_route == "needs_human_judgment":
    raise HardRevisionCall.

  IF terminal_route == "unrecoverable":
    emit OutcomeEvaluationDisposition.unrecoverable and stop retrying.
```

Required lints:

```ts
validation.sufficiency_result_duplicates_attempt_log
validation.sufficiency_result_without_termination_ledger
validation.sufficiency_result_redecides_existing_guard
validation.sufficiency_detector_overwrites_guard_disposition
validation.sufficiency_detector_terminal_route_without_guard_basis
validation.sufficiency_detector_conflict_without_explanation
validation.sufficiency_protocol_without_predicate
validation.no_improvement_without_metric
validation.no_improvement_without_epsilon
validation.procedure_exhaustion_without_candidate_universe
validation.hard_call_raised_when_no_human_choice_available
validation.sufficiency_retry_after_terminal_detection
validation.insufficiency_marker_not_mapped_to_outcome_state
```

### 8.3 B-02 / B-27 — idempotency and regenerate loop guard

Use the existing `RevisionPlanStepKind`, not a parallel `StepKind` enum.

```ts
interface StepIdempotencyKey {
  run_id: string;
  plan_id: string;
  step_id: string;
  step_kind: RevisionPlanStepKind;

  target_ref_hash: string;
  input_payload_hash: string;

  attempt_class: "first" | "retry" | "regenerate";
  attempt_seq: number;
  prior_output_hash?: string;
}
```

Required lints:

```ts
validation.step_idempotency_key_missing_attempt_seq
validation.regenerate_identical_output
validation.idempotency_key_uses_parallel_step_kind_enum
```

### 8.4 B-03 / D-16 — Source Workspace operation API

The artifact mutation path already has direct-fix protections. The gap is the Source Workspace operation path: source records, research needs, verification/freshness records, tier transitions, library candidates, and exports.

```ts
type SourceWorkspaceOperationKind =
  | "create_workspace"
  | "read_workspace_snapshot"
  | "read_source_record"
  | "add_source_record"
  | "update_source_record"
  | "append_source_query_record"
  | "update_research_need"
  | "answer_research_need"
  | "acquire_research_need_lease"
  | "release_research_need_lease"
  | "add_verification_record"
  | "add_freshness_record"
  | "mark_source_stale"
  | "record_tier_transition"
  | "create_source_set"
  | "update_source_set"
  | "promote_library_candidate"
  | "export_workspace_bundle";

interface SourceWorkspaceMutationPrecondition {
  workspace_id: string;
  expected_workspace_head_hash: string;
  expected_event_seq: number;

  target_record_ref?: StorageRef;
  expected_target_record_hash?: string;

  lock_mode: "optimistic_event_seq" | "pessimistic_write_lock";
  lock_lease_ref?: StorageRef;

  on_conflict:
    | "abort_and_reevaluate"
    | "queue_behind_lock"
    | "fail_outcome";

  schema_version: "1.0";
}

interface SourceWorkspaceOperation {
  operation_id: string;
  operation_kind: SourceWorkspaceOperationKind;

  task_id: string;
  run_id?: string;
  workspace_id: string;

  actor_ref: string;
  command_ref?: string;
  idempotency_key: string;

  precondition?: SourceWorkspaceMutationPrecondition;
  payload_ref?: StorageRef;

  governance: GovernanceEnvelope;

  created_at: ISO8601;
  schema_version: "1.0";
}

interface SourceWorkspaceOperationReceipt {
  receipt_id: string;
  operation_id: string;
  operation_kind: SourceWorkspaceOperationKind;
  workspace_id: string;

  prior_workspace_head_hash?: string;
  new_workspace_head_hash?: string;
  prior_event_seq?: number;
  new_event_seq?: number;

  status:
    | "applied"
    | "read_completed"
    | "conflict"
    | "rejected_by_policy"
    | "failed";

  conflict_reason?:
    | "workspace_head_hash_mismatch"
    | "event_seq_mismatch"
    | "target_record_hash_mismatch"
    | "lock_unavailable";

  created_at: ISO8601;
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.workspace_mutation_without_precondition
validation.workspace_event_seq_conflict
validation.workspace_api_operation_unregistered
validation.workspace_receipt_missing_head_hash
validation.workspace_command_missing_idempotency_key
```

### 8.5 Workspace externalization as side effect

Source queries and UI actions can leave the system, disclose matter material, create provider logs, or cost money. They need policy and receipts.

```ts
type WorkspaceExternalizationKind =
  | "open_in_browser"
  | "open_native_app"
  | "show_in_finder"
  | "save_as"
  | "export_bundle"
  | "external_source_query"
  | "connector_fetch"
  | "api_call"
  | "email_source_fetch"
  | "browser_session_read";

interface WorkspaceExternalizationPolicy {
  policy_id: string;
  externalization_kind: WorkspaceExternalizationKind;

  requires_user_confirmation: boolean;
  requires_redaction_preview: boolean;

  allowed_data_classes: Array<"public" | "internal" | "privileged" | "local_only">;
  allowed_taint_classes: TaintClass[];

  max_cost_vector_ref?: StorageRef;
  provider_logging_warning_required: boolean;
  receipt_required: true;
  replay_policy: ReplayPolicy;

  warning_text: string;
  schema_version: "1.0";
}

interface WorkspaceExternalizationReceipt {
  receipt_id: string;
  externalization_kind: WorkspaceExternalizationKind;
  workspace_id: string;

  source_record_refs: SourceRecordRef[];
  destination_ref?: StorageRef;

  policy_ref: string;
  user_confirmation_ref?: StorageRef;
  redaction_preview_ref?: StorageRef;

  cost_vector_ref?: StorageRef;

  status:
    | "completed"
    | "blocked_by_policy"
    | "cancelled"
    | "failed";

  irreversible_disclosure_possible: boolean;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.workspace_externalization_without_policy
validation.privileged_workspace_export_without_confirmation
validation.external_source_query_without_receipt
validation.externalization_cost_cap_missing
```

### 8.6 B-16 — deterministic concurrency tie-breaker

Do not use wall-clock `created_at`. Do not use an unestimable `estimated_lock_duration_ms`. Use a total-order policy with a computable lock-contention/cost proxy and lexicographic final tie.

```ts
interface RevisionLockContentionEstimate {
  estimate_id: string;
  plan_id: string;

  affected_artifact_count: number;
  affected_workspace_record_count: number;

  rolling_hash_in_place_step_count: number;
  external_side_effect_intent_count: number;

  revision_cost_total_tokens?: number;
  source_workspace_write_count: number;

  estimated_contention_score: number; // 0..1, higher = more contention
  formula_eval_receipt_ref?: StorageRef;

  basis:
    | "static_plan_features"
    | "historical_calibrated"
    | "heuristic_uncalibrated";

  schema_version: "1.0";
}

type ConcurrencyTieBreakerField =
  | "required_for_overall_pass_desc"
  | "is_high_stakes_desc"
  | "outcome_priority_asc"
  | "lock_contention_score_asc"
  | "revision_cost_total_tokens_asc"
  | "plan_safety_score_desc"
  | "plan_id_lexicographic_asc";

interface ConcurrencyTieBreakerPolicy {
  policy_id: string;
  ordered_fields: ConcurrencyTieBreakerField[];

  final_tiebreaker: "plan_id_lexicographic_asc";

  schema_version: "1.0";
}

const DEFAULT_CONCURRENCY_TIE_BREAKER: ConcurrencyTieBreakerPolicy = {
  policy_id: "default.concurrency_tie_breaker.v1",
  ordered_fields: [
    "required_for_overall_pass_desc",
    "is_high_stakes_desc",
    "outcome_priority_asc",
    "lock_contention_score_asc",
    "revision_cost_total_tokens_asc",
    "plan_id_lexicographic_asc"
  ],
  final_tiebreaker: "plan_id_lexicographic_asc",
  schema_version: "1.0"
};
```

Required lints:

```ts
validation.concurrency_tie_breaker_uses_wall_clock
validation.concurrency_tie_breaker_not_total_order
validation.concurrency_tie_breaker_missing_final_tiebreaker
validation.concurrency_tie_breaker_uses_unestimable_duration
validation.lock_contention_estimate_missing_for_tiebreaker
```

### 8.7 B-25R — dependency representation canonicalization

The live spec already has `depends_on_step_ids`. The final fix is to prevent drift between step-local dependencies and any `DependencyEdge[]` read model.

```ts
interface RevisionPlanStepBase {
  step_id: string;
  step_order: number;
  step_kind: RevisionPlanStepKind;

  // Canonical source of graph truth.
  depends_on_step_ids: string[];

  affected_artifact_refs: StorageRef[];
  affected_outcome_ids: outcome_id[];

  source_repair_depth: number;
  idempotency_key: string;

  preconditions: RevisionPlanStepPrecondition[];
  expected_output?: RevisionPlanStepExpectedOutput;

  on_failure: RevisionStepFailurePolicy;
  human_gate_recommended: boolean;

  goal_impact_assessment?: GoalImpactAssessment;

  expected_pre_hash?: string;
  produced_post_hash?: string;

  revalidation_policy: RevisionStepRevalidationPolicy;
  revalidation_rationale: string;

  schema_version: "1.1";
}

interface RevisionPlanDependencyReadModel {
  plan_id: string;

  dependency_edges: Array<{
    from_step_id: string;
    to_step_id: string;
    edge_kind:
      | "requires_output"
      | "requires_artifact_version"
      | "requires_human_resolution"
      | "requires_source_answer"
      | "requires_verification";
    schema_version: "1.0";
  }>;

  derived_from_step_dependency_hash: string;

  created_at: ISO8601;
  schema_version: "1.0";
}
```

Rule:

```ts
RULE revision_plan_dependency_source_of_truth:
  RevisionPlanStepBase.depends_on_step_ids is canonical.
  RevisionPlanDependencyReadModel.dependency_edges is derived.
  If both are present, they MUST be isomorphic.
```

Required lints:

```ts
validation.revision_plan_dependency_edge_drift
validation.revision_plan_dependency_read_model_stale
validation.revision_plan_step_dependency_undefined
validation.revision_plan_cycle
validation.revision_plan_dependency_targets_missing_step
```

### 8.8 B-26 — single revalidation policy field

```ts
type RevisionStepRevalidationPolicyKind =
  | "none"
  | "revalidate_targeted_outcomes"
  | "revalidate_declared_dependents"
  | "revalidate_full_closure"
  | "revalidate_full_task";

interface RevisionStepRevalidationPolicy {
  policy_kind: RevisionStepRevalidationPolicyKind;
  outcomes_to_recheck: outcome_id[];
  closure_policy_ref?: StorageRef;
  success_hint?: string;
  rationale: string;
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.revalidation_policy_ambiguous
validation.revalidation_policy_ref_missing
```

### 8.9 C-03 / B-04 — rolling hash and future-hash correction

Remove future hash prediction from the LLM-authored plan. The runtime acquires locks and computes pre/post hashes.

```ts
mutation_mode: "candidate_only" | "rolling_hash_in_place";

in_place_mutation_locks?: Array<{
  step_id: string;
  target_section_anchor_hash: string;
  expected_base_version_id: string;
  expected_pre_hash: string;       // runtime-read at lock acquisition
}>;

// Dispatcher writes after execution:
produced_post_hash?: string;
```

Required lints:

```ts
validation.revision_plan_contains_predicted_post_hash
validation.revision_plan_contains_predicted_pre_hash
validation.in_place_lock_missing_expected_pre_hash
validation.rolling_hash_parallel_steps_same_artifact
```

---

## 9. §C — Math, scoring, metrics, and functions

### 9.1 Formula registry plus scoped evaluation receipts

A registry alone says a formula exists. A receipt proves a durable number used a specific formula version and input manifest. But receipts must be scoped, not emitted for every transient hot-path calculation.

```ts
type NumericUnit =
  | "unitless"
  | "ratio"
  | "probability"
  | "score_0_1"
  | "count"
  | "tokens"
  | "usd"
  | "milliseconds"
  | "seconds"
  | "percent"
  | "custom";

type MetricValueKind =
  | "count"
  | "ratio"
  | "mean"
  | "median"
  | "quantile"
  | "calibrated_score"
  | "correlation"
  | "distribution"
  | "cost_vector"
  | "boolean_derived"
  | "enum_derived";

type MissingInputPolicy =
  | "fail_validation"
  | "return_indeterminate"
  | "exclude_with_recorded_omission"
  | "default_value_with_audit"
  | "block_computation";

type ZeroDenominatorPolicy =
  | "return_indeterminate_insufficient_data"
  | "return_zero"
  | "return_one"
  | "fail_validation";

type FiniteNumberPolicy =
  | "reject_nan_infinity"
  | "coerce_to_indeterminate"
  | "allow_only_in_test_fixture";

interface FormulaInputSpec {
  name: string;
  type_ref: SchemaRef;
  required: boolean;
  allowed_units?: NumericUnit[];
  allowed_range?: [number, number];
  missing_input_policy_override?: MissingInputPolicy;
}

interface FormulaOutputSpec {
  value_kind: MetricValueKind;
  unit: NumericUnit;
  range?: [number, number];
  higher_is_better?: boolean;
  finite_number_policy: FiniteNumberPolicy;
}

interface FormulaSpec {
  formula_id: string;
  owner_doc: OwnerDoc;
  semantic_version: string;

  purpose: string;
  expression_ref: StorageRef;
  expression_language:
    | "deterministic_typescript"
    | "sql_read_model"
    | "declarative_metric_dsl"
    | "human_review_required";

  inputs: FormulaInputSpec[];
  output: FormulaOutputSpec;

  missing_input_policy: MissingInputPolicy;
  zero_denominator_policy?: ZeroDenominatorPolicy;

  rounding_policy:
    | "no_rounding_store_full_precision"
    | "round_display_only"
    | "round_to_6_decimal_places";

  sample_policy?: {
    min_sample_size: number;
    insufficient_sample_result: "indeterminate" | "emit_with_low_confidence";
    window_required: boolean;
  };

  confidence_interval_policy?: {
    required: boolean;
    interval_level: 0.8 | 0.9 | 0.95 | 0.99;
    method:
      | "wilson"
      | "bootstrap"
      | "normal_approximation"
      | "bayesian_beta"
      | "not_applicable";
  };

  test_vectors: FormulaTestVector[];
  schema_version: "1.0";
}
```

### 9.2 Formula receipt policy — scoped, not universal

```ts
type FormulaReceiptRequirement =
  | "required"
  | "not_required_transient"
  | "optional_debug"
  | "forbidden_hot_path";

interface FormulaReceiptPolicy {
  policy_id: string;

  receipt_required_when: Array<
    | "persisted_metric_observation"
    | "persisted_metric_rollup"
    | "input_to_reliance_decision"
    | "input_to_learning_decision"
    | "input_to_reputation_decision"
    | "user_facing_certification"
    | "audit_report"
  >;

  transient_in_flight_scores:
    | "no_receipt_required"
    | "debug_trace_allowed"
    | "sampled_trace_allowed";

  max_hot_path_receipts_per_activation?: number;

  schema_version: "1.0";
}

const DEFAULT_FORMULA_RECEIPT_POLICY: FormulaReceiptPolicy = {
  policy_id: "default.formula_receipts.v1",
  receipt_required_when: [
    "persisted_metric_observation",
    "persisted_metric_rollup",
    "input_to_reliance_decision",
    "input_to_learning_decision",
    "input_to_reputation_decision",
    "user_facing_certification",
    "audit_report"
  ],
  transient_in_flight_scores: "no_receipt_required",
  max_hot_path_receipts_per_activation: 0,
  schema_version: "1.0"
};
```

```ts
interface FormulaEvaluationReceipt {
  receipt_id: string;
  formula_id: string;
  formula_semantic_version: string;

  producer_ref: string;
  task_id?: string;
  run_id?: string;

  input_refs: StorageRef[];
  input_manifest_hash: string;
  input_value_hash: string;

  output_ref: StorageRef;
  output_value_hash: string;

  omitted_input_names: string[];
  missing_input_policy_applied?: MissingInputPolicy;
  zero_denominator_policy_applied?: ZeroDenominatorPolicy;

  finite_number_check:
    | "passed"
    | "failed_nan"
    | "failed_infinity"
    | "coerced_to_indeterminate";

  validation_codes: string[];
  computed_at: ISO8601;
  schema_version: "1.0";
}

interface MetricObservation {
  observation_id: string;
  metric_id: string;
  formula_eval_receipt_ref: StorageRef;

  subject_ref: StorageRef;
  observed_at: ISO8601;
  value_ref: StorageRef;

  governance: GovernanceEnvelope;
  schema_version: "1.0";
}

interface MetricRollup {
  rollup_id: string;
  metric_id: string;
  subject_scope_ref: StorageRef;
  measurement_window: DateRange;

  included_observation_refs: StorageRef[];
  excluded_observation_refs: Array<{
    observation_ref: StorageRef;
    exclusion_reason:
      | "outside_window"
      | "wrong_subject_scope"
      | "right_censored"
      | "policy_filtered"
      | "duplicate"
      | "invalidated";
  }>;

  formula_eval_receipt_ref: StorageRef;
  sample_size: number;
  value_ref: StorageRef;
  confidence_interval?: [number, number];
  confidence_interval_level?: 0.8 | 0.9 | 0.95 | 0.99;

  created_at: ISO8601;
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.metric_without_formula_spec
validation.metric_value_without_formula_receipt
validation.metric_rollup_without_window
validation.metric_rollup_includes_invalidated_observation
validation.formula_output_nan_or_infinity
validation.formula_test_vector_missing
validation.formula_version_drift
validation.durable_metric_without_formula_receipt
validation.reliance_score_without_formula_receipt
validation.reputation_score_without_formula_receipt
validation.learning_signal_score_without_formula_receipt
validation.hot_path_formula_receipt_exceeds_policy
validation.transient_score_persisted_without_receipt
```

### 9.3 Corrected criterion weight normalization

The original function failed on unanchored criteria policy, negative/NaN weights, missing priority weights, and zero total weight.

```ts
function assertFiniteNonNegative(value: number, code: string): void {
  if (!Number.isFinite(value) || value < 0) {
    throw new Error(code);
  }
}

function aggregationEligibleCriteria(
  criteria: Criterion[],
  policy: OutcomeComplianceScoringConfig
): Criterion[] {
  const unanchored = criteria.filter(c => c.scoring_basis === "unanchored_llm_judgment");

  if (unanchored.length > 0) {
    if (policy.unanchored_llm_judgment_policy === "indeterminate") {
      throw new Error("validation.unanchored_required_criterion_indeterminate");
    }
    if (policy.unanchored_llm_judgment_policy === "exclude") {
      return criteria.filter(c => c.scoring_basis !== "unanchored_llm_judgment");
    }
    if (policy.unanchored_llm_judgment_policy === "include_with_audit_flag") {
      return criteria;
    }
  }

  return criteria;
}

function normalizeCriterionWeights(
  criteria: Criterion[],
  policy: OutcomeComplianceScoringConfig
): Record<string, number> {
  const eligible = aggregationEligibleCriteria(criteria, policy);

  if (eligible.length === 0) {
    throw new Error("validation.no_aggregation_eligible_criteria");
  }

  const rawWeights = eligible.map(c => {
    let rawWeight: number;

    if (policy.default_weight_policy === "from_criterion_weight") {
      if (c.weight == null) {
        throw new Error("validation.criterion_weight_missing_under_from_criterion_weight");
      }
      rawWeight = c.weight;
    } else if (policy.default_weight_policy === "from_priority") {
      const priority = c.priority ?? "should_have";
      rawWeight = policy.priority_weight_map[priority];
      if (rawWeight == null) {
        throw new Error("validation.criterion_priority_weight_missing");
      }
    } else {
      rawWeight = 1;
    }

    assertFiniteNonNegative(rawWeight, "validation.criterion_weight_invalid");
    return [c.criterion_id, rawWeight] as const;
  });

  const sum = rawWeights.reduce((acc, [, w]) => acc + w, 0);

  if (!Number.isFinite(sum) || sum <= 0) {
    throw new Error("validation.criterion_weight_sum_zero");
  }

  return Object.fromEntries(rawWeights.map(([id, w]) => [id, w / sum]));
}
```

Required lints:

```ts
validation.unanchored_required_criterion_indeterminate
validation.criterion_weight_invalid
validation.criterion_priority_weight_missing
validation.criterion_weight_sum_zero
validation.no_aggregation_eligible_criteria
```

### 9.4 QualityIndex pass status is derived

```ts
interface QualityIndex {
  aggregate_score: number; // 0..1
  pass_threshold: number;  // 0..1
  required_gate_failures: string[];

  aggregation_method:
    | "all_required_then_weighted_mean"
    | "weighted_mean"
    | "min_required_score"
    | "all_or_nothing";

  missing_dimension_policy:
    | "fail_required"
    | "exclude_optional_with_penalty"
    | "indeterminate";

  derived_pass_status:
    | "passed"
    | "failed_threshold"
    | "failed_required_gate"
    | "indeterminate";

  formula_eval_receipt_ref: StorageRef;
  metric_semantics_version: string;
  schema_version: "1.1";
}
```

Rule:

```ts
RULE quality_index_pass_derivation:
  IF required_gate_failures.length > 0:
    derived_pass_status = "failed_required_gate"
  ELSE IF aggregate_score >= pass_threshold:
    derived_pass_status = "passed"
  ELSE:
    derived_pass_status = "failed_threshold"
```

Required lint:

```ts
validation.quality_index_pass_status_drift
```

### 9.5 Revision-cycle metrics with censoring

```ts
type OutcomeCycleTerminalClass =
  | "succeeded"
  | "failed_unrecoverable"
  | "max_iterations_reached"
  | "blocked_by_policy"
  | "needs_human_judgment"
  | "needs_information"
  | "cancelled_by_user"
  | "still_open_right_censored";

interface RevisionCycleOutcomeObservation {
  observation_id: string;
  outcome_id: string;
  run_id: string;

  cycle_count: number;
  terminal_class: OutcomeCycleTerminalClass;

  terminal_state_ref?: StorageRef;
  right_censored_at?: ISO8601;
  observation_window: DateRange;

  cost_vector_ref?: StorageRef;
  formula_eval_receipt_ref?: StorageRef;
  schema_version: "1.0";
}

interface RevisionCycleEfficiencyRollup {
  rollup_id: string;
  measurement_window: DateRange;

  avg_cycles_to_success?: number;
  wasted_cycle_burn_rate?: number;
  right_censored_rate: number;
  max_iterations_rate: number;

  included_observation_refs: StorageRef[];
  formula_eval_receipt_ref: StorageRef;
  schema_version: "1.0";
}
```

### 9.6 Sub-agent metrics and reputation formula

```ts
interface SubAgentAdviceMetricObservation {
  observation_id: string;
  sub_agent_ref: SubAgentRef;
  coordination_point: AllowedCoordinationPoint;

  advice_ref: StorageRef;
  accepted: boolean;

  outcome_delta?: CalibratedScore;
  attribution_lift?: number;

  regression_introduced: boolean;
  regression_severity?: "minor" | "major" | "critical";

  false_positive?: boolean;
  false_negative?: boolean;

  cost_vector_ref?: StorageRef;
  formula_eval_receipt_refs: StorageRef[];

  governance: GovernanceEnvelope;

  created_at: ISO8601;
  schema_version: "1.0";
}

interface SeverityWeightedRegressionRate {
  accepted_count: number;
  regression_introduced_count: number;
  severity_breakdown: Record<"minor" | "major" | "critical", number>;

  severity_weights: Record<"minor" | "major" | "critical", number>; // default 1,2,5
  unweighted_regression_rate: number | null;
  severity_weighted_penalty_rate: number | null;

  zero_denominator_policy: ZeroDenominatorPolicy;
  formula_eval_receipt_ref: StorageRef;
  schema_version: "1.0";
}

interface SubAgentReputationFormulaConfig {
  formula_id: "sub_agent_reputation_score_v1";

  weights: {
    hit_rate: number;
    attribution_lift: number;
    inverse_regression_penalty: number;
    inverse_cost_penalty: number;
    false_negative_penalty: number;
    false_positive_penalty: number;
  };

  false_negative_weight_multiplier: number; // default 2
  min_invocation_count: number;             // default 10
  confidence_interval_method: "wilson" | "bayesian_beta" | "bootstrap";
  output_range: [0, 1];

  schema_version: "1.0";
}

interface SubAgentReputationScore {
  sub_agent_ref: SubAgentRef;
  current_score: number | null;
  score_status: "computed" | "insufficient_sample" | "quarantined_by_policy";

  component_scores: {
    hit_rate_score?: number;
    attribution_lift_score?: number;
    regression_penalty_score?: number;
    cost_penalty_score?: number;
    false_negative_penalty_score?: number;
    false_positive_penalty_score?: number;
  };

  formula_config_ref: StorageRef;
  formula_eval_receipt_ref: StorageRef;
  sample_size: number;
  confidence_interval?: [number, number];
  confidence_interval_level?: 0.8 | 0.9 | 0.95 | 0.99;

  schema_version: "1.0";
}
```

Required lints:

```ts
validation.sub_agent_metric_named_without_observation_schema
validation.sub_agent_advice_regression_without_severity
```

### 9.7 CostVector, cost records, and quantile aggregation

```ts
type CostDimension =
  | "usd"
  | "input_tokens"
  | "output_tokens"
  | "cached_input_tokens"
  | "cache_write_tokens"
  | "local_compute_seconds"
  | "wall_clock_ms"
  | "external_api_calls"
  | "external_api_usd"
  | "storage_bytes"
  | "human_review_minutes";

interface CostDistribution {
  expected: number;
  p50?: number;
  p90?: number;
  p99?: number;
  hard_cap?: number;
  unit: CostDimension;
}

interface CostVector {
  cost_vector_id: string;

  components: Partial<Record<CostDimension, CostDistribution>>;

  basis:
    | "historical"
    | "model_priced"
    | "provider_quote"
    | "heuristic"
    | "measured_actual";

  estimator_confidence: "calibrated" | "uncalibrated" | "experimental";
  sample_size?: number;
  measurement_window?: DateRange;

  assumptions: string[];
  formula_eval_receipt_ref?: StorageRef;
  schema_version: "1.0";
}

interface TaskCostRecord {
  cost_record_id: string;
  task_id: string;
  run_id?: string;
  module_id?: string;
  activation_seq?: number;

  planned_cost_vector_ref?: StorageRef;
  actual_cost_vector_ref?: StorageRef;

  cost_class:
    | "logical_llm_work"
    | "infrastructure_retry"
    | "source_research"
    | "doc24_packet_assembly"
    | "external_tool"
    | "local_compute"
    | "human_review";

  created_at: ISO8601;
  schema_version: "1.0";
}

type CostCorrelationPolicy =
  | "assume_independent_monte_carlo"
  | "assume_perfect_correlation_upper_bound"
  | "empirical_joint_distribution";
```

Rules:

```ts
RULE cost_vector_addition:
  Add only matching CostDimension units.
  p90/p99 aggregation MUST NOT sum independent quantiles unless correlation_policy is declared.
```

Required lints:

```ts
validation.cost_vector_unit_mismatch
validation.cost_quantile_sum_without_correlation_policy
```

### 9.8 Novelty assessment union

```ts
type NoveltyAssessment =
  | NoveltyAssessmentWithNeighbor
  | NoveltyAssessmentNoNeighbor;

interface NoveltyAssessmentBase {
  input_signature_hash: string;
  metric_spec_ref: string;
  metric_semantics_version: string;
  schema_version: "1.1";
}

interface NoveltyAssessmentWithNeighbor extends NoveltyAssessmentBase {
  neighbor_state: "nearest_pattern_found";
  closest_pattern_id: string;
  closest_pattern_distance: number;
  similarity_score: number;
  novelty_score: number;
  forces_fresh_reasoning: boolean;
  triggers_task_agent: boolean;
}

interface NoveltyAssessmentNoNeighbor extends NoveltyAssessmentBase {
  neighbor_state: "no_pattern_found";
  no_pattern_fallback_applied:
    | "novelty_one"
    | "indeterminate"
    | "use_domain_baseline";

  closest_pattern_id?: never;
  closest_pattern_distance?: never;

  similarity_score?: never;
  novelty_score: number | null;
  forces_fresh_reasoning: boolean;
  triggers_task_agent: boolean;
  indeterminate_reason?: "no_pattern_and_policy_indeterminate";
}
```

Required lints:

```ts
validation.novelty_no_neighbor_has_distance
validation.novelty_neighbor_missing_distance
```

### 9.9 Corrected template match function

```ts
type TemplateMatchComponent =
  | "semantic_intent_match"
  | "task_type_match"
  | "input_contract_match"
  | "output_contract_match"
  | "capability_availability_match"
  | "entity_context_match"
  | "user_preference_match"
  | "prior_assessment_score"
  | "recency_or_staleness_score";

type TemplateMatchComponents = Record<TemplateMatchComponent, number>;
type TemplateMatchWeights = Record<TemplateMatchComponent, number>;

function assertScore01(value: number, code: string): void {
  if (!Number.isFinite(value) || value < 0 || value > 1) {
    throw new Error(code);
  }
}

function computeTemplateOverallScore(
  components: TemplateMatchComponents,
  weights: TemplateMatchWeights,
  softPenaltySum: number,
  hardVetoCount: number,
  formula: TemplateMatchFormula
): number {
  let weighted = 0;
  let totalWeight = 0;

  for (const key of Object.keys(formula.component_weights) as TemplateMatchComponent[]) {
    const value = components[key];
    const weight = weights[key];

    assertScore01(value, "validation.template_match_component_out_of_range");

    if (!Number.isFinite(weight) || weight < 0) {
      throw new Error("validation.template_match_weight_invalid");
    }

    weighted += value * weight;
    totalWeight += weight;
  }

  if (!Number.isFinite(totalWeight) || totalWeight <= 0) {
    throw new Error("validation.template_match_total_weight_zero");
  }

  if (
    !Number.isFinite(softPenaltySum) ||
    softPenaltySum < 0 ||
    softPenaltySum > formula.soft_penalty_max_total
  ) {
    throw new Error("validation.template_match_soft_penalty_invalid");
  }

  assertScore01(formula.hard_veto_cap, "validation.template_match_hard_veto_cap_invalid");

  const normalized = weighted / totalWeight;
  const penalized = Math.max(0, Math.min(1, normalized - softPenaltySum));
  return hardVetoCount > 0 ? Math.min(penalized, formula.hard_veto_cap) : penalized;
}
```

Required lints:

```ts
validation.template_match_weight_invalid
validation.template_match_total_weight_zero
validation.template_match_soft_penalty_invalid
validation.template_match_hard_veto_cap_invalid
validation.template_match_output_nan
```

### 9.10 Calibration metrics are not numerator/denominator ratios

```ts
interface CalibrationMetricSpec {
  metric_id:
    | "planner_confidence_brier_score"
    | "planner_confidence_expected_calibration_error"
    | "novelty_threshold_precision_recall"
    | "novelty_threshold_auc"
    | "confidence_convergence_spearman";

  predicted_value_field: string;
  observed_outcome_field: string;

  observed_outcome_encoding:
    | "binary_success"
    | "time_to_event"
    | "ordinal"
    | "continuous_delta";

  sample_policy: {
    min_sample_size: number;
    insufficient_sample_result: "indeterminate";
  };

  binning_policy?: {
    bin_count: number;
    binning_method: "equal_width" | "equal_frequency";
  };

  censoring_policy?: {
    right_censored_allowed: boolean;
    right_censored_handling: "exclude" | "survival_model" | "count_as_non_converged_after_window";
    observation_window: DurationISO8601;
  };

  formula_ref: string;
  schema_version: "1.0";
}

interface CalibrationMetricResult {
  result_id: string;
  metric_spec_ref: string;
  metric_value: number | null;
  indeterminate_reason?: "insufficient_sample" | "invalid_inputs" | "all_one_class";

  sample_size: number;
  positive_count?: number;
  negative_count?: number;

  confidence_interval?: [number, number];
  formula_eval_receipt_ref: StorageRef;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.correlation_metric_declared_as_ratio
validation.calibration_metric_without_sample_policy
validation.calibration_metric_all_one_class
validation.calibration_metric_without_censoring_policy
```

### 9.11 C-10 — lexical hash vs semantic version

```ts
interface CriterionIdentity {
  criterion_id: string;
  criterion_text_hash: string; // lexical
  criterion_semantics_version: string;
  semantic_review_receipt_ref?: StorageRef;
  schema_version: "1.0";
}
```

Required lint:

```ts
validation.criterion_semantics_version_unbumped_on_meaning_change
```

---

## 10. §D — Source Workspace, Forum, board, taint, and evidence

### 10.1 Source authority from retrieval lineage

Do not add an orphan `SourceTrustBasis` axis. Derive authority from existing SourceRecord retrieval lineage / retrieval method fields and source kind.

```ts
type SourceAuthorityAssessmentState =
  | "external_authority_trusted"
  | "internal_corpus_trusted"
  | "user_trusted_bounded"
  | "external_untrusted"
  | "unclassified"
  | "requires_policy_review";

type RetrievalAuthoritySignal =
  | "official_api"
  | "verified_authority_database"
  | "court_record"
  | "regulator_record"
  | "issuer_filing_system"
  | "authenticated_connector"
  | "user_supplied"
  | "party_submitted"
  | "expert_authored_unverified"
  | "vendor_documentation"
  | "web_unverified"
  | "manual_override_policy"
  | "unknown";

interface SourceAuthorityAssessment {
  assessment_id: string;
  source_record_ref: SourceRecordRef;

  // Derived from existing SourceRecord retrieval-lineage fields.
  retrieval_authority_signals: RetrievalAuthoritySignal[];

  derived_taint_class: TaintClass;
  derived_authority_state: SourceAuthorityAssessmentState;

  override_applied: boolean;
  override_policy_decision_ref?: PolicyEvaluationRef;
  override_reason?: string;

  source_kind: SourceRecord["source_kind"];
  retrieval_lineage_ref: StorageRef;

  explanation: string;

  assessed_at: ISO8601;
  schema_version: "1.0";
}

interface SourceKindAuthorityDefault {
  source_kind: SourceRecord["source_kind"];

  default_authority_state: SourceAuthorityAssessmentState;
  default_taint_class: TaintClass;

  required_retrieval_authority_signals?: RetrievalAuthoritySignal[];

  override_allowed: boolean;
  override_requires_policy_decision: boolean;

  schema_version: "1.0";
}
```

Conservative defaults:

```ts
const SOURCE_KIND_AUTHORITY_DEFAULTS: SourceKindAuthorityDefault[] = [
  {
    source_kind: "case_law",
    default_authority_state: "external_authority_trusted",
    default_taint_class: "external_authority_trusted",
    required_retrieval_authority_signals: ["court_record", "verified_authority_database"],
    override_allowed: true,
    override_requires_policy_decision: true,
    schema_version: "1.0"
  },
  {
    source_kind: "statute",
    default_authority_state: "external_authority_trusted",
    default_taint_class: "external_authority_trusted",
    required_retrieval_authority_signals: ["official_api", "verified_authority_database"],
    override_allowed: true,
    override_requires_policy_decision: true,
    schema_version: "1.0"
  },
  {
    source_kind: "regulation",
    default_authority_state: "external_authority_trusted",
    default_taint_class: "external_authority_trusted",
    required_retrieval_authority_signals: ["official_api", "verified_authority_database"],
    override_allowed: true,
    override_requires_policy_decision: true,
    schema_version: "1.0"
  },
  {
    source_kind: "financial_filing",
    default_authority_state: "external_authority_trusted",
    default_taint_class: "external_authority_trusted",
    required_retrieval_authority_signals: ["issuer_filing_system", "regulator_record", "official_api"],
    override_allowed: true,
    override_requires_policy_decision: true,
    schema_version: "1.0"
  },
  {
    source_kind: "expert_report",
    default_authority_state: "user_trusted_bounded",
    default_taint_class: "user_trusted_bounded",
    required_retrieval_authority_signals: ["user_supplied", "party_submitted", "expert_authored_unverified"],
    override_allowed: true,
    override_requires_policy_decision: true,
    schema_version: "1.0"
  },
  {
    source_kind: "technical_doc",
    default_authority_state: "external_untrusted",
    default_taint_class: "external_untrusted",
    required_retrieval_authority_signals: ["vendor_documentation", "user_supplied", "official_api"],
    override_allowed: true,
    override_requires_policy_decision: true,
    schema_version: "1.0"
  },
  {
    source_kind: "custom",
    default_authority_state: "unclassified",
    default_taint_class: "unclassified",
    override_allowed: true,
    override_requires_policy_decision: true,
    schema_version: "1.0"
  }
];
```

Required lints:

```ts
validation.source_kind_authority_unmapped
validation.source_authority_without_retrieval_lineage
validation.external_authority_without_retrieval_authority_signal
validation.source_authority_override_without_policy_decision
validation.source_trust_basis_duplicates_retrieval_lineage
validation.taint_not_inherited_through_summary
```

### 10.2 D-04 — tier 0 receipt-only model

Keep tier 0, but make it receipt-only. It should not support downstream final-claim citation.

```ts
type SourceDocumentationTier = 0 | 1 | 2 | 3 | 4;

type SourceMaterializationKind =
  | "tool_receipt_only"      // tier 0
  | "source_record"          // tiers 1-3
  | "workspace_bundle";      // tier 4

interface EphemeralSourceLookupReceipt {
  receipt_id: string;
  query_id?: string;
  tool_receipt_ref: StorageRef;

  source_title_or_label?: string;
  lookup_purpose: string;

  tier: 0;
  materialization_kind: "tool_receipt_only";

  may_support_downstream_claims: false;
  may_be_cited_in_final_artifact: false;

  governance: GovernanceEnvelope;

  created_at: ISO8601;
  schema_version: "1.0";
}

interface SourceRecord {
  source_id: string;
  tier: 1 | 2 | 3;
  materialization_kind: "source_record";

  governance: GovernanceEnvelope;

  // existing SourceRecord fields...
}
```

Migration note: if existing `SourceRecord.tier == 0` records exist, migrate them to `EphemeralSourceLookupReceipt` or mark them legacy read-only until migration.

Required lints:

```ts
validation.tier0_source_record_materialized
validation.claim_depends_on_tier0_lookup
validation.tier0_lookup_cited_in_final_artifact
validation.source_tier_transition_not_persisted
validation.source_tier_transition_tier_out_of_domain
```

### 10.3 ResearchNeed scope and lease

```ts
type ResearchNeedStatus =
  | "open"
  | "leased"
  | "human_needed"
  | "answered"
  | "unresolved"
  | "cancelled";

interface ResearchNeed {
  need_id: string;
  workspace_id: string;
  need_scope: "run" | "task" | "workspace";
  task_id: string;
  run_id?: string;

  status: ResearchNeedStatus;
  question: string;
  target_refs: Array<ArtifactScopeRef | ClaimRef | SourceRecordRef>;

  created_by_ref: string;
  created_at: ISO8601;
  updated_at: ISO8601;

  governance: GovernanceEnvelope;
  schema_version: "1.0";
}

interface ResearchNeedLease {
  need_id: string;
  leased_by_module_id: string;
  lease_token: string;
  acquired_at: ISO8601;
  expires_at: ISO8601;
  on_expiry: "release_for_reclaim" | "escalate" | "mark_abandoned";
  satisfied_by_result_ref?: StorageRef;
  schema_version: "1.0";
}
```

### 10.4 Evidence anchors and claim-support derivation

```ts
type ClaimSupportStatus =
  | "supported"
  | "partially_supported"
  | "unsupported"
  | "contradicted"
  | "not_checked"
  | "indeterminate_stale_or_unverified";

type EvidenceAnchorSupportStrength =
  | "direct"
  | "indirect"
  | "contextual"
  | "contradicts";

interface SourceEvidenceAnchor {
  anchor_id: string;
  source_record_ref: SourceRecordRef;
  anchor_kind:
    | "page"
    | "quote"
    | "section"
    | "timestamp"
    | "row"
    | "url_fragment"
    | "paragraph"
    | "line_range";
  anchor_payload_ref: StorageRef;
  supports_claim_refs: ClaimRef[];
  support_strength: EvidenceAnchorSupportStrength;
  extracted_text_ref?: StorageRef;
  governance: GovernanceEnvelope;
  schema_version: "1.0";
}

interface ClaimSupportDerivationPolicy {
  policy_id: string;

  required_for_supported: {
    min_direct_supporting_anchors: number;
    require_verified_source: boolean;
    allow_stale_source: boolean;
    allow_contradicting_anchor: boolean;
  };

  partial_support_rule:
    | "any_indirect_or_contextual_anchor"
    | "direct_anchor_unverified"
    | "domain_specific";

  contradiction_rule:
    | "any_direct_contradiction_controls"
    | "weighted_by_authority"
    | "human_review_required";

  formula_ref: string;
  schema_version: "1.0";
}

interface ClaimSupportDerivationReceipt {
  receipt_id: string;
  claim_ref: ClaimRef;
  policy_ref: string;

  supporting_anchor_refs: StorageRef[];
  contradicting_anchor_refs: StorageRef[];

  source_verification_refs: StorageRef[];
  source_freshness_refs: StorageRef[];
  applicability_scope_refs: StorageRef[];

  derived_support_status: ClaimSupportStatus;
  decisive_reason:
    | "direct_verified_support"
    | "partial_indirect_support"
    | "no_supporting_anchor"
    | "direct_contradiction"
    | "stale_or_unverified_source"
    | "not_checked";

  formula_eval_receipt_ref: StorageRef;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.evidence_package_claim_support_underived
validation.claim_extractor_absent_without_not_checked_status
validation.evidence_package_without_workspace_snapshot
```

### 10.5 Run Board governance, publication, retention, matter firewall

Record privately. Publish selectively. Matter firewall is applied before visibility.

```ts
type RunBoardEventClass =
  | "module_lifecycle"
  | "artifact_event"
  | "side_effect_event"
  | "error_retry"
  | "gate_decision"
  | "evaluation_finding"
  | "repair_instruction"
  | "source_update"
  | "user_comment"
  | "task_agent_recommendation"
  | "cost_duration"
  | "run_lifecycle";

interface RunBoardGovernanceEnvelope {
  data_class: "public" | "internal" | "privileged" | "local_only";
  taint_class: TaintClass;
  privileged: boolean;
  matter_id?: string;
  policy_decision_refs: PolicyEvaluationRef[];
  visibility_scope:
    | "private_audit_only"
    | "same_module"
    | "same_segment"
    | "same_matter_modules"
    | "selected_participants"
    | "user_only";
  redaction_required: boolean;
  schema_version: "1.0";
}

interface RunBoardPublicationPolicy {
  policy_id: string;
  auto_publish_event_classes: RunBoardEventClass[];
  max_visible_posts_per_run: number;
  suppress_data_classes: Array<"privileged" | "local_only">;
  publish_redacted_stub_when_suppressed: boolean;
  rate_limit_per_minute: number;
  schema_version: "1.0";
}

interface RunBoardAuditEvent {
  event_id: string;
  task_id: string;
  run_id: string;
  event_class: RunBoardEventClass;
  payload_ref: StorageRef;
  governance: RunBoardGovernanceEnvelope;
  event_seq: number;
  created_at: ISO8601;
  schema_version: "1.0";
}

interface RunBoardVisiblePost {
  post_id: string;
  source_event_id: string;
  rendered_payload_ref: StorageRef;
  redacted: boolean;
  withheld_reason?: "privileged" | "local_only" | "volume_cap" | "matter_firewall" | "policy";
  lifecycle_state: "active" | "superseded" | "retracted";
  created_at: ISO8601;
  schema_version: "1.0";
}
```

Matter firewall rule:

```ts
RULE forum_matter_firewall:
  A post with matter_id == X is visible only to readers operating under matter_id == X.
  visibility scopes within the matter; it never expands across matters.
  privileged:true is always matter-scoped at every access tier.
```

Required lints:

```ts
validation.run_board_event_without_governance
validation.visible_post_cross_matter_leak
validation.suppressed_event_without_audit_stub
validation.forum_post_cross_matter_leak
```

### 10.6 TaskRunContextPacket request/receipt/omission model

```ts
type TaskContextAudience =
  | "module"
  | "sub_agent"
  | "task_agent"
  | "user"
  | "forum";

interface TaskRunContextPacketRequest {
  request_id: string;
  task_id: string;
  run_id: string;
  audience: TaskContextAudience;
  requested_max_tokens: number;
  required_item_refs: StorageRef[];
  optional_item_refs: StorageRef[];
  staleness_policy:
    | "latest_only"
    | "allow_stale_with_warning"
    | "block_if_stale";
  governance: GovernanceEnvelope;
  schema_version: "1.0";
}

interface OmittedPacketItem {
  item_ref: StorageRef;
  omission_reason:
    | "token_budget"
    | "governance_filtered"
    | "stale"
    | "not_relevant"
    | "unavailable";
  required: boolean;
  schema_version: "1.0";
}

interface TaskRunContextPacketAssemblyReceipt {
  receipt_id: string;
  request_id: string;
  packet_content_hash: string;
  actual_token_count: number;
  omitted_items: OmittedPacketItem[];
  valid_until_event_seq?: number;
  invalidated_by_event_kinds: string[];
  governance: GovernanceEnvelope;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

### 10.7 Feedback-to-prompt responsibility matrix

This closes the thin Grok §3.3 gap: typed ports are not enough; ownership from feedback production through prompt rendering must be explicit.

```ts
interface FeedbackToPromptResponsibilityMatrixRow {
  stage:
    | "feedback_production"
    | "feedback_routing"
    | "feedback_dispatch"
    | "consumption_receipt"
    | "doc24_context_selection"
    | "doc15_prompt_rendering"
    | "module_prompt_consumption";

  owning_doc: OwnerDoc;
  owning_component: string;

  input_type_refs: string[];
  output_type_refs: string[];

  required_receipt_or_event_type?: string;

  governance_preserved: boolean;
  taint_checked: boolean;
  empty_state_behavior: string;
  degraded_state_behavior: string;
  error_state_behavior: string;

  schema_version: "1.0";
}
```

Required lints:

```ts
validation.feedback_to_prompt_stage_unowned
validation.feedback_to_prompt_governance_lost
validation.feedback_to_prompt_missing_receipt
```

### 10.8 Task Agent forum-surface ownership and task-scoped forum

```ts
interface TaskAgentForumSurfaceOwnership {
  surface_id: string;
  surface_kind:
    | "task_forum_room"
    | "run_board_thread"
    | "module_assistance_room"
    | "task_agent_advisory_panel";

  canonical_owner_doc: OwnerDoc;
  participant_model_ref: StorageRef;
  post_model_ref: StorageRef;

  task_agent_role:
    | "participant"
    | "moderator"
    | "advisory_panel"
    | "not_allowed";

  may_create_rooms: boolean;
  may_post_to_run_board: boolean;
  may_mutate_task_graph: false;

  schema_version: "1.0";
}

type ForumScope =
  | "run"
  | "task"
  | "matter"
  | "template";

interface ForumScopePolicy {
  room_id: string;
  forum_scope: ForumScope;

  task_id?: string;
  run_id?: string;
  matter_id?: string;
  template_id?: string;

  persistence_policy:
    | "run_lifetime"
    | "task_lifetime"
    | "matter_lifetime"
    | "template_lifetime";

  cross_run_visibility:
    | "none"
    | "same_task_only"
    | "same_matter_only";

  governance: GovernanceEnvelope;

  schema_version: "1.0";
}
```

Required lints:

```ts
validation.task_agent_forum_surface_duplicate_without_owner
validation.task_agent_forum_surface_allows_graph_mutation
validation.task_scoped_forum_without_scope_policy
validation.run_forum_used_for_cross_run_task_memory
validation.forum_scope_matter_mismatch
```

### 10.9 BoardDigest ResearchNeed import

```ts
interface BoardDigestResearchNeedRef {
  research_need_ref: StorageRef; // Source Workspace §6 ResearchNeed
  source_workspace_ref: string;
  need_status_at_digest_time:
    | "open"
    | "leased"
    | "human_needed"
    | "answered"
    | "unresolved";
  included_reason: string;
  schema_version: "1.0";
}
```

Required lint:

```ts
validation.board_digest_research_need_ref_without_source_workspace_import
```

---

## 11. §G — Professional Reliance Layer

### 11.1 Architectural ruling

Keep §G. It is a deliberate feature and the product capstone. But it must be implemented as a derived/read-model layer over canonical events, receipts, findings, source records, policy decisions, and revision records.

Normative rule:

```text
RULE professional_reliance_layer_no_new_truth:

Professional Reliance Layer artifacts may summarize, project, certify,
or package existing task evidence, findings, receipts, source records,
policy decisions, and revision records.

They MUST NOT create independent substantive truth.

Any status field in §G, including reliance_status, support_status,
task_health_status, certification_status, and review_status, MUST be
derived from an input_manifest and a derivation policy, or marked
manual_human_label with a receipt.
```

Required lints:

```ts
validation.reliance_layer_status_underived
validation.reliance_layer_artifact_without_input_manifest
validation.reliance_layer_creates_substantive_truth
validation.reliance_layer_command_without_registry_entry
```

### 11.2 Reliance lifecycle, manifest, derivation, and invalidation

```ts
type RelianceArtifactLifecycleState =
  | "draft"
  | "ready_for_review"
  | "user_reviewed"
  | "issued"
  | "superseded"
  | "invalidated"
  | "archived";

type RelianceStatus =
  | "safe_to_rely_within_scope"
  | "rely_with_limitations"
  | "not_safe_to_rely"
  | "human_review_required";

type RelianceLimitationKind =
  | EvaluationLimitationKind
  | "unchecked_claims_present"
  | "stale_source_present"
  | "unresolved_research_need"
  | "unreviewed_candidate_revision"
  | "policy_warning"
  | "external_side_effect_unverified"
  | "pattern_c_chain_unresolved"
  | "evidence_package_missing";

interface RelianceInputManifest {
  final_artifact_refs: StorageRef[];
  evaluation_chain_ids: string[];
  evaluation_chain_resolution_receipt_refs: StorageRef[];
  evaluation_snapshot_refs: StorageRef[];

  source_workspace_snapshot_refs: StorageRef[];
  evidence_package_refs: StorageRef[];
  revision_review_packet_refs: StorageRef[];
  hard_call_resolution_refs: StorageRef[];
  policy_decision_refs: PolicyEvaluationRef[];
  budget_narrative_ref?: StorageRef;
  known_good_checkpoint_refs: string[];

  created_from_event_seq: number;
  input_manifest_hash: string;
  schema_version: "1.0";
}

interface RelianceStatusDerivation {
  status: RelianceStatus;
  decisive_input_refs: StorageRef[];

  unresolved_limitations: RelianceLimitationKind[];
  open_blocking_finding_refs: StorageRef[];
  pending_hard_call_refs: StorageRef[];

  required_human_review_refs: StorageRef[];
  scope_statement: string;

  derivation_policy_ref: string;
  formula_eval_receipt_ref?: StorageRef;

  explanation: string;
  schema_version: "1.0";
}

interface TaskReliancePacket {
  packet_id: string;
  task_id: string;
  run_id: string;

  input_manifest: RelianceInputManifest;
  reliance_derivation: RelianceStatusDerivation;

  lifecycle_state: RelianceArtifactLifecycleState;

  generated_by_ref: string;
  reviewed_by_user_ref?: string;
  issued_at?: ISO8601;
  invalidated_by_event_ref?: StorageRef;

  governance: GovernanceEnvelope;

  user_visible_summary: string;
  schema_version: "1.1";
}
```

Derivation rule:

```ts
RULE task_reliance_status_derivation:
  IF pending_hard_call_refs.length > 0:
    status = "human_review_required"

  ELSE IF open_blocking_finding_refs.length > 0:
    status = "not_safe_to_rely"

  ELSE IF unresolved_limitations contains any of:
    "policy_blocked",
    "unable_to_ground_claim",
    "evidence_package_missing",
    "external_side_effect_unverified",
    "pattern_c_chain_unresolved":
    status = "not_safe_to_rely"

  ELSE IF unresolved_limitations.length > 0:
    status = "rely_with_limitations"

  ELSE:
    status = "safe_to_rely_within_scope"
```

Invalidation:

```ts
interface RelianceInvalidationEvent {
  event_id: string;
  packet_id: string;
  invalidation_kind:
    | "artifact_version_changed"
    | "source_workspace_changed"
    | "finding_lifecycle_changed"
    | "policy_decision_superseded"
    | "hard_call_resolution_expired"
    | "evidence_package_superseded"
    | "evaluation_chain_resolution_changed";

  triggering_ref: StorageRef;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.reliance_status_underived
validation.reliance_packet_without_input_manifest
validation.reliance_packet_stale_snapshot
validation.reliance_packet_missing_governance
validation.work_product_certification_without_reliance_packet
```

### 11.3 G-01 — EvaluationContractReview

```ts
interface EvaluationContractReviewCriterionProjection {
  criterion_ref: StorageRef;
  criterion_id: string;
  criterion_label: string;
  required: boolean;
  weight?: number;
  threshold_summary?: string;
  scoring_basis?: string;
  user_visible_summary: string;
  schema_version: "1.0";
}

interface EvaluationContractReview {
  review_id: string;
  task_id: string;
  run_id?: string;

  compiled_plan_ref: StorageRef;
  interpreted_goal: string;

  criterion_projections: EvaluationContractReviewCriterionProjection[];
  threshold_summary: string[];

  source_requirements: string[];
  required_capabilities: CapabilityRef[];
  hard_call_triggers: HardRevisionCallKind[];

  material_differences_from_preview?: string[];

  user_approval_required: boolean;
  approval_status:
    | "pending"
    | "approved"
    | "rejected"
    | "edited"
    | "waived_by_policy";

  approval_ref?: StorageRef;

  governance: GovernanceEnvelope;

  created_at: ISO8601;
  schema_version: "1.1";
}
```

Required lint:

```ts
validation.evaluation_contract_review_criterion_projection_drift
```

### 11.4 G-02 — RevisionReviewPacket and decision receipts

```ts
type SemanticDiffArtifactKind =
  | "text_semantic_diff"
  | "structured_artifact_diff"
  | "source_citation_diff"
  | "format_only_diff"
  | "multi_artifact_diff";

interface SemanticDiffArtifact {
  diff_id: string;
  diff_kind: SemanticDiffArtifactKind;
  before_artifact_version_ref: StorageRef;
  after_candidate_artifact_version_ref: StorageRef;
  changed_scope_refs: ArtifactScopeRef[];
  summary: string;
  machine_readable_diff_ref?: StorageRef;
  user_visible_diff_ref: StorageRef;
  schema_version: "1.0";
}

interface RevisionReviewFindingChangeMapEntry {
  finding_id: string;
  finding_event_ref: StorageRef;
  revision_plan_step_ids: string[];
  changed_scope_refs: ArtifactScopeRef[];
  resolution_claim:
    | "fully_resolves"
    | "partially_resolves"
    | "does_not_resolve"
    | "introduces_tradeoff";
  explanation: string;
  schema_version: "1.0";
}

type RevisionReviewPacketState =
  | "generated"
  | "review_pending"
  | "accepted"
  | "rejected"
  | "forked"
  | "changes_requested"
  | "restored_known_good"
  | "superseded";

interface RevisionReviewPacket {
  packet_id: string;
  task_id: string;
  run_id: string;

  revision_plan_ref: StorageRef;

  before_artifact_version_ref: StorageRef;
  candidate_artifact_version_ref: StorageRef;

  semantic_diff_ref: StorageRef;

  finding_to_change_map: RevisionReviewFindingChangeMapEntry[];

  preservation_constraint_result_refs: StorageRef[];
  source_changes: SourceRecordRef[];
  revalidation_result_refs: StorageRef[];

  regression_risk_summary: string;

  lifecycle_state: RevisionReviewPacketState;

  governance: GovernanceEnvelope;

  created_at: ISO8601;
  schema_version: "1.1";
}

interface RevisionReviewDecisionReceipt {
  receipt_id: string;
  packet_id: string;

  action:
    | "accept"
    | "reject"
    | "fork"
    | "request_changes"
    | "restore_known_good_state"
    | "no_user_review_required";

  actor_ref: string;
  rationale?: string;
  resulting_candidate_state?: ArtifactVersionState;
  command_ref?: string;

  created_at: ISO8601;
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.revision_review_packet_contains_current_action
validation.review_decision_without_receipt
validation.revision_review_change_map_missing_finding_id
validation.semantic_diff_artifact_kind_unregistered
```

### 11.5 G-03 — EvidencePackage

```ts
interface EvidencePackageClaimEntry {
  claim_ref: ClaimRef;
  supporting_anchor_refs: StorageRef[];
  contradicting_anchor_refs: StorageRef[];
  support_status: ClaimSupportStatus;
  support_derivation_receipt_ref?: StorageRef;
  not_checked_reason?:
    | "claim_extractor_unavailable"
    | "evidence_anchor_unavailable"
    | "policy_filtered"
    | "outside_scope";
  schema_version: "1.0";
}

interface EvidencePackage {
  evidence_package_id: string;
  task_id: string;
  run_id: string;

  final_artifact_refs: StorageRef[];
  source_workspace_snapshot_ref: StorageRef;

  source_record_refs: SourceRecordRef[];
  evidence_anchor_refs: StorageRef[];

  claim_support_map: EvidencePackageClaimEntry[];

  unresolved_research_need_refs: string[];
  stale_or_unverified_source_refs: SourceRecordRef[];

  extractor_status:
    | "available"
    | "unavailable_all_claims_not_checked"
    | "partial";

  governance: GovernanceEnvelope;

  created_at: ISO8601;
  schema_version: "1.1";
}
```

### 11.6 G-04 — KnownGoodCheckpoint

Replace `KnownGoodState` with a restorable checkpoint that includes graph, policy, capability, event sequence, and irreversible side effects.

```ts
interface KnownGoodCheckpoint {
  checkpoint_id: string;
  task_id: string;
  run_id: string;
  label: string;

  artifact_head_refs: StorageRef[];
  artifact_version_refs: StorageRef[];
  source_workspace_snapshot_refs: StorageRef[];
  run_workspace_snapshot_ref?: StorageRef;

  graph_topology_snapshot_ref: StorageRef;
  policy_snapshot_ref: StorageRef;
  capability_snapshot_ref: StorageRef;
  event_seq: number;

  irreversible_side_effect_refs: StorageRef[];

  created_by_ref: string;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.known_good_checkpoint_missing_policy_snapshot
validation.restore_checkpoint_ignores_irreversible_side_effects
```

### 11.7 G-05 / G-09 — BudgetNarrative and pre-run forecast

```ts
interface TaskRunCostForecast {
  forecast_id: string;
  task_id: string;
  run_id?: string;
  planned_cost_vector_ref: StorageRef;
  confidence: "calibrated" | "uncalibrated" | "experimental";
  forecast_basis_refs: StorageRef[];
  created_at: ISO8601;
  schema_version: "1.0";
}

interface BudgetNarrative {
  budget_narrative_id: string;
  task_id: string;
  run_id: string;

  planned_forecast_ref?: StorageRef;
  actual_cost_record_refs: StorageRef[];

  summary: string;

  logical_llm_calls: number;
  infrastructure_retries: number;
  local_compute_seconds: number;

  external_tool_cost_vector_ref?: StorageRef;
  doc24_packet_assembly_cost_ref?: StorageRef;
  source_research_cost_ref?: StorageRef;

  skipped_optional_helpers: string[];
  preserved_non_degradable_modes: string[];
  degraded_modes_used: string[];

  forecast_vs_actual_summary: string;
  quality_impact_summary: string;

  governance: GovernanceEnvelope;

  created_at: ISO8601;
  schema_version: "1.1";
}
```

### 11.8 G-07 / G-13 — AttentionLedger and FindingsInbox

```ts
interface AttentionLedgerItem {
  item_id: string;
  task_id: string;
  run_id?: string;

  attention_kind:
    | "hard_call_pending"
    | "blocked_item"
    | "contested_finding"
    | "approval_required"
    | "research_need_human"
    | "reliance_decay"
    | "policy_block";

  target_ref: StorageRef;
  summary: string;
  priority: "low" | "medium" | "high" | "blocking";

  command_ref?: string;

  lifecycle_state:
    | "open"
    | "in_progress"
    | "resolved"
    | "dismissed"
    | "superseded";

  governance: GovernanceEnvelope;

  created_at: ISO8601;
  resolved_at?: ISO8601;
  schema_version: "1.0";
}

interface FindingsInboxQuery {
  matter_id?: string;
  severity_filter?: Array<"low" | "medium" | "high" | "blocking">;
  state_filter?: FindingState[];
  include_contested: boolean;
  include_resolved: boolean;
  schema_version: "1.0";
}
```

### 11.9 G-08 / G-12 / G-14 / G-15 / G-20 — derived UI surfaces

Each UI surface needs a standard surface contract.

```ts
type SurfaceState =
  | "loading"
  | "ready"
  | "empty"
  | "degraded"
  | "blocked"
  | "error";

interface DerivedSurfaceContract {
  surface_id: string;
  surface_kind:
    | "TaskHealthCard"
    | "WorkProductCertification"
    | "RunDiff"
    | "DecisionAuditView"
    | "UnifiedEvaluationChainView"
    | "FindingsInbox"
    | "AttentionLedger";

  read_model_kind: DerivedReadModelRecord["read_model_kind"];
  owning_doc: OwnerDoc;

  loading_state_behavior: string;
  empty_state_behavior: string;
  degraded_state_behavior: string;
  blocked_state_behavior: string;
  error_state_behavior: string;

  command_refs: string[];
  telemetry_event_kinds: string[];
  inspector_route_ref?: string;

  safe_label_policy:
    | "must_show_stale_badge"
    | "must_show_governance_badge"
    | "must_show_reliance_status"
    | "none";

  schema_version: "1.0";
}
```

Required lints:

```ts
validation.g_surface_action_without_command
validation.g_surface_missing_empty_state
validation.g_surface_missing_degraded_state
validation.g_surface_missing_error_state
validation.g_surface_missing_read_model
```

### 11.10 G-17 — TaskRunFork and side-effect ledger

```ts
interface TaskRunFork {
  fork_id: string;
  parent_run_id: string;
  forked_from_checkpoint_ref: string;
  new_run_id: string;
  fork_reason: string;

  irrevocable_side_effects_at_fork: Array<{
    side_effect_id: string;
    kind: string;
    executed_at: ISO8601;
    note: "not_reversible_in_fork";
  }>;

  created_at: ISO8601;
  schema_version: "1.0";
}
```

### 11.11 G-18 — ExplanationTrace without hidden chain-of-thought

```ts
interface ExplanationTrace {
  trace_id: string;
  trace_kind: "evaluation" | "revision" | "routing" | "reliance";
  causal_steps: Array<{
    step_id: string;
    input_refs: StorageRef[];
    operation_receipt_ref?: StorageRef;
    output_refs: StorageRef[];
    rationale_summary: string;
    evidence_refs: StorageRef[];
  }>;
  hidden_reasoning_included: false;
  schema_version: "1.0";
}
```

Required lint:

```ts
validation.explanation_trace_contains_hidden_reasoning
```

### 11.12 G-19 — TaskReplay modes and divergence

Do not promise deterministic replay when LLMs, tools, web/API sources, provider logs, and external state are involved.

```ts
type TaskReplayMode =
  | "audit_reconstruction"
  | "deterministic_reexecution"
  | "best_effort_rerun"
  | "simulation_from_recorded_outputs";

interface TaskReplayRequest {
  replay_request_id: string;
  task_id: string;
  source_run_id: string;
  replay_mode: TaskReplayMode;

  checkpoint_ref?: StorageRef;
  known_good_checkpoint_ref?: string;

  allow_external_side_effects: false;
  allow_external_queries: boolean;
  model_reexecution_policy:
    | "reuse_recorded_outputs"
    | "same_model_if_available"
    | "current_equivalent_model";

  created_at: ISO8601;
  schema_version: "1.0";
}

interface ReplayDivergenceRecord {
  divergence_id: string;
  replay_request_id: string;

  divergence_kind:
    | "model_output_drift"
    | "tool_output_drift"
    | "source_state_changed"
    | "policy_changed"
    | "capability_unavailable"
    | "non_replayable_side_effect";

  source_step_ref: StorageRef;
  original_output_hash?: string;
  replay_output_hash?: string;
  explanation: string;

  created_at: ISO8601;
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.replay_attempts_external_side_effect
validation.deterministic_replay_with_nondeterministic_step
validation.replay_divergence_unrecorded
```

### 11.13 §G command registry entries

```ts
interface RelianceLayerCommandRegistryEntry {
  command_id:
    | "reliance.issue_work_product_certification"
    | "reliance.invalidate_packet"
    | "revision_review.accept_candidate"
    | "revision_review.reject_candidate"
    | "revision_review.request_changes"
    | "revision_review.restore_known_good"
    | "evidence.export_package"
    | "finding.contest"
    | "finding.confirm"
    | "task_replay.preview"
    | "task_replay.create_fork"
    | "attention.resolve_item";

  request_schema_ref: SchemaRef;
  response_schema_ref: SchemaRef;

  durable_write:
    | "required"
    | "none"
    | "explicit_no_op";

  required_policy_checks: string[];
  idempotency_key_required: boolean;
  read_model_invalidations: DerivedReadModelRecord["read_model_kind"][];

  empty_state_behavior: string;
  blocked_state_behavior: string;
  degraded_state_behavior: string;
  error_state_behavior: string;

  owning_doc: OwnerDoc;
  schema_version: "1.0";
}
```

### 11.14 Reliance decay monitoring

This is a new product row. It makes prior work product decay when sources, findings, or policies change.

```ts
type RelianceDecayTriggerKind =
  | "source_overruled"
  | "source_amended"
  | "source_superseded"
  | "source_verification_failed"
  | "source_freshness_expired"
  | "policy_decision_superseded"
  | "finding_lifecycle_changed"
  | "artifact_version_changed";

interface RelianceDecayMonitorPolicy {
  policy_id: string;
  monitored_source_kinds: SourceRecord["source_kind"][];
  monitored_reliance_statuses: RelianceStatus[];
  trigger_kinds: RelianceDecayTriggerKind[];

  default_action:
    | "flag_attention_ledger"
    | "invalidate_reliance_packet"
    | "require_recheck_before_reuse"
    | "silent_audit_only";

  notification_threshold:
    | "any_degradation"
    | "safe_to_limited_or_worse"
    | "safe_to_not_safe"
    | "human_review_required";

  schema_version: "1.0";
}

interface RelianceDecayEvent {
  event_id: string;
  task_id: string;
  run_id?: string;

  trigger_kind: RelianceDecayTriggerKind;
  triggering_ref: StorageRef;

  affected_reliance_packet_refs: StorageRef[];
  prior_status: RelianceStatus;
  new_status: RelianceStatus;

  decay_reason: string;
  attention_ledger_item_ref?: StorageRef;

  created_at: ISO8601;
  schema_version: "1.0";
}
```

Required lints:

```ts
validation.source_change_without_reliance_decay_check
validation.reliance_packet_reused_after_decay_without_recheck
```

### 11.15 DelegationEnvelope

This composes EvaluationContractReview, AutonomousModePolicy, BudgetNarrative, and AttentionLedger into scoped autonomy.

```ts
type DelegationScope =
  | "single_run"
  | "task"
  | "matter"
  | "template"
  | "timeboxed_batch";

interface DelegationEnvelope {
  delegation_id: string;

  task_id?: string;
  run_id?: string;
  matter_id?: string;

  scope: DelegationScope;

  authorized_by_user_ref: string;
  authorized_at: ISO8601;
  expires_at?: ISO8601;

  evaluation_contract_review_ref: StorageRef;
  autonomous_mode_policy_ref: StorageRef;

  budget_cap_ref?: StorageRef;
  allowed_cost_vector_ref?: StorageRef;

  permitted_actions: Array<
    | "evaluate"
    | "revise_candidate"
    | "source_research"
    | "forum_assistance"
    | "generate_evidence_package"
    | "prepare_but_not_send_external_effect"
  >;

  prohibited_actions: Array<
    | "external_message_send"
    | "filing_or_submission"
    | "memory_promotion"
    | "library_promotion"
    | "privileged_export"
  >;

  escalation_triggers: Array<
    | "hard_call"
    | "budget_threshold_hit"
    | "source_conflict"
    | "policy_block"
    | "external_side_effect_required"
    | "reliance_status_not_safe"
    | "unrecoverable_error"
  >;

  revocation_status: "active" | "revoked" | "expired" | "superseded";
  revoked_by_user_ref?: string;
  revoked_at?: ISO8601;

  governance: GovernanceEnvelope;

  schema_version: "1.0";
}
```

Required lints:

```ts
validation.autonomous_action_without_delegation_envelope
validation.delegation_envelope_budget_missing_for_costly_run
validation.delegation_envelope_allows_irreversible_action_without_explicit_permission
validation.delegation_envelope_expired_but_active
```

---

## 12. Completeness findings and added rows

### 12.1 Dedup completeness

The adjudication card is broadly complete against the source review, but the following issues must be added or made explicit:

1. **Claude D19:** Task Agent appears in two forum-shaped surfaces. Add `TaskAgentForumSurfaceOwnership`.
2. **Claude D20:** Forum is run-scoped only; task-scoped forum substance was cited but not addressed. Add `ForumScopePolicy`.
3. **Grok §3.3:** End-to-end feedback→prompt responsibility matrix not covered by port typing alone. Add `FeedbackToPromptResponsibilityMatrixRow`.
4. **Grok §5.7:** Sub-agent advice metrics are named but lack observation schemas. Add `SubAgentAdviceMetricObservation`.
5. **Grok §5.9:** BoardDigest references Source Workspace `ResearchNeed` without import. Add `BoardDigestResearchNeedRef`.
6. **B-24 citation typo:** B-24 is Grok §4.9, not §4.10.
7. **B-03 attribution nuance:** B-03 is Source Workspace write safety; artifact write safety was already partially covered.

### 12.2 Wrong merges / wrong splits

Rows to merge:

```text
A-08 + B-23 → FeedbackRoutingResolutionPolicy
B-05 + B-06 + B-20 → cascade convergence / dependency quiescence family
D-07 + D-09 + D-12 + D-24 → Run Board governance/publication/retention/matter firewall
D-06 + G-03 → evidence anchors and claim-support derivation
G-05 + G-09 → pre-run cost forecast + BudgetNarrative reconciliation
```

Rows to cut or mark already present:

```text
A-11 → already present; value is calibration.
B-15 → wrong owner; DOC12/OP-A owns plan_review.
B-25 → false positive as missing field; replace with dependency canonicalization.
BlockingAuthorityBasis → duplicate enum; cut.
Forked EvaluationAuthorityBasis → cut; import FD canonical enum.
Broad NoVerdictReason union → do not promote until R203 checked; use alias registry.
Embedded attempts on SufficiencyDetectionResult → cut; use RevisorTerminationLedger.
Universal FormulaEvaluationReceipt → scope by FormulaReceiptPolicy.
Standalone SourceTrustBasis → derive from SourceRecord retrieval lineage.
estimated_lock_duration_ms → replace with lock_contention_score / cost proxy.
```

---

## 13. Cut-or-keep final judgment

### 13.1 Cut / decline

1. **A-11 as a fix row.** Keep cross-reference only.
2. **B-15 local Task Forum registry fix.** Keep DOC12/OP-A obligation.
3. **B-25 missing-dependency-field row.** Replace with B-25R canonicalization.
4. **D-04 “remove tier 0.”** Keep tier 0 as receipt-only.
5. **`BlockingAuthorityBasis`.** Duplicate; cut.
6. **Forked `EvaluationAuthorityBasis`.** Cut; import canonical FD enum.
7. **Broad `NoVerdictReason` union.** Defer Common promotion until R203 is checked.
8. **Embedded attempt logs in multiple places.** Ledger is canonical.
9. **Universal formula receipts.** Use scoped receipt policy.
10. **Standalone `SourceTrustBasis`.** Derive authority from retrieval lineage.

### 13.2 Keep but modify

1. **A-01/A-05:** final canonical finding package.
2. **A-02/A-03/A-04:** chain resolution with receipt.
3. **A-16/A-17:** repair port closure with sanctioned DirectFixStep exception.
4. **B-03/D-16:** Source Workspace operation API.
5. **B-16:** deterministic tie-breaker using lock-contention/cost proxy.
6. **B-24:** thin detector, richer triggers, single ledger.
7. **C-01-C-10:** math rows all valuable, but require derivation receipts, finite-number policies, zero-denominator/censoring rules, and fixtures.
8. **D-01:** taint/source authority defaults, derived from retrieval lineage.
9. **D-13:** cross-run RunGuidance injection and contested check.
10. **§G:** keep whole layer, harden as derived/read-model layer.

### 13.3 Add

1. `StructuralAdmissionRecord`.
2. `SpecObjectAdmissionRegistryEntry`.
3. `LintRegistryEntry`.
4. `GovernanceEnvelope`.
5. `SchemaReferenceValidationRule`.
6. `DerivedReadModelRecord` + `ReadModelInvalidationSpec`.
7. `RevisorTerminationLedger`.
8. `WorkspaceExternalizationPolicy` + receipt.
9. `EvaluationChainResolutionReceipt`.
10. `FormulaReceiptPolicy`, `FormulaEvaluationReceipt`, `MetricObservation`, `MetricRollup`.
11. `SourceAuthorityAssessment`.
12. `RelianceDecayMonitorPolicy` and `RelianceDecayEvent`.
13. `DelegationEnvelope`.
14. `FeedbackToPromptResponsibilityMatrixRow`.
15. `TaskAgentForumSurfaceOwnership`.
16. `ForumScopePolicy`.
17. `SubAgentAdviceMetricObservation`.
18. `BoardDigestResearchNeedRef`.

---

## 14. Conformance fixtures

Add these fixture classes to §G-21 / runtime QA.

```ts
type AddendaBFixtureKind =
  | "phantom_field_reference"
  | "duplicate_enum_owner"
  | "finding_authority_basis_blocker"
  | "finding_view_governance_drop"
  | "pattern_c_route_conflict"
  | "sufficiency_no_capability"
  | "sufficiency_identical_output_loop"
  | "sufficiency_policy_block"
  | "source_workspace_write_conflict"
  | "external_source_query_privileged"
  | "tier0_claim_support_attempt"
  | "matter_forum_leak"
  | "taint_laundering_through_summary"
  | "formula_nan_output"
  | "zero_weight_criteria"
  | "template_match_missing_component"
  | "calibration_all_one_class"
  | "cost_quantile_bad_sum"
  | "reliance_packet_stale_source"
  | "reliance_status_underived"
  | "deterministic_replay_with_nondeterministic_step";

interface AddendaBConformanceFixture {
  fixture_id: string;
  fixture_kind: AddendaBFixtureKind;
  target_lint_ids: string[];
  input_artifact_refs: StorageRef[];
  expected_result:
    | "passes"
    | "fails_schema_compile"
    | "fails_plan_compile"
    | "fails_dispatch_preflight"
    | "fails_runtime_audit"
    | "fails_post_run_audit";
  expected_error_ids: string[];
  schema_version: "1.0";
}
```

---

## 15. Explicit answers to the red-team prompt’s specific questions

### 15.1 A-01 — does canonical EvaluationFinding unification work?

**Yes, but only with the final event/record/view design and authority/assurance split.** Keeping two same-named `EvaluationFinding` schemas is worse; it guarantees producer/consumer drift. But the card’s original fix was lossy because it collapsed `authority_basis` into `assurance_basis`, which loses `user_instruction`, `saved_criteria`, `human_label`, `multi_reviewer_consensus`, and `model_judgment_only` semantics.

Final answer:

```text
Use:
  EvaluationFindingEvent      immutable emitted evidence
  EvaluationFindingRecord     mutable current-state projection
  FindingLifecycleTransitionReceipt
  FeedbackFindingView         FD projection, governance-preserving

Keep:
  assurance_basis[]           trust/assurance axis
  authority_basis[]           blocker-authority axis, canonical FD enum
  BlockingAuthorityEvaluation audit object

Cut:
  BlockingAuthorityBasis enum
  forked EvaluationAuthorityBasis enum
```

This unification does not break legitimate producers if a migration layer creates both an event and a current record from legacy findings. It does break consumers that directly mutated finding state inside an envelope; that is intentional because those consumers were corrupting audit/replay state.

### 15.2 §G Professional Reliance Layer — does it work?

**Conceptually yes. Implementation needs derivation/invalidation/command registration.** The layer is coherent: EvaluationContractReview prevents task-bar misread before spend; RevisionReviewPacket makes meaning-bearing revisions reviewable; EvidencePackage binds claims to source anchors; KnownGoodCheckpoint makes restore/fork honest; BudgetNarrative explains cost/quality; TaskReliancePacket is the cover memo; WorkProductCertification renders the reliance packet; FindingsInbox and AttentionLedger make user review tractable.

The final constraints are:

```text
1. §G creates no new substantive truth.
2. Every status is derived from an input manifest and derivation policy.
3. Every read model has invalidation rules.
4. Every user action has a command registry entry.
5. Every UI surface declares loading/empty/degraded/blocked/error states.
6. Reliance packets decay when sources, findings, artifacts, or policies change.
7. TaskReplay is not “deterministic” unless all inputs and steps are deterministic.
```

The layer should ship, but only after Layer 1 structural primitives and the math/derivation contracts exist.

### 15.3 B-24 — does the sufficiency detection contract work?

**The idea is essential; the original implementation was too shallow and too Hard-Call-centric.** The final version treats sufficiency detection as a predicate over the current attempt/procedure/capability/evidence/policy state, tied to a single RevisorTerminationLedger. It uses a richer trigger set and terminal routes that distinguish missing information, missing verification, policy block, process gap, unrecoverable state, and human judgment.

Hard Call is correct only when the user can make a meaningful choice. It is not correct for:

```text
missing source           → needs_information / ResearchNeed
missing verification     → needs_verification
missing capability       → unable_to_evaluate + process_gap_out
policy prohibition       → blocked_by_policy unless user may alter policy
identical-output loop    → record attempt, change strategy, then escalate if exhausted
cascade cycle            → process gap / hard call depending on available choices
```

The final schema is the thin `SufficiencyDetectionResult` plus the single `RevisorTerminationLedger` above.

---

## 16. Final implementation recommendation

The next spec draft should be written as a corrected combined package, not two overlapping schema sets. The draft should start with admission rules and structural primitives, then apply row-specific changes.

Recommended table of contents for the R0.4 amendment:

```text
0. Amendment admission and strip-pass rules
1. Universal governance and type ownership
2. Phantom-field lint and lint registry
3. Canonical findings and lifecycle projections
4. Pattern C envelope and chain resolution
5. State/disposition/no-verdict mapping
6. Feedback routing and dispatch expectations
7. Revision execution / termination ledger
8. Sufficiency detection and loop guards
9. Source Workspace API and externalization policy
10. Math/formula registry, receipts, and fixtures
11. Source authority, taint, evidence, and tiering
12. Forum/board governance and matter firewall
13. Professional Reliance Layer
14. UI/command/surface registration obligations
15. Conformance fixtures and OP-A closure
```

The most important implementation discipline is: **every new status field is either derived, receipt-backed, or explicitly a human label.** If that is enforced, the Addenda B family becomes much harder for a coding agent to misread.

---

## 17. Appendix — proposals explicitly not adopted

These appeared in earlier drafts or the card but should not enter the final spec package:

```text
Do not add BlockingAuthorityBasis.
Do not fork EvaluationAuthorityBasis.
Do not use cross_calibration as LearningMode.
Do not add a local Task Forum RoomKind.plan_review registry.
Do not replace the existing RevisionPlanStepBase with a minimal base.
Do not remove tier 0 from the documentation model.
Do not let tier 0 support downstream claims.
Do not embed attempt logs both in SufficiencyDetectionResult and RevisorTerminationLedger.
Do not create a standalone SourceTrustBasis orphan axis.
Do not require FormulaEvaluationReceipt for transient in-flight arithmetic.
Do not use created_at as concurrency tiebreaker.
Do not use estimated_lock_duration_ms unless a real estimator exists.
Do not promise deterministic TaskReplay for nondeterministic steps.
Do not allow §G read models to create new substantive truth.
```


---

## 18A. Audit correction appendix — accepted row details that were under-captured in the first final handoff

### 18A.0 Audit finding

A self-audit of this final handoff found that the main body correctly captures the final reconciled architecture, the disposition flips, the structural strip pass, A-01/A-05, B-24, the math/derivation layer, Source Workspace API, §G hardening, and Claude's final corrections. However, it under-captured several accepted-but-not-materially-modified rows from the adjudication card and earlier review passes. Those rows were treated as “accepted as in the card,” but the user's requested deliverable was a single comprehensive document with all final settled recommendations and paste-ready inclusions. This appendix fills that gap.

This appendix does **not** undo the final reconciled rulings above. It adds the exact settled schemas/contracts/lints for rows that remain accepted and should still be included in the next spec draft.

---

### 18A.1 A-18 — feedback-bundle emission matrix and absence reasons

The main body captures routing resolution but did not preserve the explicit feedback-bundle emission discipline. Add this to Feedback Delivery §1.2 / §2.3.

```ts
type EvaluationProducerKind =
  | "outcome_evaluator"
  | "judge"
  | "deterministic_scorer";

type FeedbackBundleEmissionRule =
  | "always"
  | "on_failure_only"
  | "never";

type FeedbackBundleAbsentReason =
  | "not_emitted_by_design"
  | "not_applicable"
  | "policy_filtered"
  | "producer_failed_before_bundle"
  | "suppressed_by_privacy_policy";

interface FeedbackEmissionMatrixEntry {
  producer_kind: EvaluationProducerKind;
  verdict: OutcomeVerdict;
  emits_envelope: true;
  emits_feedback_bundle: FeedbackBundleEmissionRule;
  required_absent_reason_when_missing: boolean;
  schema_version: "1.0";
}

interface EvaluationResultEmissionRecord {
  result_id: string;
  envelope_ref: StorageRef;
  feedback_bundle_ref?: StorageRef;
  feedback_bundle_absent_reason?: FeedbackBundleAbsentReason;
  emission_matrix_entry_ref: StorageRef;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

```ts
validation.feedback_bundle_absence_unexplained
validation.feedback_emission_matrix_missing_producer_verdict
validation.feedback_bundle_emitted_against_matrix
```

Normative rule:

```text
Every evaluation result MUST produce an EvaluationResultEmissionRecord. A missing feedback bundle is valid only when the producer/verdict row permits absence and feedback_bundle_absent_reason is populated.
```

---

### 18A.2 B-01 — RevisionExecutionLifecycle FSM

The main body added the termination ledger, but it did not preserve the base execution FSM row. Add this to V3.3.1 §11.0.

```ts
type RevisionExecutionLifecycleState =
  | "plan_compiled"
  | "dispatch_preflight"
  | "dispatched"
  | "step_waiting_dependency"
  | "step_running"
  | "step_receipt_received"
  | "parallel_batch_finalizing"
  | "revalidating"
  | "cascade_running"
  | "hard_call_pending"
  | "cancel_requested"
  | "cancelled"
  | "terminal_satisfied"
  | "terminal_failed"
  | "terminal_blocked"
  | "terminal_unrecoverable";

type RevisionExecutionLifecycleEventKind =
  | "plan_compiled"
  | "dispatch_preflight_passed"
  | "dispatch_preflight_failed"
  | "step_dispatched"
  | "dependency_satisfied"
  | "step_started"
  | "step_receipt_persisted"
  | "parallel_batch_finalized"
  | "revalidation_started"
  | "revalidation_quiescent"
  | "hard_call_opened"
  | "hard_call_resolved"
  | "cancel_requested"
  | "cancel_acknowledged"
  | "terminal_decision_recorded";

interface RevisionExecutionLifecycleTransition {
  transition_id: string;
  task_id: string;
  run_id: string;
  revision_plan_ref: StorageRef;
  from_state: RevisionExecutionLifecycleState;
  to_state: RevisionExecutionLifecycleState;
  event_kind: RevisionExecutionLifecycleEventKind;
  triggering_receipt_ref?: StorageRef;
  triggering_policy_ref?: PolicyEvaluationRef;
  termination_ledger_ref?: StorageRef;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

```ts
validation.revision_lifecycle_illegal_transition
validation.revision_lifecycle_missing_receipt
validation.revision_lifecycle_terminal_without_ledger
```

Normative rule:

```text
Every §11 runtime path MUST transition through RevisionExecutionLifecycleTransition records. Other §11.x sections may add constraints, but they must not define separate lifecycle state machines.
```

---

### 18A.3 B-07 — parallel batch finalization

The main body mentions cascade/parallel quiescence, but omitted the concrete receipt for sibling outputs after partial batch failure.

```ts
type ParallelSiblingStatus =
  | "completed"
  | "failed"
  | "cancelled"
  | "orphaned";

type ParallelSiblingDisposition =
  | "retained"
  | "discarded"
  | "held_for_review"
  | "rolled_into_candidate"
  | "blocked_by_failed_sibling";

interface ParallelBatchSiblingResult {
  step_id: string;
  status: ParallelSiblingStatus;
  candidate_ref?: StorageRef;
  output_ref?: StorageRef;
  disposition: ParallelSiblingDisposition;
  disposition_reason?: string;
  receipt_refs: StorageRef[];
  schema_version: "1.0";
}

interface ParallelBatchFinalizationReceipt {
  receipt_id: string;
  batch_id: string;
  plan_id: string;
  run_id: string;
  lifecycle_transition_ref?: StorageRef;
  sibling_results: ParallelBatchSiblingResult[];
  batch_outcome:
    | "all_completed"
    | "partial_failure"
    | "aborted"
    | "cancelled";
  downstream_revalidation_policy:
    | "none"
    | "revalidate_successful_siblings"
    | "hold_until_manual_review"
    | "discard_all_sibling_outputs";
  created_at: ISO8601;
  schema_version: "1.0";
}
```

```ts
validation.parallel_batch_failure_without_finalization_receipt
validation.parallel_sibling_candidate_orphaned_without_disposition
validation.parallel_batch_finalized_before_receipts_persist
```

---

### 18A.4 B-09 — candidate lifecycle/head split and side-effect intent candidates

The final document covers workspace externalization, but omitted the generic candidate-vs-head split and side-effect intent candidate model.

```ts
type ArtifactVersionLifecycleState =
  | "candidate"
  | "accepted"
  | "rejected"
  | "superseded"
  | "reverted"
  | "archived";

interface CandidateArtifactVersionRef {
  candidate_id: string;
  artifact_id: string;
  candidate_version_ref: StorageRef;
}

interface ArtifactHead {
  artifact_id: string;
  current_version_ref: StorageRef;
  current_candidate_ref?: CandidateArtifactVersionRef;
  updated_by_receipt_ref: StorageRef;
  updated_at: ISO8601;
  schema_version: "1.0";
}

type SideEffectClass =
  | "external_message_send"
  | "calendar_write"
  | "webhook_post"
  | "filing_or_submission"
  | "memory_write"
  | "library_promotion"
  | "workspace_externalization"
  | "external_source_query";

type SideEffectIntentState =
  | "draft"
  | "approved"
  | "executed"
  | "cancelled"
  | "blocked";

interface SideEffectIntentCandidate {
  side_effect_intent_id: string;
  task_id: string;
  run_id: string;
  side_effect_class: SideEffectClass;
  dry_run_payload_ref: StorageRef;
  approval_status:
    | "not_required"
    | "pending_user_approval"
    | "approved"
    | "rejected";
  execution_policy_ref: StorageRef;
  state: SideEffectIntentState;
  idempotency_key: string;
  execution_receipt_ref?: StorageRef;
  governance: GovernanceEnvelope;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

```ts
validation.candidate_lifecycle_head_pointer_collapsed
validation.side_effect_candidate_without_dry_run
validation.side_effect_candidate_executed_without_approval_when_required
validation.side_effect_intent_replayed_without_policy
```

---

### 18A.5 B-10 — Hard Call blocking scope and task cancellation protocol

The final document referenced Hard Calls but did not preserve the concrete B-10 protocols.

```ts
type HardCallBlockingScope =
  | "entire_run"
  | "segment"
  | "artifact"
  | "outcome"
  | "module"
  | "side_effect_only";

interface HardCallPendingPolicy {
  hard_call_id: string;
  blocking_scope: HardCallBlockingScope;
  blocked_refs: string[];
  allowed_to_continue_refs: string[];
  context_visible_to_continuing_modules:
    | "none"
    | "hard_call_pending_summary"
    | "full_context_redacted";
  on_defer:
    | "continue_with_warning"
    | "pause_scope"
    | "abort_scope";
  on_timeout:
    | "escalate"
    | "abort"
    | "continue_with_warning";
  timeout_ms?: number;
  governance: GovernanceEnvelope;
  schema_version: "1.0";
}

interface TaskCancelProtocol {
  cancel_request_id: string;
  task_id: string;
  run_id: string;
  requested_by_ref: string;
  cancel_scope:
    | "entire_run"
    | "segment"
    | "module_activation"
    | "revision_plan"
    | "side_effect_intent";
  target_refs: string[];
  in_flight_handling:
    | "request_graceful_stop"
    | "preempt_immediately"
    | "finish_current_step_then_stop";
  side_effect_policy:
    | "do_not_cancel_executed_side_effects"
    | "cancel_unexecuted_intents"
    | "create_corrective_artifact";
  candidate_disposition:
    | "discard"
    | "retain_for_manual_review"
    | "orphan_until_reconciled";
  source_workspace_disposition:
    | "retain_records"
    | "mark_records_cancelled"
    | "rollback_if_uncommitted";
  learning_signal_policy:
    | "suppress_success_signals"
    | "emit_cancel_diagnostic_only"
    | "emit_full_signals_with_cancel_flag";
  user_receipt_ref?: StorageRef;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

```ts
validation.hard_call_pending_without_blocking_scope
validation.continuing_module_received_forbidden_hard_call_context
validation.cancel_attempts_to_reverse_executed_side_effect
validation.cancel_without_candidate_disposition
```

---

### 18A.6 B-11 — skip protocol and receipts

```ts
type TaskSkipReason =
  | "not_applicable"
  | "user_directed"
  | "dependency_unavailable"
  | "policy_blocked"
  | "duplicative_work"
  | "degraded_mode";

type TaskSkipDownstreamEffect =
  | "none"
  | "marks_dependents_not_applicable"
  | "requires_human_ack"
  | "emits_upstream_failure"
  | "requires_replan";

interface TaskSkipReceipt {
  skip_id: string;
  target_ref: string;
  skipped_by_ref: string;
  reason: TaskSkipReason;
  downstream_effect: TaskSkipDownstreamEffect;
  policy_decision_refs: PolicyEvaluationRef[];
  created_at: ISO8601;
  schema_version: "1.0";
}
```

```ts
validation.skip_without_receipt
validation.skip_downstream_effect_unhandled
```

---

### 18A.7 B-12 — policy freshness fields

```ts
interface PolicyEvaluationRef {
  policy_decision_id: string;
  policy_ref: string;
  decision: "allow" | "deny" | "allow_with_conditions" | "needs_human_approval";
  issued_at: ISO8601;
  subject_hash: string;
  decision_scope_hash: string;
  superseded_by_decision_id?: string;
  policy_engine_version: string;
  schema_version: "1.1";
}
```

```ts
validation.policy_decision_missing_freshness_fields
validation.policy_decision_superseded_but_used
validation.policy_decision_subject_hash_mismatch
validation.policy_decision_scope_hash_mismatch
```

Normative rule:

```text
Any dispatch, durable write, externalization, side-effect intent, or reliance packet that cites a policy decision MUST verify that superseded_by_decision_id is absent and that subject_hash / decision_scope_hash match the current subject and scope.
```

---

### 18A.8 B-14 — forum deadlock breaker

Task Agent must not decide substantive outcomes. The deadlock breaker can escalate, pause, or choose a safe fallback only through declared policy.

```ts
type ForumNoConsensusAction =
  | "forum_deadlock_hard_call"
  | "pause_scope"
  | "prefer_safest_proposal_with_user_review"
  | "emit_process_gap";

interface ForumDeliberationPolicy {
  room_id: string;
  max_deliberation_ticks: number;
  consensus_threshold_pct: number;
  on_no_consensus: ForumNoConsensusAction;
  task_agent_role_on_deadlock:
    | "recommend_only"
    | "summarize_disagreement"
    | "not_involved";
  timeout_ms?: number;
  schema_version: "1.0";
}
```

```ts
validation.forum_deliberation_without_deadlock_policy
validation.forum_deadlock_allows_task_agent_decision
validation.forum_deadlock_timeout_without_route
```

---

### 18A.9 B-18 / B-19 — Hard Call options and producer of hard_call_resolved receipts

```ts
type HardCallResponseMode =
  | "closed_choice"
  | "freeform_required"
  | "closed_choice_with_other";

interface HumanDecisionOption {
  option_id: string;
  label: string;
  description?: string;
  resulting_route?: SufficiencyTerminalRoute | OutcomeEvaluationDisposition;
  policy_effect_refs?: PolicyEvaluationRef[];
  schema_version: "1.0";
}

interface HardRevisionCall {
  hard_call_id: string;
  response_mode: HardCallResponseMode;
  options: HumanDecisionOption[];
  default_if_no_response?: string;
  pending_policy_ref: StorageRef; // HardCallPendingPolicy
  created_at: ISO8601;
  schema_version: "1.1";
}
```

Normative constraints:

```text
If response_mode == closed_choice, options.length MUST be >= 2.
If response_mode == freeform_required, options MAY be empty, but the UI MUST render a freeform response control and no default_if_no_response may silently choose a substantive option.
```

```ts
interface HardCallResolutionOperationReceipt {
  receipt_id: string;
  operation_kind: "hard_call_resolved";
  hard_call_id: string;
  resolved_by_user_ref: string;
  emitted_by: "dispatcher";
  resolution_ref: StorageRef;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

```ts
validation.hard_call_options_empty_for_closed_choice
validation.freeform_hard_call_missing_text_control
validation.hard_call_resolved_without_dispatcher_receipt
```

---

### 18A.10 B-21 — signal emission after receipt persistence

```ts
interface SignalEmissionPrecondition {
  signal_id: string;
  referenced_receipt_refs: StorageRef[];
  receipt_persistence_check:
    | "all_persisted"
    | "failed_missing_receipt"
    | "failed_unreadable_receipt";
  checked_at: ISO8601;
  schema_version: "1.0";
}
```

Normative rule:

```text
Learning signals, feedback signals, repair-cycle signals, and RunGuidance promotion signals MUST NOT emit until every referenced receipt is durably persisted or the signal explicitly marks itself diagnostic-only with no downstream learning/promotion eligibility.
```

```ts
validation.signal_references_unpersisted_receipt
validation.signal_emitted_without_persistence_check
validation.diagnostic_only_signal_used_for_learning
```

---

### 18A.11 B-22 — Pattern C invocation budget

```ts
interface PatternCInvocationBudget {
  budget_id: string;
  task_id: string;
  run_id?: string;
  max_judge_invocations_per_run?: number;
  cadence:
    | "every_turn"
    | "every_n_turns"
    | "on_terminal_only"
    | "on_conflict_only";
  n_turns?: number;
  max_cost_vector_ref?: StorageRef;
  on_budget_exhausted:
    | "skip_judge_with_warning"
    | "route_to_human_review"
    | "block_pattern_c_chain"
    | "use_evaluator_only";
  schema_version: "1.0";
}
```

```ts
validation.pattern_c_without_invocation_budget
validation.pattern_c_budget_exhausted_without_route
validation.pattern_c_every_n_turns_missing_n
```

---

### 18A.12 C-05 — latency distribution instead of thermal-throttling-sensitive mean

```ts
interface LatencyDistributionSummary {
  p50_duration_ms: number;
  p90_duration_ms: number;
  p99_duration_ms?: number;
  sample_size: number;
  measurement_window: DateRange;
  excluded_outlier_count?: number;
  outlier_policy_ref?: StorageRef;
  schema_version: "1.0";
}

interface CostLatencyFinding {
  finding_id: string;
  subject_ref: StorageRef;
  latency_distribution: LatencyDistributionSummary;
  cost_vector_ref?: StorageRef;
  formula_eval_receipt_ref?: StorageRef;
  created_at: ISO8601;
  schema_version: "1.1";
}
```

```ts
validation.latency_metric_uses_arithmetic_mean_only
validation.latency_distribution_missing_sample_size
validation.latency_distribution_missing_window
```

---

### 18A.13 D-03 — SourceWorkspace identity unification

```ts
interface SourceWorkspaceIdentityRegistryEntry {
  workspace_id: string;
  canonical_type_name: "SourceWorkspace";
  task_source_workspace_view_ref?: StorageRef;
  task_id?: string;
  run_id?: string;
  scope: "run" | "task" | "workspace";
  source_workspace_head_hash: string;
  schema_version: "1.0";
}
```

Normative rule:

```text
TaskSourceWorkspace is a scoped view/parameterization of SourceWorkspace, not a second durable type or store.
```

```ts
validation.dual_source_workspace_identity
validation.task_source_workspace_without_canonical_workspace
```

---

### 18A.14 D-04 — source-tier transition persistence and verification-state alignment

The main body keeps tier 0 as receipt-only. Also retain the transition and verification alignment contracts.

```ts
type SourceDocumentationTier = 0 | 1 | 2 | 3 | 4;

type SourceVerificationState =
  | "not_checked"
  | "verified"
  | "failed_verification"
  | "stale"
  | "superseded"
  | "partially_verified"
  | "verification_not_available";

interface SourceTierTransition {
  transition_id: string;
  source_id: string;
  from_tier: SourceDocumentationTier;
  to_tier: SourceDocumentationTier;
  transition_kind:
    | "promotion"
    | "demotion"
    | "materialization"
    | "archive"
    | "restore";
  reason: string;
  actor_ref: string;
  cleared_by_access_tier?: "owner" | "matter_team_access" | "read_only";
  policy_decision_refs: PolicyEvaluationRef[];
  created_at: ISO8601;
  schema_version: "1.0";
}
```

```ts
validation.source_tier_transition_not_persisted
validation.source_tier_transition_tier_out_of_domain
validation.source_tier_demotion_without_authority
validation.source_verification_state_unmapped
```

---

### 18A.15 D-06 — domain payload registry and tool-receipt/source-extractor distinction

```ts
interface DomainPayloadRegistryRef {
  domain_payload_kind: string;
  domain_payload_schema_ref: SchemaRef;
  domain_payload_version: string;
  owner_doc: OwnerDoc;
  schema_version: "1.0";
}

type SourceAcquisitionResultKind =
  | "source_record_created"
  | "tool_receipt_only"
  | "claim_extractor_unavailable"
  | "source_unavailable"
  | "policy_blocked";

interface SourceAcquisitionReceipt {
  receipt_id: string;
  result_kind: SourceAcquisitionResultKind;
  source_record_ref?: SourceRecordRef;
  tool_receipt_ref?: StorageRef;
  extractor_status?: "available" | "unavailable" | "partial";
  may_support_downstream_claims: boolean;
  governance: GovernanceEnvelope;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

```ts
validation.domain_payload_without_registry_ref
validation.tool_receipt_used_as_material_source
validation.claim_extractor_unavailable_reported_as_source_unavailable
```

---

### 18A.16 D-10 — ModuleAssistanceRequest and moderator fallback

```ts
type ModuleAssistanceRequestKind =
  | "ask_for_review"
  | "ask_for_missing_input"
  | "ask_for_domain_judgment"
  | "ask_for_process_help"
  | "ask_for_source_help";

type AssistanceRequestTargetKind =
  | "module"
  | "subagent"
  | "task_agent"
  | "user"
  | "forum_room";

interface ModuleAssistanceLease {
  holder_ref: string;
  lease_version: number;
  acquired_at: ISO8601;
  expires_at: ISO8601;
  schema_version: "1.0";
}

interface ModuleAssistanceRequest {
  request_id: string;
  task_id: string;
  run_id: string;
  requester_module_id: string;
  target_kind: AssistanceRequestTargetKind;
  target_ref?: string;
  target_endpoint_ref?: StorageRef;
  request_kind: ModuleAssistanceRequestKind;
  request_payload_ref: StorageRef;
  answer_schema_ref: SchemaRef;
  response_policy:
    | "required_before_continue"
    | "optional_advisory"
    | "timeout_then_continue_with_warning"
    | "timeout_then_escalate";
  lease: ModuleAssistanceLease;
  timeout_ms: number;
  on_timeout:
    | "resume_with_warning"
    | "abort"
    | "escalate_human"
    | "ask_task_agent";
  governance: GovernanceEnvelope;
  created_at: ISO8601;
  schema_version: "1.0";
}

interface ForumModeratorFallbackPolicy {
  room_id: string;
  moderator_ref?: string;
  on_moderator_unavailable:
    | "continue_without_moderator"
    | "pause_room"
    | "ask_task_agent_to_summarize"
    | "escalate_to_user";
  schema_version: "1.0";
}
```

```ts
validation.module_assistance_request_missing_answer_schema
validation.module_assistance_request_missing_lease
validation.module_assistance_timeout_unrouted
validation.moderator_unavailable_without_fallback
```

---

### 18A.17 D-11 / D-12 — BoardDigest selection and board retention/compaction

```ts
type BoardDigestSelectionStrategy =
  | "recency"
  | "severity"
  | "score"
  | "mixed";

interface BoardDigestPolicy {
  policy_id: string;
  included_post_kinds: TaskRunBoardPostKind[];
  included_severity_threshold?: "low" | "medium" | "high" | "blocking";
  max_posts: number;
  selection_strategy: BoardDigestSelectionStrategy;
  include_open_research_needs: boolean;
  include_unresolved_repairs: boolean;
  token_budget: number;
  schema_version: "1.0";
}

interface RunBoardRetentionPolicy {
  policy_id: string;
  retain_event_classes: RunBoardEventClass[];
  retain_for_days: number;
  ec_policy_decision_ref: PolicyEvaluationRef;
  schema_version: "1.0";
}

interface RunBoardCompactionPolicy {
  policy_id: string;
  compact_after_days: number;
  strategy:
    | "summarize"
    | "drop_low_severity"
    | "archive"
    | "retain_full_for_privileged";
  governance_preservation: "preserve_max_governance";
  schema_version: "1.0";
}
```

```ts
validation.board_digest_without_selection_policy
validation.board_digest_over_token_budget
validation.run_board_without_retention_policy
validation.run_board_compaction_drops_governance
```

---

### 18A.18 D-13 — RunGuidance persistence, lifecycle, contested check

```ts
type RunGuidanceLifecycleState =
  | "proposed"
  | "active"
  | "contested"
  | "superseded"
  | "expired"
  | "rejected";

interface RunGuidanceItem {
  guidance_id: string;
  task_id: string;
  originating_run_id: string;
  target_scope:
    | "current_run"
    | "same_task_future_runs"
    | "same_matter"
    | "template";
  guidance_text: string;
  lifecycle_state: RunGuidanceLifecycleState;
  derived_from_finding_refs: string[];
  policy_decision_refs: PolicyEvaluationRef[];
  governance: GovernanceEnvelope;
  created_at: ISO8601;
  expires_at?: ISO8601;
  schema_version: "1.0";
}

interface RunGuidanceLifecycleReceipt {
  receipt_id: string;
  guidance_id: string;
  from_state: RunGuidanceLifecycleState;
  to_state: RunGuidanceLifecycleState;
  reason:
    | "promoted_from_feedback"
    | "user_contested"
    | "user_approved"
    | "superseded_by_new_guidance"
    | "expired_by_policy"
    | "rejected_by_user";
  actor_ref: string;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

```ts
validation.run_guidance_consumed_while_contested
validation.run_guidance_without_lifecycle_receipt
validation.cross_run_guidance_without_governance
validation.run_guidance_without_persistence_owner
```

Normative storage choice:

```text
RunGuidanceItem is written to TaskBlueprint.persistent_guidance[] for local task intent unless deliberately mapped to a DOC24/BDSM learning ledger. Do not write to both without an explicit projection relation.
```

---

### 18A.19 D-14 — injection slot registry, compact cards, command registry, and packet taxonomy

The main body includes §G-specific command registration but omitted the general Addenda B/Core D-14 infrastructure.

```ts
type TaskSystemInjectionSlotKind =
  | "task_opportunity_chip"
  | "saved_task_suggestion"
  | "task_invocation_directive"
  | "module_preset_card"
  | "task_template_card"
  | "run_guidance_card";

interface TaskSystemInjectionSlotRegistration {
  slot_id: string;
  slot_kind: TaskSystemInjectionSlotKind;
  owning_doc: "DOC24" | "DOC23" | "DOC15";
  rendered_by_doc: "DOC15" | "DOC24";
  surfaces: string[];
  token_cap: number;
  pii_redaction_required: boolean;
  on_unavailable:
    | "omit"
    | "degrade_direct_first"
    | "block_explicit_task_route";
  receipt_required: boolean;
  schema_version: "1.0";
}

interface CompactTaskInvocationDirectiveCard {
  card_id: string;
  task_id: string;
  task_template_ref?: StorageRef;
  directive_summary: string;
  confidence: CalibratedScore;
  risk_flags: string[];
  token_estimate: number;
  redaction_state: "not_needed" | "redacted" | "blocked";
  source_authority_ref?: StorageRef;
  schema_version: "1.0";
}

interface CompactTaskTemplateCard {
  card_id: string;
  template_ref: StorageRef;
  template_name: string;
  match_score: CalibratedScore;
  required_inputs_summary: string[];
  expected_outputs_summary: string[];
  risk_flags: string[];
  token_estimate: number;
  schema_version: "1.0";
}

interface CompactModulePresetCard {
  card_id: string;
  module_preset_ref: StorageRef;
  module_kind: string;
  preset_name: string;
  applicability_summary: string;
  risk_flags: string[];
  token_estimate: number;
  schema_version: "1.0";
}

interface TaskCommandRegistryEntry {
  command_id: string;
  request_schema_ref: SchemaRef;
  response_schema_ref: SchemaRef;
  idempotency_key_required: boolean;
  durable_write: "required" | "none" | "explicit_no_op";
  telemetry_event_kind: string;
  read_model_invalidations: DerivedReadModelRecord["read_model_kind"][];
  failure_codes: string[];
  required_policy_checks: string[];
  owning_doc: OwnerDoc;
  schema_version: "1.0";
}

interface AvailableTaskAction {
  action_id: string;
  label: string;
  command_ref: string;
  idempotency_key_required: boolean;
  enabled: boolean;
  disabled_reason?: string;
  schema_version: "1.0";
}

interface TrackedTaskReceipt {
  receipt_id: string;
  task_id: string;
  run_id?: string;
  available_actions: AvailableTaskAction[];
  created_at: ISO8601;
  schema_version: "1.0";
}
```

```ts
validation.task_injection_slot_unregistered
validation.compact_card_missing_token_estimate
validation.task_command_without_registry_entry
validation.tracked_task_receipt_boolean_action_legacy
validation.task_opportunity_packet_missing_token_budget
```

Packet taxonomy:

```text
TaskOpportunityPacket = pre-task opportunity / saved-task context.
TaskRunContextPacket = in-run module context packet.
TaskAgentDesignPacket = future design/proposal packet.
```

---

### 18A.20 D-15 — sub-agent output-contract plurality, fallback, and plan-verifier point

```ts
type AllowedCoordinationPoint =
  | "plan_builder"
  | "plan_verifier"
  | "outcome_evaluator"
  | "source_research"
  | "revision_planner";

interface SubAgentCoordinationProfile {
  profile_id: string;
  allowed_coordination_points: AllowedCoordinationPoint[];
  output_contract_refs: StorageRef[];
  fallback_policies: SubAgentFallbackPolicy[];
  schema_version: "1.0";
}

interface SubAgentFallbackPolicy {
  coordination_point: AllowedCoordinationPoint;
  on_no_sub_agent:
    | "use_primary_module"
    | "skip_with_warning"
    | "hard_call"
    | "degrade_quality_with_note";
  schema_version: "1.0";
}

interface PlanVerifierRequirementPolicy {
  policy_id: string;
  required_when:
    | "plan_risk_score_above_threshold"
    | "privileged_matter"
    | "external_side_effect_present"
    | "high_stakes_outcome";
  threshold?: number;
  on_no_plan_verifier_available:
    | "hard_call"
    | "block_dispatch"
    | "degrade_with_warning";
  schema_version: "1.0";
}
```

```ts
validation.sub_agent_point_without_fallback
validation.sub_agent_output_contract_singular_legacy
validation.plan_verifier_required_but_absent
validation.allowed_coordination_point_count_drift
```

---

### 18A.21 D-17 — anchor and hash hygiene

```ts
interface StructuredAnchor {
  section_id?: string;
  field_path?: string;
  citation_ref?: StorageRef;
  row_id?: string;
  paragraph_id?: string;
  schema_version: "1.0";
}

interface TextAnchor {
  start_offset: number;
  end_offset: number;
  context_before: string;
  context_after: string;
  context_hash: string;
  hash_algorithm: "sha256" | "blake3";
  created_at: ISO8601;
  schema_version: "1.0";
}

interface HardCallHashNormalizationPolicy {
  policy_id: string;
  trim_whitespace: true;
  normalize_unicode: "NFC";
  sort_json_keys: true;
  collapse_internal_whitespace: boolean;
  ignore_cosmetic_fields: string[];
  schema_version: "1.0";
}
```

```ts
validation.structured_anchor_empty
validation.context_hash_uncomputed
validation.context_hash_unverified
validation.hard_call_hash_unnormalized
```

---

### 18A.22 D-18 / D-19 / D-20 / D-21 / D-23 — remaining accepted operational closures

```ts
interface RepeatedFailureStableKey {
  artifact_id: string;
  outcome_definition_id: string;
  finding_match_key_ref: StorageRef;
  schema_version: "1.0";
}

interface SourceRecordCostAttribution {
  source_record_ref: SourceRecordRef;
  acquired_by_module_id: string;
  acquisition_cost_vector_ref?: StorageRef;
  acquisition_cost_estimate_ref?: StorageRef; // legacy projection only
  schema_version: "1.0";
}

interface LibraryPromotionGate {
  gate_id: string;
  min_tier: SourceDocumentationTier;
  requires_verification_state: SourceVerificationState[];
  ec_policy_decision_ref: PolicyEvaluationRef;
  requires_access_tier:
    | "owner"
    | "matter_team_access"
    | "admin";
  emits_candidate_only: boolean;
  schema_version: "1.0";
}

interface BackgroundProgressFields {
  requires_background_execution: boolean; // run/task-level background execution
  emits_progress_heartbeat: boolean;      // module-level heartbeat behavior
  heartbeat_interval_ms?: number;
  schema_version: "1.0";
}

interface FeedbackDispatchExpectation {
  expectation_id: string;
  feedback_bundle_id: string;
  consumer_module_id: string;
  consumer_activation_seq: number;
  expected_receipt_kind: "FeedbackConsumptionReceipt";
  grace_period_ms: number;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

```ts
validation.repeated_failure_keyed_on_version
validation.source_record_missing_cost_attribution
validation.library_promotion_without_gate
validation.requires_background_progress_legacy_overload
validation.feedback_consumed_without_receipt
validation.feedback_dispatch_expectation_missing
validation.repair_cycle_signal_without_consumption_link
```

---

### 18A.23 E-13 — multi-user learning forward-compat fields

The final `GovernanceEnvelope` includes `principal_id` and `learning_scope`, but the actual learning-signal envelope forward-compat fields should also be explicit.

```ts
interface LearningScopeForwardCompatFields {
  principal_id: string;
  learning_scope: "local" | "matter" | "team" | "firm" | "networked";
  scope_inference_basis: string;
  default_scope_rule: string;
  share_eligibility: "none" | "opt_in" | "policy_gated";
  schema_version: "1.0";
}
```

```ts
validation.learning_signal_missing_principal_id
validation.learning_signal_missing_scope_inference_basis
validation.learning_signal_networked_without_share_eligibility
```

Behavior remains Phase-B-gated. The fields are safe to add now as forward-compatible governance metadata.

---

### 18A.24 G-08 / G-12 / G-14 / G-15 / G-20 — minimal derived surface records

The main document provides `DerivedSurfaceContract`, but not the minimal schemas for the major surfaces. These are read models only.

```ts
interface TaskHealthCard {
  card_id: string;
  task_id: string;
  run_id?: string;
  current_state_summary: string;
  open_blocker_count: number;
  pending_hard_call_count: number;
  unresolved_research_need_count: number;
  budget_status: "within_budget" | "near_cap" | "over_cap" | "unknown";
  last_verdict?: OutcomeVerdict;
  derived_read_model_ref: StorageRef;
  governance: GovernanceEnvelope;
  schema_version: "1.0";
}

interface WorkProductCertification {
  certification_id: string;
  task_reliance_packet_ref: StorageRef;
  rendered_summary_ref: StorageRef;
  reliance_status: RelianceStatus;
  reliance_scope: string;
  issued_at?: ISO8601;
  derived_read_model_ref: StorageRef;
  governance: GovernanceEnvelope;
  schema_version: "1.0";
}

interface RunDiff {
  diff_id: string;
  base_run_id: string;
  compare_run_id: string;
  artifact_diff_refs: StorageRef[];
  plan_diff_ref?: StorageRef;
  cost_delta_ref?: StorageRef;
  verdict_delta_summary: string;
  derived_read_model_ref: StorageRef;
  governance: GovernanceEnvelope;
  schema_version: "1.0";
}

interface DecisionAuditView {
  audit_view_id: string;
  task_id: string;
  run_id: string;
  target_decision_ref: StorageRef;
  causal_receipt_refs: StorageRef[];
  policy_decision_refs: PolicyEvaluationRef[];
  finding_refs: string[];
  explanation_trace_ref?: StorageRef;
  derived_read_model_ref: StorageRef;
  governance: GovernanceEnvelope;
  schema_version: "1.0";
}

interface UnifiedEvaluationChainView {
  chain_view_id: string;
  chain_id: string;
  qualitative_result_refs: StorageRef[];
  quantitative_result_refs: StorageRef[];
  resolution_receipt_ref: StorageRef;
  rendered_view_ref: StorageRef;
  derived_read_model_ref: StorageRef;
  governance: GovernanceEnvelope;
  schema_version: "1.0";
}
```

```ts
validation.task_health_card_underived
validation.work_product_certification_without_reliance_packet
validation.run_diff_without_two_runs
validation.decision_audit_view_without_causal_receipts
validation.evaluation_chain_view_without_resolution_receipt
```

---

### 18A.25 Closeout note from audit

After this appendix, the document contains both categories of final recommendation:

1. the reconciled structural/final corrections that supersede the card where the card was wrong or under-specified; and

2. the accepted row details that still matter even though they were not the focus of the final reconciliation.

   The remaining open caveat is Addenda-A R203 verification for any Common `NoVerdictReason` promotion and exact field-name reconciliation against Source Workspace retrieval-lineage fields before finalizing `SourceAuthorityAssessment` mappings.

---



---

## 18B. Earlier Addenda B analyses folded into the final handoff

This appendix folds in the two pre-card Addenda B analyses from this same red-team round that were not fully represented in the first final handoff: the irreversible-action inventory and the load-bearing unstated-assumption review. These items remain operative recommendations for the next Addenda B draft unless a later owning-document patch explicitly supersedes them.

### 18B.1 Irreversible action inventory — final findings and patch targets

**Definition used in this review:** an irreversible action is any action that leaves the system, mutates shared state others depend on, creates provider/tool/access traces, creates durable writes, accepts or promotes candidate state, writes to memory/library/reputation systems, or otherwise cannot be cleanly undone.

| Action class                                                 | Final guard assessment                                       | Recovery if wrong                                            | Final recommendation                                         |
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| External message sends, webhooks, client-portal sends, filings/submissions | Strong guard in V3.3.1 side-effect policy: human gate, dry run, policy decision, no replay of sends/filings | Not cleanly reversible; corrective artifact only             | Keep existing guard; ensure §G reliance packets expose executed external side effects. |
| Calendar writes                                              | Human gate + policy + idempotency                            | Partially recoverable by later update/delete, but notifications/traces remain | Keep existing guard; include in side-effect ledger.          |
| External source/tool queries: web/API/database/browser/connectors/email/file-system/PACER/SEC/etc. | Partial only: allowed source types, capabilities, records, verification; no Addenda-B-wide side-effect gate | Not recoverable; provider logs, cost, access traces remain   | **Finding GAP-ADDB-IRREV-01:** add `ExternalSourceQueryPolicy` and route non-local source queries through side-effect/externalization governance. |
| Source Workspace open/save/export actions                    | Add-to-library has approval; open/browser/Finder/save/export lack a local Addenda-B guard | Local file may be deleted, but disclosure/access trace cannot be undone | **Finding GAP-ADDB-IRREV-02:** add `WorkspaceExternalizationPolicy` and receipt. |
| Internal artifact writes, direct fixes, accepted candidates  | Strong guard: candidate versions, preconditions, policy, receipts, rollback-as-new-version | Recoverable internally by new version/rollback; not by silent deletion | Keep; fold into `KnownGoodCheckpoint`/`RevisionReviewPacket`. |
| Meaning-bearing edits, privileged artifact changes, external-side-effect-capable revisions | Candidate + review/human gate                                | Candidate rejectable before acceptance; accepted internal changes revert as new version | Keep; enforce `RevisionReviewPacket`.                        |
| Run Board / Forum posts                                      | Append-only audit; visibility/participant policy             | Not cleanly recoverable; supersede/restrict later            | Keep; add `RunBoardGovernanceEnvelope`, matter firewall, redacted stubs. |
| Feedback routing, RunGuidance promotion                      | Routing/promotion policies exist but must be causally ordered and idempotent | Contest, supersede, expire, demote                           | Merge A-08/B-23 and require lifecycle/invalidation.          |
| DOC72/DOC73 memory/library/pattern promotion                 | Governance/user approval/policy gate                         | Demotion/archive/supersession, not clean deletion            | Keep; require `DelegationEnvelope` and explicit promotion receipts. |
| Learning signals to DOC8/BDSM/DOC24                          | Governed envelopes and no auto-promotion for privileged signals | Block promotion, demote pattern, emit correction signal      | Keep; add scoped formula receipts and governance envelope.   |
| HardCallResolution and human gate decisions                  | Explicit question/options/scope/expiry/supersession          | Can expire/supersede; external effects remain                | Keep; require `HardCallPendingPolicy` and `hard_call_resolved` receipt producer. |
| Task graph/template/preset/security/side-effect changes proposed by Task Agent | Task Agent is advisory, not executor                         | Versioned proposal rejectable; accepted changes need rollback/supersession | Keep; add `TaskAgentForumSurfaceOwnership` and `DelegationEnvelope`. |
| Costly model runs, calibration, sub-agent eval               | Budgets and cost caps exist but formulas need derivation     | Cost cannot be undone                                        | Add `CostVector`, forecast-vs-actual records, receipt policy. |

#### 18B.1.1 ExternalSourceQueryPolicy

```ts
type ExternalSourceQueryKind =
  | "web_search"
  | "browser_read"
  | "connector_fetch"
  | "api_call"
  | "database_query"
  | "email_source_fetch"
  | "file_system_read"
  | "pacer_query"
  | "courtlistener_query"
  | "sec_query"
  | "financial_database_query"
  | "mcp_tool_call";

interface ExternalSourceQueryPolicy {
  policy_id: string;
  query_kind: ExternalSourceQueryKind;

  requires_user_confirmation: boolean;
  requires_redaction_preview: boolean;
  provider_logging_warning_required: boolean;

  allowed_data_classes: Array<"public" | "internal" | "privileged" | "local_only">;
  allowed_taint_classes: TaintClass[];

  max_cost_vector_ref?: StorageRef;
  max_query_count_per_run?: number;

  replay_policy: ReplayPolicy;
  receipt_required: true;

  warning_text: string;
  schema_version: "1.0";
}

interface ExternalSourceQueryReceipt {
  receipt_id: string;
  query_kind: ExternalSourceQueryKind;
  workspace_id?: string;
  task_id: string;
  run_id?: string;

  query_record_ref?: StorageRef;
  source_record_refs: SourceRecordRef[];
  tool_receipt_ref?: StorageRef;

  policy_ref: string;
  user_confirmation_ref?: StorageRef;
  redaction_preview_ref?: StorageRef;
  cost_vector_ref?: StorageRef;

  status: "completed" | "blocked_by_policy" | "cancelled" | "failed";
  irreversible_external_trace_possible: boolean;

  governance: GovernanceEnvelope;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

```ts
validation.external_source_query_without_policy
validation.external_source_query_without_receipt
validation.privileged_external_source_query_without_confirmation
validation.external_source_query_cost_cap_missing
```

#### 18B.1.2 WorkspaceExternalizationPolicy

This is also specified in §8.5. The copy here records why it is required: open/save/export/browser/native/Finder actions can disclose matter-scoped material even if they do not mutate an internal artifact.

```ts
type WorkspaceExternalizationKind =
  | "open_in_browser"
  | "open_native_app"
  | "show_in_finder"
  | "save_as"
  | "export_bundle"
  | "external_source_query"
  | "connector_fetch"
  | "api_call"
  | "email_source_fetch"
  | "browser_session_read";

interface WorkspaceExternalizationPolicy {
  policy_id: string;
  externalization_kind: WorkspaceExternalizationKind;

  requires_user_confirmation: boolean;
  requires_redaction_preview: boolean;

  allowed_data_classes: Array<"public" | "internal" | "privileged" | "local_only">;
  allowed_taint_classes: TaintClass[];

  max_cost_vector_ref?: StorageRef;
  provider_logging_warning_required: boolean;
  receipt_required: true;
  replay_policy: ReplayPolicy;

  warning_text: string;
  schema_version: "1.0";
}

interface WorkspaceExternalizationReceipt {
  receipt_id: string;
  externalization_kind: WorkspaceExternalizationKind;
  workspace_id: string;

  source_record_refs: SourceRecordRef[];
  destination_ref?: StorageRef;

  policy_ref: string;
  user_confirmation_ref?: StorageRef;
  redaction_preview_ref?: StorageRef;
  cost_vector_ref?: StorageRef;

  status: "completed" | "blocked_by_policy" | "cancelled" | "failed";
  irreversible_disclosure_possible: boolean;

  governance: GovernanceEnvelope;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

```ts
validation.workspace_externalization_without_policy
validation.privileged_workspace_export_without_confirmation
validation.external_source_query_without_receipt
validation.workspace_externalization_without_governance
```

### 18B.2 Load-bearing unstated assumptions — final list and patch targets

The following are assumptions the Addenda B design quietly depends on but does not state as constraints. Each should become a preflight, lint, owner obligation, or acceptance criterion.

|    # | Load-bearing assumption                                      | What breaks if false                                         | Spec signal today                                         | Required spec inclusion                                      |
| ---: | ------------------------------------------------------------ | ------------------------------------------------------------ | --------------------------------------------------------- | ------------------------------------------------------------ |
|    1 | Cross-doc inserts are absorbed before implementation         | Build-ready surfaces remain orphaned; DOC23/DOC20/DOC12/DOC24/DOC25/DOC73 registries drift | XDOC-INSERT blocks and pending obligations                | `AddendaBAbsorptionGate` and OP-A closure checklist.         |
|    2 | DOC24 task-opportunity classifier is accurate                | Direct-first UX over- or under-invokes tasks/Task Agent      | Core direct-first language and DOC24 packet ownership     | Calibration fixtures, false-positive/false-negative thresholds, kill switch. |
|    3 | Task Agent Knowledge Pack remains current                    | Task Agent proposes stale graphs/ports/policies/capabilities | TKP generation and stale-pack degraded mode               | `TaskKnowledgePackFreshnessPolicy`.                          |
|    4 | Artifact/source/board/workspace state is snapshot-addressable later | Replay, rollback, finding matching, repair targeting, audit break | Snapshot refs scattered across Common/V3.3/SW/FD          | `SnapshotRetentionPolicy` and indexability rule.             |
|    5 | V3.3 narrow SourceWorkspace semantics and SW broader semantics do not diverge | Source applicability, taint, freshness, and availability mean different things to different modules | Source Workspace says shared object, V3.3 governs overlap | Field ownership/precedence table and overlap validator.      |
|    6 | Source documentation tiers preserve enough provenance for future downstream use | Tier-0/1 lookups become load-bearing evidence without support | Tier model + hidden-research prohibition                  | Risk-based minimum tier matrix.                              |
|    7 | External source actions and open/save/export are classified as side effects | Provider logs/disclosures/costs happen without gates         | Strong V3.3 side-effect policy, weak Source path          | `ExternalSourceQueryPolicy` and `WorkspaceExternalizationPolicy`. |
|    8 | DOC24/CIL packet rendering preserves authority, lifecycle, and scope | Summaries become stronger than source facts; stale/contested guidance leaks into prompts | FD/DOC24 packet references                                | `ContextPacketFidelityContract`.                             |
|    9 | Lifecycle transitions propagate causally before downstream reads | Superseded/contested/expired findings keep blocking or get learned | FD lifecycle and board supersession language              | `ReadModelInvalidationSpec` + causal event-seq policy.       |
|   10 | Receipt coverage is universal enough to reconstruct causality | Task Agent/replay/DOC8 cannot know what happened             | Receipts exist in V3.3, FD, SW, board                     | `ReceiptCoverageRegistry`.                                   |
|   11 | Cheap/local/model-class learning signals are comparable or isolated | Bad cheap-model patterns contaminate durable task design     | Learning envelopes include model class/fingerprint        | Model-class calibration gates and scope-limited promotion.   |
|   12 | Criterion hashes and anchors remain semantically stable      | Repairs/scores/learning attach to wrong criteria/sections    | `criterion_semantics_hash`, anchors, context hashes       | Rename lexical hash; semantic-review receipt for meaning changes. |
|   13 | Optional Source Workspace and Forum substrates can be added late without correctness loss | Evaluator emits source/forum needs with no real consumer     | Optional workspace/forum + routing channels               | Feedback branch consumer preflight / declared degraded path. |
|   14 | System reliably distinguishes substantive gaps from process gaps | Task Agent makes substantive judgments or content modules patch graph | Task Forum explains distinction                           | Gap-classifier confidence/ambiguity rule.                    |
|   15 | Pattern C dual recommendations resolve predictably           | Judge and Evaluator disagree; UI/Revisor/learning diverge    | Common says consumer policy “typically” Judge governs     | `EvaluationChainResolutionReceipt`.                          |

#### 18B.2.1 AddendaBAbsorptionGate

```ts
type AddendaBAbsorptionTarget =
  | "DOC23_R3_2_module_registry"
  | "DOC20_surface_registry"
  | "DOC21_master_ui_registry"
  | "DOC22_page_inventory"
  | "DOC12_room_kind_registry"
  | "DOC24_context_packet_registry"
  | "DOC15_prompt_rendering_contract"
  | "DOC25_ingestion_contract"
  | "DOC73_library_memory_contract"
  | "OP_A_cross_doc_obligation_tracker";

interface AddendaBAbsorptionGate {
  gate_id: string;
  target: AddendaBAbsorptionTarget;
  required_for_rows: string[];
  owner_doc: OwnerDoc;
  obligation_ref?: string;
  status: "missing" | "partial" | "absorbed" | "stubbed_with_degraded_behavior";
  degraded_behavior?: PendingConsumerDegradedBehavior;
  blocks_build_ready_claim: boolean;
  schema_version: "1.0";
}
```

```ts
validation.addenda_b_build_ready_with_unabsorbed_required_gate
validation.cross_doc_insert_without_opa_obligation
validation.pending_absorption_without_degraded_behavior
```

#### 18B.2.2 TaskKnowledgePackFreshnessPolicy

```ts
interface TaskKnowledgePackFreshnessPolicy {
  policy_id: string;
  task_knowledge_pack_ref: StorageRef;
  source_registry_snapshot_hash: string;
  module_catalog_snapshot_hash: string;
  port_registry_snapshot_hash: string;
  policy_semantics_snapshot_hash: string;
  capability_registry_snapshot_hash: string;
  max_age_hours: number;
  invalidation_triggers: Array<
    | "module_catalog_changed"
    | "port_registry_changed"
    | "side_effect_policy_changed"
    | "capability_registry_changed"
    | "type_owner_registry_changed"
    | "formula_registry_changed"
  >;
  on_stale: "block_design" | "advisory_only" | "force_recompile";
  schema_version: "1.0";
}
```

```ts
validation.task_agent_design_from_stale_tkp
validation.task_knowledge_pack_missing_snapshot_hash
```

#### 18B.2.3 ContextPacketFidelityContract

```ts
interface ContextPacketFidelityContract {
  contract_id: string;
  packet_kind: "TaskRunContextPacket" | "BoardDigest" | "FeedbackBundleProjection" | "RunGuidanceProjection";
  source_refs: StorageRef[];
  must_preserve_fields: Array<
    | "governance"
    | "lifecycle_state"
    | "authority_basis"
    | "blocking_authority"
    | "contested_state"
    | "supersession_state"
    | "source_freshness_state"
    | "do_not_use_instruction"
  >;
  omission_manifest_required: true;
  contradiction_manifest_required: boolean;
  summary_authority_rule: "summary_never_stronger_than_source";
  schema_version: "1.0";
}
```

```ts
validation.context_packet_drops_authority_basis
validation.context_packet_drops_governance
validation.context_packet_summary_strengthens_source_authority
validation.context_packet_omission_manifest_missing
```

#### 18B.2.4 ReceiptCoverageRegistry

```ts
interface ReceiptCoverageRegistryEntry {
  material_event_kind: string;
  required_receipt_or_event_type: string;
  producer_component: string;
  consumer_components: string[];
  durable_writer: "EC" | "OpenClaw_runtime" | "external_system";
  missing_receipt_behavior: "block" | "audit_error" | "degrade" | "warn";
  schema_version: "1.0";
}
```

```ts
validation.material_event_without_receipt_coverage
validation.receipt_type_unregistered
validation.receipt_missing_for_material_event
```

---

## 18C. Complete final row disposition matrix

This matrix makes the handoff self-contained. Rows marked `accept_as_card` inherit the adjudication-card fix, subject to the structural constraints in this document: governance envelopes must be preserved; new types require owner/producers/consumers; emitted values must be registered; and derived statuses require derivation receipts or input manifests.

```ts
type FinalDisposition =
  | "accept_as_card"
  | "accept_with_final_modifications"
  | "decline_false_positive"
  | "defer_phase_b"
  | "merge_into_other_row"
  | "replace_with_reframed_row"
  | "add_new_row";
```

| Row  | Final disposition               | Final action / notes                                         |
| ---- | ------------------------------- | ------------------------------------------------------------ |
| A-01 | accept_with_final_modifications | Replace one mutable mega-record with `EvaluationFindingEvent`, `EvaluationFindingRecord`, and `FeedbackFindingView`; preserve `assurance_basis[]` and canonical FD `authority_basis[]`; add governance/migration. |
| A-02 | accept_with_final_modifications | Elevate to critical; add `evaluated_target` and `evaluation_basis` to envelope; old target refs are derived projections. |
| A-03 | accept_with_final_modifications | Add chain registry/lifecycle; include expected producers, missing-producer status, and chain validation. |
| A-04 | accept_with_final_modifications | Add `EvaluationChainResolutionReceipt`; do not rely on vague consumer policy. |
| A-05 | accept_with_final_modifications | Use canonical FD `EvaluationAuthorityBasis`; cut `BlockingAuthorityBasis`; keep typed `BlockingAuthorityEvaluation`. |
| A-06 | accept_with_final_modifications | Split runtime vs disposition; add/normalize `max_iterations_reached`; one state/verdict/routing matrix. |
| A-07 | accept_with_final_modifications | Reuse B-owned `EvaluationLimitationKind`; aliases for near-dupes; verify Addenda-A R203 before Common `NoVerdictReason`. |
| A-08 | merge_into_other_row            | Merge with B-23 as `FeedbackRoutingResolutionPolicy`.        |
| A-09 | accept_with_final_modifications | Exhaustive TypeOwnerRegistry sweep and phantom-field lint, not four local pointers. |
| A-10 | accept_as_card                  | Move `EvaluationArtifactEnvelope` into Common; generalize `overall_state`; apply governance-envelope rule. |
| A-11 | decline_false_positive          | `LearningMode` already exists with `production | signal_generation | calibration`; no `cross_calibration`. |
| A-12 | accept_with_final_modifications | Define `HumanOutcomeFeedbackEvent`; use `OutcomeVerdict`, not lane-level `EvaluationVerdict`; `defer/request_changes` need no resulting verdict. |
| A-13 | accept_as_card                  | Common Contracts owns `EvaluationLearningSignalEnvelope`; Core imports and deletes malformed duplicate. |
| A-14 | accept_as_card                  | Pattern C qualitative-slice validation becomes error; owner-map issues handled by TypeOwnerRegistry. |
| A-15 | accept_with_final_modifications | Build-ready claim gated on owner registry, OP-A obligations, command registry, anchor hygiene, pending degraded behavior. |
| A-16 | accept_with_final_modifications | Critical; mutation only through `revision_in`, revision-compatible port, or sanctioned `DirectFixStep`; advisory context remains taint-bearing. |
| A-17 | accept_as_card                  | Revisor planner ports are not `revision_in`; `revision_in` reserved for artifact-mutating modules. |
| A-18 | accept_as_card                  | Add feedback emission matrix and absence reason.             |
| A-19 | accept_as_card                  | Add `proposed → dismissed` finding transition.               |
| A-20 | accept_as_card                  | Add unanchored LLM judgment acknowledgement fields.          |
| A-21 | accept_as_card                  | Add absence reason for artifact-version refs; enforce only on artifact-targeting findings. |
| A-22 | accept_as_card                  | Pending consumers require degraded behavior.                 |
| A-23 | accept_with_final_modifications | Re-anchor to Source Workspace; split authority level from legal treatment/adverseness. |
| A-24 | accept_as_card                  | Fix Pattern C parallel example to match a real topology.     |
| A-25 | merge_into_other_row            | Fold chain-id naming asymmetry into A-03.                    |
| A-26 | accept_with_final_modifications | Use stable artifact identity in `FindingMatchKey`; ProgressSignal consumes match key. |
| A-27 | accept_as_card                  | Replace artifact-keyed source workspace hashes with `SourceWorkspaceSnapshotHashSet`. |
| B-01 | accept_as_card                  | Add unified `RevisionExecutionLifecycle` FSM.                |
| B-02 | accept_with_final_modifications | Canonical key gains `attempt_seq` and `prior_output_hash`.   |
| B-03 | replace_with_reframed_row       | Re-scope to Source Workspace write/API operations; artifact direct-fix path already guarded. |
| B-04 | accept_as_card                  | Rolling-hash same-artifact steps must sequentialize; parallel only for disjoint targets. |
| B-05 | accept_with_final_modifications | Merge cascade convergence into `RevisorTerminationLedger` / `RevalidationCascadeRun`; add depth/cycle/quiescence. |
| B-06 | accept_as_card                  | Dependency cycles rejected or escalated; upstream terminal failure cascades. |
| B-07 | accept_as_card                  | Add `ParallelBatchFinalizationReceipt`.                      |
| B-08 | accept_with_final_modifications | Rename to `StepExecutionFailureKind`; register distinct failure enums. |
| B-09 | accept_as_card                  | Split candidate lifecycle from artifact head; side-effect intent candidates. |
| B-10 | accept_as_card                  | Add Hard Call blocking scope and `TaskCancelProtocol`.       |
| B-11 | accept_as_card                  | Add `TaskSkipReceipt`.                                       |
| B-12 | accept_as_card                  | Add policy freshness/supersession fields or authoritative EC policy ref. |
| B-13 | accept_as_card                  | Add `ResearchNeedLease`.                                     |
| B-14 | accept_with_final_modifications | Add forum deadlock breaker; remove `task_agent_decides`.     |
| B-15 | decline_false_positive          | DOC12/OP-A owns `RoomKind.plan_review`; no local Forum registry patch. |
| B-16 | accept_with_final_modifications | Drop wall-clock; deterministic total tie-breaker with lock-contention/cost proxy and lexicographic final tie. |
| B-17 | accept_as_card                  | Typed feedback ports or discriminator; part of feedback-to-prompt matrix. |
| B-18 | accept_with_final_modifications | Hard Call needs non-empty closed options or freeform-required mode. |
| B-19 | accept_as_card                  | Dispatcher emits `hard_call_resolved` receipt.               |
| B-20 | accept_as_card                  | Success condition waits for cascade/ledger quiescence.       |
| B-21 | accept_as_card                  | Emit signals only after referenced receipts persist.         |
| B-22 | accept_as_card                  | Add Pattern C invocation budget/cadence.                     |
| B-23 | merge_into_other_row            | Merge with A-08 routing idempotency policy.                  |
| B-24 | replace_with_reframed_row       | Thin sufficiency detector + richer triggers + single ledger; Hard Call only when meaningful. |
| B-25 | decline_false_positive          | `depends_on_step_ids` exists; replace with dependency read-model canonicalization. |
| B-26 | accept_with_final_modifications | Collapse revalidation naming into one `revalidation_policy`. |
| B-27 | accept_as_card                  | Regenerate loop guard via previous output hashes and ledger/idempotency. |
| C-01 | accept_with_final_modifications | FormulaRegistry plus scoped receipts, metric observations/rollups, finite-number policy, fixtures. |
| C-02 | accept_with_final_modifications | Split success vs wasted cycles; add right-censoring.         |
| C-03 | accept_with_final_modifications | Remove future hash prediction from LLM contract; runtime computes hashes. |
| C-04 | accept_with_final_modifications | Severity-weighted regression and complete sub-agent metric observation/reputation formula. |
| C-05 | accept_as_card                  | Use latency distribution p50/p90 instead of mean.            |
| C-06 | accept_with_final_modifications | Zero-denominator/insufficient sample policies through FormulaSpec. |
| C-07 | accept_with_final_modifications | Replace scalar estimate with `CostVector` and `TaskCostRecord`. |
| C-08 | accept_with_final_modifications | Define novelty metric and discriminated no-neighbor union.   |
| C-09 | accept_with_final_modifications | Calibrated task-mode scoring and corrected template aggregation. |
| C-10 | accept_as_card                  | Rename lexical criterion hash; semantic version requires review receipt. |
| D-01 | accept_with_final_modifications | Taint transitivity; source authority derived from retrieval lineage; conservative expert/technical defaults. |
| D-02 | accept_as_card                  | Workspace taint aggregation uses max taint and privilege propagation. |
| D-03 | accept_as_card                  | One canonical SourceWorkspace identity.                      |
| D-04 | accept_with_final_modifications | Keep tier 0 as receipt-only; persist transitions; align verification/demotion policy. |
| D-05 | accept_as_card                  | ResearchNeed scope/ref/human-needed exit.                    |
| D-06 | accept_with_final_modifications | Evidence anchors + payload registry + extractor/source distinction + support derivation. |
| D-07 | accept_as_card                  | Forum post visibility, supersession, governance.             |
| D-08 | accept_as_card                  | Context packet request/receipt/omission/total budget.        |
| D-09 | accept_with_final_modifications | Passive board auto-publication governed by publication policy and redacted stubs. |
| D-10 | accept_as_card                  | ModuleAssistanceRequest schema and moderator fallback.       |
| D-11 | accept_as_card                  | BoardDigest selection/filter policy.                         |
| D-12 | accept_as_card                  | Board retention/compaction/event class + EC policy persistence. |
| D-13 | accept_with_final_modifications | Durable RunGuidance with lifecycle, contested check, governance, invalidation. |
| D-14 | accept_as_card                  | Injection slots, compact cards, command registry, token budget, packet taxonomy. |
| D-15 | accept_as_card                  | Sub-agent output plurality, fallback, plan-verifier point.   |
| D-16 | replace_with_reframed_row       | Full Source Workspace API operations and receipts; home for B-03 write preconditions. |
| D-17 | accept_as_card                  | Anchor/hash hygiene.                                         |
| D-18 | accept_with_final_modifications | Repeated failure keyed to stable identity and ledger.        |
| D-19 | accept_as_card                  | Add acquisition cost and module attribution on source records. |
| D-20 | accept_with_final_modifications | Split library candidate queue from durable library promotion; add promotion gate. |
| D-21 | accept_as_card                  | Split overloaded `requires_background_progress`.             |
| D-22 | accept_as_card                  | Anchor hygiene and softened compatibility claim.             |
| D-23 | accept_as_card                  | Dispatch expectations make “silent ignoring” enforceable.    |
| D-24 | accept_with_final_modifications | Matter firewall precedes visibility; privileged posts always matter-scoped. |
| E-01 | defer_phase_b                   | Memory hydration phase; tracked for Phase-B / DOC80 family.  |
| E-02 | defer_phase_b                   | Memory precedence hierarchy.                                 |
| E-03 | defer_phase_b                   | SubAgentPrior injection.                                     |
| E-04 | defer_phase_b                   | TaskBlueprint topology/payload bifurcation.                  |
| E-05 | defer_phase_b                   | Flawless-execution denominator / positive signal learning.   |
| E-06 | defer_phase_b                   | Sub-agent reputation consumer behavior.                      |
| E-07 | defer_phase_b                   | LearningMode consumption behavior and cross-model learning use. |
| E-08 | defer_phase_b                   | Process-gap → design-pattern loop.                           |
| E-09 | defer_phase_b                   | Longitudinal pattern views.                                  |
| E-10 | defer_phase_b                   | ChatGPT self-learning/TIE/BDSM utility items.                |
| E-11 | defer_phase_b                   | Design-feedback as peer to artifact-repair.                  |
| E-12 | defer_phase_b                   | Automatic pattern suggestion UI.                             |
| E-13 | defer_phase_b                   | Behavior deferred; forward-compat fields addable now.        |
| F-01 | decline_false_positive          | Literal ShadowWorkspace declined; adopt TaskRunFork + side-effect ledger. |
| F-02 | decline_false_positive          | TaskConfirmationSignal folded into existing receipts/signals. |
| F-03 | decline_false_positive          | Flawless-execution as signal type declined; denominator need kept in E-05. |
| F-04 | decline_false_positive          | Chunking findings declined; use compressed views.            |
| G-01 | accept_with_final_modifications | EvaluationContractReview with typed criterion projections and governance. |
| G-02 | accept_with_final_modifications | RevisionReviewPacket with semantic diff artifact and decision receipts. |
| G-03 | accept_with_final_modifications | EvidencePackage with support derivation and degraded extractor modes. |
| G-04 | accept_with_final_modifications | Replace KnownGoodState with KnownGoodCheckpoint.             |
| G-05 | accept_with_final_modifications | BudgetNarrative consumes cost vectors and forecast-vs-actual records. |
| G-06 | accept_with_final_modifications | TaskReliancePacket with manifest, derivation, invalidation.  |
| G-07 | accept_with_final_modifications | AttentionLedger / DecisionQueue with command refs, governance, lifecycle. |
| G-08 | accept_with_final_modifications | TaskHealthCard as derived read model only.                   |
| G-09 | accept_with_final_modifications | Pre-run cost forecast + BudgetNarrative reconciliation.      |
| G-10 | accept_with_final_modifications | Unified review experience via derived surfaces.              |
| G-11 | accept_with_final_modifications | Contestability surfaced inline for defeasible findings.      |
| G-12 | accept_with_final_modifications | WorkProductCertification derived from TaskReliancePacket.    |
| G-13 | accept_with_final_modifications | FindingsInbox matter-scoped; reads canonical finding records. |
| G-14 | accept_with_final_modifications | RunDiff derived read model.                                  |
| G-15 | accept_with_final_modifications | DecisionAuditView with causal receipts.                      |
| G-16 | accept_with_final_modifications | RunReplayPreview built on replay modes and known-good checkpoints. |
| G-17 | accept_with_final_modifications | TaskRunFork with irrevocable side-effect ledger.             |
| G-18 | accept_with_final_modifications | ExplanationTrace with no hidden chain-of-thought capture.    |
| G-19 | accept_with_final_modifications | TaskReplay modes; no blanket deterministic-replay promise.   |
| G-20 | accept_with_final_modifications | Unified Evaluation Chain View from chain registry/resolution receipt. |
| G-21 | accept_as_card                  | Chaos/concurrency fixtures required for §B/D/§G.             |
| X-01 | add_new_row                     | Universal `GovernanceEnvelope`.                              |
| X-02 | add_new_row                     | Structural/object admission registry.                        |
| X-03 | add_new_row                     | `RevisorTerminationLedger`.                                  |
| X-04 | add_new_row                     | Phantom-field lint + exhaustive type-owner sweep.            |
| X-05 | add_new_row                     | Read-model invalidation.                                     |
| X-06 | add_new_row                     | Reliance-decay monitoring.                                   |
| X-07 | add_new_row                     | DelegationEnvelope.                                          |
| X-08 | add_new_row                     | Feedback-to-prompt responsibility matrix.                    |
| X-09 | add_new_row                     | Task Agent forum-surface ownership.                          |
| X-10 | add_new_row                     | Task-scoped forum policy.                                    |
| X-11 | add_new_row                     | External source query side-effect policy.                    |
| X-12 | add_new_row                     | Workspace externalization policy.                            |
| X-13 | add_new_row                     | AddendaBAbsorptionGate.                                      |
| X-14 | add_new_row                     | TaskKnowledgePackFreshnessPolicy.                            |
| X-15 | add_new_row                     | ContextPacketFidelityContract.                               |
| X-16 | add_new_row                     | ReceiptCoverageRegistry.                                     |

---

## 18D. Additional accepted-as-card carry-forward rows and exact patch notes

This appendix captures accepted rows that were not the focus of the final reconciliation but should still be applied or explicitly registered in the next draft.

### 18D.1 A-10 — EvaluationArtifactEnvelope ownership and generic overall state

```ts
interface EvaluationArtifactEnvelope {
  envelope_ref: StorageRef;
  result_id: string;
  producer_kind: ProducerKind;
  producer_module_id: string;
  task_id: string;
  run_id: string;
  overall_disposition: OutcomeEvaluationDisposition | null;
  governance: GovernanceEnvelope;
  evaluation_snapshot_ref: StorageRef;
  created_at: ISO8601;
  schema_version: "1.0";
}
```

```ts
validation.evaluation_artifact_envelope_redeclared_outside_common
validation.overall_state_uses_b_specific_runtime_state
```

### 18D.2 A-13 — Core imports the common learning-signal envelope

```ts
interface LearningSignalImportDeclaration {
  importing_doc: "DOC23_AddendaB_Core" | "DOC23_AddendaB_V3_3_1";
  canonical_type_name: "EvaluationLearningSignalEnvelope";
  canonical_owner_doc: "Evaluation Common Contracts";
  canonical_section_ref: "Common Contracts §5";
  local_redeclaration_allowed: false;
  schema_version: "1.0";
}
```

```ts
validation.learning_signal_envelope_redeclared_outside_common
validation.core_learning_signal_malformed_typescript_present
```

### 18D.3 A-14 — qualitative-slice validation severity

```ts
interface QualitativeSliceRequirementPolicy {
  chain_kind: EvaluationChainKind;
  producer_kind: ProducerKind;
  qualitative_slice_required: boolean;
  missing_slice_severity: "error" | "warning";
  schema_version: "1.0";
}

const PATTERN_C_QUALITATIVE_SLICE_POLICY: QualitativeSliceRequirementPolicy = {
  chain_kind: "pattern_c_evaluator_then_judge",
  producer_kind: "judge",
  qualitative_slice_required: true,
  missing_slice_severity: "error",
  schema_version: "1.0"
};
```

```ts
validation.envelope_judge_emitted_qualitative_slice
validation.qualitative_slice_owner_map_drift
```

### 18D.4 A-19 — proposed finding negative exit

```ts
interface FindingProposedExitPolicy {
  from_state: "proposed";
  positive_exit: "active";
  negative_exit: "dismissed";
  negative_exit_reason: "not_confirmed_at_activation_termination";
  auto_apply_at_activation_termination: true;
  schema_version: "1.0";
}
```

```ts
validation.finding_stuck_in_proposed_after_activation
```

### 18D.5 A-20 — unanchored LLM judgment acknowledgement

```ts
interface CriterionUnanchoredJudgmentAck {
  criterion_id: string;
  unanchored_aggregation_acknowledged_by_user: boolean;
  unanchored_ack_user_ref?: string;
  unanchored_ack_at?: ISO8601;
  acknowledgement_scope: "criterion" | "outcome" | "task";
  schema_version: "1.0";
}
```

```ts
validation.unanchored_required_criterion_unacknowledged
```

### 18D.6 A-21 — artifact-targeted finding version-ref requirement

```ts
interface FindingKindTargetingPolicy {
  finding_kind: FindingKind;
  targets_artifact: boolean;
  requires_artifact_version_ref: boolean;
  allowed_absent_reasons: Array<
    | "non_artifact_target"
    | "human_review_no_artifact"
    | "process_observation"
  >;
  schema_version: "1.0";
}
```

```ts
validation.artifact_targeted_finding_missing_version_ref
```

### 18D.7 A-24 / A-25 — topology and naming hygiene

```ts
interface EvaluationTopologyExampleRegistryEntry {
  example_id: string;
  topology_kind:
    | "pattern_c_evaluator_then_judge"
    | "parallel_evaluators_same_snapshot"
    | "evaluator_plus_deterministic_scorer";
  valid: boolean;
  replacement_for_invalid_example?: string;
  schema_version: "1.0";
}
```

```ts
validation.pattern_c_example_claims_parallel_judge_evaluator
validation.chain_id_name_drift
```

### 18D.8 D-02 — workspace taint aggregation

```ts
type TaintOrder = Array<
  | "safe"
  | "internal_corpus_trusted"
  | "user_trusted_bounded"
  | "external_authority_trusted"
  | "external_untrusted"
  | "unclassified"
  | "privileged"
>;

interface TaintAggregationPolicy {
  policy_id: string;
  workspace_taint_rule: "max_taint";
  taint_order: TaintOrder;
  any_privileged_record_marks_workspace_privileged: true;
  matter_scope_rule: "same_matter_only_or_block";
  schema_version: "1.0";
}
```

```ts
validation.workspace_taint_not_aggregate_max
validation.privileged_record_not_propagated_to_workspace
```

---

## 18E. Lint registry seed — severity, stage, owner, fixture requirement

Every lint introduced by the R0.4 package must be registered. This seed table lists the minimum lints that must exist before the amendment is considered build-ready. Additional lints in this document should be added to the same registry before implementation.

| Lint ID                                                      | Severity | Stage              | Owner                | Blocks            | Required fixture                   |
| ------------------------------------------------------------ | -------: | ------------------ | -------------------- | ----------------- | ---------------------------------- |
| validation.structural_object_without_owner                   |    error | schema_compile     | Common Contracts     | build-ready       | orphan new type                    |
| validation.structural_object_without_producer                |    error | schema_compile     | Common Contracts     | build-ready       | type with no producer              |
| validation.structural_object_without_consumer                |    error | schema_compile     | Common Contracts     | build-ready       | receipt with no consumer           |
| validation.structural_object_duplicate_unresolved            |    error | schema_compile     | Common Contracts     | build-ready       | duplicate enum                     |
| validation.lint_without_registry_entry                       |    error | schema_compile     | Common Contracts     | build-ready       | unregistered lint                  |
| validation.lint_without_fixture                              |    error | ci_fixture         | Common Contracts     | build-ready       | lint without fixture               |
| validation.governed_object_without_envelope                  |    error | schema_compile     | Common Contracts     | durable write     | governed object missing envelope   |
| validation.view_drops_governance_fields                      |    error | schema_compile     | Common Contracts     | projection/export | projection strips taint/matter     |
| validation.field_reference_not_in_schema                     |    error | schema_compile     | Common Contracts     | build-ready       | consumer reads absent field        |
| validation.type_reference_not_in_owner_registry              |    error | schema_compile     | Common Contracts     | build-ready       | unknown shared type                |
| validation.evaluation_authority_basis_redeclared_outside_owner |    error | schema_compile     | FD/Common            | build-ready       | forked enum                        |
| validation.blocking_authority_basis_enum_forked              |    error | schema_compile     | FD/Common            | build-ready       | duplicate blocker enum             |
| validation.blocking_finding_without_authority                |    error | plan_compile       | FD/Common            | dispatch          | blocking finding lacks basis       |
| validation.model_judgment_only_blocker_without_subjective_permission |    error | plan_compile       | FD/Common            | dispatch          | subjective blocker no permission   |
| validation.finding_state_mutated_inside_immutable_event      |    error | runtime_audit      | Common               | durable write     | event mutated after emission       |
| validation.finding_lifecycle_transition_missing_receipt      |    error | runtime_audit      | Common               | durable write     | state flip no receipt              |
| validation.pattern_c_chain_without_resolution_receipt        |    error | runtime_audit      | Common               | route             | dual result unresolved             |
| validation.pattern_c_route_conflict_unresolved               |    error | plan_compile       | Common               | dispatch          | route conflict no policy           |
| validation.no_verdict_reason_label_drift                     |    error | schema_compile     | Common/V3.3/AddendaA | build-ready       | alias label used as canonical      |
| validation.feedback_bundle_absence_unexplained               |    error | runtime_audit      | FD                   | audit             | no bundle/no reason                |
| validation.repair_routed_to_non_revision_port                |    error | plan_compile       | FD/V3.3              | dispatch          | mutation via instruction_in        |
| validation.revisor_declares_revision_in                      |    error | schema_compile     | V3.3                 | build-ready       | Revisor planner port misuse        |
| validation.feedback_consumed_without_receipt                 |    error | post_run_audit     | FD                   | audit             | expectation no receipt             |
| validation.revisor_attempt_without_termination_ledger        |    error | runtime_audit      | V3.3                 | dispatch          | attempt no ledger                  |
| validation.sufficiency_result_duplicates_attempt_log         |    error | schema_compile     | V3.3                 | build-ready       | detector embeds attempts           |
| validation.sufficiency_result_without_termination_ledger     |    error | runtime_audit      | V3.3                 | dispatch          | detector no ledger ref             |
| validation.revisor_loop_guard_counters_disagree              |    error | runtime_audit      | V3.3                 | dispatch          | count invariant fails              |
| validation.success_marked_before_ledger_quiescent            |    error | runtime_audit      | V3.3                 | terminal          | success before cascade done        |
| validation.workspace_mutation_without_precondition           |    error | dispatch_preflight | Source Workspace     | durable write     | record write no hash/lease         |
| validation.workspace_event_seq_conflict                      |    error | dispatch_preflight | Source Workspace     | durable write     | stale event seq                    |
| validation.workspace_api_operation_unregistered              |    error | schema_compile     | Source Workspace     | build-ready       | operation not in API               |
| validation.workspace_externalization_without_policy          |    error | dispatch_preflight | Source Workspace     | externalization   | export no policy                   |
| validation.privileged_workspace_export_without_confirmation  |    error | dispatch_preflight | Source Workspace     | externalization   | privileged export no confirm       |
| validation.external_source_query_without_receipt             |    error | runtime_audit      | Source Workspace     | audit             | provider call no receipt           |
| validation.source_kind_authority_unmapped                    |    error | schema_compile     | Source Workspace     | build-ready       | source_kind no default             |
| validation.source_authority_without_retrieval_lineage        |    error | runtime_audit      | Source Workspace     | use as authority  | authority no lineage               |
| validation.tier0_source_record_materialized                  |    error | schema_compile     | Source Workspace     | durable write     | tier-0 SourceRecord                |
| validation.claim_depends_on_tier0_lookup                     |    error | plan_compile       | Source Workspace     | reliance/citation | claim cites receipt-only lookup    |
| validation.source_tier_transition_not_persisted              |    error | runtime_audit      | Source Workspace     | audit             | tier change no receipt             |
| validation.claim_support_underived                           |    error | runtime_audit      | Source Workspace/§G  | reliance          | support label no derivation        |
| validation.forum_post_cross_matter_leak                      |    error | dispatch_preflight | Task Forum           | publish           | matter mismatch visible            |
| validation.run_board_event_without_governance                |    error | runtime_audit      | Task Forum           | publish           | audit event no governance          |
| validation.suppressed_event_without_audit_stub               |  warning | runtime_audit      | Task Forum           | audit             | withheld event no stub             |
| validation.context_packet_drops_governance                   |    error | plan_compile       | DOC24/DOC15          | prompt            | packet strips governance           |
| validation.context_packet_summary_strengthens_source_authority |    error | plan_compile       | DOC24/DOC15          | prompt            | summary stronger than source       |
| validation.metric_without_formula_spec                       |    error | schema_compile     | Common               | durable metric    | metric no formula                  |
| validation.durable_metric_without_formula_receipt            |    error | runtime_audit      | Common               | durable write     | persisted metric no receipt        |
| validation.formula_output_nan_or_infinity                    |    error | runtime_audit      | Common               | durable write     | NaN/Infinity stored                |
| validation.quality_index_pass_status_drift                   |    error | runtime_audit      | Common               | verdict/reliance  | pass field disagrees               |
| validation.template_match_output_nan                         |    error | runtime_audit      | V3.3                 | task routing      | NaN template score                 |
| validation.cost_vector_unit_mismatch                         |    error | runtime_audit      | Common               | budget            | adds unlike units                  |
| validation.cost_quantile_sum_without_correlation_policy      |    error | runtime_audit      | Common               | forecast          | invalid quantile aggregation       |
| validation.read_model_without_input_manifest                 |    error | schema_compile     | Common/§G            | build-ready       | read model no manifest             |
| validation.lifecycle_event_without_read_model_invalidation   |    error | schema_compile     | Common/§G            | build-ready       | event lacks invalidation rule      |
| validation.reliance_status_underived                         |    error | runtime_audit      | §G                   | certification     | status asserted                    |
| validation.reliance_packet_stale_snapshot                    |    error | runtime_audit      | §G                   | certification     | packet valid after upstream change |
| validation.work_product_certification_without_reliance_packet |    error | runtime_audit      | §G/DOC20             | certification     | cover page no packet               |
| validation.replay_attempts_external_side_effect              |    error | dispatch_preflight | §G/V3.3              | replay            | replay would send/write externally |
| validation.deterministic_replay_with_nondeterministic_step   |    error | plan_compile       | §G/V3.3              | replay            | false deterministic promise        |
| validation.delegation_envelope_allows_irreversible_action_without_explicit_permission |    error | dispatch_preflight | §G/Core              | dispatch          | delegation too broad               |
| validation.addenda_b_build_ready_with_unabsorbed_required_gate |    error | schema_compile     | Core/OP-A            | build-ready       | required insert not absorbed       |
| validation.task_agent_design_from_stale_tkp                  |    error | plan_compile       | Task Agent/Core      | design            | stale TKP used                     |
| validation.material_event_without_receipt_coverage           |    error | schema_compile     | Common/Core          | build-ready       | untracked material event           |

---

## 18F. OP-A / DOC20 / DOC21 / DOC22 / command registration checklist

The next spec draft is not complete until these registration obligations are either absorbed or entered into OP-A with explicit degraded behavior.

### 18F.1 OP-A obligations to add or close

| Obligation                        | Target owner                  | Source rows                        | Required action                                              |
| --------------------------------- | ----------------------------- | ---------------------------------- | ------------------------------------------------------------ |
| Addenda B TypeOwnerRegistry sweep | Common Contracts / OP-A       | A-09, X-04                         | Add owner rows for every shared type, enum, receipt, event, command, read model. |
| DOC12 `plan_review` dependency    | DOC12 / OP-A                  | B-15                               | Confirm existing `OBL-DOC12-FORUM-01`; do not locally redeclare. |
| DOC20 §G surfaces                 | DOC20                         | G-08, G-12–G-16, G-20              | Register pages/components/read models/commands.              |
| DOC21 Master UI update            | DOC21                         | §G, AttentionLedger, FindingsInbox | Add surface contracts: loading, empty, degraded, blocked, error, inspector. |
| DOC22 Page Inventory update       | DOC22                         | §G                                 | Add page inventory entries and component references.         |
| DOC20 Content Registry update     | DOC20 §6.18.2                 | all new stored content types       | Register `TaskReliancePacket`, `EvidencePackage`, `RevisionReviewPacket`, `KnownGoodCheckpoint`, etc. |
| DOC24 packet assembly             | DOC24                         | D-08, X-08, 18B assumptions        | Add packet-fidelity and governance preservation rules.       |
| DOC15 prompt rendering            | DOC15                         | B-17, X-08                         | Add feedback-to-prompt responsibility matrix and taint handling. |
| Source Workspace API              | Source Workspace              | B-03/D-16                          | Add operation/receipt schemas and commands.                  |
| External source query policy      | Source Workspace / EC Core    | GAP-ADDB-IRREV-01                  | Add policy, receipt, and command registrations.              |
| Workspace externalization policy  | Source Workspace / DOC20      | GAP-ADDB-IRREV-02                  | Add UI confirmation, redaction preview, and receipt registration. |
| Formula registry                  | Common Contracts              | C-01                               | Add formula registry and formula receipt policy.             |
| Reliance decay monitor            | §G / Source Workspace / DOC20 | X-06                               | Add source-change invalidation and user-facing attention items. |

### 18F.2 Command registry entries required

Every command below needs request schema, response schema, idempotency key, durable-write/no-op class, required policy checks, telemetry event kind, read-model invalidations, and error states.

```ts
type RequiredAddendaBCommandId =
  | "revision_review.accept_candidate"
  | "revision_review.reject_candidate"
  | "revision_review.request_changes"
  | "revision_review.restore_known_good"
  | "finding.contest"
  | "finding.confirm"
  | "finding.dismiss"
  | "hard_call.resolve"
  | "task.cancel"
  | "task.skip"
  | "source_workspace.add_source_record"
  | "source_workspace.update_source_record"
  | "source_workspace.answer_research_need"
  | "source_workspace.acquire_research_need_lease"
  | "source_workspace.verify_source"
  | "source_workspace.mark_source_stale"
  | "source_workspace.export_bundle"
  | "source_workspace.open_external"
  | "external_source.query"
  | "evidence.export_package"
  | "reliance.issue_work_product_certification"
  | "reliance.invalidate_packet"
  | "task_replay.preview"
  | "task_replay.create_fork"
  | "attention.resolve_item";
```

```ts
validation.addenda_b_command_without_registry_entry
validation.command_missing_idempotency_key
validation.command_missing_read_model_invalidation
validation.command_externalizes_without_policy_check
```

### 18F.3 Required surface states

Every §G and board/forum/source UI surface must define these states:

```ts
type RequiredSurfaceState =
  | "loading"
  | "empty"
  | "ready"
  | "degraded_missing_consumer"
  | "degraded_stale_read_model"
  | "blocked_by_policy"
  | "blocked_by_privilege_or_matter_firewall"
  | "error";

interface AddendaBSurfaceStateContract {
  surface_id: string;
  supported_states: RequiredSurfaceState[];
  empty_state_copy_ref: StorageRef;
  degraded_state_copy_ref: StorageRef;
  blocked_state_copy_ref: StorageRef;
  error_state_copy_ref: StorageRef;
  inspector_ref?: StorageRef;
  telemetry_event_kinds: string[];
  schema_version: "1.0";
}
```

```ts
validation.surface_missing_empty_state
validation.surface_missing_degraded_state
validation.surface_missing_blocked_state
validation.surface_missing_error_state
validation.surface_action_without_command
```

---

## 18G. Final open verification gates

Only two substantive verification gates remain before drafting the R0.4 amendment text:

1. **Addenda-A R203 verification.** Do not promote a Common `NoVerdictReason` vocabulary until the actual R203 `IndeterminateCause` member list is checked. Until then, use B-owned `EvaluationLimitationKind` and an alias registry.

2. **Source Workspace retrieval-lineage field names.** `SourceAuthorityAssessment` should derive from existing SourceRecord retrieval-lineage/provenance fields. Confirm exact field names before finalizing the assessment schema so the patch does not add an orphan provenance axis.

   These gates should appear in OP-A as explicit obligations if the R0.4 draft cannot close them immediately.


---

## 19. Closing view

The corrected R0.4 package is not a smaller product. It is a more disciplined one. The adjudication card correctly identified most of the important work, and §G should stay because it is the user-facing reliance layer that makes the system valuable for professional work. The final pass mainly prevents the fix package from becoming a second, parallel spec: canonical enums only, one durable source per fact, derived projections with invalidation, scoped receipts, one termination ledger, type-owner sweep before adoption, lints with fixtures, and Professional Reliance as a read-model layer.

That is the final settled recommendation from this red-team round.



# Gemini

**Top-line Assessment**

The deduplication is largely complete, capturing the critical distributed-systems and mathematical breaks (taint laundering, hash hallucination, clock-skew concurrency) identified across the four review passes. However, the `ACCEPT`-by-default posture has resulted in "aggregation bloat"—the card frequently solves conflicts by creating a third, unifying schema rather than ruthlessly deleting the redundant ones, particularly in §G and the lifecycle protocols. The single biggest problem with this card is that it treats UI views and system primitives as peers; it specifies multiple new schemas for things that are just UI projections of existing data.

### 🔪 The Subtractive Cut List (Rows to Merge or Kill)

- **A-05 (Authority vs Assurance):** **CUT.** Do not compute a boolean `blocking_authority_satisfied` on a view. Make `severity: "blocking"` the single source of truth. Let `assurance_basis: AssuranceBasis[]` explain *why*.
- **A-25 (`evaluation_chain_id` asymmetry):** **CUT.** It’s a trivial rename. Fold it entirely into A-03; it does not deserve its own row.
- **B-11 (`TaskSkipProtocol`):** **MERGE into B-10.** Skip and Cancel are the exact same lifecycle interrupt. Merge into `TaskInterruptProtocol { interrupt_kind: "cancel" | "skip" }`.
- **D-09 & D-11 (Board vs Digest Policies):** **MERGE.** Filtering the live forum stream and filtering the digest are the same curation problem. Merge into one `ForumCurationPolicy`.
- **G-07 (`AttentionLedger`):** **MERGE into G-13.** You don't need an `AttentionLedger` and a `FindingsInbox`. Merge into `UnifiedAttentionInbox` to prevent the user from checking two queues.
- **G-12 (`WorkProductCertification`):** **CUT.** This is just a UI render of G-06 (`TaskReliancePacket`). It requires no new schema or architectural contract.
- **G-14 (`RunDiff`) & G-16 (`RunReplayPreview`):** **MERGE into G-19.** Diffing and previewing are just functional outputs of the `TaskReplay` primitive (G-19) combined with `KnownGoodState` (G-04). They don't need standalone architectural specs.

### Per-Row Adjudication Table (Exceptions & Key Modifications)

| **ID**   | **Agree/Disagree/Partial** | **Reason**                                                   |
| -------- | -------------------------- | ------------------------------------------------------------ |
| **A-01** | **Partial (Modify)**       | Unifying is correct, but drop the `FeedbackFindingView`. Consumers should read the canonical object directly to prevent projection drift. |
| **A-12** | **Partial (Modify)**       | `HumanOutcomeFeedbackEvent` overlaps with `HardCallResolution` (B-19). Ensure they share a base `HumanInterventionEvent` interface. |
| **B-10** | **Partial (Modify)**       | Combine with B-11 into `TaskInterruptProtocol` to cut redundant state machine paths. |
| **B-16** | **Agree (Verify pass)**    | Gemini was 100% right. Wall-clock tie-breakers in local multi-agent graphs are fatal race conditions. The risk-based sorting is perfect. |
| **C-03** | **Agree (Verify pass)**    | LLMs predicting post-hashes is a fundamental misunderstanding of cryptographic hashing. Gemini's lock-targeting fix is mandatory. |
| **D-16** | **Agree (Verify pass)**    | Workspace API operations are implied but untyped. Defining CRUD + Lock operations here is a hard prerequisite for B-03. |
| **G-02** | **Agree**                  | `RevisionReviewPacket` is the most important UX addition in the set. It stops the "black box mutation" problem. |
| **G-06** | **Agree**                  | `TaskReliancePacket` is the capstone. It converts the evaluation graph into a usable legal artifact. |

### Detailed Notes & Schema Patches

**1. Merge B-10 and B-11: `TaskInterruptProtocol`**

Do not build separate state machines for skipping and cancelling.

TypeScript

```
interface TaskInterruptProtocol {
  interrupt_id: string; task_id: string; run_id: string; requested_by_ref: string;
  interrupt_kind: "cancel" | "skip";
  target_scope: "entire_run" | "segment" | "module_activation" | "revision_plan" | "outcome";
  target_refs: string[];
  reason: "not_applicable" | "user_directed" | "dependency_unavailable" | "policy_blocked" | "budget_exhausted";
  in_flight_handling: "request_graceful_stop" | "preempt_immediately" | "finish_current_step_then_stop";
  side_effect_policy: "do_not_cancel_executed" | "cancel_unexecuted_intents" | "create_corrective_artifact";
  candidate_disposition: "discard" | "retain_for_manual_review" | "orphan_until_reconciled";
  created_at: ISO8601; schema_version: "2.0";
}
```

**2. Merge D-09 and D-11: `ForumCurationPolicy`**

TypeScript

```
interface ForumCurationPolicy {
  policy_id: string;
  curation_target: "live_stream" | "board_digest";
  included_post_kinds: TaskRunBoardPostKind[];
  suppress_classes: Array<"privileged" | "local_only">;
  severity_threshold: "low" | "medium" | "high" | "blocking";
  max_posts_per_interval: number;
  selection_strategy: "recency" | "severity" | "score" | "mixed";
  schema_version: "1.0";
}
```

### Answers to Specific Questions

#### 1. A-01: Canonical EvaluationFinding

**Right call.** Maintaining two separate schemas (`EvaluationFinding` vs `FeedbackFindingView`) is a classic anti-pattern that guarantees drift. An implementing agent will inevitably add a field to one and forget the other. You do not need the `FeedbackFindingView` projection. Consumers can read the canonical schema; if a UI needs less data, it handles that at the presentation layer, not the architectural contract layer.

**Exact Schema (integrating the A-05 cut):**

TypeScript

```
interface EvaluationFinding {
  finding_id: string; result_id: string;
  finding_kind: FindingKind; finding_text: string; explanation: string;
  severity: "low" | "medium" | "high" | "blocking"; // 'blocking' is the sole source of truth for halting.
  state: FindingState;
  assurance_basis: AssuranceBasis[]; // Explains the authority, but does NOT compute a separate boolean.
  confidence_score: number; // 0.0 to 1.0
  confidence_basis: ConfidenceBasis[]; confidence_explanation: string;
  target_artifact_ref?: StorageRef; target_version_ref?: StorageRef;
  target_scope_ref?: ArtifactScopeRef; target_criterion_id?: string; affected_claim_refs?: string[];
  evidence_refs: StorageRef[]; verification_record_refs: StorageRef[];
  based_on_artifact_version_ref?: StorageRef;
  based_on_artifact_version_absent_reason?: "non_artifact_target" | "human_review_no_artifact" | "process_observation";
  based_on_source_workspace_snapshot_ref?: StorageRef; based_on_board_digest_ref?: StorageRef;
  taint_class: TaintClass; data_class: "public" | "internal" | "privileged" | "local_only";
  matter_id?: string; privileged: boolean; policy_decision_refs: PolicyEvaluationRef[];
  evaluation_target_state: "current_artifact" | "candidate_artifact" | "sandboxed_candidate";
  candidate_artifact_version_ref?: CandidateArtifactVersionRef;
  match_key: FindingMatchKey; superseded_by_finding_id?: string;
  expires_at?: ISO8601; created_at: ISO8601; schema_version: "2.0";
}
```

#### 2. §G — The 21-row Professional Reliance Layer

**Verdict: Partially scope creep.**

The *data primitives* in §G (G-01 `EvaluationContractReview`, G-02 `RevisionReviewPacket`, G-03 `EvidencePackage`, G-06 `TaskReliancePacket`) are absolute gold. They are net-new, strictly required for a litigator to trust the system, and properly scoped to the architecture.

The *UI rows* are scope creep. G-12 (`WorkProductCertification`), G-14 (`RunDiff`), G-15 (`DecisionAuditView`), and G-16 (`RunReplayPreview`) do not belong in an architectural spec. They are just front-end renders of the primitives you already defined. You should **CUT** G-12, G-14, G-15, and G-16 to keep the spec focused on the data layer.

#### 3. B-24: Revisor Sufficiency-Detection Algorithm

**Right detection contract.** Your trigger set perfectly covers the four ways an LLM agent gets stuck: missing tools (`no_capability`), asymptote looping (`max_attempts`), search-space exhaustion (`all_candidate_procedures_exhausted`), and missing priors (`evidence_insufficient`).

Routing to a Hard Call is exactly correct. When a deterministic protocol detects unresolvable insufficiency, it *must* halt and ask the human; silent fallback here is how agents hallucinate.

**Exact Schema:**

TypeScript

```
interface SufficiencyDetectionResult {
  outcome_id: string;
  no_sufficient_procedure: boolean; // Computed boolean. If true, halt and escalate.
  triggered_by: Array<
    | "no_capability_covers_outcome"
    | "max_attempts_without_score_improvement"
    | "all_candidate_procedures_exhausted"
    | "evidence_insufficient_to_proceed"
  >;
  attempts_made: number; 
  best_score_seen?: CalibratedScore;
  recommended_escalation_route: "hard_call_human_judgment" | "hard_call_missing_information" | "abort_outcome";
  schema_version: "1.0";
}
// RULE: If no_sufficient_procedure === true, Revisor MUST emit recommended_escalation_route 
// and immediately instantiate a HardRevisionCall. validation.unhandled_revisor_insufficiency (error).
```





This is the exact deep dive required. When we look past the structural flow of the **Adjudication Card (V0.1-V0.6 Consolidated)** and audit the *actual mathematical formulas, aggregations, and technical execution functions* written into its proposed schemas, several critical bugs emerge.

The card proposes mathematical fixes (like C-02, C-04, C-09) that introduce **divide-by-zero errors, float-precision masking, underflows, and memory leaks.**

Here is the exhaustive quantitative and technical-function audit of the Adjudication Card’s proposed fixes, along with the concrete schema patches needed to make the math actually execute.

### 1. The Divide-by-Zero Reputation Trap (Row C-04)

**The Card's Proposed Fix:**

TypeScript

```
unweighted_regression_rate: number; // regression_count / accepted_count
severity_weighted_penalty_score: number; // ((minor*1)+(major*2)+(critical*5)) / accepted_count
```

**The Mathematical Flaw:** The denominator is `accepted_count`. If a sub-agent provides advice that is completely rejected by the Evaluator/Revisor, its `accepted_count` is `0`. If that rejected advice contained a critical hallucination, the math attempts to divide by `0`, resulting in `NaN` or a runtime crash. Furthermore, a rate of regression must be measured against the total number of *attempts* or *interventions*, not just the ones that were accepted.

**The Patch:**

TypeScript

```
advice_regression_rate: {
  total_advice_rendered_count: number; // MUST be the denominator
  accepted_count: number;
  regression_introduced_count: number;
  unweighted_regression_rate: number; // regression_introduced_count / total_advice_rendered_count
  severity_weighted_penalty_score: number; // ((minor*1)+(major*2)+(critical*5)) / total_advice_rendered_count
}
```

### 2. Float-Precision Masking in Tie-Breakers (Row B-16)

**The Card's Proposed Fix:**

Plaintext

```
4. RevisionPlan.plan_risk_score descending 
5. RevisionCostEstimate.total_tokens ascending 
```

**The Technical Flaw:** This is a lexicographical sort. `plan_risk_score` is a continuous float (e.g., `0.8124` vs `0.8125`). In computing, two continuous floats derived from LLM probabilities or risk formulas will almost *never* exactly equal each other. Because Rule 4 will almost never tie, Rule 5 (`total_tokens` / speed) will practically **never be evaluated**. Fast plans will be stuck behind slow plans because of a 0.0001 difference in risk score.

**The Patch:** Rule 4 must use an **epsilon-banded** or binned comparison to allow meaningful ties.

Plaintext

```
RULE concurrency_tie_breaker (UPDATED):
// ... rules 1-3 ...
4. plan_risk_score descending (Banded: Treat scores within ε (e.g., 0.05) as a tie)
5. total_tokens ascending (Executes ONLY if risk scores are within the ε band)
```

### 3. The Soft-Penalty Underflow Risk (Row C-09)

**The Card's Proposed Fix:**

Plaintext

```
computeTemplateOverallScore(): weighted mean / totalWeight, minus softPenaltySum, capped at hard_veto_cap
```

**The Mathematical Flaw:** C-09 establishes that scores are bounds-checked (e.g., `[0,1]`). If the `weighted_mean` evaluates to `0.4`, and the accumulated `softPenaltySum` evaluates to `0.6`, the formula returns `-0.2`. Passing a negative template match score downstream will break probability distributions and confidence metrics that strictly expect normalized `[0, 1]` or `[0, 100]` ranges.

**The Patch:** The subtraction must be mathematically clamped to the floor of the range.

Plaintext

```
computeTemplateOverallScore(): 
Math.min( hard_veto_cap, Math.max( 0.0, (weighted_mean / totalWeight) - softPenaltySum ) )
```

### 4. The Percentile Memory Leak on Local Hardware (Row C-05)

**The Card's Proposed Fix:**

TypeScript

```
latency_distribution: { p50_duration_ms: number; p90_duration_ms: number; sample_size: number; }
```

**The Technical Flaw:** To compute an exact $P_{50}$ (median) and $P_{90}$ over a continuous stream of latency data (e.g., tracking every module execution), the system must store every single integer in an ever-growing array, then sort it. For a local-first system designed for privacy, maintaining unbounded arrays in memory for every module just to compute latency percentiles is a classic memory leak.

**The Patch:** The schema must explicitly define a rolling window or a streaming approximation algorithm (like t-digest or Exponential Moving Percentile) so the state size remains $O(1)$.

TypeScript

```
latency_distribution: { 
  p50_duration_ms: number; 
  p90_duration_ms: number; 
  sample_size: number; 
  computation_method: "exact_rolling_window" | "t_digest_approximation";
  rolling_window_limit?: number; // E.g., 1000. Drops oldest data to prevent OOM.
}
```

### 5. In-Flight Dilution in Survivorship Bias Math (Row C-02)

**The Card's Proposed Fix:**

Plaintext

```
Metric: wasted_cycle_burn_rate
  Denominator: total revision cycles executed globally
```

**The Mathematical Flaw:** The denominator "total revision cycles executed globally" includes cycles that are *currently in-flight* (neither succeeded nor failed yet). If you spin up 50 parallel tasks, your denominator spikes, artificially suppressing the `wasted_cycle_burn_rate` to look near zero until those tasks fail. Rates of terminal states MUST be measured against other terminal states.

**The Patch:** ```text

Metric: wasted_cycle_burn_rate

Denominator: cycles spent on OUTCOMES THAT HAVE REACHED A TERMINAL STATE (satisfied, aborted, unrecoverable)

Numerator: cycles spent on outcomes that ultimately aborted or reached 'unrecoverable'

```
### 6. Missing Penalty Weight in Quality Aggregation (Row C-01)
**The Card's Proposed Fix:**
```typescript
interface QualityIndex {
  missing_dimension_policy: "fail_required" | "exclude_optional_with_penalty" | "indeterminate";
}
```

**The Mathematical Flaw:** If the `missing_dimension_policy` is `exclude_optional_with_penalty`, what is the mathematical value of the penalty? The schema provides no field to define the penalty weight. The aggregation function cannot subtract a string.

**The Patch:** ```typescript

interface QualityIndex {

missing_dimension_policy: "fail_required" | "exclude_optional_with_penalty" | "indeterminate";

missing_dimension_penalty_value?: number; // REQUIRED if policy is "exclude_optional_with_penalty"

}

```
### 7. Confidence Merging in Pattern C Overrides (Row A-04)
**The Card's Proposed Fix:**
```typescript
judge_can_override_evaluator: boolean;
override_allowed_only_for_finding_states: FindingState[];
```

**The Technical Flaw:** When Pattern C dictates that the Judge's quantitative score overrides the Evaluator's qualitative score, how is the `confidence_score` of the final merged `EvaluationResultEnvelope` calculated? If the Evaluator was 90% confident it failed, and the Judge is 60% confident it passed, and the policy lets the Judge win, emitting a final envelope with "Pass" and "90% confidence" (stealing the Evaluator's confidence) is mathematically fraudulent.

**The Patch:** The resolution policy must define the confidence aggregation function.

TypeScript

```
interface EvaluationChainResolutionPolicy {
  // ... existing fields ...
  confidence_merge_strategy: "take_winning_node_confidence" | "average" | "take_lowest" | "discount_by_disagreement";
}
```

### Summary of the Math Audit

If you implement the Adjudication Card exactly as written, the architecture will route correctly, but the telemetry, sorting, and scoring will break at runtime. To finalize the spec, you must:

1. Apply the **divide-by-zero guards** to reputation (C-04).
2. Apply the **epsilon-banding** to the tie-breaker floats (B-16).
3. Apply the **clamping limits** to the penalty subtractors (C-09).
4. Apply the **O(1) memory bound** to the latency trackers (C-05).