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,767 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module pipeline
|
|
3
|
+
* @audience internal
|
|
4
|
+
* @layer app-specific
|
|
5
|
+
* @stability stable
|
|
6
|
+
*
|
|
7
|
+
* This module implements the pipeline for processing MCP (Model Context Protocol) requests, utilizing various utilities for data handling and validation. It serves as a core component in the server architecture, facilitating interactions with the database and file system. INVARIANT: All requests must be properly authenticated before reaching this module.
|
|
8
|
+
*
|
|
9
|
+
* @seeAlso adminDb (provides database access for administrative tasks).
|
|
10
|
+
* @seeAlso computeContentHash (used for content integrity verification).
|
|
11
|
+
* @seeAlso McpServer (the main server interface for handling MCP requests).
|
|
12
|
+
*
|
|
13
|
+
* @cil-generated
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
|
|
17
|
+
// CIL[DOC-MACRO purpose="This module implements the pipeline for processing MCP (Model Context Protocol) requests, utilizing various utilities..."]
|
|
18
|
+
// CIL[DOC-RESPONSIBILITY responsibility="This module implements the pipeline for processing MCP (Model Context Protocol) requests, utilizing various utilities..."]
|
|
19
|
+
// CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts"]
|
|
20
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
|
|
21
|
+
// CIL[DOC-MICRO logic_summary="This module implements the pipeline for processing MCP (Model Context Protocol) requests, utilizing various utilities..." notable_decisions="[]"]
|
|
22
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
23
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
24
|
+
// CIL[DOC-AUDIENCE audience="internal"]
|
|
25
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
26
|
+
import { z } from 'zod'
|
|
27
|
+
import { adminDb, resolveTypeRecord } from '../../shared/db.js'
|
|
28
|
+
import * as fs from 'fs'
|
|
29
|
+
import * as path from 'path'
|
|
30
|
+
import * as crypto from 'node:crypto'
|
|
31
|
+
import { toCanonicalPath, computeContentHash } from '../../../functions/_shared/cil.js'
|
|
32
|
+
// CIL[DOC-VECTOR type="context" content="purpose='This module implements the pipeline for processing MCP (Model Context Protocol) requests, utilizing various utilities...'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
|
|
33
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
34
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
35
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
36
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
37
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
38
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:module_header:module_header"]
|
|
39
|
+
|
|
40
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:computeFileHash:function" type="function" identity="computeFileHash" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
|
|
41
|
+
// CIL[DOC-MACRO purpose="Computes the SHA-256 hash of a given string content."]
|
|
42
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Computes the SHA-256 hash of a given string content."]
|
|
43
|
+
// CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
|
|
44
|
+
// CIL[DOC-CONTRACT inputs="content: string (required) — the content to hash." outputs="string — the resulting SHA-256 hash in hexadecimal format." errors="none" side_effects="none"]
|
|
45
|
+
// CIL[DOC-MICRO logic_summary="Computes the SHA-256 hash of a given string content." notable_decisions="[]"]
|
|
46
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
47
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
48
|
+
/**
|
|
49
|
+
* Computes the SHA-256 hash of a given string content. This function is used for generating a unique identifier for file contents based on their content.
|
|
50
|
+
*
|
|
51
|
+
* @inputSpec
|
|
52
|
+
* content: string (required) — the content to hash.
|
|
53
|
+
* @outputSpec string — the resulting SHA-256 hash in hexadecimal format.
|
|
54
|
+
* @sideEffects none
|
|
55
|
+
* @stability stable
|
|
56
|
+
* @calls crypto.createHash
|
|
57
|
+
* @cil-generated
|
|
58
|
+
*/
|
|
59
|
+
function computeFileHash(content: string): string {
|
|
60
|
+
return crypto.createHash('sha256').update(content, 'utf8').digest('hex')
|
|
61
|
+
}
|
|
62
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Computes the SHA-256 hash of a given string content.'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
|
|
63
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
64
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
65
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
66
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
67
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
68
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:computeFileHash:function"]
|
|
69
|
+
|
|
70
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:estimateTokens:function" type="function" identity="estimateTokens" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
|
|
71
|
+
// CIL[DOC-MACRO purpose="Estimates the number of tokens required for a given text based on its length."]
|
|
72
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Estimates the number of tokens required for a given text based on its length."]
|
|
73
|
+
// CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
|
|
74
|
+
// CIL[DOC-CONTRACT inputs="text: string (required) — the input text for which to estimate tokens." outputs="number — the estimated number of tokens." errors="none" side_effects="none"]
|
|
75
|
+
// CIL[DOC-MICRO logic_summary="Estimates the number of tokens required for a given text based on its length." notable_decisions="[]"]
|
|
76
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
77
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
78
|
+
/**
|
|
79
|
+
* Estimates the number of tokens required for a given text based on its length. This function is useful for determining resource allocation in text processing tasks.
|
|
80
|
+
*
|
|
81
|
+
* @inputSpec
|
|
82
|
+
* text: string (required) — the input text for which to estimate tokens.
|
|
83
|
+
* @outputSpec number — the estimated number of tokens.
|
|
84
|
+
* @sideEffects none
|
|
85
|
+
* @stability stable
|
|
86
|
+
* @cil-generated
|
|
87
|
+
*/
|
|
88
|
+
function estimateTokens(text: string): number {
|
|
89
|
+
return Math.ceil(text.length / 4)
|
|
90
|
+
}
|
|
91
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Estimates the number of tokens required for a given text based on its length.'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.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/pipeline.ts:estimateTokens:function"]
|
|
98
|
+
|
|
99
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:parseAgentAttributes:function" type="function" identity="parseAgentAttributes" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
|
|
100
|
+
// CIL[DOC-MACRO purpose="Parser for agent attributes in key-value format."]
|
|
101
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Uses a regular expression to match and extract key-value pairs from the input string."]
|
|
102
|
+
// CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
|
|
103
|
+
// CIL[DOC-CONTRACT inputs="attrString: string (required) — a string containing agent attributes in key-value format." outputs="Record<string, string> — a record mapping attribute names to their corresponding values." errors="none" side_effects="none"]
|
|
104
|
+
// CIL[DOC-MICRO logic_summary="Uses a regular expression to match and extract key-value pairs from the input string." notable_decisions="[]"]
|
|
105
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
106
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
107
|
+
/**
|
|
108
|
+
* Parses a string of agent attributes formatted as key-value pairs and returns them as a record. This function is useful for extracting structured data from a raw attribute string.
|
|
109
|
+
*
|
|
110
|
+
* @macro Parser for agent attributes in key-value format.
|
|
111
|
+
* @micro Uses a regular expression to match and extract key-value pairs from the input string.
|
|
112
|
+
* @inputSpec
|
|
113
|
+
* - attrString: string (required) — a string containing agent attributes in key-value format.
|
|
114
|
+
* @outputSpec Record<string, string> — a record mapping attribute names to their corresponding values.
|
|
115
|
+
* @sideEffects none
|
|
116
|
+
* @stability stable
|
|
117
|
+
* @cil-generated
|
|
118
|
+
*/
|
|
119
|
+
function parseAgentAttributes(attrString: string): Record<string, string> {
|
|
120
|
+
const attrs: Record<string, string> = {}
|
|
121
|
+
const regex = /(\w+)="([^"]*)"/g
|
|
122
|
+
let match: RegExpExecArray | null
|
|
123
|
+
while ((match = regex.exec(attrString)) !== null) {
|
|
124
|
+
attrs[match[1]] = match[2]
|
|
125
|
+
}
|
|
126
|
+
return attrs
|
|
127
|
+
}
|
|
128
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:parseAgentAttributes:function"]
|
|
129
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Parser for agent attributes in key-value format.'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
|
|
130
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
131
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
132
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
133
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
134
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
135
|
+
|
|
136
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:AgentParsedMarker:interface" type="interface" identity="AgentParsedMarker" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
|
|
137
|
+
// CIL[DOC-MACRO purpose="Defines AgentParsedMarker"]
|
|
138
|
+
// CIL[DOC-RESPONSIBILITY responsibility="AgentParsedMarker implementation"]
|
|
139
|
+
// CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
|
|
140
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
|
|
141
|
+
// CIL[DOC-MICRO logic_summary="" notable_decisions="[]"]
|
|
142
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
143
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
144
|
+
interface AgentParsedMarker {
|
|
145
|
+
stable_id: string
|
|
146
|
+
start_line: number
|
|
147
|
+
end_line: number
|
|
148
|
+
type: string
|
|
149
|
+
identity: string
|
|
150
|
+
parent: string
|
|
151
|
+
attributes?: Record<string, string>
|
|
152
|
+
}
|
|
153
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Defines AgentParsedMarker'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
|
|
154
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
155
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
156
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
157
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
158
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
159
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:AgentParsedMarker:interface"]
|
|
160
|
+
|
|
161
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:parseAgentCilMarkers:function" type="function" identity="parseAgentCilMarkers" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
|
|
162
|
+
// CIL[DOC-MACRO purpose="Defines parseAgentCilMarkers"]
|
|
163
|
+
// CIL[DOC-RESPONSIBILITY responsibility="parseAgentCilMarkers implementation"]
|
|
164
|
+
// CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
|
|
165
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
|
|
166
|
+
// CIL[DOC-MICRO logic_summary="" notable_decisions="[]"]
|
|
167
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
168
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
169
|
+
function parseAgentCilMarkers(lines: string[]): AgentParsedMarker[] {
|
|
170
|
+
const markers: AgentParsedMarker[] = []
|
|
171
|
+
const stack: { line: number; attrs: Record<string, string> }[] = []
|
|
172
|
+
|
|
173
|
+
for (let i = 0; i < lines.length; i++) {
|
|
174
|
+
const trimmed = lines[i].trim()
|
|
175
|
+
const beginMatch = trimmed.match(/^(?:\/\/|--|#)\s*CIL\[BEGIN\s+(.+)\]$/) || trimmed.match(/^<!--\s*CIL\[BEGIN\s+(.+)\]\s*-->$/)
|
|
176
|
+
const endMatch = trimmed.match(/^(?:\/\/|--|#)\s*CIL\[END\s+stable_id="([^"]+)"\]$/) || trimmed.match(/^<!--\s*CIL\[END\s+stable_id="([^"]+)"\]\s*-->$/)
|
|
177
|
+
|
|
178
|
+
if (beginMatch) {
|
|
179
|
+
const attrs = parseAgentAttributes(beginMatch[1])
|
|
180
|
+
stack.push({ line: i + 1, attrs })
|
|
181
|
+
} else if (endMatch && stack.length > 0) {
|
|
182
|
+
const opened = stack.pop()!
|
|
183
|
+
markers.push({
|
|
184
|
+
stable_id: endMatch[1],
|
|
185
|
+
start_line: opened.line,
|
|
186
|
+
end_line: i + 1,
|
|
187
|
+
type: opened.attrs.type || 'unknown',
|
|
188
|
+
identity: opened.attrs.identity || '',
|
|
189
|
+
parent: opened.attrs.parent || 'none',
|
|
190
|
+
attributes: opened.attrs,
|
|
191
|
+
})
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return markers
|
|
196
|
+
}
|
|
197
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:parseAgentCilMarkers:function"]
|
|
198
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Defines parseAgentCilMarkers'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
|
|
199
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
200
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
201
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
202
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
203
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
204
|
+
|
|
205
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:AgentParsedDocs:interface" type="interface" identity="AgentParsedDocs" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
|
|
206
|
+
// CIL[DOC-MACRO purpose="The AgentParsedDocs interface defines the structure for parsed documentation related to agents, encapsulating various..."]
|
|
207
|
+
// CIL[DOC-RESPONSIBILITY responsibility="The AgentParsedDocs interface defines the structure for parsed documentation related to agents, encapsulating various..."]
|
|
208
|
+
// CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
|
|
209
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
|
|
210
|
+
// CIL[DOC-MICRO logic_summary="The AgentParsedDocs interface defines the structure for parsed documentation related to agents, encapsulating various..." notable_decisions="[]"]
|
|
211
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
212
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
213
|
+
/**
|
|
214
|
+
* The AgentParsedDocs interface defines the structure for parsed documentation related to agents, encapsulating various attributes that describe their functionality and context. It serves as a schema for organizing agent-related information in a consistent manner.
|
|
215
|
+
*
|
|
216
|
+
* @sideEffects none
|
|
217
|
+
* @stability stable
|
|
218
|
+
* @cil-generated
|
|
219
|
+
*/
|
|
220
|
+
interface AgentParsedDocs {
|
|
221
|
+
macro?: string
|
|
222
|
+
responsibility?: string
|
|
223
|
+
context?: Record<string, any>
|
|
224
|
+
contract?: Record<string, any>
|
|
225
|
+
micro?: Record<string, any>
|
|
226
|
+
confidence?: { pass: string; score: number; flags: string[] }
|
|
227
|
+
stability?: string
|
|
228
|
+
audience?: string
|
|
229
|
+
vectors?: Record<string, { content: string; status: string }>
|
|
230
|
+
notes?: Array<Record<string, any>>
|
|
231
|
+
learnings?: Array<Record<string, any>>
|
|
232
|
+
raw: Record<string, string>
|
|
233
|
+
}
|
|
234
|
+
// CIL[DOC-VECTOR type="context" content="purpose='The AgentParsedDocs interface defines the structure for parsed documentation related to agents, encapsulating various...'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
|
|
235
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
236
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
237
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
238
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
239
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
240
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:AgentParsedDocs:interface"]
|
|
241
|
+
|
|
242
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:parseAgentCilDocs:function" type="function" identity="parseAgentCilDocs" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
|
|
243
|
+
// CIL[DOC-MACRO purpose="Documentation parser for agent CIL comments."]
|
|
244
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Iterates through specified line ranges, applying regex to extract structured documentation attributes."]
|
|
245
|
+
// CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
|
|
246
|
+
// CIL[DOC-CONTRACT inputs="lines: string[] (required), startLine: number (required), endLine: number (required)" outputs="AgentParsedDocs — an object containing parsed documentation attributes." errors="none" side_effects="none"]
|
|
247
|
+
// CIL[DOC-MICRO logic_summary="Iterates through specified line ranges, applying regex to extract structured documentation attributes." notable_decisions="[]"]
|
|
248
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
249
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
250
|
+
/**
|
|
251
|
+
* Parses lines of documentation comments for agent CIL and organizes them into a structured format. This function extracts specific documentation keys and their associated content for further processing.
|
|
252
|
+
*
|
|
253
|
+
* @macro Documentation parser for agent CIL comments.
|
|
254
|
+
* @micro Iterates through specified line ranges, applying regex to extract structured documentation attributes.
|
|
255
|
+
* @inputSpec
|
|
256
|
+
* - lines: string[] (required) — array of lines containing documentation comments.
|
|
257
|
+
* - startLine: number (required) — the starting line number for parsing.
|
|
258
|
+
* - endLine: number (required) — the ending line number for parsing.
|
|
259
|
+
* @outputSpec AgentParsedDocs — an object containing parsed documentation attributes.
|
|
260
|
+
* @sideEffects none
|
|
261
|
+
* @stability stable
|
|
262
|
+
* @calls parseAgentAttributes
|
|
263
|
+
* @cil-generated
|
|
264
|
+
*/
|
|
265
|
+
function parseAgentCilDocs(lines: string[], startLine: number, endLine: number): AgentParsedDocs {
|
|
266
|
+
const docs: AgentParsedDocs = { raw: {} }
|
|
267
|
+
for (let i = startLine - 1; i < endLine - 1; i++) {
|
|
268
|
+
const trimmed = lines[i].trim()
|
|
269
|
+
const match = trimmed.match(/^(?:\/\/|--|#)\s*CIL\[DOC-(\w+)\s+(.+)\]$/) || trimmed.match(/^<!--\s*CIL\[DOC-(\w+)\s+(.+)\]\s*-->$/)
|
|
270
|
+
if (!match) continue
|
|
271
|
+
const key = match[1]
|
|
272
|
+
const content = match[2]
|
|
273
|
+
docs.raw[key] = content
|
|
274
|
+
|
|
275
|
+
const attrs = parseAgentAttributes(content)
|
|
276
|
+
|
|
277
|
+
switch (key) {
|
|
278
|
+
case 'MACRO':
|
|
279
|
+
docs.macro = attrs.purpose || content.replace(/^purpose="|"$/g, '')
|
|
280
|
+
break
|
|
281
|
+
case 'RESPONSIBILITY':
|
|
282
|
+
docs.responsibility = attrs.responsibility || content.replace(/^responsibility="|"$/g, '')
|
|
283
|
+
break
|
|
284
|
+
case 'CONTEXT':
|
|
285
|
+
docs.context = attrs
|
|
286
|
+
break
|
|
287
|
+
case 'CONTRACT':
|
|
288
|
+
docs.contract = attrs
|
|
289
|
+
break
|
|
290
|
+
case 'MICRO':
|
|
291
|
+
docs.micro = attrs
|
|
292
|
+
break
|
|
293
|
+
case 'CONFIDENCE':
|
|
294
|
+
docs.confidence = {
|
|
295
|
+
pass: attrs.pass || 'first',
|
|
296
|
+
score: parseFloat(attrs.score || '0'),
|
|
297
|
+
flags: attrs.flags ? attrs.flags.split(',').map((s: string) => s.trim()).filter(Boolean) : [],
|
|
298
|
+
}
|
|
299
|
+
break
|
|
300
|
+
case 'VECTOR':
|
|
301
|
+
if (attrs.type) {
|
|
302
|
+
if (!docs.vectors) docs.vectors = {}
|
|
303
|
+
docs.vectors[attrs.type] = {
|
|
304
|
+
content: attrs.content || '',
|
|
305
|
+
status: attrs.status || 'ready',
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
break
|
|
309
|
+
case 'STABILITY':
|
|
310
|
+
docs.stability = attrs.stability || content.replace(/^stability="|"$/g, '')
|
|
311
|
+
break
|
|
312
|
+
case 'AUDIENCE':
|
|
313
|
+
docs.audience = attrs.audience || content.replace(/^audience="|"$/g, '')
|
|
314
|
+
break
|
|
315
|
+
case 'NOTE':
|
|
316
|
+
if (!docs.notes) docs.notes = []
|
|
317
|
+
docs.notes.push(attrs)
|
|
318
|
+
break
|
|
319
|
+
case 'LEARNING':
|
|
320
|
+
if (!docs.learnings) docs.learnings = []
|
|
321
|
+
docs.learnings.push(attrs)
|
|
322
|
+
break
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return docs
|
|
326
|
+
}
|
|
327
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:parseAgentCilDocs:function"]
|
|
328
|
+
|
|
329
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:mapAgentDocsToChunkData:function" type="function" identity="mapAgentDocsToChunkData" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
|
|
330
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Documentation parser for agent CIL comments.'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
|
|
331
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
332
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
333
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
334
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
335
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
336
|
+
// CIL[DOC-MACRO purpose="Defines mapAgentDocsToChunkData"]
|
|
337
|
+
// CIL[DOC-RESPONSIBILITY responsibility="mapAgentDocsToChunkData implementation"]
|
|
338
|
+
// CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
|
|
339
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
|
|
340
|
+
// CIL[DOC-MICRO logic_summary="" notable_decisions="[]"]
|
|
341
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
342
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
343
|
+
function mapAgentDocsToChunkData(docs: AgentParsedDocs): Record<string, any> {
|
|
344
|
+
const pendingVectors = docs.vectors
|
|
345
|
+
? Object.entries(docs.vectors).filter(([, v]) => v.status === 'pending_human_input').map(([k]) => k)
|
|
346
|
+
: []
|
|
347
|
+
|
|
348
|
+
return {
|
|
349
|
+
macro: docs.macro || docs.raw.MACRO || '',
|
|
350
|
+
micro: docs.micro?.logic_summary || docs.responsibility || '',
|
|
351
|
+
description: docs.macro || '',
|
|
352
|
+
input_spec: docs.contract?.inputs?.replace(/\\n/g, '\n') || '',
|
|
353
|
+
output_spec: docs.contract?.outputs || '',
|
|
354
|
+
side_effects: docs.contract?.side_effects || '',
|
|
355
|
+
throws: docs.contract?.errors || '',
|
|
356
|
+
module: docs.context?.module || '',
|
|
357
|
+
layer: docs.context?.layer || '',
|
|
358
|
+
doc_confidence: docs.confidence?.pass === 'second' ? 'ai_generated' : 'from_source',
|
|
359
|
+
confidence_score: docs.confidence?.score || 0,
|
|
360
|
+
confidence_flags: docs.confidence?.flags || [],
|
|
361
|
+
related_files: docs.context?.related_files || '',
|
|
362
|
+
tags: docs.micro?.notable_decisions || '',
|
|
363
|
+
depends_on: docs.contract?.dependencies || '',
|
|
364
|
+
stability: docs.stability || '',
|
|
365
|
+
audience: docs.audience || '',
|
|
366
|
+
vector_content: docs.vectors || {},
|
|
367
|
+
vectors_pending_human_review: pendingVectors,
|
|
368
|
+
notes: docs.notes || [],
|
|
369
|
+
learnings: docs.learnings || [],
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Defines mapAgentDocsToChunkData'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
|
|
373
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
374
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
375
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
376
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
377
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
378
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:mapAgentDocsToChunkData:function"]
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Registers tools for testing authentication and updating pipeline statuses in the MCP server. This module facilitates the management of file statuses within a project pipeline.
|
|
382
|
+
*
|
|
383
|
+
* @macro Tool registration function for MCP server.
|
|
384
|
+
* @micro Utilizes asynchronous database operations to update project file statuses based on input parameters.
|
|
385
|
+
* @inputSpec
|
|
386
|
+
* - server: McpServer (required) — The MCP server instance to register tools with.
|
|
387
|
+
* @outputSpec Promise<void> — No specific return value.
|
|
388
|
+
* @sideEffects Database writes to update project file statuses.
|
|
389
|
+
* @stability stable
|
|
390
|
+
* @calls adminDb.from, adminDb.update
|
|
391
|
+
* @cil-generated
|
|
392
|
+
*/
|
|
393
|
+
// CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:register:function" type="function" identity="register" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
|
|
394
|
+
// CIL[DOC-MACRO purpose="Tool registration function for MCP server."]
|
|
395
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Utilizes asynchronous database operations to update project file statuses based on input parameters."]
|
|
396
|
+
// CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
|
|
397
|
+
// CIL[DOC-CONTRACT inputs="server: McpServer (required) — The MCP server instance to register tools with." outputs="Promise<void> — No specific return value." errors="none" side_effects="Database writes to update project file statuses."]
|
|
398
|
+
// CIL[DOC-MICRO logic_summary="Utilizes asynchronous database operations to update project file statuses based on input parameters." notable_decisions="[]"]
|
|
399
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
400
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
401
|
+
export function register(server: McpServer) {
|
|
402
|
+
|
|
403
|
+
server.registerTool(
|
|
404
|
+
'spine_cil_test_auth',
|
|
405
|
+
{
|
|
406
|
+
description: 'Test authentication and module loading',
|
|
407
|
+
inputSchema: z.object({}),
|
|
408
|
+
},
|
|
409
|
+
async () => {
|
|
410
|
+
return {
|
|
411
|
+
content: [{
|
|
412
|
+
type: 'text',
|
|
413
|
+
text: JSON.stringify({ success: true, message: 'Pipeline tools loaded successfully' }, null, 2),
|
|
414
|
+
}],
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
server.registerTool(
|
|
420
|
+
'spine_cil_update_pipeline_status',
|
|
421
|
+
{
|
|
422
|
+
description: 'Update a file\'s pipeline status. Call at the end of each agent-run step. Standard statuses follow the 0–8 pipeline, but custom temporary statuses are also allowed.',
|
|
423
|
+
inputSchema: z.object({
|
|
424
|
+
project_id: z.string().uuid().describe('The cil_project UUID'),
|
|
425
|
+
file_path: z.string().describe('Relative file path within the repository'),
|
|
426
|
+
status: z.string().describe('File status — standard statuses follow the 0–8 pipeline, but custom temporary statuses are allowed'),
|
|
427
|
+
metadata: z.object({}).passthrough().optional().describe('Additional metadata to store with the status update'),
|
|
428
|
+
}),
|
|
429
|
+
},
|
|
430
|
+
async ({ project_id, file_path, status, metadata = {} }) => {
|
|
431
|
+
const [projectRes] = await Promise.allSettled([
|
|
432
|
+
adminDb.from('items').select('id, title, data').eq('id', project_id).maybeSingle(),
|
|
433
|
+
])
|
|
434
|
+
|
|
435
|
+
const project = projectRes.status === 'fulfilled' ? projectRes.value.data : null
|
|
436
|
+
if (!project) {
|
|
437
|
+
return { content: [{ type: 'text', text: JSON.stringify({ error: 'Project not found' }, null, 2) }] }
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const pipelineData = project.data || {}
|
|
441
|
+
const fileStatuses = pipelineData.file_statuses || {}
|
|
442
|
+
|
|
443
|
+
fileStatuses[file_path] = status
|
|
444
|
+
fileStatuses[`${file_path}_updated`] = new Date().toISOString()
|
|
445
|
+
if (Object.keys(metadata).length > 0) {
|
|
446
|
+
Object.assign(fileStatuses, { [`${file_path}_meta`]: metadata })
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
const [updateRes] = await Promise.allSettled([
|
|
450
|
+
adminDb.from('items').update({
|
|
451
|
+
data: { ...pipelineData, file_statuses: fileStatuses },
|
|
452
|
+
}).eq('id', project_id).select()
|
|
453
|
+
])
|
|
454
|
+
|
|
455
|
+
if (updateRes.status === 'rejected' || !updateRes.value.data) {
|
|
456
|
+
return { content: [{ type: 'text', text: JSON.stringify({ error: 'Failed to update status' }, null, 2) }] }
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
return {
|
|
460
|
+
content: [{
|
|
461
|
+
type: 'text',
|
|
462
|
+
text: JSON.stringify({
|
|
463
|
+
success: true,
|
|
464
|
+
project_id,
|
|
465
|
+
file_path,
|
|
466
|
+
new_status: status,
|
|
467
|
+
updated_at: fileStatuses[`${file_path}_updated`],
|
|
468
|
+
}, null, 2),
|
|
469
|
+
}],
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
server.registerTool(
|
|
475
|
+
'spine_cil_store_markers',
|
|
476
|
+
{
|
|
477
|
+
description: `Parse CIL[BEGIN]/CIL[END] markers and DOC tags from a source file and upsert chunk records in the DB. The file must already be saved to disk before calling this.
|
|
478
|
+
|
|
479
|
+
Key constraints:
|
|
480
|
+
- file_path must be relative from repo root — never absolute
|
|
481
|
+
- file_hash must be the SHA256 of the current file content on disk (shasum -a 256 {path} | awk '{print $1}')
|
|
482
|
+
- start_line/end_line are the 1-based line numbers of the CIL[BEGIN]/CIL[END] lines themselves
|
|
483
|
+
- stable_id format: {canonical_path}:{identity_lowercase}:{type}
|
|
484
|
+
- parent: stable_id of direct parent, or "none" for top-level chunks
|
|
485
|
+
|
|
486
|
+
Returns: { ok, created, updated, results[] } — verify ok: true and counts match before continuing.`,
|
|
487
|
+
inputSchema: z.object({
|
|
488
|
+
project_id: z.string().uuid().describe('The cil_project UUID'),
|
|
489
|
+
file_path: z.string().describe('Relative path from repo root'),
|
|
490
|
+
file_hash: z.string().optional().describe('SHA256 of the current file content'),
|
|
491
|
+
markers: z.array(z.object({
|
|
492
|
+
stable_id: z.string().describe('Stable chunk ID'),
|
|
493
|
+
chunk_id: z.string().optional().describe('Legacy chunk ID (old format)'),
|
|
494
|
+
start_line: z.number().int().min(1),
|
|
495
|
+
end_line: z.number().int().min(1),
|
|
496
|
+
type: z.string(),
|
|
497
|
+
identity: z.string(),
|
|
498
|
+
parent: z.string(),
|
|
499
|
+
})).optional().describe('Chunk boundaries extracted from the annotated source — if omitted, all CIL[BEGIN/END] markers found in the file are used'),
|
|
500
|
+
}),
|
|
501
|
+
},
|
|
502
|
+
async ({ project_id, file_path, file_hash, markers }) => {
|
|
503
|
+
const { data: projectRows } = await adminDb.from('items').select('id, data, account_id')
|
|
504
|
+
.filter('data->>kb_type', 'eq', 'cil_project')
|
|
505
|
+
.eq('id', project_id)
|
|
506
|
+
.eq('is_active', true)
|
|
507
|
+
const projectItem = (projectRows || [])[0]
|
|
508
|
+
if (!projectItem) {
|
|
509
|
+
return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `Project not found: ${project_id}` }) }] }
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
const accountId: string = projectItem.account_id || ''
|
|
513
|
+
if (!accountId) {
|
|
514
|
+
return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: 'Project has no account_id — cannot stamp chunks' }) }] }
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
const repoPath: string = projectItem.data?.repo_path || ''
|
|
518
|
+
if (!repoPath) {
|
|
519
|
+
return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: 'Project has no repo_path configured' }) }] }
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
const absolutePath = path.join(repoPath, file_path.replace(/^\//, ''))
|
|
523
|
+
if (!fs.existsSync(absolutePath)) {
|
|
524
|
+
return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `Source file not found on disk: ${absolutePath}` }) }] }
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
const content = fs.readFileSync(absolutePath, 'utf-8')
|
|
528
|
+
const computedHash = computeFileHash(content)
|
|
529
|
+
if (file_hash && computedHash !== file_hash) {
|
|
530
|
+
return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `Hash mismatch: provided ${file_hash} != computed ${computedHash}` }) }] }
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
const lines = content.split('\n')
|
|
534
|
+
const parsed = parseAgentCilMarkers(lines)
|
|
535
|
+
const parsedById = new Map(parsed.map(m => [m.stable_id, m]))
|
|
536
|
+
|
|
537
|
+
const markersToStore = (markers && markers.length > 0) ? markers : parsed
|
|
538
|
+
const providedIds = new Set(markersToStore.map(m => m.stable_id))
|
|
539
|
+
const sourceIds = new Set(parsed.map(m => m.stable_id))
|
|
540
|
+
const missingInSource = markersToStore.filter(m => !sourceIds.has(m.stable_id))
|
|
541
|
+
const extraInSource = parsed.filter(m => !providedIds.has(m.stable_id))
|
|
542
|
+
if (missingInSource.length > 0 || extraInSource.length > 0) {
|
|
543
|
+
return {
|
|
544
|
+
content: [{
|
|
545
|
+
type: 'text',
|
|
546
|
+
text: JSON.stringify({
|
|
547
|
+
ok: false,
|
|
548
|
+
error: `Marker mismatch: missing_in_source=[${missingInSource.map(m => m.stable_id).join(',')}], extra_in_source=[${extraInSource.map(m => m.stable_id).join(',')}]`,
|
|
549
|
+
}),
|
|
550
|
+
}],
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
let chunkTypeId: string, chunkDesignSchema: Record<string, any>, chunkValidationSchema: Record<string, any>
|
|
555
|
+
let fileTypeId: string, fileDesignSchema: Record<string, any>, fileValidationSchema: Record<string, any>
|
|
556
|
+
try {
|
|
557
|
+
const [chunkTypeRecord, fileTypeRecord] = await Promise.all([
|
|
558
|
+
resolveTypeRecord('item', 'cil_chunk'),
|
|
559
|
+
resolveTypeRecord('item', 'cil_file')
|
|
560
|
+
])
|
|
561
|
+
chunkTypeId = chunkTypeRecord.id
|
|
562
|
+
chunkDesignSchema = chunkTypeRecord.design_schema
|
|
563
|
+
chunkValidationSchema = chunkTypeRecord.validation_schema
|
|
564
|
+
fileTypeId = fileTypeRecord.id
|
|
565
|
+
fileDesignSchema = fileTypeRecord.design_schema
|
|
566
|
+
fileValidationSchema = fileTypeRecord.validation_schema
|
|
567
|
+
} catch (e: any) {
|
|
568
|
+
return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `CIL type not found — run migrations first: ${e.message}` }) }] }
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
const now = new Date().toISOString()
|
|
572
|
+
const versionId = projectItem.data?.active_version_id || '0.1.0'
|
|
573
|
+
|
|
574
|
+
const { data: existingFile } = await adminDb.from('items').select('id, data')
|
|
575
|
+
.filter('data->>kb_type', 'eq', 'cil_file')
|
|
576
|
+
.filter('data->>project_id', 'eq', project_id)
|
|
577
|
+
.filter('data->>file_path', 'eq', file_path)
|
|
578
|
+
.eq('is_active', true)
|
|
579
|
+
.maybeSingle()
|
|
580
|
+
|
|
581
|
+
let fileId: string
|
|
582
|
+
if (existingFile) {
|
|
583
|
+
fileId = existingFile.id
|
|
584
|
+
try {
|
|
585
|
+
const updatedFileData = {
|
|
586
|
+
...existingFile.data,
|
|
587
|
+
file_hash: computedHash,
|
|
588
|
+
version_id: versionId,
|
|
589
|
+
updated_at: now,
|
|
590
|
+
}
|
|
591
|
+
await adminDb.from('items')
|
|
592
|
+
.update({ data: updatedFileData, updated_at: now })
|
|
593
|
+
.eq('id', fileId)
|
|
594
|
+
} catch {
|
|
595
|
+
// File metadata update is best-effort; continue with chunk sync
|
|
596
|
+
}
|
|
597
|
+
} else {
|
|
598
|
+
const fileStableId = toCanonicalPath(repoPath, absolutePath)
|
|
599
|
+
const fileData = {
|
|
600
|
+
kb_type: 'cil_file',
|
|
601
|
+
project_id,
|
|
602
|
+
file_path,
|
|
603
|
+
file_hash,
|
|
604
|
+
stable_id: fileStableId,
|
|
605
|
+
version_id: versionId,
|
|
606
|
+
status: '2-chunked', // Files reach this status after chunking
|
|
607
|
+
last_status_at: now,
|
|
608
|
+
}
|
|
609
|
+
const { data: newFile, error: fileError } = await adminDb.from('items')
|
|
610
|
+
.insert({
|
|
611
|
+
title: file_path,
|
|
612
|
+
type_id: fileTypeId,
|
|
613
|
+
account_id: accountId,
|
|
614
|
+
design_schema: fileDesignSchema,
|
|
615
|
+
validation_schema: fileValidationSchema,
|
|
616
|
+
is_active: true,
|
|
617
|
+
data: fileData,
|
|
618
|
+
})
|
|
619
|
+
.select('id')
|
|
620
|
+
.maybeSingle()
|
|
621
|
+
if (fileError || !newFile) {
|
|
622
|
+
return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `Failed to create cil_file item: ${fileError?.message || 'unknown'}` }) }] }
|
|
623
|
+
}
|
|
624
|
+
fileId = newFile.id
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
const { data: existingChunks } = await adminDb.from('items').select('id, data')
|
|
628
|
+
.filter('data->>kb_type', 'eq', 'cil_chunk')
|
|
629
|
+
.filter('data->>project_id', 'eq', project_id)
|
|
630
|
+
.filter('data->>file_path', 'eq', file_path)
|
|
631
|
+
.eq('is_active', true)
|
|
632
|
+
.limit(1000)
|
|
633
|
+
const existingByChunkId = new Map((existingChunks || []).map((c: any) => [c.data?.stable_id || c.data?.legacy_chunk_id || c.data?.chunk_id || c.id, c]))
|
|
634
|
+
const existingIds = new Set((existingChunks || []).map((c: any) => c.id))
|
|
635
|
+
|
|
636
|
+
const results: any[] = []
|
|
637
|
+
const errors: string[] = []
|
|
638
|
+
const usedIds = new Set<string>()
|
|
639
|
+
|
|
640
|
+
for (const m of markersToStore) {
|
|
641
|
+
const _parsed = parsedById.get(m.stable_id)!
|
|
642
|
+
const codeContent = lines.slice(m.start_line, m.end_line - 1).join('\n')
|
|
643
|
+
const docs = parseAgentCilDocs(lines, m.start_line, m.end_line)
|
|
644
|
+
const docFields = mapAgentDocsToChunkData(docs)
|
|
645
|
+
const fullContentHash = computeContentHash(codeContent)
|
|
646
|
+
const tokenCount = estimateTokens(codeContent)
|
|
647
|
+
|
|
648
|
+
const mm = m as any
|
|
649
|
+
const parentStableId = mm.parent === 'none' ? null : mm.parent
|
|
650
|
+
const baseData = {
|
|
651
|
+
kb_type: 'cil_chunk',
|
|
652
|
+
stable_id: mm.stable_id,
|
|
653
|
+
chunk_name: m.identity,
|
|
654
|
+
project_id,
|
|
655
|
+
file_path,
|
|
656
|
+
file_id: fileId, // Link to parent file item for existing embedding/mapping functions
|
|
657
|
+
chunk_type: m.type,
|
|
658
|
+
parent_id: parentStableId,
|
|
659
|
+
parent_stable_id: parentStableId,
|
|
660
|
+
version_id: versionId,
|
|
661
|
+
line_start: m.start_line,
|
|
662
|
+
line_end: m.end_line,
|
|
663
|
+
stored_hash: fullContentHash,
|
|
664
|
+
content_hash: fullContentHash,
|
|
665
|
+
code_content: codeContent,
|
|
666
|
+
token_count: tokenCount,
|
|
667
|
+
is_dead_code: false,
|
|
668
|
+
review_status: 'approved',
|
|
669
|
+
boundary_confidence: 'high',
|
|
670
|
+
boundary_source: 'agent_markers',
|
|
671
|
+
...docFields,
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
const existing: any = existingByChunkId.get(m.stable_id)
|
|
675
|
+
if (existing) {
|
|
676
|
+
try {
|
|
677
|
+
const newData = { ...existing.data, ...baseData, updated_at: now }
|
|
678
|
+
const { error } = await adminDb.from('items')
|
|
679
|
+
.update({ data: newData, title: `${file_path}::${m.identity}`, updated_at: now })
|
|
680
|
+
.eq('id', existing.id)
|
|
681
|
+
if (error) errors.push(`${m.stable_id}: ${error.message}`)
|
|
682
|
+
else {
|
|
683
|
+
usedIds.add(existing.id)
|
|
684
|
+
results.push({ stable_id: m.stable_id, action: 'updated', id: existing.id })
|
|
685
|
+
}
|
|
686
|
+
} catch (err: any) {
|
|
687
|
+
errors.push(`${m.stable_id}: ${err?.message || String(err)}`)
|
|
688
|
+
}
|
|
689
|
+
} else {
|
|
690
|
+
try {
|
|
691
|
+
const { data: newChunk, error } = await adminDb.from('items')
|
|
692
|
+
.insert({
|
|
693
|
+
title: `${file_path}::${m.identity}`,
|
|
694
|
+
type_id: chunkTypeId,
|
|
695
|
+
account_id: accountId,
|
|
696
|
+
design_schema: chunkDesignSchema,
|
|
697
|
+
validation_schema: chunkValidationSchema,
|
|
698
|
+
is_active: true,
|
|
699
|
+
data: baseData,
|
|
700
|
+
})
|
|
701
|
+
.select('id')
|
|
702
|
+
.maybeSingle()
|
|
703
|
+
if (error) errors.push(`${m.stable_id}: ${error.message}`)
|
|
704
|
+
else {
|
|
705
|
+
if (newChunk?.id) usedIds.add(newChunk.id)
|
|
706
|
+
results.push({ stable_id: m.stable_id, action: 'created', id: newChunk?.id })
|
|
707
|
+
}
|
|
708
|
+
} catch (err: any) {
|
|
709
|
+
errors.push(`${m.stable_id}: ${err?.message || String(err)}`)
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
const idsToDeactivate = [...existingIds].filter((id: any) => !usedIds.has(id))
|
|
715
|
+
for (const orphanId of idsToDeactivate) {
|
|
716
|
+
try {
|
|
717
|
+
const { error: deactError } = await adminDb.from('items')
|
|
718
|
+
.update({ is_active: false, updated_at: now })
|
|
719
|
+
.eq('id', orphanId)
|
|
720
|
+
if (deactError) errors.push(`deactivate orphan ${orphanId}: ${deactError.message}`)
|
|
721
|
+
} catch (err: any) {
|
|
722
|
+
errors.push(`deactivate orphan ${orphanId}: ${err?.message || String(err)}`)
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
const { count: liveChunkCount } = await adminDb.from('items')
|
|
727
|
+
.select('*', { count: 'exact', head: true })
|
|
728
|
+
.filter('data->>kb_type', 'eq', 'cil_chunk')
|
|
729
|
+
.filter('data->>project_id', 'eq', project_id)
|
|
730
|
+
.eq('is_active', true)
|
|
731
|
+
if (liveChunkCount !== null) {
|
|
732
|
+
try {
|
|
733
|
+
await adminDb.from('items')
|
|
734
|
+
.update({ data: { ...projectItem.data, chunk_count: liveChunkCount } })
|
|
735
|
+
.eq('id', project_id)
|
|
736
|
+
} catch (err: any) {
|
|
737
|
+
errors.push(`project count update: ${err?.message || String(err)}`)
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
return {
|
|
742
|
+
content: [{
|
|
743
|
+
type: 'text',
|
|
744
|
+
text: JSON.stringify({
|
|
745
|
+
ok: errors.length === 0,
|
|
746
|
+
project_id,
|
|
747
|
+
file_path,
|
|
748
|
+
file_id: fileId,
|
|
749
|
+
file_hash: computedHash,
|
|
750
|
+
chunk_count: markersToStore.length,
|
|
751
|
+
created: results.filter(r => r.action === 'created').length,
|
|
752
|
+
updated: results.filter(r => r.action === 'updated').length,
|
|
753
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
754
|
+
results,
|
|
755
|
+
}, null, 2),
|
|
756
|
+
}],
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
)
|
|
760
|
+
}
|
|
761
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Tool registration function for MCP server.'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
|
|
762
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
763
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
764
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
765
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
766
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
767
|
+
// CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:register:function"]
|