From 6cceddbbbb808dac23b29ab89221947e2806cc56 Mon Sep 17 00:00:00 2001 From: dp-web4 Date: Wed, 12 Aug 2026 18:16:10 -0700 Subject: [PATCH] =?UTF-8?q?audit(C372):=20entity-types=209th=20delta=20?= =?UTF-8?q?=E2=80=94=20the=20=C2=A72.1=20register=20cannot=20be=20applied?= =?UTF-8?q?=20to=20an=20entity,=20and=20the=20one=20shape=20it=20does=20va?= =?UTF-8?q?lidate=20certifies=20an=20empty=20registry=20as=20complete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 11th pass of the entity-types lineage (rotation C332+40). Target byte-frozen 29 days (blob a2dda417, 804 L, last moved 1354e4c2 #523 2026-07-14). ZERO mutation of the standard; one new audit document. Three findings, all executed rather than read: - C372-N1 (MED, sharpens C332-N1): entity-jsonld.schema.json $defs/EntityTypeRegistry describes itself as "Full registry of all 15 canonical entity types" and carries no minItems/maxItems/uniqueItems. Executed with negative controls: empty registry PASS, human x15 PASS, 1 entry PASS; "banana" and "agent" both FAIL (enum not vacuous). The corpus's own MUST-FAIL set already contains the proof — entity-invalid-018 ships entity_types: [] charged solely for an unrelated additionalProperties key; strip it and the empty "full registry" passes. Denominator: 5 registry-shaped docs (2 MUST-PASS, 3 MUST-FAIL). Class bounded 2 of 12 schemas; sibling (capability "all 6 levels", empty PASSES) routed, not charged. C160:88's ratified deflation engaged and partially sustained -> MED, not HIGH. - C372-N2 (MED, adjudicates C364-N3, credited): §13.4's accountability-frame table keys on WAKE/FOCUS/REST/DREAM/CRISIS. C364 measured the forward direction (1 of 5 is a state); this pass runs the operational complement through the SDK enum: 1 of 8 canonical metabolic states has a frame. WAKE is a transition trigger, FOCUS is a prose noun appearing once, CRISIS is prose describing TORPOR — and TORPOR, whose own spec description IS "Crisis mode when resources critically low", resolves to NO FRAME on the table that sets the accountability equation. MED on modality (§13.4 carries no MUST; the doc has 6 total). - C372-N3 (MED, net-new): the §2.1 register is structurally unreachable for any real entity — entity-jsonld.schema.json's top-level oneOf admits only EntityTypeInfo and EntityTypeRegistry. Executed on a real LCT from the standard's own vector file: the control (a valid `human` LCT) returns FAIL(shape), so the unreachability is structural, not type-dependent. An `agent` LCT PASSES the enforced schema and raises ValueError in the Python SDK, while Go (:381) and TS (:397) also reject it. This is the mechanism that let C368-N1 survive 145 days of green gates. C368-N1 CONFIRMED with zero increment (already at C368:123); adds the dates — `agent` entered 2026-03-20, the 15-value register was authored 3 days later, contradicting for 142 d. Deferral ledger 6 of 6 discharged, 4 NEGATIVE: d1 role-extension frozen (C292-N1 stands, 3rd pass); d2 3->3 (C332-N2 stands, 57 d); d3 contexts/entity.jsonld opened for the first time in 11 passes — term mappings only, no enum, escalation hypothesis REFUTED; d4 ROUTED not executed (C120->C121 corpus-sweep hazard), receiving slots named; d5 the RFC claims are substantively CORRECT and independently confirm C332-N3's 518+63=581 arithmetic; d6 no §10 contradiction and the summary IS indexed, confirming C364's scoping. v36 inbound set-difference: residue 8 files, 0 postdating C332 — NEGATIVE, recorded. §own-error: 5. Policy review FALSIFIED this pass's proposed headline ("§2.1 has zero enforcement") — three implementations enforce the 15 on real bindings, and C332:240/:419/:182 had already recorded it, so the lineage's own predecessor contained the falsifier. The narrower schema-layer claim survives as N3. N1's strongest evidence (entity-invalid-018) was the reviewer's, not this pass's — the MUST-FAIL set was never enumerated (v46 error). The class-bounding instrument returned 0 and was believed for one step. Two reviewer corrections were themselves WRONG and were not adopted (the §13.4 anchor :779-783 is exact, not :785; the pass counter is 7th per C332:416, not 8th) — and the reviewer's C332:243 cite was off by three lines, caught by verifying the citation that exposed the error. Also named for successors: sdk/web4/validation.py's validate() does NOT raise (raise_on_error=False), so any try/except harness reports 100% PASS on every input including negative controls — the reviewer's first independent run hit exactly this trap. Out-of-slot observations routed, deliberately not charged: sdk-test.yml path-filter, schema_registry.json content-drift, test_lct_jsonld_vectors.py:285-301's contradicting 15-value set. Accountability self-audit: not applicable — this diff adds one markdown audit document and creates no surface, no caller-drivable path, and no consequential act. Co-Authored-By: Claude Opus 5 (1M context) --- .../C372-entity-types-9th-delta-2026-08-12.md | 421 ++++++++++++++++++ 1 file changed, 421 insertions(+) create mode 100644 docs/audits/C372-entity-types-9th-delta-2026-08-12.md diff --git a/docs/audits/C372-entity-types-9th-delta-2026-08-12.md b/docs/audits/C372-entity-types-9th-delta-2026-08-12.md new file mode 100644 index 00000000..b2f36a4b --- /dev/null +++ b/docs/audits/C372-entity-types-9th-delta-2026-08-12.md @@ -0,0 +1,421 @@ +# C372 Audit: `entity-types.md` — 9th-Delta Re-Audit (11th Pass) + +**Date**: 2026-08-12 +**Auditor**: Autonomous session (Legion, web4 track) — firing `20260812-180000` +**Document**: `web4-standard/core-spec/entity-types.md` (804 lines, blob `a2dda417`) +**Lineage** (11 docs, inclusive rule — the origin `docs/audits/entity-types-internal-consistency-2026-05-22.md` +self-identifies as `# C8 Audit` and is glob-invisible under `C*`, but is cited by name in all successors; +C332 verified this and ruled the C326 glob trap does **not** bite here — not re-litigated): +C8 → C26 → C64 → C65 (remediation, 7 applied) → C104 → C137 → C176 → C214 (#523 Effector §4.8) → +C252 → C292 → C332 → **C372 (this audit)** +**Window**: `38d0bd89..HEAD` — 50 commits / 41 files, 2026-08-07 → 2026-08-12. **Rotation**: `C332 + 40`. + +## Headline: the standard's entity-type register cannot be applied to an entity, and the one document shape it *can* validate certifies an empty registry as complete + +Three findings, **zero mutation of the standard**, all executed rather than read. + +The through-line: `entity-types.md` §2.1 is the register of 15 canonical entity types. Its faithful +machine transcription — `schemas/entity-jsonld.schema.json` `$defs/EntityType` — is **structurally +unreachable for any real entity**, because that schema's top-level `oneOf` admits only +`EntityTypeInfo` and `EntityTypeRegistry`: documents *about* the taxonomy. Executed against a real +LCT from the standard's own vector file, the register schema returns `FAIL(shape)` even for a +perfectly valid `human` LCT. And the one shape it *does* accept — `EntityTypeRegistry`, described in +its own text as *"Full registry of all **15** canonical entity types"* — carries no cardinality +constraint at all: an empty registry validates, and the corpus's own invalid-vector set already +contains one. + +**The proposed headline of this pass was falsified in policy review and is recorded as own-error §E.1.** + +--- + +## §0. Gates + +**Step 0 (queue).** Canonical `/home/dp/ai-workspace/private-context/SESSION_FOCUS.md` read (not the +worktree copy). `[Legion]` items: 0a hestia-owned; 0b SERVED; 0c WIRED, awaits a vault-authorized +actor (PolicyGate W-deny — not circumvented); 0d IN MOTION (HUB track's PR); 0e SERVED; 0f owned by +the CBP Publisher track. **No greenlit item pre-empts the rotation.** + +**Step 0.5 (own standing blocks).** `gh pr list --repo dp-web4/web4 --state open --json number,title,headRefName` +returns **`[]`** — zero open PRs corpus-wide. There is no branch to attribute and no PR for +`pr_standing_blocks.py` to read, so **0.5 is CLEAR on the strongest available evidence** (an empty +set, not a filtered one). Recorded explicitly because the C330/C332 instrument note stands: a +`reviewDecision` field is not evidence, and the appended-head staleness bug in +`pr_standing_blocks.py` is still unfixed. Neither mattered this pass — there was nothing to read. + +--- + +## §0.5. Pre-registration (v26) — fixed before any measurement + +**Prior, stated as prediction.** C332 left a **6-row deferral ledger naming its own blind spots** +(d1–d6) and two sibling lineages routed carries here (C364-N3, C368-N1). Predictions: + +1. The target is frozen; **§A holds by construction and will not be narrated as a discovery.** +2. d1/d2 substrates are frozen ⇒ **NEGATIVE is the predicted outcome for both.** +3. d3 (`schemas/contexts/entity.jsonld`, never opened in 10 passes) was deferred on the hypothesis + that it is a **4th published description of the register** and would escalate C332-N1. + **Pre-registered:** if it carries no type enumeration, that hypothesis is **refuted**, and the + refutation gets published as prominently as a confirmation would have been. +4. **Pre-registered matcher set** for the novelty claims, fixed before searching: site identifiers + (`EntityTypeInfo`, `EntityTypeRegistry`, `entity-jsonld.schema`) **and** domain vocabulary + (`minItems`, `uniqueItems`, `cardinality`, `completeness`, `all 15`, `full registry`). + +**Denominators published up front (v40), because the inherited counter is ambiguous.** +Two different freeze counters have been conflated in this lineage's guards, so both are published: + +| counter | value at C372 | denominator | +|---|---|---| +| passes over blob `a2dda417` | **5th** (C214, C252, C292, C332, C372) | since `1354e4c2` (#523, 2026-07-14) — a **non-audit** mutation | +| lineage's "consecutive zero-mutation pass" | **7th** (C332 self-published as 6th at `C332:416`) | audits that mutated nothing | +| byte-freeze age | **29 days** | `1354e4c2` → today | + +Policy review proposed a third reading ("8th consecutive zero-mutation, counting from the C65 +remediation `5baa160f`"). **Not adopted** — `C332:416` pairs "6th consecutive zero-mutation pass" +with the byte-freeze narrative, so the successor value is 7. The disagreement is itself the point: +**the inherited counter is under-specified, which is why all three denominators appear above.** + +**In-window movement** (`38d0bd89..HEAD`, 50 commits / 41 files): `web4-standard/` **1**, +`web4-core/` **0**, `sdk/` **0**, `hub/` **19**, `docs/` **22**. **Target: 0.** +Every artifact this pass executes is also unmoved since C332 — `entity-jsonld.schema.json`, +`entity-taxonomy.json`, `entity-jsonld-validation.json`, `contexts/entity.jsonld` = **0 commits each**. + +--- + +## §A. Held by construction + +Target blob unchanged since C332's own audit commit (`git diff --stat c32a83c0..HEAD -- ` += empty). Therefore, **without re-narration**: the 7 C65 remediations, the §4-preamble count at +`:281`, and the 9 standing carries (C8-L3, C23-H1, C24-H1, B2/B9, B7, B10/B11, B12) all **HOLD**. +Design-questions C23-H1 / C24-H1 / B7 / B2 / B9 / B10 / B11 and **C292-N1** remain +operator-unanswered → **one** operator memo, not self-applied. + +--- + +## §B. The deferral ledger — 6 of 6 discharged, 4 negative + +C332 closed with an explicit instruction: *"Do NOT inherit that list as a mirror set — it is what +this pass did NOT measure."* Each row was executed independently. + +| row | subject | disposition | +|---|---|---| +| **d1** | C292-N1 author ruling | `git log` on `ontology/role-extension.{ttl,schema.md}` since C332 = **0 commits**. **NEGATIVE — C292-N1 STANDS**, unanswered, 3rd pass. | +| **d2** | C332-N2's 3 SDK `slashed` sites | `entity.py:74`, `entity.py:306`, `test_integration.py:1531` — **3→3**. **NEGATIVE — C332-N2 STANDS**, now 57 days live. | +| **d3** | `schemas/contexts/entity.jsonld`, never opened | **Opened for the first time in 11 passes.** 35 lines, `9dd8f06e` (2026-03-23). Defines **term mappings only** — `entity_type → web4:entityType` typed `xsd:string`, **no enum, no value constraint**. **The escalation hypothesis is REFUTED**: it is not a 4th published description of the register, and it places no constraint on entity type. (See §E.3 — it is *cited* as the `@context` by every document in §C.) | +| **d4** | the other 11 top-level schemas — do any ship MUST-PASS vectors contradicting their spec? | **ROUTED, not executed.** This is a corpus-wide sweep, not an `entity-types.md` question; executing it here would repeat the standing `KEY SIGNAL C120→C121` hazard (never batch a corpus-wide MUST sweep). A **bounded** slice was run instead — see §C.3 — which is in-slot because it bounds N1's own defect class. Receiving slots named in §F. | +| **d5** | `FRACTAL_ROLE_IDENTITY.md` + `RFC-COMPOSITE-ENTITY-IDENTITY.md` — anchors were gated, **claims** never read | Both assert *"Roles are first-class LCT entities (`entity-types.md:518`, MUST)"*. **The claim is substantively CORRECT**: `:579` = `Implementations MUST:` and `:581` = `- Support role LCTs as first-class entities`. Only the **anchor** is stale. **NEGATIVE on new substance — and it independently CONFIRMS C332-N3's arithmetic** (`518 + 63 = 581`, exact). C332-N3's remedy has **not** landed (`git grep -c "entity-types.md:518"` = C332 4, FRACTAL 2, RFC 1). | +| **d6** | `DICTIONARY_INTEGRATION_SUMMARY.md` vs §10 | No contradiction: the summary's *"first-class Web4 entities … living semantic bridges"* matches §2.1's Dictionary row and §10.1. **And the summary IS indexed** (`web4-standard/README.md`) ⇒ it is one of C364's 6 indexed siblings. **NEGATIVE — and it confirms C364's scoping** of its own unindexed-summary finding to `METABOLIC_STATES_INTEGRATION_SUMMARY.md` alone. | + +**v36 inbound set-difference, pre-registered bound.** `git grep -li "entity type\|entity_type\|entityType"` +over both audit trees = **57 files**; filename sweep `git grep -li "entity-types"` = **102 files**; +`comm -23` residue = **8 files**. Bounded to audit docs **postdating C332** (2026-08-07): **0 of 8**. +**NEGATIVE — recorded as such.** The instrument has yielded for five consecutive fires; this pass it +did not, and that is reported rather than quietly dropped. + +--- + +## §C. Net-new findings + +### C372-N1 (MED) — the register schema cannot count, and the corpus's own invalid set proves it +*Filed as a **sharpening of C332-N1**, not clean net-new — see the novelty qualification below.* + +`schemas/entity-jsonld.schema.json` `$defs/EntityTypeRegistry` describes itself: + +> `"description": "Full registry of all 15 canonical entity types."` + +Its only payload property is: + +```json +"entity_types": { "type": "array", "items": { "$ref": "#/$defs/EntityTypeInfo" }, + "description": "All entity type metadata entries." } +``` + +**No `minItems`, no `maxItems`, no `uniqueItems`, no `contains`.** (`additionalProperties: false` is +present, but constrains the *key set*, not the array.) The completeness assertion lives in prose in +the parent object; nothing in the construct can enforce it. + +**Executed** via the SDK's real validator (`validate(doc, "entity").valid`), controls first: + +| case | result | +|---|---| +| registry with all 15 real types (**control**) | PASS | +| `entity_types: []` — an empty *"full registry of all 15"* | **PASS** | +| `"human"` × 15 (duplicates) | **PASS** | +| registry with 1 entry | **PASS** | +| **neg control** — type `"banana"` | FAIL | +| **neg control** — type `"agent"` | FAIL | + +The negative controls fire, so the enum is not vacuous and the instrument is admissible. + +**The sharpest evidence is the corpus's own, and it is already shipped.** Denominator: the vector +file holds **5 registry-shaped documents — 2 MUST-PASS (`entity-valid-009`, `-010`) and 3 MUST-FAIL +(`entity-invalid-016`, `-017`, `-018`).** `entity-invalid-018` ships: + +```json +{ "@context": [...], "@type": "EntityTypeRegistry", "entity_types": [], "version": "1.0" } +``` + +— an **empty** "full registry of all 15", charged solely for `"error_kind": "additionalProperties"` +(the stray `version` key). **Removing `version` and re-validating: the empty registry PASSES.** The +standard's own conformance suite therefore contains a document that is empty-and-complete, and +objects only to an unrelated extra field. Meanwhile the two MUST-PASS registries are described by +their own authors as *"minimal with one entity type"* and *"two entity types"* — so the **vector +author and the schema author disagree about what `EntityTypeRegistry` is**, and both are green. + +**Class bounded (v40), 2 of 12.** An instrument over all 12 top-level schemas — parent object whose +title/description asserts completeness (`all N`, `full`, `complete`), carrying an array property with +no cardinality guard — returns exactly **2**: + +| schema | construct | claim | guards | +|---|---|---|---| +| `entity-jsonld.schema.json` | `EntityTypeRegistry.entity_types` | *"Full registry of all 15 canonical entity types"* | **NONE** | +| `capability-jsonld.schema.json` | `CapabilityFramework.levels` | *"Complete capability level framework with all 6 levels"* | **NONE** | + +The sibling was **executed too**: a `CapabilityFramework` with `levels: []` **PASSES**. It is *not* +charged here — it routes to the `lct-capability-levels` lineage (§F). + +**Deflating precedent engaged and partially sustained.** `C160:88` ratified a deflation for exactly +this shape: *"`constraints` `minItems` unenforced by v1 schema … Schema is permissive (doesn't forbid +<3); **under-enforcement, not contradiction**."* That precedent is real and it is why **this is MED, +not HIGH**. It does not fully apply: C160's case was *spec says N, schema is silent* — two artifacts. +Here the **schema's own description** asserts the cardinality, and the **standard's own MUST-PASS +vectors** certify instances that violate it. That is self-contradiction inside one artifact plus its +conformance suite. **Severity is capped at MED** because no shipping artifact is wrong today: the +SDK's producer `entity.py:353 entity_registry_to_jsonld()` does emit all 15 and validates. + +**Remedy is an author ruling, not an auditor edit** — the two readings are mutually exclusive: +either add `minItems: 15` / `uniqueItems: true` (if `EntityTypeRegistry` means *the* register), or +correct the description to *"A registry of entity type metadata entries"* (if it means *a* registry, +which is what the vector authors evidently assumed). **Not self-applied.** + +**Novelty, qualified (v44).** Site-identifier matchers over both audit trees: `EntityTypeRegistry` +**0 of 212**, `"full registry"` **0**, `EntityTypeInfo` **4** (C64/C176/C252/C332, all this lineage), +`entity-jsonld.schema` **3**. But the claim must be qualified twice, and both qualifications were +found by searching the **domain's** vocabulary rather than the site's identifier: + +1. **The identifier is overloaded.** `archive/reference-implementations/conformance_test_suite.py:435` + has an `EntityTypeRegistry` that is a registry *of entities* (`lct_id → type`), a different object. + A zero-hit grep on an overloaded identifier is weak evidence and is not relied on alone. +2. **C332 was one hop away.** `C332:218` reads: *"All 20 invalid cases in the file assert shape errors + only (missing field, wrong enum member, wrong JSON type, `additionalProperties`, `minItems`, + `uniqueItems`) — not one asserts a taxonomy-content error."* Same file, same instrument. C332 + charged *field-content* divergence of `EntityTypeInfo`; N1 charges *registry cardinality*. It is a + genuine increment, but it is **a sharpening of C332-N1 and is filed as one.** Claiming clean + net-new here would violate this session's own v44 rule against its own lineage. + `"all 15"` hits (7 files) were each read: all concern the **Rust/Python enum membership** + (C176-N1) — none the schema's completeness constraint. + +### C372-N2 (MED) — §13.4's accountability frame keys on a vocabulary that is not the metabolic register +*Adjudicating **C364-N3**, which routed this locus here and is **credited**, not superseded.* + +`entity-types.md:779-783` publishes, under §13.4 *Accountability Frames*: + +| Frame | Metabolic States | Meaning | +|---|---|---| +| Normal | WAKE, FOCUS | Standard accountability — agent chose this outcome | +| Degraded | REST, DREAM | Reduced capabilities acknowledged | +| Duress | CRISIS | Fight-or-flight — consequences beyond agent's control | + +**C364-N3 measured the forward direction** and stated it correctly: *"Five names. One — REST — is a +state of this specification."* It routed adjudication here and explicitly declined to adjudicate. +**C372 adds the operational complement — the reverse direction — executed, not read.** An +implementation does not hold a frame and look for states; it **holds a state and looks up the frame**. +Running the canonical register (`SDK web4/metabolic.py` `MetabolicState`, = `SOCIETY_METABOLIC_STATES.md` +§2.1–§2.8, two independent witnesses at 8) through the table verbatim: + +``` +ACTIVE -> NO FRAME REST -> Degraded +SLEEP -> NO FRAME HIBERNATION -> NO FRAME +TORPOR -> NO FRAME ESTIVATION -> NO FRAME +DREAMING -> NO FRAME MOLTING -> NO FRAME + +states with an accountability frame: 1 of 8 +frame keys that are not register states: ['WAKE', 'FOCUS', 'DREAM', 'CRISIS'] +``` + +**1 of 8.** And the three non-states are not near-misses; each was checked in the canonical document: + +- **`WAKE`** — appears 23× but never as a state. It is a **transition trigger** + (`SOCIETY_METABOLIC_STATES.md:181` *"Sleep → Active: Wake trigger fired"*). Its target state is `ACTIVE`. +- **`FOCUS`** — **1** occurrence, the English noun inside a prose description of Hibernation + (`:83` *"preservation focus"*). SDK **0**, vectors **0**. It is not a state and never was. +- **`CRISIS`** — 3 occurrences, all prose. SDK **0**, vectors **0**. Decisively, + **`:99` is the description of `TORPOR`: *"Crisis mode when resources critically low."*** +- **`DREAM`** — one character from `DREAMING`, and is not it. + +**The consequence is the accountability equation itself**, which the spec states in the very next +sentence (`:785`): *"CRISIS mode changes the **accountability equation**, not policy strictness."* +`TORPOR` is the state whose own definition **is** crisis mode — and it resolves to **no frame**, while +the key `CRISIS` matches nothing any implementation can emit. A society in emergency conservation +therefore falls through to whatever the implementer's default is, on the one table that decides +whether an agent is held fully accountable for an outcome. + +**Severity MED, not HIGH**, on modality: §13.4 is a descriptive table. `entity-types.md` carries **6** +`MUST`s in total and none is in §13.4, so no conformance clause is being violated — this is a +vocabulary that cannot bind, not a broken requirement. **Remedy is an author ruling** (map the frames +onto `ACTIVE/REST/DREAMING/TORPOR/…`, or state that §13.4's vocabulary is a distinct agent-level +register and cross-reference it) — **not self-applied**, and it touches a byte-frozen document. + +**Anchor verified.** C364-N3's citation `:779-783` is **exact** (header `:779`, separator `:780`, three +rows `:781-783`). Policy review asserted the table body *"runs to `:785`"*; `:785` is the following +prose sentence. **C364-N3's anchor stands; the review's correction is not adopted** — see §E.2. + +### C372-N3 (MED) — the §2.1 register is structurally unreachable for any real entity +*This is what survived the falsification of this pass's proposed headline. See §E.1.* + +`schemas/entity-jsonld.schema.json` is the only faithful 15-value transcription of §2.1 in the schema +layer. Its top level is: + +```json +"oneOf": [ { "$ref": "#/$defs/EntityTypeInfo" }, { "$ref": "#/$defs/EntityTypeRegistry" } ] +``` + +Both branches are **taxonomy-metadata** documents. `EntityTypeInfo.required` = +`entity_type, modes, energy, can_r6, description` — that is the description of a *type*, not an +*instance*. **The schema therefore never sees an entity.** + +**Executed** on a real LCT taken verbatim from the standard's own `lct-jsonld-validation.json` +(`valid[0]`), varying only `binding.entity_type`: + +| `entity_type` | enforced schema (`"lct"`) | Python SDK `LCT.from_jsonld` | register schema (`"entity"`) | +|---|---|---|---| +| `human` (**control**) | PASS | OK | **FAIL (shape)** | +| `agent` | **PASS** | **`ValueError: 'agent' is not a valid EntityType`** | **FAIL (shape)** | +| `banana` (**neg control**) | FAIL | `ValueError` | FAIL (shape) | + +The control carries the finding: the register schema returns `FAIL(shape)` for a **perfectly valid +`human` LCT**. The unreachability is structural, not a property of the type value. + +**Consequence.** A document that PASSES the standard's own default LCT validation path **crashes the +Python SDK**, and the declarative layer that knows the correct answer cannot be pointed at it. Three +implementations *do* enforce the 15 on real bindings — and each is an independent witness that §2.1 +is canonical: + +- Python — `sdk/web4/lct.py:51-68` (15 members), enforced at `lct.py:94` (`Binding.from_dict`) and + `:655` (`LCT.from_jsonld`) by enum coercion. Executed: `agent` → `ValueError`. +- Go — `ledgers/reference/go/lct/document.go:34-39` (`ValidEntityTypes`, 15), enforced at `:381`. +- TypeScript — `ledgers/reference/typescript/lct-document.ts:363-367` (15), enforced at `:397`. + +So the disagreement is **cross-layer**: the schema layer cannot reject `agent` on an entity, and the +code layer cannot accept it. This is the *mechanism* — it explains why the C368-N1 defect survived +145 days of green gates, which C368 established but did not account for. + +**Novelty.** `C368:123` publishes the row `| schemas/entity-jsonld.schema.json | 15 | no |` — C368 +recorded that this schema holds 15 and does not gate LCTs. It did **not** state the reachability +argument (that the schema is structurally inapplicable to *any* entity document, control included), +which is what N3 charges. Severity **MED**, not HIGH: no shipping artifact emits `agent` today. + +### C368-N1 — CONFIRMED, zero increment +The `agent` cross-schema contradiction is **already recorded at `C368:123`**. This pass re-executed it +(above) and confirms it, and adds two dates: `agent` entered the enforced enum at `c787452e` +(2026-03-20, #53) = **145 days** — matching C368's number exactly and independently; the 15-value +register schema was authored at `9dd8f06e` (2026-03-23), **three days later**, so the two have +contradicted each other for **142 days**. **Filed as confirmation with zero increment** — not as a +"second family member," which would imply an increment that does not exist. Route: C368's operator +ruling (`C368:175`), unchanged. + +--- + +## §D. Measurement hazards named for successors + +1. **`validate()` does not raise.** `sdk/web4/validation.py` `validate(document, schema_name, *, raise_on_error=False)` + **returns** a `ValidationResult`; it does not throw by default. **Any harness measuring this SDK via + `try/except` reports 100% PASS on every input, including negative controls.** This pass's instrument + read `.valid` (which is why its neg controls fired), but the policy reviewer's first independent + run hit exactly this trap and reported all seven cases PASS. Named here because it manufactures + precisely the false green that C332-N1 was charging. +2. **A completeness claim sits on the parent, the enforcement gap on the child.** This pass's first + class-bounding instrument scanned array constructs' *own* descriptions and returned **0 rows** — + missing the very case that motivated it. Corrected instrument (parent's title/description → child + array's guards) returns 2 of 12. Recorded in §E.4. + +--- + +## §E. Own-error log + +**E.1 — the proposed headline was falsified in policy review, and the falsifier was already in the +lineage.** This pass drafted as its headline: *"the only faithful machine transcription of §2.1 can +never be applied to an actual entity — §2.1 has zero enforcement over the objects it governs."* The +second clause is **false**. Three implementations enforce the 15 on real bindings (Python `lct.py:94`, +Go `document.go:381`, TS `lct-document.ts:397`), all verified and executed here. Worse: **`C332:240` +already recorded it verbatim** — *"No shipping implementation is wrong today: the Python SDK is 15/15"* — +with `C332:419` publishing the measurement as a gate row and `C332:182` calling it *"load-bearing … +it makes the Python SDK an independent witness for §2.1."* The immediately prior pass of this same +lineage contained the falsifier three separate times, and this pass did not check its own predecessor +before drafting. (Policy review cited this as `C332:243`; the correct loci are `:182`, `:240`, `:419` — +verified line by line, per §E.2's rule, including on the correction that exposed this error.) +The true, narrower claim (unreachability **within the schema layer**) survives as N3. The scope claim +"zero enforcement" was reached by measuring the schema layer and generalising to the corpus — the same +undeclared-denominator error v51 was written to prevent, committed one fire after writing it. + +**E.2 — two policy-review corrections were themselves wrong, and were not adopted.** (a) The review +gave the §13.4 table as `:779-785`; `:785` is the following prose sentence — C364-N3's `:779-783` is +exact. (b) The review corrected the pass counter to "8th consecutive zero-mutation"; `C332:416` +self-publishes "6th", making the successor 7. Both were checked against the files before rejection, +per the C366 rule that a reviewer's path tokens are verified like any other. The review's **substantive** +corrections — E.1, the `entity-invalid-018` evidence, the 5-document denominator, the C332:218 +novelty qualification, the C368:123 zero-increment ruling, routing d4 — were all verified and **adopted**. + +**E.3 — d3's finding was nearly published as a pure negative.** `contexts/entity.jsonld` carries no +enum, which refutes the escalation hypothesis. But it is the `@context` of every document in §C, and +its `entity_type → web4:entityType` mapping is typed `xsd:string` — i.e. the semantic layer also +places no constraint. That is corroboration for N3 and was almost dropped as "nothing found." + +**E.4 — the class-bounding instrument returned 0 and was believed for one step.** See §D.2. The +denominator 2-of-12 exists only because the null result was distrusted enough to re-run against a +known-positive case. + +**E.5 — "the corpus's own invalid set proves it" was not this pass's discovery.** N1's strongest +evidence (`entity-invalid-018`) was surfaced by the policy reviewer, not by the audit. This pass had +measured the schema and the two MUST-PASS vectors and stopped there, having never enumerated the +MUST-FAIL set — the same "denominator decides whether an absence is a finding" error as v46. + +--- + +## §F. Routing — nothing self-applied + +| item | routes to | +|---|---| +| **C372-N1** author ruling (`minItems: 15`+`uniqueItems` **or** correct the description) | operator / standard-editor | +| **C372-N1** sibling: `capability-jsonld.schema.json` `CapabilityFramework.levels`, *"all 6 levels"*, empty PASSES (executed) | **`lct-capability-levels` lineage** | +| **C372-N2** §13.4 frame vocabulary vs the 8-state register | operator / standard-editor; cross-ref **C364-N3** (credited) | +| **C372-N3** schema-layer unreachability | operator + SDK track; joins **C368-N1**'s operator ruling (`C368:175`) | +| **C368-N1** | CONFIRMED, zero increment — no new routing | +| **C292-N1** (3rd pass), **C332-N2** (57 d), **C332-N3** (remedy not landed) | STAND — existing routes | +| **d4** corpus-wide schema/vector sweep | **NOT executed** (C120→C121 hazard). Prior art: C328 did `lct-jsonld-vectors.json`, C322 the dictionary artifacts, C332 + C372 the entity artifacts. Remaining: `acp`, `atp`, `attestation-envelope`, `capability`, `dictionary`, `r7-action`, `t3v3` → **each to its own lineage slot**, one per pass. | + +**Out-of-slot observations, routed and deliberately NOT charged here** (surfaced while mapping N3's +enforcement surface; each belongs to another lineage and none was verified to audit depth): +`sdk-test.yml` is path-filtered to `implementation/sdk/**`, so edits to `web4-standard/schemas/**` +and `web4-standard/test-vectors/**` trigger no CI → **SDK/CI track**; the wheel-shipped +`sdk/web4/schema_registry.json` carries its own copy of all 12 schemas (including the 16-enum) with +no content-equality test against `web4-standard/schemas/` → **SDK track**; +`sdk/tests/test_lct_jsonld_vectors.py:285-301` hard-codes a **15**-value `valid_types` set and would +fail an `agent` vector, contradicting the schema it validates against → **LCT lineage, joins C368-N1**; +`web4-core/src/lct.rs` 9-variant enum → **already booked C176-N1, not re-raised.** + +--- + +## §G. Deferral ledger for the next pass (**C412**) — row count 5, members named + +**Do NOT inherit this as a mirror set — it is what C372 did *not* measure.** + +- **g1** — C372-N1/N2/N3 are all author rulings; check whether any landed, and whether + `entity-jsonld.schema.json` gained `minItems`/`uniqueItems` (one `git log`, one `grep`). +- **g2** — the two Specialized-Entity sections carry **9** sub-sections between them (§10.1–10.4, + §13.1–13.5). Only **one** — §13.4 — had its vocabulary checked against the sibling spec that owns it. + **Do the other eight name vocabularies owned by other specs?** Specifically: §10.2's + `dictionary_spec` / `compression_profile` / `trust_requirements` / `evolution` blocks were read this + pass but **not** cross-checked against `dictionary-entities.md`, and §13.3 (`PolicyGate: IRP-Backed + Evaluation`) names an IRP contract owned elsewhere entirely. +- **g3** — `entity-taxonomy.json` covers **5 of 15** types (`human, society, device, infrastructure, + oracle`); `entity-jsonld-validation.json` valid docs cover **10 of 15**. The union omits + `organization`, `role`, `task`, `service`, `hybrid` — **5 types with no vector anywhere.** Not charged + this pass (coverage ≠ defect, per v43), but it is the natural companion to N1's completeness question. +- **g4** — the §2.1 table's **Mode** and **Energy** columns were verified 15/15 against the SDK by + C332; they have **never** been verified against `entity-taxonomy.json`'s `expected` blocks, which is a + third witness. C332 found the two vector files agree on **0** of 5 shared types — that comparison was + never extended to §2.1 itself. +- **g5** — d5 is answered for the two RFC documents' *role* claim only. Their **composite-identity** + claims (P1/P2, `RFC-COMPOSITE-ENTITY-IDENTITY.md:66-95`) cite `LCT §2.1` and `t3-v3 §8.2`, not + entity-types, and were **not** read against §3/§7.2. + +**Next entity-types delta ≈ C412.**