Skip to content

Releases: openbranddefinition/obds

OBDS 4.1.3

Choose a tag to compare

@ktdmax ktdmax released this 12 Sep 10:50

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 linked OBDS-4.1.0.md, OBDS-4.1.0-IMPLEMENTER-QUICKSTART.md,
    OBDS-4.1.0-TEST-RESULT.json, OBDS-4.1.0-CHANGELOG.md and
    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.md credits them to
    4.0.0, says what 4.1.0 added and what 4.1.3 is.

  • Task Facts status. The suite README.md introduced 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.md is 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.md is 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.py step 15 has said since 1.1.3 that it checks the
    README and never checked its current release. The new step 15a does: README.md must 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 into schemas/ and value-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: false limitation, and ADOPTION.md must 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 repository publication-record.json must 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:alt named the current release. A
    re-render for 4.1.2 was prepared but never published. tools/build-og-images.py now stamps
    each card with the release it was rendered for, in a PNG tEXt chunk named
    OBDS-Release, and its --check reads the stamps back. The gate refuses a
    missing, unreadable, unstamped or stale card in the repository,
    tools/build-release.py refuses to build while one exists, and
    tools/deploy-smoke-test.py reads the stamps of the cards the site serves. The
    cards are re-rendered for 4.1.3.

  • tools/test-final-closure.py gains 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

Choose a tag to compare

@ktdmax ktdmax released this 01 Sep 18:19

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

Choose a tag to compare

@ktdmax ktdmax released this 01 Sep 11:15

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, governedResultHash and artifactHash, 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 contentHash could otherwise produce two governed results, with a broad value and its own override both surviving as governed truth.
  • Section 11.5. elementValueRef resolves 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 hardBoundaries was 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

Choose a tag to compare

@ktdmax ktdmax released this 31 Aug 10:54

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

Choose a tag to compare

@ktdmax ktdmax released this 31 Aug 07:25

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

Choose a tag to compare

@ktdmax ktdmax released this 30 Aug 19:18

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:

  1. named in the target's requiresDefined;
  2. a RULES element with enforcement block or require_approval, bound for HARD_BOUNDARIES;
  3. a defined element of nature: fact outside family: rules, bound for FACT_GROUNDING;
  4. carried into STATE_MAP by the target's declared stateMap policy;
  5. carried into STYLE_TEXTURE by the target's declared styleTexture policy.

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 governedResultHash result 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.
  • schemaHash has two plausible readings, raw bytes versus canonical JSON.
  • Unquoted YAML asOf resolves to a date under YAML 1.1.
  • Section 9's closed scope vocabulary is unenforceable by the frozen 1.0.0 schema.
  • word_boundary_ci refers 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

Choose a tag to compare

@ktdmax ktdmax released this 30 Aug 17:39

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+0000U+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\rb and a\nb in 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 asOf can 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.json reads "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

Choose a tag to compare

@ktdmax ktdmax released this 30 Aug 14:16

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.json contradicting 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.json or 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

Choose a tag to compare

@ktdmax ktdmax released this 30 Aug 12:42

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 locale for locales, which then silently matches nothing. Closing it is a narrowing, so it stays deferred.
  • build.planHash bounding and governed YAML scalar canonicalisation remain deferred as breaking. governedResultHash was designed to depend on neither.
  • elementRecords is frozen and carries no subject. 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

Choose a tag to compare

@ktdmax ktdmax released this 29 Aug 18:50

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.