Elnor Repo Reader

DOC23_CHATGPT Addenda_B_Final_Comprehensive_Red_Team_Review_R2_COMPLETE.md

Active Working and Red Team/DOC23 Working/DOC23 Red Teaming/Add B Adj Card Review 5.29/DOC23_CHATGPT Addenda_B_Final_Comprehensive_Red_Team_Review_R2_COMPLETE.md

Short text page 6ccde5610a9a. 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_CHATGPT Addenda_B_Final_Comprehensive_Red_Team_Review_R2_COMPLETE.md
Source repo: /Users/OpenClaw1/Elnor/Elnor Specs
Git branch: main
Git commit: dbaa25962edc11ab30e8d4ca1715f9ae5bf77331
Generated: 2026-06-09T01:23:58.539Z

---

# 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.