@adia-ai/gen-ui 0.8.62 → 0.8.63
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 +25 -0
- package/compose/core/generator.js +12 -0
- package/compose/strategies/_shared/surface-id.js +19 -0
- package/compose/strategies/free-form-composer/transpile.js +3 -1
- package/compose/strategies/monolithic/_shared.js +5 -4
- package/compose/strategies/monolithic/generate-instant.js +3 -2
- package/compose/strategies/registry.js +12 -2
- package/compose/strategies/zettel/chunk-refiner.js +1 -1
- package/compose/strategies/zettel/generator-adapter.js +35 -20
- package/corpus/chunks/_output-hashes.json +1 -1
- package/corpus/chunks/_source-hashes.json +2 -2
- package/package.json +1 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog — @adia-ai/gen-ui
|
|
2
2
|
|
|
3
|
+
## [0.8.63] — 2026-09-12
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- chore: BREAKING, remove the deprecated `./compose/evals` export alias (ticket 4299, ADR-0098 retirement path) (#4386)
|
|
8
|
+
The one-release deprecation window LLD-3751 opened for the `@adia-ai/gen-ui/compose/evals`
|
|
9
|
+
subpath alias (introduced by commit `76789d172`, first carried by `0.8.61`, after `0.8.60`
|
|
10
|
+
shipped with the original non-aliased path) has closed: `0.8.62`, the release after `0.8.61`,
|
|
11
|
+
is published. The `./compose/evals` export entry is removed from the engine
|
|
12
|
+
`package.json`'s `exports` map outright, no successor alias; `@adia-ai/gen-ui/evals` is the
|
|
13
|
+
sole subpath. This completes the MIGRATION GUIDE lifecycle LLD-3751 started rather than
|
|
14
|
+
opening a new one: `.claude/docs/MIGRATION GUIDE.md` gains a "Shipped" entry documenting the
|
|
15
|
+
closure (the original alias-introduction entry stays as historical record, matching this
|
|
16
|
+
repo's own admin-page/admin-scroll ADR-0098 removal precedent), and its generated
|
|
17
|
+
`packages/web-components/MIGRATION.md` copy is resynced. No in-repo consumer still imported
|
|
18
|
+
the old subpath.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- fix: core/generator.js's streaming path now substitutes fallbackMessage() when validateSchema flags isRawText, matching generate-pro.js/generate-thinking.js, so a raw-text leak surviving the repair loop on that path no longer reaches the canvas verbatim (ticket 10028) (local ticket 10028)
|
|
23
|
+
- fix: every producer strategy (zettel, chunk-zettel, free-form-composer, monolithic) now imports one shared `SURFACE_ID` constant instead of three disagreeing literals (`'default'`, `'main'`, or none at all), closing a hole where a zero-named-surface or mismatched-surfaceId doc fell outside a2ui-root's single-surface inference and tore down its own throwaway surface, taking `<a2ui-root>` itself out of the DOM (ticket 10037) (local ticket 10037)
|
|
24
|
+
|
|
25
|
+
### Maintenance
|
|
26
|
+
- **`corpus/` touched in this release window** (2 file(s), e.g. `chunks/_output-hashes.json`): carried by the entries above.
|
|
27
|
+
|
|
3
28
|
## [0.8.62] — 2026-09-10
|
|
4
29
|
|
|
5
30
|
### Changed
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
buildRepairPrompt,
|
|
39
39
|
generateSuggestions,
|
|
40
40
|
foldInAntiPatterns,
|
|
41
|
+
fallbackMessage,
|
|
41
42
|
} from '../strategies/monolithic/_shared.js';
|
|
42
43
|
import { validateAndRepair } from '../shared/validate-and-repair.js';
|
|
43
44
|
import { generateInstant } from '../strategies/monolithic/generate-instant.js';
|
|
@@ -551,6 +552,17 @@ export async function* generateUIStream({ intent, executionId, llmAdapter, model
|
|
|
551
552
|
});
|
|
552
553
|
messages = repairResult.messages;
|
|
553
554
|
let validation = repairResult.validation;
|
|
555
|
+
// ticket 10028: this streaming path parses raw LLM text via
|
|
556
|
+
// parseA2UIResponse the same way generate-pro.js/generate-thinking.js do,
|
|
557
|
+
// so it is exposed to the same raw-text-leak surface `isRawText` flags,
|
|
558
|
+
// but unlike those two engines, it never substituted fallbackMessage(),
|
|
559
|
+
// so a leak surviving the repair loop here would have reached the wire
|
|
560
|
+
// verbatim instead of the same honest failure card every other engine
|
|
561
|
+
// shows.
|
|
562
|
+
if (validation.isRawText) {
|
|
563
|
+
messages = fallbackMessage('Generation produced unstructured raw text instead of a UI', { executionId, intent, mode: 'stream' });
|
|
564
|
+
validation = validateSchema(messages, { intent, context });
|
|
565
|
+
}
|
|
554
566
|
if (repairResult.attempts > 0) {
|
|
555
567
|
yield { type: 'status', stage: 'validate', message: `Score ${validation.score}/100 — repaired in ${repairResult.attempts} attempt(s)` };
|
|
556
568
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// gh#10037: the ONE canonical surfaceId every gen-ui producer strategy must
|
|
2
|
+
// target for its single-surface output. Before this module existed, three
|
|
3
|
+
// different literals were in play across the roster:
|
|
4
|
+
// - monolithic (generate-instant.js, _shared.js): 'default'
|
|
5
|
+
// - zettel's chunk-refiner.js (the chunk-zettel iteration path): 'main'
|
|
6
|
+
// - free-form-composer/transpile.js: 'main'
|
|
7
|
+
// - zettel's generator-adapter.js (pre-fix): no surfaceId at all
|
|
8
|
+
//
|
|
9
|
+
// A doc's messages must agree on which surface they target across turns:
|
|
10
|
+
// handleAuto.js reads the PRIOR turn's own surfaceId back off
|
|
11
|
+
// state.allMessages to decide whether to bracket a regenerate
|
|
12
|
+
// (beginSurfaceUpdate) or fall back to a full replaceDoc. A mismatched or
|
|
13
|
+
// missing surfaceId between two turns' engines defeats that entirely: the
|
|
14
|
+
// new doc never declares the surface the prior turn created, so
|
|
15
|
+
// a2ui-root.js's replaceDoc() tears the prior surface down as undeclared
|
|
16
|
+
// (packages/gen-ui/a2ui/renderer.js's #deleteSurface). One shared constant,
|
|
17
|
+
// imported everywhere a producer strategy builds an A2UI message, closes
|
|
18
|
+
// that gap for every present and future tier at once.
|
|
19
|
+
export const SURFACE_ID = 'default';
|
|
@@ -53,6 +53,8 @@
|
|
|
53
53
|
* - Structural substitutions (swap Card → Section, etc.).
|
|
54
54
|
*/
|
|
55
55
|
|
|
56
|
+
import { SURFACE_ID } from '../_shared/surface-id.js';
|
|
57
|
+
|
|
56
58
|
const VALID_LAYOUTS = new Set(['column', 'row', 'grid']);
|
|
57
59
|
|
|
58
60
|
/**
|
|
@@ -190,7 +192,7 @@ export function transpilePlan(plan, chunkLookup) {
|
|
|
190
192
|
return {
|
|
191
193
|
messages: [{
|
|
192
194
|
type: 'updateComponents',
|
|
193
|
-
surfaceId:
|
|
195
|
+
surfaceId: SURFACE_ID,
|
|
194
196
|
components: [root, ...flatComponents],
|
|
195
197
|
}],
|
|
196
198
|
warnings,
|
|
@@ -16,6 +16,7 @@ import { composeSubtasks } from '../../../retrieval/intent/decomposer.js';
|
|
|
16
16
|
import { getWiringCatalog } from '../../../retrieval/wiring-catalog.js';
|
|
17
17
|
import { getComponentData } from '../../../retrieval/component-catalog.js';
|
|
18
18
|
import { assessIterationFidelity } from '../../shared/iteration-fidelity.js';
|
|
19
|
+
import { SURFACE_ID } from '../_shared/surface-id.js';
|
|
19
20
|
|
|
20
21
|
// ── v0.9 .a2ui.json sidecar → prompt-catalog adapter ─────────────
|
|
21
22
|
//
|
|
@@ -1217,14 +1218,14 @@ function wrapAsMessages(parsed) {
|
|
|
1217
1218
|
if (parsed.length > 0 && validTypes.has(parsed[0].type)) return parsed;
|
|
1218
1219
|
// Bare components array
|
|
1219
1220
|
if (parsed.length > 0 && parsed[0].id && parsed[0].component) {
|
|
1220
|
-
return [{ type: 'updateComponents', surfaceId:
|
|
1221
|
+
return [{ type: 'updateComponents', surfaceId: SURFACE_ID, components: parsed }];
|
|
1221
1222
|
}
|
|
1222
1223
|
return parsed;
|
|
1223
1224
|
}
|
|
1224
1225
|
if (parsed && typeof parsed === 'object' && parsed.type === 'updateComponents') return [parsed];
|
|
1225
1226
|
if (parsed && typeof parsed === 'object' && parsed.type === 'wireComponents') return [parsed];
|
|
1226
1227
|
if (parsed && typeof parsed === 'object' && parsed.id && parsed.component) {
|
|
1227
|
-
return [{ type: 'updateComponents', surfaceId:
|
|
1228
|
+
return [{ type: 'updateComponents', surfaceId: SURFACE_ID, components: [parsed] }];
|
|
1228
1229
|
}
|
|
1229
1230
|
return null;
|
|
1230
1231
|
}
|
|
@@ -1531,7 +1532,7 @@ export function fallbackMessage(reason, opts = {}) {
|
|
|
1531
1532
|
|
|
1532
1533
|
const updateMsg = {
|
|
1533
1534
|
type: 'updateComponents',
|
|
1534
|
-
surfaceId:
|
|
1535
|
+
surfaceId: SURFACE_ID,
|
|
1535
1536
|
// Marker so validators / scorers / consumers can detect that this is a
|
|
1536
1537
|
// generation-failure surface (NOT a successful UI). Without this, the
|
|
1537
1538
|
// validator was scoring fallbacks ~89/100 because they're structurally
|
|
@@ -1558,7 +1559,7 @@ export function fallbackMessage(reason, opts = {}) {
|
|
|
1558
1559
|
|
|
1559
1560
|
const wireMsg = {
|
|
1560
1561
|
type: 'wireComponents',
|
|
1561
|
-
surfaceId:
|
|
1562
|
+
surfaceId: SURFACE_ID,
|
|
1562
1563
|
actions,
|
|
1563
1564
|
};
|
|
1564
1565
|
|
|
@@ -12,6 +12,7 @@ import { assessClarity } from '../../../retrieval/intent/clarity.js';
|
|
|
12
12
|
import { feedbackStore } from '../../../retrieval/feedback/feedback-store.js';
|
|
13
13
|
import { store, engine } from '../../core/state.js';
|
|
14
14
|
import { isRecording } from '../../../retrieval/feedback/dialog-recorder.js';
|
|
15
|
+
import { SURFACE_ID } from '../_shared/surface-id.js';
|
|
15
16
|
import {
|
|
16
17
|
generateSuggestions, foldInAntiPatterns } from './_shared.js';
|
|
17
18
|
|
|
@@ -156,7 +157,7 @@ export async function generateInstant({ intent, executionId, storeId, analysis,
|
|
|
156
157
|
const messages = [
|
|
157
158
|
{
|
|
158
159
|
type: 'updateComponents',
|
|
159
|
-
surfaceId:
|
|
160
|
+
surfaceId: SURFACE_ID,
|
|
160
161
|
components,
|
|
161
162
|
...(isPlaceholderStub ? {
|
|
162
163
|
_fallback: true,
|
|
@@ -169,7 +170,7 @@ export async function generateInstant({ intent, executionId, storeId, analysis,
|
|
|
169
170
|
if (bestMatch?.wiring) {
|
|
170
171
|
messages.push({
|
|
171
172
|
type: 'wireComponents',
|
|
172
|
-
surfaceId:
|
|
173
|
+
surfaceId: SURFACE_ID,
|
|
173
174
|
...(bestMatch.wiring.data_sources ? { data: { sources: bestMatch.wiring.data_sources } } : {}),
|
|
174
175
|
...(bestMatch.wiring.controllers ? { state: { controllers: bestMatch.wiring.controllers } } : {}),
|
|
175
176
|
...(bestMatch.wiring.actions ? { actions: bestMatch.wiring.actions } : {}),
|
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
* { executionId, messages, validation, suggestions?, strategy?, ... }
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
// Pure constant, no node:fs/node:path deps, safe to static-import even
|
|
22
|
+
// though the strategies that use it (zettel, chunk-zettel) are lazy-loaded
|
|
23
|
+
// below for browser-safety reasons that don't apply to this module.
|
|
24
|
+
import { SURFACE_ID } from './_shared/surface-id.js';
|
|
25
|
+
|
|
21
26
|
// Zettel is lazy-loaded — it transitively imports node:fs / node:path / node:url
|
|
22
27
|
// (strategies/zettel/composition-library.js), which Vite externalizes in the browser.
|
|
23
28
|
// Static-importing it here would break browser loads of core/generator.js.
|
|
@@ -324,10 +329,15 @@ async function generateChunkZettelAdapter(ctx) {
|
|
|
324
329
|
// use it directly; the pre-fix fallback (a single node carrying an
|
|
325
330
|
// UNREGISTERED `component: 'article'` type) only fires if transpilation
|
|
326
331
|
// itself somehow produced nothing, which should not happen in practice.
|
|
332
|
+
// gh#10037: this adapter's two branches used to omit `surfaceId`
|
|
333
|
+
// entirely, the same defect fixed in zettel/generator-adapter.js: a
|
|
334
|
+
// doc naming zero surfaces falls outside a2ui-root.js's single-surface
|
|
335
|
+
// inference and tears down its own throwaway surface on regenerate,
|
|
336
|
+
// taking the <a2ui-root> host element with it.
|
|
327
337
|
const messages = result.template
|
|
328
|
-
? [{ type: 'updateComponents', components: result.template }]
|
|
338
|
+
? [{ type: 'updateComponents', surfaceId: SURFACE_ID, components: result.template }]
|
|
329
339
|
: result.html
|
|
330
|
-
? [{ type: 'updateComponents', components: [{ id: 'chunk-root', component: 'article', html: result.html }] }]
|
|
340
|
+
? [{ type: 'updateComponents', surfaceId: SURFACE_ID, components: [{ id: 'chunk-root', component: 'article', html: result.html }] }]
|
|
331
341
|
: [];
|
|
332
342
|
|
|
333
343
|
// Full schema/catalog/anti-pattern conformance — the same final pass
|
|
@@ -27,10 +27,10 @@ import {
|
|
|
27
27
|
searchChunksAsync,
|
|
28
28
|
} from '../../../corpus/scripts/chunk-library.js';
|
|
29
29
|
import { composeFromPlan } from './chunk-composer.js';
|
|
30
|
+
import { SURFACE_ID } from '../_shared/surface-id.js';
|
|
30
31
|
|
|
31
32
|
const DEFAULT_MAX_ATTEMPTS = 2;
|
|
32
33
|
const PRE_SEARCH_LIMIT = 30;
|
|
33
|
-
const SURFACE_ID = 'main';
|
|
34
34
|
|
|
35
35
|
const VALID_OP_TYPES = new Set(['rebindSlot', 'appendToSlot', 'removeFromSlot', 'replacePage']);
|
|
36
36
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generator adapter for zettel MCP
|
|
2
|
+
* Generator adapter for zettel MCP: conforms to the eval harness contract:
|
|
3
3
|
*
|
|
4
4
|
* generate({ intent, mode, llmAdapter, sessionId, signal }) -> { messages, validation, strategy, ...extra }
|
|
5
5
|
*
|
|
6
6
|
* Two reasoning layers (post-§195, v0.5.6):
|
|
7
|
-
* 1. Retrieval (always available)
|
|
8
|
-
* 2. LLM synthesis (when llmAdapter provided AND retrieval weak)
|
|
7
|
+
* 1. Retrieval (always available) , keyword-rank the corpus, resolve top composition.
|
|
8
|
+
* 2. LLM synthesis (when llmAdapter provided AND retrieval weak) , bridge to
|
|
9
9
|
* chunk-zettel's `composeFromIntent` (the §37 successor codepath) which
|
|
10
10
|
* produces a single-shot html composition from the chunk corpus.
|
|
11
11
|
*
|
|
@@ -13,19 +13,19 @@
|
|
|
13
13
|
* are recorded for analytics + drift tracking, but turn≥2 takes the same code
|
|
14
14
|
* path as turn 1 (fresh retrieval → fresh synthesis). Full history-aware
|
|
15
15
|
* iteration (multi-turn refinement modifying an existing canvas) lives in the
|
|
16
|
-
* `chunk-zettel` engine via `chunk-refiner.js::refineFromIntent`
|
|
16
|
+
* `chunk-zettel` engine via `chunk-refiner.js::refineFromIntent` , wire it via
|
|
17
17
|
* `engine: 'chunk-zettel'` rather than `engine: 'zettel'`.
|
|
18
18
|
*
|
|
19
19
|
* The prior fragment-graph iteration codepath (`synthesizeComposition` with
|
|
20
20
|
* `historySummary`) was retired in §37 (2026-05-12) when fragments retired.
|
|
21
|
-
* §195 (v0.5.6) cleaned up the dangling caller
|
|
21
|
+
* §195 (v0.5.6) cleaned up the dangling caller , turn≥2 no longer throws +
|
|
22
22
|
* auto-fires a `iteration-synthesis-failure` issue on every multi-turn turn.
|
|
23
23
|
*
|
|
24
24
|
* Strategy labels in the return:
|
|
25
|
-
* - composition-match
|
|
26
|
-
* - composition-synthesized
|
|
27
|
-
* - fragment-candidates
|
|
28
|
-
* - synthesis-failed
|
|
25
|
+
* - composition-match , fresh retrieval, strong match, emitted verbatim
|
|
26
|
+
* - composition-synthesized , chunk-zettel single-shot synthesis
|
|
27
|
+
* - fragment-candidates , retrieval weak + no LLM, returning atoms only
|
|
28
|
+
* - synthesis-failed , chunk-zettel tried and failed validation
|
|
29
29
|
*/
|
|
30
30
|
import {
|
|
31
31
|
getComposition,
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
getTurns,
|
|
39
39
|
} from './session-store.js';
|
|
40
40
|
import { validateSchema } from '@adia-ai/a2ui/validate';
|
|
41
|
+
import { SURFACE_ID } from '../_shared/surface-id.js';
|
|
41
42
|
|
|
42
43
|
// Lazy-load the chunk-synthesizer bridge. It imports chunk-corpus data
|
|
43
44
|
// via composition-library's dual-mode loader, which is already top-level
|
|
@@ -51,13 +52,13 @@ async function bridgeToChunkSynthesis({ intent, llmAdapter, signal }) {
|
|
|
51
52
|
// to the synthesis-branch's prior `{ messages, template, synthesis }`
|
|
52
53
|
// contract. TKT-0009: prefer the real component array (`result.template`)
|
|
53
54
|
// over the pre-fix fallback of wrapping raw HTML in a single node with an
|
|
54
|
-
// UNREGISTERED `component: 'article'` type
|
|
55
|
+
// UNREGISTERED `component: 'article'` type , that fallback made this
|
|
55
56
|
// caller's validate-and-repair pass below structurally unable to ever
|
|
56
57
|
// report a clean pass.
|
|
57
58
|
const messages = result.template
|
|
58
|
-
? [{ type: 'updateComponents', components: result.template }]
|
|
59
|
+
? [{ type: 'updateComponents', surfaceId: SURFACE_ID, components: result.template }]
|
|
59
60
|
: result.html
|
|
60
|
-
? [{ type: 'updateComponents', components: [{ id: 'chunk-root', component: 'article', html: result.html }] }]
|
|
61
|
+
? [{ type: 'updateComponents', surfaceId: SURFACE_ID, components: [{ id: 'chunk-root', component: 'article', html: result.html }] }]
|
|
61
62
|
: [];
|
|
62
63
|
return {
|
|
63
64
|
messages,
|
|
@@ -74,7 +75,7 @@ async function bridgeToChunkSynthesis({ intent, llmAdapter, signal }) {
|
|
|
74
75
|
// Composition library auto-loads at module import time via top-level `await
|
|
75
76
|
// loadAll()` in composition-library.js (§72 dual-mode loader, commit
|
|
76
77
|
// `76dbcff2`). The previous `ensureBooted()` here called `loadAll()` WITHOUT
|
|
77
|
-
// `await`, which after §72 made it async
|
|
78
|
+
// `await`, which after §72 made it async , clearing the compositions map +
|
|
78
79
|
// racing the synchronous `searchAll` below. Symptom (caught in §87):
|
|
79
80
|
// eval:diff zettel coverage dropped 5% → 1% because the race-winner pattern
|
|
80
81
|
// emitted composition-match only for the intent whose `searchAll` happened
|
|
@@ -83,7 +84,7 @@ async function bridgeToChunkSynthesis({ intent, llmAdapter, signal }) {
|
|
|
83
84
|
// Fix: rely entirely on the top-level await. Tests that want a forced reload
|
|
84
85
|
// can call `loadAll()` directly with `await` (it's idempotent).
|
|
85
86
|
|
|
86
|
-
// Retrieval score threshold
|
|
87
|
+
// Retrieval score threshold , above this we trust the match and emit verbatim;
|
|
87
88
|
// below, fall through to LLM synthesis (creative composition from fragments).
|
|
88
89
|
// Calibrated on the 100-intent held-out set:
|
|
89
90
|
// strong matches: login-form=24 (exact), signup-form=27, chart-dashboard=48, pricing-tiers=54
|
|
@@ -95,9 +96,23 @@ async function bridgeToChunkSynthesis({ intent, llmAdapter, signal }) {
|
|
|
95
96
|
// threshold maximized verbatim-cache hits at the cost of repetitive output.
|
|
96
97
|
const STRONG_MATCH_THRESHOLD = 40;
|
|
97
98
|
|
|
99
|
+
// gh#10037: every emitted `updateComponents` message must name a `surfaceId`
|
|
100
|
+
// (the shared `SURFACE_ID` imported above, so every tier agrees across
|
|
101
|
+
// turns). Without it, a2ui-root.js's replaceDoc() has zero named
|
|
102
|
+
// surfaceIds to infer a sole surface from (its inference only covers the
|
|
103
|
+
// single-named-surface case, not zero), so the message ends up applied
|
|
104
|
+
// against surfaceId `undefined`, renderer.js synthesizes a throwaway
|
|
105
|
+
// surface rooted at the <a2ui-root> element itself for that write, and
|
|
106
|
+
// replaceDoc's own tear-down sweep then deletes it as undeclared, which
|
|
107
|
+
// removes a2ui-root from the DOM (renderer.js's `deleteSurface` calls
|
|
108
|
+
// `surface.root.remove()`). This is the same class of bug as gh#2426's
|
|
109
|
+
// fix in a2ui-root.js, reintroduced here on the zettel producer side of
|
|
110
|
+
// the contract instead of the consumer side.
|
|
111
|
+
|
|
98
112
|
function toUpdateComponentsMessages(template) {
|
|
99
113
|
return [{
|
|
100
114
|
type: 'updateComponents',
|
|
115
|
+
surfaceId: SURFACE_ID,
|
|
101
116
|
components: template.map((n) => {
|
|
102
117
|
const {
|
|
103
118
|
id, component, children,
|
|
@@ -114,12 +129,12 @@ export async function generateZettel({ intent, mode = 'instant', llmAdapter = nu
|
|
|
114
129
|
// ── Session iteration note (post-§195, v0.5.6) ──
|
|
115
130
|
// Fragment-graph history-aware iteration (`synthesizeComposition` with
|
|
116
131
|
// `historySummary`) was retired in §37 when fragments retired. Turn≥2 now
|
|
117
|
-
// takes the same path as turn 1
|
|
132
|
+
// takes the same path as turn 1 , fresh retrieval → fresh chunk-synthesis.
|
|
118
133
|
// For true history-aware iteration (modify-an-existing-canvas), wire the
|
|
119
134
|
// request via `engine: 'chunk-zettel'` which uses `chunk-refiner.js`.
|
|
120
135
|
//
|
|
121
136
|
// Prior turns are still recorded (analytics + drift tracking via `getDrift`)
|
|
122
|
-
// but the iteration BRANCH is gone
|
|
137
|
+
// but the iteration BRANCH is gone , no more spurious
|
|
123
138
|
// `iteration-synthesis-failure` auto-fires on every multi-turn request.
|
|
124
139
|
const priorTurns = sessionId ? getTurns(sessionId) : [];
|
|
125
140
|
|
|
@@ -127,10 +142,10 @@ export async function generateZettel({ intent, mode = 'instant', llmAdapter = nu
|
|
|
127
142
|
const composition = hits.find((h) => h.type === 'composition');
|
|
128
143
|
const strongMatch = composition && composition.score >= STRONG_MATCH_THRESHOLD;
|
|
129
144
|
|
|
130
|
-
// ── Strong retrieval match: emit verbatim (turn 1 only
|
|
145
|
+
// ── Strong retrieval match: emit verbatim (turn 1 only , iteration branch above handles repeats) ──
|
|
131
146
|
if (strongMatch) {
|
|
132
147
|
// On a static deploy the composition was registered from `_index.json`
|
|
133
|
-
// for SCORING only
|
|
148
|
+
// for SCORING only , its `template` is fetched lazily here, right before
|
|
134
149
|
// we resolve it. No-op in Node / Vite (template already populated). This
|
|
135
150
|
// keeps the static page-load to a single index request; only the
|
|
136
151
|
// actually-emitted match pays for its body. 2026-06-10.
|
|
@@ -142,7 +157,7 @@ export async function generateZettel({ intent, mode = 'instant', llmAdapter = nu
|
|
|
142
157
|
// is looser (it can't see templates in `_index.json`), so a handful of
|
|
143
158
|
// body-less partials (auth-card-header, onb-step-*, …) COULD surface as a
|
|
144
159
|
// strong match on a static deploy. If hydration produced no usable
|
|
145
|
-
// template, treat it as a non-match and fall through
|
|
160
|
+
// template, treat it as a non-match and fall through , keeping the
|
|
146
161
|
// static result identical to what Node would emit (synthesis / atoms),
|
|
147
162
|
// never an empty verbatim surface.
|
|
148
163
|
if (!Array.isArray(template) || template.length === 0) {
|
|
@@ -179,7 +194,7 @@ export async function generateZettel({ intent, mode = 'instant', llmAdapter = nu
|
|
|
179
194
|
if (llmAdapter && mode !== 'instant-only') {
|
|
180
195
|
try {
|
|
181
196
|
const synth = await bridgeToChunkSynthesis({ intent, llmAdapter, signal });
|
|
182
|
-
// Full schema/catalog/anti-pattern conformance (validate-only
|
|
197
|
+
// Full schema/catalog/anti-pattern conformance (validate-only , see
|
|
183
198
|
// validate-and-repair.js; TKT-0009 made this meaningful for the first
|
|
184
199
|
// time by giving synth.messages a real component graph instead of an
|
|
185
200
|
// opaque HTML wrapper).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "genui-chunk-output-hashes@1",
|
|
3
3
|
"algo": "sha256",
|
|
4
|
-
"capturedAt": "2026-09-
|
|
4
|
+
"capturedAt": "2026-09-13T00:34:01.593Z",
|
|
5
5
|
"aggregateDigest": "9eaca6f62e9dc45f78ebb2d22889b53071405a51a9bcd4410c737f076e57e8d3",
|
|
6
6
|
"harvestEnv": {
|
|
7
7
|
"nodeMajor": "24",
|
|
@@ -283,7 +283,7 @@
|
|
|
283
283
|
"catalog/ui-patterns/v050-marketing-blocks/v050-marketing-blocks.html": "7833b21ee84643978cd3ca0e6ff20caa20ec8cbc9a55e371aa295a532f8ed48a",
|
|
284
284
|
"catalog/ui-patterns/v050-nav-blocks/v050-nav-blocks.contents.html": "86f492db19b8aafc2bf25620f52377cd7a6cb92cfa2d0d3bc9dd4c5ade3e88c6",
|
|
285
285
|
"catalog/ui-patterns/v050-nav-blocks/v050-nav-blocks.html": "196862f06f495547d85f542e6a0eee152ab40a40ca969c93b0cbd0733de5a5e2",
|
|
286
|
-
"packages/gen-ui/a2ui/catalog/tier-index.json": "
|
|
286
|
+
"packages/gen-ui/a2ui/catalog/tier-index.json": "39372f0840c4564b24f999a01eda6f9024788011b72ead9c0c75593c70f6d799",
|
|
287
287
|
"packages/web-components/components/accordion/accordion.examples.html": "0218a098bc9db38f6ad5a73b7fbbd8755882d92f47790488928384b79b2e7868",
|
|
288
288
|
"packages/web-components/components/action-list/action-list.examples.html": "abcb4897fc8143a4c32b15bf82eb3340304cfa22d8498198328c1570102d7bc2",
|
|
289
289
|
"packages/web-components/components/adia-mark/adia-mark.examples.html": "2124ad37660d157e7a85fdc57eb7725ac02d629a76a47a58ff53703ed5b06238",
|
|
@@ -611,7 +611,7 @@
|
|
|
611
611
|
"site/pages/getting-started/usage.html": "23f477ad6e505876e36d6c774cd49acc3bb483f7e4872ea8d6d5261fdab02b4f",
|
|
612
612
|
"site/pages/guides/agent-skills.html": "647864bb9c6e43ed123c95b48201f3e55a5bb26e8a77cd0ee65ad361df47bd97",
|
|
613
613
|
"site/pages/guides/bundle-loading.html": "dc08497d9621c090e1581289ebf9a706ae05421a55dc9f20841c107969b3b829",
|
|
614
|
-
"site/pages/guides/bundle-sizes.html": "
|
|
614
|
+
"site/pages/guides/bundle-sizes.html": "b8b067e5e3c89bfb6ea809a971a5a7d13816b27f550a8a9e391dafa2d4421551",
|
|
615
615
|
"site/pages/guides/creating-components.html": "f34020a12d91a0239b6303e32b3c39ecc47d7a96ccfa7ff10fc12e313065a5d6",
|
|
616
616
|
"site/pages/guides/css-architecture.html": "42b4258cefc5f98d3b1297362aa090fe1310b92032871fc3144b33a42f03f331",
|
|
617
617
|
"site/pages/guides/data-flow.html": "c1965674271df66cfebf95eb012048996fc8c844179fcb1816d49aae98621219",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adia-ai/gen-ui",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.63",
|
|
4
4
|
"description": "AdiaUI generative-UI system — compose strategies, retrieval, the harvested training corpus, and catalog-aware + LLM-judge validation. Emits A2UI protocol messages; pairs with @adia-ai/a2ui (the protocol runtime). Folded from @adia-ai/a2ui-{compose,retrieval,corpus} + the catalog/semantic halves of the former @adia-ai/a2ui-validator (ADR-0048).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./compose/index.js",
|
|
@@ -45,11 +45,6 @@
|
|
|
45
45
|
"import": "./compose/transpiler/transpiler.js",
|
|
46
46
|
"default": "./compose/transpiler/transpiler.js"
|
|
47
47
|
},
|
|
48
|
-
"./compose/evals": {
|
|
49
|
-
"types": "./evals/harness.d.ts",
|
|
50
|
-
"import": "./evals/harness.mjs",
|
|
51
|
-
"default": "./evals/harness.mjs"
|
|
52
|
-
},
|
|
53
48
|
"./evals": {
|
|
54
49
|
"types": "./evals/harness.d.ts",
|
|
55
50
|
"import": "./evals/harness.mjs",
|