@adia-ai/a2ui-compose 0.5.2 → 0.5.3
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.
- package/CHANGELOG.md +23 -0
- package/package.json +1 -1
- package/strategies/registry.js +27 -0
- package/strategies/zettel/composition-library.js +11 -1
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,29 @@ generator graph.
|
|
|
12
12
|
|
|
13
13
|
_No pending changes._
|
|
14
14
|
|
|
15
|
+
## [0.5.3] - 2026-05-14
|
|
16
|
+
|
|
17
|
+
### Fixed — Deterministic chunk-loading order in zettel composition library (§160, v0.5.3)
|
|
18
|
+
|
|
19
|
+
`strategies/zettel/composition-library.js`: `walk()` now sorts `fs.readdirSync` output via `localeCompare` before recursing. Pre-§160 the directory walker relied on filesystem-defined entry order, which varies across processes on APFS/ext4. When two chunks tied on retrieval score for a given intent, the first-loaded won the tie-break — so the same intent could match chunk A in one process and chunk B in the next.
|
|
20
|
+
|
|
21
|
+
Surfaced as ~40% flake rate on the `admin dashboard with kpi cards` retrieval probe post-§143 (the 8 new UI-primitive chunks compete with the original `dashboard-kpi-grid` template). Sorted walk pins load order; remaining flakiness is now constrained to a corpus-quality bug (Stat chunks strip `label`/`value`/`change` attrs in the `template` field) tracked as v0.5.4 F-S1a.
|
|
22
|
+
|
|
23
|
+
No behavior change for callers that don't hit a tie-break — most intents have a clear retrieval winner.
|
|
24
|
+
|
|
25
|
+
### Deprecated — `_debug.attempts` and `_debug.warnings` on free-form-composed results (§146, v0.5.3)
|
|
26
|
+
|
|
27
|
+
Finalizes the v0.6.0 deprecation schedule for the last two `_debug.*` fields that consumers might still read on `generateFreeFormAdapter`'s result. Both fields are dialog-recorder-gated (silently `undefined` when not recording) — the same access pattern §109 (v0.5.1) + §107a (v0.5.2) removed for `usedIngredients` / `rationale` / `plan`.
|
|
28
|
+
|
|
29
|
+
**v0.6.0 migration path** (folded into the inline `@deprecated` JSDoc on `strategies/registry.js`):
|
|
30
|
+
|
|
31
|
+
- `result._debug?.attempts` → `result.attempts: number` (LLM round-trips: 1 normally; 2-3 with hallucination retry or paraphrase-retry)
|
|
32
|
+
- `result._debug?.warnings` → `result.warnings: string[]` (non-fatal transpile findings: unknown substitution keys, layout-value fall-throughs, chunk-resolution warns)
|
|
33
|
+
|
|
34
|
+
**Scheduled removal**: v0.6.0 drops the `_debug` block entirely from the free-form-composed result shape. The dialog-recorder will read first-class fields directly. v0.5.3 is the **migration window** — any external consumers reading `_debug.attempts` / `_debug.warnings` should switch to the first-class fields before v0.6.0 ships.
|
|
35
|
+
|
|
36
|
+
**Internal verification**: zero live in-repo consumers (`grep -rn '_debug\?\.attempts\|_debug\.attempts\|_debug\?\.warnings\|_debug\.warnings' apps/ playgrounds/ catalog/ packages/` returns only the deprecation comment itself).
|
|
37
|
+
|
|
15
38
|
## [0.5.2] - 2026-05-13
|
|
16
39
|
|
|
17
40
|
### Changed — `plan` graduates from `_debug.*` to first-class on free-form-composed result (§107a infra, v0.5.2)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adia-ai/a2ui-compose",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "AdiaUI A2UI compose engine — framework-agnostic. Takes natural-language intents + a catalog and produces A2UI protocol messages. Pairs with `@adia-ai/a2ui-retrieval` (intent classification, catalog lookup) and `@adia-ai/a2ui-validator` (schema + semantic checks).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
package/strategies/registry.js
CHANGED
|
@@ -191,6 +191,33 @@ async function generateFreeFormAdapter(ctx) {
|
|
|
191
191
|
// were removed by §109 / §107a; this block is now strictly debug-
|
|
192
192
|
// recorder fodder. Scheduled removal: v0.6.0 will fold `attempts` +
|
|
193
193
|
// `warnings` into first-class result fields and drop `_debug` here.
|
|
194
|
+
//
|
|
195
|
+
// §146 (v0.5.3): finalize the v0.6.0 deprecation schedule for the
|
|
196
|
+
// last two `_debug.*` fields that any consumer might still read.
|
|
197
|
+
//
|
|
198
|
+
// @deprecated `_debug.attempts` and `_debug.warnings` — both fields
|
|
199
|
+
// are dialog-recorder-gated (silently `undefined` when not
|
|
200
|
+
// recording), which is exactly the access pattern §109+§107a
|
|
201
|
+
// removed for `usedIngredients`/`rationale`/`plan`. v0.6.0 folds
|
|
202
|
+
// both into first-class result fields:
|
|
203
|
+
//
|
|
204
|
+
// - `result.attempts: number` — number of LLM round-trips taken
|
|
205
|
+
// to produce the final plan (1 normally; 2-3 with hallucination
|
|
206
|
+
// retry or paraphrase-retry; same value as §106's loop counter)
|
|
207
|
+
// - `result.warnings: string[]` — non-fatal transpile findings
|
|
208
|
+
// (unknown substitution keys, layout-value fall-throughs,
|
|
209
|
+
// chunk-resolution warns); same value as transpilePlan output
|
|
210
|
+
//
|
|
211
|
+
// Consumers should switch reads from `result._debug?.attempts` →
|
|
212
|
+
// `result.attempts` and `result._debug?.warnings` → `result.warnings`
|
|
213
|
+
// before v0.6.0 ships. The `_debug` block itself disappears from
|
|
214
|
+
// the free-form-composed result shape entirely in v0.6.0; the
|
|
215
|
+
// dialog-recorder will read first-class fields directly.
|
|
216
|
+
//
|
|
217
|
+
// No in-repo consumers currently read these fields (verified
|
|
218
|
+
// `grep -rn '_debug\?.attempts\|_debug.attempts\|_debug\?.warnings\|_debug.warnings'
|
|
219
|
+
// apps/ playgrounds/ catalog/ packages/` → 0 hits at v0.5.3 cut).
|
|
220
|
+
// External consumers should treat v0.6.0 as the migration window.
|
|
194
221
|
_debug: isRecording() ? {
|
|
195
222
|
systemPrompt: null,
|
|
196
223
|
rawLLMResponse: null,
|
|
@@ -101,7 +101,17 @@ async function _loadAllNode() {
|
|
|
101
101
|
|
|
102
102
|
function walk(dir, cb) {
|
|
103
103
|
if (!fs.existsSync(dir)) return;
|
|
104
|
-
|
|
104
|
+
// §160 (v0.5.3, F-S1 root cause): sort readdir output. fs.readdirSync
|
|
105
|
+
// returns entries in filesystem-defined order (variable across
|
|
106
|
+
// processes on APFS/ext4), which means chunk-loading order varied
|
|
107
|
+
// run-to-run. When two chunks tied on score for a given intent, the
|
|
108
|
+
// first-loaded won the tie-break — so the same intent could match
|
|
109
|
+
// chunk A in one process and chunk B in the next. Surfaced as
|
|
110
|
+
// ~40% probe-failure rate on admin-dashboard post-§143 (the new
|
|
111
|
+
// chunks compete with the original 4-row KPI composition).
|
|
112
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true })
|
|
113
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
114
|
+
for (const entry of entries) {
|
|
105
115
|
const p = path.join(dir, entry.name);
|
|
106
116
|
if (entry.isDirectory()) walk(p, cb);
|
|
107
117
|
else if (entry.name.endsWith('.json') && !entry.name.startsWith('_')) cb(p);
|