feat(phase0): complete GC1 feasibility and GC2 shared format contracts

- Record user evidence for directory fallback to complete GC1 (10/10 checks passed)

- Expand Format Specification 0.1 to Revision 0.2 with normative shared contracts

- Author JSON Schema Draft-07 at schema/xzbt-0.1.schema.json

- Implement zero-dependency semantic validator at tools/validate-exhibit.mjs

- Create 12-case conformance fixture suite and automated test runner (12/12 passing)

- Update implementation status, verification gates, and gap closure decisions

- Add devlog entry covering stall recovery and Phase 0 current state
This commit is contained in:
2026-09-05 11:38:48 -07:00
parent ca2830174f
commit e02d49a739
25 changed files with 2473 additions and 66 deletions
+277 -30
View File
@@ -1,33 +1,280 @@
# XZBT Format Specification 0.1
**XZBT format version:** 0.1
**Document revision:** 0.1
**Status:** Partial normative specification; contract completion required before dependent implementation
**Document revision:** 0.2
**Status:** Normative specification for shared contracts (document, types, ValueSpec, ConditionSpec, resolution); subsystem contracts in progress
**Related resources:** [PRD](../XZBT_0-1_MVP_Product_Requirements_Document.md), [decisions](XZBT_0-1_Gap_Closure_Decisions.md), [verification](XZBT_0-1_Verification_Gates.md)
This document defines shared semantic decisions and tracks the contracts still needed to implement the PRD. Existing PRD examples remain design inputs; a list of supported feature names is not a complete JSON grammar. No validator or complete JSON Schema has yet been produced.
This document defines normative syntax and runtime semantics for XZBT 0.1 exhibits. An exhibit is a UTF-8 JSON document that configures generic procedural visual, audio, cadence, and orchestration primitives. It does not contain executable JavaScript.
## 1. Format foundation
## 1. Document Structure & Metadata
Documents are UTF-8 JSON with `xzbt: "0.1"`, `meta.id`, and `meta.name` required. Unsupported format versions fail activation. Exhibit version and format version are separate. IDs use `^[a-z][a-z0-9_-]*$`; dots delimit reference paths.
### 1.1 Root Structure
A conforming `.xzbt` exhibit document consists of a top-level JSON object with the following properties:
The following is a complete minimal exhibit. An exhibit that performs no audio or visual work is valid:
| Field | Type | Required | Description |
| :--- | :--- | :---: | :--- |
| `xzbt` | `string` | **Yes** | Must be exactly `"0.1"`. Mismatched versions fail validation immediately. |
| `meta` | `object` | **Yes** | Exhibit identity and descriptive metadata. |
| `runtime` | `object` | No | Initial simulation and PRNG seed configuration. |
| `parameters` | `object` | No | User-tunable configuration definitions. Map of ID -> ParameterSpec. |
| `state` | `object` | No | Simulation-owned mutable variables. Map of ID -> StateSpec. |
| `signals` | `object` | No | Read-only runtime environmental signals. |
| `ui` | `object` | No | Generated control grouping, widgets, and layout preferences. |
| `components` | `object` | No | Reusable audio and visual sub-assemblies. |
| `visuals` | `object` | No | Visual canvas, camera, rendering passes, and primitive systems. |
| `audio` | `object` | No | Master bus, auxiliary buses, routing, and synthesizer definitions. |
| `sounds` | `object` | No | One-shot sound event templates. |
| `cadence` | `object` | No | Procedural pulse clocks, rhythm pools, and recurring trigger policies. |
| `modulators` | `object` | No | Continuous low-frequency oscillators, noise, and sample-and-hold generators. |
| `bindings` | `array` | No | Directed value-propagation links between sources and target properties. |
| `events` | `object` | No | Discrete state-change and lifecycle trigger handlers. |
| `scenarios` | `object` | No | Autonomous orchestrated sequences, timelines, and temporary overrides. |
Strict unknown-field policy: Any unrecognized property in behavior-bearing sections (`parameters`, `state`, `visuals`, `audio`, `cadence`, `modulators`, `bindings`, `events`, `scenarios`) is a fatal validation error (`ERR_UNKNOWN_FIELD`).
### 1.2 Metadata (`meta`)
Metadata provides provenance and UI presentation details. It never executes or modifies runtime logic:
| Field | Type | Required | Description |
| :--- | :--- | :---: | :--- |
| `id` | `string` | **Yes** | Unique exhibit identifier. Pattern: `^[a-z][a-z0-9_-]*$`. Max 64 chars. |
| `name` | `string` | **Yes** | Human-readable title displayed in the library and header. Max 128 chars. |
| `version` | `string` | No | Exhibit semantic version string (e.g., `"1.0.0"`). |
| `author` | `string` | No | Author or creator attribution string. Max 128 chars. |
| `description`| `string` | No | Brief narrative description of the exhibit. Max 1024 chars. |
| `license` | `string` | No | License terms (e.g., `"CC-BY-4.0"`, `"All Rights Reserved"`). |
| `tags` | `array[string]` | No | Array of category or aesthetic keywords. Max 16 tags. |
### 1.3 Identifiers and Namespaces
* **Identifier Syntax:** All resource IDs (exhibit ID, parameter IDs, state IDs, bus IDs, scenario IDs) must strictly match:
```text
^[a-z][a-z0-9_-]*$
```
* **Reference Path Syntax:** Dot-delimited path referencing a target property or namespace:
```text
<namespace>.<resource_id>[.<property>]
```
Valid canonical namespace prefixes: `parameters.*`, `state.*`, `signals.*`, `modulators.*`, `audio.buses.*`, `visuals.systems.*`. Dots are strictly forbidden within identifier names themselves.
---
## 2. Shared Type System & Coercion Rules
Every value in XZBT belongs to one of the following concrete primitive types:
| Type | Definition & Constraints | Serialization Example |
| :--- | :--- | :--- |
| `number` | IEEE 754 64-bit float. Must be finite (`Number.isFinite(v) === true`). `NaN`, `+Infinity`, and `-Infinity` are strictly forbidden and fail validation/evaluation. | `440.0`, `-0.5`, `1e3` |
| `integer` | IEEE 754 64-bit float restricted to integer values (`Number.isInteger(v) === true`). | `1`, `42`, `-8` |
| `boolean` | Logical truth value: `true` or `false`. | `true`, `false` |
| `string` | Valid UTF-8 text string. | `"drift"`, `"sine"` |
| `color` | CSS-compatible color: `#rgb`, `#rrggbb`, `#rrggbbaa`, or standard CSS color keyword. | `"#e8ad57"`, `"#11151c"` |
| `enum` | String constrained to an explicitly declared set of allowed tokens. | `"triangle"` in `["sine", "triangle", "saw"]` |
**Strict Coercion Ban:** The runtime performs **no implicit type coercion**. A string containing digits (e.g. `"440"`) will **not** be coerced into a number; a non-zero number will **not** be coerced into a boolean. Type mismatches produce `ERR_TYPE_MISMATCH`.
---
## 3. Parameter and State Specifications
### 3.1 Parameters (`parameters.<id>`)
Parameters represent user-configurable settings. They have documented defaults and bounds:
```json
{
"xzbt": "0.1",
"meta": {
"id": "empty-study",
"name": "Empty Study"
"activity": {
"type": "number",
"default": 0.5,
"min": 0.0,
"max": 1.0,
"step": 0.01,
"label": "Activity Level"
}
}
```
* **Storage Distinction:** User edits to parameters are persisted in client storage separately from default exhibit definitions.
* **Protection from `set`:** Actions triggered by scenarios or events **cannot** use `set` to mutate parameters. Temporary programmatic modifications must use `override`.
### 3.2 State Variables (`state.<id>`)
State variables represent simulation-owned state. They are initialized at launch and manipulated by runtime events and scenarios:
```json
{
"machine-load": {
"type": "number",
"initial": 0.25,
"min": 0.0,
"max": 1.0
}
}
```
* **Persistence Distinction:** State variables are transient simulation variables and are not stored across browser restarts unless explicitly configured.
---
## 4. ValueSpec 0.1 Normative Specification
A `ValueSpec` is the universal declarative expression used wherever a dynamic or configurable value is accepted. A `ValueSpec` must match one of the following five forms:
### 4.1 Literal Constant
A raw JSON number, boolean, string, or color:
```json
440.0
```
### 4.2 Reference (`ref`)
Reads the currently resolved value of a declared target:
```json
{ "ref": "parameters.activity" }
```
References are evaluated dynamically during each simulation tick unless used within a construct with documented static sampling timing.
### 4.3 Random Range (`random`)
Samples a pseudo-random value from a uniform bounded range:
```json
{
"random": {
"min": 200.0,
"max": 800.0,
"integer": false
}
}
```
* `min` (`number`, required): Lower bound.
* `max` (`number`, required): Upper bound (`max >= min`).
* `integer` (`boolean`, optional, default `false`): If `true`, output is rounded to an integer via `Math.floor(min + prng() * (max - min + 1))`.
* **Sampling Boundary:** Sampled **only** at object instantiation or event invocation. It is **never** sampled per-frame.
### 4.4 Weighted Selection (`choose`)
Selects one item from an array of weighted options:
```json
{
"choose": [
{ "value": "sine", "weight": 6 },
{ "value": "triangle", "weight": 3 },
{ "value": "square", "weight": 1 }
]
}
```
* `choose` (`array[object]`, required): Non-empty array of choice objects.
* Each entry requires `value` (`literal` or nested `ValueSpec`) and `weight` (`number > 0`).
### 4.5 Calculation Operator (`op`)
Evaluates an arithmetic or mathematical operation over argument operands:
```json
{
"op": "multiply",
"args": [
{ "ref": "parameters.activity" },
1.5
]
}
```
#### Supported Operators and Arity
| Operator | Arity | Description | Domain Rules & Safe Fallback |
| :--- | :---: | :--- | :--- |
| `abs` | 1 | Absolute value: `\|a\|` | Finite number. |
| `negate` | 1 | Arithmetic negation: `-a` | Finite number. |
| `round` | 1 | Nearest integer: `Math.round(a)` | Finite number. |
| `floor` | 1 | Floor integer: `Math.floor(a)` | Finite number. |
| `ceil` | 1 | Ceiling integer: `Math.ceil(a)` | Finite number. |
| `add` | 2 | Addition: `a + b` | Finite number. |
| `subtract` | 2 | Subtraction: `a - b` | Finite number. |
| `multiply` | 2 | Multiplication: `a * b` | Finite number. |
| `divide` | 2 | Division: `a / b` | **Division-by-zero protection:** If `b === 0`, evaluates safely to `0.0` (never `NaN` or `Infinity`). |
| `min` | 2 | Minimum: `Math.min(a, b)` | Finite numbers. |
| `max` | 2 | Maximum: `Math.max(a, b)` | Finite numbers. |
| `clamp` | 3 | Range clamp: `[val, min, max]` | Evaluates to `Math.min(max, Math.max(min, val))`. Requires `min <= max`. |
| `lerp` | 3 | Linear interpolation: `[a, b, t]` | Evaluates to `a + (b - a) * t`. Unclamped `t` unless combined with `clamp`. |
---
## 5. ConditionSpec 0.1 Normative Specification
A `ConditionSpec` evaluates to a boolean (`true` or `false`) and controls scenario triggers, conditional actions, and branching logic.
### 5.1 Comparison Expressions
Compares two `ValueSpec` expressions:
```json
{
"op": "gt",
"left": { "ref": "state.machine-load" },
"right": 0.85
}
```
* Supported comparison operators:
* `eq`: Equality (`left === right`)
* `ne`: Inequality (`left !== right`)
* `gt`: Greater than (`left > right`)
* `gte`: Greater than or equal to (`left >= right`)
* `lt`: Less than (`left < right`)
* `lte`: Less than or equal to (`left <= right`)
* `left` and `right` must evaluate to compatible primitive types (`number` with `number`, `boolean` with `boolean`, `string` with `string`). Cross-type comparison produces `ERR_TYPE_MISMATCH`.
### 5.2 Logical Combinators
Combines child condition expressions:
* **Conjunction (`and`):** All child conditions must evaluate to `true`. Short-circuits on first `false`.
```json
{ "and": [ { "op": "gt", "left": { "ref": "state.machine-load" }, "right": 0.5 }, { "op": "eq", "left": { "ref": "parameters.enabled" }, "right": true } ] }
```
* **Disjunction (`or`):** At least one child condition must evaluate to `true`. Short-circuits on first `true`.
```json
{ "or": [ { "op": "lt", "left": { "ref": "state.energy" }, "right": 0.1 }, { "op": "eq", "left": { "ref": "state.alarm" }, "right": true } ] }
```
* **Negation (`not`):** Inverts the child condition.
```json
{ "not": { "op": "eq", "left": { "ref": "parameters.mute" }, "right": true } }
```
### 5.3 Edge-Triggering & Re-Arming Semantics
* **Rising-Edge Trigger:** When a condition is used as an event trigger or scenario trigger, it fires **only** when its evaluation transitions from `false` on tick $T-1$ to `true` on tick $T$.
* **Re-Arming Rule:** As long as the condition remains continuously `true`, it **will not fire again**. It must evaluate to `false` on at least one tick to re-arm before it can fire on a subsequent `true` evaluation.
---
## 6. TimeSpec and DurationSpec 0.1
### 6.1 Duration Literals
Durations are expressed as strings containing a non-negative finite number and a single explicit unit:
* `ms`: Milliseconds (e.g., `"250ms"`, `"16.67ms"`)
* `s`: Seconds (e.g., `"4s"`, `"0.5s"`)
* `m`: Minutes (e.g., `"2.5m"`, `"1m"`)
* `h`: Hours (e.g., `"1.5h"`, `"8h"`)
Compound formats (e.g., `"1m30s"`) are strictly invalid (`ERR_INVALID_DURATION`). Internally, the runtime converts all durations to millisecond floating-point numbers.
### 6.2 Procedural Bounded Duration (`TimeSpec`)
Where procedural timing is permitted (e.g., cadence intervals, scenario wait steps), a bounded random TimeSpec may be used:
```json
{
"random": {
"min": "500ms",
"max": "2.5s"
}
}
```
Validate structure before activating resources. Follow structural validation with type, reference, graph, ownership, and resource-limit checks. Unknown fields in behavior-bearing objects are errors. Do not coerce strings to numbers or silently invent semantics for unsupported constructs.
---
A structurally valid minimal exhibit does not prove expressive capability. Complete audiovisual examples and invalid fixtures remain required under GC2.
## 7. Diagnostic Error Code Standard
## 2. Shared value resolution
To ensure consistent error reporting between structural schema validation, semantic validation, and runtime execution, all diagnostic errors must use the following standard codes:
| Error Code | Stage | Cause |
| :--- | :--- | :--- |
| `ERR_SCHEMA_VALIDATION` | Structural | Missing required fields, invalid JSON types, or malformed top-level shapes. |
| `ERR_UNKNOWN_FIELD` | Structural / Semantic | Behavior-bearing block contains an undeclared property. |
| `ERR_UNSUPPORTED_VERSION` | Structural | Document `xzbt` attribute is not `"0.1"`. |
| `ERR_INVALID_ID` | Structural / Semantic | Identifier fails `^[a-z][a-z0-9_-]*$` regex or exceeds length limits. |
| `ERR_INVALID_REFERENCE` | Semantic | Reference path does not resolve to an existing declared resource or property. |
| `ERR_TYPE_MISMATCH` | Semantic / Runtime | Provided value or expression type does not match target property type. |
| `ERR_CYCLIC_DEPENDENCY` | Semantic | Directed cycle detected in bindings or reference dependencies. |
| `ERR_OUT_OF_BOUNDS` | Semantic / Runtime | Constant or default value violates min/max clamps. |
| `ERR_INVALID_OPERATOR` | Semantic | ValueSpec `op` or ConditionSpec `op` is not in the recognized operator set. |
| `ERR_INVALID_ARITY` | Semantic | ValueSpec `args` array length does not match operator requirement. |
| `ERR_INVALID_DURATION` | Structural / Semantic | Duration string violates single-unit regex or contains negative values. |
## 8. Shared value resolution
For each supported target, evaluate:
@@ -58,7 +305,7 @@ Reject conflicting ordinary bindings and dependency cycles that cannot be evalua
| Duration and scenario overrides compete | Priority and activation order decide, not scope |
| A target has legal additive modulation | Modulation follows the winning override, then the safety clamp applies |
## 3. Time and random evaluation
## 9. Time and random evaluation
The initial logical simulation step is 1/60 second. Rendering does not own simulation time. Audio scheduling maps logical time to the audio clock with a bounded horizon.
@@ -68,7 +315,7 @@ Random and weighted-choice ValueSpecs are sampled at the containing object's doc
Separate random streams isolate cadence, scenario instances, visual systems, sound instances, and manual sampling. Reproducibility is scoped to a runtime version, recorded numeric seed, and logical input sequence. Tests that use external or analysed signals must supply deterministic input traces.
## 4. Ownership and termination
## 10. Ownership and termination
Ownership propagates through nested events and actions. Scenario resources inherit the scenario owner unless the resource type allows an explicit persistent owner. Scenario-created duration overrides cannot outlive the owner, apart from their bounded release cleanup.
@@ -78,24 +325,24 @@ Condition triggers require a false condition before rearming after a successful
Statically check event/scenario feedback where possible and bound runtime dispatch. Resource cleanup must remain possible after the ordinary dispatch budget is exhausted.
## 5. Contract completion register
## 11. Contract completion register
All rows below require work; none claims a completed implementation. Complete shared contracts before implementing dependent subsystems. Use PRD section numbers as stable lookup references.
Complete shared contracts before implementing dependent subsystems. Use PRD section numbers as stable lookup references.
| Contract | Existing PRD input | Required completion |
| --- | --- | --- |
| Document/schema | 9-14, 113-116, 121 | All structural shapes, unknown-field policy, metadata extensions, size/depth limits, diagnostic paths, full internal schema |
| Values and conditions | 15-21, 33 | Operator arity and types, numerical errors, array/object literals, live versus sampled fields, seed algorithm and stream derivation |
| References and bindings | 13, 17, 31-32 | Target-capability table, instance/input scope, evaluation order, cycles, disabled bindings, exact smoothing |
| Actions and transitions | 22-30 | Fields and defaults per action, override priorities outside scenarios, target/command matrix, interrupted transitions, instance IDs |
| Audio | 34-60 | Complete recipe/component shapes, node defaults, automation timing, clamp implementation, one-shot endings and tails, unlock behavior, master protection contract |
| Cadence | 61-68 | Exact selection/cooldown/overlap fields, clocks, pool collisions, pending audio, manual sampling isolation and continuous-sample termination |
| Visuals | 69-89 | Primitive/system/behavior fields, angle and motion units, transform order, depth projection, field behavior, morph compatibility, effect approximation and limits |
| Events/scenarios | 90-102 | Trigger shapes, hooks and failure ordering, scope inheritance, deferred ordering/expiry, relative/repeated timeline semantics and termination boundaries |
| Generated UI | 103-107 | Widget compatibility, button actions, parameter validation and override display, group/control ordering |
| Runtime/library | 108-112, 117-127 | Clock/audio synchronization and stalls, import equality, update compatibility, transactions, failure recovery, persistence schema |
| Contract | Existing PRD input | Required completion | Status |
| --- | --- | --- | --- |
| Document/schema | 9-14, 113-116, 121 | Top-level shapes, unknown-field policy, identifier regex, reference paths, standard diagnostic codes | **Complete (Rev 0.2)** |
| Values and conditions | 15-21, 33 | Operator arity/table, division-by-zero protection, sampling timing boundaries, edge-trigger re-arming | **Complete (Rev 0.2)** |
| References and bindings | 13, 17, 31-32 | Target-capability table, instance/input scope, evaluation order, cycles, disabled bindings, exact smoothing | Planned (Phase 0 / GC3) |
| Actions and transitions | 22-30 | Fields and defaults per action, override priorities outside scenarios, target/command matrix, interrupted transitions, instance IDs | Planned (Phase 0 / GC3) |
| Audio | 34-60 | Complete recipe/component shapes, node defaults, automation timing, clamp implementation, one-shot endings and tails, unlock behavior, master protection contract | Subsystem contract (Phase 3) |
| Cadence | 61-68 | Exact selection/cooldown/overlap fields, clocks, pool collisions, pending audio, manual sampling isolation and continuous-sample termination | Subsystem contract (Phase 5) |
| Visuals | 69-89 | Primitive/system/behavior fields, angle and motion units, transform order, depth projection, field behavior, morph compatibility, effect approximation and limits | Subsystem contract (Phase 4) |
| Events/scenarios | 90-102 | Trigger shapes, hooks and failure ordering, scope inheritance, deferred ordering/expiry, relative/repeated timeline semantics and termination boundaries | Subsystem contract (Phase 6) |
| Generated UI | 103-107 | Widget compatibility, button actions, parameter validation and override display, group/control ordering | Subsystem contract (Phase 7) |
| Runtime/library | 108-112, 117-127 | Clock/audio synchronization and stalls, import equality, update compatibility, transactions, failure recovery, persistence schema | Subsystem contract (Phase 1/8) |
## 6. Contract template and conformance artifacts
## 12. Contract template and conformance artifacts
Each construct must record its JSON shape; required and optional fields; types, units, ranges, and defaults; supported ValueSpec fields and evaluation timing; read/write namespaces; lifecycle and ownership; precedence; validation errors; runtime failure behavior; and resource costs or limits.