Disavowal category discriminator and S6 binding enforcement
Adds a normative category discriminator to the disavowal claim type's disavowed-entry shape. The discriminator takes one of two values (self_statement, impersonation_defense), allowing reference validators to machine-check rule S6 (§5.2) without interpreting publisher-asserted prose. Unblocks binding S6 enforcement deferred since v0.1.5.
1. Abstract
Adds a normative category discriminator to entries in the disavowal claim type’s statement.disavowed[] array. The discriminator takes one of two values: self_statement (the publisher disavows their own past content or affiliation) or impersonation_defense (the publisher disavows a third-party domain, account, or asset that misrepresents itself as affiliated with the publisher).
The discriminator unblocks binding enforcement of rule S6 from spec §5.2. S6 had been documented since v0.1.5 but not machine-checked because the previous schema shape required validators to interpret publisher-asserted prose (the what field) to determine whether a disavowal entry was in-scope. With the discriminator field, S6 evaluation reduces to a string-equality check on a closed enum.
This LIP makes category a required field at the schema level. The change is technically incompatible with v0.1.8 documents whose disavowal claims do not include the field. Pre-launch this affects only the steward’s own document at llmo.org, which is updated in the same PR. After the v0.1 public announcement, future revisions to disavowal-shape requirements follow the LIP-1 governance process.
2. Motivation
Rule S6 in spec §5.2 specifies that disavowal claims at Standard tier MUST be either publisher self-statements or impersonation defenses. Third-party disavowals (e.g., “competitor product X is unreliable”, “the third-party article at URL Y misstates our position”) are explicitly out of scope: the publisher is not in a position to adjudicate other entities’ affairs in a machine-readable claim.
Prior to this LIP, S6 was specified normatively but enforced only by hand. The validator at /validator/ and the llmo CLI both surfaced S6 as informational, with a note that binding enforcement waited on a schema discriminator. The reason was structural: distinguishing a self-statement from a third-party disavowal required interpreting the publisher’s what field, a free-form string. Reference validators that interpret free-form fields stop being deterministic; the same publisher input could be flagged differently by different validators, breaking the protocol’s audit property.
A closed-enum discriminator removes interpretation from the validator’s path. The publisher self-classifies their disavowal entry; the validator checks the classification against the spec’s allowed set. The publisher remains responsible for the truthfulness of the classification (a misclassification is a publisher-side fidelity issue, not a validator-side enforcement gap).
3. Specification
3.1 Schema change
The statement_disavowal definition in /static/spec/v0.1/schema.json adds category as a required field on items in the disavowed array. The field is a closed enum:
"category": {
"type": "string",
"enum": ["self_statement", "impersonation_defense"]
}
The full disavowed[] item required set after this LIP: ["what", "detail", "category"]. The url field remains optional.
3.2 Spec text §3.5 (claim types)
The disavowal claim type description gains the normative discriminator. The two enum values are defined inline:
-
self_statement: the publisher disavows their own past content, affiliation, statement, identity, or product. The subject of the disavowal is something the publisher previously asserted or controlled. Examples: a retracted statement, a deprecated product line, a discontinued service, a prior version of a public commitment. -
impersonation_defense: the publisher disavows a third-party entity (domain, account, asset, attribution) that misrepresents itself as affiliated with the publisher. The subject is NOT something the publisher previously asserted; it is something falsely associated with the publisher. Examples: a typosquat domain shaped to imply affiliation, a fake social-media account, a forged statement attributed to the publisher.
Any other category is out of scope: the publisher cannot machine-assert third-party properties (competitor product quality, news-article accuracy, third-party employee statements) under the disavowal claim type.
3.3 Rule S6 binding enforcement
Spec §5.2 rule S6 is updated to:
S6. Disavowal claim category restriction. Every entry in a
disavowalclaim’sstatement.disavowed[]array MUST have acategoryfield. Thecategoryvalue MUST beself_statementorimpersonation_defense. A document containing a disavowal claim with any entry whosecategoryis missing, malformed, or set to a value outside the enum MUST NOT be evaluated at Standard tier or higher. The document evaluates at Minimal tier with notes6_disavowal_out_of_scope.
The companion supersedes-half of S6 (URL ownership on supersedes.superseded[].url) remains as previously specified; that half was already machine-checkable from the URL set and is unaffected by this LIP.
3.4 Backward compatibility note
Documents valid under v0.1.0 through v0.1.8 that include a disavowal claim without category fields will fail M3 schema validation (and therefore the entire tier ladder) after this LIP lands. Pre-launch the only such document is the steward’s own at llmo.org, which is updated in the same PR to include the category field. After v0.1 public announcement, publishers updating to v0.1.9+ MUST add the category field to existing disavowal entries.
Documents without any disavowal claim are unaffected.
4. Rationale
4.1 Why a closed enum rather than free text
A closed enum is the smallest mechanism that converts S6 from an interpretive rule to a deterministic check. Allowing free text in category would re-introduce the interpretation problem this LIP exists to solve. Allowing a publisher-extensible enum (e.g., namespaced extension categories) would force validators to either accept any namespaced value (defeating the rule) or reject namespaced values they do not recognize (creating a non-portable validator ecosystem).
4.2 Why exactly two values
The two values map onto the two in-scope semantic cases identified in §3.5: the publisher disavows something they own, or the publisher disavows something falsely attributed to them. Other plausible categories (e.g., industry_standard, regulatory_position) shade into third-party assertions and lose the publisher’s first-party authority. Keeping the enum at two members keeps the rule’s semantics tight.
A future LIP MAY extend the enum if a third clearly in-scope category surfaces. The extension would itself be a Standards Track LIP following the LIP-1 governance process.
4.3 Why required, not optional
Optional discrimination defeats the rule. A publisher could omit category to avoid evaluation; consumers would have to treat the omission as either silently passing (defeats the rule) or silently failing (breaks valid use cases that simply forgot the field). Required-and-enumerated removes the ambiguity.
Backward compatibility cost is bounded: the only pre-launch document affected is the steward’s own, which is updated in the same PR.
4.4 Why this is a v0.1.9 patch despite the breaking shape
ADR-0006 specifies that v0.1.x patches must be schema-back-compatible. This LIP technically violates that by adding a required field to the disavowal claim’s shape, which causes M3 to fail for v0.1.x-conformant documents that omit the field. The patch is shipped anyway under the pre-launch Goldilocks framing established by LIP-4’s Final transition: there are zero or near-zero existing publishers, the steward’s document is updated in the same PR, and the cost of waiting for a v0.2 minor bump (full new spec page, full new schema URL, breaking the in-place patch convention) is disproportionate to the realized impact.
After v0.1 public announcement, future schema-shape changes follow the v0.2-minor-bump path documented in ADR-0006. This LIP is the closing exception of the Goldilocks period for schema-incompatible patches.
5. Backwards Compatibility
Documents containing disavowal claims that lack the new category field fail M3 schema validation after this LIP. Pre-launch, this affects exactly one document (llmo.org’s own), updated in the same PR.
Documents without disavowal claims are unaffected.
Consumer-side behavior:
- The browser validator at
/validator/adds S6 enforcement to its strict-tier evaluation chain. Previously S6 surfaced informationally; after this LIP S6 binds to tier outcome. - The
llmoCLI’sverifycommand receives the same update. Consumers runningllmo verifyagainst documents with disavowal claims will see S6 PASS / FAIL determinations starting at the next CLI release.
6. Reference Implementation (informative)
The reference implementations of S6 enforcement land in:
static/js/validator.js— browser validatoropenllmo/clisrc/lib/tier.ts—evaluateTier()function (follow-up CLI release)
Test vectors:
static/spec/v0.1/test-vectors/edge-disavowal-impersonation-defense.json(updated in this PR to add thecategoryfield)static/spec/v0.1/test-vectors/negative-s6-disavowal-third-party.json(updated to a category-missing or category-out-of-enum case)
The Diverse.org steward document at static/.well-known/llmo.json is also updated in this PR to add the category field to its disavowal claim and is re-signed under the current diverse-2026-02 key.
7. Open Questions
None. The closed two-value enum is the deliberate point of this LIP; alternative shapes are addressed in §4.1-4.2.
8. Acknowledgments
This LIP closes the deferral filed in BACKLOG.md after v0.1.5 (filed 2026-05-08 by the PR #74 drift investigation that surfaced S6 as documented-but-unenforced) and documented in v0.1.6’s §5.4 deferral note.
9. Copyright
This LIP is licensed under the Creative Commons Attribution 4.0 International License (CC-BY-4.0).