@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,418 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composition Library — zettel-style loader for harvested A2UI chunks.
|
|
3
|
+
*
|
|
4
|
+
* Reads `corpus/chunks/<name>.json` whenever the chunk carries both
|
|
5
|
+
* `metadata` (from `data-chunk-*` source-HTML attrs per §40) AND
|
|
6
|
+
* `template` (from the harvester's transpileHTML pass per §41). Chunks
|
|
7
|
+
* are normalized to composition shape by hoisting `metadata.*` to
|
|
8
|
+
* top level so consumers can search them uniformly.
|
|
9
|
+
*
|
|
10
|
+
* The legacy `corpus/compositions/<domain>/<name>.json` glob was
|
|
11
|
+
* retired in v0.4.7 (§65). The harvested-chunks substrate (~30
|
|
12
|
+
* annotated chunks at landing time) is the canonical retrieval
|
|
13
|
+
* surface; per the project's "source-of-truth = shipped /site/"
|
|
14
|
+
* principle, anything not in a shipped surface should fall through
|
|
15
|
+
* to LLM generation rather than be retrieval-matched from a curated
|
|
16
|
+
* JSON. The 199 MODE-C-MAYBE + 9 KEEP-AS-CHUNK + 3 DELETE
|
|
17
|
+
* composition/pattern files all retired alongside the dir.
|
|
18
|
+
*
|
|
19
|
+
* Records carry `_kind: 'annotated-chunk'` and the source-of-truth
|
|
20
|
+
* path so consumers can distinguish if they care; most shouldn't.
|
|
21
|
+
*
|
|
22
|
+
* Renamed from fragment-library.js in §38. Fragments retired §37.
|
|
23
|
+
* Annotated-chunk loading added §41. Compositions-glob retired §65.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
// §72 follow-up (v0.4.7): dual-mode loader so this module is safe to
|
|
27
|
+
// statically import from browser entrypoints. Previously the top-level
|
|
28
|
+
// `import 'node:fs'` poisoned the browser bundle the moment any
|
|
29
|
+
// app/playground reached `core/reference.js` → composition-library.
|
|
30
|
+
// Pattern mirrors `retrieval/component-catalog.js`.
|
|
31
|
+
//
|
|
32
|
+
// 2026-06-10: TRI-mode loader. The original dual-mode pattern assumed
|
|
33
|
+
// every browser context is a Vite dev server. The STATIC deploy
|
|
34
|
+
// (ui-kit.exe.xyz) serves the raw source JS — there is no Vite to transform
|
|
35
|
+
// the glob — so the glob `try/catch` swallowed silently and loaded 0 chunks.
|
|
36
|
+
// Every canvas intent then "composition-retrieval missed" on prod even
|
|
37
|
+
// though the chunk scored 66 in Node. Third branch: static-browser → fetch
|
|
38
|
+
// the corpus over HTTP.
|
|
39
|
+
// - Node (fs) — server / eval / smoke
|
|
40
|
+
// - Vite browser (glob) — `npm run dev`
|
|
41
|
+
// - Static browser (fetch)— deployed dist (no Vite, no /api/generate)
|
|
42
|
+
//
|
|
43
|
+
// CRUX — how we tell Vite-browser from static-browser (2026-06-10):
|
|
44
|
+
// `import.meta.glob` is a Vite **compile-time macro on the CALL expression**,
|
|
45
|
+
// NOT a runtime function. Vite rewrites `import.meta.glob('…')` into an
|
|
46
|
+
// object literal at transform time, but a bare reference like
|
|
47
|
+
// `typeof import.meta.glob` is left untouched — so at RUNTIME
|
|
48
|
+
// `import.meta.glob` is `undefined` in BOTH Vite-dev and static contexts
|
|
49
|
+
// (verified empirically 2026-06-10). The only reliable discriminator is to
|
|
50
|
+
// ATTEMPT the call in a try/catch: in Vite it was already rewritten to the
|
|
51
|
+
// object literal (succeeds, returns N loaders); on the raw static site the
|
|
52
|
+
// call hits the real `import.meta.glob` which is undefined → throws
|
|
53
|
+
// `import.meta.glob is not a function` → caught → we take the fetch branch.
|
|
54
|
+
// (This is parse-safe: `import.meta` is a real object in every ES module;
|
|
55
|
+
// the throw is a runtime TypeError, not a SyntaxError.)
|
|
56
|
+
const IS_NODE =
|
|
57
|
+
typeof process !== 'undefined' &&
|
|
58
|
+
typeof process.versions?.node === 'string';
|
|
59
|
+
|
|
60
|
+
/** @type {Map<string, object>} */
|
|
61
|
+
const compositions = new Map();
|
|
62
|
+
|
|
63
|
+
// Vite rewrites this call at transform time; on the static site the call
|
|
64
|
+
// throws (no Vite) → `_globChunkModules` stays null → fetch branch runs.
|
|
65
|
+
let _globChunkModules = null;
|
|
66
|
+
if (!IS_NODE) {
|
|
67
|
+
try {
|
|
68
|
+
_globChunkModules = import.meta.glob('../../../corpus/chunks/*.json', {
|
|
69
|
+
query: '?raw',
|
|
70
|
+
import: 'default',
|
|
71
|
+
eager: false,
|
|
72
|
+
});
|
|
73
|
+
} catch {
|
|
74
|
+
// No Vite transform here (static deploy) — fall through to the fetch branch.
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// `HAS_VITE_GLOB` is now decided by whether the glob CALL produced loaders,
|
|
78
|
+
// not by an (always-undefined-at-runtime) `typeof` probe.
|
|
79
|
+
const HAS_VITE_GLOB =
|
|
80
|
+
!IS_NODE && !!_globChunkModules && Object.keys(_globChunkModules).length > 0;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Promote an annotated chunk record to composition shape. Lifts
|
|
84
|
+
* `metadata.{domain,description,keywords,related,tags}` to top-level
|
|
85
|
+
* fields so the existing searchAll scorer can read them uniformly.
|
|
86
|
+
*/
|
|
87
|
+
function chunkToComposition(chunkDoc, sourcePath, { bodyUrl = null } = {}) {
|
|
88
|
+
const meta = chunkDoc.metadata || {};
|
|
89
|
+
return {
|
|
90
|
+
_kind: 'annotated-chunk',
|
|
91
|
+
_sourceFile: sourcePath,
|
|
92
|
+
// Static-browser only: URL to fetch the chunk body (template) on demand.
|
|
93
|
+
// null in Node / Vite, where `template` is already populated eagerly.
|
|
94
|
+
_bodyUrl: bodyUrl,
|
|
95
|
+
name: chunkDoc.name,
|
|
96
|
+
kind: 'composition', // honest with the searchAll filter
|
|
97
|
+
domain: meta.domain,
|
|
98
|
+
description: meta.description,
|
|
99
|
+
keywords: meta.keywords || [],
|
|
100
|
+
related: meta.related || [],
|
|
101
|
+
tags: meta.tags || {},
|
|
102
|
+
template: chunkDoc.template ?? null,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Track whether the eager top-level load has run. Multiple `loadAll`
|
|
108
|
+
* call sites (mcp/server.js bootstrap + any other consumer) re-clear
|
|
109
|
+
* + re-build, which is wasted work but not incorrect.
|
|
110
|
+
*/
|
|
111
|
+
let _autoLoaded = false;
|
|
112
|
+
let _loadStats = { compositionCount: 0, handAuthoredCount: 0, annotatedChunkCount: 0 };
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Filter + register an annotated chunk. Returns 1 if it qualified
|
|
116
|
+
* (had `metadata` + non-empty `template` + domain/keywords), else 0.
|
|
117
|
+
*/
|
|
118
|
+
function registerChunk(doc, sourcePath) {
|
|
119
|
+
if (!doc?.metadata) return 0;
|
|
120
|
+
if (!doc.template || !Array.isArray(doc.template) || doc.template.length === 0) return 0;
|
|
121
|
+
const meta = doc.metadata;
|
|
122
|
+
if (!meta.domain && !(meta.keywords && meta.keywords.length > 0)) return 0;
|
|
123
|
+
compositions.set(doc.name, chunkToComposition(doc, sourcePath));
|
|
124
|
+
return 1;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Static-browser only: register a chunk from its `_index.json` entry for
|
|
129
|
+
* SCORING (name + metadata.{domain,description,keywords} — verified at
|
|
130
|
+
* 2026-06-10 to be byte-identical to the per-chunk file's metadata). The
|
|
131
|
+
* `template` is NOT in the index; it is fetched lazily by
|
|
132
|
+
* `hydrateComposition(name)` when a strong match is actually emitted, so
|
|
133
|
+
* page-load costs one request (the 281 KB index) instead of 339.
|
|
134
|
+
*
|
|
135
|
+
* Index entries carry no `template`, so the eager `registerChunk` gate
|
|
136
|
+
* (which requires a non-empty template) would reject every one. We apply
|
|
137
|
+
* the SAME metadata gate (domain OR keywords present) but defer the
|
|
138
|
+
* template requirement to hydration time.
|
|
139
|
+
*/
|
|
140
|
+
function registerIndexEntry(entry, bodyUrl) {
|
|
141
|
+
if (!entry?.metadata || !entry.name) return 0;
|
|
142
|
+
const meta = entry.metadata;
|
|
143
|
+
if (!meta.domain && !(meta.keywords && meta.keywords.length > 0)) return 0;
|
|
144
|
+
// template: null here — hydrated on demand. searchAll never reads it.
|
|
145
|
+
compositions.set(entry.name, chunkToComposition(entry, entry.name, { bodyUrl }));
|
|
146
|
+
return 1;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function _loadAllNode() {
|
|
150
|
+
const fs = await import(/* @vite-ignore */ 'node:fs');
|
|
151
|
+
const path = await import(/* @vite-ignore */ 'node:path');
|
|
152
|
+
const url = await import(/* @vite-ignore */ 'node:url');
|
|
153
|
+
|
|
154
|
+
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
|
|
155
|
+
const CHUNKS_ROOT = path.resolve(__dirname, '../../../corpus/chunks');
|
|
156
|
+
|
|
157
|
+
function walk(dir, cb) {
|
|
158
|
+
if (!fs.existsSync(dir)) return;
|
|
159
|
+
// §160 (v0.5.3, F-S1 root cause): sort readdir output. fs.readdirSync
|
|
160
|
+
// returns entries in filesystem-defined order (variable across
|
|
161
|
+
// processes on APFS/ext4), which means chunk-loading order varied
|
|
162
|
+
// run-to-run. When two chunks tied on score for a given intent, the
|
|
163
|
+
// first-loaded won the tie-break — so the same intent could match
|
|
164
|
+
// chunk A in one process and chunk B in the next. Surfaced as
|
|
165
|
+
// ~40% probe-failure rate on admin-dashboard post-§143 (the new
|
|
166
|
+
// chunks compete with the original 4-row KPI composition).
|
|
167
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true })
|
|
168
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
169
|
+
for (const entry of entries) {
|
|
170
|
+
const p = path.join(dir, entry.name);
|
|
171
|
+
if (entry.isDirectory()) walk(p, cb);
|
|
172
|
+
else if (entry.name.endsWith('.json') && !entry.name.startsWith('_')) cb(p);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
let annotatedChunkCount = 0;
|
|
177
|
+
walk(CHUNKS_ROOT, (p) => {
|
|
178
|
+
const doc = JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
179
|
+
annotatedChunkCount += registerChunk(doc, p);
|
|
180
|
+
});
|
|
181
|
+
return annotatedChunkCount;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async function _loadAllBrowser() {
|
|
185
|
+
if (!_globChunkModules) return 0;
|
|
186
|
+
let annotatedChunkCount = 0;
|
|
187
|
+
for (const [globPath, loader] of Object.entries(_globChunkModules)) {
|
|
188
|
+
try {
|
|
189
|
+
const raw = await loader();
|
|
190
|
+
const doc = JSON.parse(raw);
|
|
191
|
+
annotatedChunkCount += registerChunk(doc, globPath);
|
|
192
|
+
} catch {
|
|
193
|
+
// skip malformed chunk JSON
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return annotatedChunkCount;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Base URL for the corpus on a static deploy. Relative-to-module
|
|
200
|
+
// (`import.meta.url`) — NOT an absolute `/packages/...` path — deliberately:
|
|
201
|
+
// 1. It is the SAME path the Vite glob trusts ('../../../corpus/chunks/*'),
|
|
202
|
+
// so dev and prod resolve through one mental model.
|
|
203
|
+
// 2. It is mount-point-independent: works whether dist is served at `/`,
|
|
204
|
+
// under a sub-path, or via the dist symlink layout
|
|
205
|
+
// (dist/node_modules/@adia-ai/gen-ui → packages/gen-ui),
|
|
206
|
+
// because `import.meta.url` always reflects the actually-served path.
|
|
207
|
+
// Verified 2026-06-10: `new URL('../../../corpus/chunks/_index.json',
|
|
208
|
+
// import.meta.url)` → `<root>/packages/gen-ui/corpus/chunks/_index.json`.
|
|
209
|
+
const _CORPUS_CHUNKS_BASE =
|
|
210
|
+
!IS_NODE && !HAS_VITE_GLOB
|
|
211
|
+
? new URL('../../../corpus/chunks/', import.meta.url)
|
|
212
|
+
: null;
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Static-browser loader. Fetches `_index.json` ONCE and registers every
|
|
216
|
+
* chunk for scoring. Bodies (templates) are fetched lazily by
|
|
217
|
+
* `hydrateComposition` so page-load stays at a single request, not 339.
|
|
218
|
+
*
|
|
219
|
+
* Degrades to 0 chunks (not a throw) on any fetch / parse failure — same
|
|
220
|
+
* graceful-empty contract as the Node and Vite branches.
|
|
221
|
+
*/
|
|
222
|
+
async function _loadAllStatic() {
|
|
223
|
+
if (!_CORPUS_CHUNKS_BASE) return 0;
|
|
224
|
+
let index;
|
|
225
|
+
try {
|
|
226
|
+
const res = await fetch(new URL('_index.json', _CORPUS_CHUNKS_BASE));
|
|
227
|
+
if (!res.ok) return 0;
|
|
228
|
+
index = await res.json();
|
|
229
|
+
} catch {
|
|
230
|
+
return 0;
|
|
231
|
+
}
|
|
232
|
+
const entries = Array.isArray(index?.chunks) ? index.chunks : [];
|
|
233
|
+
let count = 0;
|
|
234
|
+
for (const entry of entries) {
|
|
235
|
+
if (!entry?.name) continue;
|
|
236
|
+
const bodyUrl = new URL(`${entry.name}.json`, _CORPUS_CHUNKS_BASE).href;
|
|
237
|
+
count += registerIndexEntry(entry, bodyUrl);
|
|
238
|
+
}
|
|
239
|
+
return count;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Load all annotated chunks into the in-memory map. Returns a stats
|
|
244
|
+
* snapshot. In Node, runs synchronously via `fs.readFileSync`; in the Vite
|
|
245
|
+
* browser, dispatches the glob loaders in parallel; on a static deploy,
|
|
246
|
+
* fetches the index (bodies lazy-loaded on emit).
|
|
247
|
+
*/
|
|
248
|
+
export async function loadAll() {
|
|
249
|
+
compositions.clear();
|
|
250
|
+
let annotatedChunkCount;
|
|
251
|
+
if (IS_NODE) annotatedChunkCount = await _loadAllNode();
|
|
252
|
+
else if (HAS_VITE_GLOB) annotatedChunkCount = await _loadAllBrowser();
|
|
253
|
+
else annotatedChunkCount = await _loadAllStatic();
|
|
254
|
+
_autoLoaded = true;
|
|
255
|
+
_loadStats = {
|
|
256
|
+
compositionCount: compositions.size,
|
|
257
|
+
handAuthoredCount: 0,
|
|
258
|
+
annotatedChunkCount,
|
|
259
|
+
};
|
|
260
|
+
return _loadStats;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Ensure a composition's `template` (body) is loaded before a consumer
|
|
265
|
+
* resolves it. No-op in Node / Vite (the eager load already populated
|
|
266
|
+
* `template`). On a static deploy, fetches `<name>.json` once, patches the
|
|
267
|
+
* in-memory record's `template`, and caches it for subsequent calls.
|
|
268
|
+
*
|
|
269
|
+
* The zettel adapter's STRONG-MATCH branch awaits this immediately before
|
|
270
|
+
* `getComposition(name)` so verbatim emission has a body. Index-only
|
|
271
|
+
* scoring + lazy single-body hydration is what keeps the static page-load
|
|
272
|
+
* to one request — `searchAll` itself never needs the template.
|
|
273
|
+
*
|
|
274
|
+
* @param {string} name
|
|
275
|
+
* @returns {Promise<object|undefined>} the (now-hydrated) composition record
|
|
276
|
+
*/
|
|
277
|
+
export async function hydrateComposition(name) {
|
|
278
|
+
const rec = compositions.get(name);
|
|
279
|
+
if (!rec) return undefined;
|
|
280
|
+
// Already has a body (Node / Vite, or a prior hydration) — done.
|
|
281
|
+
if (Array.isArray(rec.template) && rec.template.length > 0) return rec;
|
|
282
|
+
if (!rec._bodyUrl) return rec; // not a static-deferred record; nothing to fetch
|
|
283
|
+
try {
|
|
284
|
+
const res = await fetch(rec._bodyUrl);
|
|
285
|
+
if (!res.ok) return rec;
|
|
286
|
+
const doc = await res.json();
|
|
287
|
+
if (Array.isArray(doc?.template) && doc.template.length > 0) {
|
|
288
|
+
rec.template = doc.template;
|
|
289
|
+
}
|
|
290
|
+
} catch {
|
|
291
|
+
// Leave template null — resolveComposition handles an empty template
|
|
292
|
+
// (emits nothing) rather than throwing.
|
|
293
|
+
}
|
|
294
|
+
return rec;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Eager top-level load so synchronous getters (getComposition,
|
|
298
|
+
// getAllCompositions, searchAll) work for consumers that don't call
|
|
299
|
+
// loadAll themselves — test harnesses, smoke scripts, and the
|
|
300
|
+
// retrieval-side helpers migrated off pattern-library in §64.
|
|
301
|
+
//
|
|
302
|
+
// In Node we top-level-await the load so the map is populated before
|
|
303
|
+
// any importer reaches the synchronous getters. In the browser the
|
|
304
|
+
// auto-load is fire-and-forget (the map fills as chunk JSONs come back
|
|
305
|
+
// from Vite's glob loaders); callers that need the map populated MUST
|
|
306
|
+
// `await loadAll()` themselves. Documented in §72-follow-up.
|
|
307
|
+
if (IS_NODE && !_autoLoaded) {
|
|
308
|
+
await loadAll();
|
|
309
|
+
} else if (!IS_NODE && !_autoLoaded) {
|
|
310
|
+
// Fire-and-forget; do not block module import on the network round-trips.
|
|
311
|
+
// Covers BOTH browser branches (Vite glob + static fetch). Consumers that
|
|
312
|
+
// need the map populated before a synchronous searchAll MUST `await
|
|
313
|
+
// loadAll()` (or await the adapter's own boot). The canvas does: its
|
|
314
|
+
// generateViaZettel awaits a fresh loadAll on the static-browser path.
|
|
315
|
+
loadAll().catch(() => { /* swallow; browsers that don't need this path won't trip */ });
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Back-compat shims removed in §38 — fragment-library.js → composition-library.js
|
|
319
|
+
// rename. The retired `getFragment` / `getAllFragments` exports had zero
|
|
320
|
+
// external callers; drop them.
|
|
321
|
+
|
|
322
|
+
export function getComposition(name) { return compositions.get(name); }
|
|
323
|
+
export function getAllCompositions() { return [...compositions.values()]; }
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Keyword search across compositions. (Fragments retired; only one
|
|
327
|
+
* corpus class to search now.)
|
|
328
|
+
*
|
|
329
|
+
* Ranking design:
|
|
330
|
+
* 1. Tokenize query, drop generic UI stop-words ("form", "page", "view"…)
|
|
331
|
+
* so they can't be the sole evidence for a match.
|
|
332
|
+
* 2. Whole-word match, not substring — prevents "form" matching "login-form".
|
|
333
|
+
* 3. Require ≥2 content-token hits (compositions are concrete templates —
|
|
334
|
+
* promiscuous matching is expensive). Exception: a direct name-token
|
|
335
|
+
* match is strong enough on its own.
|
|
336
|
+
* 4. Tiered weights: name hit > keyword hit > description.
|
|
337
|
+
*/
|
|
338
|
+
// Mirrored in `corpus/scripts/chunk-library.js` (`SEARCH_STOP_WORDS`) — this
|
|
339
|
+
// module is browser-safe and can't import that node-only one. Change both or neither.
|
|
340
|
+
const STOP_WORDS = new Set([
|
|
341
|
+
'a', 'an', 'the', 'and', 'or', 'but', 'of', 'to', 'in', 'on', 'at', 'for', 'with',
|
|
342
|
+
'form', 'forms', 'page', 'pages', 'view', 'views', 'screen', 'screens',
|
|
343
|
+
'ui', 'component', 'components', 'widget', 'widgets', 'block', 'blocks',
|
|
344
|
+
'section', 'sections', 'layout', 'layouts',
|
|
345
|
+
]);
|
|
346
|
+
|
|
347
|
+
function tokenize(str) {
|
|
348
|
+
return (str || '')
|
|
349
|
+
.toLowerCase()
|
|
350
|
+
.split(/[^a-z0-9]+/)
|
|
351
|
+
.filter((t) => t.length >= 2);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export function searchAll(query, { limit = 20 } = {}) {
|
|
355
|
+
const q = (query || '').trim();
|
|
356
|
+
if (!q) return [];
|
|
357
|
+
const queryTokens = tokenize(q);
|
|
358
|
+
|
|
359
|
+
const scoreDoc = (doc) => {
|
|
360
|
+
const nameTokens = new Set(tokenize(doc.name));
|
|
361
|
+
const keywordTokens = new Set((doc.keywords || []).flatMap((k) => tokenize(k)));
|
|
362
|
+
const descTokens = new Set(tokenize(doc.description || ''));
|
|
363
|
+
const tagTokens = new Set(
|
|
364
|
+
Object.values(doc.tags || {}).flat().flatMap((v) => tokenize(String(v))),
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
let s = 0;
|
|
368
|
+
const contentMatched = new Set();
|
|
369
|
+
|
|
370
|
+
for (const t of queryTokens) {
|
|
371
|
+
const isStop = STOP_WORDS.has(t);
|
|
372
|
+
let matched = false;
|
|
373
|
+
if (nameTokens.has(t)) { s += isStop ? 1 : 12; matched = true; }
|
|
374
|
+
if (keywordTokens.has(t)) { s += isStop ? 1 : 8; matched = true; }
|
|
375
|
+
if (tagTokens.has(t)) { s += isStop ? 0 : 3; matched = true; }
|
|
376
|
+
if (descTokens.has(t)) { s += isStop ? 0 : 2; matched = true; }
|
|
377
|
+
if (matched && !isStop) {
|
|
378
|
+
contentMatched.add(t);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const contentHits = contentMatched.size;
|
|
382
|
+
|
|
383
|
+
// Gate: compositions require ≥2 content-token hits, OR a direct
|
|
384
|
+
// name-token match (the query contains the composition's primary
|
|
385
|
+
// concept word — strong evidence on its own).
|
|
386
|
+
const nameHit = queryTokens.some((t) => !STOP_WORDS.has(t) && nameTokens.has(t));
|
|
387
|
+
if (contentHits < 2 && !nameHit) return 0;
|
|
388
|
+
|
|
389
|
+
// Coverage bonus: more distinct content tokens matched = better match
|
|
390
|
+
s += contentHits * 3;
|
|
391
|
+
|
|
392
|
+
return s;
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
return getAllCompositions()
|
|
396
|
+
.map((doc) => ({ doc, score: scoreDoc(doc) }))
|
|
397
|
+
.filter((x) => x.score > 0)
|
|
398
|
+
.sort((a, b) => b.score - a.score)
|
|
399
|
+
.slice(0, limit)
|
|
400
|
+
.map((x) => ({
|
|
401
|
+
type: 'composition',
|
|
402
|
+
name: x.doc.name,
|
|
403
|
+
score: Math.round(x.score * 100) / 100,
|
|
404
|
+
description: x.doc.description,
|
|
405
|
+
domain: x.doc.domain,
|
|
406
|
+
}));
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/** Return composition catalog for inspection / visualization. */
|
|
410
|
+
export function getGraph() {
|
|
411
|
+
return {
|
|
412
|
+
compositions: getAllCompositions().map((c) => ({
|
|
413
|
+
name: c.name,
|
|
414
|
+
domain: c.domain,
|
|
415
|
+
node_count: (c.template || []).length,
|
|
416
|
+
})),
|
|
417
|
+
};
|
|
418
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @adia-ai/gen-ui — zettel engine facade.
|
|
3
|
+
*
|
|
4
|
+
* Fragment-graph composition. Three reasoning layers:
|
|
5
|
+
* 1. Retrieval (always) — keyword-rank corpus, resolve top composition
|
|
6
|
+
* 2. LLM synthesis (when llmAdapter + weak retrieval) — compose a new
|
|
7
|
+
* composition from fragments
|
|
8
|
+
* 3. Session-aware iteration (when sessionId + prior turns) — modify
|
|
9
|
+
* existing canvas instead of regenerating
|
|
10
|
+
*
|
|
11
|
+
* The actual implementation is generator-adapter.js; this file is the
|
|
12
|
+
* spec-compliant entry point at strategies/zettel/generate.js per §11.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export { generateZettel as generate } from './generator-adapter.js';
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generator adapter for zettel MCP — conforms to the eval harness contract:
|
|
3
|
+
*
|
|
4
|
+
* generate({ intent, mode, llmAdapter, sessionId }) -> { messages, validation, strategy, ...extra }
|
|
5
|
+
*
|
|
6
|
+
* Two reasoning layers (post-§195, v0.5.6):
|
|
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
|
+
* chunk-zettel's `composeFromIntent` (the §37 successor codepath) which
|
|
10
|
+
* produces a single-shot html composition from the chunk corpus.
|
|
11
|
+
*
|
|
12
|
+
* Session iteration is currently NOT history-aware in this engine. Prior turns
|
|
13
|
+
* are recorded for analytics + drift tracking, but turn≥2 takes the same code
|
|
14
|
+
* path as turn 1 (fresh retrieval → fresh synthesis). Full history-aware
|
|
15
|
+
* iteration (multi-turn refinement modifying an existing canvas) lives in the
|
|
16
|
+
* `chunk-zettel` engine via `chunk-refiner.js::refineFromIntent` — wire it via
|
|
17
|
+
* `engine: 'chunk-zettel'` rather than `engine: 'zettel'`.
|
|
18
|
+
*
|
|
19
|
+
* The prior fragment-graph iteration codepath (`synthesizeComposition` with
|
|
20
|
+
* `historySummary`) was retired in §37 (2026-05-12) when fragments retired.
|
|
21
|
+
* §195 (v0.5.6) cleaned up the dangling caller — turn≥2 no longer throws +
|
|
22
|
+
* auto-fires a `iteration-synthesis-failure` issue on every multi-turn turn.
|
|
23
|
+
*
|
|
24
|
+
* Strategy labels in the return:
|
|
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
|
+
*/
|
|
30
|
+
import {
|
|
31
|
+
getComposition,
|
|
32
|
+
hydrateComposition,
|
|
33
|
+
searchAll,
|
|
34
|
+
} from './composition-library.js';
|
|
35
|
+
import { resolveComposition, templateToMessages } from './composer.js';
|
|
36
|
+
import {
|
|
37
|
+
recordTurn,
|
|
38
|
+
getTurns,
|
|
39
|
+
} from './session-store.js';
|
|
40
|
+
import { validateSchema } from '@adia-ai/a2ui/validate';
|
|
41
|
+
|
|
42
|
+
// Lazy-load the chunk-synthesizer bridge. It imports chunk-corpus data
|
|
43
|
+
// via composition-library's dual-mode loader, which is already top-level
|
|
44
|
+
// awaited; importing it here statically would not break anything but the
|
|
45
|
+
// async-import keeps the cold-start surface tight for the strong-match
|
|
46
|
+
// (no-LLM) path that doesn't need synthesis at all.
|
|
47
|
+
async function bridgeToChunkSynthesis({ intent, llmAdapter }) {
|
|
48
|
+
const { composeFromIntent } = await import('./chunk-synthesizer.js');
|
|
49
|
+
const result = await composeFromIntent({ intent, llmAdapter, maxAttempts: 2 });
|
|
50
|
+
// Shape-adapt chunk-synthesizer's `{ html, template, plan, source, ... }`
|
|
51
|
+
// to the synthesis-branch's prior `{ messages, template, synthesis }`
|
|
52
|
+
// contract. TKT-0009: prefer the real component array (`result.template`)
|
|
53
|
+
// over the pre-fix fallback of wrapping raw HTML in a single node with an
|
|
54
|
+
// UNREGISTERED `component: 'article'` type — that fallback made this
|
|
55
|
+
// caller's validate-and-repair pass below structurally unable to ever
|
|
56
|
+
// report a clean pass.
|
|
57
|
+
const messages = result.template
|
|
58
|
+
? [{ type: 'updateComponents', components: result.template }]
|
|
59
|
+
: result.html
|
|
60
|
+
? [{ type: 'updateComponents', components: [{ id: 'chunk-root', component: 'article', html: result.html }] }]
|
|
61
|
+
: [];
|
|
62
|
+
return {
|
|
63
|
+
messages,
|
|
64
|
+
template: result.plan ? [{ $chunk: 'composeFromIntent', plan: result.plan }] : [],
|
|
65
|
+
synthesis: {
|
|
66
|
+
source: result.source,
|
|
67
|
+
score: result.score,
|
|
68
|
+
warnings: result.warnings || [],
|
|
69
|
+
scopeDrift: result.scopeDrift || null,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Composition library auto-loads at module import time via top-level `await
|
|
75
|
+
// loadAll()` in composition-library.js (§72 dual-mode loader, commit
|
|
76
|
+
// `76dbcff2`). The previous `ensureBooted()` here called `loadAll()` WITHOUT
|
|
77
|
+
// `await`, which after §72 made it async — clearing the compositions map +
|
|
78
|
+
// racing the synchronous `searchAll` below. Symptom (caught in §87):
|
|
79
|
+
// eval:diff zettel coverage dropped 5% → 1% because the race-winner pattern
|
|
80
|
+
// emitted composition-match only for the intent whose `searchAll` happened
|
|
81
|
+
// to fire AFTER the async load resolved.
|
|
82
|
+
//
|
|
83
|
+
// Fix: rely entirely on the top-level await. Tests that want a forced reload
|
|
84
|
+
// can call `loadAll()` directly with `await` (it's idempotent).
|
|
85
|
+
|
|
86
|
+
// Retrieval score threshold — above this we trust the match and emit verbatim;
|
|
87
|
+
// below, fall through to LLM synthesis (creative composition from fragments).
|
|
88
|
+
// Calibrated on the 100-intent held-out set:
|
|
89
|
+
// strong matches: login-form=24 (exact), signup-form=27, chart-dashboard=48, pricing-tiers=54
|
|
90
|
+
// weak/false-positive matches: drop below 22 on off-topic queries
|
|
91
|
+
// Raised from 22 → 40 (2026-04-19) so that only near-perfect retrievals play
|
|
92
|
+
// verbatim; merely-good matches (login-form, signup-form) fall through to LLM
|
|
93
|
+
// synthesis instead of being emitted as canned output. Tradeoff: more LLM calls
|
|
94
|
+
// (slower, costlier) in exchange for compositional variety. The previous 22
|
|
95
|
+
// threshold maximized verbatim-cache hits at the cost of repetitive output.
|
|
96
|
+
const STRONG_MATCH_THRESHOLD = 40;
|
|
97
|
+
|
|
98
|
+
function toUpdateComponentsMessages(template) {
|
|
99
|
+
return [{
|
|
100
|
+
type: 'updateComponents',
|
|
101
|
+
components: template.map((n) => {
|
|
102
|
+
const {
|
|
103
|
+
id, component, children,
|
|
104
|
+
$fragment, bindings,
|
|
105
|
+
prependChildren, appendChildren,
|
|
106
|
+
...rest
|
|
107
|
+
} = n;
|
|
108
|
+
return { id, component, children: children || [], ...rest };
|
|
109
|
+
}),
|
|
110
|
+
}];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export async function generateZettel({ intent, mode = 'instant', llmAdapter = null, sessionId = null } = {}) {
|
|
114
|
+
// ── Session iteration note (post-§195, v0.5.6) ──
|
|
115
|
+
// Fragment-graph history-aware iteration (`synthesizeComposition` with
|
|
116
|
+
// `historySummary`) was retired in §37 when fragments retired. Turn≥2 now
|
|
117
|
+
// takes the same path as turn 1 — fresh retrieval → fresh chunk-synthesis.
|
|
118
|
+
// For true history-aware iteration (modify-an-existing-canvas), wire the
|
|
119
|
+
// request via `engine: 'chunk-zettel'` which uses `chunk-refiner.js`.
|
|
120
|
+
//
|
|
121
|
+
// Prior turns are still recorded (analytics + drift tracking via `getDrift`)
|
|
122
|
+
// but the iteration BRANCH is gone — no more spurious
|
|
123
|
+
// `iteration-synthesis-failure` auto-fires on every multi-turn request.
|
|
124
|
+
const priorTurns = sessionId ? getTurns(sessionId) : [];
|
|
125
|
+
|
|
126
|
+
const hits = searchAll(intent, { limit: 5 });
|
|
127
|
+
const composition = hits.find((h) => h.type === 'composition');
|
|
128
|
+
const strongMatch = composition && composition.score >= STRONG_MATCH_THRESHOLD;
|
|
129
|
+
|
|
130
|
+
// ── Strong retrieval match: emit verbatim (turn 1 only — iteration branch above handles repeats) ──
|
|
131
|
+
if (strongMatch) {
|
|
132
|
+
// On a static deploy the composition was registered from `_index.json`
|
|
133
|
+
// for SCORING only — its `template` is fetched lazily here, right before
|
|
134
|
+
// we resolve it. No-op in Node / Vite (template already populated). This
|
|
135
|
+
// keeps the static page-load to a single index request; only the
|
|
136
|
+
// actually-emitted match pays for its body. 2026-06-10.
|
|
137
|
+
await hydrateComposition(composition.name);
|
|
138
|
+
const comp = getComposition(composition.name);
|
|
139
|
+
const template = resolveComposition(comp);
|
|
140
|
+
// Parity guard: Node's `registerChunk` excludes template-less chunks, so
|
|
141
|
+
// they never reach this branch server-side. The static index-scoring gate
|
|
142
|
+
// is looser (it can't see templates in `_index.json`), so a handful of
|
|
143
|
+
// body-less partials (auth-card-header, onb-step-*, …) COULD surface as a
|
|
144
|
+
// strong match on a static deploy. If hydration produced no usable
|
|
145
|
+
// template, treat it as a non-match and fall through — keeping the
|
|
146
|
+
// static result identical to what Node would emit (synthesis / atoms),
|
|
147
|
+
// never an empty verbatim surface.
|
|
148
|
+
if (!Array.isArray(template) || template.length === 0) {
|
|
149
|
+
// fall through to the weak/no-match paths below
|
|
150
|
+
} else {
|
|
151
|
+
const messages = toUpdateComponentsMessages(template);
|
|
152
|
+
const validation = validateSchema(messages, { intent });
|
|
153
|
+
const rank = hits.findIndex((h) => h.type === 'composition' && h.name === composition.name) + 1;
|
|
154
|
+
const fragments = (comp.template || []).filter((n) => n.$fragment).map((n) => n.$fragment);
|
|
155
|
+
recordTurn(sessionId, {
|
|
156
|
+
intent,
|
|
157
|
+
messages,
|
|
158
|
+
template: comp.template,
|
|
159
|
+
composition: composition.name,
|
|
160
|
+
strategy: 'composition-match',
|
|
161
|
+
fragments,
|
|
162
|
+
validation,
|
|
163
|
+
});
|
|
164
|
+
return {
|
|
165
|
+
messages,
|
|
166
|
+
validation,
|
|
167
|
+
strategy: 'composition-match',
|
|
168
|
+
retrieval: { hit: true, rank, candidate: composition.name },
|
|
169
|
+
composition: composition.name,
|
|
170
|
+
retrievalScore: composition.score,
|
|
171
|
+
fragments_used: fragments,
|
|
172
|
+
candidates: hits,
|
|
173
|
+
sessionTurns: priorTurns.length + 1,
|
|
174
|
+
};
|
|
175
|
+
} // end else (template present)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ── Weak/no retrieval: bridge to chunk-zettel synthesis (the §37 successor) ──
|
|
179
|
+
if (llmAdapter && mode !== 'instant-only') {
|
|
180
|
+
try {
|
|
181
|
+
const synth = await bridgeToChunkSynthesis({ intent, llmAdapter });
|
|
182
|
+
// Full schema/catalog/anti-pattern conformance (validate-only — see
|
|
183
|
+
// validate-and-repair.js; TKT-0009 made this meaningful for the first
|
|
184
|
+
// time by giving synth.messages a real component graph instead of an
|
|
185
|
+
// opaque HTML wrapper).
|
|
186
|
+
const { validateAndRepair } = await import('../../shared/validate-and-repair.js');
|
|
187
|
+
const schemaCheck = synth.messages.length ? await validateAndRepair({ messages: synth.messages }) : { valid: false, validation: { score: 0 } };
|
|
188
|
+
const validation = schemaCheck.validation;
|
|
189
|
+
// Chunk-bridge produces an html-bearing single component, not
|
|
190
|
+
// resolved fragment instances. `fragments_used` is empty by design;
|
|
191
|
+
// consumers tracking fragment usage should switch to the
|
|
192
|
+
// chunk-zettel engine which surfaces `_debug.plan` directly.
|
|
193
|
+
recordTurn(sessionId, {
|
|
194
|
+
intent,
|
|
195
|
+
messages: synth.messages,
|
|
196
|
+
template: synth.template,
|
|
197
|
+
composition: null,
|
|
198
|
+
strategy: 'composition-synthesized',
|
|
199
|
+
fragments: [],
|
|
200
|
+
validation,
|
|
201
|
+
});
|
|
202
|
+
return {
|
|
203
|
+
messages: synth.messages,
|
|
204
|
+
validation,
|
|
205
|
+
strategy: 'composition-synthesized',
|
|
206
|
+
retrieval: {
|
|
207
|
+
hit: false,
|
|
208
|
+
rank: composition ? hits.findIndex((h) => h.type === 'composition' && h.name === composition.name) + 1 : null,
|
|
209
|
+
candidate: composition?.name ?? null,
|
|
210
|
+
reason: composition ? `top score ${composition.score} below threshold ${STRONG_MATCH_THRESHOLD}` : 'no composition retrieved',
|
|
211
|
+
},
|
|
212
|
+
composition: null,
|
|
213
|
+
fragments_used: [],
|
|
214
|
+
synthesized_template: synth.template,
|
|
215
|
+
synthesis: synth.synthesis,
|
|
216
|
+
candidates: hits,
|
|
217
|
+
sessionTurns: priorTurns.length + 1,
|
|
218
|
+
};
|
|
219
|
+
} catch (err) {
|
|
220
|
+
return {
|
|
221
|
+
messages: [],
|
|
222
|
+
validation: { score: 0 },
|
|
223
|
+
strategy: 'synthesis-failed',
|
|
224
|
+
retrieval: { hit: false, rank: null, candidate: hits[0]?.name ?? null },
|
|
225
|
+
candidates: hits,
|
|
226
|
+
error: err.message,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ── No LLM, no strong match: return atoms for downstream assembly ──
|
|
232
|
+
return {
|
|
233
|
+
messages: [],
|
|
234
|
+
validation: { score: 0 },
|
|
235
|
+
strategy: 'fragment-candidates',
|
|
236
|
+
retrieval: { hit: false, rank: null, candidate: hits[0]?.name ?? null },
|
|
237
|
+
candidates: hits,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Re-export session management so server.js / MCP tools can reset a session
|
|
242
|
+
export { clearSession, getTurns, getDrift } from './session-store.js';
|