bitwrench 2.0.24 → 2.0.30

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 (88) hide show
  1. package/README.md +17 -9
  2. package/dist/bitwrench-bccl.cjs.js +1 -1
  3. package/dist/bitwrench-bccl.cjs.min.js +1 -1
  4. package/dist/bitwrench-bccl.cjs.min.js.gz +0 -0
  5. package/dist/bitwrench-bccl.esm.js +1 -1
  6. package/dist/bitwrench-bccl.esm.min.js +1 -1
  7. package/dist/bitwrench-bccl.esm.min.js.gz +0 -0
  8. package/dist/bitwrench-bccl.umd.js +1 -1
  9. package/dist/bitwrench-bccl.umd.min.js +1 -1
  10. package/dist/bitwrench-bccl.umd.min.js.gz +0 -0
  11. package/dist/bitwrench-code-edit.cjs.js +1 -1
  12. package/dist/bitwrench-code-edit.cjs.min.js +1 -1
  13. package/dist/bitwrench-code-edit.es5.js +1 -1
  14. package/dist/bitwrench-code-edit.es5.min.js +1 -1
  15. package/dist/bitwrench-code-edit.esm.js +1 -1
  16. package/dist/bitwrench-code-edit.esm.min.js +1 -1
  17. package/dist/bitwrench-code-edit.umd.js +1 -1
  18. package/dist/bitwrench-code-edit.umd.min.js +1 -1
  19. package/dist/bitwrench-code-edit.umd.min.js.gz +0 -0
  20. package/dist/bitwrench-debug.js +1 -1
  21. package/dist/bitwrench-debug.min.js +1 -1
  22. package/dist/bitwrench-lean.cjs.js +661 -174
  23. package/dist/bitwrench-lean.cjs.min.js +7 -7
  24. package/dist/bitwrench-lean.cjs.min.js.gz +0 -0
  25. package/dist/bitwrench-lean.es5.js +690 -178
  26. package/dist/bitwrench-lean.es5.min.js +5 -5
  27. package/dist/bitwrench-lean.es5.min.js.gz +0 -0
  28. package/dist/bitwrench-lean.esm.js +661 -174
  29. package/dist/bitwrench-lean.esm.min.js +6 -6
  30. package/dist/bitwrench-lean.esm.min.js.gz +0 -0
  31. package/dist/bitwrench-lean.umd.js +661 -174
  32. package/dist/bitwrench-lean.umd.min.js +7 -7
  33. package/dist/bitwrench-lean.umd.min.js.gz +0 -0
  34. package/dist/bitwrench-util-css.cjs.js +1 -1
  35. package/dist/bitwrench-util-css.cjs.min.js +1 -1
  36. package/dist/bitwrench-util-css.es5.js +1 -1
  37. package/dist/bitwrench-util-css.es5.min.js +1 -1
  38. package/dist/bitwrench-util-css.esm.js +1 -1
  39. package/dist/bitwrench-util-css.esm.min.js +1 -1
  40. package/dist/bitwrench-util-css.umd.js +1 -1
  41. package/dist/bitwrench-util-css.umd.min.js +1 -1
  42. package/dist/bitwrench-util-css.umd.min.js.gz +0 -0
  43. package/dist/bitwrench.cjs.js +659 -172
  44. package/dist/bitwrench.cjs.min.js +6 -6
  45. package/dist/bitwrench.cjs.min.js.gz +0 -0
  46. package/dist/bitwrench.css +6 -6
  47. package/dist/bitwrench.d.ts +666 -0
  48. package/dist/bitwrench.es5.js +687 -175
  49. package/dist/bitwrench.es5.min.js +6 -6
  50. package/dist/bitwrench.es5.min.js.gz +0 -0
  51. package/dist/bitwrench.esm.js +659 -172
  52. package/dist/bitwrench.esm.min.js +5 -5
  53. package/dist/bitwrench.esm.min.js.gz +0 -0
  54. package/dist/bitwrench.min.css +1 -1
  55. package/dist/bitwrench.umd.js +659 -172
  56. package/dist/bitwrench.umd.min.js +6 -6
  57. package/dist/bitwrench.umd.min.js.gz +0 -0
  58. package/dist/builds.json +96 -96
  59. package/dist/bwserve.cjs.js +140 -7
  60. package/dist/bwserve.esm.js +141 -8
  61. package/dist/sri.json +46 -46
  62. package/docs/README.md +5 -3
  63. package/docs/bitwrench-for-wasm.md +851 -0
  64. package/docs/bitwrench-mcp.md +1 -1
  65. package/docs/bitwrench-taco-schema-discussion.md +694 -0
  66. package/docs/bitwrench_api.md +134 -24
  67. package/docs/bitwrench_typescript_usage.md +441 -0
  68. package/docs/component-cheatsheet.md +1 -1
  69. package/docs/framework-translation-table.md +1 -1
  70. package/docs/llm-bitwrench-guide.md +34 -6
  71. package/docs/routing.md +1 -1
  72. package/docs/state-management.md +27 -3
  73. package/docs/thinking-in-bitwrench.md +6 -5
  74. package/docs/tutorial-bwserve.md +1 -1
  75. package/docs/tutorial-website.md +1 -1
  76. package/package.json +16 -10
  77. package/readme.html +29 -14
  78. package/src/bitwrench-styles.js +17 -17
  79. package/src/bitwrench.d.ts +666 -0
  80. package/src/bitwrench.js +638 -150
  81. package/src/bwserve/bwclient.js +3 -3
  82. package/src/bwserve/client.js +26 -0
  83. package/src/bwserve/index.js +110 -3
  84. package/src/cli/attach.js +7 -5
  85. package/src/cli/serve.js +53 -9
  86. package/src/mcp/live.js +3 -1
  87. package/src/mcp/server.js +7 -7
  88. package/src/version.js +3 -3
@@ -150,7 +150,7 @@ These return documentation text. They teach the LLM how to use bitwrench.
150
150
  |------|-------------|--------------|
151
151
  | `bitwrench_start_here` | 30-line orientation: TACO, workflow, key rules | Always first |
152
152
  | `bitwrench_guide` | Full developer guide (629 lines). Optional `section` filter. | Before building UI |
153
- | `bitwrench_components` | Props reference for all 50+ make*() components. Optional `component` filter. | When configuring components |
153
+ | `bitwrench_components` | Props reference for all make*() components. Optional `component` filter. | When configuring components |
154
154
  | `bitwrench_server_guide` | bwserve tutorial for server-driven UI | Only for live/streaming UI |
155
155
  | `bitwrench_themes` | Theme presets, palettes, color utilities | When choosing/customizing themes |
156
156
 
@@ -0,0 +1,694 @@
1
+ # UI as Schema: Validating TACO Objects
2
+
3
+ **Status**: Discussion document -- not on the implementation roadmap
4
+ **Date**: 2026-03-28
5
+
6
+ This document explores what becomes possible when your UI layer is plain
7
+ data. It is not a specification or a product plan. It lives here to invite
8
+ discussion from developers who see the potential.
9
+
10
+ If you have thoughts, open an issue or reach out.
11
+
12
+ ---
13
+
14
+ ## The Observation
15
+
16
+ A bitwrench UI is a tree of `{t, a, c, o}` objects. That tree is JSON.
17
+ Not "JSON-like" or "serializable to JSON" -- it IS JSON (modulo function
18
+ references in `a.onclick` and `o.handle`, which are the only non-serializable
19
+ parts and can be handled with a registry pattern).
20
+
21
+ This means something that no compiled UI framework can claim: **the UI
22
+ definition is data that can be validated, transformed, and enforced using
23
+ the same tools we already use for APIs, configs, and data interchange.**
24
+
25
+ A React component tree? Opaque compiled code. A Vue template? A string
26
+ that gets parsed into a virtual DOM you never see. A Svelte component?
27
+ Gone after compilation. You cannot point a schema validator at any of
28
+ these and ask "is this UI well-formed?" -- the UI description doesn't
29
+ exist as inspectable data at runtime.
30
+
31
+ TACO objects do.
32
+
33
+ ---
34
+
35
+ ## Historical Precedent: We've Done This Before
36
+
37
+ If you're old enough to remember XML-based UI frameworks, this idea
38
+ will feel familiar:
39
+
40
+ **XAML (WPF/.NET)** -- Microsoft's UI markup was XML. You could validate
41
+ it with XSD schemas, transform it with XSLT, generate it from code, and
42
+ enforce organizational standards with schema-based tooling. The Visual
43
+ Studio designer was possible because the UI was self-describing data.
44
+
45
+ **Android XML Layouts** -- `res/layout/*.xml` files are validated against
46
+ the Android SDK's schema. The lint tool (`android lint`) catches invalid
47
+ attributes, accessibility violations, and deprecated APIs -- all because
48
+ the UI is structured data, not code.
49
+
50
+ **XUL (Mozilla)** -- Firefox's entire UI was defined in XUL/XML. Extensions
51
+ could inspect and modify the UI tree as data. Schema validation told you
52
+ if your XUL was well-formed before the browser tried to render it.
53
+
54
+ **Qt QML** -- A JSON-like declarative UI language with a type system and
55
+ static analysis tools. Qt Creator's design mode works because QML is
56
+ inspectable structured data.
57
+
58
+ These frameworks understood something the modern JS ecosystem forgot:
59
+ **when UI is data, tooling comes for free.** The shift to JSX and
60
+ compilation-first frameworks traded that capability for developer
61
+ ergonomics. TACO gets it back without the XML tax.
62
+
63
+ ---
64
+
65
+ ## What JSON Schema / Pydantic Developers Will Recognize
66
+
67
+ If you use JSON Schema for API validation or Pydantic for Python data
68
+ models, the TACO schema concept maps directly:
69
+
70
+ **JSON Schema parallel**: A TACO schema defines the valid shape of a UI
71
+ subtree the same way a JSON Schema defines the valid shape of an API
72
+ response. The difference is that the "response" is a UI component, and
73
+ the "properties" are HTML tags, attributes, and lifecycle hooks.
74
+
75
+ ```javascript
76
+ // This is conceptually identical to a JSON Schema definition:
77
+ var cardSchema = {
78
+ t: { type: 'string', const: 'div' },
79
+ a: {
80
+ properties: {
81
+ class: { type: 'string', pattern: /bw_card/ }
82
+ }
83
+ },
84
+ c: {
85
+ type: 'array',
86
+ items: { oneOf: [titleSchema, bodySchema, footerSchema] }
87
+ }
88
+ };
89
+ ```
90
+
91
+ **Pydantic parallel**: Pydantic validates Python objects against a model
92
+ definition and gives you clear error messages with field paths. A TACO
93
+ validator would do the same thing:
94
+
95
+ ```javascript
96
+ // Pydantic-style: define the model, validate input, get path-specific errors
97
+ var result = validate(taco, cardSchema);
98
+ // => { valid: false, errors: [{ path: '.a.class', message: 'missing bw_card' }] }
99
+ ```
100
+
101
+ **The key insight**: bitwrench could offer this natively because TACO
102
+ objects already have a consistent structure (every node has `t`, `a`,
103
+ `c`, `o`). JSON Schema and Pydantic work on arbitrary shapes. A TACO
104
+ schema knows the domain -- it knows that `t` is a tag name, `a` has
105
+ HTML attributes, `c` is content, and `o` has lifecycle hooks. Domain
106
+ knowledge makes the validator smaller, faster, and more helpful than
107
+ a generic tool.
108
+
109
+ And crucially, this tooling would ship as a separate add-on -- not part
110
+ of bitwrench core. The core library stays zero-dep and lean. The schema
111
+ tool is for teams that want governance, not a tax on everyone.
112
+
113
+ ---
114
+
115
+ ## Scenarios Where This Matters
116
+
117
+ ### Scenario 1: The Wrong Property Name
118
+
119
+ You write `bw.makeAccordion({ items: [{ label: 'FAQ', body: 'Answer' }] })`.
120
+ Nothing renders. No error. You stare at it for 10 minutes before realizing
121
+ the properties are `title` and `content`, not `label` and `body`.
122
+
123
+ With schema validation:
124
+ ```
125
+ [bw-schema] makeAccordion: items[0] has unknown property "label".
126
+ Did you mean "title"?
127
+ [bw-schema] makeAccordion: items[0] has unknown property "body".
128
+ Did you mean "content"?
129
+ ```
130
+
131
+ This is the simplest, most immediately useful scenario. Every bitwrench
132
+ user has hit some version of this.
133
+
134
+ ### Scenario 2: Server-Driven UI (bwserve)
135
+
136
+ A Python backend sends TACO over SSE to the browser. The browser renders
137
+ it with `bw.DOM()`. What happens when the server sends:
138
+
139
+ ```json
140
+ { "t": "script", "c": "alert('pwned')" }
141
+ ```
142
+
143
+ Or a malformed payload from a bug? Today: it renders. With validation:
144
+
145
+ ```javascript
146
+ bwserve.onMessage = function(msg) {
147
+ var result = validate(msg.taco, {
148
+ denyTags: ['script', 'iframe', 'object'],
149
+ denyStringHandlers: true,
150
+ denyRawHtml: true
151
+ });
152
+ if (!result.valid) return; // reject
153
+ bw.DOM(msg.target, msg.taco);
154
+ };
155
+ ```
156
+
157
+ This is a real security boundary. When UI is data arriving over the wire,
158
+ validation isn't optional -- it's the same as validating API input.
159
+
160
+ ### Scenario 3: Embedded Devices (ESP32, RPi)
161
+
162
+ A microcontroller sends JSON TACO updates to a browser dashboard. The
163
+ firmware is written in C. Bugs in the JSON serialization are catchable.
164
+ Schema validation on the browser side catches malformed payloads before
165
+ they break the UI -- and reports exactly what's wrong, which helps debug
166
+ the firmware.
167
+
168
+ ### Scenario 4: LLM-Generated UI
169
+
170
+ You ask an LLM to generate a TACO dashboard. It produces:
171
+
172
+ ```json
173
+ {
174
+ "t": "div",
175
+ "attributes": { "className": "dashboard" },
176
+ "children": [...]
177
+ }
178
+ ```
179
+
180
+ Wrong keys everywhere -- `attributes` instead of `a`, `className` instead
181
+ of `class`, `children` instead of `c`. The LLM hallucinated a React-shaped
182
+ object. Schema validation catches this immediately and the error messages
183
+ are specific enough to include in a retry prompt.
184
+
185
+ ### Scenario 5: Enterprise UI Governance
186
+
187
+ A large team building internal tools with bitwrench. The tech lead wants:
188
+ - No inline styles (use design tokens)
189
+ - No string event handlers (security policy)
190
+ - All images must have alt text (accessibility)
191
+ - Only approved BCCL components in production code
192
+
193
+ Today this requires code review discipline. With a schema policy engine,
194
+ it's automated -- run it in CI, same as a linter.
195
+
196
+ ```javascript
197
+ var policy = {
198
+ rules: [
199
+ { rule: 'no-inline-styles', severity: 'warn' },
200
+ { rule: 'no-string-handlers', severity: 'error' },
201
+ { rule: 'require-alt-text', severity: 'error' },
202
+ { rule: 'allowed-components', value: ['card', 'button', 'table', 'nav', 'form'] }
203
+ ]
204
+ };
205
+ ```
206
+
207
+ ### Scenario 6: Cross-Language Portability
208
+
209
+ Because TACO schema definitions would be plain JSON (no JS-specific
210
+ constructs), the same schema works in:
211
+ - **JavaScript/Node** -- validate in browser or server
212
+ - **Python** -- validate bwserve payloads before sending
213
+ - **Go/Rust** -- validate in microservices that generate UI
214
+ - **C** -- embedded devices that serialize TACO
215
+
216
+ This is the JSON Schema advantage: the schema itself is data, portable
217
+ across any language that can parse JSON.
218
+
219
+ ---
220
+
221
+ ## How It Might Work
222
+
223
+ ### The Simplest Useful Thing
224
+
225
+ A single function that validates the `{t, a, c, o}` shape:
226
+
227
+ ```javascript
228
+ function validateTaco(obj) {
229
+ var errors = [];
230
+ if (!obj || typeof obj !== 'object') {
231
+ return { valid: false, errors: [{ message: 'not an object' }] };
232
+ }
233
+ if (typeof obj.t !== 'string') {
234
+ errors.push({ path: '.t', message: 'tag must be a string' });
235
+ }
236
+ if (obj.a !== undefined && typeof obj.a !== 'object') {
237
+ errors.push({ path: '.a', message: 'attributes must be an object' });
238
+ }
239
+ if (obj.o !== undefined) {
240
+ var knownKeys = ['state', 'mounted', 'unmount', 'render', 'handle', 'slots', 'type'];
241
+ Object.keys(obj.o).forEach(function(k) {
242
+ if (knownKeys.indexOf(k) === -1) {
243
+ errors.push({ path: '.o.' + k, message: 'unknown option "' + k + '"' });
244
+ }
245
+ });
246
+ }
247
+ return { valid: errors.length === 0, errors: errors };
248
+ }
249
+ ```
250
+
251
+ That's maybe 30 lines and it already catches the most common mistakes.
252
+ No build step, no dependencies, works in any JS environment.
253
+
254
+ ### Recursive Tree Validation
255
+
256
+ Walk the content tree and validate every node:
257
+
258
+ ```javascript
259
+ function validateTree(taco, path) {
260
+ path = path || '';
261
+ var result = validateTaco(taco);
262
+ // Recurse into content
263
+ if (Array.isArray(taco.c)) {
264
+ taco.c.forEach(function(child, i) {
265
+ if (child && typeof child === 'object' && child.t) {
266
+ var childResult = validateTree(child, path + '.c[' + i + ']');
267
+ result.errors = result.errors.concat(childResult.errors);
268
+ }
269
+ });
270
+ } else if (taco.c && typeof taco.c === 'object' && taco.c.t) {
271
+ var childResult = validateTree(taco.c, path + '.c');
272
+ result.errors = result.errors.concat(childResult.errors);
273
+ }
274
+ result.valid = result.errors.length === 0;
275
+ return result;
276
+ }
277
+ ```
278
+
279
+ ### BCCL Config Validation with Fuzzy Matching
280
+
281
+ ```javascript
282
+ var knownConfigs = {
283
+ makeCard: ['title', 'content', 'footer', 'image', 'variant', 'shadow',
284
+ 'clickable', 'style', 'class'],
285
+ makeAccordion: ['items', 'multiple', 'variant', 'style', 'class'],
286
+ makeNav: ['items', 'variant', 'vertical', 'style', 'class']
287
+ // ... all 45+ components
288
+ };
289
+
290
+ function validateConfig(factoryName, config) {
291
+ var known = knownConfigs[factoryName];
292
+ if (!known) return { valid: true, errors: [] };
293
+ var errors = [];
294
+ Object.keys(config).forEach(function(key) {
295
+ if (known.indexOf(key) === -1) {
296
+ var suggestion = findClosest(key, known); // Levenshtein
297
+ errors.push({
298
+ path: '.' + key,
299
+ message: factoryName + ': unknown property "' + key + '"'
300
+ + (suggestion ? '. Did you mean "' + suggestion + '"?' : '')
301
+ });
302
+ }
303
+ });
304
+ return { valid: errors.length === 0, errors: errors };
305
+ }
306
+ ```
307
+
308
+ ### Policy Rules as Functions
309
+
310
+ ```javascript
311
+ var builtinRules = {
312
+ 'no-inline-styles': function(taco, path) {
313
+ if (taco.a && taco.a.style && typeof taco.a.style === 'object') {
314
+ return { path: path + '.a.style', message: 'inline styles not allowed by policy' };
315
+ }
316
+ },
317
+ 'no-string-handlers': function(taco, path) {
318
+ if (!taco.a) return;
319
+ var errors = [];
320
+ Object.keys(taco.a).forEach(function(k) {
321
+ if (k.indexOf('on') === 0 && typeof taco.a[k] === 'string') {
322
+ errors.push({
323
+ path: path + '.a.' + k,
324
+ message: k + ' must be a function, not a string'
325
+ });
326
+ }
327
+ });
328
+ return errors;
329
+ },
330
+ 'require-alt-text': function(taco, path) {
331
+ if (taco.t === 'img' && (!taco.a || !taco.a.alt)) {
332
+ return { path: path + '.a.alt', message: '<img> requires alt attribute' };
333
+ }
334
+ }
335
+ };
336
+ ```
337
+
338
+ None of this is rocket science. The power comes from the fact that TACO
339
+ gives you a uniform data structure to walk. Every node has the same shape.
340
+ The validator doesn't need to understand React hooks, Vue reactivity, or
341
+ Svelte compilation -- it just walks a tree of `{t, a, c, o}` objects.
342
+
343
+ ---
344
+
345
+ ## Proposed v0 Specification Skeleton (Additive)
346
+
347
+ This section is intentionally concrete so implementers can converge on one
348
+ validator behavior. It does not replace the discussion above. It turns the
349
+ discussion into a proposed minimum contract that can be implemented in a
350
+ standalone package (`bw-schema`) without changing bitwrench core.
351
+
352
+ ### 1) Scope
353
+
354
+ v0 covers:
355
+
356
+ - Structural validation of TACO trees (`{t, a, c, o}`)
357
+ - Optional policy validation (security, accessibility, governance)
358
+ - Validation for both in-process objects and wire payloads (bwserve/LLM)
359
+ - Machine-readable errors suitable for IDEs, CI, and LLM retry loops
360
+
361
+ v0 does not cover:
362
+
363
+ - Full semantic DOM validation against every HTML spec edge case
364
+ - TypeScript replacement
365
+ - Compiler transforms or code generation
366
+
367
+ ### 2) Canonical Node Shape (Normative)
368
+
369
+ A node is valid TACO if:
370
+
371
+ - `t` exists and is a non-empty string (tag name)
372
+ - `a` is optional; when present, it is an object
373
+ - `c` is optional; when present, it is one of:
374
+ - string
375
+ - number
376
+ - `null`/`undefined`/`false` (treated as skipped content)
377
+ - `BwRaw` sentinel (`{ __bw_raw: true, v: string }`)
378
+ - nested TACO node
379
+ - array of any allowed content values above
380
+ - `o` is optional; when present, it is an object with known keys only:
381
+ - `state`, `mounted`, `unmount`, `render`, `handle`, `slots`, `type`
382
+
383
+ Unknown top-level keys are validator findings (severity depends on mode).
384
+
385
+ ### 3) Validation Modes (Normative)
386
+
387
+ `validateTree(input, options)` supports:
388
+
389
+ - `mode: 'permissive'` (default for developer ergonomics)
390
+ - checks required shape (`t`, object-ness)
391
+ - unknown keys are `warn`
392
+ - `mode: 'strict'`
393
+ - unknown keys are `error`
394
+ - invalid content unions are `error`
395
+ - malformed `o` options are `error`
396
+ - `mode: 'wire'` (for bwserve/LLM/embedded payload boundaries)
397
+ - strict shape checks
398
+ - policy defaults enabled:
399
+ - deny dangerous tags (`script`, `iframe`, `object`, `embed`)
400
+ - deny string event handlers
401
+ - configurable `bw.raw` allowance (default deny)
402
+
403
+ ### 4) Error Model (Normative)
404
+
405
+ Each finding follows a stable shape:
406
+
407
+ ```javascript
408
+ {
409
+ code: 'BW_SCHEMA_UNKNOWN_KEY',
410
+ severity: 'error', // 'error' | 'warn' | 'info'
411
+ path: '.c[2].a.className', // JSONPath-like pointer
412
+ message: 'Unknown key "className"; did you mean "class"?',
413
+ hint: 'Use TACO key "a.class" for CSS classes.',
414
+ suggestion: 'class',
415
+ meta: { received: 'className', allowed: ['id', 'class', 'style', '...'] }
416
+ }
417
+ ```
418
+
419
+ Result envelope:
420
+
421
+ ```javascript
422
+ {
423
+ valid: false, // true if no "error" findings
424
+ summary: { errors: 2, warns: 1, infos: 0 },
425
+ findings: [/* ordered by path, then severity */],
426
+ normalized: null // optional output if auto-fix is enabled
427
+ }
428
+ ```
429
+
430
+ Codes should be stable across versions for tooling interoperability.
431
+
432
+ ### 5) Suggested v0 Error Code Set
433
+
434
+ - `BW_SCHEMA_NOT_OBJECT`
435
+ - `BW_SCHEMA_MISSING_TAG`
436
+ - `BW_SCHEMA_INVALID_TAG_TYPE`
437
+ - `BW_SCHEMA_UNKNOWN_TOP_LEVEL_KEY`
438
+ - `BW_SCHEMA_INVALID_ATTRS_TYPE`
439
+ - `BW_SCHEMA_INVALID_OPTIONS_TYPE`
440
+ - `BW_SCHEMA_UNKNOWN_OPTION_KEY`
441
+ - `BW_SCHEMA_INVALID_CONTENT_TYPE`
442
+ - `BW_SCHEMA_UNKNOWN_ATTR_KEY` (optional, configurable)
443
+ - `BW_POLICY_DENY_TAG`
444
+ - `BW_POLICY_DENY_STRING_HANDLER`
445
+ - `BW_POLICY_DENY_RAW_HTML`
446
+ - `BW_POLICY_REQUIRE_ALT_TEXT`
447
+
448
+ ### 6) Policy Engine Contract (Normative)
449
+
450
+ Policy rules are pure functions:
451
+
452
+ ```javascript
453
+ function rule(node, ctx) {
454
+ // ctx: { path, mode, parent, options, helpers }
455
+ // return: null | finding | finding[]
456
+ }
457
+ ```
458
+
459
+ Evaluation order:
460
+
461
+ 1. Structural validation
462
+ 2. Built-in policies (if enabled)
463
+ 3. User policies
464
+
465
+ Policy merge behavior:
466
+
467
+ - Global defaults
468
+ - Mode defaults
469
+ - User overrides (last write wins)
470
+
471
+ ### 7) Integration Points (Normative Recommendations)
472
+
473
+ #### A) bwserve ingress (high priority)
474
+
475
+ Validate message payloads before `bw.DOM()`/`bw.apply()`:
476
+
477
+ ```javascript
478
+ var result = validateTree(msg.node, { mode: 'wire', policy: wirePolicy });
479
+ if (!result.valid) {
480
+ // reject payload, log findings, optionally patch an error placeholder
481
+ return;
482
+ }
483
+ ```
484
+
485
+ #### B) LLM output boundary
486
+
487
+ Validate parsed model output before render:
488
+
489
+ ```javascript
490
+ var r = validateTree(parsed, { mode: 'wire', autoSuggest: true });
491
+ if (!r.valid) {
492
+ // feed r.findings back into retry prompt
493
+ }
494
+ ```
495
+
496
+ #### C) CLI/CI
497
+
498
+ `bwcli validate` should:
499
+
500
+ - return non-zero on `error` findings
501
+ - optionally fail on `warn` with `--strict-warn`
502
+ - emit JSON (`--json`) and human text by default
503
+
504
+ ### 8) Function and Serialization Profiles
505
+
506
+ Because function references are the main non-JSON part of TACO, v0 should
507
+ define explicit profiles:
508
+
509
+ - `profile: 'runtime'`
510
+ - allows function values in `a.on*`, `o.mounted`, `o.render`, etc.
511
+ - `profile: 'wire-safe'`
512
+ - disallows function values
513
+ - allows only data payload representation
514
+ - `profile: 'wire-registry'`
515
+ - allows function references only as registry tokens/IDs
516
+
517
+ This avoids ambiguity between "authoring objects" and "transport objects."
518
+
519
+ ### 9) Normalization / Auto-Fix (Optional v0.1)
520
+
521
+ Auto-fix is opt-in and conservative:
522
+
523
+ - key aliases only (safe rewrites), e.g.:
524
+ - `attributes` -> `a`
525
+ - `children` -> `c`
526
+ - `className` -> `class`
527
+ - never auto-enable dangerous features (`bw.raw`, string handlers)
528
+ - every rewrite emits an `info` finding with before/after path
529
+
530
+ Recommended API:
531
+
532
+ ```javascript
533
+ validateTree(input, { normalize: true, aliasMap: defaultAliasMap });
534
+ ```
535
+
536
+ ### 10) Performance Expectations
537
+
538
+ Target complexity:
539
+
540
+ - Structural walk: O(n) nodes
541
+ - Policy checks: O(n * p) where `p` is active rule count
542
+
543
+ Operational guidance:
544
+
545
+ - Validate at boundaries (wire/LLM ingress), not every frame
546
+ - Cache by stable hash for repeated payloads
547
+ - Offer depth/node-count limits to protect against pathological payloads
548
+
549
+ ### 11) Versioning and Compatibility
550
+
551
+ Schema contract should include:
552
+
553
+ ```javascript
554
+ {
555
+ schemaVersion: '1.0.0',
556
+ tacoVersion: '2.x',
557
+ profile: 'runtime'
558
+ }
559
+ ```
560
+
561
+ Compatibility policy:
562
+
563
+ - Minor version: additive checks/codes only
564
+ - Major version: breaking code/path semantics
565
+ - Error codes remain stable within major versions
566
+
567
+ ### 12) JSON Schema Interop Track
568
+
569
+ Two-layer model is recommended:
570
+
571
+ - Native validator contract (optimized for TACO semantics)
572
+ - Optional JSON Schema export/import for tooling interoperability
573
+
574
+ Practical approach:
575
+
576
+ 1. Maintain canonical TACO spec in native format
577
+ 2. Generate JSON Schema artifacts from canonical spec
578
+ 3. Allow editor/tooling consumers to use `$schema` references
579
+
580
+ ### 13) Suggested MVP Sequence
581
+
582
+ Phase 1 (smallest useful):
583
+
584
+ - `validateTaco` + `validateTree`
585
+ - strict/permissive modes
586
+ - stable findings envelope + core error codes
587
+
588
+ Phase 2 (boundary safety):
589
+
590
+ - `wire` mode
591
+ - deny-tag/string-handler/raw-html policies
592
+ - bwserve integration examples
593
+
594
+ Phase 3 (tooling):
595
+
596
+ - `bwcli validate`
597
+ - JSON output for CI
598
+ - LLM retry prompt formatter
599
+
600
+ Phase 4 (governance):
601
+
602
+ - policy packs
603
+ - optional normalization aliases
604
+ - JSON Schema export
605
+
606
+ ### 14) Open Design Defaults (Proposed)
607
+
608
+ If no options are provided:
609
+
610
+ - mode: `permissive`
611
+ - profile: `runtime`
612
+ - findings include suggestions when confidence is high
613
+ - validator never mutates input unless `normalize: true`
614
+
615
+ For boundary validation (recommended default):
616
+
617
+ - mode: `wire`
618
+ - profile: `wire-safe`
619
+ - deny dangerous tags + string handlers + raw HTML unless explicitly allowed
620
+
621
+ ---
622
+
623
+ ## What This Is NOT
624
+
625
+ - **Not part of bitwrench core.** The core library stays zero-dep and
626
+ lean. Schema tooling is a separate add-on for teams that want it.
627
+ - **Not a build step.** Validation runs at dev time or at data boundaries
628
+ (bwserve, LLM output). It does not require a compiler or bundler.
629
+ - **Not a type system.** TypeScript already provides static types for
630
+ bitwrench (see `dist/bitwrench.d.ts`). Schema validation is runtime
631
+ checking for data that arrives dynamically -- server payloads, LLM
632
+ output, config-driven UI.
633
+ - **Not on the roadmap.** This document describes what's possible. If
634
+ demand materializes, the architecture is ready. The TACO format
635
+ doesn't need to change to support any of this.
636
+
637
+ ---
638
+
639
+ ## Why This Matters Strategically
640
+
641
+ The JS framework landscape is dominated by compiled, opaque approaches.
642
+ Every major framework (React, Vue, Svelte, Solid) compiles away the UI
643
+ description before runtime. This makes certain categories of tooling
644
+ impossible:
645
+
646
+ | Capability | Compiled frameworks | TACO |
647
+ |------------|-------------------|------|
648
+ | Schema-validate a component tree | Impossible | Walk the JSON |
649
+ | Enforce UI policies in CI | Requires AST parsing | Validate the data |
650
+ | Validate server-sent UI before render | No standard format | `validate(payload)` |
651
+ | Cross-language UI generation | Each needs its own SDK | Emit JSON |
652
+ | LLM UI output validation | Framework-specific | `validate(parse(response))` |
653
+ | Accessibility audit at data level | Requires rendered DOM | Walk the tree |
654
+ | Generate docs from component specs | Custom per framework | Read the schema |
655
+ | Diff two UI versions | Render and compare | `JSON.diff(v1, v2)` |
656
+
657
+ This isn't an argument that TACO is better than React for building UIs.
658
+ It's an argument that data-as-UI opens a category of tooling that
659
+ code-as-UI structurally cannot access. For enterprise environments where
660
+ governance, security, and cross-platform generation matter, that's a
661
+ meaningful differentiator.
662
+
663
+ The XML UI world understood this. XAML, Android XML, and XUL all had
664
+ schema validation, design-time tooling, and cross-language generation
665
+ because the UI was structured data. The modern web lost that when it
666
+ moved to JSX. TACO brings it back in a lighter, JSON-native form.
667
+
668
+ ---
669
+
670
+ ## Discussion Questions
671
+
672
+ We'd welcome input on any of these:
673
+
674
+ 1. Which scenarios resonate most with your use case?
675
+
676
+ 2. Is JSON Schema interop important (standard `$schema` references,
677
+ editor autocomplete via schema files), or is a JS-native format
678
+ sufficient?
679
+
680
+ 3. For the bwserve/embedded security boundary -- what validation rules
681
+ would you need for server-sent TACO in your environment?
682
+
683
+ 4. Would a CLI tool (`bwcli validate myapp.js`) be useful for CI
684
+ integration, or is runtime-only validation enough?
685
+
686
+ 5. How strict should a default schema be? Should `validate()` with
687
+ no options be permissive (just check `t` exists) or strict (validate
688
+ everything we know about)?
689
+
690
+ 6. For cross-language use: which server-side languages would benefit
691
+ most from a portable TACO schema? Python? Go? Rust?
692
+
693
+ Open an issue at [github.com/deftio/bitwrench](https://github.com/deftio/bitwrench/issues)
694
+ to share your thoughts.