§11 Spaces
11.1 Joint visual-text spaces
VER 1.0's kind is visual | text | fused, and 1.0 §8 requires a contextual embedding to carry “a text-space space_id”. CLIP- and SigLIP-class models — the dominant architecture for exactly this use case — are neither: one set of weights embeds images and text into one geometry, which is what makes a natural-language query comparable with a visual vector. Under 1.0 a Producer must either put text vectors in a kind: "visual" space or mint a second space_id over identical weights, and both are misdeclarations.
spaceDescriptor.kindgainsjoint_visual_text: a single space whose weights embed both images and text into one comparable geometry.
- A
canonical_visualembedding MAY be declared in ajoint_visual_textspace. 1.0 §6's requirement — “at least one embedding with `role: canonical_visualin a space ofkind: "visual"`” — is read in 1.1 as satisfied bykind ∈ {visual, joint_visual_text}.- A
contextualembedding MAY be declared in ajoint_visual_textspace. 1.0 §8's “a text-spacespace_id” is read as “a space that admits text input”, i.e.kind ∈ {text, joint_visual_text}.- A
joint_visual_textdescriptor'spreprocessingMUST state both halves: the visual members (resize, interpolation, antialias, crop, mean, std, channel order) and the text members (tokenizer id and hash, max length, truncation, casing). A joint space that states only one half is not a full descriptor (E13). Per-kind member lists are graded by the profile (VER405) rather than encoded — see §15.4.- 1.0 §8's prohibition is unchanged and is not weakened by co-location: a contextual vector MUST NOT alter, contribute to, or be fused into any
canonical_visualembedding, even when both live in the same space.
11.2 hamming, tolerance_hamming_max, and quantized spaces
dtype: "binary" is legal in VER 1.0 and unusable: the metric enum offers only cosine | dot | l2, normalization is meaningless for bit vectors, dim's unit is undefined, and the inline vector array cannot carry bits.
Everything in this section that JSON Schema can express is now expressed. An earlier revision left it all in prose to protect the superset property; the result was a specification whose central claim about binary spaces was invisible to every validator.
spaceDescriptor.metricgainshamming.- For
dtype: "binary":dimcounts bits;metricMUST behamming;normalizationMUST benone. All three directions are schema-encoded, including the converse —metric: "hamming"MUST NOT appear on a space whosedtypeis notbinary.- The payload is carried as
vector_b64orvector_refonly: **the inlinevectorarray MUST NOT be used for a binary embedding** (schema-encoded). A float array of ±1 is a different object from the packed bits the space defines, and publishing it under the space'sdimwould misstate the vector's length by a factor of eight.- Packing is 8 components per octet, most-significant-bit first within each octet, in ascending component order,
ceil(dim / 8)octets total (E24). The byte-length arithmetic relatesdim,dtypeand a payload length; JSON Schema cannot compare two members, so it is profile-enforced (VER603–VER605).- A binary space's reference claim is stated in Hamming distance.
tolerance_hamming_max— the maximum Hamming distance in bits between a published reference vector and a re-computed one — is REQUIRED wherever a binary space carries areferenceblock, andtolerance_cosine,tolerance_cosine_p5andtolerance_cosine_worstMUST NOT appear on it. Both halves are schema-encoded. The earlier ±1-expansion reading, under which a cosine floor was evaluated over the expanded bits, is withdrawn: it is monotone in Hamming distance but it is not the quantity a binary retrieval system measures, and expressing a bit-vector tolerance in a float-vector metric made binary conformance claims incomparable with the systems that consume them.tolerance_hamming_maxMUST NOT exceed the space'sdim; that bound compares two members and is profile-enforced.- For
dtype: "int8":metricSHOULD bedotorl2.cosineover int8 vectors is well-defined but is a different geometry from the fp32 space it was quantized from, and the two MUST be declared as differentspace_ids regardless. This is a SHOULD and a cross-Record MUST; neither is encodable, and neither is claimed to be.
11.3 Descriptor binding
1.0 §6.2 declares descriptors immutable once published, but they are carried inline in every Record with no binding to the published form, so two Records can present contradictory descriptors under one space_id and nothing detects it.
spaceDescriptorgains two optional members:
descriptor_uri— where the authoritative published descriptor for thisspace_idis retrievable.descriptor_sha256— SHA-256 of the RFC 8785 JCS serialization of the published descriptor with thedescriptor_sha256member removed.
descriptor_uripresent ⇒descriptor_sha256REQUIRED (schema-encoded, §15.3). A Consumer that holds two Records citing the samespace_idwith differentdescriptor_sha256values MUST treat the vectors as incomparable and SHOULD report a drift violation of 1.0 §6.2. A Consumer that fetchesdescriptor_uriMUST verify it againstdescriptor_sha256.
11.4 Duplicate space_id becomes normative
E18 established as a profile rule that space_id is unique within a Record's spaces[]. In 1.1 it is normative specification text:
space_idMUST be unique withinspaces[]. A Record carrying two entries with the samespace_id— identical or not — is non-conformant, and a Consumer MUST reject it rather than resolve the duplicate by array order.
What changes in 1.1 is the status of the rule, not who enforces it: it is now a requirement of the standard rather than of one profile. The 1.1 schema still cannot express it — JSON Schema has no key-uniqueness keyword over an array of objects, and uniqueItems compares whole items, so two entries differing in any member slip past it — so enforcement remains in the profile validator (VER401). This is a limit of the language, not a compatibility trade-off, and §15.4 records it as such.
11.5 Fused spaces: model optional, recipe in identity
VER 1.0 requires model with family, checkpoint, and weights_sha256 on every space, including a kind: "fused" space that runs no forward pass and has no weights of its own. Producers satisfy it by copying an input space's model block, which is a fabricated pin.
spaceDescriptor.modelis REQUIRED for `kind ∈ {visual, text, joint_visual_text}and OPTIONAL forkind: "fused"` (schema-encoded).- A
fusedspace SHOULD instead declarederived_from: the two or morespace_idvalues it is derived from.- The fusion recipe is part of the fused space's identity. 1.0 §6.2's rule reads, in 1.1: new weights, preprocessing, dtype, metric, **or fusion recipe** ⇒ new
space_id. Changingmethodorweightswhile keeping thespace_idis non-conformant (E20).embeddings[].recipe.inputsarespace_idvalues declared in the same Record (E20), andweights, when present, aligns 1:1 withinputs.
The model relaxation is a widening. The identity rule is prose that no schema can check: whether two descriptors with one space_id differ is a cross-Record question.
11.6 space_id syntax
The 1.0 pattern contradicts the prose it implements: it rejects a reverse-DNS authority whose first label contains a hyphen (which excludes every punycode/IDN domain and any organisation with a hyphenated name), and it rejects semver prerelease and build metadata.
The
space_idpattern is widened so that:
- the first authority label may contain hyphens —
[a-z0-9][a-z0-9-]*, where 1.0.1 allowed[a-z0-9]+;- later labels keep the 1.0.1 character class exactly (
[a-z0-9-]+);- the version part accepts optional lowercase prerelease and build metadata (
1.0.0-rc.1,2.1.0+build.7,2.1.0-rc.1+build.7).This is a pure widening: every
space_idthe 1.0.1 pattern accepts, this pattern accepts. That includes identifiers the 1.0.1 pattern admits by accident —org.-example/1.0,org.example-/1.0,acme.my-org.space-/2.1— whose later labels begin or end with a hyphen. Tidying those edges would be a narrowing of a published pattern, and this is the one place in the draft where a narrowing would buy nothing: nospace_idin circulation is made safer by rejecting an edge hyphen. New identifiers SHOULD NOT use a hyphen at the start or end of any label; a future major release may withdraw them.Numeric version components SHOULD follow semver's no-leading-zeros rule; the pattern remains permissive on that point for the same reason.
Two constraints the syntax cannot carry, stated normatively: the authority label sequence MUST be a domain the descriptor's publisher controls, and a Producer MUST NOT mint identifiers under an authority it does not control. Registry-backed resolvability of
space_idis deferred past 1.1.
The widening is verified over the grammar of the 1.0.1 pattern, not over a sample identifier: RELEASE.md § "Verification" carries a generator that emits identifiers from the 1.0.1 grammar — an exhaustive sweep of every one- and two-character label, which covers every hyphen position in them, plus a randomized sweep over longer labels, label counts and both version shapes — and checks each against the 1.1 pattern. A single-example regression test cannot establish a subset relation between two regular languages, and the earlier draft's did not: it missed a silent narrowing of exactly these edge forms.
