spine-framework 0.3.145 → 0.4.1
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/.env.example +76 -0
- package/.framework/.spine-manifest.json +19 -0
- package/.framework/cli/commands/agents.ts +61 -33
- package/.framework/cli/commands/auth.ts +60 -28
- package/.framework/cli/commands/create-app.ts +212 -80
- package/.framework/cli/commands/dev.ts +184 -68
- package/.framework/cli/commands/doctor.ts +324 -152
- package/.framework/cli/commands/generate.ts +119 -68
- package/.framework/cli/commands/init.ts +141 -242
- package/.framework/cli/commands/install-app.ts +1336 -314
- package/.framework/cli/commands/items.ts +31 -29
- package/.framework/cli/commands/migrate.ts +299 -156
- package/.framework/cli/commands/migrations.ts +62 -30
- package/.framework/cli/commands/pipelines.ts +31 -29
- package/.framework/cli/commands/status.ts +105 -45
- package/.framework/cli/commands/system.ts +47 -42
- package/.framework/cli/commands/test.ts +161 -102
- package/.framework/cli/commands/upgrade.ts +260 -0
- package/.framework/cli/commands/validate-app.ts +517 -161
- package/.framework/cli/context.ts +117 -85
- package/.framework/cli/env-loader.ts +74 -43
- package/.framework/cli/index.ts +70 -46
- package/.framework/cli/lib/project-files.ts +404 -0
- package/.framework/docs/guides/testing-guide.md +1 -1
- package/.framework/docs/runtime-types.md +72 -72
- package/.framework/functions/_shared/access.ts +84 -0
- package/.framework/functions/_shared/agent-runner.ts +5067 -1026
- package/.framework/functions/_shared/app-manifest.ts +214 -94
- package/.framework/functions/_shared/ast.ts +214 -0
- package/.framework/functions/_shared/audit.ts +91 -55
- package/.framework/functions/_shared/cil.ts +368 -127
- package/.framework/functions/_shared/db.ts +337 -68
- package/.framework/functions/_shared/funnel.ts +228 -0
- package/.framework/functions/_shared/geo.ts +105 -0
- package/.framework/functions/_shared/hash-api-key.ts +94 -17
- package/.framework/functions/_shared/index.ts +22 -224
- package/.framework/functions/_shared/kb.ts +832 -58
- package/.framework/functions/_shared/llm.ts +118 -18
- package/.framework/functions/_shared/logging.ts +317 -19
- package/.framework/functions/_shared/middleware.ts +701 -131
- package/.framework/functions/_shared/notify.ts +70 -0
- package/.framework/functions/_shared/outcomes.ts +34 -19
- package/.framework/functions/_shared/permissions.ts +501 -315
- package/.framework/functions/_shared/pipeline-runner.ts +704 -155
- package/.framework/functions/_shared/principal.ts +436 -263
- package/.framework/functions/_shared/rate-limit.ts +233 -0
- package/.framework/functions/_shared/resolve-credentials.ts +86 -19
- package/.framework/functions/_shared/resolve-ids.ts +203 -139
- package/.framework/functions/_shared/retry-deliveries.ts +51 -16
- package/.framework/functions/_shared/schema-utils.ts +602 -521
- package/.framework/functions/_shared/security.ts +345 -0
- package/.framework/functions/_shared/testing.ts +197 -172
- package/.framework/functions/_shared/tracing.ts +351 -21
- package/.framework/functions/_shared/trigger-engine.ts +425 -136
- package/.framework/functions/_shared/webhook-registration.ts +71 -70
- package/.framework/functions/_shared/webhook-registry.ts +126 -83
- package/.framework/functions/account-nodes.ts +30 -30
- package/.framework/functions/adapters/generic-webhook-inbound.ts +49 -16
- package/.framework/functions/adapters/generic-webhook-outbound.ts +17 -17
- package/.framework/functions/adapters/openai-outbound.ts +15 -16
- package/.framework/functions/admin-data.ts +596 -173
- package/.framework/functions/admin-funnel.ts +64 -60
- package/.framework/functions/admin-install-funnel.ts +84 -66
- package/.framework/functions/admin-signals.ts +69 -51
- package/.framework/functions/ai-agents.ts +431 -106
- package/.framework/functions/ai-interactions.ts +186 -112
- package/.framework/functions/api-keys.ts +107 -107
- package/.framework/functions/apps.ts +154 -136
- package/.framework/functions/auth.ts +83 -65
- package/.framework/functions/cil-agent-ingest.ts +189 -232
- package/.framework/functions/cil-agent.ts +433 -177
- package/.framework/functions/cil-callmap.ts +642 -430
- package/.framework/functions/cil-config.ts +139 -135
- package/.framework/functions/cil-context.ts +214 -127
- package/.framework/functions/cil-doc.ts +587 -458
- package/.framework/functions/cil-embeddings.ts +453 -364
- package/.framework/functions/cil-graph.ts +427 -142
- package/.framework/functions/cil-ingest.ts +1418 -1154
- package/.framework/functions/cil-pipeline.ts +276 -21
- package/.framework/functions/cil-project.ts +659 -132
- package/.framework/functions/cil-validate.ts +198 -164
- package/.framework/functions/debug-auth.ts +57 -55
- package/.framework/functions/deliveries.ts +80 -21
- package/.framework/functions/embeddings.ts +1023 -318
- package/.framework/functions/eval-harness.ts +146 -108
- package/.framework/functions/integration-outbound.ts +205 -75
- package/.framework/functions/integration-routes.ts +128 -23
- package/.framework/functions/integrations.ts +125 -100
- package/.framework/functions/invites.ts +1095 -460
- package/.framework/functions/item-progress.ts +158 -102
- package/.framework/functions/kb.ts +34 -10
- package/.framework/functions/logs.ts +133 -133
- package/.framework/functions/observability.ts +152 -122
- package/.framework/functions/pipeline-executions.ts +147 -132
- package/.framework/functions/pipelines.ts +134 -119
- package/.framework/functions/prompt-configs.ts +96 -80
- package/.framework/functions/roles.ts +112 -82
- package/.framework/functions/security.ts +450 -0
- package/.framework/functions/system-cron.ts +117 -80
- package/.framework/functions/system.ts +158 -98
- package/.framework/functions/tests.ts +29 -29
- package/.framework/functions/timers.ts +94 -95
- package/.framework/functions/trigger-scheduler.ts +10 -0
- package/.framework/functions/triggers.ts +179 -149
- package/.framework/functions/types.ts +137 -125
- package/.framework/mcp/index.ts +133 -0
- package/.framework/mcp/load-env.ts +60 -0
- package/.framework/mcp/shared/app-manifest.ts +275 -0
- package/.framework/mcp/shared/db.ts +477 -0
- package/.framework/mcp/shared/kb.ts +118 -0
- package/.framework/mcp/tools/architect.ts +431 -0
- package/.framework/mcp/tools/cil/context.ts +345 -0
- package/.framework/mcp/tools/cil/graph.ts +242 -0
- package/.framework/mcp/tools/cil/ingest.ts +1217 -0
- package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +693 -0
- package/.framework/mcp/tools/cil/pipeline.ts +767 -0
- package/.framework/mcp/tools/cil/project.ts +791 -0
- package/.framework/mcp/tools/cil/retrieval.ts +336 -0
- package/.framework/mcp/tools/cil/search-core.ts +454 -0
- package/.framework/mcp/tools/cil/search.ts +97 -0
- package/.framework/mcp/tools/cil/suggest.ts +186 -0
- package/.framework/mcp/tools/cil/validate.ts +1369 -0
- package/.framework/mcp/tools/kb/delete.ts +139 -0
- package/.framework/mcp/tools/kb/index.ts +52 -0
- package/.framework/mcp/tools/kb/ingest.ts +84 -0
- package/.framework/mcp/tools/kb/list-types.ts +102 -0
- package/.framework/mcp/tools/kb/publish.ts +100 -0
- package/.framework/mcp/tools/kb/reindex.ts +86 -0
- package/.framework/mcp/tools/kb/revoke.ts +85 -0
- package/.framework/mcp/tools/kb/search.ts +101 -0
- package/.framework/mcp/tools/kb/upsert.ts +125 -0
- package/.framework/mcp/tools/observability.ts +510 -0
- package/.framework/migrations/001_core_schema.sql +15 -0
- package/.framework/migrations/002_core_rls_and_functions.sql +15 -0
- package/.framework/migrations/003_core_system_data.sql +16 -1
- package/.framework/migrations/004_core_rpc_and_broker.sql +17 -1
- package/.framework/migrations/005_core_observability.sql +17 -1
- package/.framework/migrations/006_security_hardening_rls.sql +15 -0
- package/.framework/migrations/007_kb_article_list.sql +17 -1
- package/.framework/migrations/008_items_target.sql +15 -0
- package/.framework/migrations/009_roles_slug_unique.sql +15 -0
- package/.framework/migrations/010_auth_user_trigger.sql +15 -0
- package/.framework/migrations/011_spine_system_account.sql +16 -0
- package/.framework/migrations/012_service_role_grants.sql +16 -0
- package/.framework/migrations/013_get_account_apps_role_filter.sql +15 -0
- package/.framework/migrations/014_apps_required_roles.sql +16 -0
- package/.framework/migrations/015_types_kind_slug_unique.sql +15 -0
- package/.framework/migrations/016_cil_types.sql +281 -0
- package/.framework/migrations/017_cil_stable_ids.sql +37 -0
- package/.framework/migrations/018_runtime_tables.sql +129 -0
- package/.framework/migrations/019_agent_prompt_columns.sql +56 -0
- package/.framework/migrations/020_schema_reconciliation.sql +67 -0
- package/.framework/migrations/021_kb_embedding_lifecycle.sql +31 -0
- package/.framework/migrations/032_cil_status_migration.sql +73 -0
- package/.framework/migrations/033_cil_versioning.sql +73 -0
- package/.framework/migrations/034_match_embeddings_knn.sql +115 -0
- package/.framework/migrations/035_rate_limits.sql +55 -0
- package/.framework/migrations/036_demo_record_flags.sql +72 -0
- package/.framework/migrations/037_kb_types_canonical.sql +244 -0
- package/.framework/migrations/038_drop_demo_record_flags.sql +38 -0
- package/.framework/migrations/042_registration_hierarchy.sql +309 -0
- package/.framework/migrations/043_policy_actor_cleanup.sql +39 -0
- package/.framework/migrations/044_match_embeddings_filtered_knn.sql +151 -0
- package/.framework/migrations/045_security_critical_rls.sql +139 -0
- package/.framework/migrations/046_security_missing_rls.sql +79 -0
- package/.framework/migrations/047_people_updated_by.sql +27 -0
- package/.framework/migrations/048_watcher_last_seen_at.sql +24 -0
- package/.framework/migrations/049_security_blocklist.sql +148 -0
- package/.framework/migrations/050_notifications.sql +49 -0
- package/.framework/migrations/051_message_agent_fields.sql +74 -0
- package/.framework/migrations/052_registration_security.sql +421 -0
- package/.framework/migrations/053_builtin_action_seeds.sql +66 -0
- package/.framework/migrations/054_kb_ingest_lease.sql +157 -0
- package/.framework/migrations/055_type_id_drift_reconciliation.sql +33 -0
- package/.framework/migrations/056_slug_column_reconciliation.sql +38 -0
- package/.framework/migrations/057_pipelines_slug_identity.sql +14 -0
- package/.framework/migrations/058_account_data_field_declarations.sql +53 -0
- package/.framework/migrations/059_registration_placement_fixes.sql +269 -0
- package/.framework/migrations/060_account_person_record_permissions.sql +38 -0
- package/.framework/migrations/061_fk_dedup.sql +32 -0
- package/.framework/public/spine-logo.svg +10 -3
- package/.framework/scripts/app-install-cli.ts +190 -93
- package/.framework/scripts/assemble-frontend.sh +127 -44
- package/.framework/scripts/assemble-functions.sh +128 -30
- package/.framework/scripts/boundary-check.sh +6 -2
- package/.framework/scripts/build-manifest.sh +24 -68
- package/.framework/scripts/check-core-integrity.sh +15 -76
- package/.framework/scripts/checksum-manifest.mts +343 -0
- package/.framework/scripts/cil-migrate-markers.ts +403 -0
- package/.framework/scripts/fix-cil-markers.mjs +176 -0
- package/.framework/scripts/verify-integrity.sh +21 -57
- package/.framework/scripts/verify-manifest.mts +305 -0
- package/.framework/seeds/types/funnel_signal_use.json +74 -21
- package/.framework/seeds/types/spine_instance.json +73 -21
- package/.framework/src/App.tsx +118 -72
- package/.framework/src/apps/admin/index.tsx +855 -58
- package/.framework/src/components/AppWrapper.tsx +43 -45
- package/.framework/src/components/CustomAppLoader.tsx +160 -116
- package/.framework/src/components/admin/AdminListPage.tsx +46 -44
- package/.framework/src/components/admin/AdminSidebar.tsx +57 -47
- package/.framework/src/components/admin/AdminStatsCard.tsx +46 -44
- package/.framework/src/components/admin/PageInstructions.tsx +98 -2
- package/.framework/src/components/admin/SortableTableHeader.tsx +44 -45
- package/.framework/src/components/app-shell/GenericAppShell.tsx +64 -65
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +44 -47
- package/.framework/src/components/app-shell/GenericListPage.tsx +45 -49
- package/.framework/src/components/app-sidebar.tsx +42 -45
- package/.framework/src/components/auth/ProtectedRoute.tsx +48 -41
- package/.framework/src/components/auth/TurnstileWidget.tsx +27 -0
- package/.framework/src/components/kb/KBArticleEditor.tsx +231 -22
- package/.framework/src/components/kb/KBArticleList.tsx +251 -10
- package/.framework/src/components/layout/AppShell.tsx +51 -45
- package/.framework/src/components/layout/Header.tsx +42 -43
- package/.framework/src/components/layout/Layout.tsx +46 -46
- package/.framework/src/components/layout/Sidebar.tsx +196 -96
- package/.framework/src/components/runtime/DataDetailHeader.tsx +55 -30
- package/.framework/src/components/runtime/DataDetailPage.tsx +31 -269
- package/.framework/src/components/runtime/DataFilters.tsx +49 -74
- package/.framework/src/components/runtime/DataHeader.tsx +53 -32
- package/.framework/src/components/runtime/DataListPage.tsx +51 -155
- package/.framework/src/components/runtime/DataStats.tsx +66 -44
- package/.framework/src/components/runtime/DataTable.tsx +49 -149
- package/.framework/src/components/runtime/SchemaDetailForm.tsx +45 -75
- package/.framework/src/components/runtime/index.ts +119 -16
- package/.framework/src/components/search-form.tsx +46 -29
- package/.framework/src/components/shared/AgentView.tsx +65 -48
- package/.framework/src/components/shared/FieldRenderer.tsx +144 -50
- package/.framework/src/components/shared/InviteManager.tsx +207 -97
- package/.framework/src/components/shared/MemberList.tsx +97 -0
- package/.framework/src/components/shared/SchemaFields.tsx +107 -86
- package/.framework/src/components/ui/DataTable.tsx +80 -68
- package/.framework/src/components/ui/Form.tsx +157 -146
- package/.framework/src/components/ui/ItemCard.tsx +74 -67
- package/.framework/src/components/ui/ItemListView.tsx +73 -68
- package/.framework/src/components/ui/LoadingSpinner.tsx +43 -48
- package/.framework/src/components/ui/Modal.tsx +78 -68
- package/.framework/src/components/ui/RichTextEditor.tsx +89 -69
- package/.framework/src/components/ui/accordion.tsx +85 -86
- package/.framework/src/components/ui/alert-dialog.tsx +197 -184
- package/.framework/src/components/ui/alert.tsx +105 -94
- package/.framework/src/components/ui/aspect-ratio.tsx +57 -43
- package/.framework/src/components/ui/avatar.tsx +122 -107
- package/.framework/src/components/ui/badge.tsx +60 -55
- package/.framework/src/components/ui/breadcrumb.tsx +127 -128
- package/.framework/src/components/ui/button-group.tsx +86 -72
- package/.framework/src/components/ui/button.tsx +71 -50
- package/.framework/src/components/ui/calendar.tsx +72 -57
- package/.framework/src/components/ui/card.tsx +136 -129
- package/.framework/src/components/ui/carousel.tsx +226 -107
- package/.framework/src/components/ui/chart.tsx +252 -147
- package/.framework/src/components/ui/checkbox.tsx +43 -44
- package/.framework/src/components/ui/collapsible.tsx +86 -71
- package/.framework/src/components/ui/combobox.tsx +282 -249
- package/.framework/src/components/ui/command.tsx +158 -146
- package/.framework/src/components/ui/context-menu.tsx +239 -240
- package/.framework/src/components/ui/dialog.tsx +174 -157
- package/.framework/src/components/ui/direction.tsx +72 -56
- package/.framework/src/components/ui/drawer.tsx +168 -169
- package/.framework/src/components/ui/dropdown-menu.tsx +254 -223
- package/.framework/src/components/ui/empty.tsx +131 -120
- package/.framework/src/components/ui/field.tsx +205 -173
- package/.framework/src/components/ui/hover-card.tsx +71 -72
- package/.framework/src/components/ui/input-group.tsx +148 -133
- package/.framework/src/components/ui/input-otp.tsx +99 -86
- package/.framework/src/components/ui/input.tsx +43 -41
- package/.framework/src/components/ui/item.tsx +207 -185
- package/.framework/src/components/ui/kbd.tsx +57 -56
- package/.framework/src/components/ui/label.tsx +45 -41
- package/.framework/src/components/ui/menubar.tsx +268 -236
- package/.framework/src/components/ui/native-select.tsx +85 -86
- package/.framework/src/components/ui/navigation-menu.tsx +166 -156
- package/.framework/src/components/ui/pagination.tsx +131 -141
- package/.framework/src/components/ui/popover.tsx +125 -128
- package/.framework/src/components/ui/progress.tsx +47 -44
- package/.framework/src/components/ui/radio-group.tsx +60 -55
- package/.framework/src/components/ui/resizable.tsx +85 -72
- package/.framework/src/components/ui/scroll-area.tsx +57 -58
- package/.framework/src/components/ui/select.tsx +182 -169
- package/.framework/src/components/ui/separator.tsx +42 -43
- package/.framework/src/components/ui/sheet.tsx +170 -159
- package/.framework/src/components/ui/sidebar.tsx +395 -398
- package/.framework/src/components/ui/skeleton.tsx +42 -43
- package/.framework/src/components/ui/slider.tsx +61 -44
- package/.framework/src/components/ui/sonner.tsx +44 -44
- package/.framework/src/components/ui/spinner.tsx +47 -42
- package/.framework/src/components/ui/switch.tsx +56 -42
- package/.framework/src/components/ui/table-primitives.tsx +272 -132
- package/.framework/src/components/ui/table.tsx +140 -142
- package/.framework/src/components/ui/tabs.tsx +110 -93
- package/.framework/src/components/ui/textarea.tsx +43 -44
- package/.framework/src/components/ui/toggle-group.tsx +87 -71
- package/.framework/src/components/ui/toggle.tsx +56 -56
- package/.framework/src/components/ui/tooltip.tsx +99 -85
- package/.framework/src/contexts/AppContext.tsx +166 -114
- package/.framework/src/contexts/AuthContext.tsx +232 -137
- package/.framework/src/hooks/use-mobile.ts +43 -44
- package/.framework/src/hooks/useApi.ts +185 -172
- package/.framework/src/hooks/useAppPath.ts +31 -29
- package/.framework/src/hooks/useApps.ts +77 -42
- package/.framework/src/hooks/useEntityList.ts +66 -29
- package/.framework/src/hooks/useEntityRecord.ts +76 -32
- package/.framework/src/hooks/useForm.ts +62 -30
- package/.framework/src/hooks/useListSchema.ts +60 -43
- package/.framework/src/hooks/useSchemaRecord.ts +115 -95
- package/.framework/src/lib/api.ts +258 -134
- package/.framework/src/lib/registration.ts +181 -0
- package/.framework/src/lib/supabase.ts +118 -81
- package/.framework/src/lib/utils.ts +266 -266
- package/.framework/src/main.tsx +43 -44
- package/.framework/src/pages/DashboardPage.tsx +44 -43
- package/.framework/src/pages/NoAppPage.tsx +50 -0
- package/.framework/src/pages/NotFoundPage.tsx +32 -29
- package/.framework/src/pages/SetupPage.tsx +34 -33
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +69 -58
- package/.framework/src/pages/admin/AIAgentsPage.tsx +43 -40
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +63 -55
- package/.framework/src/pages/admin/APIKeysPage.tsx +44 -42
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +117 -94
- package/.framework/src/pages/admin/AppDetailPage.tsx +48 -42
- package/.framework/src/pages/admin/AppsPage.tsx +45 -42
- package/.framework/src/pages/admin/DeliveriesPage.tsx +49 -17
- package/.framework/src/pages/admin/DesignedPage.tsx +31 -30
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +58 -0
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +49 -0
- package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +31 -29
- package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +46 -29
- package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -29
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +68 -55
- package/.framework/src/pages/admin/IntegrationsPage.tsx +45 -42
- package/.framework/src/pages/admin/InvitesPage.tsx +60 -44
- package/.framework/src/pages/admin/LogsPage.tsx +87 -137
- package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +31 -29
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +150 -89
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +77 -104
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +44 -43
- package/.framework/src/pages/admin/PipelinesPage.tsx +59 -145
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +53 -42
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +47 -117
- package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +31 -44
- package/.framework/src/pages/admin/RoleDetailPage.tsx +49 -92
- package/.framework/src/pages/admin/RolesPage.tsx +47 -164
- package/.framework/src/pages/admin/SecurityPage.tsx +310 -0
- package/.framework/src/pages/admin/SelectTestPage.tsx +30 -32
- package/.framework/src/pages/admin/ShadcnTestPage.tsx +37 -44
- package/.framework/src/pages/admin/SimpleDashboard.tsx +32 -44
- package/.framework/src/pages/admin/TestRunDetailPage.tsx +97 -44
- package/.framework/src/pages/admin/TestingDashboard.tsx +126 -71
- package/.framework/src/pages/admin/TimerDetailPage.tsx +67 -55
- package/.framework/src/pages/admin/TimersPage.tsx +44 -42
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +47 -42
- package/.framework/src/pages/admin/TriggersPage.tsx +58 -57
- package/.framework/src/pages/admin/TypeDetailPage.tsx +91 -55
- package/.framework/src/pages/admin/TypesPage.tsx +45 -42
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +258 -128
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +127 -123
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +308 -235
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +159 -110
- package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +432 -0
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +200 -178
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +286 -239
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +211 -90
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +156 -143
- package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +379 -0
- package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +337 -0
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +219 -214
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
- package/.framework/src/pages/auth/AuthConfirmPage.tsx +135 -65
- package/.framework/src/pages/auth/ForgotPasswordPage.tsx +39 -31
- package/.framework/src/pages/auth/LoginPage.tsx +38 -32
- package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -28
- package/.framework/src/pages/auth/RegisterPage.tsx +429 -155
- package/.framework/src/pages/spine-framework/APIPage.tsx +33 -30
- package/.framework/src/pages/spine-framework/CLIPage.tsx +32 -30
- package/.framework/src/types/auth.ts +101 -93
- package/.framework/src/types/types.ts +283 -262
- package/.framework/templates/project.json +87 -0
- package/.framework/templates/spine.config.neutral.json +7 -0
- package/.framework/tests/api/api-surface.test.ts +381 -0
- package/.framework/tests/fixtures/seed.ts +427 -0
- package/.framework/tests/fixtures/teardown.ts +228 -0
- package/.framework/tests/reporter.ts +351 -0
- package/.framework/tests/setup.ts +135 -0
- package/.framework/tests/ui/ui-sweep.ts +278 -0
- package/.framework/tests/unit/admin-data-logger.test.ts +310 -0
- package/.framework/tests/unit/agent-runner.test.ts +2389 -0
- package/.framework/tests/unit/ai-interactions.test.ts +81 -0
- package/.framework/tests/unit/app-manifest.test.ts +359 -0
- package/.framework/tests/unit/assembly-scripts.test.ts +172 -0
- package/.framework/tests/unit/cil-determinism.test.ts +85 -0
- package/.framework/tests/unit/core-isolation.test.ts +153 -0
- package/.framework/tests/unit/funnel-signals.test.ts +135 -0
- package/.framework/tests/unit/install-app.test.ts +1759 -0
- package/.framework/tests/unit/invites-security.test.ts +572 -0
- package/.framework/tests/unit/kb-ingest-lease.test.ts +287 -0
- package/.framework/tests/unit/kb-search.test.ts +119 -0
- package/.framework/tests/unit/migrate.test.ts +509 -0
- package/.framework/tests/unit/notify.test.ts +136 -0
- package/.framework/tests/unit/permissions.test.ts +269 -0
- package/.framework/tests/unit/pipeline-runner.test.ts +755 -0
- package/.framework/tests/unit/principal-cache.test.ts +138 -0
- package/.framework/tests/unit/retrieval-golden.test.ts +520 -0
- package/.framework/tests/unit/runtime-isolation.test.ts +642 -0
- package/.framework/tests/unit/schema-utils.test.ts +225 -0
- package/.framework/tests/unit/trigger-engine.test.ts +513 -0
- package/.framework/tests/unit/validate-app.test.ts +527 -0
- package/README.md +34 -3
- package/bin/spine-framework.cjs +1 -0
- package/config/tailwind.config.cjs +7 -0
- package/config/tsconfig.functions.json +42 -0
- package/config/tsconfig.json +37 -9
- package/config/vite.config.ts +31 -2
- package/netlify.toml +31 -3
- package/package.json +46 -29
- package/scripts/assemble-frontend.sh +127 -44
- package/scripts/assemble-functions.sh +127 -29
- package/scripts/boundary-check.sh +6 -2
- package/scripts/build-manifest.sh +24 -68
- package/scripts/checksum-manifest.mts +345 -0
- package/scripts/dev-clean.sh +86 -0
- package/scripts/dev-netlify.sh +49 -0
- package/scripts/netlify-dev-wrapper.sh +2 -0
- package/scripts/verify-install.ts +358 -0
- package/scripts/verify-integrity.sh +21 -57
- package/scripts/verify-manifest.mts +305 -0
- package/templates/project/gitignore +45 -0
- package/{config → templates/project}/package-lock.json +22335 -9366
- package/vitest.config.ts +46 -0
- package/.framework/public/spine.config.json +0 -91
- package/config/deno.lock +0 -108
- package/config/tsconfig.node.tsbuildinfo +0 -1
- package/config/tsconfig.tsbuildinfo +0 -1
- package/config/vite.config.d.ts +0 -2
- package/custom/.devin/AGENT.md +0 -357
- package/custom/.devin/skills/install-app/SKILL.md +0 -39
- package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +0 -39
- package/custom/.devin/skills/spine-workbench-idea/SKILL.md +0 -36
- package/custom/.devin/skills/spine-workbench-implement/SKILL.md +0 -46
- package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +0 -28
- package/custom/.devin/skills/spine-workbench-plan/SKILL.md +0 -38
- package/custom/.devin/workflows/app-install.yaml +0 -83
- package/custom/README.md +0 -79
- package/docs/README.md +0 -15
- package/scripts/app-install-cli.ts +0 -286
- package/scripts/check-core-integrity.sh +0 -82
- package/scripts/ingest-chunks.cjs +0 -202
- package/scripts/kb-chunk-parser.cjs +0 -312
- package/scripts/kb-chunk-parser.ts +0 -330
- package/scripts/kb-ingest-docs.ts +0 -203
- package/scripts/load-test-app-install.ts +0 -484
- package/scripts/test-login.js +0 -33
- package/spine.config.json +0 -91
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/architect.ts:architect:file" type="file" identity="architect" parent="~/.framework/mcp/tools/architect.ts"]
|
|
2
|
+
// CIL[DOC-MACRO purpose="Register architect MCP tools for Spine Way evaluation, design schema validation, and app manifest lookups."]
|
|
3
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Expose MCP tools that evaluate proposals against Spine fundamentals, validate design schemas, and query installed app manifests."]
|
|
4
|
+
// CIL[DOC-CONTEXT module="mcp" layer="framework" related_files=".framework/mcp/shared/app-manifest.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/architect.ts"]
|
|
5
|
+
// CIL[DOC-CONTRACT inputs="server: McpServer; tool-specific parameters for proposal, primitive, fundamental, design_schema, app slug/id" outputs="JSON content with assessment, placement, validation errors, or app record" errors="Unknown fundamental; invalid design schema; missing app; Supabase query failures" side_effects="Reads public.apps via adminDb; no writes"]
|
|
6
|
+
// CIL[DOC-MICRO logic_summary="Registers six tools on the MCP server: evaluate proposals, core-vs-custom placement, get a fundamental, validate a design schema, list apps, and get an app merged with its manifest." notable_decisions="FUNDAMENTALS, DATA_TYPES, and DISPLAY_TYPES are hard-coded local maps; app queries use adminDb with manifest helper functions."]
|
|
7
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
8
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
9
|
+
|
|
10
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
11
|
+
import { z } from 'zod'
|
|
12
|
+
import { adminDb } from '../shared/db.js'
|
|
13
|
+
import { loadManifest, mergeWithManifest } from '../shared/app-manifest.js'
|
|
14
|
+
|
|
15
|
+
export function register(server: McpServer) {
|
|
16
|
+
server.registerTool(
|
|
17
|
+
'spine_architect_evaluate',
|
|
18
|
+
{
|
|
19
|
+
description: 'Evaluate a code or design proposal against the Spine Way fundamentals and return a structured assessment with observations and recommendations.',
|
|
20
|
+
inputSchema: z.object({
|
|
21
|
+
proposal: z.string().describe('The proposal or change description to evaluate'),
|
|
22
|
+
against: z.array(z.string()).optional().describe('Specific fundamental names to evaluate against (optional)'),
|
|
23
|
+
}),
|
|
24
|
+
},
|
|
25
|
+
async ({ proposal, against }) => {
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
const observations = [
|
|
29
|
+
'Core-vs-custom boundary: framework primitives live in .framework/, product-specific behavior lives in custom/apps/.',
|
|
30
|
+
'Design schema completeness: every new runtime type needs fields, views, and record_permissions.',
|
|
31
|
+
'Permission design: record_permissions are the base grant; field permissions are overrides only.',
|
|
32
|
+
'CIL hygiene: code changes are followed by re-syncing CIL chunks, embeddings, and mappings.',
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
if (against && against.length > 0) {
|
|
36
|
+
// A richer implementation would filter to the requested fundamentals.
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
content: [{
|
|
41
|
+
type: 'text',
|
|
42
|
+
text: JSON.stringify({
|
|
43
|
+
proposal,
|
|
44
|
+
verdict: 'review',
|
|
45
|
+
observations,
|
|
46
|
+
recommendation: 'Re-read the Spine Way and the design-schema checklist before proceeding.',
|
|
47
|
+
}, null, 2),
|
|
48
|
+
}],
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
server.registerTool(
|
|
54
|
+
'spine_core_vs_custom_check',
|
|
55
|
+
{
|
|
56
|
+
description: 'Advise whether a change belongs in the core .framework/ layer or a custom app in custom/apps/.',
|
|
57
|
+
inputSchema: z.object({
|
|
58
|
+
description: z.string().describe('What the change does'),
|
|
59
|
+
primitives: z.array(z.string()).optional().describe('Spine primitives it touches (e.g., types, roles, migrations, functions, components)'),
|
|
60
|
+
}),
|
|
61
|
+
},
|
|
62
|
+
async ({ description, primitives }) => {
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
const primitivesList = primitives?.join(', ') || 'none provided'
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
const lower = (description + ' ' + primitivesList).toLowerCase()
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
let placement = 'custom'
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
let reason = 'This looks like product-specific behavior that should live in a custom app.'
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
if (
|
|
86
|
+
lower.includes('migration') ||
|
|
87
|
+
lower.includes('rls') ||
|
|
88
|
+
lower.includes('rpc') ||
|
|
89
|
+
lower.includes('auth') ||
|
|
90
|
+
lower.includes('permission') ||
|
|
91
|
+
lower.includes('core primitive') ||
|
|
92
|
+
lower.includes('design schema') ||
|
|
93
|
+
lower.includes('shared component') ||
|
|
94
|
+
lower.includes('admin-data')
|
|
95
|
+
) {
|
|
96
|
+
placement = 'core'
|
|
97
|
+
reason = 'This change touches framework-level primitives (data model, auth, permissions, migrations, shared runtime, or generic components) and should live in .framework/.'
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
content: [{
|
|
107
|
+
type: 'text',
|
|
108
|
+
text: JSON.stringify({
|
|
109
|
+
description,
|
|
110
|
+
primitives: primitivesList,
|
|
111
|
+
placement,
|
|
112
|
+
reason,
|
|
113
|
+
boundary_rule: 'If it could be used by more than one app, it belongs in .framework/; if it is specific to one product workflow, it belongs in custom/apps/.',
|
|
114
|
+
}, null, 2),
|
|
115
|
+
}],
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
const FUNDAMENTALS: Record<string, { rule: string; guidance: string }> = {
|
|
123
|
+
'core-never-imports-from-custom': {
|
|
124
|
+
rule: 'Core never imports from custom',
|
|
125
|
+
guidance: '.framework/ must not contain imports from custom/ or hardcoded custom app slugs. Custom code extends core through data or custom functions.',
|
|
126
|
+
},
|
|
127
|
+
'custom-uses-core-aliases': {
|
|
128
|
+
rule: 'Custom code uses @core/* aliases, not relative paths into .framework/',
|
|
129
|
+
guidance: 'From custom apps: import from "@core/...". From custom functions after assembly: import from "./_shared/...".',
|
|
130
|
+
},
|
|
131
|
+
'apps-register-through-public-apps': {
|
|
132
|
+
rule: 'Custom apps register through public.apps',
|
|
133
|
+
guidance: 'A custom app is defined by a manifest.json, installed via install-app, and represented as a row in public.apps.',
|
|
134
|
+
},
|
|
135
|
+
'runtime-crud-through-admin-data': {
|
|
136
|
+
rule: 'Runtime record CRUD goes through /api/admin-data',
|
|
137
|
+
guidance: 'Use /api/admin-data for items, threads, messages, links, attachments, watchers. Do not write custom Netlify wrappers for runtime CRUD.',
|
|
138
|
+
},
|
|
139
|
+
'types-define-behavior-via-design-schema': {
|
|
140
|
+
rule: 'Types define behavior via design_schema',
|
|
141
|
+
guidance: 'Domain logic belongs in the type\'s design_schema (fields, views, permissions, functionality). validation_schema is generated from it.',
|
|
142
|
+
},
|
|
143
|
+
'record-permissions-are-base-grant': {
|
|
144
|
+
rule: 'record_permissions are the base grant; field permissions are overrides',
|
|
145
|
+
guidance: 'Start with the most restrictive record_permissions per role. Add fields.<name>.permissions only to loosen or further restrict a specific field.',
|
|
146
|
+
},
|
|
147
|
+
'rls-enabled-and-correct': {
|
|
148
|
+
rule: 'RLS must be enabled with correct policies',
|
|
149
|
+
guidance: 'Every tenant/account table must have RLS. Policies use current_actor_id() and get_accessible_accounts(). Use adminDb only when bypassing RLS is necessary.',
|
|
150
|
+
},
|
|
151
|
+
'migrations-idempotent-and-ordered': {
|
|
152
|
+
rule: 'Migrations are idempotent and ordered',
|
|
153
|
+
guidance: 'File naming: NNN_description.sql with unique 3-digit prefixes. Use IF NOT EXISTS, DROP POLICY IF EXISTS, ON CONFLICT DO NOTHING, and conditional DO $$ blocks.',
|
|
154
|
+
},
|
|
155
|
+
'field-storage-follows-system-flag': {
|
|
156
|
+
rule: 'Field storage follows the system flag',
|
|
157
|
+
guidance: 'system: true fields are top-level record columns; non-system fields live inside record.data.<field>. Send payloads accordingly to /api/admin-data.',
|
|
158
|
+
},
|
|
159
|
+
'secrets-on-backend-only': {
|
|
160
|
+
rule: 'Secrets and service keys stay on the backend',
|
|
161
|
+
guidance: 'Browser code uses VITE_SUPABASE_ANON_KEY and VITE_SUPABASE_URL only. Service keys and app secrets never appear in frontend code or committed env files.',
|
|
162
|
+
},
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
server.registerTool(
|
|
168
|
+
'spine_get_fundamental',
|
|
169
|
+
{
|
|
170
|
+
description: 'Return a named Spine Way fundamental rule and guidance.',
|
|
171
|
+
inputSchema: z.object({
|
|
172
|
+
name: z.string().describe('Fundamental name, e.g. "core-never-imports-from-custom" or "record-permissions-are-base-grant"'),
|
|
173
|
+
}),
|
|
174
|
+
},
|
|
175
|
+
async ({ name }) => {
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
const fundamental = FUNDAMENTALS[name]
|
|
179
|
+
|
|
180
|
+
if (!fundamental) {
|
|
181
|
+
return {
|
|
182
|
+
content: [{
|
|
183
|
+
type: 'text',
|
|
184
|
+
text: JSON.stringify({
|
|
185
|
+
ok: false,
|
|
186
|
+
error: `Unknown fundamental: ${name}`,
|
|
187
|
+
available: Object.keys(FUNDAMENTALS),
|
|
188
|
+
}, null, 2),
|
|
189
|
+
}],
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
content: [{
|
|
195
|
+
type: 'text',
|
|
196
|
+
text: JSON.stringify({ ok: true, name, ...fundamental }, null, 2),
|
|
197
|
+
}],
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
const DATA_TYPES = new Set([
|
|
205
|
+
'text', 'textarea', 'rich_text', 'email', 'phone', 'url', 'number', 'currency', 'range',
|
|
206
|
+
'date', 'datetime', 'boolean', 'checkbox', 'select', 'multiselect', 'radio', 'color',
|
|
207
|
+
'file', 'image', 'json', 'reference', 'address',
|
|
208
|
+
])
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
const DISPLAY_TYPES = new Set([
|
|
214
|
+
'text', 'input', 'textarea', 'rich_text', 'select', 'multiselect', 'radio', 'checkbox',
|
|
215
|
+
'switch', 'date_picker', 'datetime_picker', 'color_picker', 'file_upload', 'image_upload',
|
|
216
|
+
'range_slider', 'badge', 'timestamp', 'currency', 'number',
|
|
217
|
+
])
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
function validateDesignSchema(schema: any): { ok: boolean; errors: string[] } {
|
|
222
|
+
const errors: string[] = []
|
|
223
|
+
if (!schema || typeof schema !== 'object') {
|
|
224
|
+
errors.push('design_schema must be an object')
|
|
225
|
+
return { ok: false, errors }
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
const scope = schema.scope ?? 'account'
|
|
231
|
+
if (scope !== 'account' && scope !== 'platform') {
|
|
232
|
+
errors.push('scope must be "account" or "platform"')
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (!schema.fields || typeof schema.fields !== 'object' || Object.keys(schema.fields).length === 0) {
|
|
236
|
+
errors.push('fields is required and must contain at least one field definition')
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
for (const [key, field] of Object.entries(schema.fields || {})) {
|
|
240
|
+
if (!field || typeof field !== 'object') {
|
|
241
|
+
errors.push(`fields.${key} must be an object`)
|
|
242
|
+
continue
|
|
243
|
+
}
|
|
244
|
+
const f = field as any
|
|
245
|
+
if (!f.data_type) errors.push(`fields.${key} is missing data_type`)
|
|
246
|
+
else if (!DATA_TYPES.has(f.data_type)) errors.push(`fields.${key} has unknown data_type: ${f.data_type}`)
|
|
247
|
+
if (!f.label) errors.push(`fields.${key} is missing label`)
|
|
248
|
+
if (f.required === undefined) errors.push(`fields.${key} is missing required`)
|
|
249
|
+
if (['select', 'multiselect', 'radio'].includes(f.data_type) && (!f.options || !Array.isArray(f.options) || f.options.length === 0)) {
|
|
250
|
+
errors.push(`fields.${key} (${f.data_type}) requires options`)
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (!schema.record_permissions || typeof schema.record_permissions !== 'object') {
|
|
255
|
+
errors.push('record_permissions is required')
|
|
256
|
+
} else if (!Object.keys(schema.record_permissions).includes('system-admin') && !Object.keys(schema.record_permissions).includes('system_admin')) {
|
|
257
|
+
errors.push('record_permissions must grant at least system-admin or system_admin')
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (schema.views) {
|
|
261
|
+
if (schema.views.default_list) {
|
|
262
|
+
const list = schema.views.default_list
|
|
263
|
+
if (list.type !== 'list') errors.push('views.default_list.type must be "list"')
|
|
264
|
+
if (!list.fields || typeof list.fields !== 'object') errors.push('views.default_list.fields is required')
|
|
265
|
+
if (!list.default_sort) errors.push('views.default_list.default_sort is required')
|
|
266
|
+
}
|
|
267
|
+
if (schema.views.default_detail) {
|
|
268
|
+
const detail = schema.views.default_detail
|
|
269
|
+
if (detail.type !== 'detail') errors.push('views.default_detail.type must be "detail"')
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return { ok: errors.length === 0, errors }
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
server.registerTool(
|
|
277
|
+
'spine_design_schema_validate',
|
|
278
|
+
{
|
|
279
|
+
description: 'Validate a proposed design_schema against the Spine design-schema rules. Returns ok and a list of errors.',
|
|
280
|
+
inputSchema: z.object({
|
|
281
|
+
design_schema: z.record(z.any()).describe('The design_schema object to validate'),
|
|
282
|
+
check_views: z.boolean().default(true).optional().describe('Whether to require default_list and default_detail views'),
|
|
283
|
+
}),
|
|
284
|
+
},
|
|
285
|
+
async ({ design_schema, check_views }) => {
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
const result = validateDesignSchema(design_schema)
|
|
289
|
+
|
|
290
|
+
if (check_views && !design_schema.views) {
|
|
291
|
+
result.errors.push('views is required when check_views is true')
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (design_schema.views) {
|
|
295
|
+
if (check_views && !design_schema.views.default_list) result.errors.push('views.default_list is required')
|
|
296
|
+
if (check_views && !design_schema.views.default_detail) result.errors.push('views.default_detail is required')
|
|
297
|
+
for (const [viewName, view] of Object.entries(design_schema.views || {})) {
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
const v = view as any
|
|
301
|
+
|
|
302
|
+
if (!v || typeof v !== 'object') continue
|
|
303
|
+
for (const [fieldName, field] of Object.entries(v.fields || {})) {
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
const f = field as any
|
|
307
|
+
|
|
308
|
+
if (f && f.display_type && !DISPLAY_TYPES.has(f.display_type)) {
|
|
309
|
+
result.errors.push(`views.${viewName}.fields.${fieldName} has unknown display_type: ${f.display_type}`)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
}
|
|
314
|
+
if (v.sections) {
|
|
315
|
+
for (const section of v.sections) {
|
|
316
|
+
for (const [fieldName, field] of Object.entries(section.fields || {})) {
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
const f = field as any
|
|
320
|
+
|
|
321
|
+
if (f && f.display_type && !DISPLAY_TYPES.has(f.display_type)) {
|
|
322
|
+
result.errors.push(`views.${viewName}.sections.*.fields.${fieldName} has unknown display_type: ${f.display_type}`)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
content: [{
|
|
332
|
+
type: 'text',
|
|
333
|
+
text: JSON.stringify({
|
|
334
|
+
ok: result.ok && result.errors.length === 0,
|
|
335
|
+
error_count: result.errors.length,
|
|
336
|
+
errors: result.errors,
|
|
337
|
+
}, null, 2),
|
|
338
|
+
}],
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
server.registerTool(
|
|
344
|
+
'spine_app_manifest_list',
|
|
345
|
+
{
|
|
346
|
+
description: 'List installed apps from the public.apps table.',
|
|
347
|
+
inputSchema: z.object({
|
|
348
|
+
include_manifest: z.boolean().default(false).optional().describe('Load and include each app manifest.json content'),
|
|
349
|
+
}),
|
|
350
|
+
},
|
|
351
|
+
async ({ include_manifest }) => {
|
|
352
|
+
const { data, error } = await adminDb.from('apps').select('id, slug, name, description, app_type, renderer, manifest_path, is_active, route_prefix').order('name')
|
|
353
|
+
if (error) {
|
|
354
|
+
return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: error.message }) }] }
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
const apps = (data || []).map((app: any) => {
|
|
360
|
+
const base = {
|
|
361
|
+
id: app.id,
|
|
362
|
+
slug: app.slug,
|
|
363
|
+
name: app.name,
|
|
364
|
+
description: app.description || '',
|
|
365
|
+
app_type: app.app_type || '',
|
|
366
|
+
renderer: app.renderer || '',
|
|
367
|
+
manifest_path: app.manifest_path || '',
|
|
368
|
+
is_active: app.is_active ?? true,
|
|
369
|
+
route_prefix: app.route_prefix || '',
|
|
370
|
+
}
|
|
371
|
+
if (include_manifest && app.manifest_path) {
|
|
372
|
+
const manifest = loadManifest(app.manifest_path)
|
|
373
|
+
return { ...base, manifest: manifest || null }
|
|
374
|
+
}
|
|
375
|
+
return base
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
return { content: [{ type: 'text', text: JSON.stringify({ ok: true, count: apps.length, apps }, null, 2) }] }
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
server.registerTool(
|
|
385
|
+
'spine_app_manifest_get',
|
|
386
|
+
{
|
|
387
|
+
description: 'Get one installed app by slug or id, optionally merged with its manifest.json.',
|
|
388
|
+
inputSchema: z.object({
|
|
389
|
+
slug: z.string().optional().describe('App slug'),
|
|
390
|
+
id: z.string().uuid().optional().describe('App UUID'),
|
|
391
|
+
}),
|
|
392
|
+
},
|
|
393
|
+
async ({ slug, id }) => {
|
|
394
|
+
if (!slug && !id) {
|
|
395
|
+
return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: 'Provide either slug or id' }) }] }
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
let query = adminDb.from('apps').select('*')
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
if (id) query = query.eq('id', id)
|
|
405
|
+
else query = query.eq('slug', slug)
|
|
406
|
+
const { data, error } = await query.maybeSingle()
|
|
407
|
+
if (error) {
|
|
408
|
+
return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: error.message }) }] }
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
if (!data) {
|
|
413
|
+
return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `App not found: ${slug || id}` }) }] }
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
const merged = mergeWithManifest(data)
|
|
418
|
+
|
|
419
|
+
return { content: [{ type: 'text', text: JSON.stringify({ ok: true, app: merged }, null, 2) }] }
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
)
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Register architect MCP tools for Spine Way evaluation, design schema validation, and app manifest lookups.'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/mcp/shared/app-manifest.ts"]
|
|
426
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
427
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
428
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
429
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
430
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
431
|
+
// CIL[END stable_id="~/.framework/mcp/tools/architect.ts:architect:file"]
|