@texuli/spec 0.1.0-next.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +157 -159
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,170 +1,168 @@
1
1
  # @texuli/spec
2
2
 
3
- The schema-first blueprint contract (spec/Compose design, plan B1): the
4
- platform-neutral source of truth for blueprint structure, the catalog
5
- vocabulary, capability tiers and diagnostics. TypeScript and Kotlin are
6
- deterministic projections generated from it, and a conformance harness keeps
7
- everything from drifting.
8
-
9
- **Status: in development, not published.** Layer 0, no dependencies,
10
- framework-free. Kotlin is generated as committed text by this package's
11
- TypeScript generator; no Kotlin toolchain runs here, and nothing is compiled
12
- or published to Maven.
13
-
14
- The package tarball build compiles `generated/typescript/` into the matching
15
- `dist/generated/typescript/` location. The source stays beside `src/` so the
16
- spec generator and integrity manifest keep their established output paths;
17
- the packer maps runtime and declaration imports to emitted `.js` and `.d.ts`
18
- files there. Kotlin projections remain generated text and are not part of the
19
- TypeScript package output.
20
-
21
- ## Layout
22
-
23
- | Path | What it holds |
24
- | --- | --- |
25
- | `schemas/` | The normative JSON schemas: `blueprint` (envelope v1 and the node tree), `catalog`, `diagnostics`, `manifest` |
26
- | `catalog/components.json` | The closed vocabulary, projected from the built catalog: id, label, summary, group, placement (`app`/`content`), emit tiers, capability and props |
27
- | `catalog/capabilities.json` | Reviewed capability claims. Empty: no id is audited portable yet, so every capability is `unknown` (ADR-003) |
28
- | `fixtures/golden/` | Blueprints that must validate: a report, a dashboard, a proactive deck and a report with a named slot and a `when` condition (fictional data) |
29
- | `fixtures/invalid/` | Blueprints that must fail with exact diagnostic codes, one or more per code, including slot and condition cases (an undeclared or root `slot`, an unknown condition `op`, an extra condition field) |
30
- | `manifest.json` | The spec version, the dialect and a SHA-256 per normative file |
31
- | `versions.json` | Every released spec version pinned to its spec digest (not normative: it pins the normative files) |
32
- | `generated/typescript/`, `generated/kotlin/` | The projections. Never edit them |
33
- | `generated-manifest.json` | A SHA-256 per generated file |
34
-
35
- ## The dialect
36
-
37
- Schemas use a closed subset of JSON Schema 2020-12 (`DIALECT_KEYWORDS`):
38
- `type`, `properties`, `required`, `additionalProperties`, `items`, `enum`,
39
- `const`, string, number and array bounds, `pattern`, and local `$ref` /
40
- `$defs`. Objects must be closed (`additionalProperties: false`) or explicit
41
- maps. Anything else fails `checkSchemaDocument`, and generation refuses it.
42
-
43
- ## Exports
44
-
45
- - `@texuli/spec`, the runtime half:
46
- - the generated types (`BlueprintEnvelope`, `SpecCatalog`, `SpecValidation` …);
47
- - `SPEC_COMPONENT_IDS` and `SpecComponentProps`;
48
- - `validateInstance` (the dialect validator);
49
- - `validateBlueprint` (the target-neutral blueprint check: envelope
50
- schema, closed ids and props, prop kinds and enums, required props, no
51
- platform-extension props from data, a node `slot` that names a slot prop
52
- of its parent (`unknown-slot`), the portable profile failing closed,
53
- and an optional catalog binding);
54
- - `canonicalJson` and a synchronous `sha256`.
55
- - `@texuli/spec/codegen`, build time: `buildSpec`, `projectCatalog`,
56
- `checkConformance`, `formatJson`.
57
-
58
- URL policy, tree limits, grammar and rendering stay in the runtime validator,
59
- `@texuli/catalog/validate`.
60
-
61
- ## Projections
62
-
63
- - **Web extensions.** Props of kind `slot`, `event` or `unknown`, and the
64
- `class`, `className`, `style` and chart `renderer` props, are marked
65
- `extension: "web"`. They are left out of `SpecComponentProps`, and data
66
- that sets them is refused.
67
- - **Kotlin** (`com.texuli.spec`, Kotlin 1.9+ for `entries` and
68
- `data object`): data classes, closed enums and static decoders over a
69
- generated `JsonValue` model, with no library dependency. Decoders check
70
- JSON types, required and unknown fields, enums and constants. Patterns
71
- and limits are the shared validator's job.
72
- - **Stamp.** Every generated file carries the spec version and a digest of
73
- the normative files. There are no timestamps, and output is
74
- byte-identical for the same inputs in any order.
75
-
76
- ## Regenerate
3
+ The blueprint contract of [Texuli](https://texuli.com), an MIT-licensed
4
+ Svelte 5 component library by Dailybot, Inc. (*Small pieces. Infinite
5
+ possibilities.*). A **blueprint** is a JSON document, usually written by an
6
+ AI agent, that describes an interface as a tree of components from Texuli's
7
+ closed catalog. `@texuli/spec` is the platform-neutral source of truth for
8
+ that format: the generated TypeScript types, the closed component
9
+ vocabulary, a target-neutral blueprint validator and deterministic hashing.
10
+
11
+ Use it when you generate, store, diff or check blueprints, or build a
12
+ renderer for them. The same contract also generates the Kotlin models used
13
+ by Texuli's Kotlin Multiplatform twin. The package is framework-free: no
14
+ DOM, no Svelte, no Node APIs and no runtime dependencies.
15
+
16
+ > **Status: 0.x release.** Texuli is in development. The packages are
17
+ > published to npm as `0.2.0`, a pre-1.0 release (1.0.0 will be the first
18
+ > stable release). Under 0.x, a new minor (`0.3.0`) may contain breaking
19
+ > changes, so pin the exact version or use `^0.2.0`, which accepts only 0.2.x.
20
+
21
+ ## Install
77
22
 
78
23
  ```bash
79
- pnpm exec tsx packages/spec/scripts/bootstrap-catalog.ts # refresh catalog/components.json from the built catalog
80
- pnpm exec tsx packages/spec/scripts/generate.ts # write manifests and projections
81
- pnpm exec tsx packages/spec/scripts/generate.ts --check # fail on drift
24
+ npm install @texuli/spec
82
25
  ```
83
26
 
84
- ## Conformance
85
-
86
- `pnpm vitest run packages/spec` runs the harness. Drift is a failed gate:
87
- - every schema stays in the dialect;
88
- - the manifest digests match the normative files;
89
- - regenerating gives byte-identical files, none missing or extra;
90
- - the golden fixtures validate and the invalid fixtures fail with exactly
91
- their codes, covering every diagnostic code;
92
- - `components.json` equals the projection of the live catalog, and the
93
- blueprint schema matches the envelope `@texuli/catalog` reads;
94
- - generation is deterministic and refuses schemas outside the dialect;
95
- - the Kotlin text declares its package, balances its brackets, defines
96
- every type it references and decodes closed;
97
- - the spec version and digest match the newest release in `versions.json`.
98
-
99
- When the catalog changes, refresh `components.json`, regenerate and review
100
- the diff. Then classify the change, bump the version, and pin it (see
101
- Versioning).
27
+ ```bash
28
+ pnpm add @texuli/spec
29
+ # or
30
+ yarn add @texuli/spec
31
+ ```
102
32
 
103
- ## Versioning
33
+ No peer dependencies and no CSS. The package is ESM-only and ships
34
+ TypeScript declarations. The normative JSON documents (the blueprint
35
+ schema, the component catalog and the fixtures) live in the
36
+ [repository](https://github.com/DailybotHQ/texuli/tree/main/packages/spec);
37
+ they are not part of the npm package.
38
+
39
+ ## Quick start
40
+
41
+ ```ts
42
+ import {
43
+ canonicalJson,
44
+ type Schema,
45
+ SPEC_COMPONENT_IDS,
46
+ SPEC_VERSION,
47
+ sha256,
48
+ validateInstance,
49
+ } from '@texuli/spec';
50
+
51
+ SPEC_VERSION; // the spec version, e.g. '0.2.0'
52
+ SPEC_COMPONENT_IDS.includes('alert'); // true: the closed component vocabulary
53
+
54
+ // The dialect validator: a closed subset of JSON Schema 2020-12.
55
+ const schema: Schema = {
56
+ type: 'object',
57
+ properties: { title: { type: 'string', maxLength: 80 } },
58
+ required: ['title'],
59
+ additionalProperties: false,
60
+ };
61
+ validateInstance(schema, { title: 'Weekly report' }); // []
62
+ validateInstance(schema, { title: 42, extra: true });
63
+ // [{ code: 'type', path: '$.title', … }, { code: 'additional-property', path: '$.extra', … }]
64
+
65
+ // Deterministic serialization and hashing, identical in every runtime.
66
+ const digest = sha256(canonicalJson({ b: 1, a: [true, null] }));
67
+ ```
68
+
69
+ To check a whole blueprint, pass the blueprint schema and catalog documents
70
+ from the repository's `packages/spec/schemas/blueprint.schema.json` and
71
+ `packages/spec/catalog/components.json`:
104
72
 
105
- **The spec digest** is the SHA-256 of `manifest.json`'s canonical JSON: the
106
- spec version, the dialect and a digest per normative file (schemas,
107
- `catalog/components.json`, `catalog/capabilities.json` and every fixture).
108
- Every generated file carries it in its stamp (`// Spec 0.2.0, digest …`).
109
- The same normative files always give the same digest.
73
+ ```ts
74
+ import { type Schema, type SpecCatalog, validateBlueprint } from '@texuli/spec';
75
+
76
+ const result = validateBlueprint(blueprint, {
77
+ blueprintSchema: blueprintSchemaJson as Schema,
78
+ catalog: componentsJson as SpecCatalog,
79
+ });
80
+ if (!result.ok) {
81
+ for (const d of result.diagnostics) console.warn(d.code, d.path, d.message);
82
+ }
83
+ ```
84
+
85
+ A node with an id outside the catalog fails with `unknown-id`; other codes
86
+ include `schema`, `unknown-prop`, `prop-type`, `enum-value`,
87
+ `missing-required`, `extension-prop`, `catalog-mismatch`,
88
+ `unsupported-profile` and `unknown-slot`.
89
+
90
+ ## What's inside
91
+
92
+ | Subpath | Purpose | Headline exports |
93
+ | --- | --- | --- |
94
+ | `@texuli/spec` | Runtime: types, vocabulary, validation, hashing | `BlueprintEnvelope`, `SpecCatalog`, `SpecValidation` and the other generated types; `SPEC_COMPONENT_IDS`, `SpecComponentProps`, `SPEC_CATALOG_HASH`, `SPEC_VERSION`; `validateBlueprint`, `validateTree`, `validateInstance`, `checkSchemaDocument`; `canonicalJson`, `sha256` |
95
+ | `@texuli/spec/codegen` | Build time: generation and conformance | `buildSpec`, `projectCatalog`, `checkConformance`, `formatJson`, `nextSpecVersion`, `checkVersionHistory` |
96
+
97
+ ## Key guarantees
98
+
99
+ - **Closed vocabulary.** Component ids, prop names, prop kinds and enum
100
+ values are closed; anything outside the catalog is refused.
101
+ - **No platform props from data.** Web-only props (slots, events, `class`,
102
+ `className`, `style` and the chart `renderer`) are marked as web
103
+ extensions, left out of `SpecComponentProps`, and refused when a
104
+ blueprint sets them.
105
+ - **Fails closed.** The portable profile is refused until a capability is
106
+ audited portable, and a blueprint bound to another catalog hash is
107
+ refused when you pass `catalogHash`.
108
+ - **Deterministic.** Canonical JSON sorts keys at every depth, and every
109
+ generated file carries the spec version and digest with no timestamps.
110
+ - **Structure only.** This validator checks structure. URL policy, tree
111
+ limits and rendering live in the runtime validator of
112
+ [`@texuli/catalog`](https://www.npmjs.com/package/@texuli/catalog).
113
+
114
+ ## Versioning
110
115
 
111
- **The version follows the digest.** Every normative change changes the
112
- digest, and a changed digest needs a new semantic version.
113
- `tests/versioning.test.ts` fails when the digest moves without one. The
114
- release goes in `versions.json`: its version, its digest, its change class
115
- and a one-line summary.
116
+ The spec has its own semantic version (`SPEC_VERSION`), separate from the
117
+ npm package version. The **spec digest** is the SHA-256 of the manifest
118
+ that pins every normative file (schemas, catalog and fixtures); any
119
+ normative change moves the digest and requires a new spec version.
116
120
 
117
- | Class | What it covers | Before 1.0.0 | From 1.0.0 |
121
+ | Change class | Examples | Before 1.0.0 | From 1.0.0 |
118
122
  | --- | --- | --- | --- |
119
- | patch | Nothing accepted changes: descriptions, diagnostic wording, a new fixture for behavior that already holds | patch | patch |
120
- | minor | Additive: optional fields, new catalog ids, new optional props, new diagnostic codes for data that was already refused, new named extensions. Existing portable fixtures still pass | minor | minor |
121
- | major | Removing or renaming ids, props or fields; changing a prop type; making something required; changing what accepted data means | minor | major |
122
-
123
- `nextSpecVersion(previous, class)` computes the step and
124
- `checkVersionHistory` enforces it. Before 1.0.0, any change to accepted data
125
- bumps the minor number. Moving to 1.0.0 is a release decision for the owner,
126
- not a side effect of a change. 0.1.0, the bootstrap, has no pinned digest:
127
- its normative files moved without a version until 0.2.0.
128
-
129
- **What a projection change means for consumers:**
130
- - **TypeScript (`@texuli/spec`):** a patch release leaves the generated types
131
- and `SPEC_COMPONENT_IDS` alone, apart from the stamp. Code that compiled
132
- against a minor release keeps compiling, but new optional fields and ids
133
- can appear in data it reads. A major-class change (a minor bump before
134
- 1.0.0) may remove or retype what it relied on.
135
- - **Kotlin and native (`native/`):** `texuli-spec` compiles
136
- `generated/kotlin` from this package, so a native build always matches the
137
- checked-out spec. The generated decoders are closed: a blueprint that uses
138
- a field from a newer spec fails to decode on an older native build with a
139
- `schema` diagnostic. It does not pass silently. After a change, regenerate,
140
- rebuild native, and refresh the conformance traces when goldens moved
141
- (`pnpm exec tsx native/conformance/web/trace.ts --write`). Native
142
- conformance compares the native refusals with every invalid fixture's
143
- codes.
144
- - **Blueprints:** a blueprint binds to an exact catalog hash today. The
145
- envelope field for a compatible spec range is **planned, not built**.
146
- Until it exists, a consumer checks the spec version it ships against the
147
- stamp of the spec it was built from.
148
-
149
- Migrations between versions (deterministic blueprint transforms tested per
150
- version pair) are **planned, not built**: nothing has needed one yet.
151
-
152
-
153
- ## Named slots and conditions
154
-
155
- A node may carry `slot` (audit G04: the parent's named slot, a string such as
156
- `hero`) and `when` (audit G07: the blocks `Condition` AST that shows the node
157
- when true). Both match what `@texuli/catalog` renders.
158
-
159
- ## Not yet
160
-
161
- - Behavior contracts, token roles and the token-to-Compose generator (B1
162
- steps 2 and 5).
163
- - Making the spec authoritative for the web packages (B1 step 3 cutover);
164
- today the catalog manifests are the bootstrap input.
165
- - Compiling the Kotlin, and the native runtime (B2).
166
- - A full type for `when`. The dialect has no unions, so `condition` and
167
- `numberFormula` are closed records whose `op` is an enum and whose operands
168
- are typed (except `value`, which is a number for `num` and a formula for
169
- `round` and `clamp`). Which operands each `op` needs, and the formula
170
- limits, are checked by the runtime parser in `@texuli/blocks/formula`.
123
+ | patch | Descriptions, diagnostic wording, a fixture for behavior that already holds | patch | patch |
124
+ | minor | Optional fields, new catalog ids, new optional props, new diagnostic codes for data that was already refused | minor | minor |
125
+ | major | Removing or renaming ids, props or fields; changing a prop type; making something required | minor | major |
126
+
127
+ For TypeScript consumers, a patch leaves the generated types and
128
+ `SPEC_COMPONENT_IDS` unchanged; code that compiled against a minor release
129
+ keeps compiling, though new optional fields and ids can appear in data it
130
+ reads. Native (Kotlin) builds compile the generated models from the same
131
+ spec, and their decoders are closed: a blueprint that uses a field from a
132
+ newer spec fails to decode on an older native build with a `schema`
133
+ diagnostic instead of passing silently. A blueprint binds to an exact
134
+ catalog hash today; an envelope field for a compatible spec range, and
135
+ migrations between versions, are planned and not built.
136
+
137
+ The full rules (the digest, `versions.json` pins, regeneration and the
138
+ conformance harness) are in
139
+ [contract.md](https://github.com/DailybotHQ/texuli/blob/main/packages/spec/docs/contract.md).
140
+
141
+ ## Documentation
142
+
143
+ - Website: [texuli.com](https://texuli.com), the
144
+ [agents overview](https://texuli.com/agents-page/) and
145
+ [web and native](https://texuli.com/web-and-native/)
146
+ - Schemas, catalog and fixtures:
147
+ [packages/spec](https://github.com/DailybotHQ/texuli/tree/main/packages/spec)
148
+ - The contract in depth (the JSON Schema dialect, projections, conformance
149
+ and versioning): [contract.md](https://github.com/DailybotHQ/texuli/blob/main/packages/spec/docs/contract.md)
150
+ - The Kotlin Multiplatform twin that consumes the generated models:
151
+ [native/README.md](https://github.com/DailybotHQ/texuli/blob/main/native/README.md)
152
+ - Architecture: [ARCHITECTURE.md](https://github.com/DailybotHQ/texuli/blob/main/docs/ARCHITECTURE.md)
153
+
154
+ ## Related packages
155
+
156
+ - [`@texuli/catalog`](https://www.npmjs.com/package/@texuli/catalog): the agent catalog and the renderer with no HTML sinks.
157
+ - [`@texuli/player`](https://www.npmjs.com/package/@texuli/player): the Svelte paint runtime for validated blueprints.
158
+ - [`texuli`](https://www.npmjs.com/package/texuli): the styled Svelte 5 components blueprints are built from.
159
+
160
+ ## Contributing
161
+
162
+ Source, issues and contribution guidelines live at
163
+ [github.com/DailybotHQ/texuli](https://github.com/DailybotHQ/texuli). Report
164
+ bugs at [github.com/DailybotHQ/texuli/issues](https://github.com/DailybotHQ/texuli/issues).
165
+
166
+ ## License
167
+
168
+ MIT © Dailybot, Inc.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@texuli/spec",
3
- "version": "0.1.0-next.1",
3
+ "version": "0.2.0",
4
4
  "description": "The schema-first blueprint contract: JSON schemas, the catalog vocabulary, deterministic TypeScript and Kotlin projections, and the conformance harness.",
5
5
  "keywords": [
6
6
  "svelte",