@notis_ai/cli 0.2.18 → 0.2.19
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/README.md +542 -146
- package/bin/check-runtime.js +15 -0
- package/bin/notis.js +2 -0
- package/config/notis_app_design_rules.json +320 -0
- package/config/portal-route-roots.json +45 -0
- package/dist/agent-hooks/notis-agent-hook.mjs +42325 -18273
- package/dist/base-skills/notis-cli/.notis-base-skill.json +1 -0
- package/dist/base-skills/notis-cli/SKILL.md +51 -280
- package/dist/base-skills/notis-cli/references/app-delivery.md +17 -0
- package/dist/base-skills/notis-cli/references/intelligence.md +94 -0
- package/dist/base-skills/notis-cli/references/native-databases.md +21 -0
- package/dist/base-skills/notis-cli/references/tool-examples.md +56 -0
- package/dist/base-skills/notis-cli/references/troubleshooting.md +67 -0
- package/dist/base-skills/notis-query/.notis-base-skill.json +1 -0
- package/dist/base-skills/notis-query/SKILL.md +35 -699
- package/dist/base-skills/notis-query/references/database-discovery.md +59 -0
- package/dist/base-skills/notis-query/references/documents.md +74 -0
- package/dist/base-skills/notis-query/references/query.md +76 -0
- package/dist/base-skills/notis-spaces/.notis-base-skill.json +1 -0
- package/dist/base-skills/notis-spaces/SKILL.md +218 -0
- package/dist/base-skills/notis-spaces/references/architecture.md +116 -0
- package/dist/base-skills/notis-spaces/references/context.md +81 -0
- package/dist/base-skills/notis-spaces/references/design.md +141 -0
- package/dist/base-skills/notis-spaces/references/fixtures.md +29 -0
- package/dist/base-skills/notis-spaces/references/memory.md +58 -0
- package/dist/base-skills/notis-spaces/references/reading.md +73 -0
- package/dist/base-skills/notis-spaces/references/release.md +120 -0
- package/dist/base-skills/notis-spaces/references/reports.md +77 -0
- package/dist/base-skills/notis-spaces/references/sdk.md +273 -0
- package/dist/base-skills/notis-spaces/references/store.md +118 -0
- package/dist/base-skills/notis-spaces/references/troubleshooting.md +28 -0
- package/dist/base-skills/notis-spaces/references/views.md +229 -0
- package/{template/packages → dist}/sdk/package.json +9 -10
- package/dist/sdk/src/agentContext.ts +36 -0
- package/dist/sdk/src/bundleModule.ts +175 -0
- package/dist/sdk/src/components/Dialog.tsx +103 -0
- package/dist/sdk/src/components/DocumentEditor.tsx +113 -0
- package/dist/sdk/src/components/DocumentPage.tsx +184 -0
- package/{template/packages → dist}/sdk/src/components/Markdown.tsx +9 -3
- package/{template/packages → dist}/sdk/src/components/MarkdownEditor.tsx +26 -5
- package/{template/packages → dist}/sdk/src/components/MultiSelectActionBar.tsx +95 -12
- package/{template/packages → dist}/sdk/src/components/MultiSelectCheckbox.tsx +4 -2
- package/dist/sdk/src/components/NotisCommentBoundary.tsx +172 -0
- package/{template/packages → dist}/sdk/src/components/NotisSelectionBoundary.tsx +9 -5
- package/dist/sdk/src/components/RecordComponents.tsx +111 -0
- package/dist/sdk/src/components/Skeleton.tsx +38 -0
- package/dist/sdk/src/config.ts +31 -0
- package/{template/packages → dist}/sdk/src/documents.ts +21 -6
- package/dist/sdk/src/hooks/useAction.ts +28 -0
- package/dist/sdk/src/hooks/useAgentContext.ts +23 -0
- package/{template/packages → dist}/sdk/src/hooks/useBackend.ts +3 -2
- package/dist/sdk/src/hooks/useCloudComputer.ts +94 -0
- package/dist/sdk/src/hooks/useCloudComputerShell.ts +114 -0
- package/{template/packages → dist}/sdk/src/hooks/useCollectionInteractions.ts +157 -147
- package/dist/sdk/src/hooks/useDatabaseSchema.ts +50 -0
- package/{template/packages → dist}/sdk/src/hooks/useDatabaseSubscription.ts +2 -2
- package/dist/sdk/src/hooks/useDocument.ts +51 -0
- package/{template/packages → dist}/sdk/src/hooks/useDocuments.ts +25 -59
- package/{template/packages → dist}/sdk/src/hooks/useHandover.ts +7 -7
- package/dist/sdk/src/hooks/useLongPressSelection.ts +79 -0
- package/dist/sdk/src/hooks/useMarqueeSelection.ts +194 -0
- package/{template/packages → dist}/sdk/src/hooks/useMultiSelect.ts +2 -8
- package/dist/sdk/src/hooks/useNativeDocumentBody.ts +50 -0
- package/dist/sdk/src/hooks/useNativeDocuments.ts +143 -0
- package/{template/packages → dist}/sdk/src/hooks/useNotis.ts +6 -1
- package/dist/sdk/src/hooks/useNotisNavigation.ts +70 -0
- package/dist/sdk/src/hooks/useQuery.ts +81 -0
- package/dist/sdk/src/hooks/useToolQuery.ts +12 -0
- package/dist/sdk/src/hooks/useTopBarSearch.ts +102 -0
- package/dist/sdk/src/hooks/useTopBarTitleLeaf.ts +75 -0
- package/{template/packages → dist}/sdk/src/hooks/useUpsertDocument.ts +1 -1
- package/dist/sdk/src/hooks/useViewParams.ts +195 -0
- package/dist/sdk/src/hooks/useViewerReads.ts +129 -0
- package/{template/packages → dist}/sdk/src/index.ts +64 -1
- package/{template/packages → dist}/sdk/src/interactions/actions.ts +14 -1
- package/{template/packages → dist}/sdk/src/interactions/shortcuts.tsx +129 -23
- package/dist/sdk/src/interactions/visibility.ts +13 -0
- package/{template/packages → dist}/sdk/src/interactions.ts +5 -1
- package/dist/sdk/src/nativeData.ts +39 -0
- package/{template/packages → dist}/sdk/src/provider.tsx +9 -4
- package/dist/sdk/src/queryCache.ts +292 -0
- package/dist/sdk/src/queryErrors.ts +51 -0
- package/dist/sdk/src/runtime.ts +675 -0
- package/dist/sdk/src/runtimeModules.ts +33 -0
- package/dist/sdk/src/space.ts +442 -0
- package/dist/sdk/src/standardViewParams.ts +36 -0
- package/{template/packages → dist}/sdk/src/styles.css +81 -16
- package/dist/sdk/src/tailwind.ts +66 -0
- package/dist/sdk/src/ui/charts/RenderChartData.tsx +25 -0
- package/dist/sdk/src/ui/engine/core.ts +392 -0
- package/dist/sdk/src/ui/engine/dom.ts +183 -0
- package/dist/sdk/src/ui/engine/hooks.ts +195 -0
- package/dist/sdk/src/ui/engine/instance.ts +63 -0
- package/dist/sdk/src/ui/engine/keycapContext.ts +2 -0
- package/dist/sdk/src/ui/engine/registry.ts +262 -0
- package/dist/sdk/src/ui/engine/types.ts +62 -0
- package/dist/sdk/src/ui/icons.tsx +91 -0
- package/dist/sdk/src/ui/util.ts +83 -0
- package/dist/sdk/src/viewPeriod.ts +26 -0
- package/dist/sdk/src/vite.ts +92 -0
- package/dist/sdk/src/words/actions.ts +295 -0
- package/dist/sdk/src/words/clashes.ts +158 -0
- package/dist/sdk/src/words/format.ts +136 -0
- package/dist/sdk/src/words/index.ts +13 -0
- package/dist/sdk/src/words/keymap.ts +72 -0
- package/dist/sdk/src/words/keys.ts +297 -0
- package/dist/sdk/src/words/shell.ts +46 -0
- package/dist/sdk/src/words/types.ts +65 -0
- package/dist/skill-sync/index.js +832 -151
- package/dist/skill-sync/index.js.map +4 -4
- package/dist/skill-sync-worker.mjs +3941 -0
- package/dist/space-harness/host.js +1460 -0
- package/dist/space-sdk/dist/chunk-ZSN57ATH.js +5 -0
- package/dist/space-sdk/dist/index.js +15 -0
- package/dist/space-sdk/dist/ui.js +18 -0
- package/dist/space-sdk/package.json +33 -0
- package/dist/space-sdk/src/agentContext.d.ts +36 -0
- package/dist/space-sdk/src/components/Dialog.d.ts +20 -0
- package/dist/space-sdk/src/components/DocumentEditor.d.ts +46 -0
- package/dist/space-sdk/src/components/DocumentPage.d.ts +53 -0
- package/dist/space-sdk/src/components/Markdown.d.ts +18 -0
- package/dist/space-sdk/src/components/MarkdownEditor.d.ts +11 -0
- package/dist/space-sdk/src/components/MultiSelectActionBar.d.ts +31 -0
- package/dist/space-sdk/src/components/MultiSelectCheckbox.d.ts +14 -0
- package/dist/space-sdk/src/components/MultiSelectDragOverlay.d.ts +8 -0
- package/dist/space-sdk/src/components/NotisCommentBoundary.d.ts +36 -0
- package/dist/space-sdk/src/components/NotisSelectionBoundary.d.ts +16 -0
- package/dist/space-sdk/src/components/RecordComponents.d.ts +64 -0
- package/dist/space-sdk/src/components/ShortcutHints.d.ts +12 -0
- package/dist/space-sdk/src/components/Skeleton.d.ts +23 -0
- package/dist/space-sdk/src/config.ts +31 -0
- package/dist/space-sdk/src/documents.d.ts +59 -0
- package/dist/space-sdk/src/hooks/useAction.d.ts +8 -0
- package/dist/space-sdk/src/hooks/useActiveResource.d.ts +3 -0
- package/dist/space-sdk/src/hooks/useAgentContext.d.ts +7 -0
- package/dist/space-sdk/src/hooks/useBackend.d.ts +23 -0
- package/dist/space-sdk/src/hooks/useCloudComputer.d.ts +45 -0
- package/dist/space-sdk/src/hooks/useCloudComputerShell.d.ts +49 -0
- package/dist/space-sdk/src/hooks/useCollectionInteractions.d.ts +118 -0
- package/dist/space-sdk/src/hooks/useDatabaseSchema.d.ts +14 -0
- package/dist/space-sdk/src/hooks/useDatabaseSubscription.d.ts +26 -0
- package/dist/space-sdk/src/hooks/useDocument.d.ts +22 -0
- package/dist/space-sdk/src/hooks/useDocuments.d.ts +31 -0
- package/dist/space-sdk/src/hooks/useHandover.d.ts +43 -0
- package/dist/space-sdk/src/hooks/useLongPressSelection.d.ts +9 -0
- package/dist/space-sdk/src/hooks/useMarqueeSelection.d.ts +57 -0
- package/dist/space-sdk/src/hooks/useMultiSelect.d.ts +51 -0
- package/dist/space-sdk/src/hooks/useNativeDocumentBody.d.ts +24 -0
- package/dist/space-sdk/src/hooks/useNativeDocuments.d.ts +55 -0
- package/dist/space-sdk/src/hooks/useNotis.d.ts +25 -0
- package/dist/space-sdk/src/hooks/useNotisNavigation.d.ts +33 -0
- package/dist/space-sdk/src/hooks/useQuery.d.ts +22 -0
- package/dist/space-sdk/src/hooks/useTool.d.ts +20 -0
- package/dist/space-sdk/src/hooks/useToolQuery.d.ts +3 -0
- package/dist/space-sdk/src/hooks/useTools.d.ts +15 -0
- package/dist/space-sdk/src/hooks/useTopBarSearch.d.ts +48 -0
- package/dist/space-sdk/src/hooks/useTopBarTitleLeaf.d.ts +24 -0
- package/dist/space-sdk/src/hooks/useUpsertDocument.d.ts +27 -0
- package/dist/space-sdk/src/hooks/useViewParams.d.ts +76 -0
- package/dist/space-sdk/src/hooks/useViewerReads.d.ts +38 -0
- package/dist/space-sdk/src/index.d.ts +98 -0
- package/dist/space-sdk/src/interactions/actions.d.ts +33 -0
- package/dist/space-sdk/src/interactions/shortcuts.d.ts +42 -0
- package/dist/space-sdk/src/interactions/visibility.d.ts +2 -0
- package/dist/space-sdk/src/nativeData.d.ts +66 -0
- package/dist/space-sdk/src/provider.d.ts +17 -0
- package/dist/space-sdk/src/queryCache.d.ts +45 -0
- package/dist/space-sdk/src/queryErrors.ts +51 -0
- package/dist/space-sdk/src/runtime.d.ts +615 -0
- package/dist/space-sdk/src/runtimeModules.ts +33 -0
- package/dist/space-sdk/src/space.ts +442 -0
- package/dist/space-sdk/src/standardViewParams.d.ts +15 -0
- package/dist/space-sdk/src/tailwind-candidates.d.ts +3418 -0
- package/dist/space-sdk/src/tailwind.ts +66 -0
- package/dist/space-sdk/src/ui/actions/ActionToast.d.ts +15 -0
- package/dist/space-sdk/src/ui/actions/actionWords.d.ts +16 -0
- package/dist/space-sdk/src/ui/actions/index.d.ts +7 -0
- package/dist/space-sdk/src/ui/actions/useActions.d.ts +69 -0
- package/dist/space-sdk/src/ui/actions/useToast.d.ts +41 -0
- package/dist/space-sdk/src/ui/blocks/Tabs.d.ts +139 -0
- package/dist/space-sdk/src/ui/blocks/blocks.d.ts +217 -0
- package/dist/space-sdk/src/ui/blocks/index.d.ts +4 -0
- package/dist/space-sdk/src/ui/board/BoardView.d.ts +36 -0
- package/dist/space-sdk/src/ui/board/boardModel.d.ts +46 -0
- package/dist/space-sdk/src/ui/board/boardWords.d.ts +9 -0
- package/dist/space-sdk/src/ui/board/index.d.ts +5 -0
- package/dist/space-sdk/src/ui/calendar/CalendarView.d.ts +49 -0
- package/dist/space-sdk/src/ui/calendar/DayPicker.d.ts +23 -0
- package/dist/space-sdk/src/ui/calendar/calendarMath.d.ts +81 -0
- package/dist/space-sdk/src/ui/charts/Chart.d.ts +203 -0
- package/dist/space-sdk/src/ui/charts/ChartTable.d.ts +37 -0
- package/dist/space-sdk/src/ui/charts/RenderChartData.d.ts +16 -0
- package/dist/space-sdk/src/ui/charts/StatRow.d.ts +59 -0
- package/dist/space-sdk/src/ui/charts/chartData.d.ts +84 -0
- package/dist/space-sdk/src/ui/comments/CommentPane.d.ts +58 -0
- package/dist/space-sdk/src/ui/comments/commentModel.d.ts +157 -0
- package/dist/space-sdk/src/ui/comments/commentWords.d.ts +60 -0
- package/dist/space-sdk/src/ui/comments/index.d.ts +4 -0
- package/dist/space-sdk/src/ui/comments/useComments.d.ts +146 -0
- package/dist/space-sdk/src/ui/engine/HelpSheet.d.ts +12 -0
- package/dist/space-sdk/src/ui/engine/KeyboardEngine.d.ts +27 -0
- package/dist/space-sdk/src/ui/engine/core.d.ts +73 -0
- package/dist/space-sdk/src/ui/engine/hooks.d.ts +64 -0
- package/dist/space-sdk/src/ui/engine/index.d.ts +14 -0
- package/dist/space-sdk/src/ui/engine/instance.d.ts +21 -0
- package/dist/space-sdk/src/ui/engine/keycapContext.d.ts +2 -0
- package/dist/space-sdk/src/ui/engine/registry.d.ts +77 -0
- package/dist/space-sdk/src/ui/engine/step.d.ts +11 -0
- package/dist/space-sdk/src/ui/engine/types.d.ts +54 -0
- package/dist/space-sdk/src/ui/fields/fieldWords.d.ts +56 -0
- package/dist/space-sdk/src/ui/fields/fields.d.ts +162 -0
- package/dist/space-sdk/src/ui/fields/index.d.ts +5 -0
- package/dist/space-sdk/src/ui/fields/useFieldDraft.d.ts +22 -0
- package/dist/space-sdk/src/ui/gallery/AttachmentGallery.d.ts +53 -0
- package/dist/space-sdk/src/ui/gallery/ImageViewer.d.ts +27 -0
- package/dist/space-sdk/src/ui/gallery/galleryWords.d.ts +95 -0
- package/dist/space-sdk/src/ui/gallery/index.d.ts +5 -0
- package/dist/space-sdk/src/ui/icons.d.ts +13 -0
- package/dist/space-sdk/src/ui/index.d.ts +54 -0
- package/dist/space-sdk/src/ui/keycap/Keycap.d.ts +22 -0
- package/dist/space-sdk/src/ui/keycap/index.d.ts +2 -0
- package/dist/space-sdk/src/ui/layout/Panels.d.ts +50 -0
- package/dist/space-sdk/src/ui/layout/chatPanelEdge.d.ts +77 -0
- package/dist/space-sdk/src/ui/layout/index.d.ts +5 -0
- package/dist/space-sdk/src/ui/layout/panelMath.d.ts +91 -0
- package/dist/space-sdk/src/ui/list/ListReader.d.ts +380 -0
- package/dist/space-sdk/src/ui/list/Row.d.ts +145 -0
- package/dist/space-sdk/src/ui/list/SelectionBar.d.ts +65 -0
- package/dist/space-sdk/src/ui/list/index.d.ts +14 -0
- package/dist/space-sdk/src/ui/list/rowState.d.ts +22 -0
- package/dist/space-sdk/src/ui/list/useListKeys.d.ts +89 -0
- package/dist/space-sdk/src/ui/list/useReorder.d.ts +86 -0
- package/dist/space-sdk/src/ui/list/useSelection.d.ts +90 -0
- package/dist/space-sdk/src/ui/open/OpenAsMenu.d.ts +15 -0
- package/dist/space-sdk/src/ui/open/index.d.ts +6 -0
- package/dist/space-sdk/src/ui/open/openModeStore.d.ts +39 -0
- package/dist/space-sdk/src/ui/open/useOpenMode.d.ts +17 -0
- package/dist/space-sdk/src/ui/overlay/Menu.d.ts +88 -0
- package/dist/space-sdk/src/ui/overlay/Popover.d.ts +28 -0
- package/dist/space-sdk/src/ui/overlay/Tooltip.d.ts +19 -0
- package/dist/space-sdk/src/ui/overlay/index.d.ts +9 -0
- package/dist/space-sdk/src/ui/overlay/layerRoot.d.ts +24 -0
- package/dist/space-sdk/src/ui/overlay/position.d.ts +31 -0
- package/dist/space-sdk/src/ui/period/PeriodPicker.d.ts +30 -0
- package/dist/space-sdk/src/ui/period/dateFormat.d.ts +50 -0
- package/dist/space-sdk/src/ui/period/dateWords.d.ts +88 -0
- package/dist/space-sdk/src/ui/period/periods.d.ts +70 -0
- package/dist/space-sdk/src/ui/period/usePeriod.d.ts +23 -0
- package/dist/space-sdk/src/ui/present/index.d.ts +3 -0
- package/dist/space-sdk/src/ui/present/presentWords.d.ts +27 -0
- package/dist/space-sdk/src/ui/present/screens.d.ts +36 -0
- package/dist/space-sdk/src/ui/present/useAudienceScreen.d.ts +38 -0
- package/dist/space-sdk/src/ui/styles.d.ts +21 -0
- package/dist/space-sdk/src/ui/timeline/TimelineView.d.ts +44 -0
- package/dist/space-sdk/src/ui/timeline/timelineMath.d.ts +123 -0
- package/dist/space-sdk/src/viewPeriod.d.ts +8 -0
- package/dist/space-sdk/src/vite.ts +92 -0
- package/dist/space-sdk/src/words/actions.ts +295 -0
- package/dist/space-sdk/src/words/clashes.ts +158 -0
- package/dist/space-sdk/src/words/format.ts +136 -0
- package/dist/space-sdk/src/words/index.ts +13 -0
- package/dist/space-sdk/src/words/keymap.ts +72 -0
- package/dist/space-sdk/src/words/keys.ts +297 -0
- package/dist/space-sdk/src/words/shell.ts +46 -0
- package/dist/space-sdk/src/words/types.ts +65 -0
- package/dist/view-renderer/dist/host.css +1 -0
- package/dist/view-renderer/dist/host.js +2374 -0
- package/dist/view-renderer/dist/theme.css +73 -0
- package/dist/view-renderer/src/dom.js +212 -0
- package/dist/view-renderer/src/errors.js +8 -0
- package/dist/view-renderer/src/host.tsx +250 -0
- package/dist/view-renderer/src/index.js +4 -0
- package/dist/view-renderer/src/png.js +213 -0
- package/dist/view-renderer/src/pool.js +110 -0
- package/dist/view-renderer/src/remote-broker.js +59 -0
- package/dist/view-renderer/src/renderer.js +271 -0
- package/package.json +21 -11
- package/skills/notis-cli/AGENT_INSTRUCTIONS.md +63 -12
- package/skills/notis-onboarding/BRIEF.md +14 -9
- package/skills/notis-query/cli.md +1 -1
- package/skills/notis-spaces/cli.md +540 -0
- package/src/cli.js +8 -8
- package/src/command-specs/agents.js +121 -8
- package/src/command-specs/auth.js +3 -3
- package/src/command-specs/diagnostics.js +97 -20
- package/src/command-specs/documents.js +158 -0
- package/src/command-specs/files.js +29 -0
- package/src/command-specs/handover.js +331 -79
- package/src/command-specs/helpers.js +50 -40
- package/src/command-specs/index.js +14 -5
- package/src/command-specs/meta.js +38 -9
- package/src/command-specs/onboarding.js +1 -1
- package/src/command-specs/profile.js +42 -1
- package/src/command-specs/skills.js +314 -9
- package/src/command-specs/smoke.js +16 -4
- package/src/command-specs/spaces.js +783 -0
- package/src/command-specs/tools.js +118 -21
- package/src/command-specs/version-history.js +20 -0
- package/src/command-specs/views.js +69 -0
- package/src/runtime/agent-browser.js +178 -267
- package/src/runtime/agent-setup.js +172 -13
- package/src/runtime/app-boundary-validator.js +338 -2
- package/src/runtime/app-data-literals.js +82 -0
- package/src/runtime/app-platform.js +750 -1570
- package/src/runtime/auth-recovery.js +17 -0
- package/src/runtime/base-skills.d.ts +11 -0
- package/src/runtime/base-skills.js +100 -3
- package/src/runtime/computer-identity.d.ts +30 -0
- package/src/runtime/computer-identity.js +151 -0
- package/src/runtime/config-lock.js +135 -0
- package/src/runtime/confined-space-build.js +74 -0
- package/src/runtime/confined-space-verify.js +49 -0
- package/src/runtime/delegated-context.js +5 -21
- package/src/runtime/native-record-files.js +47 -0
- package/src/runtime/oauth.js +342 -31
- package/src/runtime/profiles.js +19 -112
- package/src/runtime/retired-sdk-files.js +24 -0
- package/src/runtime/retry.js +150 -0
- package/src/runtime/skill-sync/cloud-client.ts +33 -8
- package/src/runtime/skill-sync/index.ts +443 -106
- package/src/runtime/skill-sync/local-scanner.ts +248 -32
- package/src/runtime/skill-sync/native-identity.ts +102 -0
- package/src/runtime/skill-sync/native-plan.ts +70 -0
- package/src/runtime/skill-sync/symlink-manager.ts +66 -16
- package/src/runtime/skill-sync/sync-plan.ts +34 -2
- package/src/runtime/skill-sync/types.ts +54 -0
- package/src/runtime/skill-sync/write-cloud-skill.ts +4 -4
- package/src/runtime/skill-sync-service.js +109 -0
- package/src/runtime/source-root.js +32 -0
- package/src/runtime/space-collection-scaffold.js +107 -0
- package/src/runtime/space-database-structures.js +229 -0
- package/src/runtime/space-fixture-broker.js +68 -0
- package/src/runtime/space-lock.js +337 -0
- package/src/runtime/space-platform.js +133 -0
- package/src/runtime/space-source.js +290 -0
- package/src/runtime/space-test-server.js +354 -0
- package/src/runtime/space-verification.js +94 -0
- package/src/runtime/space-verify-browser-worker.js +51 -0
- package/src/runtime/space-view-manifest.js +368 -0
- package/src/runtime/sync-skills.d.ts +5 -1
- package/src/runtime/sync-skills.js +11 -2
- package/src/runtime/tool-confirmation.js +138 -0
- package/src/runtime/transport.js +118 -24
- package/src/runtime/upsell.js +219 -0
- package/src/runtime/view-render.js +49 -0
- package/src/skill-sync-worker-entry.js +2 -0
- package/src/skill-sync-worker.js +114 -0
- package/src/space-harness-host.ts +122 -0
- package/template/.harness/index.html.tmpl +9 -352
- package/template/app/globals.css +29 -3
- package/template/app/layout.tsx +2 -6
- package/template/components/ui/badge.tsx +7 -4
- package/template/components/ui/button.tsx +1 -1
- package/template/components/ui/native-select.tsx +24 -0
- package/template/notis.config.ts +4 -36
- package/template/package-lock.json +1800 -1867
- package/template/package.json +16 -14
- package/template/postcss.config.mjs +1 -1
- package/template/tailwind.config.ts +1 -6
- package/template/tsconfig.json +1 -0
- package/template/vite.config.ts +2 -2
- package/dist/base-skills/notis-apps/SKILL.md +0 -613
- package/skills/notis-apps/cli.md +0 -285
- package/src/command-specs/apps.js +0 -3011
- package/src/runtime/app-changelog.js +0 -79
- package/src/runtime/app-dev-consumers.js +0 -154
- package/src/runtime/app-dev-host-lock.js +0 -80
- package/src/runtime/app-dev-process-identity.js +0 -111
- package/src/runtime/app-dev-roots.js +0 -284
- package/src/runtime/app-dev-server.js +0 -1140
- package/src/runtime/app-dev-sessions.js +0 -185
- package/src/runtime/app-registry-scaffolds.js +0 -367
- package/src/runtime/assets/store-screenshot-dark.png +0 -0
- package/src/runtime/cli-mode.generated.js +0 -5
- package/src/runtime/cli-mode.js +0 -34
- package/src/runtime/store-screenshot.js +0 -143
- package/template/CHANGELOG.md +0 -5
- package/template/app/page.tsx +0 -60
- package/template/components/ui/card.tsx +0 -56
- package/template/packages/sdk/src/components/DocumentEditor.tsx +0 -103
- package/template/packages/sdk/src/config.ts +0 -259
- package/template/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
- package/template/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
- package/template/packages/sdk/src/hooks/useDocument.ts +0 -78
- package/template/packages/sdk/src/hooks/useNotisNavigation.ts +0 -52
- package/template/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
- package/template/packages/sdk/src/runtime.ts +0 -439
- package/template/packages/sdk/src/vite.ts +0 -56
- package/template/packages/sdk/tsconfig.json +0 -15
- /package/{template/packages → dist}/sdk/src/components/MultiSelectDragOverlay.tsx +0 -0
- /package/{template/packages → dist}/sdk/src/components/ShortcutHints.tsx +0 -0
- /package/{template/packages → dist}/sdk/src/hooks/useActiveResource.ts +0 -0
- /package/{template/packages → dist}/sdk/src/hooks/useTool.ts +0 -0
- /package/{template/packages → dist}/sdk/src/hooks/useTools.ts +0 -0
- /package/{template/packages → dist}/sdk/src/ui.ts +0 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# SDK reference for Space views
|
|
2
|
+
|
|
3
|
+
For offline verification, read [the fixture contract](fixtures.md) before
|
|
4
|
+
creating a `verificationFixtures` file. That short reference contains the exact
|
|
5
|
+
list-case format and every required initial-read fixture.
|
|
6
|
+
|
|
7
|
+
| Import | Holds |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| `@notis/sdk` | Data hooks, navigation, host interactions and record components |
|
|
10
|
+
| `@notis/sdk/ui` | The toolkit pieces and their hooks |
|
|
11
|
+
| `@notis/sdk/config` | `defineSpace` and view declarations |
|
|
12
|
+
| `@notis/sdk/words` | Pure action ids, EN and FR words and key specs |
|
|
13
|
+
|
|
14
|
+
`@notis/sdk` and `@notis/sdk/ui` are provided live by the host: never vendor,
|
|
15
|
+
copy or deep-import them (`@notis/sdk/src/...`), and never import the toolkit
|
|
16
|
+
stylesheet; the host adopts it. The host runtime is scoped: source never owns an
|
|
17
|
+
account credential or backend transport.
|
|
18
|
+
|
|
19
|
+
For a toolkit select, import `NativeSelect` from `@notis/sdk/ui` and pass
|
|
20
|
+
`options={[{value: 'all', label: {en: 'All', fr: 'Tous'}}]}`, `value`,
|
|
21
|
+
`onChange={value => ...}` and an accessible `label`. Its callback receives the
|
|
22
|
+
selected string, not a DOM event; its options come from `options`, not child
|
|
23
|
+
`<option>` elements. Keep the visible field label in the surrounding layout.
|
|
24
|
+
|
|
25
|
+
## Records and declared reads
|
|
26
|
+
|
|
27
|
+
| API | Use |
|
|
28
|
+
| --- | --- |
|
|
29
|
+
| `useViewParams<typeof definition>()` | `{params, invalid, missing, declared, ready, setParams}` for declared typed URL params. Unknown names are dropped; invalid values use their declared default. `setParams(changes, {replace?})` changes this view's own params (`null` removes one) and keeps the same Space and record open. |
|
|
30
|
+
| `useShown<Row>(name, options?)` | Execute the native list in `shows[name]` with current params. Options: `sorts`, `pageSize`, `offset`, `includeContent`, `allPages` (every page, for a whole count or a local search); rows are in `data?.rows` and the schema revision a write needs in `data?.schema_revision`, with `loading`, `hasData`, `isFetching`, `error`, `refetch` (resolves to the read's error, or null when it succeeded; it never rejects). |
|
|
31
|
+
| `useShownAvailable(name)` | Check whether this host exposes the declared native list. A record Site can expose only its exact server-pinned row scope. |
|
|
32
|
+
| `useAction<Inputs, Result>(name)` / `useActionQuery<Result>(name, inputs)` | Call a declared action (`call(inputs, options)`); read the result of a declared read action. Never call account-wide tools from a Space. |
|
|
33
|
+
| `useNativeMutation(binding, operation)` | Insert, update or delete one row of a linked database through the action that declares `LOCAL_NOTIS_DATABASE_INSERT`, `_UPDATE` or `_DELETE` on that binding with `request: { $input: 'request' }`. `mutate(input, {schemaRevision, requestId})` returns the receipt (`record_key`, `revision`); a delete moves the record to the bin, leaves every list at once and comes back if the write fails. One new request ID per effect. An insert action takes no `content_markdown`: insert, then save the body with `useNativeDocumentBody` and the record's revision. |
|
|
34
|
+
| `useNativeDelete(binding)` | Trash many rows of one linked database (a deck and its slides, a multi-select). `deleteMany(inputs, {schemaRevision, requestId})` hides every row from the lists at once, runs the writes a few at a time, each with the request ID `${requestId}:${record_key}` (a retry with the same `requestId` replays instead of trashing twice), refreshes the lists once at the end and brings back the rows whose write failed. It never throws for a failed row: it resolves to `{done, failed}`; say how many failed. Use it rather than a loop of `mutate`. |
|
|
35
|
+
| `useNativeDocumentBody(binding, recordKey, {readAction, writeAction?, enabled?})` | Markdown body adapter. Keep drafts in the view; save with the original content, record/schema revisions and stable request ID. Rich editing normally uses `DocumentEditor`. |
|
|
36
|
+
| `useNotis()` | Host resource, Space labels, route and ready state. Use `resource.id` for the current Space identity. |
|
|
37
|
+
|
|
38
|
+
Keep hooks unconditional. `loading` means no first successful read;
|
|
39
|
+
`isFetching` includes a silent refresh. Do not copy rows into mount-only state
|
|
40
|
+
or clear them on error ([loading rules](design.md#loading-empty-and-error)).
|
|
41
|
+
`Skeleton` and `ViewSkeleton` come from `@notis/sdk`; `ViewSkeleton`'s `label`
|
|
42
|
+
names what loads (`{ en: 'Loading meetings', fr: 'Chargement des réunions' }`),
|
|
43
|
+
said in the Space's language, default Loading content.
|
|
44
|
+
|
|
45
|
+
For another explicitly idempotent read use `useActionQuery`, or
|
|
46
|
+
`useQuery(keyArray, readCallback, { readOnly: true })` with every input in the
|
|
47
|
+
key. Call declared read actions inside a custom read with
|
|
48
|
+
`{ readOnly: true, dedupe: true }`; never mark a whole tool family read-only.
|
|
49
|
+
`useQueryClient().prefetch(...)` with the exact foreground key prepares a small
|
|
50
|
+
known read after render or on hover; never prefetch a write, a polling action or
|
|
51
|
+
a fan-out aggregate. The host keeps one in-memory cache per account, Space,
|
|
52
|
+
version and permission; do not add module-global or `localStorage` caches of
|
|
53
|
+
user data.
|
|
54
|
+
|
|
55
|
+
## First-party record components
|
|
56
|
+
|
|
57
|
+
| Component | Contract |
|
|
58
|
+
| --- | --- |
|
|
59
|
+
| `<DocumentPage recordKey>` | A record as the view's main content: save state, menu, cover, icon, title, meta, properties that save automatically, collaborative body. Slots `breadcrumb`, `actions`, `menuItems`, `aboveBody`, `belowBody`; toggles `share` (off by default, never for a report record), `header`, `meta`, `properties`, `width` (`standard` 900 px centred column by default, `wide` 1200 px, `full`); `viewer: 'html'` shows a record whose one stored `.html` file is the page; `onSaved`; `layout`. Pair with `DocumentPageSkeleton` and `usePrefetchRecord()`. It is the usual `reader` slot of `ListReader`; there it takes no `breadcrumb`, because the top bar crumb already names the open record. A page with a `breadcrumb` (a record opened from the view) names the top bar crumb leaf with its title itself; `topBarTitle` overrides that, and `onTitle` hears the title. |
|
|
60
|
+
| `<DocumentEditor recordKey>` | Native collaborative body, properties, images and attachments. With separate properties use `showProperties={false}`. |
|
|
61
|
+
| `<RecordProperties recordKey>` | Native revision-checked property editing. |
|
|
62
|
+
| `<HtmlFrame recordKey>` | Attached HTML under viewer CSP and an opaque-origin sandbox. Source cannot relax that boundary. `onReady` is called once per page after it has loaded and painted, or when the record cannot load: keep a slide hidden until then instead of showing a half-drawn page. `presentation={{ onAction }}` turns the pointer into a laser dot inside the page, keeps its buttons and links clickable, and hands the presenter's keys and plain clicks back as `next`, `previous`, `first`, `last` or `stop`; the page can send the same actions, so treat them as navigation only. |
|
|
63
|
+
| `<ReportFrame recordKey>` | A report row's saved independent implementation in its database's current view. |
|
|
64
|
+
| `<ShareControl recordKey>` | Private/shared record Site, copy link and revoke. |
|
|
65
|
+
| `<SpacePageFrame href>` | Another Notis Space page, live in this view: `href` is a Notis link (a path or a full link of this origin, such as a Page property). The Portal shows only that page's view (no sidebar, top bar or chat) with the viewer's own session and permissions. `interactive` (default `false`) lets it take clicks and keys; off, the view around it (a deck's arrows and swipes) keeps them. `title`, `className` (sizes the box it fills). Any other link, and every verify or build preview, shows a card with the title, the path and Open page. |
|
|
66
|
+
|
|
67
|
+
In its own Space's view, a record's Site is a row of the top bar Share panel, not
|
|
68
|
+
a toolbar button. The published Space declares the database binding; the server
|
|
69
|
+
rechecks record scope and binding revision. A Site exposes read-only body and
|
|
70
|
+
property snapshots and HTML for its pinned record, including a declared
|
|
71
|
+
non-collection record param. A report row cannot be shared as a Site; a report
|
|
72
|
+
saved as an HTML file can. A Site has no upload, collaboration credential,
|
|
73
|
+
authoring controls or sharing mutation. No credentials or filesystem URLs belong
|
|
74
|
+
in component props.
|
|
75
|
+
|
|
76
|
+
## Toolkit pieces
|
|
77
|
+
|
|
78
|
+
From `@notis/sdk/ui`. Their props live in the piece types; read them there
|
|
79
|
+
rather than from a copy.
|
|
80
|
+
|
|
81
|
+
- **Lists**: `ListReader`, `Row`, `TabRow`, `SelectionBar`, `Panels`,
|
|
82
|
+
`OpenAsMenu`, `Keycap`. `ListReader` draws the whole list chrome from props:
|
|
83
|
+
`search` (the host top bar field), `tabs` (pills in one 44px row), `title`
|
|
84
|
+
(a short status with its count at the start of that row, such as "23 to
|
|
85
|
+
triage"), `create` (the "+" at its end), `viewMenu`, `infoLine`,
|
|
86
|
+
`readerLabel` and `readerActions` (the reader bar), `crumbLabel` (the open
|
|
87
|
+
item in the top bar crumb), `onOpenChange(id, reason)` (`reason` is `user`,
|
|
88
|
+
`auto` for a move the list makes itself, or `url`), `renderTile` (tiles), `look` (`two-tone` keeps
|
|
89
|
+
the list tinted) and `autoOpen` (opens the first item). It has no toolbar or
|
|
90
|
+
header slot. `Row` takes `wrap` (title lines) and `now` (a fixed clock for
|
|
91
|
+
relative times). Drag to select is automatic on a list that selects several
|
|
92
|
+
(`selectable` or a bulk action): a drag from empty space selects the rows
|
|
93
|
+
under it, as in the Manager; `dragSelect={false}` turns it off. Reorder is
|
|
94
|
+
off until the view passes `reorder={{ onReorder, canReorder }}`: a row then
|
|
95
|
+
drags with a line where it lands, or moves with Alt and an arrow key (Alt
|
|
96
|
+
with Home or End for the ends), and screen readers hear its new place.
|
|
97
|
+
`onReorder({ item, id, from, to, ids })` gets the moved item, its new index
|
|
98
|
+
and the whole new order; save `ids` in the view's own order (a position
|
|
99
|
+
property, for example). The list shows the new order at once and puts the
|
|
100
|
+
old one back with an error toast if the promise rejects. Pending and
|
|
101
|
+
disabled rows, and rows `canReorder` refuses, do not move; reorder is off
|
|
102
|
+
while `search` filters or `groupBy` groups. For a strip of your own (slide
|
|
103
|
+
thumbnails, a rail), `useReorder({ items, getId, onReorder, orientation })`
|
|
104
|
+
gives the ordered `items`, `getItemProps(id)` for each element and an
|
|
105
|
+
`announcer` to render once.
|
|
106
|
+
- **Boards**: `BoardView` is a Kanban board (a funnel, a pipeline): one
|
|
107
|
+
column per stage (`columns`, each `{ id, label, tone? }`, with `getColumn`
|
|
108
|
+
saying where an item sits) and a tile per item (`renderTile`, the same
|
|
109
|
+
`TileParts` as tiles). It is `ListReader` underneath, so `reader`, the open
|
|
110
|
+
modes, `actions`, selection and `search` work the same; a tile opens on
|
|
111
|
+
Enter or a click and nothing opens on its own. `onMove(ids, toColumnId,
|
|
112
|
+
index?)` moves tiles by drag and drop, Shift+Left/Right and M (Move to):
|
|
113
|
+
update the items in the page (optimistically if you like) and return an
|
|
114
|
+
undo function for Undo in the toast. Leave `onMove` out for a board that
|
|
115
|
+
only reads. Use it rather than columns of your own.
|
|
116
|
+
- **Time and numbers**: `PeriodPicker` with `usePeriod`, `DayPicker`,
|
|
117
|
+
`CalendarView`, `TimelineView`, `Chart`, `StatRow`, `ChartTable`,
|
|
118
|
+
`RenderChartData`. `Chart` stacks bars or areas (`stacked`) and runs bars
|
|
119
|
+
left to right (`horizontal`): each label on up to two lines before its bar
|
|
120
|
+
in a measured axis, and its value after it; `labelFormat` gives that short
|
|
121
|
+
value ("1.2k") while `format` stays the exact tooltip and table text. Draw
|
|
122
|
+
category bars this way rather than with your own recharts. For a chart of
|
|
123
|
+
your own, `ChartContainer` takes `aspect` or `height`; `ChartTooltipContent`
|
|
124
|
+
and `ChartLegend` also work outside it; `<Bar shape={barShape}
|
|
125
|
+
label={{ content: barLabel }} />` keeps zero bars and their value labels. A
|
|
126
|
+
sparkline `null` is a gap. `PeriodPicker` without the `custom` preset offers
|
|
127
|
+
presets only.
|
|
128
|
+
- **Floating**: `Menu`, `Popover`, `Tooltip`.
|
|
129
|
+
- **Files and pictures**: `AttachmentGallery` and `ImageViewer`, the ones
|
|
130
|
+
Notis conversations use. `AttachmentGallery` draws a row of file cards
|
|
131
|
+
(`items`: `url`, `name`, `type` or `kind`, `size`, `thumbnailUrl`); an
|
|
132
|
+
image card opens `ImageViewer` on the gallery's images (zoom, pan, arrows,
|
|
133
|
+
copy, download, Escape), and any other card goes to `onOpen` (a new tab by
|
|
134
|
+
default). `renderOpener` swaps a card's opener, `itemAction` adds a corner
|
|
135
|
+
button, `viewerActions` adds viewer buttons (class `nui-viewer-btn`) and
|
|
136
|
+
`onNotice` hears copy and download results. Use `ImageViewer` alone for a
|
|
137
|
+
picture that opens full screen. Do not build your own lightbox.
|
|
138
|
+
- **Presenting on a second screen**: `useAudienceScreen({ onAction, onClose,
|
|
139
|
+
title })` works like PowerPoint. `secondScreen` says whether another screen
|
|
140
|
+
is connected; call `open(anchor)` from the Present press itself. It answers
|
|
141
|
+
`opened` (the audience window is on the other screen), `one-screen` (present
|
|
142
|
+
full screen in this window, as before), `press-again` (the browser just asked
|
|
143
|
+
for permission and used up the press: show `PRESENT_WORDS.pressAgain`) or
|
|
144
|
+
`blocked` (pop-ups blocked: show `PRESENT_WORDS.blocked`). Render the
|
|
145
|
+
audience view with `portal(<Slide ... />)` from the same component, so both
|
|
146
|
+
windows share one state: the current slide, next and previous, and a
|
|
147
|
+
presented `HtmlFrame`'s laser all stay in sync. Keys, clicks and right clicks
|
|
148
|
+
in the audience window come back through `onAction` (`next`, `previous`,
|
|
149
|
+
`first`, `last`, `stop`); the presenter window keeps the normal view (notes,
|
|
150
|
+
previews, a timer). The browser asks once to place windows on screens; the
|
|
151
|
+
desktop app never asks. Leaving the view closes the audience window.
|
|
152
|
+
- **Blocks**: `Section`, `Badge`, `Button`, `ToggleGroup`, `SegmentedControl`,
|
|
153
|
+
`NativeSelect`, `EmptyState`, `Notice`, `Metric`. A page is a stack of
|
|
154
|
+
`Section`s, full width and without boxes: `kind` is `bar` (period and
|
|
155
|
+
filters), `stats`, `chart`, `data` (a table) or `form`, and its head takes
|
|
156
|
+
`title`, `count`, `meta`, `tabs` and `actions`. There is no page heading and
|
|
157
|
+
no card: the host top bar shows the title. One toggle is a `Button` with
|
|
158
|
+
`pressed`; several with any number on (filters, chart series) are a
|
|
159
|
+
`ToggleGroup`; tabs and filters over a whole list or section are pills
|
|
160
|
+
(`TabRow`); a `SegmentedControl` is only a mode switch inside a section.
|
|
161
|
+
A `Notice` is read politely, danger too; pass `urgent` only for a problem the
|
|
162
|
+
person must act on now (it becomes an alert that interrupts the screen reader).
|
|
163
|
+
- **Fields**: `EditableFields` (a form; Save and Cancel show once something
|
|
164
|
+
changed) or `FieldList` (the same rows without them) around `FieldRow`s holding
|
|
165
|
+
`FieldText`, `FieldLongText`, `FieldSelect`, `FieldMultiSelect` (`searchable`
|
|
166
|
+
for a long list, `onAdd` to add the typed text as an option) or
|
|
167
|
+
`FieldDisclosure` (its summary, such as a `formatLongDay` date, wraps in a
|
|
168
|
+
narrow reader). A row's `hint` describes its control; `invalid` reads the
|
|
169
|
+
hint as the error. Their rules ship in the toolkit styles: draw no `<style>`.
|
|
170
|
+
- **Hooks for your own layout**: `useListKeys` and `useSelection` (list keys and
|
|
171
|
+
selection), `useShortcut` (a key at route scope or below), `usePanels` (split
|
|
172
|
+
or stacked), `useOpenMode`, `useActions` (standard and own actions),
|
|
173
|
+
`useLayerRoot` (container for anything floating), `useEscapeLayer`.
|
|
174
|
+
|
|
175
|
+
A standard action is an id (`archive`, `complete`, `star`, `later`, `move`,
|
|
176
|
+
`assign`, `read`, `delete`...) plus `run`; without `run` it is hidden. The standard
|
|
177
|
+
`delete` hides its records from the lists while `run` works, keeps hidden the
|
|
178
|
+
ones it removed and brings back the ones in `failed` (or all of them when `run`
|
|
179
|
+
throws, and on Undo): return `{ failed }` rather than refetching yourself. An own
|
|
180
|
+
action is `{ id, label: { en, fr }, icon?, key?, tone?, bulk?, appliesTo?, run }`.
|
|
181
|
+
A standard id with a `label` keeps its key, icon and toast: `unarchive` reads
|
|
182
|
+
Move to triage, and a Space whose first stop has a name passes
|
|
183
|
+
`{ id: 'unarchive', label: { en: 'Move to Inbox', fr: 'Remettre dans la boîte' } }`.
|
|
184
|
+
|
|
185
|
+
A status maps to one of ten groups (`backlog`, `todo`, `active`, `review`,
|
|
186
|
+
`waiting`, `done`, `cancelled`, `failed`, and `up`/`down` for a service), each
|
|
187
|
+
with its icon, words and the one status palette: pass the Space's own status to
|
|
188
|
+
`Row` or `StatusIcon` (with `label` for its own name), never a colour.
|
|
189
|
+
|
|
190
|
+
## Navigation
|
|
191
|
+
|
|
192
|
+
`useNotisNavigation()` exposes `toSpace(spaceId, {recordKey?, params?})` and
|
|
193
|
+
`toNamedSpace(alias, {recordKey?, params?})`. Both return a promise that settles
|
|
194
|
+
once the host has taken the navigation and rejects when the host refuses it:
|
|
195
|
+
`await` it (or `void` it in a click handler). Prefer declared portable navigation
|
|
196
|
+
aliases for sibling destinations; the host resolves them under current access.
|
|
197
|
+
Use declared params for view state, for example `{params: {project: key, period: 'week'}}`.
|
|
198
|
+
The destination drops unknown params and authorizes referenced records. Changing
|
|
199
|
+
a slug cannot change identity. Agents cite current server-returned links.
|
|
200
|
+
|
|
201
|
+
To change the open view's own params (an open item, a tab, a filter), call
|
|
202
|
+
`useViewParams().setParams({open: key})` instead of navigating to the same Space:
|
|
203
|
+
there is no alias to declare and no destination request, and each call adds a
|
|
204
|
+
history entry unless you pass `{replace: true}`. `ListReader` with `openParam` and
|
|
205
|
+
`usePeriod` already write this way.
|
|
206
|
+
|
|
207
|
+
## Viewer-only exploration
|
|
208
|
+
|
|
209
|
+
`viewerReads: ['databases', 'skills']` permits read-only inspection of what the
|
|
210
|
+
signed-in viewer already reaches. It creates no shared grant. Use
|
|
211
|
+
`useViewerReadAvailable(family)`, `useViewerDatabases`, `useViewerSkills`, or
|
|
212
|
+
`useViewerRead(operation, input)`. Anonymous Sites cannot use these families.
|
|
213
|
+
Explicit synthetic `viewerReads` fixtures stand in for the viewer's reads offline.
|
|
214
|
+
|
|
215
|
+
## The viewer's cloud computer
|
|
216
|
+
|
|
217
|
+
`cloudComputer: 'shell'` (or `'read'` for facts only) lets a page run one command
|
|
218
|
+
or write one file on the signed-in viewer's own cloud computer, after that viewer
|
|
219
|
+
allows it in the Portal prompt. Use `useCloudComputerShell()`: check `level`, call
|
|
220
|
+
`requestApproval()` when `approved` is false (either level; the facts of
|
|
221
|
+
`useCloudComputer()` are read again once allowed), then, when `available` (`shell`),
|
|
222
|
+
`run(command, options)` or
|
|
223
|
+
`upload({ path, content, content_encoding: 'base64', mode: 0o600 })`. Never put
|
|
224
|
+
secrets in a command; send them as upload content. A run is never repeated for one
|
|
225
|
+
request key: pass `requestId` (run option, or `request_id` in the upload) when the
|
|
226
|
+
page retries a run itself; `cloud_computer_already_ran` means it already ran. The
|
|
227
|
+
approval covers only the exact code the viewer allowed, so every new release asks
|
|
228
|
+
again. Keep a fallback (a Manager draft) for Sites, previews offline and viewers
|
|
229
|
+
who do not allow it. Declare it only when the page's core controls run on the
|
|
230
|
+
cloud computer.
|
|
231
|
+
|
|
232
|
+
## Visual data and Markdown
|
|
233
|
+
|
|
234
|
+
Give a chart its numbers through `RenderChartData` (the toolkit's `Chart` and
|
|
235
|
+
`ChartTable` already do): it adds a semantic table without a second visible one.
|
|
236
|
+
The renderer never guesses exact numbers from SVG or canvas geometry; a chart
|
|
237
|
+
without it contributes only its accessible name to the Markdown.
|
|
238
|
+
|
|
239
|
+
An optional `markdown` source module exports a pure function of `{params, shown}`.
|
|
240
|
+
It must describe the rendered selection and its actual data. Ordinary rendering
|
|
241
|
+
extracts tables, lists, controls and visible document/HTML content automatically.
|
|
242
|
+
|
|
243
|
+
## Host interactions and context
|
|
244
|
+
|
|
245
|
+
- `useHandover()` exposes `{handover, available, pending, error}`. Call a declared
|
|
246
|
+
linked Skill with `handover({skill, prompt})`; fall back when no agent UI exists.
|
|
247
|
+
A selected row goes as `record: {binding, recordKey, readAction}`: the host
|
|
248
|
+
reads that row without its body, so pass the database's `query_` action (a
|
|
249
|
+
`read_record_` action fixed to `include_content: true` is refused).
|
|
250
|
+
- The host top bar owns the title, the search and Share. `ListReader` `search`
|
|
251
|
+
fills the host search field; a Space never wires its own search. The open
|
|
252
|
+
item joins the crumb through `ListReader` `crumbLabel`, or
|
|
253
|
+
`useTopBarTitleLeaf(label, onBack)` on your own layout; the view crumb then
|
|
254
|
+
calls `onBack`. When the item is a record of the Space's `collection`, pass
|
|
255
|
+
`useTopBarTitleLeaf(label, onBack, { recordKey })` so Editors rename it from
|
|
256
|
+
the crumb; read its name from your data, which refreshes after the rename. A
|
|
257
|
+
`DocumentPage` breadcrumb moves into the top bar on wide
|
|
258
|
+
screens and stays in the page only on narrow ones, so never draw your own
|
|
259
|
+
title or breadcrumb row. Do not duplicate host chrome.
|
|
260
|
+
- `useActiveResource` publishes the current resource; `useAgentContext`,
|
|
261
|
+
`NotisSelectionBoundary`, `NotisCommentBoundary` and `NotisCommentBox` support
|
|
262
|
+
explicit reference context. [Context sharing](context.md) owns the contract.
|
|
263
|
+
- `Dialog` supplies a themed modal with focus handling; while it is open, only
|
|
264
|
+
its own keys and Escape work. For a confirmation (delete, discard), pass
|
|
265
|
+
`nativeOnTouch` and mark the buttons `data-dialog-confirm` and
|
|
266
|
+
`data-dialog-cancel`: phones and tablets then ask with the system dialog.
|
|
267
|
+
- `MarkdownEditor` is for a view-owned Markdown draft/persistence adapter. Native
|
|
268
|
+
documents use `DocumentEditor` so collaboration and file authority stay with Notis.
|
|
269
|
+
|
|
270
|
+
## Offline fixtures
|
|
271
|
+
|
|
272
|
+
Read the complete [offline fixture contract](fixtures.md). Keep every fixture
|
|
273
|
+
fictional; verification never falls back to the user's real account.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Store publishing
|
|
2
|
+
|
|
3
|
+
Use this when the user asks to publish a Space, or an update to one, in the
|
|
4
|
+
Store. You prepare everything; the user chooses where it goes and presses
|
|
5
|
+
Publish on the submission page. Store publication stays separate from deploying
|
|
6
|
+
the installed Space ([Delivery](release.md)).
|
|
7
|
+
|
|
8
|
+
## Never publish for the user
|
|
9
|
+
|
|
10
|
+
There is no agent publish operation, and you never press, simulate or script
|
|
11
|
+
the Publish button. Only the page's Publish button publishes, after the user
|
|
12
|
+
picks Team or Public there. Asking you to publish means: prepare the submission
|
|
13
|
+
and send the page link. A team listing goes live as soon as the user presses
|
|
14
|
+
Publish; a public listing goes to the sandbox reviewer, and Notis messages the
|
|
15
|
+
user with its result.
|
|
16
|
+
|
|
17
|
+
## The flow
|
|
18
|
+
|
|
19
|
+
All steps use `LOCAL_NOTIS_MANAGE_SPACE`. Each answer is the submission view:
|
|
20
|
+
status, listing text, locales, sample rows and counts, screenshots, findings,
|
|
21
|
+
`can_publish`, `blocked_reason` and `link`.
|
|
22
|
+
|
|
23
|
+
1. **Prepare.** Call `store_prepare {space_id, request_id}` with the root of the
|
|
24
|
+
tree to publish and a stable request ID. Notis copies the tree into the
|
|
25
|
+
user's hidden Store review Space (the test copy, automations paused), pins
|
|
26
|
+
the source revision, takes screenshots and runs the safety scan. Retry with
|
|
27
|
+
the same request ID; never prepare twice to recover a lost answer.
|
|
28
|
+
2. **Write the listing** with `store_submission_update {submission_id, metadata,
|
|
29
|
+
locales}`: name, tagline, description, category, icon and accent in
|
|
30
|
+
`metadata` (English), and the French name, tagline and description in
|
|
31
|
+
`locales.fr`. The optional `locales.fr.items` maps `pages`, `databases`,
|
|
32
|
+
`skills` and `automations` by the immutable `key` returned in the submission's
|
|
33
|
+
item inventory. Supply display-only `name` and `description` (`summary` for
|
|
34
|
+
automations), preserving the package's identities and order. A null or blank
|
|
35
|
+
leaf clears that translation, so the viewer falls back to English. Say what the Space does for the person who installs it, from
|
|
36
|
+
its views, databases and Skills. Write French as natural French (tu), not a
|
|
37
|
+
word-for-word translation. No personal names, account details, customer or
|
|
38
|
+
company data from the source.
|
|
39
|
+
3. **Write sample rows** with `store_submission_update {submission_id,
|
|
40
|
+
sample_rows}` (see below), then read the screenshots. Pass
|
|
41
|
+
`retake_screenshots: true` after sample rows or listing text change what the
|
|
42
|
+
views show.
|
|
43
|
+
4. **Handle the findings** (see below): ask about privacy, fix the rest in the
|
|
44
|
+
source Space, and list every fix.
|
|
45
|
+
5. **Send the link.** When `can_publish` is true, give the user the page
|
|
46
|
+
`link`, one short line on what is ready, the fixes you made and their answers.
|
|
47
|
+
If it stays false, say what still blocks it from `blocked_reason` and what
|
|
48
|
+
they can do.
|
|
49
|
+
|
|
50
|
+
## Sample rows
|
|
51
|
+
|
|
52
|
+
- Up to 8 rows per database, keyed by database key: `{database_key:
|
|
53
|
+
[{key, properties, body}]}`. Use only properties in that database's schema; a
|
|
54
|
+
relation lists the `key` of another row in the same sample set. `body` is
|
|
55
|
+
optional plain text (one paragraph per line); `key` is optional short text.
|
|
56
|
+
- Realistic and wholly synthetic: plausible titles, dates, amounts and states
|
|
57
|
+
that show every main view working (a few statuses, a spread of dates, at
|
|
58
|
+
least one row in each group a view shows).
|
|
59
|
+
- Never a real person's name, email address, phone number, company, address or
|
|
60
|
+
account identifier, and never content copied or paraphrased from the user's
|
|
61
|
+
own rows, notes, contacts or history. Use invented first names only when a
|
|
62
|
+
field needs a person ("Alex", "Camille"), and no contact details at all.
|
|
63
|
+
- Sample rows exist only in the test copy and the published version. They never
|
|
64
|
+
enter the source Space. Installs start with them, and the installer removes
|
|
65
|
+
all of them with one click; updates never bring them back.
|
|
66
|
+
|
|
67
|
+
## Findings
|
|
68
|
+
|
|
69
|
+
Each finding has `id`, `check`, `severity` (`red` or `amber`), `privacy`,
|
|
70
|
+
`where`, `message`, `fix` and `status`. Publish needs no open red finding and no
|
|
71
|
+
unanswered privacy question.
|
|
72
|
+
|
|
73
|
+
**Privacy.** A finding with `privacy: true` is a candidate, not yet a question.
|
|
74
|
+
Judge whether it carries a real privacy risk for the publisher or for people in
|
|
75
|
+
their data: an outside host that would receive installers' data, an integration
|
|
76
|
+
or MCP call that reads private accounts, a read of Spaces outside the published
|
|
77
|
+
tree, a sharing change, personal data in the listing, screenshots or samples. A
|
|
78
|
+
candidate with no real risk is treated like any other finding. Sample or fake
|
|
79
|
+
data is never a risk: the scan already skips tests, fixtures and placeholder
|
|
80
|
+
hosts, so never ask the user to confirm data you can see is a sample. If one
|
|
81
|
+
still shows up, say it is sample data the scan missed instead of asking about
|
|
82
|
+
it. For each real risk, ask the user one plain question naming what and where, with two choices:
|
|
83
|
+
|
|
84
|
+
- **Remove**: take it out of what is published.
|
|
85
|
+
- **Keep**: publish it as it is; Notis adds your note to the listing so
|
|
86
|
+
installers see it.
|
|
87
|
+
|
|
88
|
+
Record their answer with `store_finding_answer {submission_id, finding_id,
|
|
89
|
+
answer: 'remove'|'keep', note, user_words}`. `user_words` are the user's own
|
|
90
|
+
words; `note` is the short listing sentence for a Keep, written in plain words.
|
|
91
|
+
Never answer a privacy question for the user.
|
|
92
|
+
|
|
93
|
+
**Everything else.** Fix each non-privacy red finding in the source Space
|
|
94
|
+
through the normal release path: pull, change, build, verify, deploy, read back
|
|
95
|
+
([Delivery](release.md)). Then call `store_prepare` again for the same Space
|
|
96
|
+
with a new request ID, so the open submission pins the new revision and scans
|
|
97
|
+
again. List every fix for the user: what was found, where, and what you changed.
|
|
98
|
+
A finding you cannot fix keeps Publish blocked; say so plainly. Amber findings
|
|
99
|
+
need no fix; mention the ones an installer would notice.
|
|
100
|
+
|
|
101
|
+
Test chats about the submission run on the test copy only; never write sample
|
|
102
|
+
rows, listing text or fixes for the listing into the source Space's data.
|
|
103
|
+
|
|
104
|
+
## Updates
|
|
105
|
+
|
|
106
|
+
Publishing an update follows the same flow: `store_prepare` on the same root
|
|
107
|
+
creates a new submission on the same listing, and Publish adds a new version to
|
|
108
|
+
it. Never create a second listing, a copy of the Space or a new Space to ship an
|
|
109
|
+
update. Installs that differ only in listing text or screenshots update
|
|
110
|
+
themselves; installs of a version that changes code or databases show an
|
|
111
|
+
Update available card and update when their owner chooses.
|
|
112
|
+
|
|
113
|
+
## Status
|
|
114
|
+
|
|
115
|
+
Read the submission with `store_submission_read {submission_id}`. `ready` means
|
|
116
|
+
the page can publish; `in_review` means the public review is running and Notis
|
|
117
|
+
will message the user with the result; `published` is live; `rejected` lists what
|
|
118
|
+
to fix, which starts again from step 4 with a new `store_prepare`.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
Start with the actual failing operation and its exact Space, source/record
|
|
4
|
+
revision and current target. [Delivery](release.md) owns the release sequence.
|
|
5
|
+
|
|
6
|
+
| Failure | Check |
|
|
7
|
+
| --- | --- |
|
|
8
|
+
| Build rejects a view | Required `specVersion`, path, descriptions, params, executable shows and memory; use the file/line diagnostic. |
|
|
9
|
+
| Design check rejects a view | Replace the flagged code with the piece or hook the diagnostic names (`useShortcut` for a key listener, `useLayerRoot` for a portal, tokens for a colour, EN and FR copy for a literal). Do not disable the rule. |
|
|
10
|
+
| Main-view conflict | Inspect current database links/main view. Move the existing claim explicitly or retain it; do not remove main just to publish. |
|
|
11
|
+
| Source creation fails | Check its canonical schema and same-view main record param. Verify creates no resource; promotion is atomic. |
|
|
12
|
+
| View-link warning after a successful write | Use `FIND_VIEWS` with the returned record key. The write is already committed; do not insert again. |
|
|
13
|
+
| Empty list or missing properties | Inspect the live schema, filter, authorized binding and returned projection. Distinguish a successful empty result from a denied/failed read. |
|
|
14
|
+
| Verification fails on a read | Add the exact fictional case to the selected fixture file. Never fill missing fixtures with live private data. |
|
|
15
|
+
| A caught write-on-load fails rendering | Remove the side effect from initial rendering. A read-only check cannot authorize writes. |
|
|
16
|
+
| Stale binding/schema/record | Read current state, preserve the original receipt/intent and merge the intended edit. Do not overwrite concurrent changes. |
|
|
17
|
+
| Old code in Workspace | Read the published revision and requested bundle; source edits or restarting Desktop do not deploy it. |
|
|
18
|
+
| `client_update_required` | This Notis app or CLI is too old. Update it, then repeat the same operation. Old apps are not supported. |
|
|
19
|
+
| `protocol_required`, `invalid_protocol` or another 400 naming a `field` | The call is malformed, not out of date. Fix the named field (native Space and database tools take `"protocol": 1`) and call again. |
|
|
20
|
+
| Uncertain deployment | Run `notis doctor`, read the same Space and release/request identity, then reconcile before retrying. |
|
|
21
|
+
| A tool call fails with `network_error`, `network_timeout` or a 502, 503 or 504 | The CLI already retried it where repeating is safe (`attempts` in its answer). Do not add your own retry loop: read back the same target, then run it again only if it did not happen, with the same `request_id`. |
|
|
22
|
+
| Screenshot misses content | Inspect actual inner scrolling, lazy data and frame layout; keep full-height limits and treat a failed capture as unverified. |
|
|
23
|
+
| Site unexpectedly has editor controls | Recheck the anonymous scoped runtime. A Site cannot borrow an ambient signed-in session or another record's authority. |
|
|
24
|
+
| Memory hit looks current but access/freshness is unknown | Render its current link and verify the relevant value. Do not release historical content from an unverified read set. |
|
|
25
|
+
|
|
26
|
+
For visual defects, compare the installed page at 390px and 1440px in EN/FR,
|
|
27
|
+
including loading, empty and error states. A standalone harness cannot certify
|
|
28
|
+
the Portal parent layout, collaboration or public Site behavior.
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# View authoring
|
|
2
|
+
|
|
3
|
+
A view is the presentation of a Space. A record opens in a view; its database has
|
|
4
|
+
one main view. Words in links describe the destination, while IDs choose it.
|
|
5
|
+
Get links from write results or `LOCAL_NOTIS_FIND_VIEWS`, not by joining labels.
|
|
6
|
+
|
|
7
|
+
## Start from the collection scaffold
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
notis spaces init "Notes" ./notes --database-key notes --path notes
|
|
11
|
+
notis spaces build ./notes --space collection
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`init` is local only. For an existing Space, pull its exact ID instead. Keep its
|
|
15
|
+
lock and local source key; one build/deploy changes that selected Space only.
|
|
16
|
+
A container has children but no page; page-only params/shows/memory belong on views.
|
|
17
|
+
|
|
18
|
+
## Index the Space in the workspace
|
|
19
|
+
|
|
20
|
+
The root `notis.config.ts` maps each local Space key to an object with its
|
|
21
|
+
definition file. The value is not a path string or the definition itself:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { defineSpaces } from '@notis/sdk/config';
|
|
25
|
+
|
|
26
|
+
export default defineSpaces({
|
|
27
|
+
spaces: { notes: { definition: 'spaces/notes/space.config.ts' } },
|
|
28
|
+
});
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
That definition file exports `defineSpace`, as below; its `entry` is relative to
|
|
32
|
+
the definition file. `spaces init` creates this index for a new collection.
|
|
33
|
+
When writing a new source workspace through the confined source tools, include
|
|
34
|
+
the index and the definition before requesting a build.
|
|
35
|
+
|
|
36
|
+
## A complete view declaration
|
|
37
|
+
|
|
38
|
+
The linked `notes` resource below must already resolve to this installation's
|
|
39
|
+
native database. Descriptions explain what a person or agent can do here.
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { defineSpace } from '@notis/sdk/config';
|
|
43
|
+
|
|
44
|
+
export default defineSpace({
|
|
45
|
+
specVersion: 2,
|
|
46
|
+
name: 'Notes',
|
|
47
|
+
path: 'notes',
|
|
48
|
+
description: 'Browse notes and open one with its files.',
|
|
49
|
+
readableContext: 'The note parameter opens one note. The list shows all notes available through this Space.',
|
|
50
|
+
entry: './view.tsx',
|
|
51
|
+
resources: { notes: { kind: 'database', key: 'notes' } },
|
|
52
|
+
collection: { database: 'notes', titleProperty: 'title' },
|
|
53
|
+
params: {
|
|
54
|
+
note: { type: 'record', database: 'notes', main: true,
|
|
55
|
+
description: 'The note to open beside the list.' },
|
|
56
|
+
},
|
|
57
|
+
shows: { notes: { database: 'notes', where: {}, open: 'note' } },
|
|
58
|
+
memory: { markdown: true, attachments: true, screenshot: false, snapshots: [] },
|
|
59
|
+
actions: {
|
|
60
|
+
read: {
|
|
61
|
+
tool: 'LOCAL_NOTIS_DATABASE_QUERY',
|
|
62
|
+
inputs: { type: 'object', additionalProperties: false,
|
|
63
|
+
required: ['request'], properties: { request: {
|
|
64
|
+
type: 'object', additionalProperties: false,
|
|
65
|
+
required: ['filter', 'page_size', 'include_content'],
|
|
66
|
+
properties: {
|
|
67
|
+
filter: { type: 'object', additionalProperties: false,
|
|
68
|
+
required: ['field', 'op', 'value'], properties: {
|
|
69
|
+
field: { type: 'object', additionalProperties: false,
|
|
70
|
+
required: ['column'], properties: { column: { const: 'record_key' } } },
|
|
71
|
+
op: { const: 'equals' }, value: { type: 'string', format: 'uuid' },
|
|
72
|
+
} },
|
|
73
|
+
page_size: { const: 1 }, include_content: { const: true },
|
|
74
|
+
},
|
|
75
|
+
} } },
|
|
76
|
+
arguments: { database_id: { $asset: 'notes' }, request: { $input: 'request' } },
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The saved `read` action is deliberately constrained to one native record for
|
|
83
|
+
body/Site reads; `shows.notes` owns the Editor's collection list. Keep both tied
|
|
84
|
+
to the same declared resource.
|
|
85
|
+
|
|
86
|
+
## Write the view
|
|
87
|
+
|
|
88
|
+
Start from the piece that matches the view. A list beside a reader is one
|
|
89
|
+
`ListReader`:
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
import { DocumentPage, useAction, useNotisRuntime, useShown } from '@notis/sdk';
|
|
93
|
+
import { ListReader, Row } from '@notis/sdk/ui';
|
|
94
|
+
|
|
95
|
+
type Note = { record_key: string; title: string; updated_at: string };
|
|
96
|
+
const keys = (items: Note[]) => ({ record_keys: items.map((n) => n.record_key) });
|
|
97
|
+
const copy = { en: { search: 'Search notes' }, fr: { search: 'Rechercher des notes' } };
|
|
98
|
+
|
|
99
|
+
export default function Notes() {
|
|
100
|
+
const t = copy[useNotisRuntime()?.context.locale === 'fr' ? 'fr' : 'en'];
|
|
101
|
+
const notes = useShown<Note>('notes', { allPages: true });
|
|
102
|
+
const archive = useAction('archive_notes'); // declared write actions
|
|
103
|
+
const pin = useAction('pin_notes');
|
|
104
|
+
return (
|
|
105
|
+
<ListReader
|
|
106
|
+
label={{ en: 'Notes', fr: 'Notes' }}
|
|
107
|
+
items={notes.data?.rows ?? []}
|
|
108
|
+
getId={(n) => n.record_key}
|
|
109
|
+
openParam="note"
|
|
110
|
+
search={{ placeholder: t.search,
|
|
111
|
+
match: (n, query) => n.title.toLocaleLowerCase().includes(query.toLocaleLowerCase()) }}
|
|
112
|
+
row={(n) => <Row title={n.title} time={n.updated_at} />}
|
|
113
|
+
readerLabel={(n) => n.title}
|
|
114
|
+
crumbLabel={(n) => n.title}
|
|
115
|
+
reader={(n) => <DocumentPage recordKey={n.record_key} />}
|
|
116
|
+
actions={[
|
|
117
|
+
{ id: 'archive', run: (items) => archive.call(keys(items)) },
|
|
118
|
+
{ id: 'pin', key: 'shift+p', label: { en: 'Pin', fr: 'Épingler' },
|
|
119
|
+
run: (items) => pin.call(keys(items)) },
|
|
120
|
+
]}
|
|
121
|
+
/>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
That is the whole view. J/K (wrapping), Enter, Escape, selection with X,
|
|
127
|
+
Shift+J/K and Mod+A, E with Notis's Archive words and toast, the selection bar,
|
|
128
|
+
the `?` sheet, open as Side, Center or Full, the one-pane rule next to chat and the
|
|
129
|
+
phone layout come with it. `openParam` names the declared record param, so the
|
|
130
|
+
open note lives in the link. `search` fills the host top bar search field and
|
|
131
|
+
filters the loaded notes; `crumbLabel` adds the open note to the top bar crumb
|
|
132
|
+
("Notes / Groceries"); `readerLabel` names it in the reader bar. The view draws
|
|
133
|
+
no title, heading or search field of its own. `archive` is a standard action: it
|
|
134
|
+
brings its own words and key. `pin` is the Space's own: it brings its EN and FR
|
|
135
|
+
words and a key the clash check accepts. Add `tabs` for real saved filters and
|
|
136
|
+
`create` for a "+" that makes a record. Other kinds of view start from their own
|
|
137
|
+
piece; see [Design](design.md#pick-the-piece).
|
|
138
|
+
|
|
139
|
+
Keep hooks unconditional; conditional record/list branches can be separate
|
|
140
|
+
components. The [SDK reference](sdk.md) covers data hooks, record components,
|
|
141
|
+
navigation and the toolkit pieces.
|
|
142
|
+
|
|
143
|
+
## Params and declared lists
|
|
144
|
+
|
|
145
|
+
- Param types: `record`, `enum`, `text`, `number`, `date`, `boolean`. Each needs a
|
|
146
|
+
description. Enum values and defaults are typed; a required param has no default.
|
|
147
|
+
- Record params name a declared database and have no default record. `main: true`
|
|
148
|
+
claims that database's main view. `slugProperty` is a title/number property used
|
|
149
|
+
for readable link text, not record identity.
|
|
150
|
+
- One optional (never `required`) record param per view may declare `page: {where}`:
|
|
151
|
+
a matching saved HTML page or report then opens full screen as its own page, for
|
|
152
|
+
Editors in the Portal (Back, plus Share for HTML) and, for HTML pages only, on its
|
|
153
|
+
record Site. `where` compares
|
|
154
|
+
fixed values over `record_key`/`id`, `content_type`/`file_type`/`title` and select,
|
|
155
|
+
status or checkbox properties; it never reaches the browser. Viewers still get the
|
|
156
|
+
view, so keep its own HTML/report rendering. The full rules live under Record pages
|
|
157
|
+
in the platform reference (`docs/notis-spaces-platform.md`).
|
|
158
|
+
- `path` is descriptive lowercase words, up to four slash-separated segments;
|
|
159
|
+
do not put IDs, credentials or reserved product routes in it.
|
|
160
|
+
- `shows` for native data is `{database, where, open?}`. `where` is the native filter
|
|
161
|
+
grammar and is what `useShown` executes, not commentary beside a different query.
|
|
162
|
+
`open` names a record param over the same database.
|
|
163
|
+
- A condition may add `when: 'late'`, naming a boolean param. It is included
|
|
164
|
+
only when that setting is true; absent/false drops it before pagination.
|
|
165
|
+
This also gates `is_empty` for unplanned tasks. `tasksViewFilter` pairs with
|
|
166
|
+
`tasksViewParams`; bind their property names and Done status to the actual schema.
|
|
167
|
+
Its `today` date param defaults to the declared timezone's today; pin it for
|
|
168
|
+
dated answers. Clear conflicting date/period/late/unplanned settings in controls.
|
|
169
|
+
- A project-scoped task list can use
|
|
170
|
+
`{field: {property: 'Project'}, op: 'contains', value: '{project}'}` with a declared
|
|
171
|
+
project record param. `{project.Status}` reads a property of that authorized record.
|
|
172
|
+
- For connected-service content use `{about, services?}` and declared actions.
|
|
173
|
+
This descriptive form is not a native executable list; use `useAction` for reads.
|
|
174
|
+
- Preserve the application's real semantics and option names. For the existing
|
|
175
|
+
Tasks migration, Inbox is **Project empty OR Status equals Inbox**. Keep imported
|
|
176
|
+
rows, statuses and creation defaults; add the Inbox option only if absent. Its
|
|
177
|
+
native filter is `{or: [{field: {property: 'Project'}, op: 'is_empty'},
|
|
178
|
+
{field: {property: 'Status'}, op: 'equals', value: 'Inbox'}]}`. Other applications
|
|
179
|
+
must use their own inspected schema rather than copying these labels blindly.
|
|
180
|
+
|
|
181
|
+
## Create a database in the same release
|
|
182
|
+
|
|
183
|
+
Replace an existing database reference with:
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
resources: {
|
|
187
|
+
notes: { kind: 'database', create: {
|
|
188
|
+
name: 'Notes',
|
|
189
|
+
schema: {
|
|
190
|
+
schema_version: 1, value_encoding_version: 1, coercion_version: 1,
|
|
191
|
+
title_property_id: 'title', property_order: ['title'],
|
|
192
|
+
properties: { title: { id: 'title', name: 'Name', kind: 'title',
|
|
193
|
+
storage_family: 'textish', description: '', order: 0, config: {} } },
|
|
194
|
+
},
|
|
195
|
+
} },
|
|
196
|
+
},
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
The same view declares a record param over `notes` with `main: true`. Promotion
|
|
200
|
+
creates the database, link, main view, optional fictional `starterRows` and source
|
|
201
|
+
atomically; a later failure leaves none of them behind. Verification does not create
|
|
202
|
+
it. `create` is creation-only: later schema edits use native database tools;
|
|
203
|
+
`spaces pull` refreshes the declaration from the live schema.
|
|
204
|
+
|
|
205
|
+
The separate native schema-tool creation route requires `links.add` and
|
|
206
|
+
`main_view: {space_id, param}` in that linked Space. Until the Space next deploys
|
|
207
|
+
that main param, record links open the Space and writes return `view_warning`.
|
|
208
|
+
Inspect current tools for exact argument shapes; do not repeatedly insert rows
|
|
209
|
+
because a pending main view cannot yet open one.
|
|
210
|
+
|
|
211
|
+
## Rendering and memory
|
|
212
|
+
|
|
213
|
+
Choose [memory](memory.md) deliberately. `chrome: 'hidden'` is for full-screen
|
|
214
|
+
presentations; ordinary collection views keep Portal chrome.
|
|
215
|
+
A Space whose published view hides chrome starts hidden from each person's sidebar;
|
|
216
|
+
it stays reachable by link and search. Each person can turn on **Show hidden Spaces**
|
|
217
|
+
in the sidebar's Spaces menu, then choose **Show in sidebar** in that Space's menu.
|
|
218
|
+
Skill review Spaces stay out of the sidebar, even with **Show hidden Spaces** on:
|
|
219
|
+
people open them from the Skill page's **Changes** list. A review a person already
|
|
220
|
+
chose to show stays in their sidebar until they hide it.
|
|
221
|
+
Optional `markdown: './markdown.ts'` names a module exporting a pure function of
|
|
222
|
+
`{params, shown}`. Its output must represent this view, not make hidden writes.
|
|
223
|
+
Use `<RenderChartData>` with the chart's actual rows so rendered Markdown contains
|
|
224
|
+
precise labels and values as well as its image.
|
|
225
|
+
|
|
226
|
+
Add synthetic action/list/body/record fixtures, then build and verify. Verification
|
|
227
|
+
and live rendering share the read-only renderer; fixture success does not prove
|
|
228
|
+
live permissions or data. After an authorized deploy, render the returned view link
|
|
229
|
+
with `notis views render` and inspect both the Markdown and full-height screenshot.
|