@adia-ai/gen-ui 0.8.37
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 +26 -0
- package/README.md +77 -0
- package/compose/CHANGELOG.md +1707 -0
- package/compose/README.md +215 -0
- package/compose/core/artifacts.js +262 -0
- package/compose/core/context-store.js +218 -0
- package/compose/core/generator.d.ts +4 -0
- package/compose/core/generator.js +602 -0
- package/compose/core/pipeline/engine.js +289 -0
- package/compose/core/pipeline/types.js +91 -0
- package/compose/core/plan-primitives.js +120 -0
- package/compose/core/plan-turn.js +145 -0
- package/compose/core/reference.js +150 -0
- package/compose/core/state.js +15 -0
- package/compose/evals/harness.d.ts +4 -0
- package/compose/evals/harness.mjs +193 -0
- package/compose/index.d.ts +4 -0
- package/compose/index.js +16 -0
- package/compose/shared/validate-and-repair.js +122 -0
- package/compose/strategies/_shared/chunk-loader.js +282 -0
- package/compose/strategies/cascade.d.ts +67 -0
- package/compose/strategies/cascade.js +165 -0
- package/compose/strategies/escalation.d.ts +13 -0
- package/compose/strategies/escalation.js +132 -0
- package/compose/strategies/free-form-composer/index.js +254 -0
- package/compose/strategies/free-form-composer/system-prompt.js +205 -0
- package/compose/strategies/free-form-composer/transpile.js +279 -0
- package/compose/strategies/monolithic/_shared.js +1619 -0
- package/compose/strategies/monolithic/generate-instant.js +228 -0
- package/compose/strategies/monolithic/generate-pro.js +490 -0
- package/compose/strategies/monolithic/generate-thinking.js +206 -0
- package/compose/strategies/registry.d.ts +20 -0
- package/compose/strategies/registry.js +495 -0
- package/compose/strategies/zettel/_smoke.js +27 -0
- package/compose/strategies/zettel/chunk-composer.js +214 -0
- package/compose/strategies/zettel/chunk-refiner.js +582 -0
- package/compose/strategies/zettel/chunk-synthesizer.js +458 -0
- package/compose/strategies/zettel/composer.js +78 -0
- package/compose/strategies/zettel/composition-library.js +418 -0
- package/compose/strategies/zettel/generate.js +15 -0
- package/compose/strategies/zettel/generator-adapter.d.ts +4 -0
- package/compose/strategies/zettel/generator-adapter.js +242 -0
- package/compose/strategies/zettel/issue-reporter.js +607 -0
- package/compose/strategies/zettel/session-store.js +121 -0
- package/compose/strategies/zettel/state-cache.js +158 -0
- package/compose/transpiler/transpiler-maps.js +675 -0
- package/compose/transpiler/transpiler.d.ts +4 -0
- package/compose/transpiler/transpiler.js +962 -0
- package/corpus/CHANGELOG.md +1957 -0
- package/corpus/README.md +279 -0
- package/corpus/catalog-a2ui_0_9.d.ts +4 -0
- package/corpus/catalog-a2ui_0_9.json +29571 -0
- package/corpus/catalog-a2ui_0_9_rules.txt +1215 -0
- package/corpus/chunk-embeddings.d.ts +4 -0
- package/corpus/chunk-embeddings.json +1 -0
- package/corpus/chunks/_index.json +16658 -0
- package/corpus/chunks/_source-hashes.json +571 -0
- package/corpus/chunks/access-denied-with-request.json +124 -0
- package/corpus/chunks/access-request-form.json +166 -0
- package/corpus/chunks/access-request-pending.json +133 -0
- package/corpus/chunks/accordion-settings.json +176 -0
- package/corpus/chunks/achievement-badges.json +413 -0
- package/corpus/chunks/achievement-unlock.json +104 -0
- package/corpus/chunks/action-list-record-actions.json +84 -0
- package/corpus/chunks/activity-feed.json +390 -0
- package/corpus/chunks/admin-page-header-flush.json +83 -0
- package/corpus/chunks/admin-page-header-title-description.json +80 -0
- package/corpus/chunks/admin-page-header-with-actions.json +107 -0
- package/corpus/chunks/admin-page-header-with-tabs.json +144 -0
- package/corpus/chunks/admin-shell-rounded-borderless.json +287 -0
- package/corpus/chunks/admin-shell-standard.json +310 -0
- package/corpus/chunks/admin-sidebar-brand-signin.json +158 -0
- package/corpus/chunks/admin-sidebar-brand-version.json +130 -0
- package/corpus/chunks/admin-sidebar-flat-nav.json +131 -0
- package/corpus/chunks/admin-sidebar-nav-dividers.json +150 -0
- package/corpus/chunks/admin-sidebar-nav-groups.json +171 -0
- package/corpus/chunks/admin-sidebar-workspace-switcher.json +139 -0
- package/corpus/chunks/admin-topbar-breadcrumb-actions.json +130 -0
- package/corpus/chunks/admin-topbar-breadcrumb-minimal.json +79 -0
- package/corpus/chunks/admin-topbar-deep-breadcrumb.json +129 -0
- package/corpus/chunks/admin-topbar-search.json +104 -0
- package/corpus/chunks/admin-topbar-status-indicator.json +122 -0
- package/corpus/chunks/admin-topbar-trailing-toggle.json +114 -0
- package/corpus/chunks/agent-activity-feed.json +163 -0
- package/corpus/chunks/agent-artifact-stub-card.json +115 -0
- package/corpus/chunks/agent-canvas-shell.json +305 -0
- package/corpus/chunks/agent-citations-source-chips.json +82 -0
- package/corpus/chunks/agent-command-palette-search.json +120 -0
- package/corpus/chunks/agent-cost-detailed.json +260 -0
- package/corpus/chunks/agent-cost-inline.json +78 -0
- package/corpus/chunks/agent-memory-detail.json +181 -0
- package/corpus/chunks/agent-memory-editor.json +173 -0
- package/corpus/chunks/agent-memory-list.json +207 -0
- package/corpus/chunks/agent-pipeline-status-stages.json +61 -0
- package/corpus/chunks/agent-prompt-card.json +179 -0
- package/corpus/chunks/agent-prompt-library-grid.json +341 -0
- package/corpus/chunks/agent-prompt-picker.json +282 -0
- package/corpus/chunks/agent-rate-limit.json +100 -0
- package/corpus/chunks/agent-reasoning-collapsed.json +128 -0
- package/corpus/chunks/agent-tool-call-accordion.json +109 -0
- package/corpus/chunks/agent-tool-call-collapsed.json +98 -0
- package/corpus/chunks/agent-tool-call-error.json +112 -0
- package/corpus/chunks/agent-tool-call-result.json +145 -0
- package/corpus/chunks/agent-tool-call-running.json +85 -0
- package/corpus/chunks/agent-tool-call-success.json +137 -0
- package/corpus/chunks/agent-trace-timeline.json +244 -0
- package/corpus/chunks/ai-streaming-response.json +147 -0
- package/corpus/chunks/alert-banner-stack.json +78 -0
- package/corpus/chunks/alert-banner.json +55 -0
- package/corpus/chunks/alert-dialog-simple.json +72 -0
- package/corpus/chunks/alert-dialog-typed.json +107 -0
- package/corpus/chunks/alert-dialog-unsaved.json +81 -0
- package/corpus/chunks/analytics-chart.json +213 -0
- package/corpus/chunks/analytics-sparklines-dashboard.json +259 -0
- package/corpus/chunks/anchor-bar-selection-bar.json +226 -0
- package/corpus/chunks/api-key-table.json +148 -0
- package/corpus/chunks/api-keys-create.json +140 -0
- package/corpus/chunks/api-keys-list.json +271 -0
- package/corpus/chunks/app-nav-badges-counts.json +77 -0
- package/corpus/chunks/app-nav-badges-group-rollup-badges.json +100 -0
- package/corpus/chunks/app-nav-badges-plan-tiers.json +76 -0
- package/corpus/chunks/app-nav-badges-status-callouts.json +75 -0
- package/corpus/chunks/app-nav-full-example.json +195 -0
- package/corpus/chunks/app-nav-groups.json +103 -0
- package/corpus/chunks/app-nav-items.json +74 -0
- package/corpus/chunks/app-nav-labels-and-dividers.json +92 -0
- package/corpus/chunks/app-nav-spacer.json +77 -0
- package/corpus/chunks/app-product-listing-card.json +214 -0
- package/corpus/chunks/approvals-detail.json +240 -0
- package/corpus/chunks/approvals-queue.json +321 -0
- package/corpus/chunks/audit-log-basic.json +184 -0
- package/corpus/chunks/audit-log.json +174 -0
- package/corpus/chunks/auth-account-deleted-actions.json +51 -0
- package/corpus/chunks/auth-account-deleted.json +202 -0
- package/corpus/chunks/auth-card-content.json +260 -0
- package/corpus/chunks/auth-card-header.json +205 -0
- package/corpus/chunks/auth-email-entry.json +65 -0
- package/corpus/chunks/auth-email-verify-confirm.json +52 -0
- package/corpus/chunks/auth-email-verify.json +196 -0
- package/corpus/chunks/auth-forbidden-actions.json +59 -0
- package/corpus/chunks/auth-forbidden.json +203 -0
- package/corpus/chunks/auth-invite-actions.json +49 -0
- package/corpus/chunks/auth-invite-team-card.json +86 -0
- package/corpus/chunks/auth-link-expired-form.json +65 -0
- package/corpus/chunks/auth-link-expired.json +196 -0
- package/corpus/chunks/auth-locked-account.json +211 -0
- package/corpus/chunks/auth-locked-recovery-options.json +60 -0
- package/corpus/chunks/auth-mfa-enrollment-submit.json +54 -0
- package/corpus/chunks/auth-mfa-enrollment.json +284 -0
- package/corpus/chunks/auth-mfa-fallback-actions.json +52 -0
- package/corpus/chunks/auth-mfa-recovery.json +61 -0
- package/corpus/chunks/auth-new-password-form.json +75 -0
- package/corpus/chunks/auth-new-password.json +217 -0
- package/corpus/chunks/auth-oauth-fallback-actions.json +52 -0
- package/corpus/chunks/auth-oauth-interstitial.json +160 -0
- package/corpus/chunks/auth-password-challenge.json +94 -0
- package/corpus/chunks/auth-password-reset-form.json +64 -0
- package/corpus/chunks/auth-password-reset.json +195 -0
- package/corpus/chunks/auth-profile-form.json +72 -0
- package/corpus/chunks/auth-profile-setup.json +194 -0
- package/corpus/chunks/auth-reset-sent.json +188 -0
- package/corpus/chunks/auth-session-expired-actions.json +52 -0
- package/corpus/chunks/auth-session-expired.json +201 -0
- package/corpus/chunks/auth-signin-card-email.json +245 -0
- package/corpus/chunks/auth-signin-card-magic-link.json +147 -0
- package/corpus/chunks/auth-signin-card-mfa.json +231 -0
- package/corpus/chunks/auth-signin-card-otp.json +205 -0
- package/corpus/chunks/auth-signin-card-password.json +264 -0
- package/corpus/chunks/auth-signin-card-recovery.json +218 -0
- package/corpus/chunks/auth-signout-actions.json +51 -0
- package/corpus/chunks/auth-signout.json +184 -0
- package/corpus/chunks/auth-signup-email-entry.json +66 -0
- package/corpus/chunks/auth-signup-entry.json +281 -0
- package/corpus/chunks/auth-signup-social-auths.json +54 -0
- package/corpus/chunks/auth-signup-verify.json +227 -0
- package/corpus/chunks/auth-social-auths.json +62 -0
- package/corpus/chunks/auth-sso-providers.json +55 -0
- package/corpus/chunks/auth-sso-required.json +213 -0
- package/corpus/chunks/auth-team-invite.json +288 -0
- package/corpus/chunks/avatar-group-overflow.json +137 -0
- package/corpus/chunks/avatar-stack-overflow.json +124 -0
- package/corpus/chunks/banner-announcement-beta.json +99 -0
- package/corpus/chunks/banner-announcement-promo.json +102 -0
- package/corpus/chunks/banner-live-update.json +102 -0
- package/corpus/chunks/banner-system-maintenance.json +101 -0
- package/corpus/chunks/banner-system-offline.json +85 -0
- package/corpus/chunks/banner-system-update.json +102 -0
- package/corpus/chunks/bell-menu-empty.json +107 -0
- package/corpus/chunks/bell-menu-unread.json +395 -0
- package/corpus/chunks/billing-cancel-subscription-danger.json +61 -0
- package/corpus/chunks/billing-invoice-history-table.json +75 -0
- package/corpus/chunks/billing-overview.json +202 -0
- package/corpus/chunks/billing-payment-method-card-on-file.json +157 -0
- package/corpus/chunks/billing-progress-label.json +101 -0
- package/corpus/chunks/blog-post-card.json +212 -0
- package/corpus/chunks/breadcrumb-navigation.json +72 -0
- package/corpus/chunks/bulk-action-toolbar-floating.json +199 -0
- package/corpus/chunks/bulk-action-toolbar-swap.json +158 -0
- package/corpus/chunks/bulk-selection-actions-bar.json +162 -0
- package/corpus/chunks/business-address-form.json +953 -0
- package/corpus/chunks/calendar-month-view.json +74 -0
- package/corpus/chunks/card-grid-images.json +459 -0
- package/corpus/chunks/card-header-with-description.json +47 -0
- package/corpus/chunks/card-with-empty-state.json +96 -0
- package/corpus/chunks/card-with-form.json +143 -0
- package/corpus/chunks/card-with-sparkline.json +90 -0
- package/corpus/chunks/card-with-stat-kpi.json +86 -0
- package/corpus/chunks/changelog-feed-basic.json +470 -0
- package/corpus/chunks/chart-in-card-chart-plus-breakdown.json +188 -0
- package/corpus/chunks/chart-in-card-chart-plus-stat.json +89 -0
- package/corpus/chunks/chart-in-card-chart-with-filter-pills.json +124 -0
- package/corpus/chunks/chart-in-card-full-bleed-legend.json +116 -0
- package/corpus/chunks/chart-in-card-full-chart.json +107 -0
- package/corpus/chunks/chart-in-card-sparkline-tile.json +93 -0
- package/corpus/chunks/chart-in-card-stat-with-sparkline.json +73 -0
- package/corpus/chunks/chart-in-card-trend-footer.json +115 -0
- package/corpus/chunks/chart-with-filter-pills.json +169 -0
- package/corpus/chunks/chat-empty-state-hero.json +102 -0
- package/corpus/chunks/chat-message-assistant-byline.json +85 -0
- package/corpus/chunks/chat-message-user-byline.json +84 -0
- package/corpus/chunks/chat-page-shell.json +379 -0
- package/corpus/chunks/chat-streaming-surface.json +169 -0
- package/corpus/chunks/checkout-order-summary-card.json +140 -0
- package/corpus/chunks/code-snippet.json +107 -0
- package/corpus/chunks/col-form-stack.json +93 -0
- package/corpus/chunks/col-heading-body-action.json +79 -0
- package/corpus/chunks/col-stat-label.json +63 -0
- package/corpus/chunks/color-picker-swatches.json +153 -0
- package/corpus/chunks/command-palette.json +327 -0
- package/corpus/chunks/comments-composer.json +158 -0
- package/corpus/chunks/comments-mention-menu.json +237 -0
- package/corpus/chunks/comments-thread.json +344 -0
- package/corpus/chunks/commerce-pricing-tiers.json +401 -0
- package/corpus/chunks/comparison-table.json +246 -0
- package/corpus/chunks/contact-form-card.json +197 -0
- package/corpus/chunks/contact-form.json +157 -0
- package/corpus/chunks/contact-support-form.json +702 -0
- package/corpus/chunks/conversion-funnel-4-step-funnel.json +139 -0
- package/corpus/chunks/conversion-funnel-6step.json +151 -0
- package/corpus/chunks/conversion-funnel-wide-summary.json +192 -0
- package/corpus/chunks/conversion-funnel-with-segment-compare.json +202 -0
- package/corpus/chunks/cta-banner-centered.json +102 -0
- package/corpus/chunks/dashboard-acquisition-panel.json +212 -0
- package/corpus/chunks/dashboard-admin-page.json +104 -0
- package/corpus/chunks/dashboard-audience-kpis.json +165 -0
- package/corpus/chunks/dashboard-audience-panel.json +756 -0
- package/corpus/chunks/dashboard-behavior-panel.json +114 -0
- package/corpus/chunks/dashboard-chart-recent.json +566 -0
- package/corpus/chunks/dashboard-cohort-retention.json +83 -0
- package/corpus/chunks/dashboard-conversion-panel.json +234 -0
- package/corpus/chunks/dashboard-country-list.json +304 -0
- package/corpus/chunks/dashboard-filter-bar.json +118 -0
- package/corpus/chunks/dashboard-funnel.json +142 -0
- package/corpus/chunks/dashboard-notifications-panel.json +423 -0
- package/corpus/chunks/dashboard-overview-panel.json +1644 -0
- package/corpus/chunks/dashboard-page-header.json +166 -0
- package/corpus/chunks/dashboard-pages-table.json +86 -0
- package/corpus/chunks/dashboard-quick-actions.json +116 -0
- package/corpus/chunks/dashboard-reports-panel.json +166 -0
- package/corpus/chunks/dashboard-reports-table.json +138 -0
- package/corpus/chunks/dashboard-storage-card.json +117 -0
- package/corpus/chunks/dashboard-tabs.json +86 -0
- package/corpus/chunks/dashboard-team-actions-storage.json +605 -0
- package/corpus/chunks/dashboard-team-list.json +334 -0
- package/corpus/chunks/dashboard-traffic-channels.json +184 -0
- package/corpus/chunks/dashboard-transactions-table.json +145 -0
- package/corpus/chunks/data-export-history.json +192 -0
- package/corpus/chunks/data-export-request.json +197 -0
- package/corpus/chunks/data-import-wizard.json +391 -0
- package/corpus/chunks/date-range-picker.json +156 -0
- package/corpus/chunks/date-time-picker-form.json +222 -0
- package/corpus/chunks/departments-checkbox-form.json +390 -0
- package/corpus/chunks/destructive-confirm-modal.json +149 -0
- package/corpus/chunks/diff-inline.json +84 -0
- package/corpus/chunks/diff-side-by-side.json +131 -0
- package/corpus/chunks/diff-structured.json +216 -0
- package/corpus/chunks/digest-email-preview.json +374 -0
- package/corpus/chunks/divider-text-label.json +87 -0
- package/corpus/chunks/doc-editor-shell.json +356 -0
- package/corpus/chunks/drawer-2fa-key.json +273 -0
- package/corpus/chunks/drawer-2fa-sms.json +261 -0
- package/corpus/chunks/drawer-2fa-totp.json +385 -0
- package/corpus/chunks/drawer-cancel-sub.json +636 -0
- package/corpus/chunks/drawer-change-plan.json +561 -0
- package/corpus/chunks/drawer-custom-roles.json +696 -0
- package/corpus/chunks/drawer-data-start.json +171 -0
- package/corpus/chunks/drawer-delete-account.json +341 -0
- package/corpus/chunks/drawer-delete-workspace.json +362 -0
- package/corpus/chunks/drawer-discord.json +434 -0
- package/corpus/chunks/drawer-figma.json +401 -0
- package/corpus/chunks/drawer-first-dashboard.json +220 -0
- package/corpus/chunks/drawer-gcal.json +475 -0
- package/corpus/chunks/drawer-github.json +589 -0
- package/corpus/chunks/drawer-invite.json +397 -0
- package/corpus/chunks/drawer-record-detail.json +44 -0
- package/corpus/chunks/drawer-report.json +528 -0
- package/corpus/chunks/drawer-revoke-session.json +331 -0
- package/corpus/chunks/drawer-role.json +190 -0
- package/corpus/chunks/drawer-slack.json +429 -0
- package/corpus/chunks/drawer-smtp.json +476 -0
- package/corpus/chunks/drawer-source.json +294 -0
- package/corpus/chunks/drawer-transaction.json +493 -0
- package/corpus/chunks/drawer-with-create-form.json +43 -0
- package/corpus/chunks/editor-code-pane.json +204 -0
- package/corpus/chunks/editor-page-shell.json +149 -0
- package/corpus/chunks/editor-preview-pane.json +136 -0
- package/corpus/chunks/editor-statusbar-ready.json +99 -0
- package/corpus/chunks/editor-toolbar-import-export.json +195 -0
- package/corpus/chunks/email-inbox-list.json +678 -0
- package/corpus/chunks/empty-state-danger.json +58 -0
- package/corpus/chunks/empty-state-minimal.json +44 -0
- package/corpus/chunks/empty-state-warning.json +53 -0
- package/corpus/chunks/empty-state.json +65 -0
- package/corpus/chunks/error-404-actions.json +54 -0
- package/corpus/chunks/error-404.json +204 -0
- package/corpus/chunks/error-500-actions.json +61 -0
- package/corpus/chunks/error-500.json +220 -0
- package/corpus/chunks/error-maintenance-actions.json +53 -0
- package/corpus/chunks/error-maintenance.json +203 -0
- package/corpus/chunks/error-page-shell.json +132 -0
- package/corpus/chunks/export-flow-async.json +210 -0
- package/corpus/chunks/export-flow-delivery.json +163 -0
- package/corpus/chunks/export-flow-sync.json +162 -0
- package/corpus/chunks/extended-profile-form.json +512 -0
- package/corpus/chunks/faq-accordion.json +123 -0
- package/corpus/chunks/feature-grid-icons.json +314 -0
- package/corpus/chunks/feature-grid-three-cards.json +187 -0
- package/corpus/chunks/feature-toggle-switch-grid.json +213 -0
- package/corpus/chunks/file-upload-dnd.json +166 -0
- package/corpus/chunks/file-upload-field.json +97 -0
- package/corpus/chunks/file-upload-form.json +251 -0
- package/corpus/chunks/filter-bar-active-filters.json +176 -0
- package/corpus/chunks/filter-bar-filter-bar-with-table.json +113 -0
- package/corpus/chunks/filter-bar-saved-views.json +117 -0
- package/corpus/chunks/filter-popover-form.json +137 -0
- package/corpus/chunks/footer-multi-column.json +270 -0
- package/corpus/chunks/footer-primary-only.json +41 -0
- package/corpus/chunks/form-checkbox-group.json +65 -0
- package/corpus/chunks/form-drawer-edit-form.json +178 -0
- package/corpus/chunks/form-drawer-simple-form.json +151 -0
- package/corpus/chunks/form-drawer-tall-form.json +325 -0
- package/corpus/chunks/form-field-email-hint.json +53 -0
- package/corpus/chunks/form-field-range.json +54 -0
- package/corpus/chunks/form-field-required.json +52 -0
- package/corpus/chunks/form-field-select.json +66 -0
- package/corpus/chunks/form-field-textarea.json +51 -0
- package/corpus/chunks/form-field-with-error.json +151 -0
- package/corpus/chunks/form-fields-two-column.json +69 -0
- package/corpus/chunks/form-page-shell.json +146 -0
- package/corpus/chunks/form-switch-toggle.json +41 -0
- package/corpus/chunks/form-system-live-demo.json +123 -0
- package/corpus/chunks/forms-address-autocomplete.json +277 -0
- package/corpus/chunks/forms-address-fields.json +221 -0
- package/corpus/chunks/forms-conditional-reveal.json +195 -0
- package/corpus/chunks/gallery-page-shell.json +444 -0
- package/corpus/chunks/grid-2col-entry-cards.json +140 -0
- package/corpus/chunks/grid-kpi-4col.json +164 -0
- package/corpus/chunks/grid-responsive-kpi.json +165 -0
- package/corpus/chunks/hero-cta-simple.json +107 -0
- package/corpus/chunks/hero-cta-split.json +183 -0
- package/corpus/chunks/hero-section-split.json +111 -0
- package/corpus/chunks/icon-text-row.json +60 -0
- package/corpus/chunks/image-caption-tile.json +99 -0
- package/corpus/chunks/image-carousel.json +156 -0
- package/corpus/chunks/image-thumbnail-grid.json +77 -0
- package/corpus/chunks/image-upload-preview.json +118 -0
- package/corpus/chunks/import-mapping-flow.json +972 -0
- package/corpus/chunks/inline-dialog-rename.json +128 -0
- package/corpus/chunks/inline-dialog-schedule.json +154 -0
- package/corpus/chunks/inline-dialog-status.json +179 -0
- package/corpus/chunks/integrations-api-keys-card-list.json +475 -0
- package/corpus/chunks/integrations-connect-form.json +550 -0
- package/corpus/chunks/integrations-grid.json +141 -0
- package/corpus/chunks/integrations-webhooks-empty-state.json +66 -0
- package/corpus/chunks/inventory-list-stock.json +137 -0
- package/corpus/chunks/invite-members.json +153 -0
- package/corpus/chunks/invoice-line-items.json +493 -0
- package/corpus/chunks/kanban-board-3col.json +713 -0
- package/corpus/chunks/kanban-page-shell.json +671 -0
- package/corpus/chunks/key-value-detail-list.json +242 -0
- package/corpus/chunks/keyboard-shortcut-display.json +250 -0
- package/corpus/chunks/labeled-textarea.json +45 -0
- package/corpus/chunks/leaderboard-table.json +140 -0
- package/corpus/chunks/library-browser-search-filter.json +109 -0
- package/corpus/chunks/linked-record-row.json +61 -0
- package/corpus/chunks/loading-skeleton-placeholder.json +387 -0
- package/corpus/chunks/login-form-card.json +207 -0
- package/corpus/chunks/logo-cloud-trusted-by.json +235 -0
- package/corpus/chunks/map-with-location-list.json +293 -0
- package/corpus/chunks/marketing-hero-cta.json +102 -0
- package/corpus/chunks/marketing-page-shell.json +352 -0
- package/corpus/chunks/masonry-gallery.json +154 -0
- package/corpus/chunks/member-edit-drawer.json +236 -0
- package/corpus/chunks/members-active-table-search-filter.json +184 -0
- package/corpus/chunks/members-pending-invites-cards.json +251 -0
- package/corpus/chunks/members-roles-permissions-list.json +146 -0
- package/corpus/chunks/menu-context-actions.json +113 -0
- package/corpus/chunks/metadata-description-list.json +178 -0
- package/corpus/chunks/modal-create-project-form.json +133 -0
- package/corpus/chunks/modal-preferences-tabs.json +147 -0
- package/corpus/chunks/multi-field-form-validation.json +394 -0
- package/corpus/chunks/nav-menu-icons.json +74 -0
- package/corpus/chunks/newsletter-subscription.json +190 -0
- package/corpus/chunks/notification-badges-feed.json +411 -0
- package/corpus/chunks/notification-preferences-panel.json +238 -0
- package/corpus/chunks/onb-completion.json +139 -0
- package/corpus/chunks/onb-extension-install.json +172 -0
- package/corpus/chunks/onb-hero-welcome.json +156 -0
- package/corpus/chunks/onb-import-picker.json +86 -0
- package/corpus/chunks/onb-mobile-handoff.json +121 -0
- package/corpus/chunks/onb-notification-prefs.json +83 -0
- package/corpus/chunks/onb-persona-picker.json +82 -0
- package/corpus/chunks/onb-provider-tiles.json +137 -0
- package/corpus/chunks/onb-settings-review.json +257 -0
- package/corpus/chunks/onb-step-footer.json +121 -0
- package/corpus/chunks/onb-step-header.json +121 -0
- package/corpus/chunks/onb-step-progress.json +140 -0
- package/corpus/chunks/onb-step-shell.json +380 -0
- package/corpus/chunks/onb-story-pane.json +121 -0
- package/corpus/chunks/onb-tutorial-steps.json +193 -0
- package/corpus/chunks/order-confirmation-success-card.json +177 -0
- package/corpus/chunks/order-tracking-timeline.json +131 -0
- package/corpus/chunks/pagination-controls.json +82 -0
- package/corpus/chunks/pane-settings-sidebar.json +204 -0
- package/corpus/chunks/patient-visit-shell.json +191 -0
- package/corpus/chunks/payment-checkout-form.json +341 -0
- package/corpus/chunks/payment-method-form.json +328 -0
- package/corpus/chunks/period-comparison.json +236 -0
- package/corpus/chunks/permission-matrix-table.json +438 -0
- package/corpus/chunks/permissions-matrix-grid.json +111 -0
- package/corpus/chunks/permissions-matrix-summary.json +157 -0
- package/corpus/chunks/permissions-role-picker-radio.json +107 -0
- package/corpus/chunks/permissions-role-picker-select.json +101 -0
- package/corpus/chunks/permissions-share-link.json +256 -0
- package/corpus/chunks/permissions-share-people.json +297 -0
- package/corpus/chunks/permissions-sharing-scopes.json +109 -0
- package/corpus/chunks/plan-selection-form.json +529 -0
- package/corpus/chunks/playground-a2ui.json +181 -0
- package/corpus/chunks/playground-agent-admin.json +117 -0
- package/corpus/chunks/playground-agent-chat.json +126 -0
- package/corpus/chunks/playground-app-shell.json +488 -0
- package/corpus/chunks/playground-chat.json +265 -0
- package/corpus/chunks/playground-construct-canvas.json +118 -0
- package/corpus/chunks/playground-css-channel.json +487 -0
- package/corpus/chunks/playground-gen-ui.json +224 -0
- package/corpus/chunks/playground-render-preview.json +369 -0
- package/corpus/chunks/playground-streams-bridge.json +437 -0
- package/corpus/chunks/playground-table-toolbar.json +38 -0
- package/corpus/chunks/popover-with-content.json +118 -0
- package/corpus/chunks/pricing-tiers.json +561 -0
- package/corpus/chunks/product-tour.json +158 -0
- package/corpus/chunks/profile-public.json +297 -0
- package/corpus/chunks/progress-tracker-milestones.json +294 -0
- package/corpus/chunks/radio-button-group.json +83 -0
- package/corpus/chunks/rating-stars-review-summary.json +259 -0
- package/corpus/chunks/reactions-bar.json +75 -0
- package/corpus/chunks/reactions-picker.json +245 -0
- package/corpus/chunks/real-time-metrics-dashboard.json +344 -0
- package/corpus/chunks/record-detail-drawer-simple-detail.json +296 -0
- package/corpus/chunks/record-detail-drawer-tabbed-detail.json +443 -0
- package/corpus/chunks/referral-share-link.json +128 -0
- package/corpus/chunks/referral-status.json +243 -0
- package/corpus/chunks/reg-address-form.json +825 -0
- package/corpus/chunks/reg-billing-card.json +210 -0
- package/corpus/chunks/reg-brand-scrape.json +599 -0
- package/corpus/chunks/reg-departments-toggle.json +259 -0
- package/corpus/chunks/reg-extended-profile.json +356 -0
- package/corpus/chunks/reg-final-done.json +457 -0
- package/corpus/chunks/reg-helpdesk-grid.json +571 -0
- package/corpus/chunks/reg-import-picker.json +112 -0
- package/corpus/chunks/reg-integrations-grid.json +418 -0
- package/corpus/chunks/reg-invite-form.json +245 -0
- package/corpus/chunks/reg-legal-entity.json +260 -0
- package/corpus/chunks/reg-org-chart-review.json +891 -0
- package/corpus/chunks/reg-profile-identity.json +188 -0
- package/corpus/chunks/reg-step-footer.json +201 -0
- package/corpus/chunks/reg-step-header.json +201 -0
- package/corpus/chunks/reg-step-progress.json +236 -0
- package/corpus/chunks/reg-step-shell.json +605 -0
- package/corpus/chunks/reg-story-pane.json +201 -0
- package/corpus/chunks/reg-success-summary.json +257 -0
- package/corpus/chunks/reg-team-size.json +128 -0
- package/corpus/chunks/reg-usecase-picker.json +104 -0
- package/corpus/chunks/reg-workspace-name.json +159 -0
- package/corpus/chunks/responsive-grid-pattern.json +71 -0
- package/corpus/chunks/responsive-kpi-grid.json +166 -0
- package/corpus/chunks/responsive-row-pattern.json +71 -0
- package/corpus/chunks/responsive-shell-sidebar.json +308 -0
- package/corpus/chunks/responsive-wrap-at-pattern.json +124 -0
- package/corpus/chunks/retention-cohort-default-retention.json +80 -0
- package/corpus/chunks/retention-cohort-stat-pair.json +163 -0
- package/corpus/chunks/retention-cohort-with-legend.json +135 -0
- package/corpus/chunks/revenue-heatmap.json +82 -0
- package/corpus/chunks/role-management.json +272 -0
- package/corpus/chunks/row-action-cluster.json +54 -0
- package/corpus/chunks/row-avatar-name-role.json +71 -0
- package/corpus/chunks/row-icon-label.json +52 -0
- package/corpus/chunks/row-spread-label-value.json +54 -0
- package/corpus/chunks/row-wrap-tags.json +72 -0
- package/corpus/chunks/schedule-meeting-form-card.json +229 -0
- package/corpus/chunks/search-recents-menu.json +195 -0
- package/corpus/chunks/search-results-grouped.json +357 -0
- package/corpus/chunks/search-results-list.json +202 -0
- package/corpus/chunks/search-saved-views.json +356 -0
- package/corpus/chunks/search-with-filters.json +311 -0
- package/corpus/chunks/searchable-picker-modal.json +164 -0
- package/corpus/chunks/section-with-stack.json +48 -0
- package/corpus/chunks/security-active-sessions-devices.json +287 -0
- package/corpus/chunks/security-change-password-form.json +102 -0
- package/corpus/chunks/security-delete-account-danger.json +79 -0
- package/corpus/chunks/segmented-control-billing-tabs.json +164 -0
- package/corpus/chunks/select-multiple-preselected.json +70 -0
- package/corpus/chunks/settings-2fa-setup.json +307 -0
- package/corpus/chunks/settings-admin-page.json +1205 -0
- package/corpus/chunks/settings-appearance-primitives.json +145 -0
- package/corpus/chunks/settings-appearance-theme-panel.json +55 -0
- package/corpus/chunks/settings-appearance.json +81 -0
- package/corpus/chunks/settings-danger-zone-delete-workspace.json +93 -0
- package/corpus/chunks/settings-general-form.json +69 -0
- package/corpus/chunks/settings-integrations.json +298 -0
- package/corpus/chunks/settings-members-invite.json +112 -0
- package/corpus/chunks/settings-notification-activity-checkboxes.json +108 -0
- package/corpus/chunks/settings-notification-channels-switches.json +101 -0
- package/corpus/chunks/settings-page-shell.json +190 -0
- package/corpus/chunks/settings-privacy.json +83 -0
- package/corpus/chunks/settings-profile-security.json +122 -0
- package/corpus/chunks/settings-toggle-switches.json +66 -0
- package/corpus/chunks/sidebar-nav.json +120 -0
- package/corpus/chunks/sidebar-navigation-panel.json +165 -0
- package/corpus/chunks/signup-form-card.json +218 -0
- package/corpus/chunks/signup-team-size-form.json +259 -0
- package/corpus/chunks/single-select-card-form.json +231 -0
- package/corpus/chunks/slider-range-controls.json +119 -0
- package/corpus/chunks/social-media-post-card.json +159 -0
- package/corpus/chunks/sortable-list.json +307 -0
- package/corpus/chunks/sortable-search-paginate-table.json +162 -0
- package/corpus/chunks/split-pane-editor.json +146 -0
- package/corpus/chunks/stack-avatar-badge-overlay.json +53 -0
- package/corpus/chunks/stack-image-shimmer.json +51 -0
- package/corpus/chunks/stat-cards-kpi-dashboard.json +178 -0
- package/corpus/chunks/stats-band-big-numbers.json +175 -0
- package/corpus/chunks/status-dashboard.json +282 -0
- package/corpus/chunks/stepper-form-wizard.json +165 -0
- package/corpus/chunks/subscription-status-renewal-card.json +285 -0
- package/corpus/chunks/survey-rating-form.json +165 -0
- package/corpus/chunks/swiper-product-carousel.json +349 -0
- package/corpus/chunks/swiper-testimonial-carousel.json +279 -0
- package/corpus/chunks/table-empty-state.json +116 -0
- package/corpus/chunks/table-inline-edit-row.json +269 -0
- package/corpus/chunks/table-spreadsheet-cells.json +334 -0
- package/corpus/chunks/table-toolbar-no-search.json +42 -0
- package/corpus/chunks/table-toolbar-with-table.json +208 -0
- package/corpus/chunks/table-with-toolbar-card.json +80 -0
- package/corpus/chunks/tabs-with-panels.json +187 -0
- package/corpus/chunks/tag-chips-filter.json +100 -0
- package/corpus/chunks/team-invite-form.json +380 -0
- package/corpus/chunks/team-members-list.json +341 -0
- package/corpus/chunks/testimonial-grid.json +269 -0
- package/corpus/chunks/testimonial-pull-quote.json +137 -0
- package/corpus/chunks/testimonials-avatar-cards.json +286 -0
- package/corpus/chunks/timeline-events.json +89 -0
- package/corpus/chunks/timezone-selector-basic.json +99 -0
- package/corpus/chunks/timezone-selector-preview.json +104 -0
- package/corpus/chunks/toolbar-icons.json +216 -0
- package/corpus/chunks/toolbar-rich-text-editor.json +230 -0
- package/corpus/chunks/toolbar-tooltips.json +191 -0
- package/corpus/chunks/tooltip-hover-button.json +106 -0
- package/corpus/chunks/tree-file-explorer.json +136 -0
- package/corpus/chunks/tree-table-basic.json +171 -0
- package/corpus/chunks/trial-banner.json +158 -0
- package/corpus/chunks/url-import-form.json +728 -0
- package/corpus/chunks/usage-quota-meter-card.json +217 -0
- package/corpus/chunks/user-identity-row.json +81 -0
- package/corpus/chunks/user-onboarding-checklist.json +301 -0
- package/corpus/chunks/user-profile-card.json +192 -0
- package/corpus/chunks/users-table-badge.json +135 -0
- package/corpus/chunks/verification-document-upload.json +179 -0
- package/corpus/chunks/verification-status.json +97 -0
- package/corpus/chunks/verification-stepper.json +111 -0
- package/corpus/chunks/video-player-controls.json +120 -0
- package/corpus/chunks/webhook-config.json +209 -0
- package/corpus/chunks/webhooks-list.json +204 -0
- package/corpus/chunks/wizard-drawer-three-step-wizard.json +443 -0
- package/corpus/manifest.d.ts +4 -0
- package/corpus/manifest.json +6 -0
- package/corpus/scripts/chunk-library.d.ts +4 -0
- package/corpus/scripts/chunk-library.js +335 -0
- package/node-shims.d.ts +48 -0
- package/package.json +215 -0
- package/retrieval/CHANGELOG.md +1073 -0
- package/retrieval/README.md +71 -0
- package/retrieval/anti-patterns.js +189 -0
- package/retrieval/authoring/index.d.ts +4 -0
- package/retrieval/authoring/index.js +9 -0
- package/retrieval/authoring/web-research.js +220 -0
- package/retrieval/catalog.js +250 -0
- package/retrieval/component-catalog.js +168 -0
- package/retrieval/component-entry.js +80 -0
- package/retrieval/context-assembler.js +174 -0
- package/retrieval/domain-router.js +417 -0
- package/retrieval/embedding/chunk-embedding-retriever.js +117 -0
- package/retrieval/embedding/embedding-provider.js +72 -0
- package/retrieval/embedding/index.d.ts +4 -0
- package/retrieval/embedding/index.js +2 -0
- package/retrieval/feedback/dialog-recorder.js +107 -0
- package/retrieval/feedback/feedback-analyzer.js +180 -0
- package/retrieval/feedback/feedback-store.js +194 -0
- package/retrieval/feedback/feedback.js +117 -0
- package/retrieval/feedback/gap-registry.js +80 -0
- package/retrieval/feedback/human-signal.js +113 -0
- package/retrieval/feedback/index.d.ts +4 -0
- package/retrieval/feedback/index.js +24 -0
- package/retrieval/feedback/submit-feedback.js +45 -0
- package/retrieval/index.d.ts +4 -0
- package/retrieval/index.js +53 -0
- package/retrieval/intent/clarity.js +139 -0
- package/retrieval/intent/decomposer.js +124 -0
- package/retrieval/intent/index.d.ts +4 -0
- package/retrieval/intent/index.js +18 -0
- package/retrieval/intent/intent-alignment.js +172 -0
- package/retrieval/intent/intent-categorizer.js +69 -0
- package/retrieval/intent/intent-gate.js +96 -0
- package/retrieval/intent/prompt-analyzer.js +162 -0
- package/retrieval/wiring-catalog.js +168 -0
- package/validate/catalog-validator.d.ts +4 -0
- package/validate/catalog-validator.js +327 -0
- package/validate/semantic/cache.js +54 -0
- package/validate/semantic/classify-intent.js +128 -0
- package/validate/semantic/index.js +163 -0
- package/validate/semantic/intent-specs.js +162 -0
- package/validate/semantic/judge.js +180 -0
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chunk-aware composition synthesizer.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the existing `synthesizer.js` (fragment-graph) but operates on the
|
|
5
|
+
* gen-UI training-chunk corpus instead of the fragment catalog. When pure
|
|
6
|
+
* retrieval can't surface a strong match for an intent, this asks the LLM to
|
|
7
|
+
* mix-and-match: pick a page-kind chunk, then bind block/panel chunks to its
|
|
8
|
+
* slots. Validator checks slot names + chunk-kind contracts before composing.
|
|
9
|
+
*
|
|
10
|
+
* Two-tier behavior:
|
|
11
|
+
* 1. Retrieval first — searchChunks returns a strong match (score > threshold)
|
|
12
|
+
* → return that chunk directly. Fast path; no LLM call.
|
|
13
|
+
* 2. Synthesis fallback — retrieval is weak → invoke the LLM to compose
|
|
14
|
+
* from the catalog. This is the creative mix-and-match path.
|
|
15
|
+
*
|
|
16
|
+
* Token-budget mitigation: pre-search filters the catalog to ~30 candidates
|
|
17
|
+
* before the LLM sees them. Mirrors the fragment-synthesizer technique.
|
|
18
|
+
*
|
|
19
|
+
* Plan: .claude/docs/plans/training-pipeline-chunk-harvest-2026-04-27.md (Phase C.2).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
getChunk,
|
|
24
|
+
searchChunks,
|
|
25
|
+
searchChunksAsync,
|
|
26
|
+
listChunksByKind,
|
|
27
|
+
getAllChunks,
|
|
28
|
+
resolveNestedChunks,
|
|
29
|
+
} from '../../../corpus/scripts/chunk-library.js';
|
|
30
|
+
import { composeFromPlan, validatePlan } from './chunk-composer.js';
|
|
31
|
+
import { transpileHTML } from '../../transpiler/transpiler.js';
|
|
32
|
+
|
|
33
|
+
// TKT-0009: composeFromIntent used to return only a raw HTML string,
|
|
34
|
+
// which every caller wrapped in a single node carrying an UNREGISTERED
|
|
35
|
+
// A2UI type (`component: 'article'`) — meaning full schema/catalog
|
|
36
|
+
// validation against it always reported invalid, regardless of the
|
|
37
|
+
// composed content's actual quality (registry.has('article') is false).
|
|
38
|
+
// Ratified direction: reuse the SAME transpileHTML() infrastructure the
|
|
39
|
+
// docs-transpiler and harvest-chunks.mjs already run at scale, rather
|
|
40
|
+
// than inventing a new passthrough construct — this makes every
|
|
41
|
+
// composeFromIntent() result a REAL component graph, so it qualifies for
|
|
42
|
+
// the shared validate-and-repair loop like every other engine. A chunk's
|
|
43
|
+
// own precomputed `.template` (from harvest-chunks.mjs) is used directly
|
|
44
|
+
// when available (accurate, no re-transpile cost); multi-instance chunk
|
|
45
|
+
// records don't carry one per-instance, so this falls back to
|
|
46
|
+
// transpiling the HTML on demand either way — every return path leaves
|
|
47
|
+
// with a real template, never just a string.
|
|
48
|
+
async function ensureTemplate(html, precomputedTemplate) {
|
|
49
|
+
if (Array.isArray(precomputedTemplate) && precomputedTemplate.length) return precomputedTemplate;
|
|
50
|
+
if (!html) return null;
|
|
51
|
+
const { messages } = await transpileHTML(html);
|
|
52
|
+
return messages?.[0]?.components ?? null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const STRONG_RETRIEVAL_SCORE = 8; // search-score threshold for fast path
|
|
56
|
+
const PRE_SEARCH_LIMIT = 30; // chunks shown to the LLM in the prompt
|
|
57
|
+
const DEFAULT_MAX_ATTEMPTS = 2;
|
|
58
|
+
// Scope-drift gate: composed HTML's component count vs. the sum of bound
|
|
59
|
+
// chunks' component counts. A multiplier > SCOPE_DRIFT_RATIO trips a warning
|
|
60
|
+
// + auto-fires a `scope-drift` issue. Floor prevents false positives on
|
|
61
|
+
// small UIs where slot-wrapper noise dominates.
|
|
62
|
+
export const SCOPE_DRIFT_RATIO = 1.5;
|
|
63
|
+
export const SCOPE_DRIFT_MIN_ACTUAL = 20;
|
|
64
|
+
|
|
65
|
+
const SYSTEM_PROMPT = `You compose web-app pages by binding training chunks into named slots.
|
|
66
|
+
|
|
67
|
+
## YOUR TASK
|
|
68
|
+
|
|
69
|
+
Given a user intent and a catalog of chunks, return a JSON object that:
|
|
70
|
+
1. SELECTS the most appropriate page-kind shell
|
|
71
|
+
2. BINDS block/panel chunks into its slots
|
|
72
|
+
|
|
73
|
+
## STEP 1 — SELECT A PAGE SHELL
|
|
74
|
+
|
|
75
|
+
Page shells (kind=page or kind=panel) define the layout topology. Match the
|
|
76
|
+
intent domain to the right shell — NEVER default to dashboard-admin-page for
|
|
77
|
+
non-dashboard intents:
|
|
78
|
+
|
|
79
|
+
| Shell | Domain | Slots |
|
|
80
|
+
|-------|--------|-------|
|
|
81
|
+
| dashboard-admin-page | Admin/analytics dashboards | page-header, page-content |
|
|
82
|
+
| settings-page-shell | Settings, preferences, configuration | page-header, page-tabs, page-content |
|
|
83
|
+
| form-page-shell | Auth forms, sign-in, sign-up, profile | page-header, form-content, page-footer |
|
|
84
|
+
| marketing-page-shell | Landing pages, heroes, features, CTAs | hero, features, cta |
|
|
85
|
+
| error-page-shell | Error states (404, 500, permission denied) | error-content, navigation |
|
|
86
|
+
| editor-page-shell | Split-pane editors (code + preview) | editor-pane, preview-pane |
|
|
87
|
+
| onb-step-shell | Onboarding wizards, multi-step flows | page-story, page-header, page-content, page-footer |
|
|
88
|
+
| reg-step-shell | Registration flows, multi-step sign-up | page-story, page-header, page-content, page-footer |
|
|
89
|
+
|
|
90
|
+
Selection rule: the shell whose DOMAIN matches the intent keywords wins.
|
|
91
|
+
|
|
92
|
+
## STEP 2 — SELECT BLOCKS TO FILL SLOTS
|
|
93
|
+
|
|
94
|
+
- Search the block catalog for chunks whose name contains intent keywords.
|
|
95
|
+
- Prefer blocks whose primary tag matches the desired component (e.g.
|
|
96
|
+
"stat-ui" for stat cards, "chart-ui" for charts).
|
|
97
|
+
- If a slot is optional and no matching block exists, OMIT it rather
|
|
98
|
+
than forcing a random block.
|
|
99
|
+
- Never invent chunk names. Every bound name must appear in the catalog.
|
|
100
|
+
|
|
101
|
+
## STEP 3 — RETURN JSON
|
|
102
|
+
|
|
103
|
+
Return ONLY a JSON object shaped exactly like:
|
|
104
|
+
{
|
|
105
|
+
"page": "<name of page-kind chunk>",
|
|
106
|
+
"slot_bindings": {
|
|
107
|
+
"<slot-name>": "<bound chunk name>"
|
|
108
|
+
OR
|
|
109
|
+
"<slot-name>": ["<chunk1>", "<chunk2>"]
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
Rules:
|
|
114
|
+
- The "page" must be a chunk with kind="page" or kind="panel".
|
|
115
|
+
- Every slot key must be declared by the chosen page shell.
|
|
116
|
+
- Every bound value must be a real chunk name from the catalog.
|
|
117
|
+
- Return valid JSON. No prose, no comments, no markdown fences. Begin with "{".
|
|
118
|
+
`;
|
|
119
|
+
|
|
120
|
+
function buildCatalogSummary(chunks) {
|
|
121
|
+
return chunks.map((c) => ({
|
|
122
|
+
name: c.name,
|
|
123
|
+
kind: c.kind,
|
|
124
|
+
primary: c.primary || c.instances?.[0]?.primary,
|
|
125
|
+
slots: (c.slots || c.instances?.[0]?.slots || []).map((s) => s.name),
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function buildExamples() {
|
|
130
|
+
// Four canonical examples spanning different domains. Diverse examples
|
|
131
|
+
// prevent the LLM from defaulting to dashboard-shaped output.
|
|
132
|
+
return [
|
|
133
|
+
{
|
|
134
|
+
intent: 'admin dashboard with KPIs and a conversion funnel',
|
|
135
|
+
output: {
|
|
136
|
+
page: 'dashboard-admin-page',
|
|
137
|
+
slot_bindings: {
|
|
138
|
+
'page-header': 'dashboard-page-header',
|
|
139
|
+
'page-content': ['dashboard-overview-panel', 'dashboard-funnel'],
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
intent: 'sign-in form with email and password',
|
|
145
|
+
output: {
|
|
146
|
+
page: 'form-page-shell',
|
|
147
|
+
slot_bindings: {
|
|
148
|
+
'page-header': 'auth-signin-card-password',
|
|
149
|
+
'form-content': 'auth-email-entry',
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
intent: 'settings page with tabs for general and billing',
|
|
155
|
+
output: {
|
|
156
|
+
page: 'settings-page-shell',
|
|
157
|
+
slot_bindings: {
|
|
158
|
+
'page-header': 'settings-general-form',
|
|
159
|
+
'page-tabs': 'check-combinations-settings-group',
|
|
160
|
+
'page-content': 'settings-general-form',
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
intent: 'marketing landing hero with feature cards',
|
|
166
|
+
output: {
|
|
167
|
+
page: 'marketing-page-shell',
|
|
168
|
+
slot_bindings: {
|
|
169
|
+
hero: 'hero-cta-simple',
|
|
170
|
+
features: 'empty-state-action',
|
|
171
|
+
cta: 'button-primary',
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
];
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function buildUserPrompt(intent, catalog, examples) {
|
|
179
|
+
const lines = [];
|
|
180
|
+
lines.push(`Intent: ${intent}`);
|
|
181
|
+
lines.push('');
|
|
182
|
+
lines.push('## Available chunks');
|
|
183
|
+
lines.push('');
|
|
184
|
+
for (const c of catalog) {
|
|
185
|
+
const slots = c.slots?.length ? ` slots=[${c.slots.join(', ')}]` : '';
|
|
186
|
+
lines.push(`- ${c.name} (kind=${c.kind}, primary=${c.primary})${slots}`);
|
|
187
|
+
}
|
|
188
|
+
lines.push('');
|
|
189
|
+
lines.push('## Example bindings');
|
|
190
|
+
lines.push('');
|
|
191
|
+
for (const ex of examples) {
|
|
192
|
+
lines.push(`Intent: ${ex.intent}`);
|
|
193
|
+
lines.push('Output:');
|
|
194
|
+
lines.push(JSON.stringify(ex.output, null, 2));
|
|
195
|
+
lines.push('');
|
|
196
|
+
}
|
|
197
|
+
lines.push('## Your turn');
|
|
198
|
+
lines.push('');
|
|
199
|
+
lines.push('Return JSON binding for the intent above. JSON only.');
|
|
200
|
+
return lines.join('\n');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function extractJSON(raw) {
|
|
204
|
+
if (!raw || typeof raw !== 'string') return null;
|
|
205
|
+
const trimmed = raw.trim();
|
|
206
|
+
// Strip markdown fences if present
|
|
207
|
+
const fenced = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
208
|
+
const candidate = fenced ? fenced[1].trim() : trimmed;
|
|
209
|
+
try {
|
|
210
|
+
return JSON.parse(candidate);
|
|
211
|
+
} catch {
|
|
212
|
+
// Find the first { ... } balanced object
|
|
213
|
+
const m = candidate.match(/\{[\s\S]*\}/);
|
|
214
|
+
if (!m) return null;
|
|
215
|
+
try { return JSON.parse(m[0]); } catch { return null; }
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Try retrieval-first; fall back to synthesis if retrieval is weak or missing.
|
|
221
|
+
*
|
|
222
|
+
* @param {object} opts
|
|
223
|
+
* @param {string} opts.intent
|
|
224
|
+
* @param {object} opts.llmAdapter — { complete: async ({ messages, systemPrompt }) => { content|text } }
|
|
225
|
+
* @param {number} [opts.maxAttempts=2]
|
|
226
|
+
* @returns {Promise<{ html: string, template: object[]|null, plan: object|null, source: 'retrieval'|'synthesis', score?: number, warnings: string[], synthesis?: object }>}
|
|
227
|
+
* `template` (TKT-0009) is a real A2UI component array — derived from the
|
|
228
|
+
* chunk's own precomputed template when available, else transpiled from
|
|
229
|
+
* `html` on demand — so callers get a validatable component graph, not
|
|
230
|
+
* just an HTML string to wrap opaquely.
|
|
231
|
+
*/
|
|
232
|
+
export async function composeFromIntent({ intent, llmAdapter, maxAttempts = DEFAULT_MAX_ATTEMPTS }) {
|
|
233
|
+
// Tier 1 — retrieval. Try semantic-blended hit first; fall back to keyword
|
|
234
|
+
// when embeddings are unavailable (no chunk-embeddings.json or no API key).
|
|
235
|
+
//
|
|
236
|
+
// Restricted to kind=block: page/panel chunks are SKELETONS that need
|
|
237
|
+
// slot-binding composition (Tier 2 handles them). Returning a skeleton
|
|
238
|
+
// Fast path — deterministic keyword-first; embeddings as tie-breaker only.
|
|
239
|
+
// Embeddings can drift (e.g. "pane" matching "panel" boosting unrelated
|
|
240
|
+
// chunks). Sync keyword search is stable and keyword-discoverability is
|
|
241
|
+
// the baseline guarantee. We run both and prefer the sync result when
|
|
242
|
+
// it meets the threshold; only use async when sync is weak but async
|
|
243
|
+
// is strong (e.g. semantic match on content not captured by keywords).
|
|
244
|
+
const syncHits = searchChunks(intent, { kind: 'block', limit: 5 });
|
|
245
|
+
const asyncHits = await searchChunksAsync(intent, { kind: 'block', limit: 5 });
|
|
246
|
+
|
|
247
|
+
const syncTop = syncHits[0];
|
|
248
|
+
const asyncTop = asyncHits[0];
|
|
249
|
+
const useSync = syncTop && syncTop.score >= STRONG_RETRIEVAL_SCORE;
|
|
250
|
+
const useAsync = !useSync && asyncTop && asyncTop.score >= STRONG_RETRIEVAL_SCORE;
|
|
251
|
+
|
|
252
|
+
if (useSync || useAsync) {
|
|
253
|
+
const hit = useSync ? syncTop : asyncTop;
|
|
254
|
+
const top = getChunk(hit.name);
|
|
255
|
+
// A block chunk harvested from a page with nested markers is itself a
|
|
256
|
+
// skeleton — its body is `<!-- nested: … -->` comments. Returning that
|
|
257
|
+
// verbatim ships an empty shell, so inline the referenced chunks.
|
|
258
|
+
const html = resolveNestedChunks(top.html || top.instances?.[0]?.html || '', {
|
|
259
|
+
page: top.page || top.source || top.instances?.[0]?.page,
|
|
260
|
+
});
|
|
261
|
+
const scopeDrift = computeScopeDrift(html, [top, ...(top.nested || []).map(getChunk)]);
|
|
262
|
+
return {
|
|
263
|
+
html,
|
|
264
|
+
template: await ensureTemplate(html, top.template),
|
|
265
|
+
// gh#832 — a retrieval hit IS a composition, so it carries a plan like
|
|
266
|
+
// every synthesis result does: the single-chunk plan that materializes
|
|
267
|
+
// back to exactly this HTML. It used to be `null`, which made both
|
|
268
|
+
// tiers' outputs structurally different and left `refineFromIntent` /
|
|
269
|
+
// `applyOps` with nothing to mutate — refine silently no-opped on the
|
|
270
|
+
// entire Tier-1 path, in the product as well as the eval.
|
|
271
|
+
plan: { page: top.name, slot_bindings: {} },
|
|
272
|
+
source: 'retrieval',
|
|
273
|
+
score: hit.score,
|
|
274
|
+
cosineScore: hit.cosineScore,
|
|
275
|
+
warnings: scopeDrift.drift
|
|
276
|
+
? [`scope drift: ${scopeDrift.actual} components in HTML vs ${scopeDrift.expected} in bound chunk (ratio ${scopeDrift.ratio.toFixed(2)}×)`]
|
|
277
|
+
: [],
|
|
278
|
+
scopeDrift,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Tier 2 — synthesis. Need an LLM adapter.
|
|
283
|
+
if (!llmAdapter?.complete) {
|
|
284
|
+
return {
|
|
285
|
+
html: null,
|
|
286
|
+
plan: null,
|
|
287
|
+
source: 'synthesis',
|
|
288
|
+
warnings: ['retrieval was weak and no llmAdapter provided — cannot synthesize'],
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Pre-search the catalog to keep the prompt token-budget bounded.
|
|
293
|
+
// Strategy: retrieve top N by semantic-blended search; ALWAYS include all
|
|
294
|
+
// page-kind chunks (small set, the LLM needs to see what shells are
|
|
295
|
+
// available). Block pre-search uses embeddings when available.
|
|
296
|
+
const pageChunks = listChunksByKind('page');
|
|
297
|
+
const panelChunks = listChunksByKind('panel');
|
|
298
|
+
const blockHits = await searchChunksAsync(intent, {
|
|
299
|
+
kind: 'block',
|
|
300
|
+
limit: PRE_SEARCH_LIMIT - pageChunks.length - panelChunks.length,
|
|
301
|
+
});
|
|
302
|
+
const blockChunks = blockHits.map((h) => getChunk(h.name)).filter(Boolean);
|
|
303
|
+
|
|
304
|
+
const filtered = [
|
|
305
|
+
...pageChunks,
|
|
306
|
+
...panelChunks,
|
|
307
|
+
...blockChunks,
|
|
308
|
+
];
|
|
309
|
+
const catalog = buildCatalogSummary(filtered);
|
|
310
|
+
const examples = buildExamples();
|
|
311
|
+
|
|
312
|
+
const userPrompt = buildUserPrompt(intent, catalog, examples);
|
|
313
|
+
let lastError = null;
|
|
314
|
+
const attempts = [];
|
|
315
|
+
|
|
316
|
+
// Trace: snapshot of the retrieval log for the issue-reporter to surface
|
|
317
|
+
// verbatim on bug tickets. Recorded once before the retry loop so it
|
|
318
|
+
// describes what the LLM actually saw.
|
|
319
|
+
const tier1HitList = useSync ? syncHits : (useAsync ? asyncHits : []);
|
|
320
|
+
const retrievalTrace = {
|
|
321
|
+
tier1Hits: tier1HitList.slice(0, 5).map((h) => ({
|
|
322
|
+
name: h.name,
|
|
323
|
+
score: Number(h.score.toFixed(3)),
|
|
324
|
+
kind: h.kind,
|
|
325
|
+
cosineScore: h.cosineScore != null ? Number(h.cosineScore.toFixed(3)) : null,
|
|
326
|
+
})),
|
|
327
|
+
tier1Threshold: STRONG_RETRIEVAL_SCORE,
|
|
328
|
+
tier1Pass: tier1HitList.length > 0 && tier1HitList[0].score >= STRONG_RETRIEVAL_SCORE,
|
|
329
|
+
catalogSize: filtered.length,
|
|
330
|
+
catalogPageNames: pageChunks.map((c) => c.name),
|
|
331
|
+
catalogPanelNames: panelChunks.map((c) => c.name),
|
|
332
|
+
catalogBlockTopN: blockHits.slice(0, 10).map((h) => ({
|
|
333
|
+
name: h.name,
|
|
334
|
+
score: Number(h.score.toFixed(3)),
|
|
335
|
+
})),
|
|
336
|
+
userPromptChars: userPrompt.length,
|
|
337
|
+
systemPromptChars: SYSTEM_PROMPT.length,
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
341
|
+
const retryNudge = lastError
|
|
342
|
+
? `\n\nPREVIOUS ATTEMPT FAILED: ${lastError}. Return ONLY a JSON object shaped as { "page": "...", "slot_bindings": { ... } }. No prose, no questions.`
|
|
343
|
+
: '';
|
|
344
|
+
const messages = [{ role: 'user', content: userPrompt + retryNudge }];
|
|
345
|
+
const response = await llmAdapter.complete({ messages, systemPrompt: SYSTEM_PROMPT });
|
|
346
|
+
const raw = response?.content || response?.text || (typeof response === 'string' ? response : '');
|
|
347
|
+
attempts.push({ attempt: i + 1, raw });
|
|
348
|
+
|
|
349
|
+
const plan = extractJSON(raw);
|
|
350
|
+
if (!plan || !plan.page || !plan.slot_bindings) {
|
|
351
|
+
lastError = 'Response was not valid JSON with { page, slot_bindings } fields.';
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const validation = validatePlan(plan);
|
|
356
|
+
if (!validation.ok) {
|
|
357
|
+
lastError = validation.errors.slice(0, 3).join('; ');
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const composed = composeFromPlan(plan);
|
|
362
|
+
if (!composed.html) {
|
|
363
|
+
lastError = composed.warnings.join('; ') || 'composer returned null html';
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Compute scope-drift signal: composed envelope vs sum of bound chunks.
|
|
368
|
+
// Bound chunks = page chunk + every block/panel resolved into a slot.
|
|
369
|
+
const boundNames = new Set([plan.page]);
|
|
370
|
+
for (const v of Object.values(plan.slot_bindings || {})) {
|
|
371
|
+
const arr = Array.isArray(v) ? v : [v];
|
|
372
|
+
for (const n of arr) boundNames.add(n);
|
|
373
|
+
}
|
|
374
|
+
const boundChunks = [...boundNames].map((n) => getChunk(n)).filter(Boolean);
|
|
375
|
+
const scopeDrift = computeScopeDrift(composed.html, boundChunks);
|
|
376
|
+
const driftWarnings = scopeDrift.drift
|
|
377
|
+
? [`scope drift: ${scopeDrift.actual} components in composed HTML vs ${scopeDrift.expected} in bound chunks (ratio ${scopeDrift.ratio.toFixed(2)}× exceeds gate ${SCOPE_DRIFT_RATIO}×)`]
|
|
378
|
+
: [];
|
|
379
|
+
|
|
380
|
+
return {
|
|
381
|
+
html: composed.html,
|
|
382
|
+
template: await ensureTemplate(composed.html, null),
|
|
383
|
+
plan,
|
|
384
|
+
source: 'synthesis',
|
|
385
|
+
warnings: [...composed.warnings, ...driftWarnings],
|
|
386
|
+
scopeDrift,
|
|
387
|
+
synthesis: {
|
|
388
|
+
attempts: i + 1,
|
|
389
|
+
attemptsLog: attempts,
|
|
390
|
+
validation,
|
|
391
|
+
retrievalTrace,
|
|
392
|
+
userPrompt,
|
|
393
|
+
systemPromptHash: hashString(SYSTEM_PROMPT),
|
|
394
|
+
},
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return {
|
|
399
|
+
html: null,
|
|
400
|
+
plan: null,
|
|
401
|
+
source: 'synthesis',
|
|
402
|
+
warnings: [`synthesis failed after ${maxAttempts} attempts: ${lastError}`],
|
|
403
|
+
synthesis: {
|
|
404
|
+
attempts: maxAttempts,
|
|
405
|
+
attemptsLog: attempts,
|
|
406
|
+
retrievalTrace,
|
|
407
|
+
userPrompt,
|
|
408
|
+
systemPromptHash: hashString(SYSTEM_PROMPT),
|
|
409
|
+
},
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Cheap non-crypto hash for prompt-version fingerprinting in tickets.
|
|
414
|
+
function hashString(s) {
|
|
415
|
+
let h = 5381;
|
|
416
|
+
for (let i = 0; i < s.length; i++) h = ((h * 33) ^ s.charCodeAt(i)) >>> 0;
|
|
417
|
+
return 'h' + h.toString(36);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Heuristic component count — number of opening tags in the HTML.
|
|
422
|
+
* Loose but stable proxy for A2UI envelope size; used by the scope-drift
|
|
423
|
+
* gate (above) and by issue-reporter's ticket-rendering counter.
|
|
424
|
+
*/
|
|
425
|
+
function countComponents(html) {
|
|
426
|
+
if (typeof html !== 'string') return 0;
|
|
427
|
+
return (html.match(/<[a-z][a-z0-9-]*/g) || []).length;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Compute the scope-drift signal for a composed result.
|
|
432
|
+
*
|
|
433
|
+
* Inputs: the final HTML string + the chunk records that fed into it
|
|
434
|
+
* (page chunk for Tier-2; the single block for Tier-1). Sums the bound
|
|
435
|
+
* chunks' component counts to get an "expected envelope," compares it to
|
|
436
|
+
* the actual composed count, and reports the ratio.
|
|
437
|
+
*
|
|
438
|
+
* Returns { actual, expected, ratio, drift } where `drift` is true when
|
|
439
|
+
* actual exceeds SCOPE_DRIFT_RATIO × expected AND actual ≥ SCOPE_DRIFT_MIN_ACTUAL.
|
|
440
|
+
*/
|
|
441
|
+
export function computeScopeDrift(html, boundChunks) {
|
|
442
|
+
const actual = countComponents(html);
|
|
443
|
+
let expected = 0;
|
|
444
|
+
for (const c of boundChunks) {
|
|
445
|
+
if (!c) continue;
|
|
446
|
+
const chunkHtml = c.html || c.instances?.[0]?.html;
|
|
447
|
+
expected += countComponents(chunkHtml);
|
|
448
|
+
}
|
|
449
|
+
// Guard against zero-expected: when bound chunks have no HTML accounted for
|
|
450
|
+
// (rare; should only happen in malformed corpora), skip the gate rather
|
|
451
|
+
// than report infinite drift.
|
|
452
|
+
if (expected === 0) {
|
|
453
|
+
return { actual, expected, ratio: null, drift: false };
|
|
454
|
+
}
|
|
455
|
+
const ratio = actual / expected;
|
|
456
|
+
const drift = actual >= SCOPE_DRIFT_MIN_ACTUAL && ratio > SCOPE_DRIFT_RATIO;
|
|
457
|
+
return { actual, expected, ratio, drift };
|
|
458
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composer — passes A2UI composition templates straight through.
|
|
3
|
+
*
|
|
4
|
+
* History: this file used to expand `$fragment` refs in compositions
|
|
5
|
+
* via a slot-binding mechanism (zettel-style fragment graph). As of
|
|
6
|
+
* §37 (2026-05-12) fragments are retired — all compositions are
|
|
7
|
+
* pre-inlined into flat A2UI templates by /tmp/inline-compositions.py.
|
|
8
|
+
* `resolveComposition` is now a defensive copy + strip pass; any
|
|
9
|
+
* lingering `$fragment` ref is treated as a placeholder (the LLM /
|
|
10
|
+
* renderer will fail noisily, surfacing corpus drift).
|
|
11
|
+
*
|
|
12
|
+
* Kept as a thin wrapper rather than deleted because zettel's
|
|
13
|
+
* generator-adapter still calls `resolveComposition(comp)` —
|
|
14
|
+
* downstream rename is a follow-up arc.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const ID_PREFIX_SEPARATOR = '--';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Return a defensive copy of a composition's flat template.
|
|
21
|
+
*
|
|
22
|
+
* Compositions are pre-inlined, so there's nothing to expand. We
|
|
23
|
+
* still strip zettel-era fields that may linger in the corpus —
|
|
24
|
+
* future-proof against accidental re-introduction.
|
|
25
|
+
*
|
|
26
|
+
* @param {object} composition - { template: [...] }
|
|
27
|
+
* @returns {Array<object>}
|
|
28
|
+
*/
|
|
29
|
+
export function resolveComposition(composition) {
|
|
30
|
+
const template = composition?.template || [];
|
|
31
|
+
const out = [];
|
|
32
|
+
for (const node of template) {
|
|
33
|
+
if (!node || typeof node !== 'object') continue;
|
|
34
|
+
if (node.$fragment) {
|
|
35
|
+
// Stale $fragment refs shouldn't exist after the §37 inline pass.
|
|
36
|
+
// Surface them as a visible placeholder so corpus drift is easy
|
|
37
|
+
// to spot at render time.
|
|
38
|
+
out.push({
|
|
39
|
+
id: node.id || `stale-${node.$fragment}`,
|
|
40
|
+
component: 'Text',
|
|
41
|
+
textContent: `⚠ stale $fragment ref (compositions are pre-inlined): ${node.$fragment}`,
|
|
42
|
+
});
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const {
|
|
46
|
+
// Strip composition-only fields that never reach the renderer
|
|
47
|
+
$fragment, bindings, prependChildren, appendChildren,
|
|
48
|
+
...rest
|
|
49
|
+
} = node;
|
|
50
|
+
out.push({ ...rest });
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Convert a flat A2UI template into `beginComponent` messages for the
|
|
57
|
+
* validator / renderer. Strips composition-era fields.
|
|
58
|
+
*/
|
|
59
|
+
export function templateToMessages(template) {
|
|
60
|
+
return template.map((node) => {
|
|
61
|
+
const {
|
|
62
|
+
id, component, children,
|
|
63
|
+
$fragment, bindings,
|
|
64
|
+
prependChildren, appendChildren,
|
|
65
|
+
...rest
|
|
66
|
+
} = node;
|
|
67
|
+
return {
|
|
68
|
+
messageType: 'beginComponent',
|
|
69
|
+
componentId: id,
|
|
70
|
+
componentType: component,
|
|
71
|
+
children: children || [],
|
|
72
|
+
...rest,
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Re-export the separator for any downstream code that still uses it.
|
|
78
|
+
export { ID_PREFIX_SEPARATOR };
|