diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index e77eeaf..5f1313a 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -13,6 +13,13 @@ https://semver.org/spec/v2.0.0.html[Semantic Versioning]. ==== Changed +* *Modality profiles distinguished from the fixed Octad schema* (vcl-ut#118): + adopted `modality profile` for versioned, implementation-specific modality + selections and `modality set` for membership alone. Clarified that VCL-UT's + `OctadSchema` and `VCLS` v1 remain fixed at eight modality slots; empty or + omitted schema fields do not signal profile membership or witness presence. + No type, JSON contract, or wire format changed. See + `docs/standards/MODALITY-PROFILES.adoc` and ADR-0007. * *Licensing and REUSE policy normalized*: software and package metadata use MPL-2.0; human-readable documentation uses CC-BY-SA-4.0. Removed the unused AGPL license text, corrected invalid PMPL SPDX declarations, and clarified diff --git a/README.adoc b/README.adoc index c172f5c..36a8f7e 100644 --- a/README.adoc +++ b/README.adoc @@ -132,6 +132,18 @@ it. Simple statements short-circuit at the early safety levels; proof-bearing statements and high-risk lifecycle transitions go through the deeper proof, effect, resource, and cross-cutting checks (L9-L10). +[NOTE] +==== +Keep a deployment's **modality profile** (which modalities it supports or +enables) separate from the **Octad** and VCL-UT's `OctadSchema`. The Octad is +the fixed eight-modality model; a subject may have data in only some of its +slots. `OctadSchema` still has all eight schema slots, even when a slot has no +field definitions. The current `VCLS` v1 wire format is fixed-arity and does +not carry a modality profile. See +link:docs/standards/MODALITY-PROFILES.adoc[the terminology and compatibility +contract]. +==== + [source] ---- User / system writes VCL @@ -170,6 +182,8 @@ routine VCL safe. Prefer: consonance language, statement, transition, identity claim, consonance subject, modal witness, proof-bearing statement, verified transition, octad. +When discussing implementation/deployment modality support, use *modality +profile*; reserve `OctadSchema` for the fixed eight-slot schema. Avoid or qualify: query language, query, record, CRUD, delete, proof-carrying query, 6-modal engine, passive store. Use "query" only for a read-only syntactic diff --git a/ROADMAP.adoc b/ROADMAP.adoc index ae67c9d..6326dbd 100644 --- a/ROADMAP.adoc +++ b/ROADMAP.adoc @@ -74,9 +74,12 @@ These are ordered by value, not by version number. . *Discharge the two disclosed L10 residuals.* Transitive `ENTAILS`-cycle detection and proposition well-typedness, both recorded as owed in `verification/proofs/VERIFICATION-STANCE.adoc`. -. *Retire the `HEXAD` keyword* once VeriSimDB's default modality context - carries all eight witnesses. The parser accepts both `OCTAD` and `HEXAD` - today for compatibility. +. *Optional syntax cleanup: retire the legacy `HEXAD` spelling* when all + supported frontends can do so compatibly. The current Rust parser accepts + both `OCTAD` and `HEXAD` as the same `Source::Octad`; this is a source-name + alias, not a six-modality profile. Its deprecation is independent of which + modalities a deployment enables or which witnesses a subject populates. + See link:docs/standards/MODALITY-PROFILES.adoc[the profile/Octad contract]. == Milestones diff --git a/container/README.adoc b/container/README.adoc index 5313b85..0f941fe 100644 --- a/container/README.adoc +++ b/container/README.adoc @@ -155,7 +155,7 @@ For k9-svc managed deployments: [source,bash] ---- # Validate the deployment component -nickel typecheck container/deploy.k9.ncl +k9-svc validate container/deploy.k9.ncl # Deploy (requires Hunt-level authorisation) k9-svc deploy container/deploy.k9.ncl --env production diff --git a/container/deploy.k9.ncl b/container/deploy.k9.ncl index 06be343..382be69 100644 --- a/container/deploy.k9.ncl +++ b/container/deploy.k9.ncl @@ -1,3 +1,4 @@ +K9! # SPDX-License-Identifier: MPL-2.0 # deploy.k9.ncl — VCL-total deployment component (Hunt level) # @@ -8,65 +9,9 @@ # It requires explicit authorisation via the Leash system. # # Usage: -# nickel typecheck container/deploy.k9.ncl # k9-svc validate container/deploy.k9.ncl # k9-svc deploy container/deploy.k9.ncl --env production -# The component's pedigree (self-description across five layers) -let component_pedigree = { - # ───────────────────────────────────────────────────────────── - # L1: The Snout — Identity - # ───────────────────────────────────────────────────────────── - metadata = { - name = "vcl-total-deploy", - version = "0.1.0", - breed = "application/vnd.k9+nickel", - magic_number = "K9!", - description = "VCL-total deployment component (Hunt level)", - }, - - # ───────────────────────────────────────────────────────────── - # L2: The Scent — Target Environment - # ───────────────────────────────────────────────────────────── - target = { - os = 'Linux, - is_edge = false, - requires_podman = true, - min_memory_mb = 256, - }, - - # ───────────────────────────────────────────────────────────── - # L3: The Leash — Security - # ───────────────────────────────────────────────────────────── - security = { - trust_level = 'Hunt, - allow_network = true, - allow_filesystem_write = true, - allow_subprocess = true, - # In production, replace with a real Ed25519 signature. - signature = "PLACEHOLDER-SIGNATURE-REQUIRED-FOR-HUNT", - }, - - # ───────────────────────────────────────────────────────────── - # L4: The Gut — Self-Validation - # ───────────────────────────────────────────────────────────── - validation = { - checksum = "sha256:placeholder", - pedigree_version = "1.0.0", - hunt_authorized = false, # Must be set true after handshake - }, - - # ───────────────────────────────────────────────────────────── - # L5: The Muscle — Deployment Recipes - # ───────────────────────────────────────────────────────────── - recipes = { - install = "just container-build", - validate = "just container-verify", - deploy = "just container-up", - migrate = "just container-build && just container-up", - }, -} in - # Deployment configuration let deployment = { # Target environments (dev / staging / production) @@ -143,7 +88,61 @@ echo "K9: Rollback complete." # Export the component { - pedigree = component_pedigree, + # The component's pedigree (self-description across five layers) + pedigree = { + # ───────────────────────────────────────────────────────────── + # L1: The Snout — Identity + # ───────────────────────────────────────────────────────────── + metadata = { + name = "vcl-total-deploy", + version = "0.1.0", + breed = "application/vnd.k9+nickel", + magic_number = "K9!", + description = "VCL-total deployment component (Hunt level)", + }, + + # ───────────────────────────────────────────────────────────── + # L2: The Scent — Target Environment + # ───────────────────────────────────────────────────────────── + target = { + os = 'Linux, + is_edge = false, + requires_podman = true, + min_memory_mb = 256, + }, + + # ───────────────────────────────────────────────────────────── + # L3: The Leash — Security + # ───────────────────────────────────────────────────────────── + security = { + leash = 'Hunt, + trust_level = 'Hunt, + allow_network = true, + allow_filesystem_write = true, + allow_subprocess = true, + # In production, replace with a real Ed25519 signature. + signature = "PLACEHOLDER-SIGNATURE-REQUIRED-FOR-HUNT", + }, + + # ───────────────────────────────────────────────────────────── + # L4: The Gut — Self-Validation + # ───────────────────────────────────────────────────────────── + validation = { + checksum = "sha256:placeholder", + pedigree_version = "1.0.0", + hunt_authorized = false, # Must be set true after handshake + }, + + # ───────────────────────────────────────────────────────────── + # L5: The Muscle — Deployment Recipes + # ───────────────────────────────────────────────────────────── + recipes = { + install = "just container-build", + validate = "just container-verify", + deploy = "just container-up", + migrate = "just container-build && just container-up", + }, + }, deployment = deployment, scripts = scripts, diff --git a/docs/2026-07-21-workup-consonance-and-verisim.adoc b/docs/2026-07-21-workup-consonance-and-verisim.adoc index db6abcf..bde657b 100644 --- a/docs/2026-07-21-workup-consonance-and-verisim.adoc +++ b/docs/2026-07-21-workup-consonance-and-verisim.adoc @@ -435,9 +435,15 @@ named `HexadType` throughout (`VCLTypes.res:50`, `:206`, `:270`, `VCLSubtyping.res:101`). The hexad-to-octad migration reached the variants and stopped before the defaults and the names. -Note the same legacy is visible here: the parser still accepts `HEXAD` -alongside `OCTAD`. That is deliberate compatibility, and it should be retired -once VeriSimDB's default context carries all eight — not before. +Terminology correction (2026-10-05): the six-entry `availableModalities` +value is an implementation-specific modality set; if a versioned profile is +introduced, it can describe that selection. It does not change the fixed +eight-slot Octad model or VCL-UT's `OctadSchema`. In this repository's current +Rust parser, `OCTAD` and `HEXAD` both map to the same `Source::Octad`, with +`HEXAD` retained as a legacy source spelling. Alias removal is a separate +cross-frontend compatibility decision; it is not gated on the default context +listing all eight modalities. Other frontends must be checked independently. +See link:standards/MODALITY-PROFILES.adoc[the profile/Octad contract]. === The seam is unwired @@ -480,8 +486,9 @@ Ordered by value delivered per unit of risk. Items 1-2 are in this repository; | 5 | *Converge the checkers.* Once (4) is live, retire the ReScript checker's independent verdict in favour of the gate's, keeping the ReScript surface - parser and diagnostics. Then rename `HexadType` and retire the `HEXAD` - keyword together. + parser and diagnostics. Treat `HexadType` renaming and `HEXAD` alias removal + as separate compatibility cleanups; neither is implied by changing the + default modality set. | both | 6 diff --git a/docs/QUICKSTART.adoc b/docs/QUICKSTART.adoc index 1d93e1f..4ec3131 100644 --- a/docs/QUICKSTART.adoc +++ b/docs/QUICKSTART.adoc @@ -120,7 +120,7 @@ Create a file called `my-query.vcltotal`: ---- -- A query that exercises 6 of the 10 safety levels SELECT GRAPH, DOCUMENT -FROM HEXAD 550e8400-e29b-41d4-a716-446655440000 +FROM OCTAD 550e8400-e29b-41d4-a716-446655440000 WHERE FULLTEXT CONTAINS $searchTerm CONSUME AFTER 1 USE WITH SESSION ReadOnlyProtocol @@ -260,7 +260,7 @@ Every function is total (`%default total`), every proof is real (zero Start with: -- `Core.idr` — Foundation types (modalities, hexad references) +- `Core.idr` — Foundation types (modalities, Octad source references) - `Linear.idr` — Simplest safety level (QTT linearity) - `Proofs.idr` — Cross-cutting invariants (see how levels compose) diff --git a/docs/WHAT-IS-VERISIMDB.adoc b/docs/WHAT-IS-VERISIMDB.adoc index 0c5d840..4d6b718 100644 --- a/docs/WHAT-IS-VERISIMDB.adoc +++ b/docs/WHAT-IS-VERISIMDB.adoc @@ -68,8 +68,12 @@ them in one system, with _automatic consistency guarantees_. === The Octad: One Entity, Eight Views -Every piece of data in VeriSimDB is stored as an **octad** -- a single entity -with up to eight simultaneous representations: +VeriSimDB's **Octad** is a single-entity model with exactly eight named +modality slots. A particular subject may have actual witness data in only a +subset of those slots; “up to eight populated representations” describes +runtime population, not a variable-length Octad schema. A deployment's +modality profile, when defined by that implementation, is a separate statement +about supported or enabled modalities: ---- ┌─────────────────────────────────────────────────────────────┐ @@ -114,6 +118,15 @@ with up to eight simultaneous representations: | Geospatial coordinates and geometries -- where this entity is in the world |=== +These are the eight named Octad slots, not a promise that every subject has +data in all eight. Keep four questions distinct: which modalities the model +names, which a deployment supports (its *modality profile*), which fields the +safety schema declares, and which witnesses are populated for a particular +subject. VCL-UT's `OctadSchema` has a fixed slot for every modality; an empty +slot in the schema input does not encode a deployment profile or runtime +absence. See +link:standards/MODALITY-PROFILES.adoc[the VCL-UT profile/Octad contract]. + === Why This Matters Suppose you have a customer record. In a traditional setup: @@ -129,13 +142,15 @@ That is six copies of the same customer, in six different systems, with six different update mechanisms. When the customer changes their address, you have to update _all six_ -- and if any update fails or is delayed, your data drifts. -In VeriSimDB, there is one octad for that customer. All eight views are -maintained automatically. When the document modality updates, VeriSimDB detects -that the vector embedding, graph relationships, and search index may have -drifted, and triggers automatic re-normalisation. +In VeriSimDB, that customer is modeled by one Octad with eight named slots. +Which witnesses are supported by a deployment and which are populated for +that subject are implementation/runtime matters; the fixed eight-slot model +is independent of those choices. When document and vector witnesses are both +present, for example, the engine can detect that the vector embedding may have +drifted from the document and trigger re-normalisation. -**You do not have to choose between MongoDB and Neo4j and Redis. You get all -of them, and they stay in sync.** +**The Octad supplies one identity model across modalities; it is not a promise +that every deployment or subject has every witness populated.** === Drift Detection @@ -150,7 +165,7 @@ When drift exceeds a configurable threshold, VeriSimDB: 1. Identifies the most authoritative modality 2. Regenerates the drifted modalities from it -3. Validates consistency across all eight views +3. Validates consistency across the applicable, populated witnesses (within the fixed Octad model) 4. Updates everything atomically (all at once, or not at all) == The Three Query Paths @@ -313,12 +328,13 @@ A proof technique discovered for VCL-total can be applied to PanLL, and vice ver | Concept | One-Sentence Summary | **VeriSimDB** -| A database where every entity exists in 8 views simultaneously, with automatic - drift detection and repair. +| A multi-modal engine whose Octad model has eight fixed modality slots; which + witnesses are supported or populated can vary by implementation and subject. | **Octad** -| The 8 simultaneous representations of a single entity (graph, vector, tensor, - semantic, document, temporal, provenance, spatial). +| The fixed eight-slot model for graph, vector, tensor, semantic, document, + temporal, provenance, and spatial witnesses; a subject need not populate all + eight slots. | **VCL** | The fast, unverified query language for VeriSimDB. diff --git a/docs/WHY-TYPE-SAFETY-MATTERS.adoc b/docs/WHY-TYPE-SAFETY-MATTERS.adoc index 5d342f0..019063d 100644 --- a/docs/WHY-TYPE-SAFETY-MATTERS.adoc +++ b/docs/WHY-TYPE-SAFETY-MATTERS.adoc @@ -168,10 +168,13 @@ FETCH orders.order_total WHERE orders.status = "completed" ==== Why It Matters for Databases -In VeriSimDB, data exists across 8 modalities simultaneously (the octad). A -typo in a modality reference could silently query the wrong view of your data. -Schema binding ensures that every reference is checked against the live schema -before the query runs. +VeriSimDB's Octad names eight fixed modality slots, although a subject may +have witness data in only a subset. A deployment's modality profile (which +modalities it supports or enables) is a separate concept from both that fixed +Octad and VCL-UT's `OctadSchema`. A typo in a modality reference could silently +query the wrong view of your data; schema binding checks field references +against the supplied schema. See +link:standards/MODALITY-PROFILES.adoc[the profile/Octad contract]. --- @@ -436,10 +439,12 @@ FETCH OPTIONAL users WHERE users.email = ?email ==== Why It Matters for Databases -In VeriSimDB, an entity's octad has exactly 8 modality slots but any subset -might be populated. Cardinality safety ensures you know at compile time whether -a modality query will return data or might be empty, eliminating an entire -class of "expected data that was not there" bugs. +In VeriSimDB, the Octad has exactly eight named modality slots, but any subset +may have witness data for a particular entity. A modality profile can describe +what an implementation supports; it does not prove that a subject has data in +a supported modality. Cardinality safety concerns the possible result count, +not the profile's modality count, and helps catch assumptions that a modality +will necessarily return data when it might be empty. --- diff --git a/docs/architecture/DECISIONS.adoc b/docs/architecture/DECISIONS.adoc index b753f02..f0d3253 100644 --- a/docs/architecture/DECISIONS.adoc +++ b/docs/architecture/DECISIONS.adoc @@ -45,6 +45,11 @@ toc::[] |Epistemic types via S5 modal logic |Accepted |2026-04-10 + +|ADR-0007 +|Separate modality profiles from the fixed Octad schema (see link:../decisions/0007-modality-profiles-vs-octad-schema.adoc[record]) +|Accepted +|2026-10-05 |=== --- diff --git a/docs/architecture/TOPOLOGY.adoc b/docs/architecture/TOPOLOGY.adoc index 883ac56..a998d13 100644 --- a/docs/architecture/TOPOLOGY.adoc +++ b/docs/architecture/TOPOLOGY.adoc @@ -64,7 +64,7 @@ query language. │ │ Tensor, Semantic, Document, │ │ │ │ Temporal, Provenance, Spatial) │ │ │ │ │ │ - │ │ HEXAD addressing │ │ + │ │ OCTAD source (HEXAD alias) │ │ │ └──────────────────────────────────┘ │ └─────────────────────────────────────────┘ ---- @@ -147,7 +147,7 @@ The dependency chain from theory to execution: ┌──────────────────────────────────────────────────────────────┐ │ VeriSimDB │ │ │ - │ The database engine. 8 modalities, HEXAD addressing, │ + │ Fixed eight-slot Octad; OCTAD source, HEXAD legacy alias. │ │ Rust core, Elixir orchestration. │ │ │ │ Receives: compiled query plans with proof certificates. │ @@ -314,7 +314,7 @@ performance-critical type checking in the hot path. │ ┌──────────────────────────────────────────────────┐ │ │ │ VeriSimDB Cluster │ │ │ │ ↳ Rust core engine │ │ - │ │ ↳ 8-modality HEXAD storage │ │ + │ │ ↳ Fixed Octad slots; HEXAD is a source alias │ │ │ │ ↳ Receives compiled query plans + certificates │ │ │ └──────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘ diff --git a/docs/decisions/0.2-AI-MANIFEST.a2ml b/docs/decisions/0.2-AI-MANIFEST.a2ml index ac26298..25aeb80 100644 --- a/docs/decisions/0.2-AI-MANIFEST.a2ml +++ b/docs/decisions/0.2-AI-MANIFEST.a2ml @@ -9,3 +9,7 @@ parent: "../0.1-AI-MANIFEST.a2ml" ### [AI_MANIFEST] description: | Sub-unit of the docs pillar focusing on decisions. + +canonical_locations: + index: "README.adoc" + modality_profiles_octad: "0007-modality-profiles-vs-octad-schema.adoc" diff --git a/docs/decisions/0007-modality-profiles-vs-octad-schema.adoc b/docs/decisions/0007-modality-profiles-vs-octad-schema.adoc new file mode 100644 index 0000000..ef38b4f --- /dev/null +++ b/docs/decisions/0007-modality-profiles-vs-octad-schema.adoc @@ -0,0 +1,64 @@ += Architecture Decision Record: 0007 — Modality Profiles vs the Fixed Octad Schema +// SPDX-License-Identifier: CC-BY-SA-4.0 +// Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) + +Date: 2026-10-05 + +## Status + +Accepted. Normative terminology and compatibility detail: +[`docs/standards/MODALITY-PROFILES.adoc`](../standards/MODALITY-PROFILES.adoc). +Tracked by hyperpolymath/vcl-ut#118, aligned with +hyperpolymath/verisimdb#299. + +## Context + +“Octad” names VeriSimDB's fixed eight-modality model and `OctadSchema` is a +concrete eight-slot schema in the VCL-UT type checker and `VCLS` v1 wire +codec. At the same time, implementations and deployments can support or enable +different modality subsets. Calling both concepts “the schema” makes a +capability/configuration choice look like a change to the fixed Octad record +and risks implying that current VCL-UT transport accepts variable arity. + +Actual per-subject witness population is a third concern: an entity may have +data in only some modalities even though the static schema has a slot for +each. Empty schema fields do not encode whether a modality is supported or +populated. + +## Decision + +- Use **modality profile** for a versioned, implementation-specific selection + of modalities supported or enabled at a declared scope. +- Use **modality set** for membership alone, without implied policy or version. +- Reserve **Octad** / **`OctadSchema`** for the current fixed eight-modality + model and its concrete eight-slot schema. +- Treat profile membership, field declarations, and per-subject witness + population as separate facts. +- Keep `OctadSchema`, the gate contract, and `VCLS` v1 unchanged. This decision + adds no profile type, negotiation, serialization, or variable-arity support. +- Treat `HEXAD` as a legacy spelling of the Octad source in the current Rust + parser, not as a six-modality profile. Retiring that spelling is an + independent compatibility decision. + +## Consequences + +### Positive + +- Downstream discussions can describe non-Octad or implementation-specific + modality selections without renaming or weakening VCL-UT's fixed schema. +- Schema, capability, and runtime-presence claims become auditable as separate + contracts. +- Existing `OctadSchema` and `VCLS` v1 consumers retain their exact contract. + +### Negative + +- A profile cannot yet be passed to or validated by VCL-UT; integrations must + not mistake this vocabulary decision for implemented profile support. + +### Future work boundary + +If profile exchange becomes necessary, define a separate versioned type and +transport that states scope, catalog, membership/cardinality, omission +semantics, and the distinction between supported, enabled, and populated +modalities. Do not encode a profile by omitting slots from `OctadSchema` or by +reinterpreting the existing schema-version fields. diff --git a/docs/decisions/README.adoc b/docs/decisions/README.adoc index a70e749..c205d77 100644 --- a/docs/decisions/README.adoc +++ b/docs/decisions/README.adoc @@ -1,4 +1,27 @@ -// SPDX-FileCopyrightText: Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) // SPDX-License-Identifier: CC-BY-SA-4.0 -= decisions Unit += Architecture Decisions +:toc: preamble + +Accepted and superseded architecture decisions for VCL-UT. The historical +architecture ADR index is at +link:../architecture/DECISIONS.adoc[docs/architecture/DECISIONS.adoc]; ADR-0007 +is cross-indexed there and its full record is stored here. + +[cols="1,3,1"] +|=== +|ADR |Decision |Status + +|link:0001-adopt-rsr-standard.adoc[0001] +|Adopt the Rhodium Standard Repository template +|Accepted + +|link:0002-ffi-attestation-trust-boundary.adoc[0002] +|Use recomputation-PCC over wasm32 with C-ABI attestation as fallback +|Accepted + +|link:0007-modality-profiles-vs-octad-schema.adoc[0007] +|Distinguish implementation-specific modality profiles from the fixed Octad schema +|Accepted +|=== diff --git a/docs/standards/0.2-AI-MANIFEST.a2ml b/docs/standards/0.2-AI-MANIFEST.a2ml index c147c6f..d96db7e 100644 --- a/docs/standards/0.2-AI-MANIFEST.a2ml +++ b/docs/standards/0.2-AI-MANIFEST.a2ml @@ -8,4 +8,7 @@ parent: "../0.1-AI-MANIFEST.a2ml" --- ### [AI_MANIFEST] description: | - Standards unit for high-rigor verification. + Standards unit for high-rigor verification and cross-layer contracts. + +canonical_locations: + modality_profiles: "MODALITY-PROFILES.adoc" diff --git a/docs/standards/MODALITY-PROFILES.adoc b/docs/standards/MODALITY-PROFILES.adoc new file mode 100644 index 0000000..0a8d424 --- /dev/null +++ b/docs/standards/MODALITY-PROFILES.adoc @@ -0,0 +1,190 @@ +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) +// SPDX-License-Identifier: CC-BY-SA-4.0 + += Modality Profiles and the Fixed Octad Contract +Jonathan D.A. Jewell +:revdate: 2026-10-05 +:toc: preamble +:icons: font + +[.lead] +This specification separates implementation-specific *modality profiles* from +VCL-UT's fixed, eight-slot `OctadSchema`. It defines vocabulary and records the +current contract; it does not add a profile API or change any wire format. + +== Status and Scope + +This is the accepted terminology clarification for +https://github.com/hyperpolymath/vcl-ut/issues/118[vcl-ut#118], aligned with +the related https://github.com/hyperpolymath/verisimdb/issues/299[VeriSimDB +proposal]. It describes the VCL-UT contract present on 2026-10-05. The +`OctadSchema` type, gate JSON contract, `VCLS` v1 codec, and accepted statement +syntax are unchanged. + +This document does *not* claim that VCL-UT or VeriSimDB currently negotiates, +serializes, or validates a modality profile. The profile terms below are +available for architecture and documentation; a runtime profile contract +would need its own implementation and versioned interface. + +== Terms + +Modality:: +A named kind of modal witness. VCL-UT's current Octad catalog is exactly +Graph, Vector, Tensor, Semantic, Document, Temporal, Provenance, and Spatial. + +Modality set:: +A collection whose meaning is only membership: which modality names are in +that set. The generic term does not impose a fixed cardinality, version, or +policy. A modality set is not, by itself, a schema or a capability contract. + +Modality profile:: +A versioned, implementation-specific selection of modalities that are +supported or enabled at an explicitly stated scope (for example, an +implementation, deployment, tenant, or subject). The profile's own contract +must define its scope, versioning, cardinality/membership representation, and +the meaning of omitted members (including any required/optional/unsupported +semantics). The word *profile* alone defines none of those wire-level details. + +Octad:: +VCL-UT's specific fixed model with eight named modality slots. An individual +subject may have witness data in only some of those slots; sparse runtime +population does not make the Octad structure variable-arity. + +`OctadSchema`:: +VCL-UT's static schema value: eight named slot members (graph, vector, +tensor, semantic, document, temporal, provenance, and spatial), each carrying +a `ModalitySchema`. It describes declared fields and their types/nullability; +it is not a modality profile, a per-subject population bitmap, or a record of +which modalities a deployment supports. + +Populated/present modality:: +A statement about whether a subject has actual witness data in a modality at a +particular point in time. This runtime fact is distinct from profile support, +from a schema's field declarations, and from the fixed arity of `OctadSchema`. + +== Keep Four Questions Separate + +[cols="1,2,3"] +|=== +|Question |Term |What it says + +|Which modality names exist in this language's model? +|Modality catalog +|VCL-UT's current catalog contains the eight named Octad modalities. + +|Which modalities can or will an implementation use? +|Modality profile / modality set +|An implementation-specific capability or configuration choice. VCL-UT has + no profile object or profile transport today. + +|Which fields and field types can the checker resolve? +|`OctadSchema` +|The static schema passed to the checker, with a fixed slot for each Octad + modality. An empty field list declares no fields for that slot; it does not + declare the modality unsupported or physically absent. + +|Which witnesses have data for this subject now? +|Population / presence +|Runtime state. It is not represented by `OctadSchema` or inferred from an + empty field list. +|=== + +In particular, *supported*, *enabled*, *schema-described*, and *populated* are +not synonyms. If an implementation wants to make those states interchangeable, +its own profile/runtime contract must state and validate that rule. + +== VCL-UT Contract Today + +=== The schema is exactly eight slots + +`src/core/Schema.idr` defines `OctadSchema` as eight named fields, in this +order: Graph, Vector, Tensor, Semantic, Document, Temporal, Provenance, and +Spatial. The Rust mirror is `src/interface/parse/src/schema.rs`. There is no +variable-length modality collection and no profile field in either type. + +The binary `VCLS` v1 schema stream carries exactly eight `ModalitySchema` +payloads in canonical record order, with no modality-count prefix. Its v1 +codec version is not a modality-profile version; it is not a variable-arity +profile transport. The decoder reads those eight payloads and rejects trailing +bytes. See +link:../../src/interface/parse/WIRE-FORMAT.adoc[the wire-format contract]. + +=== JSON omission does not change the arity + +The `vclt-gate` request may omit the top-level `schema`; that path constructs +an empty `OctadSchema` containing all eight slots. In the JSON `schema` object, +a modality key may also be omitted; the current parser fills that fixed slot +with an empty field list. The resulting value is still an eight-slot +`OctadSchema`. + +An omitted key or an empty `fields` array therefore means only that no field +definitions were supplied for that slot to this checker input. It does *not* +mean “this deployment does not support the modality,” “this subject has no +witness here,” or “the profile has fewer modalities.” The gate request's +`schema_version: 1` versions the gate request contract; it does not identify a +modality profile. See +link:../vclt-gate-contract.adoc[the gate contract]. + +=== `OCTAD` and `HEXAD` are source spellings, not profiles + +The current Rust parser accepts `OCTAD` and `HEXAD` in a direct `FROM` source +and maps both to the same `Source::Octad` value. `HEXAD` is the legacy spelling +in that parser; it does not mean “select six modalities.” This terminology +decision does not remove either spelling or define alias support in other +frontends. Any eventual syntax cleanup is independent of a deployment's +modality profile and requires its own compatibility decision. + +=== Wildcard projection is not a profile + +The EBNF describes `SELECT *` as selecting all modalities exposed in the target +context. That is a statement-projection rule whose available set must be +defined by the execution context; it does not encode a profile in the +statement, add/remove `OctadSchema` slots, or change `VCLS` arity. + +== Examples + +[cols="1,3"] +|=== +|Situation |Correct reading + +|A subject currently has Graph and Document witnesses. +|Those are two populated modalities in a fixed eight-slot Octad. The statement + says nothing by itself about the deployment's profile or the schema arity. + +|A deployment-specific profile lists Graph, Vector, and Document. +|That is a three-member modality set *if and when* a separately specified + profile contract defines it. VCL-UT does not currently encode this object in + `OctadSchema` or `VCLS` v1. + +|The gate input supplies `"graph": {"fields": [...]}` and omits `"spatial"`. +|The JSON parser materializes both fixed slots; the Spatial slot has an empty + field list. This is not a claim that Spatial is unsupported or unpopulated. + +|A statement uses `FROM HEXAD id`. +|In the current Rust parser this is a legacy spelling for the same Octad source + as `FROM OCTAD id`; it is not a request for a six-modality profile. +|=== + +== Compatibility and Future Profile Work + +Keep `OctadSchema` and `VCLS` v1 fixed-arity and unchanged. Do not overload the +current schema type, gate `schema_version`, or `VCLS` version with profile +selection or profile versioning. + +If a future integration needs profiles on the wire, define a separate, +explicitly versioned profile type and transport. At minimum, that contract must +name its scope, identify its supported modality catalog, state membership and +cardinality unambiguously, define what omission means, and distinguish +capability from per-subject witness presence. It must not imply that an +`OctadSchema` decoder accepts arbitrary modality counts. Keep such API/schema +work separate from this terminology decision and version it according to the +consumer contract. + +== References + +* `src/core/Schema.idr` — the dependent `OctadSchema` definition. +* `src/interface/parse/src/schema.rs` — the Rust mirror. +* `src/interface/parse/WIRE-FORMAT.adoc` — the exact `VCLS` v1 codec. +* `docs/vclt-gate-contract.adoc` — the JSON gate input contract. +* `docs/decisions/0007-modality-profiles-vs-octad-schema.adoc` — the + architecture decision that adopts this distinction. diff --git a/docs/standards/README.adoc b/docs/standards/README.adoc index 9402c0b..ebe2b04 100644 --- a/docs/standards/README.adoc +++ b/docs/standards/README.adoc @@ -2,3 +2,17 @@ // SPDX-License-Identifier: CC-BY-SA-4.0 = Standards Unit +:toc: preamble + +This unit contains the repository's normative technical and terminology +contracts. + +[cols="2,4"] +|=== +|Document |Contract + +|link:MODALITY-PROFILES.adoc[Modality profiles and the fixed Octad contract] +|Defines the distinction between implementation-specific modality profiles, + runtime witness population, and VCL-UT's fixed eight-slot `OctadSchema` and + `VCLS` v1 wire contract. +|=== diff --git a/docs/vcl-total-grammar.ebnf b/docs/vcl-total-grammar.ebnf index db43817..8dff96a 100644 --- a/docs/vcl-total-grammar.ebnf +++ b/docs/vcl-total-grammar.ebnf @@ -85,7 +85,7 @@ modality_spec = 'GRAPH', [graph_projection] | 'TEMPORAL', [temporal_projection] | 'PROVENANCE', [provenance_projection] | 'SPATIAL', [spatial_projection] - | '*' ; (* All available modalities *) + | '*' ; (* All modalities exposed in the target context; OctadSchema stays 8-slot *) modality_name = 'GRAPH' | 'VECTOR' | 'TENSOR' | 'SEMANTIC' | 'DOCUMENT' | 'TEMPORAL' | 'PROVENANCE' | 'SPATIAL' ; @@ -105,10 +105,13 @@ spatial_projection = '(', spatial_fields, ')' ; ============================================================================ *) from_clause = 'FROM', source_spec ; -source_spec = hexad_source | federation_source | store_source ; +source_spec = octad_source | federation_source | store_source ; -(* Direct hexad reference *) -hexad_source = 'HEXAD', uuid ; +(* Direct reference to one Octad identity; this does not select a modality profile. *) +octad_source = octad_keyword, (uuid | identifier | string_literal) ; + +(* OCTAD is preferred. HEXAD is a legacy alias for the same fixed Octad source. *) +octad_keyword = 'OCTAD' | 'HEXAD' ; (* Federation pattern (multiple nodes) *) federation_source = 'FEDERATION', node_pattern, [drift_policy] ; @@ -284,7 +287,7 @@ proof_spec_list = proof_spec, { 'AND', proof_spec } ; proof_spec = proof_type, '(', contract_name, ')', [proof_params] ; -proof_type = 'EXISTENCE' (* Hexad exists and is accessible *) +proof_type = 'EXISTENCE' (* Octad subject exists and is accessible *) | 'CITATION' (* Citation chain is valid *) | 'ACCESS' (* User has access rights *) | 'INTEGRITY' (* Data has not been tampered with *) @@ -533,7 +536,7 @@ comment = '--', { ? any character except newline ? }, '\n' (* Line comment *) keywords = 'SELECT' | 'FROM' | 'WHERE' | 'PROOF' | 'LIMIT' | 'OFFSET' | 'GRAPH' | 'VECTOR' | 'TENSOR' | 'SEMANTIC' | 'DOCUMENT' | 'TEMPORAL' | 'PROVENANCE' | 'SPATIAL' - | 'HEXAD' | 'FEDERATION' | 'STORE' + | 'OCTAD' | 'HEXAD' | 'FEDERATION' | 'STORE' | 'WITH' | 'DRIFT' | 'STRICT' | 'REPAIR' | 'TOLERATE' | 'LATEST' | 'AND' | 'OR' | 'NOT' | 'SIMILAR' | 'TO' | 'WITHIN' | 'NEAREST' | 'USING' diff --git a/docs/vclt-gate-contract.adoc b/docs/vclt-gate-contract.adoc index beca016..c162bc1 100644 --- a/docs/vclt-gate-contract.adoc +++ b/docs/vclt-gate-contract.adoc @@ -83,7 +83,7 @@ The gate explicitly does **NOT**: ---- { "schema_version": 1, - "statement": "ASSERT GRAPH.knows FROM HEXAD 'e-1' WHERE depth < 3 LIMIT 10", + "statement": "ASSERT GRAPH.knows FROM OCTAD 'e-1' WHERE depth < 3 LIMIT 10", "schema": { "...": "OctadSchema JSON, optional — see §Schema payload" } } ---- @@ -191,7 +191,20 @@ corpus soundness proof carries through to the gate. The optional `schema` object mirrors `src/interface/parse/src/schema.rs` `OctadSchema` (itself a 1:1 mirror of `src/core/Schema.idr`): the eight -modality schemas in record order, each a list of field definitions. +modality schemas in record order, each a list of field definitions. This is a +fixed eight-slot schema payload, not a modality profile or a variable-length +selection of modalities. + +In this JSON form, individual modality keys are optional. A missing key is +normalized by the current gate parser to that modality's fixed slot with an +empty `fields` list. Omitting the entire top-level `schema` constructs an +empty schema with all eight slots. Empty fields mean “no field declarations +were supplied here”; they do not mean unsupported, disabled, or unpopulated. +The request's `schema_version` versions this gate JSON contract, not a +modality profile. For the fixed `VCLS` v1 binary contract and the profile +terminology, see +link:../src/interface/parse/WIRE-FORMAT.adoc[WIRE-FORMAT.adoc] and +link:standards/MODALITY-PROFILES.adoc[MODALITY-PROFILES.adoc]. [source,json] ---- @@ -307,7 +320,7 @@ Request: [source,json] ---- { "schema_version": 1, - "statement": "INSPECT GRAPH.knows FROM HEXAD 'e-1' WHERE depth < 3 LIMIT 10", + "statement": "INSPECT GRAPH.knows FROM OCTAD 'e-1' WHERE depth < 3 LIMIT 10", "schema": { "graph": { "fields": [ { "name": "depth", "ty": "TInt", "nullable": false, "indexed": true } ] }, "vector": {"fields":[]}, "tensor": {"fields":[]}, "semantic": {"fields":[]}, "document": {"fields":[]}, "temporal": {"fields":[]}, "provenance": {"fields":[]}, "spatial": {"fields":[]} } } diff --git a/docs/wikis/GLOSSARY.adoc b/docs/wikis/GLOSSARY.adoc index d7cbece..c61b144 100644 --- a/docs/wikis/GLOSSARY.adoc +++ b/docs/wikis/GLOSSARY.adoc @@ -106,9 +106,22 @@ transaction handles. == M Modality (VeriSimDB):: -One of the 8 views of an entity in VeriSimDB's octad: graph, vector, tensor, -semantic, document, temporal, provenance, spatial. Each modality stores a -different representation of the same data. +A named kind of modal witness. VCL-UT's current Octad catalog has exactly +eight: graph, vector, tensor, semantic, document, temporal, provenance, and +spatial. A catalog entry does not by itself say whether a deployment supports +it or a subject currently has data in it. + +Modality profile:: +A versioned, implementation-specific selection of supported or enabled +modalities at a declared scope. Its own contract must define versioning, +membership/cardinality, and what omission means. VCL-UT currently has no +runtime profile type or profile wire format; this term is distinct from +`OctadSchema`. + +Modality set:: +A collection that states modality membership only. The term carries no fixed +cardinality, version, or capability policy; use *modality profile* when those +implementation-specific semantics are intended. Modal type:: A type that carries information about its context -- for example, whether data @@ -125,9 +138,15 @@ to prevent silent failures. == O Octad:: -The core data structure in VeriSimDB: a single entity with up to 8 simultaneous -representations (the 8 modalities). Every entity exists across all populated -modalities, and VeriSimDB keeps them in sync. +VeriSimDB's specific fixed model of eight named modality slots. A subject may +have witness data in only a subset of the slots; sparse runtime population +does not make the Octad structure variable-arity. + +`OctadSchema`:: +VCL-UT's fixed-arity schema value with one `ModalitySchema` for each of the +eight Octad modalities. It declares fields and their types; it does not encode +a deployment's modality profile or per-subject witness presence. An empty +field list is not an unsupported/absent-modality marker. == P @@ -210,9 +229,10 @@ VCL with all 10 levels of type safety. The subject of this project. If successful, it replaces VCL-DT as THE type-safe query path for VeriSimDB. VeriSimDB:: -A multi-modal database engine where every entity exists across up to 8 -simultaneous representations (the octad), with automatic drift detection and -self-normalisation. +A multi-modal database engine whose Octad model names eight modality slots. +Which slots are supported/enabled and which have witness data for a particular +subject are distinct implementation and runtime questions; neither changes +the fixed arity of VCL-UT's `OctadSchema`. == Z diff --git a/examples/inspect.vcl b/examples/inspect.vcl index 6185d07..c50f77f 100644 --- a/examples/inspect.vcl +++ b/examples/inspect.vcl @@ -5,17 +5,19 @@ -- VCL statements are propositions and epistemic requests to a consonance -- engine, not queries against a passive store (see README.adoc). The -- read-style `SELECT ... FROM ...` surface below is the epistemic-inspection --- convenience; `HEXAD ` is the legacy keyword naming the octad source --- (the eight modal witnesses). VCL-total decides admissibility of any +-- convenience; `OCTAD ` is the preferred spelling and `HEXAD ` is +-- a legacy alias for the same fixed eight-slot Octad source. Neither spelling +-- selects a modality profile. VCL-total decides admissibility of any -- proof-bearing statement before it affects live consonance state. -- Epistemic inspection: read consonance state across modal witnesses. -SELECT GRAPH.*, DOCUMENT.*, VECTOR.* FROM HEXAD 'entity-001' +SELECT GRAPH.*, DOCUMENT.*, VECTOR.* FROM OCTAD 'entity-001' -- Inspect cross-modal drift between two witnesses. -SELECT * FROM HEXAD 'entity-001' +SELECT * FROM OCTAD 'entity-001' WHERE DRIFT(VECTOR, DOCUMENT) > 0.3 +-- The legacy spelling remains accepted by the current Rust parser. -- Proof-bearing statement: VCL-total must discharge the attached obligation -- (existence + provenance) before the result is admissible. SELECT GRAPH.* FROM HEXAD 'entity-001' diff --git a/src/core/Grammar.idr b/src/core/Grammar.idr index 089c9a5..688a5ff 100644 --- a/src/core/Grammar.idr +++ b/src/core/Grammar.idr @@ -222,7 +222,7 @@ mutual ||| FROM clause source. public export data Source - = SrcOctad String -- HEXAD + = SrcOctad String -- OCTAD ; HEXAD is a legacy spelling | SrcFederation String -- FEDERATION | SrcStore String -- STORE diff --git a/src/core/Schema.idr b/src/core/Schema.idr index e000c0f..8d31c5d 100644 --- a/src/core/Schema.idr +++ b/src/core/Schema.idr @@ -8,6 +8,10 @@ ||| their types, and nullability — enabling Level 1 (schema binding) and ||| Level 3 (null safety) checking at compile time. ||| +||| `OctadSchema` is the fixed eight-slot schema, not a modality profile. +||| Empty fields in a slot do not encode deployment support or per-subject +||| witness presence. See `docs/standards/MODALITY-PROFILES.adoc`. +||| ||| Key properties proved: ||| - Field lookup is total (every reference resolves or fails explicitly) ||| - Type assignment is unique (no field has two types) diff --git a/src/interface/parse/WIRE-FORMAT.adoc b/src/interface/parse/WIRE-FORMAT.adoc index 3cd6f44..7df8e0f 100644 --- a/src/interface/parse/WIRE-FORMAT.adoc +++ b/src/interface/parse/WIRE-FORMAT.adoc @@ -123,7 +123,7 @@ mis-parse: Header: `56 43 4C 53` ("VCLS") then `u16` version (`01 00` for v1). -Body — `OctadSchema` is the 8 modality schemas in `Grammar.idr`/ +Body — `OctadSchema` is exactly the 8 modality schemas in `Grammar.idr`/ `Schema.idr` record order (fixed arity, no count): `ModalitySchema` (graph), `ModalitySchema` (vector), @@ -136,6 +136,16 @@ otherwise). Same totality contract as the `Statement` decoder; `VqlType`'s recursion is fuel-bounded identically (every node ≥ 1 discriminant byte). +[IMPORTANT] +==== +This fixed-arity `OctadSchema` stream does not encode a modality profile, +profile version, selected-subset count, or per-subject witness-presence bit. +Empty fields inside a slot remain an empty schema for that slot, not a signal +to omit it. A variable-cardinality modality profile requires a distinct, +versioned contract; it is not a `VCLS` v1 encoding. See +link:../../../docs/standards/MODALITY-PROFILES.adoc[the profile/Octad contract]. +==== + == Totality contract The decoder is *total*: bounds-checked, no panics, every malformed diff --git a/src/interface/parse/src/parser.rs b/src/interface/parse/src/parser.rs index 0bd1826..38277ce 100644 --- a/src/interface/parse/src/parser.rs +++ b/src/interface/parse/src/parser.rs @@ -453,10 +453,13 @@ fn parse_select_item(p: &mut P) -> Result { p.err("expected a SELECT item (`*`, MODALITY[.field], or AGG(expr))") } +/// Parses a FROM source: `OCTAD `, `HEXAD `, +/// `FEDERATION `, or `STORE `. +/// +/// `OCTAD` (preferred) and `HEXAD` (legacy alias) name the same +/// `Source::Octad`; neither spelling selects a modality profile. +/// Returns a parse error for an unknown source kind or missing identifier. fn parse_source(p: &mut P) -> Result { - // `OCTAD`/`HEXAD `, `FEDERATION `, `STORE `. - // OCTAD/HEXAD both accepted (grammar comment vs constructor name - // disagree); reconciled with the ReScript bridge in a later slice. if p.is_kw("OCTAD") || p.is_kw("HEXAD") { p.bump(); return Ok(Source::Octad(parse_source_arg(p)?)); diff --git a/src/interface/parse/src/schema.rs b/src/interface/parse/src/schema.rs index 1515967..1969453 100644 --- a/src/interface/parse/src/schema.rs +++ b/src/interface/parse/src/schema.rs @@ -56,7 +56,10 @@ pub struct ModalitySchema { } /// `Schema.idr`: `record OctadSchema` — the 8 modality schemas, in -/// record order (fixed arity; no length prefix on the wire). +/// record order (fixed arity; no length prefix on the wire). This is a static +/// schema, not a deployment's modality profile or a per-subject presence map; +/// an empty field list does not mean that the modality is unsupported or +/// unpopulated. See `docs/standards/MODALITY-PROFILES.adoc`. #[derive(Debug, Clone, PartialEq)] pub struct OctadSchema { pub graph: ModalitySchema, diff --git a/src/interface/parse/tests/parse.rs b/src/interface/parse/tests/parse.rs index abed127..b55a8c0 100644 --- a/src/interface/parse/tests/parse.rs +++ b/src/interface/parse/tests/parse.rs @@ -9,7 +9,7 @@ #![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use proptest::prelude::*; -use vcltotal_parse::{parse, parse_op}; +use vcltotal_parse::{ast::Source, parse, parse_op}; proptest! { #![proptest_config(ProptestConfig::with_cases(4096))] @@ -62,6 +62,16 @@ fn known_good_queries_parse() { } } +/// Verifies that legacy `HEXAD` and preferred `OCTAD` produce the same source. +#[test] +fn legacy_hexad_spelling_is_the_same_octad_source() { + let preferred = parse("SELECT * FROM OCTAD 'subject-1'").expect("OCTAD source parses"); + let legacy = parse("SELECT * FROM HEXAD 'subject-1'").expect("legacy HEXAD parses"); + + assert_eq!(preferred.source, Source::Octad("subject-1".to_string())); + assert_eq!(legacy.source, preferred.source); +} + // ── Deep nesting must fail-closed (typed error), NOT overflow the stack ── // Regression for the adversarial-review finding: the recursive-descent // expression grammar (parens, NOT chains, sub-queries) is depth-guarded so diff --git a/verification/proofs/corpus/VclTotal/Core/Grammar.idr b/verification/proofs/corpus/VclTotal/Core/Grammar.idr index 089c9a5..688a5ff 100644 --- a/verification/proofs/corpus/VclTotal/Core/Grammar.idr +++ b/verification/proofs/corpus/VclTotal/Core/Grammar.idr @@ -222,7 +222,7 @@ mutual ||| FROM clause source. public export data Source - = SrcOctad String -- HEXAD + = SrcOctad String -- OCTAD ; HEXAD is a legacy spelling | SrcFederation String -- FEDERATION | SrcStore String -- STORE diff --git a/verification/proofs/corpus/VclTotal/Core/Schema.idr b/verification/proofs/corpus/VclTotal/Core/Schema.idr index e000c0f..8d31c5d 100644 --- a/verification/proofs/corpus/VclTotal/Core/Schema.idr +++ b/verification/proofs/corpus/VclTotal/Core/Schema.idr @@ -8,6 +8,10 @@ ||| their types, and nullability — enabling Level 1 (schema binding) and ||| Level 3 (null safety) checking at compile time. ||| +||| `OctadSchema` is the fixed eight-slot schema, not a modality profile. +||| Empty fields in a slot do not encode deployment support or per-subject +||| witness presence. See `docs/standards/MODALITY-PROFILES.adoc`. +||| ||| Key properties proved: ||| - Field lookup is total (every reference resolves or fails explicitly) ||| - Type assignment is unique (no field has two types)