spine-framework 0.3.144 → 0.4.0
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 +5051 -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 +20 -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,454 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module search-core
|
|
3
|
+
* @audience both
|
|
4
|
+
* @layer shared-core
|
|
5
|
+
* @stability stable
|
|
6
|
+
*
|
|
7
|
+
* This module provides core search functionalities for the application, leveraging the admin database for data retrieval and manipulation. It serves as a critical component in the overall architecture, facilitating efficient search operations across various datasets. INVARIANT: The module assumes that the database is always accessible and properly configured for search queries.
|
|
8
|
+
*
|
|
9
|
+
* @seeAlso db.js (provides the database connection and operations needed for search functionality.)
|
|
10
|
+
* @seeAlso shared.js (contains shared utilities that may be used across different modules.)
|
|
11
|
+
*
|
|
12
|
+
* @cil-generated
|
|
13
|
+
*/
|
|
14
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/search-core.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/mcp/tools/cil/search-core.ts"]
|
|
15
|
+
// CIL[DOC-MACRO purpose="Provides core search operations over the CIL chunk index"]
|
|
16
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Expose title, content, semantic and hybrid search utilities for CIL chunks"]
|
|
17
|
+
// CIL[DOC-CONTEXT module=".framework/mcp/tools/cil" layer="shared-core" related_files=".framework/mcp/shared/db.ts"]
|
|
18
|
+
// CIL[DOC-CONTRACT inputs="N/A" outputs="N/A" errors="Database and network failures propagate to caller" side_effects="N/A"]
|
|
19
|
+
// CIL[DOC-MICRO logic_summary="Imports adminDb and exports normalizeIdentifier, buildSearchResult, titleSearch, contentSearch, embedQuery, semanticSearch and hybridSearch" notable_decisions="[]"]
|
|
20
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
21
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
22
|
+
// CIL[DOC-AUDIENCE audience="both"]
|
|
23
|
+
import { adminDb } from '../../shared/db.js'
|
|
24
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Provides core search operations over the CIL chunk index'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
|
|
25
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
26
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
27
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
28
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
29
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
30
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/search-core.ts:module_header:module_header"]
|
|
31
|
+
|
|
32
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/search-core.ts:normalizeIdentifier:function" type="function" identity="normalizeIdentifier" parent="~/.framework/mcp/tools/cil/search-core.ts"]
|
|
33
|
+
// CIL[DOC-MACRO purpose="Normalize a string identifier to lowercase alphanumeric"]
|
|
34
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Sanitize raw strings for consistent identifier comparison"]
|
|
35
|
+
// CIL[DOC-CONTEXT module=".framework/mcp/tools/cil" layer="shared-core" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/search-core.ts"]
|
|
36
|
+
// CIL[DOC-CONTRACT inputs="s: string" outputs="string" errors="N/A" side_effects="none"]
|
|
37
|
+
// CIL[DOC-MICRO logic_summary="Converts input to lowercase and removes all non-alphanumeric characters" notable_decisions="[]"]
|
|
38
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
39
|
+
// CIL[DOC-STABILITY stability="internal"]
|
|
40
|
+
/**
|
|
41
|
+
* Normalizes a string identifier by converting it to lowercase and removing all non-alphanumeric characters. This function ensures that identifiers are consistent and suitable for further processing.
|
|
42
|
+
*
|
|
43
|
+
* @inputSpec
|
|
44
|
+
* s: string (required) — the string identifier to normalize.
|
|
45
|
+
* @outputSpec string — the normalized identifier consisting only of lowercase alphanumeric characters.
|
|
46
|
+
* @sideEffects none
|
|
47
|
+
* @stability internal
|
|
48
|
+
* @cil-generated
|
|
49
|
+
*/
|
|
50
|
+
export const normalizeIdentifier = (s: string) =>
|
|
51
|
+
s.toLowerCase().replace(/[^a-z0-9]/g, '')
|
|
52
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Normalize a string identifier to lowercase alphanumeric'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
|
|
53
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
54
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
55
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
56
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
57
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
58
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/search-core.ts:normalizeIdentifier:function"]
|
|
59
|
+
|
|
60
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/search-core.ts:SearchResult:interface" type="interface" identity="SearchResult" parent="~/.framework/mcp/tools/cil/search-core.ts"]
|
|
61
|
+
// CIL[DOC-MACRO purpose="Defines the typed shape of a CIL search result"]
|
|
62
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Standardize chunk metadata, scoring and content fields returned by search APIs"]
|
|
63
|
+
// CIL[DOC-CONTEXT module=".framework/mcp/tools/cil" layer="shared-core" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/search-core.ts"]
|
|
64
|
+
// CIL[DOC-CONTRACT inputs="N/A" outputs="N/A" errors="N/A" side_effects="N/A"]
|
|
65
|
+
// CIL[DOC-MICRO logic_summary="Declares fields including stable_id, macro, micro, code_content, match_type and similarity" notable_decisions="[]"]
|
|
66
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
67
|
+
// CIL[DOC-STABILITY stability="internal"]
|
|
68
|
+
/**
|
|
69
|
+
* The SearchResult interface defines the structure of a search result object, encapsulating various attributes related to search outcomes. It exists to standardize the representation of search results across the application.
|
|
70
|
+
*
|
|
71
|
+
* @sideEffects none
|
|
72
|
+
* @stability internal
|
|
73
|
+
* @cil-generated
|
|
74
|
+
*/
|
|
75
|
+
export interface SearchResult {
|
|
76
|
+
id: string
|
|
77
|
+
stable_id: string
|
|
78
|
+
version_id: string | null
|
|
79
|
+
chunk_name: string
|
|
80
|
+
file_path: string
|
|
81
|
+
chunk_type: string
|
|
82
|
+
source_set_id: string | null
|
|
83
|
+
layer: string | null
|
|
84
|
+
macro: string
|
|
85
|
+
micro: string
|
|
86
|
+
input_spec: string
|
|
87
|
+
output_spec: string
|
|
88
|
+
side_effects: string
|
|
89
|
+
stability: string
|
|
90
|
+
tags: string
|
|
91
|
+
complexity: string
|
|
92
|
+
doc_confidence: string
|
|
93
|
+
validation_errors: string[]
|
|
94
|
+
code_content: string
|
|
95
|
+
similarity: number | null
|
|
96
|
+
match_type: 'content' | 'semantic' | 'text'
|
|
97
|
+
}
|
|
98
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Defines the typed shape of a CIL search result'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
|
|
99
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
100
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
101
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
102
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
103
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
104
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/search-core.ts:SearchResult:interface"]
|
|
105
|
+
|
|
106
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/search-core.ts:buildSearchResult:function" type="function" identity="buildSearchResult" parent="~/.framework/mcp/tools/cil/search-core.ts"]
|
|
107
|
+
// CIL[DOC-MACRO purpose="Construct a SearchResult object from a raw chunk row"]
|
|
108
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Map database chunk fields into a typed search result with sensible defaults"]
|
|
109
|
+
// CIL[DOC-CONTEXT module=".framework/mcp/tools/cil" layer="shared-core" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/search-core.ts"]
|
|
110
|
+
// CIL[DOC-CONTRACT inputs="chunk: any, match_type: SearchResult['match_type'], similarity: number | null (optional)" outputs="SearchResult" errors="N/A" side_effects="none"]
|
|
111
|
+
// CIL[DOC-MICRO logic_summary="Extracts chunk.data, applies defaults for missing metadata, and assembles the SearchResult" notable_decisions="[]"]
|
|
112
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
113
|
+
// CIL[DOC-STABILITY stability="internal"]
|
|
114
|
+
/**
|
|
115
|
+
* Builds a structured search result object from a given chunk of data, encapsulating various attributes for search functionality. This function is essential for transforming raw data into a standardized format for search results.
|
|
116
|
+
*
|
|
117
|
+
* @macro Function that constructs a search result object from a data chunk.
|
|
118
|
+
* @micro Extracts properties from the chunk and assigns default values where necessary.
|
|
119
|
+
* @inputSpec
|
|
120
|
+
* - chunk: any (required) — the data chunk containing search-related information.
|
|
121
|
+
* - match_type: SearchResult['match_type'] (required) — the type of match for the search result.
|
|
122
|
+
* - similarity: number | null (optional[nullable]) — a similarity score associated with the search result.
|
|
123
|
+
* @outputSpec SearchResult — an object containing structured search result data.
|
|
124
|
+
* @sideEffects none
|
|
125
|
+
* @stability internal
|
|
126
|
+
* @cil-generated
|
|
127
|
+
*/
|
|
128
|
+
export function buildSearchResult(
|
|
129
|
+
chunk: any,
|
|
130
|
+
match_type: SearchResult['match_type'],
|
|
131
|
+
similarity: number | null = null,
|
|
132
|
+
): SearchResult {
|
|
133
|
+
const d = chunk.data || {}
|
|
134
|
+
return {
|
|
135
|
+
id: chunk.id,
|
|
136
|
+
stable_id: d.stable_id || '',
|
|
137
|
+
version_id: d.version_id || null,
|
|
138
|
+
chunk_name: d.chunk_name || '',
|
|
139
|
+
file_path: d.file_path || '',
|
|
140
|
+
chunk_type: d.chunk_type || '',
|
|
141
|
+
source_set_id: d.source_set_id || null,
|
|
142
|
+
layer: d.layer || null,
|
|
143
|
+
macro: d.macro || '',
|
|
144
|
+
micro: d.micro || '',
|
|
145
|
+
input_spec: d.input_spec || '',
|
|
146
|
+
output_spec: d.output_spec || '',
|
|
147
|
+
side_effects: d.side_effects || '',
|
|
148
|
+
stability: d.stability || 'unknown',
|
|
149
|
+
tags: d.tags || '',
|
|
150
|
+
complexity: d.complexity || '',
|
|
151
|
+
doc_confidence: d.doc_confidence || 'unverified_legacy',
|
|
152
|
+
validation_errors: d.doc_validation_errors || [],
|
|
153
|
+
code_content: d.code_content || '',
|
|
154
|
+
similarity,
|
|
155
|
+
match_type,
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Construct a SearchResult object from a raw chunk row'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
|
|
159
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
160
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
161
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
162
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
163
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
164
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/search-core.ts:buildSearchResult:function"]
|
|
165
|
+
|
|
166
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/search-core.ts:titleSearch:function" type="function" identity="titleSearch" parent="~/.framework/mcp/tools/cil/search-core.ts"]
|
|
167
|
+
// CIL[DOC-MACRO purpose="Case-insensitive title substring search over CIL chunks"]
|
|
168
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Return chunks whose title contains the query"]
|
|
169
|
+
// CIL[DOC-CONTEXT module=".framework/mcp/tools/cil" layer="shared-core" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/search-core.ts"]
|
|
170
|
+
// CIL[DOC-CONTRACT inputs="q: string, project_id?: string, limit?: number" outputs="Promise<SearchResult[]>" errors="Database errors propagate" side_effects="Queries the items table"]
|
|
171
|
+
// CIL[DOC-MICRO logic_summary="Builds a Supabase query for active cil_chunks, optionally filters by project_id and maps rows to SearchResult" notable_decisions="[]"]
|
|
172
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
173
|
+
// CIL[DOC-STABILITY stability="internal"]
|
|
174
|
+
export async function titleSearch({
|
|
175
|
+
q,
|
|
176
|
+
project_id,
|
|
177
|
+
limit = 10,
|
|
178
|
+
}: {
|
|
179
|
+
q: string
|
|
180
|
+
project_id?: string
|
|
181
|
+
limit?: number
|
|
182
|
+
}): Promise<SearchResult[]> {
|
|
183
|
+
let qb = adminDb
|
|
184
|
+
.from('items')
|
|
185
|
+
.select('id, title, data')
|
|
186
|
+
.filter('data->>kb_type', 'eq', 'cil_chunk')
|
|
187
|
+
.eq('is_active', true)
|
|
188
|
+
.ilike('title', `%${q}%`)
|
|
189
|
+
.limit(limit)
|
|
190
|
+
if (project_id) qb = (qb as any).filter('data->>project_id', 'eq', project_id)
|
|
191
|
+
|
|
192
|
+
const { data } = await qb
|
|
193
|
+
return (data || []).map((c: any) => buildSearchResult(c, 'text', null))
|
|
194
|
+
}
|
|
195
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Case-insensitive title substring search over CIL chunks'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
|
|
196
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
197
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
198
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
199
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
200
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
201
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/search-core.ts:titleSearch:function"]
|
|
202
|
+
|
|
203
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/search-core.ts:contentSearch:function" type="function" identity="contentSearch" parent="~/.framework/mcp/tools/cil/search-core.ts"]
|
|
204
|
+
// CIL[DOC-MACRO purpose="Score CIL chunks by keyword presence across metadata and code"]
|
|
205
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Find the most relevant chunks for a free-text query using term scoring"]
|
|
206
|
+
// CIL[DOC-CONTEXT module=".framework/mcp/tools/cil" layer="shared-core" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/search-core.ts"]
|
|
207
|
+
// CIL[DOC-CONTRACT inputs="q: string, project_id?: string, limit?: number" outputs="Promise<SearchResult[]>" errors="N/A" side_effects="Queries the items table; may call titleSearch as fallback"]
|
|
208
|
+
// CIL[DOC-MICRO logic_summary="Fetches active chunks, scores matches in title, macro, micro, tags and code, boosts exact phrases, returns top results or titleSearch fallback" notable_decisions="[]"]
|
|
209
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
210
|
+
// CIL[DOC-STABILITY stability="internal"]
|
|
211
|
+
export async function contentSearch({
|
|
212
|
+
q,
|
|
213
|
+
project_id,
|
|
214
|
+
limit = 10,
|
|
215
|
+
}: {
|
|
216
|
+
q: string
|
|
217
|
+
project_id?: string
|
|
218
|
+
limit?: number
|
|
219
|
+
}): Promise<SearchResult[]> {
|
|
220
|
+
const pageLimit = 5000
|
|
221
|
+
let qb = adminDb
|
|
222
|
+
.from('items')
|
|
223
|
+
.select('id, title, data')
|
|
224
|
+
.filter('data->>kb_type', 'eq', 'cil_chunk')
|
|
225
|
+
.eq('is_active', true)
|
|
226
|
+
.order('updated_at', { ascending: false })
|
|
227
|
+
.limit(pageLimit)
|
|
228
|
+
if (project_id) qb = (qb as any).filter('data->>project_id', 'eq', project_id)
|
|
229
|
+
|
|
230
|
+
const { data: allChunks } = await qb
|
|
231
|
+
|
|
232
|
+
const terms = q.toLowerCase().split(/\s+/).filter(Boolean)
|
|
233
|
+
const normalizedTerms = terms
|
|
234
|
+
.map((t) => normalizeIdentifier(t))
|
|
235
|
+
.filter((t) => t.length >= 2)
|
|
236
|
+
|
|
237
|
+
if (normalizedTerms.length === 0) return titleSearch({ q, project_id, limit })
|
|
238
|
+
|
|
239
|
+
const scored = (allChunks || [])
|
|
240
|
+
.map((c: any) => {
|
|
241
|
+
const title = (c.title || '').toLowerCase()
|
|
242
|
+
const macro = (c.data?.macro || '').toLowerCase()
|
|
243
|
+
const micro = (c.data?.micro || '').toLowerCase()
|
|
244
|
+
const tags = (c.data?.tags || '').toLowerCase()
|
|
245
|
+
const codeContent = (c.data?.code_content || '').toLowerCase()
|
|
246
|
+
|
|
247
|
+
const normTitle = normalizeIdentifier(title)
|
|
248
|
+
const normMacro = normalizeIdentifier(macro)
|
|
249
|
+
const normMicro = normalizeIdentifier(micro)
|
|
250
|
+
const normTags = normalizeIdentifier(tags)
|
|
251
|
+
const normCode = normalizeIdentifier(codeContent)
|
|
252
|
+
|
|
253
|
+
let score = 0
|
|
254
|
+
for (const term of normalizedTerms) {
|
|
255
|
+
if (normTitle.includes(term)) score += 3
|
|
256
|
+
if (normMacro.includes(term)) score += 2
|
|
257
|
+
if (normMicro.includes(term)) score += 1
|
|
258
|
+
if (normTags.includes(term)) score += 1
|
|
259
|
+
if (normCode.includes(term)) {
|
|
260
|
+
const count = normCode.split(term).length - 1
|
|
261
|
+
score += Math.min(count, 3)
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const phrase = q.toLowerCase()
|
|
266
|
+
const normPhrase = normalizeIdentifier(phrase)
|
|
267
|
+
if (codeContent.includes(phrase) || normCode.includes(normPhrase)) score += 5
|
|
268
|
+
|
|
269
|
+
return { chunk: c, score }
|
|
270
|
+
})
|
|
271
|
+
.filter(({ score }) => score > 0)
|
|
272
|
+
.sort((a, b) => b.score - a.score)
|
|
273
|
+
.slice(0, limit)
|
|
274
|
+
|
|
275
|
+
if (scored.length === 0) return titleSearch({ q, project_id, limit })
|
|
276
|
+
|
|
277
|
+
const maxScore = scored[0].score || 1
|
|
278
|
+
return scored.map(({ chunk, score }) =>
|
|
279
|
+
buildSearchResult(chunk, 'content', score / maxScore),
|
|
280
|
+
)
|
|
281
|
+
}
|
|
282
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Score CIL chunks by keyword presence across metadata and code'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
|
|
283
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
284
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
285
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
286
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
287
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
288
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/search-core.ts:contentSearch:function"]
|
|
289
|
+
|
|
290
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/search-core.ts:embedQuery:function" type="function" identity="embedQuery" parent="~/.framework/mcp/tools/cil/search-core.ts"]
|
|
291
|
+
// CIL[DOC-MACRO purpose="Fetch an OpenAI embedding vector for a query string"]
|
|
292
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Convert a search query into a JSON array vector string for semantic search"]
|
|
293
|
+
// CIL[DOC-CONTEXT module=".framework/mcp/tools/cil" layer="shared-core" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/search-core.ts"]
|
|
294
|
+
// CIL[DOC-CONTRACT inputs="q: string" outputs="Promise<string | null>" errors="Returns null on any API or parsing failure" side_effects="POST to the OpenAI embeddings endpoint"]
|
|
295
|
+
// CIL[DOC-MICRO logic_summary="Sends the query to the embeddings endpoint and serializes the returned vector as a JSON array string" notable_decisions="[]"]
|
|
296
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
297
|
+
// CIL[DOC-STABILITY stability="internal"]
|
|
298
|
+
/**
|
|
299
|
+
* The embedQuery function sends a query string to an external API to retrieve its embedding vector. It exists to facilitate the integration of OpenAI's embedding capabilities into the application.
|
|
300
|
+
*
|
|
301
|
+
* @macro Async function that retrieves text embeddings from an external API.
|
|
302
|
+
* @micro Constructs a POST request to the embeddings endpoint with the query string as input.
|
|
303
|
+
* @inputSpec
|
|
304
|
+
* - q: string (required) — the query string to be embedded.
|
|
305
|
+
* @outputSpec Promise<string | null> — returns the embedding vector as a string in JSON array format or null if an error occurs.
|
|
306
|
+
* @sideEffects makes an external API call to OpenAI's embeddings endpoint
|
|
307
|
+
* @stability internal
|
|
308
|
+
* @calls fetch
|
|
309
|
+
* @errorHandling returns null on any error during the API call or response processing
|
|
310
|
+
* @cil-generated
|
|
311
|
+
*/
|
|
312
|
+
async function embedQuery(q: string): Promise<string | null> {
|
|
313
|
+
const apiKey = process.env.OPENAI_API_KEY || process.env.LLM_API_KEY
|
|
314
|
+
const baseUrl = process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1'
|
|
315
|
+
if (!apiKey) return null
|
|
316
|
+
try {
|
|
317
|
+
const res = await fetch(`${baseUrl}/embeddings`, {
|
|
318
|
+
method: 'POST',
|
|
319
|
+
headers: {
|
|
320
|
+
'Content-Type': 'application/json',
|
|
321
|
+
Authorization: `Bearer ${apiKey}`,
|
|
322
|
+
},
|
|
323
|
+
body: JSON.stringify({ model: 'text-embedding-3-small', input: [q] }),
|
|
324
|
+
})
|
|
325
|
+
if (!res.ok) return null
|
|
326
|
+
const j: any = await res.json()
|
|
327
|
+
const vec = j.data?.[0]?.embedding
|
|
328
|
+
if (!Array.isArray(vec)) return null
|
|
329
|
+
return `[${vec.join(',')}]`
|
|
330
|
+
} catch {
|
|
331
|
+
return null
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Fetch an OpenAI embedding vector for a query string'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
|
|
335
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
336
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
337
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
338
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
339
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
340
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/search-core.ts:embedQuery:function"]
|
|
341
|
+
|
|
342
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/search-core.ts:semanticSearch:function" type="function" identity="semanticSearch" parent="~/.framework/mcp/tools/cil/search-core.ts"]
|
|
343
|
+
// CIL[DOC-MACRO purpose="Semantic search over CIL chunks using vector similarity"]
|
|
344
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Return chunks semantically similar to the query using the match_embeddings RPC"]
|
|
345
|
+
// CIL[DOC-CONTEXT module=".framework/mcp/tools/cil" layer="shared-core" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/search-core.ts"]
|
|
346
|
+
// CIL[DOC-CONTRACT inputs="q: string, project_id?: string, limit?: number" outputs="Promise<SearchResult[]>" errors="Returns empty array on RPC failure or missing data" side_effects="Calls embedQuery and adminDb RPC"]
|
|
347
|
+
// CIL[DOC-MICRO logic_summary="Embeds the query, calls match_embeddings, fetches chunk records by id and maps results" notable_decisions="[]"]
|
|
348
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
349
|
+
// CIL[DOC-STABILITY stability="internal"]
|
|
350
|
+
export async function semanticSearch({
|
|
351
|
+
q,
|
|
352
|
+
project_id,
|
|
353
|
+
limit = 10,
|
|
354
|
+
}: {
|
|
355
|
+
q: string
|
|
356
|
+
project_id?: string
|
|
357
|
+
limit?: number
|
|
358
|
+
}): Promise<SearchResult[]> {
|
|
359
|
+
const vector = await embedQuery(q)
|
|
360
|
+
if (!vector) return []
|
|
361
|
+
|
|
362
|
+
const matchCount = limit * 3
|
|
363
|
+
let rpcResult: { data: any; error: any } | null = null
|
|
364
|
+
try {
|
|
365
|
+
rpcResult = await adminDb.rpc('match_embeddings', {
|
|
366
|
+
query_embedding: vector,
|
|
367
|
+
match_count: matchCount,
|
|
368
|
+
filter_account_ids: null,
|
|
369
|
+
filter_vector_type: null,
|
|
370
|
+
similarity_threshold: 0.15,
|
|
371
|
+
filter_item_types: ['cil_chunk'],
|
|
372
|
+
})
|
|
373
|
+
} catch (err: any) {
|
|
374
|
+
console.error('match_embeddings rpc failed:', err?.message || String(err))
|
|
375
|
+
return []
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const { data, error } = rpcResult || { data: null, error: 'rpc call failed' }
|
|
379
|
+
if (error || !data || !data.length) return []
|
|
380
|
+
|
|
381
|
+
const docIds = data.map((d: any) => d.document_id)
|
|
382
|
+
let chunkQb = adminDb
|
|
383
|
+
.from('items')
|
|
384
|
+
.select('id, title, data')
|
|
385
|
+
.filter('data->>kb_type', 'eq', 'cil_chunk')
|
|
386
|
+
.eq('is_active', true)
|
|
387
|
+
.in('data->>stable_id', docIds)
|
|
388
|
+
if (project_id)
|
|
389
|
+
chunkQb = (chunkQb as any).filter('data->>project_id', 'eq', project_id)
|
|
390
|
+
|
|
391
|
+
const { data: chunks } = await chunkQb
|
|
392
|
+
const chunkMap = new Map((chunks || []).map((c: any) => [c.data?.stable_id, c]))
|
|
393
|
+
|
|
394
|
+
return (data as any[])
|
|
395
|
+
.map((d: any) => {
|
|
396
|
+
const c = chunkMap.get(d.document_id)
|
|
397
|
+
if (!c) return null
|
|
398
|
+
return buildSearchResult(c, 'semantic', d.similarity)
|
|
399
|
+
})
|
|
400
|
+
.filter(Boolean)
|
|
401
|
+
.slice(0, limit) as SearchResult[]
|
|
402
|
+
}
|
|
403
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Semantic search over CIL chunks using vector similarity'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
|
|
404
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
405
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
406
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
407
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
408
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
409
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/search-core.ts:semanticSearch:function"]
|
|
410
|
+
|
|
411
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/search-core.ts:hybridSearch:function" type="function" identity="hybridSearch" parent="~/.framework/mcp/tools/cil/search-core.ts"]
|
|
412
|
+
// CIL[DOC-MACRO purpose="Combine content and semantic search results into a single ranked list"]
|
|
413
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Merge and rank content-based and vector-based search results"]
|
|
414
|
+
// CIL[DOC-CONTEXT module=".framework/mcp/tools/cil" layer="shared-core" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/search-core.ts"]
|
|
415
|
+
// CIL[DOC-CONTRACT inputs="q: string, project_id?: string, limit?: number" outputs="Promise<SearchResult[]>" errors="N/A" side_effects="Calls contentSearch and semanticSearch"]
|
|
416
|
+
// CIL[DOC-MICRO logic_summary="Runs both search strategies in parallel, merges results by id, sorts by similarity and slices to limit" notable_decisions="[]"]
|
|
417
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
418
|
+
// CIL[DOC-STABILITY stability="internal"]
|
|
419
|
+
export async function hybridSearch({
|
|
420
|
+
q,
|
|
421
|
+
project_id,
|
|
422
|
+
limit = 10,
|
|
423
|
+
}: {
|
|
424
|
+
q: string
|
|
425
|
+
project_id?: string
|
|
426
|
+
limit?: number
|
|
427
|
+
}): Promise<SearchResult[]> {
|
|
428
|
+
const [content, semantic] = await Promise.all([
|
|
429
|
+
contentSearch({ q, project_id, limit }),
|
|
430
|
+
semanticSearch({ q, project_id, limit }),
|
|
431
|
+
])
|
|
432
|
+
|
|
433
|
+
const byId = new Map<string, SearchResult>()
|
|
434
|
+
for (const r of content) {
|
|
435
|
+
byId.set(r.id, r)
|
|
436
|
+
}
|
|
437
|
+
for (const r of semantic) {
|
|
438
|
+
const existing = byId.get(r.id)
|
|
439
|
+
if (!existing || (r.similarity ?? 0) > (existing.similarity ?? 0)) {
|
|
440
|
+
byId.set(r.id, r)
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return Array.from(byId.values())
|
|
445
|
+
.sort((a, b) => (b.similarity ?? 0) - (a.similarity ?? 0))
|
|
446
|
+
.slice(0, limit)
|
|
447
|
+
}
|
|
448
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Combine content and semantic search results into a single ranked list'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
|
|
449
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
450
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
451
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
452
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
453
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
454
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/search-core.ts:hybridSearch:function"]
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module search
|
|
3
|
+
* @audience both
|
|
4
|
+
* @layer shared-core
|
|
5
|
+
* @stability stable
|
|
6
|
+
*
|
|
7
|
+
* This module provides search functionality for the MCP framework, enabling content, semantic, and title-based searches. It acts as a bridge between the search core and the server, facilitating efficient query handling. INVARIANT: The search functions must always return results in a consistent format.
|
|
8
|
+
*
|
|
9
|
+
* @seeAlso search-core.js (contains the core search logic)
|
|
10
|
+
* @seeAlso @mcp/sdk (provides the server interface)
|
|
11
|
+
*
|
|
12
|
+
* @cil-generated
|
|
13
|
+
*/
|
|
14
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/search.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/mcp/tools/cil/search.ts"]
|
|
15
|
+
// CIL[DOC-MACRO purpose="Provides search functionality for the MCP framework"]
|
|
16
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Bridge the CIL search core and the MCP server by exporting the register function"]
|
|
17
|
+
// CIL[DOC-CONTEXT module="mcp-tools-cil" layer="shared-core" related_files=".framework/mcp/tools/cil/search-core.ts"]
|
|
18
|
+
// CIL[DOC-CONTRACT inputs="N/A" outputs="N/A" errors="N/A" side_effects="N/A"]
|
|
19
|
+
// CIL[DOC-MICRO logic_summary="Imports McpServer, zod and the search core, then exposes a register function for the MCP tool" notable_decisions="[]"]
|
|
20
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
21
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
22
|
+
// CIL[DOC-AUDIENCE audience="both"]
|
|
23
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
24
|
+
import { z } from 'zod'
|
|
25
|
+
import { contentSearch, semanticSearch, titleSearch } from './search-core.js'
|
|
26
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Provides search functionality for the MCP framework'; No verified external callers; imports: .framework/mcp/tools/cil/search-core.ts"]
|
|
27
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
28
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
29
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
30
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
31
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
32
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/search.ts:module_header:module_header"]
|
|
33
|
+
|
|
34
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/search.ts:register:function" type="function" identity="register" parent="~/.framework/mcp/tools/cil/search.ts"]
|
|
35
|
+
// CIL[DOC-MACRO purpose="Register the spine_cil_search_chunks MCP tool and dispatch queries"]
|
|
36
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Implement the tool handler that selects search mode and formats JSON results"]
|
|
37
|
+
// CIL[DOC-CONTEXT module="mcp-tools-cil" layer="shared-core" related_files=".framework/mcp/tools/cil/search-core.ts,.framework/mcp/tools/cil/search.ts"]
|
|
38
|
+
// CIL[DOC-CONTRACT inputs="server: McpServer" outputs="void" errors="Database and network failures propagate to caller" side_effects="registers tool on server and calls search functions"]
|
|
39
|
+
// CIL[DOC-MICRO logic_summary="Use server.registerTool with a zod schema, then dispatch semantic, text or hybrid search and return JSON text" notable_decisions="Hybrid merges content and semantic by similarity; falls back to title search if empty"]
|
|
40
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
41
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
42
|
+
export function register(server: McpServer) {
|
|
43
|
+
|
|
44
|
+
server.registerTool(
|
|
45
|
+
'spine_cil_search_chunks',
|
|
46
|
+
{
|
|
47
|
+
description: 'Search for code chunks by purpose, behaviour, or name. Uses hybrid semantic + text search over all embedded chunks. Returns chunk_name, file_path, macro (purpose), chunk_type, doc_confidence, and similarity score.',
|
|
48
|
+
inputSchema: z.object({
|
|
49
|
+
q: z.string().describe('Search query — describe what the chunk does, e.g. "authenticate user and check roles"'),
|
|
50
|
+
project_id: z.string().optional().describe('Limit to a specific project UUID'),
|
|
51
|
+
mode: z.enum(['hybrid', 'semantic', 'text']).default('hybrid').optional().describe('hybrid = semantic + content; semantic = embedding only; text = name/path substring'),
|
|
52
|
+
limit: z.number().int().min(1).max(50).default(10).optional().describe('Max results to return'),
|
|
53
|
+
}),
|
|
54
|
+
},
|
|
55
|
+
async ({ q, project_id, mode, limit }) => {
|
|
56
|
+
let results: any[] = []
|
|
57
|
+
|
|
58
|
+
if (mode === 'semantic') {
|
|
59
|
+
results = await semanticSearch({ q, project_id, limit })
|
|
60
|
+
if (results.length === 0) results = await contentSearch({ q, project_id, limit })
|
|
61
|
+
} else if (mode === 'text') {
|
|
62
|
+
results = await titleSearch({ q, project_id, limit })
|
|
63
|
+
} else {
|
|
64
|
+
const [content, semantic] = await Promise.all([
|
|
65
|
+
contentSearch({ q, project_id, limit }),
|
|
66
|
+
semanticSearch({ q, project_id, limit }),
|
|
67
|
+
])
|
|
68
|
+
const byId = new Map<string, any>()
|
|
69
|
+
for (const r of content) byId.set(r.id, r)
|
|
70
|
+
for (const r of semantic) {
|
|
71
|
+
const existing = byId.get(r.id)
|
|
72
|
+
if (!existing || (r.similarity ?? 0) > (existing.similarity ?? 0)) {
|
|
73
|
+
byId.set(r.id, r)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
results = Array.from(byId.values())
|
|
77
|
+
.sort((a, b) => (b.similarity ?? 0) - (a.similarity ?? 0))
|
|
78
|
+
.slice(0, limit ?? 10)
|
|
79
|
+
if (results.length === 0) results = await titleSearch({ q, project_id, limit })
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
content: [{
|
|
84
|
+
type: 'text',
|
|
85
|
+
text: JSON.stringify({ query: q, mode: mode ?? 'hybrid', count: results.length, results }, null, 2),
|
|
86
|
+
}],
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Register the spine_cil_search_chunks MCP tool and dispatch queries'; No verified external callers; imports: .framework/mcp/tools/cil/search-core.ts"]
|
|
92
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
93
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
94
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
95
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
96
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
97
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/search.ts:register:function"]
|