@agent-native/core 0.80.2 → 0.80.5
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +66 -2
- package/corpus/core/docs/content/locales/ar-SA/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/real-time-collaboration.mdx +3 -3
- package/corpus/core/docs/content/locales/de-DE/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/es-ES/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +1 -1
- package/corpus/core/docs/content/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/template-design.mdx +1 -1
- package/corpus/core/package.json +3 -7
- package/corpus/core/src/action.ts +32 -0
- package/corpus/core/src/agent/durable-background.ts +32 -11
- package/corpus/core/src/agent/production-agent.ts +14 -1
- package/corpus/core/src/agent/run-loop-with-resume.ts +3 -1
- package/corpus/core/src/brand-kit/fig/index.ts +17 -37
- package/corpus/core/src/cli/index.ts +1 -1
- package/corpus/core/src/cli/mcp-config-writers.ts +187 -51
- package/corpus/core/src/cli/plan-local.ts +445 -108
- package/corpus/core/src/cli/skills.ts +32 -8
- package/corpus/core/src/client/AssistantChat.tsx +11 -1
- package/corpus/core/src/client/agent-chat.ts +12 -1
- package/corpus/core/src/client/composer/PromptComposer.tsx +100 -41
- package/corpus/core/src/client/org/OrgSwitcher.tsx +1 -1
- package/corpus/core/src/client/sharing/ShareButton.tsx +3 -27
- package/corpus/core/src/collab/presence.ts +1 -1
- package/corpus/core/src/mcp/connect-route.ts +34 -5
- package/corpus/core/src/server/action-discovery.ts +4 -0
- package/corpus/core/src/server/action-routes.ts +14 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +20 -0
- package/corpus/core/src/vite/client.ts +15 -1
- package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +2 -0
- package/corpus/templates/analytics/actions/update-dashboard.ts +8 -0
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +117 -33
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +4 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +7 -0
- package/corpus/templates/analytics/changelog/2026-06-27-dashboards-can-now-nest-under-a-parent-in-the-sidebar-via-a-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-analytics-pages-now-sit-closer-under-the-header-with-tighter.md +6 -0
- package/corpus/templates/assets/actions/generate-image-batch.ts +3 -0
- package/corpus/templates/assets/actions/generate-image.ts +3 -0
- package/corpus/templates/assets/changelog/2026-06-29-longer-agent-generation-window.md +6 -0
- package/corpus/templates/assets/netlify.toml +3 -3
- package/corpus/templates/assets/server/plugins/agent-chat.ts +4 -1
- package/corpus/templates/clips/app/components/capture-install-options.tsx +7 -8
- package/corpus/templates/clips/app/components/player/timestamped-comment-button.tsx +162 -0
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +1 -1
- package/corpus/templates/clips/app/i18n/ar-SA.ts +4 -0
- package/corpus/templates/clips/app/i18n/de-DE.ts +4 -0
- package/corpus/templates/clips/app/i18n/en-US.ts +4 -0
- package/corpus/templates/clips/app/i18n/es-ES.ts +4 -0
- package/corpus/templates/clips/app/i18n/fr-FR.ts +4 -0
- package/corpus/templates/clips/app/i18n/hi-IN.ts +4 -0
- package/corpus/templates/clips/app/i18n/ja-JP.ts +4 -0
- package/corpus/templates/clips/app/i18n/ko-KR.ts +4 -0
- package/corpus/templates/clips/app/i18n/pt-BR.ts +4 -0
- package/corpus/templates/clips/app/i18n/zh-CN.ts +4 -0
- package/corpus/templates/clips/app/i18n/zh-TW.ts +4 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +42 -18
- package/corpus/templates/content/AGENTS.md +12 -0
- package/corpus/templates/content/app/blocks/BuilderDocsBlocks.tsx +10 -0
- package/corpus/templates/content/app/components/editor/BubbleToolbar.tsx +1 -0
- package/corpus/templates/content/app/components/editor/ContentReferencePreview.tsx +185 -0
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +3 -0
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +19 -0
- package/corpus/templates/content/app/components/editor/extensions/ContentReferenceNode.tsx +82 -0
- package/corpus/templates/content/app/global.css +9 -0
- package/corpus/templates/content/app/i18n/zh-TW.ts +12 -0
- package/corpus/templates/content/app/i18n-data.ts +140 -0
- package/corpus/templates/content/changelog/2026-06-29-reusable-mdx-references-now-preview-linked-local-documents-i.md +6 -0
- package/corpus/templates/content/shared/builder-docs-blocks.ts +8 -0
- package/corpus/templates/content/shared/builder-mdx.ts +141 -4
- package/corpus/templates/content/shared/nfm.ts +62 -0
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +10 -11
- package/corpus/templates/design/AGENTS.md +5 -0
- package/corpus/templates/design/_gitignore +7 -0
- package/corpus/templates/design/actions/apply-visual-edit.ts +22 -12
- package/corpus/templates/design/actions/create-design-system.ts +15 -4
- package/corpus/templates/design/actions/create-file.ts +20 -1
- package/corpus/templates/design/actions/delete-design-system.ts +2 -2
- package/corpus/templates/design/actions/duplicate-design.ts +35 -9
- package/corpus/templates/design/actions/generate-design.ts +146 -69
- package/corpus/templates/design/actions/generate-screens.ts +51 -19
- package/corpus/templates/design/actions/get-design-snapshot.ts +5 -1
- package/corpus/templates/design/actions/get-design.ts +2 -0
- package/corpus/templates/design/actions/import-design-project.ts +28 -9
- package/corpus/templates/design/actions/import-document.ts +22 -8
- package/corpus/templates/design/actions/index-design-system-with-builder.ts +6 -153
- package/corpus/templates/design/actions/navigate.ts +105 -54
- package/corpus/templates/design/actions/set-default-design-system.ts +17 -3
- package/corpus/templates/design/actions/show-design-questions.ts +2 -0
- package/corpus/templates/design/actions/update-design.ts +2 -1
- package/corpus/templates/design/actions/view-screen.ts +12 -6
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +4 -4
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +159 -41
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +8 -4
- package/corpus/templates/design/app/components/design/DrawOverlay.tsx +37 -42
- package/corpus/templates/design/app/components/design/EditPanel.tsx +336 -183
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +153 -34
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +135 -33
- package/corpus/templates/design/app/components/design/QuestionFlow.tsx +6 -0
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +2 -1
- package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +4 -10
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +84 -43
- package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +4 -4
- package/corpus/templates/design/app/components/design/inspector/{FigmaColorPicker.tsx → DesignColorPicker.tsx} +89 -62
- package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +14 -26
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +40 -12
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +13 -4
- package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +13 -13
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +13 -9
- package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +13 -4
- package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +6 -6
- package/corpus/templates/design/app/components/design/inspector/{figma-icons.tsx → design-icons.tsx} +2 -2
- package/corpus/templates/design/app/components/design/inspector/index.ts +12 -12
- package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +5 -2
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +3 -3
- package/corpus/templates/design/app/components/layout/Layout.tsx +5 -2
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +167 -91
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +16 -3
- package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +15 -0
- package/corpus/templates/design/app/global.css +4 -0
- package/corpus/templates/design/app/hooks/use-design-system.ts +4 -1
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +38 -3
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +9 -2
- package/corpus/templates/design/app/i18n/zh-TW.ts +22 -0
- package/corpus/templates/design/app/i18n-data.ts +527 -0
- package/corpus/templates/design/app/lib/design-systems.ts +6 -4
- package/corpus/templates/design/app/lib/design-templates.ts +15 -3
- package/corpus/templates/design/app/pages/DesignEditor.tsx +641 -158
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +42 -34
- package/corpus/templates/design/app/pages/VisualEdit.tsx +100 -0
- package/corpus/templates/design/app/root.tsx +42 -9
- package/corpus/templates/design/app/routes/visual-edit.tsx +7 -0
- package/corpus/templates/design/changelog/2026-06-28-live-cursors-now-keep-names-beside-a-cleaner-pointer-marker.md +1 -1
- package/corpus/templates/design/changelog/2026-06-28-mode-switching-now-lives-in-a-compact-bottom-right-icon-dock.md +1 -1
- package/corpus/templates/design/changelog/2026-06-28-visual-code-design-mode.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-generation-prompts-now-show-connect-ai-before-sending.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-mode-top-chrome-now-groups-collaborators-preview-shar.md +1 -1
- package/corpus/templates/design/changelog/2026-06-29-fixed-design-editor-exports-and-gradient-edits-so-multi-scre.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-longer-hosted-agent-turns.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-png-export-handles-modern-css-color-functions-more-reliably.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-png-export-now-ignores-duplicate-clicks-while-a-download-is-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-public-visual-edit-and-shared-design-links-now-invite-visito.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-visual-edit-actions-now-reject-missing-design-targets-before.md +6 -0
- package/corpus/templates/design/e2e/README.md +71 -0
- package/corpus/templates/design/e2e/global-setup.ts +157 -0
- package/corpus/templates/design/e2e/helpers.ts +148 -0
- package/corpus/templates/design/netlify.toml +3 -4
- package/corpus/templates/design/package.json +5 -1
- package/corpus/templates/design/playwright.config.ts +51 -0
- package/corpus/templates/design/server/handlers/index-design-system-with-builder.ts +121 -0
- package/corpus/templates/design/server/handlers/uploads.ts +89 -38
- package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +181 -0
- package/corpus/templates/design/server/lib/coding-handoff.ts +33 -4
- package/corpus/templates/design/server/lib/design-export.ts +35 -8
- package/corpus/templates/design/server/plugins/agent-chat.ts +4 -0
- package/corpus/templates/design/server/plugins/auth.ts +10 -1
- package/corpus/templates/design/server/routes/api/index-design-system-with-builder.post.ts +1 -0
- package/corpus/templates/design/shared/api.ts +2 -0
- package/corpus/templates/design/shared/apply-edits.ts +12 -8
- package/corpus/templates/design/shared/canvas-math.ts +19 -1
- package/corpus/templates/design/shared/code-layer.ts +87 -28
- package/corpus/templates/design/shared/generation-session.ts +1 -0
- package/corpus/templates/design/shared/resolve-tweaks.ts +4 -3
- package/corpus/templates/design/shared/shader-presets.ts +10 -0
- package/corpus/templates/design/shared/source-mode.ts +9 -0
- package/corpus/templates/design/vitest.config.ts +2 -1
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +1 -1
- package/corpus/templates/plan/.agents/skills/visual-plan/references/canvas.md +1 -1
- package/corpus/templates/plan/.agents/skills/visual-plan/references/local-files.md +14 -5
- package/corpus/templates/plan/.agents/skills/visual-recap/references/local-files.md +14 -5
- package/corpus/templates/plan/AGENTS.md +1 -1
- package/corpus/templates/plan/actions/create-plan-design.ts +1 -1
- package/corpus/templates/plan/actions/validate-local-plan-source.ts +110 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +1 -0
- package/corpus/templates/plan/docs/commenting-ux-plan.md +2 -2
- package/corpus/templates/plan/server/lib/plan-connector-catalog.ts +1 -0
- package/corpus/templates/plan/server/lib/public-action-paths.ts +1 -0
- package/corpus/templates/plan/server/plan-content.ts +1 -1
- package/corpus/templates/plan/server/ui-plan-html.ts +2 -2
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +6 -153
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +53 -38
- package/corpus/templates/slides/app/components/design-system/{fig-import-response.ts → builder-index-response.ts} +9 -6
- package/corpus/templates/slides/app/components/visual-editor/MultiSelectChip.tsx +1 -1
- package/corpus/templates/slides/changelog/2026-06-29-design-system-setup-now-indexes-uploaded-design-files-throug.md +6 -0
- package/corpus/templates/slides/changelog/2026-06-29-longer-hosted-agent-turns.md +6 -0
- package/corpus/templates/slides/netlify.toml +3 -6
- package/corpus/templates/slides/server/handlers/index-design-system-with-builder.ts +116 -0
- package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +179 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +4 -1
- package/corpus/templates/slides/server/routes/api/index-design-system-with-builder.post.ts +1 -0
- package/dist/action.d.ts +23 -0
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +9 -0
- package/dist/action.js.map +1 -1
- package/dist/agent/durable-background.d.ts +9 -7
- package/dist/agent/durable-background.d.ts.map +1 -1
- package/dist/agent/durable-background.js +27 -11
- package/dist/agent/durable-background.js.map +1 -1
- package/dist/agent/production-agent.d.ts +10 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +4 -1
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-loop-with-resume.d.ts +2 -1
- package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
- package/dist/agent/run-loop-with-resume.js +2 -2
- package/dist/agent/run-loop-with-resume.js.map +1 -1
- package/dist/brand-kit/fig/index.d.ts +4 -4
- package/dist/brand-kit/fig/index.d.ts.map +1 -1
- package/dist/brand-kit/fig/index.js +14 -27
- package/dist/brand-kit/fig/index.js.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-config-writers.d.ts +15 -7
- package/dist/cli/mcp-config-writers.d.ts.map +1 -1
- package/dist/cli/mcp-config-writers.js +198 -45
- package/dist/cli/mcp-config-writers.js.map +1 -1
- package/dist/cli/plan-local.d.ts +30 -0
- package/dist/cli/plan-local.d.ts.map +1 -1
- package/dist/cli/plan-local.js +281 -56
- package/dist/cli/plan-local.js.map +1 -1
- package/dist/cli/skills.d.ts +2 -2
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +32 -8
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +11 -1
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +15 -2
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +35 -1
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/org/OrgSwitcher.js +1 -1
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +1 -1
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +2 -15
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/collab/presence.d.ts +1 -1
- package/dist/collab/presence.js +1 -1
- package/dist/collab/presence.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/mcp/connect-route.d.ts.map +1 -1
- package/dist/mcp/connect-route.js +34 -5
- package/dist/mcp/connect-route.js.map +1 -1
- package/dist/observability/routes.d.ts +2 -2
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +5 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +14 -0
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +6 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +12 -3
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +12 -1
- package/dist/vite/client.js.map +1 -1
- package/docs/content/locales/ar-SA/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/ar-SA/template-design.mdx +1 -1
- package/docs/content/locales/de-DE/real-time-collaboration.mdx +3 -3
- package/docs/content/locales/de-DE/template-design.mdx +1 -1
- package/docs/content/locales/es-ES/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/es-ES/template-design.mdx +1 -1
- package/docs/content/locales/fr-FR/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/fr-FR/template-design.mdx +1 -1
- package/docs/content/locales/hi-IN/template-design.mdx +1 -1
- package/docs/content/locales/ja-JP/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/ja-JP/template-design.mdx +1 -1
- package/docs/content/locales/ko-KR/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/ko-KR/template-design.mdx +1 -1
- package/docs/content/locales/pt-BR/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/pt-BR/template-design.mdx +1 -1
- package/docs/content/locales/zh-CN/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/zh-CN/template-design.mdx +1 -1
- package/docs/content/locales/zh-TW/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/zh-TW/template-design.mdx +1 -1
- package/docs/content/real-time-collaboration.mdx +2 -2
- package/docs/content/template-design.mdx +1 -1
- package/package.json +3 -7
- package/corpus/core/src/brand-kit/fig/decode.ts +0 -410
- package/corpus/core/src/brand-kit/fig/extract-design-system.ts +0 -947
- package/corpus/core/src/brand-kit/fig/fig-to-html.ts +0 -1906
- package/corpus/templates/design/actions/import-figma.ts +0 -55
- package/corpus/templates/design/changelog/2026-06-28-figma-style-code-design-mode.md +0 -6
- package/corpus/templates/design/server/handlers/import-figma-system.ts +0 -86
- package/corpus/templates/design/server/routes/api/import-figma-system.post.ts +0 -1
- package/corpus/templates/slides/server/handlers/import-figma-system.ts +0 -101
- package/corpus/templates/slides/server/routes/api/import-figma-system.post.ts +0 -1
- package/dist/brand-kit/fig/decode.d.ts +0 -33
- package/dist/brand-kit/fig/decode.d.ts.map +0 -1
- package/dist/brand-kit/fig/decode.js +0 -358
- package/dist/brand-kit/fig/decode.js.map +0 -1
- package/dist/brand-kit/fig/extract-design-system.d.ts +0 -44
- package/dist/brand-kit/fig/extract-design-system.d.ts.map +0 -1
- package/dist/brand-kit/fig/extract-design-system.js +0 -752
- package/dist/brand-kit/fig/extract-design-system.js.map +0 -1
- package/dist/brand-kit/fig/fig-to-html.d.ts +0 -246
- package/dist/brand-kit/fig/fig-to-html.d.ts.map +0 -1
- package/dist/brand-kit/fig/fig-to-html.js +0 -1506
- package/dist/brand-kit/fig/fig-to-html.js.map +0 -1
package/dist/cli/plan-local.js
CHANGED
|
@@ -711,10 +711,16 @@ function lintColumnsBlocks(file, source, issues) {
|
|
|
711
711
|
const openingEnd = findJsxOpeningTagEnd(scanSource, start);
|
|
712
712
|
if (openingEnd < 0)
|
|
713
713
|
continue;
|
|
714
|
-
const opening =
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
714
|
+
const opening = source.slice(start, openingEnd + 1);
|
|
715
|
+
const columnsAttr = readJsxAttribute(opening, "columns");
|
|
716
|
+
if (!columnsAttr)
|
|
717
|
+
continue;
|
|
718
|
+
const entries = columnsAttr.kind === "expression"
|
|
719
|
+
? extractTopLevelObjectLiterals(columnsAttr.value)
|
|
720
|
+
: null;
|
|
721
|
+
if (entries && entries.length > 0)
|
|
722
|
+
continue;
|
|
723
|
+
addValidationIssue(issues, file, source, start, 'Columns must use <Column> children or a columns={[{ id, label, blocks }]} array, not a bare columns= prop. Use <Columns><Column label="Before">...</Column><Column label="After">...</Column></Columns>.');
|
|
718
724
|
}
|
|
719
725
|
}
|
|
720
726
|
function findBalancedEnd(source, start, open, close) {
|
|
@@ -983,6 +989,56 @@ function hasRequiredEnumLiteral(objectSource, name, allowed) {
|
|
|
983
989
|
return false;
|
|
984
990
|
return allowed.includes(trimmed.slice(1, -1).trim());
|
|
985
991
|
}
|
|
992
|
+
// Shared per-item checks so the top-level `<Checklist items={[…]} />` tag and
|
|
993
|
+
// blocks authored as JSON inside a container's `tabs={[…]}` / `columns={[…]}`
|
|
994
|
+
// array enforce the SAME required fields. `listBase` is the absolute offset of
|
|
995
|
+
// the items array in the original source so line numbers point near the item.
|
|
996
|
+
function checkChecklistItemList(items, listBase, file, source, issues) {
|
|
997
|
+
items.forEach((item, index) => {
|
|
998
|
+
const base = listBase + item.start;
|
|
999
|
+
if (!hasRequiredStaticId(item.source)) {
|
|
1000
|
+
addValidationIssue(issues, file, source, base, `Checklist items[${index}].id is required by the Plan renderer schema; add a stable string id.`);
|
|
1001
|
+
}
|
|
1002
|
+
if (!hasRequiredStaticString(item.source, "label")) {
|
|
1003
|
+
addValidationIssue(issues, file, source, base, `Checklist items[${index}].label is required by the Plan renderer schema; add a non-empty string label.`);
|
|
1004
|
+
}
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
1007
|
+
function checkQuestionObjectList(questionObjects, listBase, tag, file, source, issues) {
|
|
1008
|
+
questionObjects.forEach((question, questionIndex) => {
|
|
1009
|
+
const questionBase = listBase + question.start;
|
|
1010
|
+
if (!hasRequiredStaticId(question.source)) {
|
|
1011
|
+
addValidationIssue(issues, file, source, questionBase, `${tag} questions[${questionIndex}].id is required by the Plan renderer schema; add a stable string id.`);
|
|
1012
|
+
}
|
|
1013
|
+
if (!hasRequiredStaticString(question.source, "title")) {
|
|
1014
|
+
addValidationIssue(issues, file, source, questionBase, `${tag} questions[${questionIndex}].title is required by the Plan renderer schema; add a non-empty string title.`);
|
|
1015
|
+
}
|
|
1016
|
+
if (!hasRequiredEnumLiteral(question.source, "mode", [
|
|
1017
|
+
"single",
|
|
1018
|
+
"multi",
|
|
1019
|
+
"freeform",
|
|
1020
|
+
])) {
|
|
1021
|
+
addValidationIssue(issues, file, source, questionBase, `${tag} questions[${questionIndex}].mode is required by the Plan renderer schema; use "single", "multi", or "freeform".`);
|
|
1022
|
+
}
|
|
1023
|
+
const options = readTopLevelObjectProperty(question.source, "options");
|
|
1024
|
+
if (!options)
|
|
1025
|
+
return;
|
|
1026
|
+
const optionObjects = extractTopLevelObjectLiterals(options.value);
|
|
1027
|
+
if (!optionObjects) {
|
|
1028
|
+
addValidationIssue(issues, file, source, questionBase + options.valueStart, `${tag} questions[${questionIndex}].options must be an inline array of object literals.`);
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
optionObjects.forEach((option, optionIndex) => {
|
|
1032
|
+
const optionBase = questionBase + options.valueStart + option.start;
|
|
1033
|
+
if (!hasRequiredStaticId(option.source)) {
|
|
1034
|
+
addValidationIssue(issues, file, source, optionBase, `${tag} questions[${questionIndex}].options[${optionIndex}].id is required by the Plan renderer schema; add a stable string id.`);
|
|
1035
|
+
}
|
|
1036
|
+
if (!hasRequiredStaticString(option.source, "label")) {
|
|
1037
|
+
addValidationIssue(issues, file, source, optionBase, `${tag} questions[${questionIndex}].options[${optionIndex}].label is required by the Plan renderer schema; add a non-empty string label.`);
|
|
1038
|
+
}
|
|
1039
|
+
});
|
|
1040
|
+
});
|
|
1041
|
+
}
|
|
986
1042
|
function lintChecklistShape(file, source, issues) {
|
|
987
1043
|
const scanSource = maskCodeRegions(source);
|
|
988
1044
|
const re = /<Checklist\b/g;
|
|
@@ -1005,15 +1061,7 @@ function lintChecklistShape(file, source, issues) {
|
|
|
1005
1061
|
addValidationIssue(issues, file, source, start + items.start, "Checklist items must be an inline array of object literals so local check can validate the renderer schema.");
|
|
1006
1062
|
continue;
|
|
1007
1063
|
}
|
|
1008
|
-
objects.
|
|
1009
|
-
const base = start + items.start + item.start;
|
|
1010
|
-
if (!hasRequiredStaticId(item.source)) {
|
|
1011
|
-
addValidationIssue(issues, file, source, base, `Checklist items[${index}].id is required by the Plan renderer schema; add a stable string id.`);
|
|
1012
|
-
}
|
|
1013
|
-
if (!hasRequiredStaticString(item.source, "label")) {
|
|
1014
|
-
addValidationIssue(issues, file, source, base, `Checklist items[${index}].label is required by the Plan renderer schema; add a non-empty string label.`);
|
|
1015
|
-
}
|
|
1016
|
-
});
|
|
1064
|
+
checkChecklistItemList(objects, start + items.start, file, source, issues);
|
|
1017
1065
|
}
|
|
1018
1066
|
}
|
|
1019
1067
|
function lintQuestionFormShape(file, source, issues) {
|
|
@@ -1041,43 +1089,114 @@ function lintQuestionFormShape(file, source, issues) {
|
|
|
1041
1089
|
addValidationIssue(issues, file, source, start + questions.start, `${tag} questions must be a non-empty inline array of object literals.`);
|
|
1042
1090
|
continue;
|
|
1043
1091
|
}
|
|
1044
|
-
questionObjects.
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1092
|
+
checkQuestionObjectList(questionObjects, start + questions.start, tag, file, source, issues);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
function staticStringLiteralValue(value) {
|
|
1096
|
+
if (value === undefined)
|
|
1097
|
+
return undefined;
|
|
1098
|
+
const trimmed = value.trim();
|
|
1099
|
+
const quote = trimmed[0];
|
|
1100
|
+
if (quote !== '"' && quote !== "'" && quote !== "`")
|
|
1101
|
+
return undefined;
|
|
1102
|
+
if (!trimmed.endsWith(quote) || trimmed.length < 2)
|
|
1103
|
+
return undefined;
|
|
1104
|
+
if (quote === "`" && /\$\{/.test(trimmed))
|
|
1105
|
+
return undefined;
|
|
1106
|
+
return trimmed.slice(1, -1);
|
|
1107
|
+
}
|
|
1108
|
+
// Container blocks authored with a JSON attribute array (`<TabsBlock tabs={[…]}
|
|
1109
|
+
// />`) carry their children as nested block objects, not top-level JSX tags, so
|
|
1110
|
+
// the tag-based linters above never inspect them — the exact "false green" the
|
|
1111
|
+
// renderer catches because it validates the whole parsed block tree. Walk those
|
|
1112
|
+
// nested `blocks: [...]` arrays and enforce the same per-block required fields,
|
|
1113
|
+
// recursing through nested containers. This is still a subset of the renderer
|
|
1114
|
+
// schema (which is why `verify` is the authority), but it closes the common
|
|
1115
|
+
// nested checklist / question-form / missing-id case offline.
|
|
1116
|
+
const NESTED_CONTAINER_TAGS = [
|
|
1117
|
+
{ tag: "TabsBlock", attr: "tabs" },
|
|
1118
|
+
{ tag: "Tabs", attr: "tabs" },
|
|
1119
|
+
{ tag: "Columns", attr: "columns" },
|
|
1120
|
+
];
|
|
1121
|
+
function lintNestedContainerEntry(entrySource, entryBase, file, source, issues) {
|
|
1122
|
+
const blocksProp = readTopLevelObjectProperty(entrySource, "blocks");
|
|
1123
|
+
if (!blocksProp)
|
|
1124
|
+
return;
|
|
1125
|
+
const blockObjects = extractTopLevelObjectLiterals(blocksProp.value);
|
|
1126
|
+
if (!blockObjects)
|
|
1127
|
+
return;
|
|
1128
|
+
const blocksBase = entryBase + blocksProp.valueStart;
|
|
1129
|
+
for (const block of blockObjects) {
|
|
1130
|
+
lintNestedBlock(block.source, blocksBase + block.start, file, source, issues);
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
function lintNestedBlock(blockSource, blockBase, file, source, issues) {
|
|
1134
|
+
const typeProp = readTopLevelObjectProperty(blockSource, "type");
|
|
1135
|
+
const type = staticStringLiteralValue(typeProp?.value);
|
|
1136
|
+
if (!hasRequiredStaticId(blockSource)) {
|
|
1137
|
+
addValidationIssue(issues, file, source, blockBase, `Nested ${type ?? "block"} is missing a required string \`id\`; the Plan renderer schema validates every nested block.`);
|
|
1138
|
+
}
|
|
1139
|
+
const dataProp = readTopLevelObjectProperty(blockSource, "data");
|
|
1140
|
+
if (!dataProp)
|
|
1141
|
+
return;
|
|
1142
|
+
const dataBase = blockBase + dataProp.valueStart;
|
|
1143
|
+
if (type === "checklist") {
|
|
1144
|
+
const itemsProp = readTopLevelObjectProperty(dataProp.value, "items");
|
|
1145
|
+
if (!itemsProp)
|
|
1146
|
+
return;
|
|
1147
|
+
const items = extractTopLevelObjectLiterals(itemsProp.value);
|
|
1148
|
+
if (items) {
|
|
1149
|
+
checkChecklistItemList(items, dataBase + itemsProp.valueStart, file, source, issues);
|
|
1150
|
+
}
|
|
1151
|
+
return;
|
|
1152
|
+
}
|
|
1153
|
+
// visual-questions shares question-form's schema; lint both.
|
|
1154
|
+
if (type === "question-form" || type === "visual-questions") {
|
|
1155
|
+
const questionsProp = readTopLevelObjectProperty(dataProp.value, "questions");
|
|
1156
|
+
if (!questionsProp)
|
|
1157
|
+
return;
|
|
1158
|
+
const questionObjects = extractTopLevelObjectLiterals(questionsProp.value);
|
|
1159
|
+
if (questionObjects) {
|
|
1160
|
+
checkQuestionObjectList(questionObjects, dataBase + questionsProp.valueStart, type, file, source, issues);
|
|
1161
|
+
}
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
if (type === "tabs" || type === "columns") {
|
|
1165
|
+
const innerAttr = type === "tabs" ? "tabs" : "columns";
|
|
1166
|
+
const innerProp = readTopLevelObjectProperty(dataProp.value, innerAttr);
|
|
1167
|
+
if (!innerProp)
|
|
1168
|
+
return;
|
|
1169
|
+
const innerEntries = extractTopLevelObjectLiterals(innerProp.value);
|
|
1170
|
+
if (!innerEntries)
|
|
1171
|
+
return;
|
|
1172
|
+
const innerBase = dataBase + innerProp.valueStart;
|
|
1173
|
+
for (const entry of innerEntries) {
|
|
1174
|
+
lintNestedContainerEntry(entry.source, innerBase + entry.start, file, source, issues);
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
function lintNestedContainerBlocks(file, source, issues) {
|
|
1179
|
+
const scanSource = maskCodeRegions(source);
|
|
1180
|
+
for (const { tag, attr } of NESTED_CONTAINER_TAGS) {
|
|
1181
|
+
const re = new RegExp(`<${tag}\\b`, "g");
|
|
1182
|
+
let match;
|
|
1183
|
+
while ((match = re.exec(scanSource))) {
|
|
1184
|
+
const start = match.index;
|
|
1185
|
+
const openingEnd = findJsxOpeningTagEnd(scanSource, start);
|
|
1186
|
+
if (openingEnd < 0)
|
|
1187
|
+
continue;
|
|
1188
|
+
const opening = source.slice(start, openingEnd + 1);
|
|
1189
|
+
const attrValue = readJsxAttribute(opening, attr);
|
|
1190
|
+
if (!attrValue || attrValue.kind !== "expression")
|
|
1191
|
+
continue;
|
|
1192
|
+
const entries = extractTopLevelObjectLiterals(attrValue.value);
|
|
1193
|
+
if (!entries)
|
|
1194
|
+
continue;
|
|
1195
|
+
const entriesBase = start + attrValue.start;
|
|
1196
|
+
for (const entry of entries) {
|
|
1197
|
+
lintNestedContainerEntry(entry.source, entriesBase + entry.start, file, source, issues);
|
|
1066
1198
|
}
|
|
1067
|
-
|
|
1068
|
-
const optionBase = start +
|
|
1069
|
-
questions.start +
|
|
1070
|
-
question.start +
|
|
1071
|
-
options.valueStart +
|
|
1072
|
-
option.start;
|
|
1073
|
-
if (!hasRequiredStaticId(option.source)) {
|
|
1074
|
-
addValidationIssue(issues, file, source, optionBase, `${tag} questions[${questionIndex}].options[${optionIndex}].id is required by the Plan renderer schema; add a stable string id.`);
|
|
1075
|
-
}
|
|
1076
|
-
if (!hasRequiredStaticString(option.source, "label")) {
|
|
1077
|
-
addValidationIssue(issues, file, source, optionBase, `${tag} questions[${questionIndex}].options[${optionIndex}].label is required by the Plan renderer schema; add a non-empty string label.`);
|
|
1078
|
-
}
|
|
1079
|
-
});
|
|
1080
|
-
});
|
|
1199
|
+
}
|
|
1081
1200
|
}
|
|
1082
1201
|
}
|
|
1083
1202
|
// Blank out fenced code blocks and inline code spans (preserving newlines and
|
|
@@ -1098,6 +1217,7 @@ export function validateLocalPlanFiles(files) {
|
|
|
1098
1217
|
lintColumnsBlocks(entry.file, source, issues);
|
|
1099
1218
|
lintChecklistShape(entry.file, entry.source, issues);
|
|
1100
1219
|
lintQuestionFormShape(entry.file, entry.source, issues);
|
|
1220
|
+
lintNestedContainerBlocks(entry.file, entry.source, issues);
|
|
1101
1221
|
}
|
|
1102
1222
|
return issues;
|
|
1103
1223
|
}
|
|
@@ -1247,7 +1367,8 @@ export function writeLocalPlanPreview(input) {
|
|
|
1247
1367
|
function buildLocalPlanBridgePayload(input) {
|
|
1248
1368
|
const dir = path.resolve(input.dir);
|
|
1249
1369
|
const files = readLocalPlanFiles(dir);
|
|
1250
|
-
|
|
1370
|
+
if (!input.skipSourceValidation)
|
|
1371
|
+
assertLocalPlanFilesValid(files);
|
|
1251
1372
|
const parsed = stripFrontmatter(files.planMdx);
|
|
1252
1373
|
const kind = input.kind || normalizeKind(parsed.frontmatter.kind);
|
|
1253
1374
|
const title = input.title ||
|
|
@@ -1317,6 +1438,7 @@ export async function startLocalPlanBridge(input) {
|
|
|
1317
1438
|
kind: input.kind,
|
|
1318
1439
|
title: input.title,
|
|
1319
1440
|
brief: input.brief,
|
|
1441
|
+
skipSourceValidation: input.skipSourceValidation,
|
|
1320
1442
|
});
|
|
1321
1443
|
const token = input.token || crypto.randomBytes(24).toString("base64url");
|
|
1322
1444
|
const host = input.host || "127.0.0.1";
|
|
@@ -1345,6 +1467,7 @@ export async function startLocalPlanBridge(input) {
|
|
|
1345
1467
|
kind: input.kind,
|
|
1346
1468
|
title: input.title,
|
|
1347
1469
|
brief: input.brief,
|
|
1470
|
+
skipSourceValidation: input.skipSourceValidation,
|
|
1348
1471
|
}));
|
|
1349
1472
|
}
|
|
1350
1473
|
catch (error) {
|
|
@@ -1418,8 +1541,88 @@ function localPlanBridgeWarnings(input) {
|
|
|
1418
1541
|
}
|
|
1419
1542
|
return warnings;
|
|
1420
1543
|
}
|
|
1544
|
+
const VALIDATE_LOCAL_PLAN_ACTION = "validate-local-plan-source";
|
|
1545
|
+
/**
|
|
1546
|
+
* Ask the Plan app to validate the folder against its real renderer schema
|
|
1547
|
+
* (`parsePlanMdxFolder` + `planContentSchema`) via the public, no-DB
|
|
1548
|
+
* `validate-local-plan-source` action. This is what makes `verify`
|
|
1549
|
+
* authoritative: the hand-rolled `check` lint can disagree with the renderer,
|
|
1550
|
+
* but this runs the renderer's own parser. Degrades gracefully (`ran: false`)
|
|
1551
|
+
* when the endpoint is unreachable or a Plan app predates the action, so an
|
|
1552
|
+
* old deploy never turns into a hard failure.
|
|
1553
|
+
*/
|
|
1554
|
+
export async function fetchRendererValidation(input) {
|
|
1555
|
+
const fetchFn = input.fetchFn ?? fetch;
|
|
1556
|
+
const endpoint = planActionEndpoint(input.appUrl, VALIDATE_LOCAL_PLAN_ACTION);
|
|
1557
|
+
try {
|
|
1558
|
+
const response = await fetchActionWithTimeout(endpoint, {
|
|
1559
|
+
method: "POST",
|
|
1560
|
+
headers: {
|
|
1561
|
+
accept: "application/json",
|
|
1562
|
+
"content-type": "application/json",
|
|
1563
|
+
},
|
|
1564
|
+
body: JSON.stringify({ mdx: localPlanMdxFolder(input.files) }),
|
|
1565
|
+
}, fetchFn);
|
|
1566
|
+
if (!response.ok) {
|
|
1567
|
+
const detail = await response.text().catch(() => "");
|
|
1568
|
+
return {
|
|
1569
|
+
ran: false,
|
|
1570
|
+
endpoint,
|
|
1571
|
+
error: `${VALIDATE_LOCAL_PLAN_ACTION} failed ${response.status} ${response.statusText}: ${sanitizeHttpDetail(detail, 300)}`,
|
|
1572
|
+
};
|
|
1573
|
+
}
|
|
1574
|
+
const json = (await response.json().catch(() => null));
|
|
1575
|
+
const body = json && isRecord(json.result) ? json.result : (json ?? undefined);
|
|
1576
|
+
if (!body || typeof body.valid !== "boolean") {
|
|
1577
|
+
return {
|
|
1578
|
+
ran: false,
|
|
1579
|
+
endpoint,
|
|
1580
|
+
error: `${VALIDATE_LOCAL_PLAN_ACTION} returned an unexpected payload.`,
|
|
1581
|
+
};
|
|
1582
|
+
}
|
|
1583
|
+
const issues = Array.isArray(body.issues)
|
|
1584
|
+
? body.issues.filter(isRecord).map((issue) => ({
|
|
1585
|
+
path: typeof issue.path === "string" ? issue.path : "",
|
|
1586
|
+
message: typeof issue.message === "string" ? issue.message : "Invalid value",
|
|
1587
|
+
}))
|
|
1588
|
+
: [];
|
|
1589
|
+
return { ran: true, endpoint, valid: body.valid, issues };
|
|
1590
|
+
}
|
|
1591
|
+
catch (err) {
|
|
1592
|
+
return {
|
|
1593
|
+
ran: false,
|
|
1594
|
+
endpoint,
|
|
1595
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1596
|
+
};
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
function rendererValidationWarnings(validation, offlineIssues) {
|
|
1600
|
+
if (!validation.ran) {
|
|
1601
|
+
const base = `Plan content was NOT validated against the renderer schema (${validation.error ?? "validate endpoint unavailable"}). Fell back to the offline lint. Run against a Plan app that exposes ${VALIDATE_LOCAL_PLAN_ACTION} (e.g. --app-url http://localhost:8096) for authoritative validation.`;
|
|
1602
|
+
if (offlineIssues.length === 0)
|
|
1603
|
+
return [base];
|
|
1604
|
+
const preview = offlineIssues
|
|
1605
|
+
.slice(0, 8)
|
|
1606
|
+
.map((issue) => `${issue.file}:${issue.line} ${issue.message}`)
|
|
1607
|
+
.join("; ");
|
|
1608
|
+
const overflow = offlineIssues.length > 8 ? ` (+${offlineIssues.length - 8} more)` : "";
|
|
1609
|
+
return [base, `Offline lint rejected this plan: ${preview}${overflow}`];
|
|
1610
|
+
}
|
|
1611
|
+
if (validation.valid)
|
|
1612
|
+
return [];
|
|
1613
|
+
const issues = validation.issues ?? [];
|
|
1614
|
+
const preview = issues
|
|
1615
|
+
.slice(0, 8)
|
|
1616
|
+
.map((issue) => issue.path ? `${issue.path}: ${issue.message}` : issue.message)
|
|
1617
|
+
.join("; ");
|
|
1618
|
+
const overflow = issues.length > 8 ? ` (+${issues.length - 8} more)` : "";
|
|
1619
|
+
return [
|
|
1620
|
+
`Renderer schema rejected this plan — it will not render. ${preview}${overflow}`,
|
|
1621
|
+
];
|
|
1622
|
+
}
|
|
1421
1623
|
export async function verifyLocalPlanBridge(input) {
|
|
1422
1624
|
const fetchFn = input.fetchFn ?? fetch;
|
|
1625
|
+
const files = readLocalPlanFiles(input.dir);
|
|
1423
1626
|
const bridge = await startLocalPlanBridge({
|
|
1424
1627
|
dir: input.dir,
|
|
1425
1628
|
kind: input.kind,
|
|
@@ -1430,6 +1633,9 @@ export async function verifyLocalPlanBridge(input) {
|
|
|
1430
1633
|
port: input.port,
|
|
1431
1634
|
token: input.token,
|
|
1432
1635
|
urlFile: input.urlFile,
|
|
1636
|
+
// Don't let the weaker offline lint abort the bridge before the authoritative
|
|
1637
|
+
// renderer check runs — verify reports the renderer's verdict, not the lint's.
|
|
1638
|
+
skipSourceValidation: true,
|
|
1433
1639
|
});
|
|
1434
1640
|
try {
|
|
1435
1641
|
const preflight = await fetchFn(bridge.result.bridgeUrl, {
|
|
@@ -1456,8 +1662,21 @@ export async function verifyLocalPlanBridge(input) {
|
|
|
1456
1662
|
const preflightOk = preflight.status === 204 &&
|
|
1457
1663
|
preflight.headers.get("access-control-allow-origin") === "*" &&
|
|
1458
1664
|
preflight.headers.get("access-control-allow-private-network") === "true";
|
|
1665
|
+
const validation = await fetchRendererValidation({
|
|
1666
|
+
appUrl: bridge.result.appUrl,
|
|
1667
|
+
files,
|
|
1668
|
+
fetchFn,
|
|
1669
|
+
});
|
|
1670
|
+
// The renderer's verdict is authoritative and gates `ok`. When it could not
|
|
1671
|
+
// run (old/unreachable Plan app), fall back to the offline lint as the
|
|
1672
|
+
// content signal so verify still catches the common cases offline instead
|
|
1673
|
+
// of silently passing unvalidated content.
|
|
1674
|
+
const offlineIssues = validation.ran ? [] : validateLocalPlanFiles(files);
|
|
1675
|
+
const contentOk = validation.ran
|
|
1676
|
+
? validation.valid === true
|
|
1677
|
+
: offlineIssues.length === 0;
|
|
1459
1678
|
return {
|
|
1460
|
-
ok: bridgeOk && preflightOk,
|
|
1679
|
+
ok: bridgeOk && preflightOk && contentOk,
|
|
1461
1680
|
dir: bridge.result.dir,
|
|
1462
1681
|
url: bridge.result.url,
|
|
1463
1682
|
...(bridge.result.urlFile ? { urlFile: bridge.result.urlFile } : {}),
|
|
@@ -1482,10 +1701,14 @@ export async function verifyLocalPlanBridge(input) {
|
|
|
1482
1701
|
...(mdxFiles ? { mdxFiles } : {}),
|
|
1483
1702
|
...(payload?.error ? { error: payload.error } : {}),
|
|
1484
1703
|
},
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1704
|
+
validation,
|
|
1705
|
+
warnings: [
|
|
1706
|
+
...localPlanBridgeWarnings({
|
|
1707
|
+
appUrl: bridge.result.appUrl,
|
|
1708
|
+
bridgeUrl: bridge.result.bridgeUrl,
|
|
1709
|
+
}),
|
|
1710
|
+
...rendererValidationWarnings(validation, offlineIssues),
|
|
1711
|
+
],
|
|
1489
1712
|
};
|
|
1490
1713
|
}
|
|
1491
1714
|
finally {
|
|
@@ -1551,7 +1774,9 @@ function runCheck(args) {
|
|
|
1551
1774
|
const result = {
|
|
1552
1775
|
ok: true,
|
|
1553
1776
|
noDb: true,
|
|
1554
|
-
validation: "passed",
|
|
1777
|
+
validation: "lint-passed",
|
|
1778
|
+
validationScope: "offline-lint",
|
|
1779
|
+
note: "Quick offline lint only — NOT the full Plan renderer schema. A green here does not guarantee the plan renders. Run `plan local verify` against a Plan app for authoritative validation before handing off.",
|
|
1555
1780
|
dir: files.dir,
|
|
1556
1781
|
title: parsed.frontmatter.title || firstHeading(parsed.body),
|
|
1557
1782
|
kind: normalizeKind(parsed.frontmatter.kind),
|