A. EVERY TEXT/BLOB COLUMN IN SCHEMA_V16 — 28 tables

   arity_era                effective_at
   arity_inventory          edge_id, user_id, pre_invalidated_at, pre_reason
   confirmations            id, user_id, edge_id, confirmed_at, actor, call_path, correlation_id, request_digest, origin, recorded_correlation_id, origin_store, origin_user, origin_act_id
   consolidation_ops        operation_id, user_id, state, owner, lease_expires_at, claimed_ids
   contribution_ledger      id, user_id, survivor_type, survivor_id, site, identity_digest, evidence_ref_digest, payload, op_key, created_at, contributor_type, contributor_ref
   edge_embedding           edge_id, user_id, embedder_id, content_digest, vec, built_at
   edge_event               user_id, edge_id, kind, reason, state, recorded_at
   edges                    id, user_id, subject ←DUPLICATES json, relation ←DUPLICATES json, object ←DUPLICATES json, json
   episode_event            user_id, episode_id, kind, reason, state, recorded_at
   episodes                 id, user_id, date, json
   migration_op             op_id, mode, inputs_digest, admitted_at
   migration_outcome        plan_id, user_id, edge_id, outcome, pre_invalidated_at, pre_reason, successor_evidence, origin, outcome_uid, undone_at, undo_request_ref, op_id
   migration_run            plan_id, user_id, op_id, committed_at
   plan_header              plan_id, effective_at, registry_digest, op_id
   policy_receipt           user_id, recall_id, policy_id, policy_version, recorded_at, receipt
   reclassification_plan    plan_id, relation, from_arity, to_arity
   redactions               id, user_id, target_kind, target_id, fields, reason, event_ref, recorded_at, source_body, source_origin, source_user, source_event_ref, state, pending_reason
   refusal_inventory        refusal_id, user_id
   replies                  id, user_id, edge_id, kind, target, text, actor, correlation_id, request_digest, origin, recorded_correlation_id, origin_store, origin_user, origin_act_id, written_at
   request_registry         user_id, correlation_id, verb, target_edge_id, request_digest, result_ref, written_at
   source_revocations       user_id, identity_digest, action, at, reason
   store_epoch              started_at
   store_identity           origin
   supersession_operations  user_id, operation_id, logical_request_digest, status, request_digest, response, request_digest_domain
   supersession_refusals    refusal_id, user_id, prior_edge_id, incoming_edge_id, relation, rule_version, created_at
   wiki                     user_id, text
   write_counter            user_id

   → 3 columns duplicate a json field: ['edges.subject', 'edges.relation', 'edges.object']
     INV-2 must plant a mutant PER COLUMN, enumerated from here.
     Every other TEXT column above is a candidate carrier §2 must
     name or explicitly record as a non-carrier.

B. Model fields that can carry TEXT — the DDL is blind to these
   19 models DISCOVERED in veracium.schema, never named: AgreementRecord, Confirmation, ConsolidationOp, ConsolidationOutputDraft, ContestedGroup, ContestedLinkage, ContributionDraft, ContributionRecord, CorrectionAuthorisation, Edge, Episode, OutcomeJudgmentDraft, Provenance, Relation, Reply, SupersessionPlan, SupersessionRefusal, SupersessionRefusalDraft, SupersessionResult

     AgreementRecord.markers                     list[str]
     AgreementRecord.direction                   <class 'str'>
     AgreementRecord.lexicon                     <class 'str'>
     Confirmation.edge_id                     <class 'str'>
     Confirmation.correlation_id              <class 'str'>
     Confirmation.request_digest              <class 'str'>
     ConsolidationOp.operation_id                <class 'str'>
     ConsolidationOp.owner                       <class 'str'>
     ConsolidationOp.lease_expires_at            <class 'str'>
     ConsolidationOp.claimed_ids                 list[str]
     ConsolidationOutputDraft.summary                     <class 'str'>
     ConsolidationOutputDraft.date_start                  <class 'str'>
     ConsolidationOutputDraft.date_end                    <class 'str'>
     ContestedGroup.subject                     <class 'str'>
     ContestedGroup.relation                    <class 'str'>
     ContestedGroup.exposed.id                  <class 'str'>
     ContestedGroup.exposed.user_id             <class 'str'>
     ContestedGroup.exposed.subject             <class 'str'>
     ContestedGroup.exposed.relation            <class 'str'>
     ContestedGroup.exposed.object              <class 'str'>
     ContestedGroup.exposed.note                <class 'str'>
     ContestedGroup.exposed.provenance.evidence_ref<class 'str'>
     ContestedGroup.exposed.provenance.source_idstr | None
     ContestedGroup.exposed.provenance.origin   str | None
     ContestedGroup.exposed.invalidation_reason str | None
     ContestedGroup.exposed.supersedes          str | None
     ContestedGroup.exposed.original_relation   str | None
     ContestedGroup.exposed.agreement.markers   list[str]
     ContestedGroup.exposed.agreement.direction <class 'str'>
     ContestedGroup.exposed.agreement.lexicon   <class 'str'>
     ContestedGroup.exposed.src                 str | None
     ContestedGroup.exposed.attv                str | None
     ContestedGroup.exposed.outcome_counts      dict[str, int]
     ContestedGroup.linkage.edge_id             <class 'str'>
     ContestedGroup.linkage.partition           <class 'str'>
     ContestedGroup.prior_edge_ids              list[str]
     ContestedLinkage.edge_id                     <class 'str'>
     ContestedLinkage.partition                   <class 'str'>
     ContributionDraft.site                        <class 'str'>
     ContributionDraft.survivor_type               <class 'str'>
     ContributionDraft.survivor_id                 <class 'str'>
     ContributionDraft.contributor_type            <class 'str'>
     ContributionDraft.contributor_id              <class 'str'>
     ContributionRecord.survivor_type               <class 'str'>
     ContributionRecord.survivor_id                 <class 'str'>
     ContributionRecord.site                        <class 'str'>
     ContributionRecord.identity_digest             str | None
     ContributionRecord.evidence_ref_digest         str | None
     ContributionRecord.op_key                      str | None
     ContributionRecord.contributor_type            str | None
     ContributionRecord.contributor_ref             str | None
     CorrectionAuthorisation.origin                      <class 'str'>
     CorrectionAuthorisation.prior_edge_id               <class 'str'>
     CorrectionAuthorisation.replacement_digest          <class 'str'>
     CorrectionAuthorisation.kind                        <class 'str'>
     CorrectionAuthorisation.principal                   <class 'str'>
     Edge.subject                     <class 'str'>
     Edge.relation                    <class 'str'>
     Edge.object                      <class 'str'>
     Edge.note                        <class 'str'>
     Edge.provenance.evidence_ref     <class 'str'>
     Edge.provenance.source_id        str | None
     Edge.provenance.origin           str | None
     Edge.invalidation_reason         str | None
     Edge.supersedes                  str | None
     Edge.original_relation           str | None
     Edge.agreement.markers           list[str]
     Edge.agreement.direction         <class 'str'>
     Edge.agreement.lexicon           <class 'str'>
     Edge.src                         str | None
     Edge.attv                        str | None
     Edge.outcome_counts              dict[str, int]
     Episode.date                        <class 'str'>
     Episode.summary                     <class 'str'>
     Episode.provenance.evidence_ref     <class 'str'>
     Episode.provenance.source_id        str | None
     Episode.provenance.origin           str | None
     Episode.kind                        <class 'str'>
     Episode.edge_id                     str | None
     Episode.context_ref                 str | None
     Episode.retired_reason              str | None
     Episode.supersedes_episode          str | None
     Episode.claimed_by                  str | None
     Episode.operation_id                str | None
     Episode.lineage                     list[str] | None
     Episode.date_start                  str | None
     Episode.date_end                    str | None
     OutcomeJudgmentDraft.event_timestamp             <class 'str'>
     OutcomeJudgmentDraft.summary                     <class 'str'>
     OutcomeJudgmentDraft.context_ref                 str | None
     Provenance.evidence_ref                <class 'str'>
     Provenance.source_id                   str | None
     Provenance.origin                      str | None
     Relation.name                        <class 'str'>
     Relation.desc                        <class 'str'>
     Reply.edge_id                     <class 'str'>
     Reply.target                      str | None
     Reply.text                        str | None
     Reply.correlation_id              <class 'str'>
     Reply.request_digest              <class 'str'>
     SupersessionPlan.incoming_edge.id            <class 'str'>
     SupersessionPlan.incoming_edge.user_id       <class 'str'>
     SupersessionPlan.incoming_edge.subject       <class 'str'>
     SupersessionPlan.incoming_edge.relation      <class 'str'>
     SupersessionPlan.incoming_edge.object        <class 'str'>
     SupersessionPlan.incoming_edge.note          <class 'str'>
     SupersessionPlan.incoming_edge.provenance.evidence_ref<class 'str'>
     SupersessionPlan.incoming_edge.provenance.source_idstr | None
     SupersessionPlan.incoming_edge.provenance.originstr | None
     SupersessionPlan.incoming_edge.invalidation_reasonstr | None
     SupersessionPlan.incoming_edge.supersedes    str | None
     SupersessionPlan.incoming_edge.original_relationstr | None
     SupersessionPlan.incoming_edge.agreement.markerslist[str]
     SupersessionPlan.incoming_edge.agreement.direction<class 'str'>
     SupersessionPlan.incoming_edge.agreement.lexicon<class 'str'>
     SupersessionPlan.incoming_edge.src           str | None
     SupersessionPlan.incoming_edge.attv          str | None
     SupersessionPlan.incoming_edge.outcome_countsdict[str, int]
     SupersessionPlan.operation_id                <class 'str'>
     SupersessionPlan.expected_state              <class 'str'>
     SupersessionPlan.refusals.prior_edge_id      <class 'str'>
     SupersessionPlan.refusals.incoming_edge_id   <class 'str'>
     SupersessionPlan.refusals.relation           <class 'str'>
     SupersessionPlan.contribution_drafts.site    <class 'str'>
     SupersessionPlan.contribution_drafts.survivor_type<class 'str'>
     SupersessionPlan.contribution_drafts.survivor_id<class 'str'>
     SupersessionPlan.contribution_drafts.contributor_type<class 'str'>
     SupersessionPlan.contribution_drafts.contributor_id<class 'str'>
     SupersessionRefusal.refusal_id                  <class 'str'>
     SupersessionRefusal.prior_edge_id               <class 'str'>
     SupersessionRefusal.incoming_edge_id            <class 'str'>
     SupersessionRefusal.relation                    <class 'str'>
     SupersessionRefusal.rule_version                <class 'str'>
     SupersessionRefusalDraft.prior_edge_id               <class 'str'>
     SupersessionRefusalDraft.incoming_edge_id            <class 'str'>
     SupersessionRefusalDraft.relation                    <class 'str'>

   136 text-capable fields, RECURSED through nested models.
   Every one lives inside a json blob and is invisible to the schema.

C. TRIAGE -- carriers, DERIVED from persistence and value-space bounds
   93 TERMINAL (model, field) identities behind 148 paths.

   -> 73 CARRIERS. Each must be named in 0041 section 2, or recorded there as an explicit exclusion.
      AgreementRecord.direction                [nested in Edge (json blob)]
      [also reachable as ContestedGroup.exposed.agreement.direction, Edge.agreement.direction, SupersessionPlan.incoming_edge.agreement.direction]
      AgreementRecord.lexicon                  [nested in Edge (json blob)]
      [also reachable as ContestedGroup.exposed.agreement.lexicon, Edge.agreement.lexicon, SupersessionPlan.incoming_edge.agreement.lexicon]
      AgreementRecord.markers                  [nested in Edge (json blob)]
      [also reachable as ContestedGroup.exposed.agreement.markers, Edge.agreement.markers, SupersessionPlan.incoming_edge.agreement.markers]
      Confirmation.correlation_id           [RULED carrier -> confirmations]
      Confirmation.edge_id                  [RULED carrier -> confirmations]
      Confirmation.id                       [RULED carrier -> confirmations]
      Confirmation.request_digest           [RULED carrier -> confirmations]
      Confirmation.user_id                  [RULED carrier -> confirmations]
      ConsolidationOp.claimed_ids              [IS the row -> consolidation_ops]
      ConsolidationOp.lease_expires_at         [IS the row -> consolidation_ops]
      ConsolidationOp.operation_id             [IS the row -> consolidation_ops]
      ConsolidationOp.owner                    [IS the row -> consolidation_ops]
      ConsolidationOp.user_id                  [IS the row -> consolidation_ops]
      ContributionDraft.contributor_id           [RULED carrier -> contribution_ledger]
      [also reachable as SupersessionPlan.contribution_drafts.contributor_id]
      ContributionDraft.contributor_type         [RULED carrier -> contribution_ledger]
      [also reachable as SupersessionPlan.contribution_drafts.contributor_type]
      ContributionDraft.site                     [RULED carrier -> contribution_ledger]
      [also reachable as SupersessionPlan.contribution_drafts.site]
      ContributionDraft.survivor_id              [RULED carrier -> contribution_ledger]
      [also reachable as SupersessionPlan.contribution_drafts.survivor_id]
      ContributionDraft.survivor_type            [RULED carrier -> contribution_ledger]
      [also reachable as SupersessionPlan.contribution_drafts.survivor_type]
      ContributionRecord.contributor_ref          [IS the row -> contribution_ledger]
      ContributionRecord.contributor_type         [IS the row -> contribution_ledger]
      ContributionRecord.evidence_ref_digest      [IS the row -> contribution_ledger]
      ContributionRecord.id                       [IS the row -> contribution_ledger]
      ContributionRecord.identity_digest          [IS the row -> contribution_ledger]
      ContributionRecord.op_key                   [IS the row -> contribution_ledger]
      ContributionRecord.site                     [IS the row -> contribution_ledger]
      ContributionRecord.survivor_id              [IS the row -> contribution_ledger]
      ContributionRecord.survivor_type            [IS the row -> contribution_ledger]
      ContributionRecord.user_id                  [IS the row -> contribution_ledger]
      Edge.attv                     [json blob]
      [also reachable as ContestedGroup.exposed.attv, SupersessionPlan.incoming_edge.attv]
      Edge.id                       [json blob]
      [also reachable as ContestedGroup.exposed.id, SupersessionPlan.incoming_edge.id]
      Edge.invalidation_reason      [json blob]
      [also reachable as ContestedGroup.exposed.invalidation_reason, SupersessionPlan.incoming_edge.invalidation_reason]
      Edge.note                     [json blob]
      [also reachable as ContestedGroup.exposed.note, SupersessionPlan.incoming_edge.note]
      Edge.object                   [json blob]
      [also reachable as ContestedGroup.exposed.object, SupersessionPlan.incoming_edge.object]
      Edge.original_relation        [json blob]
      [also reachable as ContestedGroup.exposed.original_relation, SupersessionPlan.incoming_edge.original_relation]
      Edge.outcome_counts           [json blob]
      [also reachable as ContestedGroup.exposed.outcome_counts, SupersessionPlan.incoming_edge.outcome_counts]
      Edge.relation                 [json blob]
      [also reachable as ContestedGroup.exposed.relation, SupersessionPlan.incoming_edge.relation]
      Edge.src                      [json blob]
      [also reachable as ContestedGroup.exposed.src, SupersessionPlan.incoming_edge.src]
      Edge.subject                  [json blob]
      [also reachable as ContestedGroup.exposed.subject, SupersessionPlan.incoming_edge.subject]
      Edge.supersedes               [json blob]
      [also reachable as ContestedGroup.exposed.supersedes, SupersessionPlan.incoming_edge.supersedes]
      Edge.user_id                  [json blob]
      [also reachable as ContestedGroup.exposed.user_id, SupersessionPlan.incoming_edge.user_id]
      Episode.claimed_by               [json blob]
      Episode.context_ref              [json blob]
      Episode.date                     [json blob]
      Episode.date_end                 [json blob]
      Episode.date_start               [json blob]
      Episode.edge_id                  [json blob]
      Episode.id                       [json blob]
      Episode.kind                     [json blob]
      Episode.lineage                  [json blob]
      Episode.operation_id             [json blob]
      Episode.retired_reason           [json blob]
      Episode.summary                  [json blob]
      Episode.supersedes_episode       [json blob]
      Episode.user_id                  [json blob]
      Provenance.evidence_ref             [nested in Edge (json blob)]
      [also reachable as ContestedGroup.exposed.provenance.evidence_ref, Edge.provenance.evidence_ref, Episode.provenance.evidence_ref, SupersessionPlan.incoming_edge.provenance.evidence_ref]
      Provenance.origin                   [nested in Edge (json blob)]
      [also reachable as ContestedGroup.exposed.provenance.origin, Edge.provenance.origin, Episode.provenance.origin, SupersessionPlan.incoming_edge.provenance.origin]
      Provenance.source_id                [nested in Edge (json blob)]
      [also reachable as ContestedGroup.exposed.provenance.source_id, Edge.provenance.source_id, Episode.provenance.source_id, SupersessionPlan.incoming_edge.provenance.source_id]
      Reply.correlation_id           [RULED carrier -> replies]
      Reply.edge_id                  [RULED carrier -> replies]
      Reply.id                       [RULED carrier -> replies]
      Reply.request_digest           [RULED carrier -> replies]
      Reply.target                   [RULED carrier -> replies]
      Reply.text                     [RULED carrier -> replies]
      Reply.user_id                  [RULED carrier -> replies]
      SupersessionRefusal.incoming_edge_id         [IS the row -> supersession_refusals]
      SupersessionRefusal.prior_edge_id            [IS the row -> supersession_refusals]
      SupersessionRefusal.refusal_id               [IS the row -> supersession_refusals]
      SupersessionRefusal.relation                 [IS the row -> supersession_refusals]
      SupersessionRefusal.rule_version             [IS the row -> supersession_refusals]
      SupersessionRefusal.user_id                  [IS the row -> supersession_refusals]
      SupersessionRefusalDraft.incoming_edge_id         [IS the row -> supersession_refusals]
      [also reachable as SupersessionPlan.refusals.incoming_edge_id]
      SupersessionRefusalDraft.prior_edge_id            [IS the row -> supersession_refusals]
      [also reachable as SupersessionPlan.refusals.prior_edge_id]
      SupersessionRefusalDraft.relation                 [IS the row -> supersession_refusals]
      [also reachable as SupersessionPlan.refusals.relation]


   RULED, against the write path (see RULINGS):
      Confirmation         CARRIER. Subset failed on `replayed` alone, and the model's own comment calls it `runtime only: True when returned for a replay` -- it is not a column. The model IS the confirmations row; INSERTed by SqliteStore.confirm_edge.
      ContestedGroup       NON-CARRIER as a storage SITE. `exposed`/`linkage`/`prior_edge_ids` are not columns: it is a view ASSEMBLED from rows, never written. Its text is Edge's, already carried above. (`partition` greps clean in store/ -- every hit is str.partition(), our word, their sense.)
      ContributionDraft    CARRIER. Subset failed on `contributor_id` alone, which is INSERTed into the column `contributor_ref` -- SqliteStore._write_contribution documents the rename in its own comment. The draft's content reaches disk.
      CorrectionAuthorisation NON-CARRIER as a replies row. It neared `replies` on two shared NAMES, `kind` and `origin`, which mean other things there. It is minted and verified inside SqliteStore.apply_supersession_plan, never INSERTed into any table.
      Reply                CARRIER. Subset failed on `replayed` alone, the runtime flag the Confirmation ruling names (`runtime only: True when returned for a replay`). The model IS the replies row; INSERTed by SqliteStore.add_reply.

   -> 0 UNRESOLVED -- shares a table's columns but is not a row.
      NOT defaulted into either pile: guessing non-carrier loses a real
      carrier, and that is the direction that costs something. Each needs
      one explicit ruling in 0041 section 2, recorded with its reason.

   -> 20 NON-CARRIERS, each with the reason it cannot carry text:
      ConsolidationOutputDraft.date_end                 TRANSIENT (never stored)
      ConsolidationOutputDraft.date_start               TRANSIENT (never stored)
      ConsolidationOutputDraft.summary                  TRANSIENT (never stored)
      ContestedGroup.prior_edge_ids           RULED non-carrier
      ContestedGroup.relation                 RULED non-carrier
      ContestedGroup.subject                  RULED non-carrier
      ContestedLinkage.edge_id                  TRANSIENT (never stored)
      ContestedLinkage.partition                TRANSIENT (never stored)
      CorrectionAuthorisation.kind                     RULED non-carrier
      CorrectionAuthorisation.origin                   RULED non-carrier
      CorrectionAuthorisation.principal                RULED non-carrier
      CorrectionAuthorisation.prior_edge_id            RULED non-carrier
      CorrectionAuthorisation.replacement_digest       RULED non-carrier
      OutcomeJudgmentDraft.context_ref              TRANSIENT (never stored)
      OutcomeJudgmentDraft.event_timestamp          TRANSIENT (never stored)
      OutcomeJudgmentDraft.summary                  TRANSIENT (never stored)
      Relation.desc                     TRANSIENT (never stored)
      Relation.name                     TRANSIENT (never stored)
      SupersessionPlan.expected_state           TRANSIENT (never stored)
      SupersessionPlan.operation_id             TRANSIENT (never stored)

   is_bounded fired on 0 of 20 non-carriers, as predicted: no
   text-capable field in veracium.schema has a closed value space. EVERY
   non-carrier is one because it never reaches disk -- NOT because its
   content is constrained. If storage changes, they become carriers at once.
