@hyperfixi/engine 3.3.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 (46) hide show
  1. package/CHANGELOG.md +921 -0
  2. package/LICENSE +20 -0
  3. package/README.md +272 -0
  4. package/dist/additions.d.ts +30 -0
  5. package/dist/ast.d.ts +277 -0
  6. package/dist/commands/animation.d.ts +34 -0
  7. package/dist/commands/control.d.ts +36 -0
  8. package/dist/commands/dom-more.d.ts +68 -0
  9. package/dist/commands/dom.d.ts +50 -0
  10. package/dist/commands/events.d.ts +25 -0
  11. package/dist/commands/js.d.ts +22 -0
  12. package/dist/commands/loops.d.ts +34 -0
  13. package/dist/commands/misc.d.ts +36 -0
  14. package/dist/commands/morph.d.ts +18 -0
  15. package/dist/commands/pick.d.ts +22 -0
  16. package/dist/commands/platform.d.ts +44 -0
  17. package/dist/commands/setters.d.ts +38 -0
  18. package/dist/common.js +3020 -0
  19. package/dist/common.min.js +17 -0
  20. package/dist/conversions.d.ts +6 -0
  21. package/dist/cookies.d.ts +10 -0
  22. package/dist/core.js +2190 -0
  23. package/dist/core.min.js +17 -0
  24. package/dist/engine.d.ts +79 -0
  25. package/dist/everything.d.ts +2 -0
  26. package/dist/expressions-extra.d.ts +2 -0
  27. package/dist/expressions.d.ts +51 -0
  28. package/dist/features.d.ts +47 -0
  29. package/dist/full.js +5673 -0
  30. package/dist/full.min.js +19 -0
  31. package/dist/hyperfixi-hs.dev.js +5676 -0
  32. package/dist/hyperfixi-hs.js +19 -0
  33. package/dist/index.d.ts +39 -0
  34. package/dist/index.js +5737 -0
  35. package/dist/live-templates.d.ts +3 -0
  36. package/dist/minimal.js +2580 -0
  37. package/dist/minimal.min.js +17 -0
  38. package/dist/on.d.ts +39 -0
  39. package/dist/parser.d.ts +97 -0
  40. package/dist/reactivity.d.ts +30 -0
  41. package/dist/runtime.d.ts +160 -0
  42. package/dist/statements.d.ts +24 -0
  43. package/dist/templates.d.ts +61 -0
  44. package/dist/tokenizer.d.ts +25 -0
  45. package/dist/util.d.ts +34 -0
  46. package/package.json +60 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,921 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [3.3.0] - 2026-10-02
11
+
12
+ The first publication of `@hyperfixi/engine`, the hyperscript engine meant to replace the one
13
+ in `@hyperfixi/core`, and the example gallery moved onto it.
14
+
15
+ ### Added
16
+
17
+ - **`@hyperfixi/engine` is published.** A hyperscript engine written against upstream
18
+ `_hyperscript`'s source, with upstream's own test suite as the acceptance oracle (1,401 of
19
+ 1,467 tests; the 66 known failures are upstream's internal API, sockets and workers). It
20
+ ships `dist/hyperfixi-hs.js`, a script-tag bundle of hyperscript and nothing else, 34.1 KB
21
+ gzipped, which 36 of the repository's example pages now load instead of `hyperfixi.js`. It
22
+ keeps two forms upstream lacks, `new X(...)` and `toggle <element>`; the other hyperfixi-only
23
+ forms are not in it. It is typed (`tsc --strict`, no `any`), built from modules, and exposes
24
+ upstream's public API shape plus one hook, `addSourceTransform`, which
25
+ `@lokascript/hyperscript-adapter` uses to run the 24 languages on it.
26
+
27
+ ### Changed
28
+
29
+ - **Examples and docs are written in upstream `_hyperscript`'s spelling** wherever upstream has
30
+ one: `put Y into X` for the `swap` strategies, `debounced at 300ms`, `matches`, `set X's @a`,
31
+ `increment #count's textContent` (core counted in a bare `#count`; upstream does not),
32
+ `on mutation of childList from #x`, `my offsetLeft` in place of `measure x`. The multilingual
33
+ reader still accepts the old forms; the renderer writes upstream's. Corpus rows follow.
34
+ - **`@lokascript/semantic` renders `repeat for x in xs index i`** (was `with index`) and
35
+ `tell X show` (was `tell X to show`), upstream's spellings.
36
+ - **The examples' bundle loader** takes a per-page default (`data-default="hs"`), and `?bundle=hs`
37
+ switches any page to the engine bundle.
38
+
39
+ ### Fixed
40
+
41
+ - **`@hyperfixi/core`**: `toggle *display of X` parsed and then threw.
42
+ - **Hybrid bundles (`hyperfixi-hx.js`)**: `increment` / `decrement` of a possessive wrote only
43
+ style properties; `increment #count's textContent` evaluated to the text and threw on
44
+ `querySelectorAll('0')`. They now write the property.
45
+ - **`@lokascript/semantic`**: a template-literal URL in a Korean handler was read as a custom
46
+ event name.
47
+
48
+ ## [3.2.0] - 2026-09-30
49
+
50
+ A correctness release for multilingual hyperscript. The semantic parser behind
51
+ `translate()`, `@lokascript/hyperscript-adapter`, MCP `translate_code` and hyperfixi's
52
+ non-English path now keeps whole programs that it used to shorten or drop: values,
53
+ conditions, loops and handler heads. Every value shape in a generated matrix of 4,205
54
+ (executed in 24 languages, directly and through the adapter, against upstream
55
+ \_hyperscript) now matches upstream, apart from two documented differences. Core
56
+ matches upstream \_hyperscript on more forms.
57
+
58
+ ### Added
59
+
60
+ - **Counted loops are written in each language's own words**: es `repetir 3 veces`,
61
+ fr `répéter 3 fois`, ja `3 回 を 繰り返し`, hi `3 बार को दोहराएं`, where translations
62
+ wrote English `times` in 18 languages and English `repeat` in the SOV six. English
63
+ `times`/`repeat` and each language's other count words (es `vez`, ru `раза`, …) still
64
+ read. 18 i18n dictionaries gain a `temporal.times` word.
65
+ - **Variable names that are words of the target language.** A variable spelled like a
66
+ structure word (es `si`, pl `w`, tr `al`) is written in parentheses, `(si)`, where the
67
+ plain translation would be misread, and read back as the variable. The language server
68
+ warns (`name-collision`, with a rename quick fix), MCP `validate_hyperscript` reports
69
+ `NAME_COLLISION`, and `translate_code` warns when a variable reads as a value word in
70
+ the target (tl `ako` is `me`). `@lokascript/semantic` exports `nameCollision`,
71
+ `findNameCollisions` and `findTranslationCollisions`.
72
+ - Event-handler modifiers (`once`, `debounced at`, `throttled at`, `from`) render in every
73
+ language and are scored by the fidelity signals.
74
+ - `of`-paths and pseudo-commands (`reset() the closest <form/>`) survive translation.
75
+ - `@lokascript/hyperscript-adapter`'s host gate also rejects a translation that reads a
76
+ reference as a handler's event (`on click on me toggle .active`, an empty click handler
77
+ plus a handler for an event named `me`), falling back to the author's text with a
78
+ warning; such a translation used to parse cleanly and do nothing.
79
+ - **Localized htmx attributes: all 23 non-English languages now cover
80
+ every attribute the _Hypermedia Systems_ book's code listings use** —
81
+ `hx-vals`, `hx-select`, `hx-swap-oob` and `hx-sync` join the Contact.app
82
+ twelve (`hx-値`, `hx-valores`, `hx-값`, `hx-werte`, `hx-選択`, `hx-selección`,
83
+ `hx-seçim`, `hx-auswahl`, `hx-sélection`, `hx-选择`, …). tr/de/fr/zh are new
84
+ in the table: the Contact.app seven they lacked (`hx-sil`, `hx-löschen`,
85
+ `hx-supprimer`, `hx-删除`, …) plus audited trigger/swap primaries following
86
+ loka-js (`hx-tetikleyici`, `hx-auslöser`, `hx-déclencheur`, `hx-替换`; the
87
+ profile words `hx-tetikle`, `hx-auslösen`, `hx-déclencher`, `hx-交换` still
88
+ resolve). de gains a lowercase `hx-ziel`: the profile's `hx-Ziel` could never
89
+ match a parsed attribute, since HTML lowercases attribute names. The other
90
+ 15 languages (ar, bn, he, hi, id, it, ms, pl, qu, ru, sw, th, tl, uk, vi)
91
+ are unreviewed drafts, every entry flagged `lowConfidence`; they also gain
92
+ the trigger heads their dictionaries left in English (ms and tl all six,
93
+ vi/he/ar some). id gains `hx-sasaran` for a target that was the English
94
+ identity; tl keeps `hx-target` on purpose. `hx-ext` is left in English on
95
+ purpose: htmx 4 removed it. The vocab table gains an `events` block for
96
+ trigger heads the i18n dictionaries do not name; ja, es, pt and ko author
97
+ the DOM `search` event (`検索`, `buscar`, `검색`), which the book's and
98
+ Contact.app's search box fires. htmx's own trigger words (`revealed`,
99
+ `every`) stay English, like the `delay:` / `from:` modifiers.
100
+ - Adapter-only vocab keys now resolve from the authored table alone, never
101
+ from a semantic profile: 22 profiles carry a `select` keyword that means
102
+ mark/highlight text (de `markieren`, tr `vurgula`), and it would otherwise
103
+ have shipped as `hx-select` in 22 unreviewed languages.
104
+
105
+ - **Localized htmx attributes: ja, es, pt and ko now cover every attribute the
106
+ _Hypermedia Systems_ Contact.app uses** — `hx-post`, `hx-delete`,
107
+ `hx-confirm`, `hx-push-url`, `hx-boost`, `hx-indicator` and `hx-include` join
108
+ the existing five (e.g. `hx-削除`, `hx-eliminar`, `hx-excluir`, `hx-삭제`).
109
+ `hx-indicator` / `hx-include` localize under `@hyperfixi/htmx-adapter` (stock
110
+ htmx implements them; the embedded layer does not).
111
+ - **Vocab aliases.** Several localized names may map to one attribute or event;
112
+ the first is the form to teach, later ones keep already-authored pages
113
+ working. Core's embedded orchestrator now reads whichever form an element
114
+ carries (it previously kept a single name per attribute).
115
+
116
+ ### Changed
117
+
118
+ - **Rendered vocabulary** (owner decisions): `null` is written `null` in ar, hi, id, qu,
119
+ sw, th and tr, where it shared the word for `empty`; hi writes `no` as `कोई नहीं`; qu
120
+ writes `and` as `hinallataq`; tl and tr write `includes` with `contains`' word (both
121
+ engines read the two as one operator).
122
+ - `@lokascript/semantic` exports its real `VERSION` (it was `0.1.0` since the first
123
+ release); browser bundles report `<version>-<bundle>`.
124
+ - MCP `translate_hyperscript` is described accurately: it uses the same semantic engine as
125
+ `translate_code`, without the verification.
126
+ - **Audited primaries for `hx-trigger` / `hx-swap`** in ja (`hx-トリガー`,
127
+ `hx-置換`), es (`hx-disparador`, `hx-intercambio`), pt (`hx-gatilho`,
128
+ `hx-troca`) and ko (`hx-교체`), following loka-js's terminology reviews. The
129
+ names that shipped before (`hx-引き金`, `hx-disparar`, …) still resolve.
130
+ - The vocab modules are regenerated against the current i18n dictionaries.
131
+ **No working name was removed** — 141 retired event names and three attribute
132
+ names are kept as aliases. One name changed meaning with its dictionary: sw
133
+ `panya_juu` is now `mouseup` (was `mouseover`).
134
+
135
+ ### Fixed
136
+
137
+ - **Translations that lost code** (semantic parse and render, in every language):
138
+ - `get` of a literal (`get "hello"`, `get 3`, `get true`) dropped the whole command; an
139
+ object literal after `get` was cut to `get {`.
140
+ - Loops keep their extent and body; `repeat until` stops; a loop keeps its index
141
+ variable, the tail after an `if` inside it, and the command after an empty loop its own
142
+ `end` closes; a count may be any value (a variable, `$n`, `it`, a possessive), where
143
+ some translations read `forever`, a silent infinite loop.
144
+ - Handler heads keep `or` events, filters and event parameters; a translated
145
+ `wait for <event>` waits instead of throwing; behaviors keep their handlers and init
146
+ blocks; an else-if chain shares one `end`.
147
+ - Values keep their comparison phrases (`is equal to`, `includes`, `is an Element`, …),
148
+ `and`/`or`/`not`, `mod`, possessive and `of` chains, object and array literals, every
149
+ conversion core supports (`as Int`, `as Fixed:2`, piped conversions), unary minus and
150
+ property paths; `true`/`false`/`null` keep their meaning.
151
+ - Commands keep `put … into <variable>`, `tell … to show`, fetch's `do not throw` and
152
+ response type, event-source/socket URLs, show/hide `with` strategies, `go`/`scroll`
153
+ positions, `${…}` URLs, core's `has`, and a class query's `in` scope.
154
+ - **`@hyperfixi/core` follows upstream \_hyperscript**:
155
+ - `X of Y` binds as property access, and the X of a null target is null.
156
+ - `increment` reads its amount and counter as upstream does, and writing an object's
157
+ property through `'s`/`of` works.
158
+ - A loop's count reads as upstream's `index < times` does: `"6.5"` loops 7 times and
159
+ `"6abc"` none, in the full runtime and in the hybrid bundles (`hyperfixi-hx.js`,
160
+ plugin bundles), which read `parseInt`.
161
+ - Blocks close at the end of input; `morph … to`; `render … with name: value`; `beep!`
162
+ as an expression; `transition`'s owners, several properties, `from` and `using`; three
163
+ handler forms from _Hypermedia Systems_; four upstream-valid forms that compiled and
164
+ then failed at run time; `.item in #list` keeps its scope; `on click once` fires on
165
+ the first click.
166
+ - htmx: camelCase event names survive an attribute name.
167
+ - MCP: the validators report what the parsers actually did.
168
+ - The AOT compiler (experimental): loops were compiled to `while (true)`; targets,
169
+ property access, scoped queries, `empty` and variable scope now compile to what they
170
+ mean.
171
+ - `@lokascript/hyperscript-adapter` and `@hyperscript-tools/multilingual` READMEs: the
172
+ Japanese quickstart example was a dead button, and the multi-language example loaded
173
+ only the Spanish bundle; the examples are now native and run in a test. Bundle sizes are
174
+ measured.
175
+ - Bare CDN URLs now serve a browser bundle: `unpkg.com/@lokascript/hyperscript-adapter@3` (and
176
+ jsDelivr) served `dist/index.cjs`, which throws in a `<script>` tag. The adapter,
177
+ `@hyperscript-tools/multilingual`, `@lokascript/semantic`, `@hyperfixi/core` and
178
+ `@lokascript/htmx-adapter` declare `unpkg`/`jsdelivr` entries.
179
+ - `hyperfixi-multilingual.js`'s error names the semantic bundle that exists (the full
180
+ `browser.global.js`, the only one that defines `LokaScriptSemantic`).
181
+ - READMEs: `@lokascript/i18n` no longer claims to translate (and its `/lsp` export and CLI,
182
+ which do not exist, are gone); `@lokascript/semantic`, `@hyperfixi/vite-plugin` and
183
+ `@hyperfixi/core` have correct package names, API calls, language lists (24) and measured
184
+ bundle sizes.
185
+ - Dependencies: the js-yaml and smol-toml advisories; Vite 8, vitest 5 and happy-dom 20.14.
186
+ - **Vietnamese `hx-get` / `hx-target` / `hx-swap` / `hx-trigger` / `sse-swap`
187
+ never worked**: the names were emitted with spaces (`hx-lấy giá trị`), which
188
+ HTML reads as three attributes. They are now hyphen-joined
189
+ (`hx-lấy-giá-trị`), like vi's existing `hx-trực-tiếp`.
190
+ - 29 multi-word event names (ar, vi) were removed from the vocab modules: an
191
+ event is a single token of an `hx-trigger` value, so they could never match.
192
+
193
+ ## [3.1.1] - 2026-09-04
194
+
195
+ ### Fixed
196
+
197
+ - **`@hyperfixi/mcp-server` no longer installs two copies of the contract
198
+ packages.** 3.1.0 pinned `@lokascript/domains ^2.11.1`, whose framework /
199
+ semantic / intent were hard 2.x dependencies — a clean install got 3.1.0 at
200
+ the top level and 2.11.1 nested under domains, and every `DomainRegistry` /
201
+ schema singleton forked across that boundary. mcp-server, framework and
202
+ server-bridge now range on `@lokascript/domains ^3.0.0`, which peers on
203
+ framework 3.x instead.
204
+
205
+ ### Added
206
+
207
+ - **`scripts/check-domains-peer-major.cjs`** — the cross-repo guard for that
208
+ class: the domains version the lockfile pins must PEER (not depend) on
209
+ framework / semantic / intent at a range the version this repo publishes
210
+ satisfies. Runs in `lint-typecheck`, first thing in `publish.yml` after the
211
+ version bump, and from the pre-commit hook. `examples/release-smoke/run.mjs`
212
+ additionally asserts one installed copy of each contract package, and
213
+ Dependabot now gives `@lokascript/domains` its own PR group so a domains
214
+ release is visible on its own instead of riding the weekly tooling PR.
215
+
216
+ ## [3.1.0] - 2026-09-04
217
+
218
+ ### Added
219
+
220
+ - **`hyperscript.use(frontEnd)`** — register the multilingual front-end
221
+ `compile()` consults for a non-English program (and `toLSE`/`fromLSE` for
222
+ a semantic node and a renderer). The contract is `FrontEnd` in
223
+ `@hyperfixi/core` (`parseToAST`, optional `parse`/`render`);
224
+ `@lokascript/semantic` satisfies it through
225
+ `createBridgeFrontEnd(new SemanticGrammarBridge())` from
226
+ `@hyperfixi/core/multilingual`. The full browser bundle registers it at
227
+ boot. The library entry registers nothing and, through 3.x, builds the same
228
+ bridge lazily on the first non-English compile — so nothing changes for a
229
+ consumer with `@lokascript/semantic` installed. **4.0 will remove that
230
+ default:** a non-English `compile()` with no front-end registered will
231
+ return the same result the core-parser-only path returns today, and
232
+ `@lokascript/semantic` becomes an optional peer. Engine-migration plan
233
+ Arc 1, steps 2 and 3.
234
+
235
+ ### Fixed
236
+
237
+ - **Language server: valid non-English code no longer gets a `parse-error`.**
238
+ In `lokascript`/`hyperscript-i18n` mode the server ran core's English
239
+ parser on every region regardless of what the semantic front-end said, so
240
+ `al hacer clic alternar .activo` (accepted at 0.89 confidence) was published
241
+ as `Unexpected token: hacer`. Core's errors are now suppressed for a region
242
+ the front-end accepted in a non-English language. The integration suite
243
+ that claimed to cover this had been discarding every notification; it now
244
+ records `publishDiagnostics` and asserts on it.
245
+
246
+ - **Language server: settings actually reach the server.** Neither VS Code
247
+ extension set `synchronize.configurationSection`, so the client pushed
248
+ `settings: null` and every `mode`/`language`/`maxDiagnostics` value was
249
+ ignored; `initializationOptions` was ignored too. The server now reads
250
+ `initializationOptions`, a pushed `lokascript`/`hyperscript` section, or
251
+ pulls `workspace/configuration` when the push is empty — and merges partial
252
+ objects over the defaults instead of replacing them (a bare
253
+ `{ maxDiagnostics }` used to leave `language` undefined and error on every
254
+ document). Both extensions push their section, and the LokaScript one now
255
+ contributes `lokascript.mode`.
256
+
257
+ - **Both VS Code extension server bundles build and run.** The standalone
258
+ hyperscript extension's `bundle:server` had failed since #1016 (no shim for
259
+ `@hyperfixi/core/multilingual`); the LokaScript extension externalized
260
+ `@hyperfixi/core` without shipping it, so every install ran with core
261
+ absent ("diagnostics and hover degraded"). Core is bundled in now, and CI
262
+ runs both bundle scripts.
263
+
264
+ - **`@lokascript/language-server` declares what it imports.**
265
+ `@lokascript/semantic` was an optional peer but a static import (the
266
+ server crashed at startup without it); `@lokascript/framework` was
267
+ undeclared and got inlined together with `@lokascript/intent` (261 KB) —
268
+ and without `--clean`, `dist/` shipped every previous build's chunk (three
269
+ dead ones, 63% of the tarball). Both are regular dependencies now, the
270
+ build cleans, the 20-byte `--dts` output is gone, and `npm test` rebuilds
271
+ the server it spawns.
272
+
273
+ - **Hyperscript-compat mode stops flagging portable code.** `as Int`, `Float`,
274
+ `JSON`, `Date`, `Set`, `Map` are upstream conversions (the extension list
275
+ is now `Math`/`Values`, the ones core registers and upstream lacks);
276
+ `my.x`/`your.x` evaluate upstream (only `its.` is flagged); and the
277
+ extension-command scan no longer fires inside `y.replace(`, `arr.push(`,
278
+ string literals, `:process`, `--` comments, or the upstream trailing
279
+ `… unless …` modifier.
280
+
281
+ - **Language-server false positives and misses.** A `.hs` file containing a
282
+ query literal like `<li/>` was classified as HTML and lost every feature;
283
+ possessives after `)`/`]`/`>` and apostrophes in `--` comments raised
284
+ `unmatched-quote`; the outline reported the `on` in `toggle .x on me` as a
285
+ handler and `.init` as an init block; `install Foo(args)` produced
286
+ overlapping rename edits VS Code rejects; `on draggable:start` became a
287
+ variable named `:start`; and keyword boundaries were ASCII `\b`, so
288
+ definitions and symbols were silently absent in the ten non-Latin
289
+ languages. Completion-context and document-symbol logic moved out of the
290
+ entry script into `completion-context.ts` / `document-symbols.ts` so the
291
+ unit suite tests the shipped code rather than the hand-copied twins it
292
+ used to carry.
293
+
294
+ - **MCP `get_diagnostics`, `get_completions` and `get_document_symbols` read
295
+ the AST.** The bridge guarded those paths on helper names core never
296
+ exported, so all three had only ever taken their token-based fallback.
297
+ They now read the interchange: the core parser's own errors become
298
+ diagnostics, completions inside a command offer that command's argument
299
+ shapes, symbols carry their commands as children, and a document with
300
+ several `end`-terminated handlers keeps all of them.
301
+
302
+ - **`hyperscript.process()` honours the event grammar.** The API-side DOM
303
+ processor carried its own listener installer for `on …` attributes and
304
+ silently dropped what the runtime's installer handles: `on
305
+ click[event.shiftKey]` fired on a plain click, `on mouseenter or click` never
306
+ fired on mouseenter, `on click from document` never fired. Every browser
307
+ bundle already went through the runtime; `process()` now does too, and
308
+ `config.logAll` moved into the runtime so both paths log. Pinned by
309
+ `api/dom-processor.test.ts`, which runs each case on both paths.
310
+
311
+ - **The browser bundles' attribute processor now runs the element lifecycle,
312
+ and its lazy stub only takes the shapes it can run faithfully.** Measured
313
+ side by side with `hyperscript.process()`: the bundle path never dispatched
314
+ `hyperscript:before:init` / `hyperscript:after:init` and never set
315
+ `data-hyperscript-powered` — both lived only in the API processor, so a
316
+ morph engine reading the marker saw nothing on a bundle-processed page, and
317
+ canceling `before:init` was impossible there. It also compiled every
318
+ attribute as English; it now detects the element's language (`data-lang`,
319
+ closest `lang`, the document's) the way `process()` always did. And the
320
+ `lazyParsing` stub read only the event NAME from the header, so for the
321
+ first event it ignored a filter (`on click[event.shiftKey]` fired on a
322
+ plain click), listened for the first name of an `or` list only, and never
323
+ saw `from <target>` at all; a header with a filter, `(args)`, `or`, `from`,
324
+ `elsewhere`, `queue`, `debounced`, `throttled` or `in` is now processed
325
+ eagerly. `dom/processor-parity.test.ts` runs every row on all three paths
326
+ (API, eager, lazy) and is the gate the DOM-processor collapse landed under.
327
+
328
+ - **`hyperscript.process()` and the browser bundles share one DOM
329
+ processor.** `process()` and `cleanup()` now run on the attribute
330
+ processor every bundle uses, which receives its compiler and runtime from
331
+ the API by injection instead of importing it (the `dom -> api` layering
332
+ edge is gone). What changes for `process()` callers, all of it upstream
333
+ parity: an element is initialized once however many times it is passed or
334
+ scanned (it used to re-install on every call); `<script
335
+ type="text/hyperscript">` tags inside the tree are processed, with or
336
+ without `for=`, before the elements that may `install` what they define;
337
+ each element gets a non-bubbling `load` event once its program has run,
338
+ and an unparseable attribute is reported through `console.error`, the
339
+ `hyperfixi:compile-error` event and `config.onCompileError` (it was logged
340
+ at debug level only). And `cleanup(container)` now un-marks every processed
341
+ descendant — it stripped the root's `data-hyperscript-powered` only — and
342
+ drops a lazy stub still waiting on an element, so cleanup-then-process
343
+ re-initializes the tree once. A second scan in `lazyParsing` mode no longer
344
+ registers a second stub.
345
+ The API-side processor module is deleted; the multilingual bundle's own
346
+ copy of the language walk now calls the shared one, narrowed to the
347
+ languages that bundle ships; and a subtree the `MutationObserver` picks up
348
+ takes the same entry as `process()`.
349
+
350
+ - **`set *<css-property>` writes inline style in every spelling upstream
351
+ accepts.** `set *opacity to 0.5`, `set *opacity of me to 0.5` and
352
+ `set *background-color of me to "red"` were silent no-ops and
353
+ `set the *opacity of me to 0.5` threw; only the possessive `set my *opacity`
354
+ worked. The tokenizer classes `*opacity` as a selector (for `measure`), and
355
+ `set`'s parser now re-types it into the identifier property the runtime's
356
+ style rungs already handle, so one path serves all of them — bare, `of
357
+ <target>`, `the … of <target>`, `<target>'s`. Ten rows pinned against
358
+ `_hyperscript` 0.9.93.
359
+
360
+ - **`require('@hyperfixi/core')` returned `{}`, and the subpath `require`s
361
+ threw — since `"type": "module"`, on 3.0.0 too.** Every `exports.*.require`
362
+ and `main` pointed at a `.js` file built as CommonJS, which Node reads as
363
+ ESM under that flag. The CJS outputs are `.cjs` now (main entry, the 21
364
+ subpaths, the parser modules); the `import` conditions are unchanged. The
365
+ bare-Node check in CI now `require()`s the entries as well as importing
366
+ them, which is the check that would have caught this. Found by the
367
+ end-to-end probe that landed Arc 1's build half.
368
+
369
+ ### Changed
370
+
371
+ - **`@hyperfixi/core`'s library entry no longer bundles the multilingual
372
+ front-end.** `dist/index.mjs`/`index.js` had `@lokascript/semantic`,
373
+ `@lokascript/intent` and `@lokascript/framework` inlined whole (3.33 MB, zero
374
+ dynamic imports left); they are external now (1.04 MB) and load on the first
375
+ non-English `compileAsync`, the way the source always said they would. No
376
+ API change: semantic and intent stay `dependencies`, framework stays an
377
+ optional peer — and is now genuinely one. A consumer that imported both core
378
+ and semantic no longer holds two copies of semantic. `dist/index.min.js`
379
+ (UMD, not in `exports`) stays self-contained. Gated by
380
+ `scripts/check-node-import.mjs` on the sourcemap. Engine-migration plan Arc 1
381
+ step 2, build half.
382
+
383
+ - **`@lokascript/semantic` drops its `asyncSchema`.** Core deleted the `async`
384
+ command in 3.0.0 (#1102); the semantic front-end never emitted the action
385
+ anyway — its `stripAsyncModifier` pass removes the keyword (in all 24
386
+ languages) and parses the following command, so `async fetch /api as json`
387
+ is a `fetch`. The schema, its registration, the `'async'` `ActionType`
388
+ member and the AST-builder mapper row are gone. Kept on purpose: every
389
+ profile's `keywords.async` (the stripper matches on it) and the
390
+ `'then' | 'and' | 'async'` chain type (a different concept). The IR-level
391
+ `async all/race` node lives in `@lokascript/intent` and is untouched.
392
+
393
+ ## [3.0.0] - 2026-09-03
394
+
395
+ Full notes: [GitHub Releases](https://github.com/codetalcott/hyperfixi/releases/tag/v3.0.0).
396
+
397
+ One major, two themes. `@lokascript/i18n`'s grammar transformer is gone,
398
+ because `@lokascript/semantic` overtook it on every row of the translation
399
+ corpus (#973–#1001). And the engine-migration plan
400
+ (`docs-internal/ENGINE_MIGRATION_PLAN.md`) closed its last arc, which deleted
401
+ the exported dead code it had been carrying and collapsed the browser bundle
402
+ lineup to two names (#1099–#1105). One arc is still open: Arc 1's steps 2
403
+ and 3 — `@hyperfixi/core`'s library entry still bundles the semantic
404
+ front-end (recorded in the plan's History, 2026-09-03).
405
+
406
+ ### ⚠ BREAKING
407
+
408
+ - **`@lokascript/i18n` no longer translates** (#1001). `translate()`, `toLocale()`,
409
+ `toEnglish()`, `GrammarTransformer` and `createTransformer` are deleted; the
410
+ package is per-language vocabulary and grammar profiles. Migrate to
411
+ `import { translate } from '@lokascript/semantic'` (same signature; it throws
412
+ on unparseable input where the transformer returned nonsense). The classic-i18n
413
+ browser bundle, `@hyperscript-tools/i18n` and `@lokascript/types-browser` drop
414
+ the same members (#998, #999); the patterns corpus writer is semantic-only (#1000).
415
+ - **The prebuilt browser bundles are two names** (#1105): `hyperfixi-hx.js`
416
+ (small: hybrid parser, blocks, expressions, htmx v1/v2 attributes) and
417
+ `hyperfixi.js` (everything); `hyperfixi-hx-v4.js` and
418
+ `hyperfixi-multilingual.js` stay as separate products. `hyperfixi-lite.js`,
419
+ `-lite-plus.js`, `-minimal.js`, `-standard.js` and their `./browser/*`
420
+ exports are gone — use `hyperfixi-hx.js`, `hyperfixi.js`, or the Vite
421
+ plugin, which picks the tier itself. `./browser/hybrid-complete` remains as
422
+ the plugin's internal fallback.
423
+ - **Exported dead code deleted from `@hyperfixi/core`** — none had a
424
+ production caller: the six `@deprecated` `features/` families and the
425
+ modular bundle's `features` namespace (#1099); `Lexer`/`Tokens` (#1100 —
426
+ use `tokenize`); the `unified-types` `Validator`, the `types.d.ts` shim and
427
+ `registry/multilingual` (#1101); the `async` command (#1102 — it was
428
+ unreachable from parsed hyperscript; the manifest is 58 commands);
429
+ `ContextProviderRegistry`, the context-provider `Proxy`, the registry's
430
+ `context` slot and the plugin `contextProviders` field (#1104 — set
431
+ request-scoped values as `context.locals`).
432
+
433
+ ### Fixed
434
+
435
+ - **A small bundle fails loudly on a command it lacks and names `hyperfixi.js`**
436
+ (#1103). The hybrid parser had been dropping an unrecognised word silently;
437
+ making it loud also exposed and fixed three silent mis-parses in the hybrid
438
+ bundles: unquoted `fetch /api/data` fetched `/`, `send custom:event` sent
439
+ `custom` to `me`, and `repeat forever` ran zero iterations.
440
+ - **English→foreign rendering is gated** (#931–#972, #953): 3105/3105 corpus
441
+ renders parse on the canonical engine; the bare (handler-less) surface has its
442
+ own gate. `as JSON` stays part of the value (#991); a flattened loop header
443
+ closes (#992).
444
+ - Plugins report their real versions (#926); `analyze_content` is unshadowed in
445
+ the MCP server (#927); four dependency advisories resolved; the `domain-flow`
446
+ → `server-bridge` route contract is pinned (#1000s).
447
+
448
+ ### Changed
449
+
450
+ - `hyperfixi.js` and `hyperfixi-hx-v4.js` carry the 24-language render
451
+ vocabulary (~19 KB gzip each) so `translate` works in the browser (#931).
452
+ - Deprecated `@lokascript/domain-*` references repoint to `@lokascript/domains`.
453
+
454
+ ## [2.11.1] - 2026-08-25
455
+
456
+ Patch release. Fixes the release workflow itself: the build now runs **after**
457
+ the version sync, so a published tarball carries its own version rather than
458
+ the previous one, and `version.ts` is committed (#925). Also lands the
459
+ agent-loop A/B benchmark with an isolated generator (#924).
460
+
461
+ ## [2.11.0] - 2026-08-24
462
+
463
+ Full notes: [GitHub Releases](https://github.com/codetalcott/hyperfixi/releases/tag/v2.11.0).
464
+
465
+ ### Changed
466
+
467
+ - **The domain-DSL family moved out** (#909). Twelve packages left this
468
+ monorepo: the ten publishable `@lokascript/domain-*` packages (bdd,
469
+ behaviorspec, config, flow, jsx, learn, llm, sql, todo, voice) plus the
470
+ private `domain-toolkit` and `mcp-multilingual-intent`. They now ship as
471
+ **`@lokascript/domains`**, one subpath export per domain, from the
472
+ [lokascript-domains](https://github.com/codetalcott/lokascript-domains)
473
+ repository.
474
+
475
+ All ten published names are **deprecated on npm**, each naming its
476
+ replacement subpath (`@lokascript/domain-sql` → "import from
477
+ `@lokascript/domains/sql`"). Existing installs keep working — deprecation is
478
+ a warning, not a removal — they simply stop receiving updates. The
479
+ pre-deletion tree is preserved at the `moved/domain-family` tag.
480
+
481
+ _Migration:_ replace nine dependencies with one, and change
482
+ `from '@lokascript/domain-x'` to `from '@lokascript/domains/x'`. The root
483
+ entry absorbed `domain-config` and exports `createDomainRegistry`,
484
+ `registerAllDomains` and `DOMAIN_PRIORITY`.
485
+
486
+ ### Added
487
+
488
+ - **"Show in My Language"** — LSP request plus VSCode command (#921).
489
+ - **Verified-translation badge** in the compilation service (#920).
490
+ - **`scoreFidelity` / `@lokascript/semantic/fidelity`** (#919).
491
+ - **Inert-shape warnings** (#918) and surfaced unconsumed-input warnings (#916)
492
+ in the compilation service.
493
+ - **The agent-loop benchmark** and the silent-failure finding it produced
494
+ (#915), and the MCP server's agent-era roadmap (#914).
495
+ - **Element-collection write-back** for hypermedia tables, with gallery
496
+ examples and four system fixes (#904).
497
+ - **The comprehensive Playwright tier now runs in CI** (#908) alongside
498
+ `quick`. It had never run: 122 specs, hiding four real bugs — a detached
499
+ `startViewTransition`, untracked reads of unset globals, concurrent effects
500
+ clobbering dependency capture, and `put` stringifying DocumentFragments
501
+ (#905).
502
+
503
+ ### Fixed
504
+
505
+ - **The `hyperscript-adapter` review arc** (#895–#902): whole-string
506
+ translation first, taking canonical validity from 2849/3105 to **3105/3105**
507
+ (#899); a host-parser validity gate so an invalid render falls back to the
508
+ author's text (#900); the dead split-statement fallback deleted after
509
+ measuring 0 outputs (#901); and the slim divergence set burned 6 → 1 via
510
+ schema marker data, repairing 39 body-dropping corpus rows (#902).
511
+ - **`qu take.recipient`** — the R1 tail's last `take` row (#910).
512
+ - **The release workflows** no longer reference the moved-out domain family
513
+ (#922).
514
+
515
+ ## [2.10.0] - 2026-08-01
516
+
517
+ Full notes: [GitHub Releases](https://github.com/codetalcott/hyperfixi/releases/tag/v2.10.0).
518
+
519
+ Highlights: `swap`/`process`/`morph … using view transition` across all 24
520
+ languages (#870, #873, #875), typed command registration (#869, #871),
521
+ `tell`/`process` parser fixes (#861, #872), the R1 role-fidelity burn-down
522
+ (#864, #867, #868, #874, #878), and guards for the remaining hand-maintained
523
+ CI package lists (#862, #865).
524
+
525
+ ## [2.9.0] - 2026-07-25
526
+
527
+ > **Gap note:** 2.9.1 through 2.9.4 shipped without entries in this file; their
528
+ > details live in [GitHub Releases](https://github.com/codetalcott/hyperfixi/releases).
529
+
530
+ ### ⚠ BREAKING (types)
531
+
532
+ - **Domain renderers return `string | null`.** `renderSQL`, `renderJSX`, `renderTodo`,
533
+ `renderLLM`, `renderFlow`, `renderBDD`, `renderVoice` and `renderBehaviorSpec`
534
+ previously signalled "I don't know this action" with a successful-looking
535
+ sentinel string — `` `-- Unknown: ${node.action}` `` (or `// Unknown:` in three
536
+ domains). Consumers were forced into string matching, and any legitimately
537
+ rendered sentence starting with `--` was silently dropped. They now return
538
+ `null`.
539
+
540
+ **Rendered output for every previously-known action is byte-identical** — all
541
+ 1,939 existing domain tests pass unchanged.
542
+
543
+ _Migration:_ replace sentinel sniffing with a null check. A guard of the shape
544
+ `if (!sentence || sentence.startsWith('--')) return null;` already handles it.
545
+
546
+ ### Added
547
+
548
+ - **Domains are open for extension** (`@lokascript/framework` + all 8 domain packages).
549
+ A consumer can add a command to a domain **without editing that package**, by
550
+ passing a `DomainExtension` to `createXDSL({ extensions })`. A schema plus one
551
+ vocabulary entry per language is enough to parse, render and compile it in all
552
+ of them — word order, marker placement and keyword position derive from the
553
+ schema and the language profiles. Vocabulary may cover a subset of the DSL's
554
+ languages, so it can be filled in over time. See
555
+ [Extending an Existing Domain](packages/framework/docs/DOMAIN_AUTHOR_GUIDE.md#extending-an-existing-domain).
556
+ - **`createDomainRenderer`** (`@lokascript/framework`) composes a domain's
557
+ hand-written per-action renderers with a schema-driven fallback, returning
558
+ `null` for actions it has neither for. It is what each domain's `renderX` now
559
+ runs, and what makes an extension command render without the domain knowing it
560
+ exists.
561
+ - **`MultilingualDSL.render(node, language)`** — render a parsed node back to
562
+ natural language. Chains extension renderer → domain renderer → schema
563
+ fallback → `null`. `parse()` + `render()` is the language-to-language path that
564
+ does not need a `grammarProfile`.
565
+ - **`getAllTranslationsWithStatus()`** (`@lokascript/semantic`) — the same result
566
+ as `getAllTranslations()`, plus a `failed` map naming each language that could
567
+ not render and why.
568
+ - **`createMultilingualDSL` is now a named export** of `@lokascript/framework`
569
+ rather than reaching consumers only through a wildcard re-export. Domains also
570
+ export `allProfiles`, which extension authors need.
571
+ - **A CHANGELOG now ships in every published package.** Determining what changed
572
+ between two releases previously meant probing the installed code.
573
+
574
+ ### Changed
575
+
576
+ - **Directional markers for `add` / `put` / `go` in es, ar, zh, fr, de, pt**
577
+ (`@lokascript/semantic`). Every language profile's `destination` marker is
578
+ locative (`on` / `على` / `在` / `sur` / `auf`) because it also serves
579
+ `toggle`/`show`; only English overrode it for the directional commands, so the
580
+ rest rendered "add .active ON #box". Now: add → es `a`, ar `إلى`, zh `到`,
581
+ fr `à`, de `zu`, pt `a`; put → ar `في`, zh `到`, fr `dans`, de `in`; go → es `a`,
582
+ ar `إلى`, fr `à`, de `zu`, pt `para`. ja `に` / ko `에` / tr `e` were already
583
+ directional and are unchanged.
584
+
585
+ **Parsing accepts a strict superset**: a new `RoleSpec.markerLegacy` keeps every
586
+ previously-rendered marker parsing, so source written against ≤2.8 keeps working.
587
+ Downstream consumers maintaining correction tables for these markers (as
588
+ `lokascript-learn` does) can now delete those entries.
589
+
590
+ - **`createSchemaRenderer` honors `svoPosition` / `sovPosition`.** It previously
591
+ iterated roles in declaration order and never read the positions, so a schema
592
+ whose declared order differed from its declaration order rendered a surface its
593
+ own generated pattern could not re-parse. It now sorts with the same comparator
594
+ pattern generation uses (**descending — higher values render earlier**). Affects
595
+ only custom schemas; no in-repo consumer relied on the old behavior.
596
+ - **Absent roles no longer leave a dangling marker.** `createSchemaRenderer` emitted
597
+ a role's marker even with no value, producing `analyze #content as` /
598
+ `#content として 分析`.
599
+ - **`getAllTranslations()` covers every registered language** (24) instead of a
600
+ frozen 13-language list, and a language that fails to render is skipped rather
601
+ than throwing. The full browser bundle now registers Hebrew, which was
602
+ registered everywhere except there.
603
+ - **Schema-validation diagnostics are opt-in.** `import '@lokascript/domain-llm'`
604
+ printed ~44 lines of `[SCHEMA VALIDATION]` stderr into every downstream test run
605
+ and CI log. Set `LOKASCRIPT_SCHEMA_VALIDATION=1` to see them; a standing test in
606
+ `@lokascript/semantic` keeps them honest.
607
+ - **`dsl.translate()` names the missing config field** when a language has no
608
+ `grammarProfile`, instead of failing deep in the transformer with
609
+ "No profile found for language: en". Anyone matching that exact message must update.
610
+ - **`defineCommand` / `getRoleSpec` validate their input.** A malformed schema now
611
+ fails with a message naming the field, instead of
612
+ `TypeError: undefined is not an object (evaluating 'schema.roles[0]')` from
613
+ inside the package.
614
+
615
+ ### Fixed
616
+
617
+ - **A corrected marker stopped parsing in nested contexts.** Three separate
618
+ override branches — the SOV and VSO event-handler generators and the shared
619
+ marker resolver — each dropped marker alternatives, so Arabic
620
+ `ضع هو إلى #chat` parsed standalone but not inside a `socket` block. They now
621
+ share one definition of what an override still accepts.
622
+
623
+ ## [2.8.0] - 2026-07-25
624
+
625
+ > **Gap note:** 2.6.0 through 2.7.2 shipped without entries in this file; their
626
+ > details live in [GitHub Releases](https://github.com/codetalcott/hyperfixi/releases).
627
+ > Full notes for this release: `docs-internal/RELEASE_NOTES_v2.8.0-draft.md` (swapped
628
+ > into the GitHub release on publish day).
629
+
630
+ A size and correctness release: the full bundles shed a duplicated core+semantic copy (~534 → ~299 KB gz), the semantic parser closes out several multilingual correctness arcs, and the publish pipeline's gates are now honest end-to-end.
631
+
632
+ ### Highlights
633
+
634
+ - **Full bundles nearly halved** (`@hyperfixi/core`): since 2.7.0 the full bundles shipped two copies of the core runtime and multilingual parser (the bundled reactivity/realtime plugins resolved `@hyperfixi/core` to its prebuilt dist alongside the bundle's own source graph). A rollup alias folds everything onto one graph: `hyperfixi.js` ~534 → **~299 KB gz**, `hyperfixi-hx-v4.js` ~540 → **~311 KB gz**. Same features and pre-installed plugins; CI size ceilings ratcheted down to catch re-duplication.
635
+ - **`fetch … with { … }` options in all 24 languages** (#662): request options (braced bodies, `method:` / `headers:` / `body:` named args) are captured by the semantic parser in every supported language — previously most non-English languages silently dropped the clause and issued a bare GET.
636
+ - **Event modifiers in all 24 languages** (#673): `once`, `debounce(N)`, `throttle(N)` and their translated forms flow from every language's event-handler head to the runtime.
637
+ - **Foreign→English canonical validity: 3059/3059** (#724–#732, pick text-range #733/#734/#736): every authored foreign translation now renders English that the canonical hyperscript.org parser accepts — both canonical-validity allowlists are empty — and a new R4 canonical-validity ratchet (#727) plus a ninth `--regression` signal keep it that way.
638
+ - **New package: `@lokascript/htmx-adapter`** (#735): multilingual adapter for upstream htmx v4 (canonicalizing extension).
639
+
640
+ ### Fixed
641
+
642
+ - **`go to url "/page"` no longer drops the URL** (#680) — the destination was silently lost in every language (the English reference itself was affected, which masked it).
643
+ - **Broken event listeners in six languages** (#681) — de/fr/id/it/pl/zh dictionaries rendered `mousedown`/`mouseup` as words the parser could not resolve; a V3c vocabulary check now verifies every dictionary event word round-trips on the parse side.
644
+ - **"Unknown command: compound" on semantic-path bundles** (#675) — multi-command handler bodies could throw at runtime on the full bundles; the per-segment semantic adapter now defers non-command parses to the traditional parser.
645
+
646
+ ### Infrastructure
647
+
648
+ - Publish pipeline hardening (#672, #674): reproducible `npm ci` installs, `pre-publish-check` with real exit codes end-to-end, export validation after bundle builds, complete BUILD_ORDER, and a final verdict step that always runs.
649
+ - Vocab consistency gate and total input-coverage instrumentation in CI; the multilingual fidelity ratchet holds the 2026-07-11 high-water marks (fidelity 1.000 on all 3,696 corpus rows across 24 languages).
650
+
651
+ ## [2.5.1] - 2026-05-24
652
+
653
+ A single-bug patch for a v2.5.0 publishing regression that broke every localized htmx attribute.
654
+
655
+ ### Fixed
656
+
657
+ - **`hyperfixi-hx.js` / `hyperfixi-hx-v4.js`: `window.__hyperfixi_i18n` lost to terser** (`@hyperfixi/core`). The Phase 8 orchestrator's public-API singleton (`window.__hyperfixi_i18n = { register }`) was being eliminated by terser in the published v2.5.0 hybrid-hx and hybrid-hx-v4 bundles, silently breaking every `vocab/htmx/{lang}.js` module on load with `"loaded before the htmx-compat orchestrator"`. Two layers fixed: (1) the module-level `installPublicAPI()` invocation is now exported and called explicitly from each bundle entry that includes htmx-compat, so terser's `unused: true, toplevel: true` pass can't drop it; (2) the API is exposed via bracket-access (`window['__hyperfixi_i18n']`) to bypass terser's `properties.regex: /^_/` mangling. Localized htmx attribute names (`hx-obtener`, `hx-取得`, `hx-احصل`, …) now resolve correctly in the published bundles, matching their already-working behavior under the source-aliased vitest suite.
658
+
659
+ ### Tests
660
+
661
+ - **Orchestrator public-API gate** in pre-publish-check + release-smoke. New 2-test Playwright spec (`packages/core/src/compatibility/browser-tests/i18n-orchestrator-api.spec.ts`, ~600 ms) asserts `typeof window.__hyperfixi_i18n.register === 'function'` in both shipped htmx bundles. Wired into `.github/workflows/pre-publish-check.yml` (fails the workflow on regression) and the `--matrix` stage of `examples/release-smoke/run.mjs` (so the gate fires against the registry-installed tarball, not only the locally-built dist). Surgical — no swap-pipeline dependency. The broader `i18n-htmx.spec.ts` remains un-wired pending two pre-existing bugs unrelated to this release: a reactivity / notify-hook bug breaking localized `hx-live` re-renders, and a swap-pipeline bug stringifying `DocumentFragment`s in `fetch ... as html` → `put it into target`.
662
+
663
+ ## [2.5.0] - 2026-05-22
664
+
665
+ A focused release: a new LLM-domain introspection API, plus correctness fixes for the parser, the multilingual renderers, and how published packages declare their internal dependencies.
666
+
667
+ ### Added
668
+
669
+ - **`describeCommands()` / `describeCommand()`** in `@lokascript/domain-llm` — a JSON-serializable description of every LLM command: its roles, per-language marker keywords, and a verified runnable example in each of the 8 supported languages. Adds the `LLM_LANGUAGE_CODES` export. One source of truth for docs, MCP tool schemas, and LLM-agent discovery. `@lokascript/domain-llm` also gains a package README.
670
+
671
+ ### Fixed
672
+
673
+ - **`toggle @attribute`** (`@hyperfixi/core`): `toggle @disabled`, `toggle @required`, and similar threw `toggle command: no valid class names found` in the browser. `toggle` now skips semantic parsing (like its sibling DOM commands `add` / `remove`), so the `@attr` / `.class` / `*property` argument forms all work.
674
+ - **SOV word order in the multilingual renderers** (`@lokascript/domain-bdd`, `@lokascript/domain-llm`): Japanese / Korean / Turkish output from `renderBDD` and `renderLLM` was not parseable — particle placement and word order were wrong, so `translate_bdd` / `translate_llm` produced broken SOV text. Fixed, with render→compile round-trip guardrail tests.
675
+ - **Internal dependency versions**: published packages declared their internal workspace dependencies as `"*"`, which shipped literally to npm and could let a consumer resolve a mismatched (older) internal package. Internal deps now carry exact caret ranges.
676
+
677
+ ## [2.4.0] - 2026-05-20
678
+
679
+ Two parallel arcs landed since v2.3.1: **upstream `_hyperscript` 0.9.90 parity** (9 phases — commands, comparators, collection ops, event modifiers, plugin system, 3 new public plugin packages, i18n) and **htmx v4 compatibility** (reactive `hx-live`, SSE/WebSocket streaming, per-element localized attribute names, the size-busting `hyperfixi-hx-v4.js` bundle).
680
+
681
+ ### Added
682
+
683
+ #### Core language (upstream \_hyperscript 0.9.90 compat)
684
+
685
+ - **9 new commands**: `focus`, `blur`, `empty`, `open`, `close`, `select`, `clear`, `reset`, `breakpoint` — covers DOM focus management, form state, window control, and debugger integration.
686
+ - **4 comparator expressions**: `X starts with Y`, `X ends with Y`, `X is between A and B`, and the postfix `... ignoring case` modifier for case-insensitive string comparison. `between` is inclusive and auto-orders bounds.
687
+ - **5 collection infix operators**: `collection where <pred>`, `collection sorted by <key>`, `collection mapped to <expr>`, `string split by <sep>`, `array joined by <sep>`. `where`/`sorted by`/`mapped to` bind `it` per element for inline predicates/keys.
688
+ - **Event modifiers**: `on first <event>` alias for `.once`, plus synthetic `on resize` for HTMLElements backed by `ResizeObserver` (browser standard `resize` is window-only).
689
+
690
+ #### Plugin system
691
+
692
+ - **`HyperfixiPlugin` public API**: `installPlugin(plugin)` on Runtime, `ParserExtensionRegistry` singleton with snapshot/restore for test isolation. Five plugin seams: `registerFeature`, `registerNodeEvaluator`, `registerGlobalWriteHook`, `registerGlobalReadHook`, and `HyperfixiPluginContext.runtime`. `$name` globals canonicalized to bare-key storage across `setVariableValue` and both identifier evaluators.
693
+
694
+ #### New plugin packages
695
+
696
+ - **`@hyperfixi/speech`**: Voice I/O via Web Speech API — `speak "text"` (with optional `rate`/`pitch`/`voice`/`volume`), `ask "question"`, `answer with "value"`. Idempotent installation; no-ops cleanly when the Web Speech API or `window.prompt()` is unavailable.
697
+ - **`@hyperfixi/reactivity`**: Reactive signals — `live { ... }` blocks, `bind` expressions (now also accepts explicit property via `'s` or `.` syntax), `when X changes`, `^name` reactive reads. Microtask-flushed scheduler with cycle guard and auto-stop on element disconnect.
698
+ - **`@hyperfixi/components`**: Custom Element registration from `<template component="tag">` / `<script type="text/hyperscript-template" component="tag">`. **v2 shipped this release** — reactive `^var` rendering (via `@hyperfixi/reactivity`), `#if` / `#for` directives, slot substitution, `${expr}` interpolation. Init scripts (`_=` on the `<template>`) run on each stamp.
699
+
700
+ #### Internationalization (i18n)
701
+
702
+ - Phase 1 commands translated across all 23 COMPLETE_LANGUAGES (7 new schemas in `@lokascript/semantic`: `empty`, `open`, `close`, `select`, `clear`, `reset`, `breakpoint`).
703
+ - Phase 2 comparators (`starts with`, `ends with`, `between`, `ignoring case`) translated across all 23 languages (with `starts with`/`ends with`/`between` backfills in bn, th, vi).
704
+ - Phase 3 collection ops (`sorted by`, `mapped to`, `split by`, `joined by`) translated across all 23 languages (`where` predated this release).
705
+ - New `packages/i18n/src/schema-alignment.test.ts` — guards drift: every `CommandSchema` must have an `en.ts` entry, Phase 1/2/3 operators must exist across all complete dictionaries.
706
+
707
+ #### htmx v4 integration
708
+
709
+ - **`hx-live` reactive expressions**: When `@hyperfixi/reactivity` is installed, the htmx-compat layer recognizes htmx v4's `hx-live` attribute and translates it to a `live ... end` block. The expression body is hyperscript (not JavaScript like upstream htmx v4), so it gets fine-grained dependency tracking + inherits multilingual support. If reactivity isn't installed, the element is skipped with a clear console error.
710
+ - **`sse-connect` / `sse-swap`**: Long-lived `EventSource` per element. Bounded exponential reconnect backoff (1s → 2s → 4s … capped at 30s, 5 retries). Auto-close on DOM removal via `MutationObserver`. Lifecycle events: `htmx:sseOpen`, `htmx:sseMessage`, `htmx:sseError`, `htmx:sseClose`. Multiple named events per connection. Swap targets resolve `closest`/`find`/`next`/`previous`.
711
+ - **`ws-connect` / `ws-send`**: Bidirectional WebSocket per element. JSON envelope routing (`{ target, swap?, data }`) drives surgical updates through the existing `hx-target`/`hx-swap` machinery; raw messages dispatch as `htmx:wsMessage`. Outbound sends queue while connecting, flush on `htmx:wsOpen`. Same reconnect backoff as SSE.
712
+ - **Localized htmx attribute names (Phases 8–10)**: Per-element `lang=` resolution. Authors can write `hx-obtener` / `hx-objetivo` / `sse-conectar` (Spanish), `hx-取得` / `hx-ターゲット` (Japanese), `hx-احصل` / `hx-هدف` (Arabic), etc. — the orchestrator translates them to canonical English before they hit the existing processor. 8 priority vocab modules ship with the bundle (en, es, fr, ja, zh, ar, ko, de). Missing-vocab languages log a one-time warning per language and fall back to English. `eventNameOf` / `selectorFor` / `nameOf` hooks are namespaced (`hx`, `sse`, `ws`) so `hx-on:*` localizes correctly.
713
+ - **htmx event lifecycle**: New CustomEvents `htmx:configuring` (cancelable, mutate `e.detail.config`), `htmx:beforeRequest` (cancelable), `htmx:afterSettle`, `htmx:error`, plus the SSE/WS lifecycle events listed above.
714
+
715
+ #### Bundles & build tooling
716
+
717
+ - **`hyperfixi-hx-v4.js`** (~257 KB gz): Full runtime + `@hyperfixi/reactivity` (auto-installed) + htmx-compat + SSE/WS support, all in a single script tag. The "batteries-included" choice for projects using htmx v4 reactive/streaming features. The slim `hyperfixi-hx.js` (~13 KB gz) does NOT ship reactivity/SSE/WS — choose hx-v4 when you reach for `hx-live` / `sse-connect` / `ws-connect`, hx otherwise.
718
+ - **Vite plugin: htmx v4 surface detection** — scans HTML for `hx-live` / `sse-*` / `ws-*` attributes and auto-routes to `hyperfixi-hx-v4.js`; otherwise emits a minimal handcrafted bundle as before.
719
+ - **`getDefaultRuntime()`** exposed for forcing lazy runtime construction (useful for bundles that defer wiring until first DOM event).
720
+
721
+ ### Fixed
722
+
723
+ - **Runtime**: `it`/`its`/`result` identifier cache no longer returns stale values across loop iterations — required for Phase 3 collection operators that rebind `it` per element (16 ms TTL cache had masked all Phase 3 tests before fix).
724
+ - **Runtime**: method-call `this` binding preserved on member callees — `items mapped to it.toUpperCase()` no longer throws "called on null or undefined". Uses `.apply(thisArg, args)` for member expressions.
725
+ - **Parser**: `is not` binary operator now routes to `notEquals.evaluate` — pre-existing gap where tokens parsed but runtime dispatch threw `Unknown binary operator: is not`.
726
+ - **Runtime**: `execute()` now mutates the caller's `ExecutionContext` in place when injecting the `ExpressionRegistry`, rather than shallow-cloning. Commands writing to `context.result` / `context.it` (e.g. the new `answer` command) now propagate those writes back to the caller — matching the long-standing `context.locals.set(...)` / `context.globals.set(...)` mutation pattern in the same function. `ExecutionContext.registry` is now mutable in the type signature (the runtime is the only legitimate writer; the `readonly` modifier was a defensive holdover from an earlier consolidation arc).
727
+ - **Runtime**: `or` / `and` short-circuit now returns the operand value (truthy/falsy), not a coerced boolean — matches upstream `_hyperscript` semantics.
728
+ - **Runtime**: `put` / `set` / `toggle` accept plain property names as write targets (not just `the X.Y` chains).
729
+ - **Runtime**: `evalHyperScript()` defaults to shared globals when none provided.
730
+ - **Runtime**: scoped `notifyLocalRead()` now fires when reading scoped locals (was missing — broke reactive `bind` to local vars).
731
+ - **Math**: binary-arithmetic operands accept DOM elements (coerced through the consolidated "is this convertible" path).
732
+ - **Parser**: `set the X.Y to Z` dotted property chains (e.g. `set the event.detail.result to ...`) now use the full expression parser rather than a fixed 2-token lookahead — handles arbitrary-depth chains and `of` expressions uniformly.
733
+ - **Parser**: `pick first 3 of arr` and other keyword-led command syntaxes (commands whose argument grammar starts with a keyword) now route through dedicated parsers and preserve trailing args. Added to `COMPOUND_COMMANDS` with a dedicated `parseXxxCommand` per case.
734
+ - **Browser bundle**: `ExpressionRegistry` threaded through the command-execution path (`processCommand` → `adapter.execute` → `parseInput`). Without this, commands like `tell`/`send`/`toggle` whose `parseInput()` evaluates AST nodes failed in the example gallery with "Expression X not in ExecutionContext.registry".
735
+ - **htmx-compat**: `hx-on:*` registers real event listeners directly from the processor (the translator never sees them, so it can stay declarative-only). Refresh observer wired correctly; localized `hx-on:*` prefix resolved via the namespaced i18n hooks.
736
+ - **i18n**: Reactive blocks (`live`, `when X changes`) route around `parseStatement` to fix `when`/`unless` + SOV-language `live` block parsing. Suppressed spurious "then" injection inside live blocks.
737
+ - **patterns-reference**: HTML patterns marked non-translatable (they're DOM markup, not source code); cleaned orphan languages from the database seed.
738
+ - **Semantic**: registry singleton shared across tsup entries (multi-entry split was forking the registry, breaking cross-entry pattern lookups).
739
+
740
+ ### Changed (internal)
741
+
742
+ - **Evaluator consolidation**: Retired the `BaseExpressionEvaluator` class hierarchy and 4 helper modules (~2,700 LOC removed) in favor of the single canonical evaluator at `parser/runtime.ts:evaluateAST` with the `ExpressionRegistry` on `ExecutionContext`. Both consolidation arcs (α + β) closed.
743
+ - **Domain DSLs**: Extracted a shared config package (`@hyperfixi/domain-config`) consumed by all 8 domain DSLs.
744
+ - **Published infrastructure packages**: `@lokascript/intent`, `@hyperfixi/domain-config`, `@hyperfixi/planner`, and `@hyperfixi/intent-element` are published to npm as transitive dependencies (required for `@hyperfixi/core` and the domain DSLs to install cleanly from the registry). They are infra deps — users do not install them directly. (These were published from post-tag fix-forward commits; the `v2.4.0` git tag predates them.)
745
+
746
+ ## [2.3.1] - 2026-04-23
747
+
748
+ ### Fixed
749
+
750
+ - **CI**: Added `planner` package to the build step (before `mcp-server`, which depends on it) across `ci.yml`, `publish.yml`, and `pre-publish-check.yml`; added `planner/dist` to the build-artifacts upload.
751
+ - **hybrid-complete bundle**: `toggle @attribute` and positional selectors (`first .x`, `last .y` in selector position) now work — closed a parser gap surfaced by the README "try it live" examples.
752
+
753
+ ### Added
754
+
755
+ - **README**: "Try it live" link to the gallery, broken-up counter example, tier links.
756
+
757
+ ### Changed
758
+
759
+ - **`planner` package**: Marked private (workspace-only — published packages should not list private deps).
760
+
761
+ ## [2.3.0] - 2026-03-17
762
+
763
+ ### Added
764
+
765
+ - **Lazy behavior resolver**: `install X` just works — behaviors resolve on demand without manual registration
766
+ - **Hyperscript-native behaviors**: Behaviors defined as hyperscript source strings via patterns-reference schemas
767
+ - **Dynamic class selectors**: `.{varName}` syntax in `toggle`, `add`, and `remove` resolves variables as CSS class names
768
+ - **Variable/expression durations**: `wait` command now accepts variable and expression durations (e.g., `wait feedbackDuration ms`)
769
+ - **Behavior schema sources**: Single source of truth for behavior schemas in patterns-reference
770
+
771
+ ### Fixed
772
+
773
+ - **Parser**: `js()` single-quote parsing, `set the X.Y` dotted property chains (e.g., `event.detail.result`), improved `set` error messages
774
+ - **Parser**: Namespaced events (`custom:activate`) and `trigger`/`on` inside `repeat` blocks in behaviors
775
+ - **Parser**: Adjacent dot after keywords treated as property access, not CSS selector
776
+ - **Behaviors**: Clipboard `wait feedbackDuration`, AutoDismiss wait timing, Removable confirm dialog
777
+ - **Browser**: Resolver bundle timing and Playwright test stability
778
+ - **CI**: Behaviors package added to build pipeline, artifact upload, and pre-publish-check build order
779
+
780
+ ## [2.2.1] - 2026-03-16
781
+
782
+ ### Fixed
783
+
784
+ - Parser: adjacent dot after keywords treated as property access, not CSS selector
785
+ - Dependency updates (build-tools group)
786
+
787
+ ## [2.2.0] - 2026-03-15
788
+
789
+ ### Fixed
790
+
791
+ - Dependency security: resolved 27 of 33 Dependabot vulnerabilities
792
+ - CI: copy examples gallery into repo, remove external clone dependency
793
+ - CI: suppress already-published errors in publish dry run
794
+
795
+ ## [2.1.0] - 2026-02-20
796
+
797
+ ### Added
798
+
799
+ - **domain-llm**: Expanded from 4 to 8 languages (added Korean, Chinese, Turkish, French) — 68 tests
800
+ - **domain-flow**: Expanded from 4 to 8 languages (added Korean, Chinese, Turkish, French) — 108 tests
801
+ - **domain-flow**: First npm publication as `@lokascript/domain-flow`
802
+
803
+ ### Changed
804
+
805
+ - All 7 domain DSLs now consistently support 8 languages (en, es, ja, ar, ko, zh, tr, fr)
806
+ - MCP server registry updated for new domain languages
807
+
808
+ ### Fixed
809
+
810
+ - Resolved test failures in 4 packages (19 tests)
811
+ - Scoped `first .X in me` to context element instead of document
812
+ - Property target bugs: disabled on button, tabIndex as number
813
+
814
+ ## [2.0.0] - 2026-02-15
815
+
816
+ ### Changed
817
+
818
+ - **Rebrand**: Renamed from LokaScript to HyperFixi for engine packages (`@lokascript/core` → `@hyperfixi/core`)
819
+ - Multilingual packages remain under `@lokascript/*` scope
820
+ - Synchronized all package versions to 2.0.0
821
+
822
+ ## [1.4.0] - 2026-02-10
823
+
824
+ ### Added
825
+
826
+ - **Language Server & VSCode Extension**: Full LSP with Go to Definition, Find References, multilingual hover, syntax highlighting, and HTML region extraction
827
+ - **AOT Compiler** (internal): Ahead-of-time compiler with 45 command codegens, expression transforms, 4 optimization passes, and 533 tests
828
+ - **Compilation Service** (internal): HTTP service for multilingual compilation with React renderer, test generation, and semantic diffing
829
+ - **Hyperscript Adapter** (@lokascript/hyperscript-adapter): Multilingual preprocessor plugin for original \_hyperscript with 24 per-language bundles
830
+ - **Semantic**: Russian/Ukrainian normalizers, improved SOV pass rates (JA 99%, KO 96%, TR 96%)
831
+ - **Vite Plugin**: htmx/fixi attribute scanning for zero-config support, hybrid-plus bundle commands
832
+
833
+ ### Changed
834
+
835
+ - **Monorepo cleanup**: Moved experimental packages (analytics, server-integration, multi-tenant, ssr-support, siren) to `experiments/`
836
+ - **Code audits**: Comprehensive audits across core (+58 tests), runtime (+34 tests), behaviors (+66 tests), expressions (9 security fixes), validation (+20 tests), features (+19 tests), i18n (+33 tests)
837
+ - **Semantic refactoring**: Modularized tokenizer, split pattern generator by word order, eliminated all `as any` casts
838
+ - **CI**: Consolidated workflows, switched to OIDC trusted publishing, upgraded to Node 24 LTS
839
+ - **Test count**: 4046 → 8100+ tests
840
+
841
+ ### Fixed
842
+
843
+ - Runtime correctness: GC fix, timeout handling, expression security hardening
844
+ - Browser test timeouts and false CI failures
845
+ - TypeScript errors across 6 packages for clean workspace typecheck
846
+ - Debug console.log leak in set command
847
+
848
+ ## [1.3.0] - 2026-01-23
849
+
850
+ _Synchronized version release. See git history for details._
851
+
852
+ ## [1.2.0] - 2026-01-21
853
+
854
+ _Synchronized version release. See git history for details._
855
+
856
+ ## [1.0.0] - 2026-01-19
857
+
858
+ ### Added
859
+
860
+ - **Initial Release**: First public release of LokaScript
861
+ - **Core Package** (@lokascript/core): Full hyperscript runtime with 43 commands
862
+ - **Semantic Package** (@lokascript/semantic): Multilingual parsing for 23 languages
863
+ - **I18n Package** (@lokascript/i18n): Grammar transformation for SOV/VSO/SVO word orders
864
+ - **Vite Plugin** (@lokascript/vite-plugin): Zero-config Vite integration
865
+ - **MCP Server** (@lokascript/mcp-server): Model Context Protocol server for LLM integration
866
+ - **Browser Bundles**: 7 size-optimized bundles (lite, lite-plus, hybrid-complete, hybrid-hx, minimal, standard, full)
867
+ - **23 Language Support**: English, Spanish, Japanese, Korean, Arabic, Chinese, French, German, Portuguese, Indonesian, Turkish, Swahili, Quechua, and more
868
+ - **4046 Tests**: Comprehensive test suite with >95% coverage
869
+ - **Etymology**: "LokaScript" from Sanskrit "loka" (world/realm/universe) reflecting multilingual scope
870
+
871
+ ### Changed
872
+
873
+ - **Rebrand**: Project renamed from HyperFixi to LokaScript
874
+ - **NPM Organization**: Published under @lokascript/\* scope
875
+ - **Browser API**: Primary global changed to window.lokascript (with window.hyperfixi backward compatibility)
876
+ - **Lifecycle Events**: Renamed to lokascript:_ prefix (dual dispatch with hyperfixi:_ for compatibility)
877
+
878
+ ### Fixed
879
+
880
+ - Workspace dependency resolution using wildcard versions (\*)
881
+ - TypeScript compilation across all 20+ packages
882
+ - Build system for browser bundles
883
+
884
+ ### Backward Compatibility
885
+
886
+ - window.hyperfixi available as deprecated alias to window.lokascript
887
+ - hyperfixi:_ events still dispatched alongside lokascript:_ events
888
+ - File names kept for compatibility (e.g., hyperfixi-browser.js)
889
+
890
+ ### Documentation
891
+
892
+ - Complete rebrand of all README files
893
+ - Updated CLAUDE.md with project context
894
+ - NPM organization setup guide
895
+ - Version management documentation
896
+
897
+ ### Security
898
+
899
+ - npm access token stored in GitHub Secrets
900
+ - 2FA recommended for npm organization
901
+
902
+ [Unreleased]: https://github.com/codetalcott/hyperfixi/compare/v3.3.0...HEAD
903
+ [3.3.0]: https://github.com/codetalcott/hyperfixi/compare/v3.2.0...v3.3.0
904
+ [3.2.0]: https://github.com/codetalcott/hyperfixi/compare/v3.1.0...v3.2.0
905
+ [3.1.0]: https://github.com/codetalcott/hyperfixi/compare/v3.0.0...v3.1.0
906
+ [2.10.0]: https://github.com/codetalcott/hyperfixi/compare/v2.9.0...v2.10.0
907
+ [2.9.0]: https://github.com/codetalcott/hyperfixi/compare/v2.8.0...v2.9.0
908
+ [2.8.0]: https://github.com/codetalcott/hyperfixi/compare/v2.5.1...v2.8.0
909
+ [2.5.1]: https://github.com/codetalcott/hyperfixi/compare/v2.5.0...v2.5.1
910
+ [2.5.0]: https://github.com/codetalcott/hyperfixi/compare/v2.4.0...v2.5.0
911
+ [2.4.0]: https://github.com/codetalcott/hyperfixi/compare/v2.3.1...v2.4.0
912
+ [2.3.1]: https://github.com/codetalcott/hyperfixi/compare/v2.3.0...v2.3.1
913
+ [2.3.0]: https://github.com/codetalcott/hyperfixi/compare/v2.2.1...v2.3.0
914
+ [2.2.1]: https://github.com/codetalcott/hyperfixi/compare/v2.2.0...v2.2.1
915
+ [2.2.0]: https://github.com/codetalcott/hyperfixi/compare/v2.1.0...v2.2.0
916
+ [2.1.0]: https://github.com/codetalcott/hyperfixi/compare/v2.0.0...v2.1.0
917
+ [2.0.0]: https://github.com/codetalcott/hyperfixi/compare/v1.4.0...v2.0.0
918
+ [1.4.0]: https://github.com/codetalcott/hyperfixi/compare/v1.3.0...v1.4.0
919
+ [1.3.0]: https://github.com/codetalcott/hyperfixi/compare/v1.2.0...v1.3.0
920
+ [1.2.0]: https://github.com/codetalcott/hyperfixi/compare/v1.0.0...v1.2.0
921
+ [1.0.0]: https://github.com/codetalcott/hyperfixi/releases/tag/v1.0.0