Releases: openbranddefinition/obds
Release list
OBDS 4.1.3
12 September 2026.
Public-surface and documentation release. PATCH.
OBDS 4.1.3 repairs the public and implementer surface and closes the release-gate
gap that let it drift. No normative contract, no schema, no value schema, no Task
Facts semantic, no suite identity, no governed hash, no conformance behaviour and
no conformance case count changed. The 1.0.0 contract surface stays frozen and
every contract fingerprint is unchanged against 4.1.2.
What moved
-
README.md, the page GitHub shows first and the README inside the release
archive, still named 4.1.0 as the current release, dated 9 September 2026. Its
repository table linkedOBDS-4.1.0.md,OBDS-4.1.0-IMPLEMENTER-QUICKSTART.md,
OBDS-4.1.0-TEST-RESULT.json,OBDS-4.1.0-CHANGELOG.mdand
OBDS-4.1.0-MIGRATION.md. Four of them left the root with 4.1.1 and the
changelog with 4.1.2, so the links to the specification, the quickstart and the
test result were dead.
It now names the current files and the current release, describes Task Facts
1.0 as published and optional, and states the 1.0.0 contract identity without
the release list that had to be edited every release and had stopped at 4.1.0. -
The public README said "OBDS 4.1.0 closes five production boundaries" and that
model_failed"makes this a major release". Those closures are 4.0.0, the
Production Boundary Closure release; the sentence had been carried forward by
version replacement since 4.0.x.OBDS-PUBLIC-README-4.1.3.mdcredits them to
4.0.0, says what 4.1.0 added and what 4.1.3 is. -
Task Facts status. The suite
README.mdintroduced itself as a "Prospective
OBDS 4.1.0 internal candidate", and the quickstart, architecture and
test-requirements documents called the release that carries Task Facts "this
prospective release". They now say that Task Facts 1.0 is published and
optional, added in 4.1.0 and unchanged since, and the suite README links the
current specification.ADOPTION.mdis the adoption record and keeps its text
byte for byte under a new status block that says the record predates
publication and that no production integration is claimed.
RUNNER-CONTRACT.mdis not edited: it is one of the suite identity files in
SUITE.json, so its bytes are part of the Task Facts suite hash. The suite
README says so instead. -
reference/release-gate.pystep 15 has said since 1.1.3 that it checks the
README and never checked its current release. The new step 15a does:README.mdmust carry
exactly one current release line with this release and its date, must name no
root document of another release, must link the current specification,
quickstart, test result, changelog and migration, and every relative link in it
must resolve in the repository. In an extracted archive, which flattens the
frozen contract surface, links intoschemas/andvalue-schemas/are not
resolved and every other link is. The
README, the public README, the current quickstart, architecture,
test-requirements and migration documents and the Task Facts suite README may
not describe another release in the present tense or anything as prospective.
The Task Facts suite README must state the published, optional status and the
productionIntegration: falselimitation, andADOPTION.mdmust open with
its status block. The release date is read from this changelog; the
specification's own Date: line and the public README must carry it, and in
the repositorypublication-record.jsonmust agree. -
Open Graph cards. The eight cards under
og/were rendered for 4.0.4, and the
cards published with 4.1.0, 4.1.1 and 4.1.2 still printed 4.0.4 on every social
preview, while the pages'og:image:altnamed the current release. A
re-render for 4.1.2 was prepared but never published.tools/build-og-images.pynow stamps
each card with the release it was rendered for, in a PNGtEXtchunk named
OBDS-Release, and its--checkreads the stamps back. The gate refuses a
missing, unreadable, unstamped or stale card in the repository,
tools/build-release.pyrefuses to build while one exists, and
tools/deploy-smoke-test.pyreads the stamps of the cards the site serves. The
cards are re-rendered for 4.1.3. -
tools/test-final-closure.pygains focused regressions for every new check,
including the README and the public README exactly as 4.1.2 shipped them, which
the gate now refuses for each defect they carried.
What did not move
No normative section, no schema, no value schema, no Task Facts contract,
fixture, vector, suite identity or evaluator behaviour, no TFJ or snapshot
identity, no governed hash, no Build Plan, Model Input Package or Runtime
Decision Record semantics, no conformance decision semantics, no conformance
case. spec/4.1.2/ and every earlier snapshot are byte-identical and their tags
are unchanged.
OBDS 2.0.0
MAJOR under section 27.1. It rejects governed YAML forms 1.x accepted and changes how one class of form resolves. It is not a redesign: no schema, Brand State, profile, capability or architecture changed, and the OBDS 1.0.0 contract surface stays byte-identical.
What changed
Section 28.1 pins how governed YAML is read. Section 28 always made JSON canonical and allowed YAML where it produces an equivalent JSON document, but never said how a YAML plain scalar becomes a JSON value. Governed YAML is now a subset of YAML 1.2 defined by that section: plain scalars resolve under the JSON number grammar, a form some YAML version reads as a value that grammar does not produce is rejected rather than guessed, explicit tags and the merge key are refused, anchors and aliases stay available under a documented expansion bound, and nesting is bounded over the data model so JSON and YAML cannot disagree about which documents are governable. The same bytes can no longer produce two governed values and two canonical hashes.
Section 26.2 conformance evidence names executed cases. The requirement list is derived from the normative text rather than maintained beside it, and the release gate resolves each requirement against the run it performs itself.
Section 14.3a is aligned with section 10.2a. A decision-relevant unresolved conflict fails the target and produces no governedResultHash; a conflict that cannot change the governed result leaves the build free to proceed, stays visible in the build evidence, and contributes no governed selection. governedResultHash identifies the governed result, not the diagnostic history that produced it.
Migration
Almost certainly nothing. OBDS-2.0.0-MIGRATION.md carries the full table and two checks: python -m obds_ref.cli validate for the rejected forms, which are loud, and a grep for exponent notation, which is the one silent change in the release. All 29 governed YAML documents shipped here read identically under 1.1.6 and 2.0.0.
Conformance
429 passed, 0 failed, 0 skipped. Release gate PASS. Public schema surface unchanged since 1.0.0 at sha256:517683bb3496867d.
OBDS 1.1.6
Hardening release. PATCH, with one normative addition.
Five blockers reported by the final outreach gate against the published 1.1.5, each reproduced on a clean checkout before any code was written.
- Section 14.3c, new. The Unicode version governing canonical NFC is pinned to 15.1.0. A governed string admits only code points assigned in that version plus the 66 permanent noncharacters, and no surrogate. Without the pin, byte-identical code on two runtimes produced different canonical bytes, and therefore different
manifestContentHash,governedResultHashandartifactHash, for the same document. Minimum CPython 3.13, Node 21. - Section 8.0a, new. Element ids and semantic subjects are compared, grouped, ordered and emitted on their NFC form. One approved
contentHashcould otherwise produce two governed results, with a broad value and its own override both surviving as governed truth. - Section 11.5.
elementValueRefresolves through the governed selection instead of the raw manifest snapshot, so an expired, out-of-scope or subject-losing value can no longer be compiled into an active blocking check. - Section 10.2a. A subject conflict is decision-relevant whenever resolving it differently would change what this target requires, blocks, prohibits or checks. Correcting this exposed that
hardBoundarieswas filtered on enforcement alone, dropping applicable prohibitions with advisory enforcement; section 14.1 requires both. - Section 10.1. The half-open
[from, to)boundary is now proved by tests that execute the implementation at the exact instants, and the release gate runs them. The previous test and gate guard compared fixture constants to each other.
Conformance rises from 199 to 279 passing tests. No schema changed, no Brand State was added, no capability was added, and the frozen OBDS 1.0.0 contract surface is byte-identical.
Full detail: OBDS-1.1.6-CHANGELOG.md and OBDS-1.1.6-MIGRATION.md.
OBDS 1.1.5
Fixes enforcement of RULE requiresDefinedRefs. An applicable RULE may now be used only when every declared required dependency resolves to one applicable defined Brand Element. Missing, unresolved, conflicting, expired, out-of-scope or non-defined dependencies fail the target build as already required by the OBDS specification.
This is a reference and conformance defect correction, not a new capability. No schema changed, no Brand State was added, and governedResultHash semantics are unchanged. Conformance moves from 184 to 199 passing tests, the added tests being regression coverage for this defect.
OBDS 1.1.4
Fixes Scope comparison so canonically equivalent Unicode values are compared after NFC normalisation as already required by the OBDS contract. The fix also rejects duplicate Scope values after normalisation and prevents Unicode representation from changing applicability, winner selection or prohibit-rule enforcement.
This is a defect correction, not a new capability. No schema changed, no Brand State was added, and governedResultHash semantics are unchanged. Conformance moves from 176 to 184 passing tests, the eight added tests being regression coverage for this defect.
OBDS 1.1.3
OBDS 1.1.3 — maintenance release. PATCH. No new capability.
Five defects found by fresh external readers against published 1.1.2. One corrects a behaviour, in one direction only; the rest are specification text, vectors and tooling. Both published example hashes are unchanged.
A hard conflict now fails a target only when the target can read it
Section 10.2 said a conflict is a conflict and stopped there. The reference therefore failed every target whenever any subject anywhere in the scope-matching set was unresolved, including subjects the target neither requires nor selects.
That is fail-arbitrary rather than fail-closed: the same manifest blocked or built depending on which unrelated subject a curator happened to leave open.
New section 10.2a states when a conflict is decision-relevant. A subject is decision-relevant to a target when one of its incomparable maximal elements would, if it won, reach that target's requirements or its compiled context:
- named in the target's
requiresDefined; - a RULES element with
enforcementblockorrequire_approval, bound for HARD_BOUNDARIES; - a
definedelement ofnature: factoutsidefamily: rules, bound for FACT_GROUNDING; - carried into STATE_MAP by the target's declared
stateMappolicy; - carried into STYLE_TEXTURE by the target's declared
styleTexturepolicy.
The first three are unconditional: a target cannot opt out of its own requirements, its hard boundaries or its fact grounding. The last two follow the policy the target declared, so a target that selects narrowly is not failed by a conflict it never reads.
An irrelevant conflict is not discarded. It stays in conflicts[] marked decisionRelevant: false, because it remains a manifest defect even when this target does not touch it. It is a manifest problem either way; it is only this target's problem when the target reads it.
The change runs one way. A build that failed solely because of a conflict the target could not observe now succeeds. No previously succeeding build fails, no previously valid artefact becomes invalid, and every one of the 165 existing conformance cases keeps its outcome. Five fixture cases pin the rule, including two the default policies make relevant without the target naming anything — the correction is narrow by construction.
Key ordering says one thing
Step 3 of section 14.3 cited "RFC 8785 / ECMAScript property sorting" as if those were one algorithm. They are not:
Object.keys({"10":1,"2":2,"b":3,"a":4}) ["2","10","b","a"] ECMAScript enumeration
code-unit sort ["10","2","a","b"] RFC 8785
The step now states lexicographic UTF-16 code-unit order, spells out the prefix rule, names ECMAScript enumeration order as explicitly not it, and gives the worked case. Nine ordering vectors were added; none existed. Both implementations already behaved correctly, so no hash moved.
selection is applicability then precedence, and nothing after it
Section 14.3a named three filters and never said that styleTexture and stateMap are not among them, so an implementer building selection from includedElementIds would resolve a different governed result.
It now says so, and says the half that is easy to get wrong in the other direction: both policies do sit inside target, which the payload carries verbatim, so changing one still moves governedResultHash. That is correct and not a contradiction — two Build Plans asking for different projections are different governed requests. What is forbidden is the projection silently changing which truth was resolved.
A four-variant fixture pins it: four targets whose artefacts render nothing in common resolve the identical selection.
The cross-language vectors are now a standalone oracle
canonical-vectors.json carried inputs only. It could prove two implementations agreed with each other and nothing more; a third party had no published expected output to check against.
Every vector now carries its canonical form as text, the lowercase hex of its canonical UTF-8 bytes, and their SHA-256. Documents that must be rejected are listed separately with the reason. canonicalHex is authoritative, because it survives transports that mangle U+2028, U+2029 and line endings.
vectors with expected output : 59
must-reject documents : 1
Python vs the published file : 0 differences
JavaScript vs the published file : 0 differences
Both implementations are now tested against the file, not against each other.
Current-release surfaces
The /authoring/ page announced OBDS 1.1.0 in its title, status badge and subtitle for the whole of 1.1.2, while its own deep links pointed at the current release. The home page said "Previous release: OBDS 1.1.0" when it was 1.1.1, and gave both 27 and 28 as the public contract count. All corrected.
The cause was scope: the version guard added in 1.1.2 read index.html alone. It now reads every HTML page in the tree — title, visible status badge and subtitle — plus llms.txt's current-release line. Each widened guard was proven by reintroducing its regression into a copy and confirming the gate fails.
Conformance
176 passed
0 failed
0 skipped
foundation 81, context-delivery 3, context-assembly 15, design-space 18, integration 15, golden 6, adversarial 38. Foundation conformance suite 15 of 15, re-executed by the gate.
An independent TypeScript implementation, written from the specification alone, still reproduces both governed result hashes with byte-identical canonical payloads: 8 of 8.
Verification
testOutputHash sha256:818a335f9fcca9a8251766a196223ce6ba5557ec9e11b4d5ed3693720953dc43
suiteHash sha256:efcb5b72af9f401563cc0a96a9b1955d0b4367f8335d2c6a954f6f80c75bbfbd
packageZipSha256 sha256:e4e1717b151ebdf7fa24928c8a6cbbb695fa6abf4a92667c5ef0ed77d0209e64
schemaSurfaceFingerprint sha256:517683bb3496867daa2346ceb2f7844e46015f926ff757a9c23da90cf1e5f469
example artifactHash sha256:193b760d887d5730615664f5ae95ccced0aa9375528ef5dcd2cdcdaea560fc3f
example governedResultHash sha256:c7594c47e076f4565ab82abd8fcf6fad51a2ad399843784283db4e7768e4ca42
The two example hashes are the values published in 1.1.0, 1.1.1 and 1.1.2, unchanged.
The 27 public OBDS 1.0.0 contracts and schemas/1.1.0/compiled-context.schema.json are byte-identical to 1.1.2. 28 public contracts served, mapped, indexed and hash-matched. Release gate PASS in both the repository and the archive layout.
Known and deliberately not fixed
- No published cross-implementation
governedResultHashresult exists, while 1.1 is described as the independent-implementability release and section 14.3a makes agreement a normative MUST. The evidence exists and has not been published. This is the single thing a sceptical evaluator asks for first. - Section 26 conformance remains unobtainable for every capability except Foundation; Compiled Runtime has no declared suite.
- Where the duplicate-key check runs is still unstated, so an implementation can pass every vector and still collapse colliding keys in its stock parser.
- Unpaired surrogates, invalid UTF-8 and an input byte-order mark are undefined.
schemaHashhas two plausible readings, raw bytes versus canonical JSON.- Unquoted YAML
asOfresolves to a date under YAML 1.1. - Section 9's closed scope vocabulary is unenforceable by the frozen 1.0.0 schema.
word_boundary_cirefers to registry fixtures not in the package.- The section 14 example's
"sha256:..."placeholders. - The cosmetic title of
schemas/1.1.0/compiled-context.schema.json, frozen because correcting it would move the bytes of a contract already published at a versioned URL.
Downloads
OBDS-1.1.3-FINAL.zip — specification, 27 frozen 1.0.0 contracts, the versioned 1.1.0 contract, reference implementation and the full conformance suite. 186 files.
Specification and documentation: CC BY 4.0. Schemas, release metadata, reference implementation, conformance suite and examples: Apache License 2.0. Commercial implementation is permitted and requires no separate permission.
OBDS 1.1.2
OBDS 1.1.2 — maintenance release. PATCH. No breaking change, no new capability.
Five defects, all found by fresh external readers against published 1.1.1. Both changes to normative text write down behaviour the shipped reference already had — measured before a word was written — so neither changes a byte any implementation produces. Both published example hashes are unchanged.
The string escape set is now stated
OBDS 1.1.1 resolved line endings in section 14.3 and still named no escape set: step 7 covered non-ASCII only. A tab could be serialised as \t or as , both valid JSON, and the two hash differently. That is the same defect class as the carriage-return divergence 1.1.1 fixed, one layer down, and it is reachable from ordinary governed text: obds:whitespace-v1 treats TAB as a separator inside governed strings.
Both shipped canonicalisers were measured first, over 19 characters in string values and in object keys:
38 cases, 0 divergences
New section 14.3b records that behaviour rather than choosing a new one. Identical for string values and object keys:
| Input | Output |
|---|---|
| quote, reverse solidus | \", \\ |
| backspace, tab, line feed, form feed, carriage return | \b, \t, \n, \f, \r |
other U+0000–U+001F |
\u00xx, lowercase hex |
| solidus | not escaped |
U+007F |
emitted directly |
non-ASCII BMP, non-BMP, U+2028, U+2029 |
emitted directly |
This is RFC 8785 section 3.2.2.2, which section 14.3 already cited for the key sort and for numbers but never for strings. It is written out in full so an implementation whose standard library differs has an unambiguous target.
Thirty-two vectors were added, every row of the table in both positions:
published cross-language vectors: 51 vectors, 0 byte differences
escape-alphabet differential fuzz: 2000 documents, 0 byte differences
The validity window has one rule
Section 14.0 said both "the interval in which the compiled selection remains valid" and "the nearest surrounding validity boundaries of all target-scope-matching elements". Those are different sets: selection happens after the asOf filter and after precedence. The two readings give different validTo values, so two conforming runtimes would accept and reject the same artefact — and no governed-result vector can catch it, because section 14.3a deliberately excludes these fields.
The shipped behaviour was measured before anything was written. Six discriminating cases at asOf = 2026-08-28T00:00:00Z:
| Scenario | validTo |
|---|---|
| nothing carries validity | null |
a scope-matching element not yet valid at asOf |
2027-01-01 |
| the selected element expires | 2026-12-01 |
| a scope-matching element that loses its subject to an override | 2026-11-01 |
| an element whose scope does not match | null |
| a scope-matching element for another subject, starting later | 2026-09-15 |
The window comes from every element whose scope matches the target scope, taken before the asOf filter and before precedence. Section 14.0 now says exactly that, and says why: a losing candidate whose validity begins tomorrow changes the selection tomorrow. Deriving the window from the surviving selection alone would leave an artefact nominally valid past the moment its own selection stops being correct, which is the failure this field exists to prevent.
Six fixture cases pin it, including the half-open boundary: an artefact is valid at 2026-11-30T23:59:59Z and invalid at 2026-12-01T00:00:00Z.
Version stamps and changelog history
The 1.1.1 specification stamped itself **Version:** 1.1.0. The public README announced 1.1.0. The website <title>, meta description and og:description said 1.1.0 while the page body said 1.1.1. All corrected.
The changelog's 1.1.0 section had been rewritten with 1.1.1's conformance numbers by a careless string replacement. It is restored to what 1.1.0 actually ran: 123 cases, foundation 43.
Four new release-gate guards
Each was proven by reintroducing its regression into a copy of the repository and confirming the gate fails:
14 spec Version line names another release CAUGHT
15 website <title> names another release CAUGHT
15 obds-version meta names another release CAUGHT
16 historical changelog section rewritten CAUGHT
17 escape vectors removed CAUGHT
17 validity rule wording retired CAUGHT
guards proven: 6 of 6
Guard 15 reads the <head>, which the 1.1.1 checks never did — the reason three version stamps shipped.
One test-harness defect fell out of the measurement: canonical_js.mjs printed canonical text with console.log, and U+2028 and U+2029 are line terminators for Python's splitlines(), so adding those vectors would have silently misaligned the batch comparison. The harness now emits one line of hex per vector.
Conformance
165 passed
0 failed
0 skipped
foundation 75, context-delivery 3, context-assembly 15, design-space 18, integration 15, golden 6, adversarial 33. Foundation conformance suite 15 of 15, profile foundation, re-executed by the gate.
An independent TypeScript implementation, written from the specification alone, still reproduces both governed result hashes with byte-identical canonical payloads: 8 of 8.
Verification
testOutputHash sha256:23bede5d1009b139013ed3be47a4b054ba3e313273d386abf6ffdef7ad03e278
suiteHash sha256:723da8ddfcf4cc4eac29bfce9a100244cffdb718672c4e1c413e62eb7489637a
packageZipSha256 sha256:cfda913485e0b908158bbfb42ef9fabdc91ffa06a876ae33bfd3e81c8aa91405
schemaSurfaceFingerprint sha256:517683bb3496867daa2346ceb2f7844e46015f926ff757a9c23da90cf1e5f469
example artifactHash sha256:193b760d887d5730615664f5ae95ccced0aa9375528ef5dcd2cdcdaea560fc3f
example governedResultHash sha256:c7594c47e076f4565ab82abd8fcf6fad51a2ad399843784283db4e7768e4ca42
The two example hashes are the values published in 1.1.0 and 1.1.1, unchanged. That is the PATCH claim as a number rather than an assertion.
The 27 public OBDS 1.0.0 contracts and schemas/1.1.0/compiled-context.schema.json are byte-identical to 1.1.1. 28 public contracts served, mapped, indexed and hash-matched. Release gate PASS in both the repository and the archive layout.
Known and deliberately not fixed
Named honestly rather than left to be found:
- Where the duplicate-key check runs is still unstated. An implementation can satisfy all nine steps of section 14.3, pass all 51 vectors, and still collapse
a\rbanda\nbin its stock JSON parser before canonicalisation begins. No vector can catch that. - Unpaired surrogates, invalid UTF-8 input and an input byte-order mark are undefined, and each produced an observed divergence between two independent implementations.
- The wide-integer MUST is conditioned on "parsers with wider integer types", so a JavaScript implementation is not literally required to reject
9007199254740993. - YAML timestamp resolution is unpinned, so an unquoted
asOfcan re-serialise differently. Both published Build Plans quote it. - Section 9's closed scope vocabulary is not enforceable by the frozen 1.0.0 schema.
- The section 14 example uses
"sha256:..."placeholders, so a literal schema run on it fails on four format errors. The gate substitutes well-formed digests; the specification does not yet say so. - The title of
schemas/1.1.0/compiled-context.schema.jsonreads "OBDS Compiled Brand Context 1.0.0 1.1.0". It stands: correcting it would move the bytes of a contract already published at a versioned URL.
Downloads
OBDS-1.1.2-FINAL.zip — specification, 27 frozen 1.0.0 contracts, the versioned 1.1.0 contract, reference implementation and the full conformance suite. 184 files.
Specification and documentation: CC BY 4.0. Schemas, release metadata, reference implementation, conformance suite and examples: Apache License 2.0. Commercial implementation is permitted and requires no separate permission.
OBDS 1.1.1
OBDS 1.1.1 — maintenance release. PATCH. No breaking change, no new capability.
Every change here fixes a defect an external reader found in 1.1.0. Nothing was added, nothing was designed, and no normative contract moved. Both published example hashes are unchanged, which is the PATCH claim stated as a number rather than an assertion.
The one that mattered: two canonicalisers disagreed
Section 14.3 step 1 said "recursively normalise every string and object key". Step 2 said "convert line endings inside strings to LF". The asymmetry was the ambiguity, and both readings were defensible — so the two canonicalisers shipped in 1.1.0 read it differently. The Python reference normalised CR inside object keys; canonical_js.mjs did not.
The consequence was the thing OBDS 1.1 exists to prevent: the same manifest and the same Build Plan producing two different governedResultHash values.
input {"a\rb": "x", "plain": "y\rz"}
1.1.0 python {"a\nb":"x","plain":"y\nz"} ad53ea9d2c27f13b
node {"a\rb":"x","plain":"y\nz"} 7c4c3e7c43855599 ← different
1.1.1 python {"a\nb":"x","plain":"y\nz"} ad53ea9d2c27f13b
node {"a\nb":"x","plain":"y\nz"} ad53ea9d2c27f13b ← identical
Step 2 now reads "convert line endings inside every string and object key to LF, CRLF first and then any remaining CR". The JavaScript canonicaliser uses a single normalisation function for keys and values, so the two cannot drift apart again. Six cross-language vectors cover CR and CRLF in values, in object keys, mixed in one document, and nested through objects and arrays: 19 vectors, 0 differences.
A key collision created by the normalisation — a\rb beside a\nb — must be rejected rather than silently collapsed. Both implementations are now tested to reject it, in both directions.
No published hash moved: no governed payload in any published example or fixture contains a carriage return.
Specification self-consistency
The section 14 artefact example carried schemaVersion: 1.0.0 and no governedResultHash, so an implementer who followed the normative example emitted an artefact the release's own contract rejected. It is now a valid 1.1 artefact, and the release gate validates it against schemas/1.1.0/compiled-context.schema.json on every run.
The context id rule. context-id.json asserted a rule and cited section 14 for it; section 14 did not contain the rule, and its example contradicted the fixture. Section 14 now states it — {manifest.id}:context:{targetId}, neither part escaped, trimmed or case-folded — and the example follows it.
The asOf representation. Section 14.3a pinned target as verbatim and said nothing about asOf beside it. It now says asOf is the timezone-aware ISO 8601 string exactly as the validated Build Plan carries it, never parsed and re-serialised. Two spellings of one instant are two documents, and reconciling them is a Build Plan authoring decision.
requiresDefined. The OBDS-BUILD-REQUIRED-NOT-DEFINED description was two-valued about an element that lost its subject to a more specific override, and the two readings disagreed about whether the build succeeds. Section 13.1 now states one: requiresDefined is an element-ID requirement, the listed element must itself be the defined winner of its subject, and an override does not satisfy a requirement naming the element it displaced. This is the behaviour the reference already had. Subject-level reusable requirements stay deferred target-governance research. Four fixture cases pin it.
Release metadata, and a gate that now catches it
1.1.0 stated three different conformance numbers across its own documents — 123, 122 and 107 — shipped a TEST-REQUIREMENTS.md that was a verbatim 1.0.4 file, and omitted its only new contract from both the schema index and the publication map. All corrected.
More usefully, the duplication that caused it is gone. TEST-RESULT.json notes and promotedFrom, and the whole publication surface — testOutputHash, packageZipSha256, websiteIndexSha256 and the counts — are now generated by the build rather than hand-copied. requirementsExercised enumerates all fourteen section 26.2 requirements rather than twelve; the two missing were "every required element present in the produced context" and governedResultHash, 1.1's own addition.
The release gate now fails on this class. Six new check groups, each one because a human reader found the defect and no mechanical check did:
- documents that disagree on the case counts
- a release document that names another release, in its text or its title
TEST-RESULT.jsoncontradicting itself, or promising a field it does not carry- a served contract missing from the index or the map, a listed contract the release does not serve, or a mapped hash that does not match the served bytes
publication-record.jsonor the website disagreeing with the built artefacts- a normative or published example that fails its own published schema
Authoring page
The /authoring/ page's only worked example failed two published schemas: sourceRefs was an array of objects against items: {type: string}, and the colour value omitted the required name. Both fixed. The gate now validates every published structured example.
Conformance
139 passed
0 failed
0 skipped
foundation 49, context-delivery 3, context-assembly 15, design-space 18, integration 15, golden 6, adversarial 33. Foundation conformance suite 15 of 15, profile foundation, re-executed by the gate.
An independent TypeScript implementation, written from the specification alone, reproduces both governed result hashes with byte-identical canonical payloads: 8 of 8, including context-id, which it failed under 1.1.0 because the rule was unstated.
Verification
testOutputHash sha256:37e81ebdccc55c887bc00581f30d67b4c60629ee61abaa71d9a6e82facf087e7
suiteHash sha256:228db72ffb20baa70d29294b47991224ecef8b0362b52acfed9b62c73c0d754c
packageZipSha256 sha256:193c1710e7dee95c4487eab90bca55b82a3a071cd6b3a2306d49ad1971ca7568
schemaSurfaceFingerprint sha256:517683bb3496867daa2346ceb2f7844e46015f926ff757a9c23da90cf1e5f469
example artifactHash sha256:193b760d887d5730615664f5ae95ccced0aa9375528ef5dcd2cdcdaea560fc3f
example governedResultHash sha256:c7594c47e076f4565ab82abd8fcf6fad51a2ad399843784283db4e7768e4ca42
The two example hashes are the ones published in 1.1.0, unchanged.
The 27 public OBDS 1.0.0 contracts are byte-identical across 1.0.0 through 1.1.1, and schemas/1.1.0/compiled-context.schema.json is byte-identical to 1.1.0. 28 public contracts served, mapped, indexed and hash-matched. Release gate PASS in both the repository and the archive layout.
Known issue, deliberately not fixed
The title of schemas/1.1.0/compiled-context.schema.json reads "OBDS Compiled Brand Context 1.0.0 1.1.0". It is a botched string edit and it should read "OBDS Compiled Brand Context 1.1.0".
It stands. Correcting it would move the bytes of a contract already published at a versioned URL, and byte-identity of published contracts is the guarantee this project makes. title is a JSON Schema annotation: no instance that validated before fails now, and no build is affected. The correction is recorded for the next contract version.
Downloads
OBDS-1.1.1-FINAL.zip — specification, 27 frozen 1.0.0 contracts, the versioned 1.1.0 contract, reference implementation and the full conformance suite. 182 files.
Specification and documentation: CC BY 4.0. Schemas, release metadata, reference implementation, conformance suite and examples: Apache License 2.0. Commercial implementation is permitted and requires no separate permission.
OBDS 1.1.0
OBDS 1.1.0 — the independent-implementability release.
What 1.1 adds
governedResultHash is a cross-implementation hash of the resolved governed result: which manifest, which target, which approved truth applied, in which knowledge states. Two implementations given the same manifest and the same Build Plan must agree on it.
They may still differ on artifactHash. That hash identifies the exact artefact — its model-facing prose, its token counts, its compiler provenance — and the specification deliberately leaves that surface undefined. Different implementations producing different artefacts while agreeing on the same governed result is the intended outcome, not a defect.
This was verified against an independent TypeScript implementation written from the specification alone, with no access to the reference Python source: 28 of 28 fixture vectors agree, zero divergences in any computed value. For the published example the two implementations produce an identical governedResultHash and different artifactHash values, differing in exactly three fields, all of them in undefined surface.
That exercise found three defects in the independent implementation and one in the reference, all fixed before this release. It is evidence of agreement between two implementations on a defined set of vectors. It is not a certification programme, and no certification is claimed.
Also defined rather than inferred in 1.1: precedence subset semantics, the nine-dimension scope vocabulary, the obds:whitespace-v1 tokenizer separator set, the validator registry, the build failure codes, the elementRecords shape, and the context id construction rule.
R-15 — the contract-identity statement, restated in full
OBDS 1.0.x remains frozen. The 27 public 1.0 contracts are byte-identical across releases 1.0.0 through 1.0.4. OBDS 1.1 introduces one new versioned Compiled Brand Context contract at schemas/1.1.0/compiled-context.schema.json, while leaving every published 1.0 contract unchanged.
This is stated here deliberately rather than left to be discovered. Earlier releases carried the byte-identical wording as a statement about the whole published schema surface; from 1.1.0 that surface contains one contract more than it did. Nothing was withdrawn, nothing was rewritten, and no 1.0 contract moved a byte — but the sentence now needs the second half to stay true, and the release gate fails if the first half ever stops being true.
Practically: manifests stay at schemaVersion 1.0.0; compiled contexts move to 1.1.0. A 1.1 implementation reads 1.0.0 manifests and produces 1.1.0 compiled contexts. A strict 1.0.0 consumer will reject a 1.1.0 compiled context — that is what the new contract version is for.
New public material
/authoring/ names the human role that approves Brand Truth, states where OBDS begins and ends, and states the two things it cannot guarantee: a curator who approves a wrong value ships it faithfully with every hash valid, and a build target that under-declares what it requires builds successfully with nothing blocking the claim.
Published English-only and marked as such. German copy is deferred, not forgotten.
Verification
full suite 123 passed / 0 failed / 0 skipped
Foundation conformance 15 passed / 0 failed, profile foundation
release gate PASS, repository layout and archive layout
docs smoke test PASS, four stages, both layouts
1.0.0 through 1.0.4 frozen and unchanged
testOutputHash sha256:5bd68cef150fc70a48fd7eb64dec183c14c456c142dd044fd9d1284c15b1bdb3
suiteHash sha256:11047c22e69d307a431dfdceddcddafedd388da40150d65f4dfbf6fc64fd9c4d
packageZipSha256 sha256:d27d509d49c0135de37d7f66ef41fae0b3e9115109b8a7503c6cec58e2ae4794
schemaSurfaceFingerprint sha256:517683bb3496867daa2346ceb2f7844e46015f926ff757a9c23da90cf1e5f469
example governedResultHash sha256:c7594c47e076f4565ab82abd8fcf6fad51a2ad399843784283db4e7768e4ca42
The conformance result applies to the reference implementation. Under section 26 this release claims exactly two profiles: OBDS Foundation (26.1) and OBDS Compiled Runtime (26.2). No profile is claimed for Context Delivery, Context Assembly, Visual Operations or Composition.
Known limitations, carried into 1.1
- A 1.1 artefact is not a valid 1.0.0 artefact. Additive for producers; a version change for strict consumers.
- The nine-dimension scope vocabulary is prose-only. A schema-only validator still accepts
localeforlocales, which then silently matches nothing. Closing it is a narrowing, so it stays deferred. build.planHashbounding and governed YAML scalar canonicalisation remain deferred as breaking.governedResultHashwas designed to depend on neither.elementRecordsis frozen and carries nosubject. Redesigning it is 2.0 work.
Downloads
OBDS-1.1.0-FINAL.zip — specification, 27 public schemas, the new 1.1.0 contract, reference implementation and the full conformance suite. 181 files.
Specification and documentation: CC BY 4.0. Schemas, release metadata, reference implementation, conformance suite and examples: Apache License 2.0. Commercial implementation is permitted and requires no separate permission.
OBDS 1.0.4
Hygiene release. No normative contract change. All 27 public contracts are byte-identical to 1.0.0, 1.0.1, 1.0.2 and 1.0.3, and schemaVersion stays 1.0.0.
The conformance result now satisfies section 26
Section 26 permits a conformance claim only when the result identifies implementation name and version, suite hash, profile and the counts, and states that no required case was skipped or changed. OBDS-1.0.3-TEST-RESULT.json published the counts and none of the rest, so the project's own release did not meet the rule it places on every other implementer.
OBDS-1.0.4-TEST-RESULT.json now carries all of them. release-schemas/release-test-result.schema.json requires them, and reference/release-gate.py verifies them, recomputes the suite hash from the suite on disk, and rejects any profile it cannot defend.
The claim is deliberately narrow. Two profiles:
- OBDS Foundation (26.1) — on
reference/foundation/conformance-suite.yaml, the only artefact in the package that names a conformance profile. 15 of 15 declared cases pass. - OBDS Compiled Runtime (26.2) — with a named executed case for every one of the twelve requirements that section lists.
No profile is claimed for Context Delivery, Context Assembly, Visual Operations or Composition. Those suites exercise modules other than the reference compiler and are reported as coverage only.
The official Foundation conformance suite was failing, and nothing ran it
One case, canonical-hashes, had been red since before 1.0.3 shipped. The same failure reproduces from the published 1.0.3 archive. run_all.py runs seven pytest directories and never invoked obds conformance, and the fixture it uses was referenced from nowhere else.
The cause was stale fixture data, not the canonicaliser: both documents in fixtures/canonical-hash-vectors.json predated the 1.0.0 contract shape. The fixture is now derived from the published examples/simple documents, and its expected manifest hash is independently pinned in two other files that the 107-case run already verifies.
The suite passes 15 of 15. The build publishes OBDS-1.0.4-FOUNDATION-CONFORMANCE.json and the release gate re-executes the suite on every run, so a release cannot omit it again.
The two results are not added together. Fourteen of the fifteen declared cases exercise the same fixtures and examples as the pytest suites, through the obds conformance harness instead of pytest, so aggregating them would double-count the same coverage.
Foundation and Compiled Runtime
The README said Foundation is the minimum and nothing beyond it is mandatory, placed Compiled Runtime in the optional tier, and then demonstrated requiresDefined, the failed target and the absent Compiled Brand Context under the heading "Foundation minimal". Every mechanism in that sequence is section 26.2.
Section 4.2 of the specification was always correct; the surrounding material was not. The README, the examples, the website, llms.txt and the release documents now state the boundary: Foundation governs Brand Truth, Compiled Runtime adds the build gate. The fail-closed guarantee is unchanged and still mechanically tested. Only its capability label was wrong.
Results
aggregate pytest 107 passed / 0 failed / 0 skipped
Foundation conformance 15 passed / 0 failed, profile foundation
zip sha256:18c4c29de21b99233597f32ef92834935f8d3da701c59d26f414695394ea4560
testOutputHash sha256:3e75be9e9127b0d728599a61c9add2a549a413cd8aec57e0c4a72c0b9fad7306
suiteHash sha256:30bb8b89676fdd4fd8d6f2899891cffa8a31b5dd8d49b99cab6d66218c4b3cc9
schema surface sha256:517683bb3496867daa2346ceb2f7844e46015f926ff757a9c23da90cf1e5f469
Migration
None. An implementation that conforms to 1.0.3 conforms to 1.0.4 with no work. See OBDS-1.0.4-MIGRATION.md.
Specification and documentation: CC BY 4.0. Schemas, release metadata, reference implementation, conformance suite and examples: Apache License 2.0.