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
|
@@ -1,24 +1,27 @@
|
|
|
1
|
-
// CIL[BEGIN
|
|
2
|
-
// CIL[DOC-MACRO purpose="
|
|
3
|
-
// CIL[DOC-RESPONSIBILITY responsibility="
|
|
4
|
-
// CIL[DOC-CONTEXT module="
|
|
5
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="
|
|
6
|
-
// CIL[DOC-MICRO logic_summary="
|
|
7
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.
|
|
1
|
+
// CIL[BEGIN stable_id="~/.framework/functions/cil-project.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/functions/cil-project.ts"]
|
|
2
|
+
// CIL[DOC-MACRO purpose="Import dependencies and set module context for the cil-project Netlify function"]
|
|
3
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Load shared middleware, database, id resolution, admin-data helpers, CIL hashing and semver for the project handler"]
|
|
4
|
+
// CIL[DOC-CONTEXT module=".framework/functions/cil-project" layer="function" related_files=".framework/functions/_shared/cil.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-ids.ts,.framework/functions/admin-data.ts"]
|
|
5
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
|
|
6
|
+
// CIL[DOC-MICRO logic_summary="Imports createHandler, adminDb, resolveTypeId, admin-data CRUD, computeContentHash and semver to support the exported handler" notable_decisions="[]"]
|
|
7
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
8
8
|
// CIL[DOC-STABILITY stability="stable"]
|
|
9
|
-
// CIL[DOC-AUDIENCE audience="
|
|
10
|
-
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: .framework/migrations/015_simplify_apps_table.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, custom/apps/portal/pages/ContentPage.tsx, .framework/src/components/ui/table-primitives.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
|
|
11
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
12
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
13
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
14
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
15
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
9
|
+
// CIL[DOC-AUDIENCE audience="maintainer"]
|
|
16
10
|
|
|
17
11
|
|
|
18
12
|
import { createHandler } from './_shared/middleware'
|
|
19
13
|
import { adminDb } from './_shared/db'
|
|
20
14
|
import { resolveTypeId } from './_shared/resolve-ids'
|
|
21
15
|
import { create as adminCreate, update as adminUpdate, remove as adminRemove } from './admin-data'
|
|
16
|
+
import { computeContentHash } from './_shared/cil'
|
|
17
|
+
import * as semver from 'semver'
|
|
18
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Import dependencies and set module context for the cil-project Netlify function'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/resolve-ids.ts"]
|
|
19
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
20
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
21
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
22
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
23
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
24
|
+
// CIL[END stable_id="~/.framework/functions/cil-project.ts:module_header:module_header"]
|
|
22
25
|
|
|
23
26
|
|
|
24
27
|
|
|
@@ -26,62 +29,55 @@ import { create as adminCreate, update as adminUpdate, remove as adminRemove } f
|
|
|
26
29
|
|
|
27
30
|
|
|
28
31
|
|
|
29
|
-
// CIL[
|
|
30
|
-
// CIL[
|
|
31
|
-
// CIL[DOC-
|
|
32
|
-
// CIL[DOC-
|
|
33
|
-
// CIL[DOC-
|
|
34
|
-
// CIL[DOC-
|
|
35
|
-
// CIL[DOC-
|
|
36
|
-
// CIL[DOC-
|
|
37
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
38
|
-
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/principal.ts, custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/src/pages/admin/IntegrationsPage.tsx, custom/apps/portal/pages/ContentPage.tsx, \."]
|
|
39
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
40
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
41
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
42
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
43
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
32
|
+
// CIL[BEGIN stable_id="~/.framework/functions/cil-project.ts:DEFAULT_GLOBS:constant" type="constant" identity="DEFAULT_GLOBS" parent="~/.framework/functions/cil-project.ts"]
|
|
33
|
+
// CIL[DOC-MACRO purpose="Define default source glob patterns for CIL project discovery"]
|
|
34
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Provide the default list of file extensions to include during CIL discovery"]
|
|
35
|
+
// CIL[DOC-STABILITY stability="internal"]
|
|
36
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
37
|
+
// CIL[DOC-CONTEXT module=".framework/functions/cil-project" layer="constant" related_files=".framework/functions/_shared/cil.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-ids.ts,.framework/functions/admin-data.ts,.framework/functions/cil-project.ts"]
|
|
38
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="string[] of glob patterns" errors="none" side_effects="none"]
|
|
39
|
+
// CIL[DOC-MICRO logic_summary="Declares a constant array of glob strings for TypeScript and TSX source discovery" notable_decisions="[]"]
|
|
44
40
|
const DEFAULT_GLOBS = ['**/*.ts', '**/*.tsx', '**/*.sql']
|
|
41
|
+
// CIL[END stable_id="~/.framework/functions/cil-project.ts:DEFAULT_GLOBS:constant"]
|
|
45
42
|
|
|
43
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Define default source glob patterns for CIL project discovery'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/resolve-ids.ts"]
|
|
44
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
45
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
46
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
47
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
48
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
46
49
|
|
|
47
50
|
|
|
48
51
|
|
|
49
|
-
// CIL[
|
|
50
|
-
// CIL[
|
|
51
|
-
// CIL[DOC-
|
|
52
|
-
// CIL[DOC-
|
|
53
|
-
// CIL[DOC-
|
|
54
|
-
// CIL[DOC-
|
|
55
|
-
// CIL[DOC-
|
|
56
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
52
|
+
// CIL[BEGIN stable_id="~/.framework/functions/cil-project.ts:DEFAULT_EXCLUDE_GLOBS:constant" type="constant" identity="DEFAULT_EXCLUDE_GLOBS" parent="~/.framework/functions/cil-project.ts"]
|
|
53
|
+
// CIL[DOC-MACRO purpose="Define default exclusion globs for CIL project discovery"]
|
|
54
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Provide default ignored paths during CIL discovery"]
|
|
55
|
+
// CIL[DOC-CONTEXT module=".framework/functions/cil-project" layer="constant" related_files=".framework/functions/_shared/cil.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-ids.ts,.framework/functions/admin-data.ts,.framework/functions/cil-project.ts"]
|
|
56
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="string[] of exclusion globs" errors="none" side_effects="none"]
|
|
57
|
+
// CIL[DOC-MICRO logic_summary="Declares a constant array of exclusion globs covering dependencies, build output and generated files" notable_decisions="[]"]
|
|
58
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
57
59
|
// CIL[DOC-STABILITY stability="stable"]
|
|
58
|
-
|
|
59
|
-
// CIL[DOC-VECTOR type="
|
|
60
|
-
// CIL[DOC-VECTOR type="
|
|
61
|
-
// CIL[DOC-VECTOR type="
|
|
60
|
+
const DEFAULT_EXCLUDE_GLOBS = ['node_modules/**', '.git/**', '.assembled/**', 'dist/**', 'build/**', '.netlify/**', '**/*.min.js', '**/*.d.ts']
|
|
61
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Define default exclusion globs for CIL project discovery'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/resolve-ids.ts"]
|
|
62
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
63
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
64
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
62
65
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
63
66
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
64
|
-
|
|
67
|
+
// CIL[END stable_id="~/.framework/functions/cil-project.ts:DEFAULT_EXCLUDE_GLOBS:constant"]
|
|
65
68
|
|
|
66
69
|
|
|
67
70
|
|
|
68
71
|
|
|
69
72
|
|
|
70
|
-
// CIL[
|
|
71
|
-
// CIL[
|
|
72
|
-
// CIL[DOC-
|
|
73
|
-
// CIL[DOC-
|
|
74
|
-
// CIL[DOC-
|
|
75
|
-
// CIL[DOC-
|
|
76
|
-
// CIL[DOC-
|
|
77
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
73
|
+
// CIL[BEGIN stable_id="~/.framework/functions/cil-project.ts:SourceSet:interface" type="interface" identity="SourceSet" parent="~/.framework/functions/cil-project.ts"]
|
|
74
|
+
// CIL[DOC-MACRO purpose="Define the typed shape of a CIL project source set"]
|
|
75
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Describe the fields of a SourceSet configuration"]
|
|
76
|
+
// CIL[DOC-CONTEXT module=".framework/functions/cil-project" layer="interface" related_files=".framework/functions/_shared/cil.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-ids.ts,.framework/functions/admin-data.ts,.framework/functions/cil-project.ts"]
|
|
77
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="SourceSet TypeScript interface" errors="none" side_effects="none"]
|
|
78
|
+
// CIL[DOC-MICRO logic_summary="Declares an interface with id, name, base_path, globs, exclude_globs and optional layer" notable_decisions="[]"]
|
|
79
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
78
80
|
// CIL[DOC-STABILITY stability="stable"]
|
|
79
|
-
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/principal.ts, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/migrations/015_simplify_apps_table.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
|
|
80
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
81
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
82
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
83
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
84
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
85
81
|
interface SourceSet {
|
|
86
82
|
id: string
|
|
87
83
|
name: string
|
|
@@ -90,56 +86,57 @@ interface SourceSet {
|
|
|
90
86
|
exclude_globs?: string[]
|
|
91
87
|
layer?: string
|
|
92
88
|
}
|
|
89
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Define the typed shape of a CIL project source set'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/resolve-ids.ts"]
|
|
90
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
91
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
92
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
93
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
94
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
95
|
+
// CIL[END stable_id="~/.framework/functions/cil-project.ts:SourceSet:interface"]
|
|
93
96
|
|
|
94
97
|
|
|
95
98
|
|
|
96
99
|
|
|
97
100
|
|
|
98
|
-
// CIL[
|
|
99
|
-
// CIL[
|
|
100
|
-
// CIL[DOC-
|
|
101
|
-
// CIL[DOC-
|
|
102
|
-
// CIL[DOC-
|
|
103
|
-
// CIL[DOC-
|
|
104
|
-
// CIL[DOC-
|
|
105
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
101
|
+
// CIL[BEGIN stable_id="~/.framework/functions/cil-project.ts:CreateProjectRequest:interface" type="interface" identity="CreateProjectRequest" parent="~/.framework/functions/cil-project.ts"]
|
|
102
|
+
// CIL[DOC-MACRO purpose="Define the typed request shape for creating a CIL project"]
|
|
103
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Declare the input fields accepted by the project create action"]
|
|
104
|
+
// CIL[DOC-CONTEXT module=".framework/functions/cil-project" layer="interface" related_files=".framework/functions/_shared/cil.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-ids.ts,.framework/functions/admin-data.ts,.framework/functions/cil-project.ts"]
|
|
105
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="CreateProjectRequest TypeScript interface" errors="none" side_effects="none"]
|
|
106
|
+
// CIL[DOC-MICRO logic_summary="Declares an interface with name, description, repo_path, language_mix, kind, globs, exclude_globs, source_sets and dependencies" notable_decisions="[]"]
|
|
107
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
106
108
|
// CIL[DOC-STABILITY stability="stable"]
|
|
107
|
-
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/principal.ts, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/migrations/015_simplify_apps_table.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
|
|
108
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
109
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
110
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
111
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
112
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
113
109
|
interface CreateProjectRequest {
|
|
114
110
|
name: string
|
|
115
111
|
description?: string
|
|
116
112
|
repo_path: string
|
|
117
113
|
language_mix?: string
|
|
114
|
+
kind?: 'core' | 'custom'
|
|
118
115
|
globs?: string[]
|
|
119
116
|
exclude_globs?: string[]
|
|
120
117
|
source_sets?: SourceSet[]
|
|
121
118
|
dependencies?: string[]
|
|
122
119
|
}
|
|
120
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Define the typed request shape for creating a CIL project'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/resolve-ids.ts"]
|
|
121
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
122
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
123
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
124
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
125
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
126
|
+
// CIL[END stable_id="~/.framework/functions/cil-project.ts:CreateProjectRequest:interface"]
|
|
123
127
|
|
|
124
128
|
|
|
125
129
|
|
|
126
130
|
|
|
127
131
|
|
|
128
|
-
// CIL[
|
|
129
|
-
// CIL[
|
|
130
|
-
// CIL[DOC-
|
|
131
|
-
// CIL[DOC-
|
|
132
|
-
// CIL[DOC-
|
|
133
|
-
// CIL[DOC-
|
|
134
|
-
// CIL[DOC-
|
|
135
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
132
|
+
// CIL[BEGIN stable_id="~/.framework/functions/cil-project.ts:ProjectStats:interface" type="interface" identity="ProjectStats" parent="~/.framework/functions/cil-project.ts"]
|
|
133
|
+
// CIL[DOC-MACRO purpose="Define the typed shape for CIL project statistics"]
|
|
134
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Declare the aggregate counters returned by getProjectStats"]
|
|
135
|
+
// CIL[DOC-CONTEXT module=".framework/functions/cil-project" layer="interface" related_files=".framework/functions/_shared/cil.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-ids.ts,.framework/functions/admin-data.ts,.framework/functions/cil-project.ts"]
|
|
136
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="ProjectStats TypeScript interface" errors="none" side_effects="none"]
|
|
137
|
+
// CIL[DOC-MICRO logic_summary="Declares an interface with file, chunk, proposal, approved, pending review, dead code and doc confidence counters" notable_decisions="[]"]
|
|
138
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
136
139
|
// CIL[DOC-STABILITY stability="stable"]
|
|
137
|
-
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
138
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
139
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
140
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
141
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
142
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
143
140
|
interface ProjectStats {
|
|
144
141
|
file_count: number
|
|
145
142
|
chunk_count: number
|
|
@@ -150,6 +147,13 @@ interface ProjectStats {
|
|
|
150
147
|
doc_verified_count: number
|
|
151
148
|
doc_ai_count: number
|
|
152
149
|
}
|
|
150
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Define the typed shape for CIL project statistics'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/resolve-ids.ts"]
|
|
151
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
152
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
153
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
154
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
155
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
156
|
+
// CIL[END stable_id="~/.framework/functions/cil-project.ts:ProjectStats:interface"]
|
|
153
157
|
|
|
154
158
|
|
|
155
159
|
|
|
@@ -157,21 +161,14 @@ interface ProjectStats {
|
|
|
157
161
|
|
|
158
162
|
|
|
159
163
|
|
|
160
|
-
// CIL[
|
|
161
|
-
// CIL[
|
|
162
|
-
// CIL[DOC-
|
|
163
|
-
// CIL[DOC-
|
|
164
|
-
// CIL[DOC-
|
|
165
|
-
// CIL[DOC-
|
|
166
|
-
// CIL[DOC-
|
|
167
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
164
|
+
// CIL[BEGIN stable_id="~/.framework/functions/cil-project.ts:getProjectStats:function" type="function" identity="getProjectStats" parent="~/.framework/functions/cil-project.ts"]
|
|
165
|
+
// CIL[DOC-MACRO purpose="Compute aggregate CIL project statistics from the database"]
|
|
166
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Query files, chunks and proposals for a project and return summary counts"]
|
|
167
|
+
// CIL[DOC-CONTEXT module=".framework/functions/cil-project" layer="function" related_files=".framework/functions/_shared/cil.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-ids.ts,.framework/functions/admin-data.ts,.framework/functions/cil-project.ts"]
|
|
168
|
+
// CIL[DOC-CONTRACT inputs="projectId: string" outputs="ProjectStats object" errors="throws on database error" side_effects="none"]
|
|
169
|
+
// CIL[DOC-MICRO logic_summary="Runs three parallel adminDb queries, filters results by review_status, is_dead_code and doc_confidence to populate counters" notable_decisions="[]"]
|
|
170
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
168
171
|
// CIL[DOC-STABILITY stability="stable"]
|
|
169
|
-
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
170
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
171
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
172
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
173
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
174
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
175
172
|
async function getProjectStats(projectId: string): Promise<ProjectStats> {
|
|
176
173
|
const [filesResult, chunksResult, proposalsResult] = await Promise.all([
|
|
177
174
|
adminDb.from('items').select('id, data', { count: 'exact' })
|
|
@@ -202,27 +199,27 @@ async function getProjectStats(projectId: string): Promise<ProjectStats> {
|
|
|
202
199
|
doc_ai_count: chunks.filter(c => c.data?.doc_confidence === 'ai_generated').length,
|
|
203
200
|
}
|
|
204
201
|
}
|
|
202
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Compute aggregate CIL project statistics from the database'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/resolve-ids.ts"]
|
|
203
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
204
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
205
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
206
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
207
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
208
|
+
// CIL[END stable_id="~/.framework/functions/cil-project.ts:getProjectStats:function"]
|
|
205
209
|
|
|
206
210
|
|
|
207
211
|
|
|
208
212
|
|
|
209
213
|
|
|
210
214
|
|
|
211
|
-
// CIL[
|
|
212
|
-
// CIL[
|
|
213
|
-
// CIL[DOC-
|
|
214
|
-
// CIL[DOC-
|
|
215
|
-
// CIL[DOC-
|
|
216
|
-
// CIL[DOC-
|
|
217
|
-
// CIL[DOC-
|
|
218
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
215
|
+
// CIL[BEGIN stable_id="~/.framework/functions/cil-project.ts:bulkAdminRemove:function" type="function" identity="bulkAdminRemove" parent="~/.framework/functions/cil-project.ts"]
|
|
216
|
+
// CIL[DOC-MACRO purpose="Bulk delete admin-data records while tolerating individual failures"]
|
|
217
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Remove many records of a given entity and return the count of successful deletions"]
|
|
218
|
+
// CIL[DOC-CONTEXT module=".framework/functions/cil-project" layer="function" related_files=".framework/functions/_shared/cil.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-ids.ts,.framework/functions/admin-data.ts,.framework/functions/cil-project.ts"]
|
|
219
|
+
// CIL[DOC-CONTRACT inputs="ctx: any, entity: string, ids: string[]" outputs="number of successful deletions" errors="logs per-item failures and returns count" side_effects="calls adminRemove for each id"]
|
|
220
|
+
// CIL[DOC-MICRO logic_summary="Maps ids through adminRemove with soft false, catches errors per id, and counts non-null results" notable_decisions="[]"]
|
|
221
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
219
222
|
// CIL[DOC-STABILITY stability="stable"]
|
|
220
|
-
// CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
221
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
222
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
223
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
224
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
225
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
226
223
|
async function bulkAdminRemove(ctx: any, entity: string, ids: string[]): Promise<number> {
|
|
227
224
|
const results = await Promise.all(ids.map(id =>
|
|
228
225
|
adminRemove({ ...ctx, query: { ...(ctx.query || {}), entity, id, soft: 'false' } } as any).catch((e: any) => {
|
|
@@ -232,26 +229,233 @@ async function bulkAdminRemove(ctx: any, entity: string, ids: string[]): Promise
|
|
|
232
229
|
))
|
|
233
230
|
return results.filter(r => r !== null).length
|
|
234
231
|
}
|
|
232
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Bulk delete admin-data records while tolerating individual failures'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/resolve-ids.ts"]
|
|
233
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
234
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
235
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
236
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
237
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
238
|
+
// CIL[END stable_id="~/.framework/functions/cil-project.ts:bulkAdminRemove:function"]
|
|
239
|
+
|
|
235
240
|
|
|
236
241
|
|
|
237
242
|
|
|
238
243
|
|
|
239
244
|
|
|
240
|
-
// CIL[
|
|
241
|
-
// CIL[
|
|
242
|
-
// CIL[DOC-
|
|
243
|
-
// CIL[DOC-
|
|
244
|
-
// CIL[DOC-
|
|
245
|
-
// CIL[DOC-
|
|
246
|
-
// CIL[DOC-
|
|
247
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
245
|
+
// CIL[BEGIN stable_id="~/.framework/functions/cil-project.ts:buildVersionManifest:function" type="function" identity="buildVersionManifest" parent="~/.framework/functions/cil-project.ts"]
|
|
246
|
+
// CIL[DOC-MACRO purpose="Build a version manifest from CIL project files, chunks, embeddings and links"]
|
|
247
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Collect all versioned CIL items for a project into a manifest object"]
|
|
248
|
+
// CIL[DOC-CONTEXT module=".framework/functions/cil-project" layer="function" related_files=".framework/functions/_shared/cil.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-ids.ts,.framework/functions/admin-data.ts,.framework/functions/cil-project.ts"]
|
|
249
|
+
// CIL[DOC-CONTRACT inputs="projectId: string" outputs="Record with files, chunks, embeddings, links and metadata" errors="throws if manifest or embedding queries fail" side_effects="reads from items, embeddings and links tables"]
|
|
250
|
+
// CIL[DOC-MICRO logic_summary="Loads files and chunks, joins embeddings by chunk id, and batches link queries both directions to build a stable-id keyed manifest" notable_decisions="[]"]
|
|
251
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
248
252
|
// CIL[DOC-STABILITY stability="stable"]
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
+
async function buildVersionManifest(projectId: string): Promise<Record<string, any>> {
|
|
254
|
+
const IN_LIMIT = 500
|
|
255
|
+
|
|
256
|
+
const { data: fileItems, error: fErr } = await adminDb
|
|
257
|
+
.from('items')
|
|
258
|
+
.select('id, data')
|
|
259
|
+
.filter('data->>kb_type', 'eq', 'cil_file')
|
|
260
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
261
|
+
.eq('is_active', true)
|
|
262
|
+
|
|
263
|
+
const { data: chunkItems, error: cErr } = await adminDb
|
|
264
|
+
.from('items')
|
|
265
|
+
.select('id, data')
|
|
266
|
+
.filter('data->>kb_type', 'eq', 'cil_chunk')
|
|
267
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
268
|
+
.eq('is_active', true)
|
|
269
|
+
|
|
270
|
+
if (fErr) throw new Error(`Failed to load files for manifest: ${fErr.message}`)
|
|
271
|
+
if (cErr) throw new Error(`Failed to load chunks for manifest: ${cErr.message}`)
|
|
272
|
+
|
|
273
|
+
const files: Record<string, any> = {}
|
|
274
|
+
const chunks: Record<string, any> = {}
|
|
275
|
+
const itemIdToStable: Record<string, { stable_id: string; type: string }> = {}
|
|
276
|
+
|
|
277
|
+
for (const f of fileItems || []) {
|
|
278
|
+
const stable = f.data?.stable_id || f.data?.file_path || f.id
|
|
279
|
+
files[stable] = {
|
|
280
|
+
file_id: f.id,
|
|
281
|
+
stable_id: stable,
|
|
282
|
+
stored_hash: f.data?.stored_hash || f.data?.file_hash || '',
|
|
283
|
+
spine_version_id: f.data?.spine_version_id || '',
|
|
284
|
+
customer_version_id: f.data?.customer_version_id || '',
|
|
285
|
+
customized: f.data?.customized || false,
|
|
286
|
+
}
|
|
287
|
+
itemIdToStable[f.id] = { stable_id: stable, type: 'file' }
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const chunkIds: string[] = []
|
|
291
|
+
for (const c of chunkItems || []) {
|
|
292
|
+
const stable = c.data?.stable_id || c.id
|
|
293
|
+
chunks[stable] = {
|
|
294
|
+
chunk_id: c.id,
|
|
295
|
+
file_id: c.data?.file_id || '',
|
|
296
|
+
file_path: c.data?.file_path || '',
|
|
297
|
+
stable_id: stable,
|
|
298
|
+
stored_hash: c.data?.stored_hash || c.data?.content_hash || '',
|
|
299
|
+
spine_version_id: c.data?.spine_version_id || '',
|
|
300
|
+
customer_version_id: c.data?.customer_version_id || '',
|
|
301
|
+
customized: c.data?.customized || false,
|
|
302
|
+
}
|
|
303
|
+
itemIdToStable[c.id] = { stable_id: stable, type: 'chunk' }
|
|
304
|
+
chunkIds.push(c.id)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const embeddings: Record<string, any> = {}
|
|
308
|
+
if (chunkIds.length > 0) {
|
|
309
|
+
const { data: embeddingRows, error: eErr } = await adminDb
|
|
310
|
+
.from('embeddings')
|
|
311
|
+
.select('id, source_item_id, data')
|
|
312
|
+
.in('source_item_id', chunkIds)
|
|
313
|
+
.eq('is_active', true)
|
|
314
|
+
if (eErr) throw new Error(`Failed to load embeddings for manifest: ${eErr.message}`)
|
|
315
|
+
for (const e of embeddingRows || []) {
|
|
316
|
+
const type = e.data?.type || 'semantic'
|
|
317
|
+
const contentHash = e.data?.input_hash || e.data?.content_hash || ''
|
|
318
|
+
const chunkStable = itemIdToStable[e.source_item_id]?.stable_id
|
|
319
|
+
if (!chunkStable) continue
|
|
320
|
+
if (!embeddings[chunkStable]) embeddings[chunkStable] = {}
|
|
321
|
+
embeddings[chunkStable][type] = {
|
|
322
|
+
embedding_id: e.id,
|
|
323
|
+
content_hash: contentHash,
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const links: any[] = []
|
|
329
|
+
const seenLinks = new Set<string>()
|
|
330
|
+
const allIds = Object.keys(itemIdToStable)
|
|
331
|
+
for (let i = 0; i < allIds.length; i += IN_LIMIT) {
|
|
332
|
+
const batch = allIds.slice(i, i + IN_LIMIT)
|
|
333
|
+
const [{ data: sourceLinks }, { data: targetLinks }] = await Promise.all([
|
|
334
|
+
adminDb.from('links').select('id, source_id, target_id, link_type_id, data').in('source_id', batch),
|
|
335
|
+
adminDb.from('links').select('id, source_id, target_id, link_type_id, data').in('target_id', batch),
|
|
336
|
+
])
|
|
337
|
+
for (const l of [...(sourceLinks || []), ...(targetLinks || [])]) {
|
|
338
|
+
if (seenLinks.has(l.id)) continue
|
|
339
|
+
seenLinks.add(l.id)
|
|
340
|
+
const sourceStable = itemIdToStable[l.source_id]?.stable_id || l.source_id
|
|
341
|
+
const targetStable = itemIdToStable[l.target_id]?.stable_id || l.target_id
|
|
342
|
+
links.push({
|
|
343
|
+
link_id: l.id,
|
|
344
|
+
source_id: l.source_id,
|
|
345
|
+
target_id: l.target_id,
|
|
346
|
+
source_stable_id: sourceStable,
|
|
347
|
+
target_stable_id: targetStable,
|
|
348
|
+
link_type_id: l.link_type_id,
|
|
349
|
+
metadata_hash: computeContentHash(JSON.stringify(l.data || {})),
|
|
350
|
+
})
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return {
|
|
355
|
+
files,
|
|
356
|
+
chunks,
|
|
357
|
+
embeddings,
|
|
358
|
+
links,
|
|
359
|
+
project_id: projectId,
|
|
360
|
+
generated_at: new Date().toISOString(),
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Build a version manifest from CIL project files, chunks, embeddings and links'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/resolve-ids.ts"]
|
|
364
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
365
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
366
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
253
367
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
254
368
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
369
|
+
// CIL[END stable_id="~/.framework/functions/cil-project.ts:buildVersionManifest:function"]
|
|
370
|
+
|
|
371
|
+
// CIL[BEGIN stable_id="~/.framework/functions/cil-project.ts:buildVersionDiff:function" type="function" identity="buildVersionDiff" parent="~/.framework/functions/cil-project.ts"]
|
|
372
|
+
// CIL[DOC-MACRO purpose="Compute a diff between two CIL version manifests"]
|
|
373
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Compare from and to manifests to produce added, removed and modified lists"]
|
|
374
|
+
// CIL[DOC-CONTEXT module=".framework/functions/cil-project" layer="function" related_files=".framework/functions/_shared/cil.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-ids.ts,.framework/functions/admin-data.ts,.framework/functions/cil-project.ts"]
|
|
375
|
+
// CIL[DOC-CONTRACT inputs="fromManifest: Record<string, any>, toManifest: Record<string, any>" outputs="Record with added/removed/modified files, chunks, embeddings and links" errors="none" side_effects="none"]
|
|
376
|
+
// CIL[DOC-MICRO logic_summary="Iterates combined keys for files, chunks, embeddings and links, comparing stored_hash or metadata_hash to classify changes" notable_decisions="[]"]
|
|
377
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
378
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
379
|
+
function buildVersionDiff(fromManifest: Record<string, any> = {}, toManifest: Record<string, any> = {}): Record<string, any> {
|
|
380
|
+
const diff: Record<string, any> = {
|
|
381
|
+
added_files: [],
|
|
382
|
+
removed_files: [],
|
|
383
|
+
modified_files: [],
|
|
384
|
+
added_chunks: [],
|
|
385
|
+
removed_chunks: [],
|
|
386
|
+
modified_chunks: [],
|
|
387
|
+
added_embeddings: [],
|
|
388
|
+
removed_embeddings: [],
|
|
389
|
+
modified_embeddings: [],
|
|
390
|
+
added_links: [],
|
|
391
|
+
removed_links: [],
|
|
392
|
+
modified_links: [],
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const fromFiles = fromManifest.files || {}
|
|
396
|
+
const toFiles = toManifest.files || {}
|
|
397
|
+
const fromChunks = fromManifest.chunks || {}
|
|
398
|
+
const toChunks = toManifest.chunks || {}
|
|
399
|
+
|
|
400
|
+
const allFileStables = new Set([...Object.keys(fromFiles), ...Object.keys(toFiles)])
|
|
401
|
+
for (const stable of allFileStables) {
|
|
402
|
+
if (!fromFiles[stable]) diff.added_files.push({ stable_id: stable, ...toFiles[stable] })
|
|
403
|
+
else if (!toFiles[stable]) diff.removed_files.push({ stable_id: stable, ...fromFiles[stable] })
|
|
404
|
+
else if (fromFiles[stable].stored_hash !== toFiles[stable].stored_hash) diff.modified_files.push({ stable_id: stable, from: fromFiles[stable], to: toFiles[stable] })
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const allChunkStables = new Set([...Object.keys(fromChunks), ...Object.keys(toChunks)])
|
|
408
|
+
for (const stable of allChunkStables) {
|
|
409
|
+
if (!fromChunks[stable]) diff.added_chunks.push({ stable_id: stable, ...toChunks[stable] })
|
|
410
|
+
else if (!toChunks[stable]) diff.removed_chunks.push({ stable_id: stable, ...fromChunks[stable] })
|
|
411
|
+
else if (fromChunks[stable].stored_hash !== toChunks[stable].stored_hash) diff.modified_chunks.push({ stable_id: stable, from: fromChunks[stable], to: toChunks[stable] })
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const fromEmbeddings = fromManifest.embeddings || {}
|
|
415
|
+
const toEmbeddings = toManifest.embeddings || {}
|
|
416
|
+
const allChunkEmbeds = new Set([...Object.keys(fromEmbeddings), ...Object.keys(toEmbeddings)])
|
|
417
|
+
for (const chunkStable of allChunkEmbeds) {
|
|
418
|
+
const fromTypes = fromEmbeddings[chunkStable] || {}
|
|
419
|
+
const toTypes = toEmbeddings[chunkStable] || {}
|
|
420
|
+
const allTypes = new Set([...Object.keys(fromTypes), ...Object.keys(toTypes)])
|
|
421
|
+
for (const type of allTypes) {
|
|
422
|
+
const fromE = fromTypes[type]
|
|
423
|
+
const toE = toTypes[type]
|
|
424
|
+
if (!fromE) diff.added_embeddings.push({ chunk_stable_id: chunkStable, vector_type: type, ...toE })
|
|
425
|
+
else if (!toE) diff.removed_embeddings.push({ chunk_stable_id: chunkStable, vector_type: type, ...fromE })
|
|
426
|
+
else if (fromE.content_hash !== toE.content_hash) diff.modified_embeddings.push({ chunk_stable_id: chunkStable, vector_type: type, from: fromE, to: toE })
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const linkKey = (l: any) => `${l.source_stable_id}:${l.target_stable_id}:${l.link_type_id}`
|
|
431
|
+
const fromLinks = (fromManifest.links || []).reduce((acc: Record<string, any>, l: any) => { acc[linkKey(l)] = l; return acc }, {})
|
|
432
|
+
const toLinks = (toManifest.links || []).reduce((acc: Record<string, any>, l: any) => { acc[linkKey(l)] = l; return acc }, {})
|
|
433
|
+
const allLinkKeys = new Set([...Object.keys(fromLinks), ...Object.keys(toLinks)])
|
|
434
|
+
for (const key of allLinkKeys) {
|
|
435
|
+
const fromL = fromLinks[key]
|
|
436
|
+
const toL = toLinks[key]
|
|
437
|
+
if (!fromL) diff.added_links.push(toL)
|
|
438
|
+
else if (!toL) diff.removed_links.push(fromL)
|
|
439
|
+
else if (fromL.metadata_hash !== toL.metadata_hash) diff.modified_links.push({ from: fromL, to: toL })
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
return diff
|
|
443
|
+
}
|
|
444
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Compute a diff between two CIL version manifests'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/resolve-ids.ts"]
|
|
445
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
446
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
447
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
448
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
449
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
450
|
+
// CIL[END stable_id="~/.framework/functions/cil-project.ts:buildVersionDiff:function"]
|
|
451
|
+
// CIL[BEGIN stable_id="~/.framework/functions/cil-project.ts:handler:constant" type="constant" identity="handler" parent="~/.framework/functions/cil-project.ts"]
|
|
452
|
+
// CIL[DOC-MACRO purpose="Netlify function handler for CIL project CRUD and version lifecycle actions"]
|
|
453
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Dispatch actions: list, get, create, update, delete, pipeline progress, create_version, set_active_version, publish_version, mark_versions_inactive, archive_versions"]
|
|
454
|
+
// CIL[DOC-CONTEXT module=".framework/functions/cil-project" layer="function" related_files=".framework/functions/_shared/cil.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/resolve-ids.ts,.framework/functions/admin-data.ts,.framework/functions/cil-project.ts"]
|
|
455
|
+
// CIL[DOC-CONTRACT inputs="ctx: RequestContext, body: any" outputs="action-specific response object" errors="throws Error with action-specific message for missing/invalid inputs or DB failures" side_effects="reads and writes items, embeddings and links via adminDb and admin-data"]
|
|
456
|
+
// CIL[DOC-MICRO logic_summary="createHandler wrapper that branches on action and method to list, fetch, create, update, delete, version and publish CIL projects" notable_decisions="[]"]
|
|
457
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
458
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
255
459
|
export const handler = createHandler(async (ctx, body) => {
|
|
256
460
|
const action = ctx.query?.action
|
|
257
461
|
const method = (ctx as any).method || (body ? 'POST' : 'GET')
|
|
@@ -311,20 +515,22 @@ export const handler = createHandler(async (ctx, body) => {
|
|
|
311
515
|
|
|
312
516
|
|
|
313
517
|
if (action === 'create' || (!action && method === 'POST')) {
|
|
314
|
-
const req = body as
|
|
315
|
-
|
|
518
|
+
const req = body as any
|
|
519
|
+
const name = req?.name || req?.title
|
|
520
|
+
if (!name) throw new Error('name is required')
|
|
316
521
|
if (!req?.repo_path) throw new Error('repo_path is required')
|
|
317
522
|
|
|
318
523
|
const result = await adminCreate(ctx, {
|
|
319
524
|
entity: 'items',
|
|
320
525
|
type_slug: 'cil_project',
|
|
321
|
-
title:
|
|
526
|
+
title: name,
|
|
322
527
|
description: req.description || '',
|
|
323
528
|
status: 'active',
|
|
324
529
|
data: {
|
|
325
530
|
kb_type: 'cil_project',
|
|
326
531
|
repo_path: req.repo_path,
|
|
327
532
|
language_mix: req.language_mix || '',
|
|
533
|
+
kind: req.kind || 'custom',
|
|
328
534
|
ingestion_status: 'not_started',
|
|
329
535
|
file_count: 0,
|
|
330
536
|
chunk_count: 0,
|
|
@@ -337,7 +543,30 @@ export const handler = createHandler(async (ctx, body) => {
|
|
|
337
543
|
}
|
|
338
544
|
})
|
|
339
545
|
|
|
340
|
-
|
|
546
|
+
const defaultVersion = await adminCreate(ctx, {
|
|
547
|
+
entity: 'items',
|
|
548
|
+
type_slug: 'cil_version',
|
|
549
|
+
title: `${name} v0.0.0`,
|
|
550
|
+
status: 'active',
|
|
551
|
+
data: {
|
|
552
|
+
project_id: result.id,
|
|
553
|
+
version: 'v0.0.0',
|
|
554
|
+
base_version: '',
|
|
555
|
+
is_iteration: false,
|
|
556
|
+
status: 'active',
|
|
557
|
+
},
|
|
558
|
+
})
|
|
559
|
+
|
|
560
|
+
const updateCtx = { ...ctx, query: { ...ctx.query, entity: 'items', id: result.id } }
|
|
561
|
+
await adminUpdate(updateCtx, {
|
|
562
|
+
data: {
|
|
563
|
+
...result.data,
|
|
564
|
+
active_version_id: defaultVersion.id,
|
|
565
|
+
default_version_id: defaultVersion.id,
|
|
566
|
+
},
|
|
567
|
+
})
|
|
568
|
+
|
|
569
|
+
return { project: { ...result, data: { ...result.data, active_version_id: defaultVersion.id, default_version_id: defaultVersion.id } } }
|
|
341
570
|
}
|
|
342
571
|
|
|
343
572
|
|
|
@@ -357,6 +586,7 @@ export const handler = createHandler(async (ctx, body) => {
|
|
|
357
586
|
data: mergedData,
|
|
358
587
|
...(body?.status ? { status: body.status } : {}),
|
|
359
588
|
...(body?.title ? { title: body.title } : {}),
|
|
589
|
+
...(body?.description ? { description: body.description } : {}),
|
|
360
590
|
})
|
|
361
591
|
|
|
362
592
|
return { project: result }
|
|
@@ -430,7 +660,7 @@ export const handler = createHandler(async (ctx, body) => {
|
|
|
430
660
|
}
|
|
431
661
|
|
|
432
662
|
|
|
433
|
-
for (const kbType of ['cil_chunk', 'cil_chunk_proposal', 'cil_file', 'cil_config']) {
|
|
663
|
+
for (const kbType of ['cil_chunk', 'cil_chunk_proposal', 'cil_file', 'cil_config', 'cil_version', 'cil_suggestion', 'cil_learning_proposal']) {
|
|
434
664
|
const { data: itemsToDelete } = await adminDb
|
|
435
665
|
.from('items')
|
|
436
666
|
.select('id')
|
|
@@ -471,6 +701,7 @@ export const handler = createHandler(async (ctx, body) => {
|
|
|
471
701
|
const by_status: Record<string, number> = {}
|
|
472
702
|
for (const [key, val] of Object.entries(fileStatuses)) {
|
|
473
703
|
if (key.endsWith('_updated')) continue
|
|
704
|
+
if (typeof val !== 'string') continue
|
|
474
705
|
by_status[val] = (by_status[val] || 0) + 1
|
|
475
706
|
}
|
|
476
707
|
|
|
@@ -491,9 +722,305 @@ export const handler = createHandler(async (ctx, body) => {
|
|
|
491
722
|
}
|
|
492
723
|
}
|
|
493
724
|
|
|
494
|
-
|
|
495
|
-
|
|
725
|
+
|
|
726
|
+
if (action === 'create_version') {
|
|
727
|
+
const projectId = body?.project_id
|
|
728
|
+
const version = body?.version
|
|
729
|
+
if (!projectId) throw new Error('project_id is required')
|
|
730
|
+
if (!version) throw new Error('version is required')
|
|
731
|
+
if (!semver.valid(version)) throw new Error(`Invalid semver version: ${version}`)
|
|
732
|
+
|
|
733
|
+
const versionTypeId = await resolveTypeId('item', 'cil_version')
|
|
734
|
+
const { count, error: countErr } = await adminDb
|
|
735
|
+
.from('items')
|
|
736
|
+
.select('*', { count: 'exact', head: true })
|
|
737
|
+
.eq('type_id', versionTypeId)
|
|
738
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
739
|
+
if (countErr) throw new Error(`Failed to check existing versions: ${countErr.message}`)
|
|
740
|
+
|
|
741
|
+
const isFirst = (count || 0) === 0
|
|
742
|
+
const isIteration = semver.prerelease(version) !== null
|
|
743
|
+
const status = isFirst ? 'active' : 'inactive'
|
|
744
|
+
|
|
745
|
+
const versionRecord = await adminCreate(ctx, {
|
|
746
|
+
entity: 'items',
|
|
747
|
+
type_slug: 'cil_version',
|
|
748
|
+
title: version,
|
|
749
|
+
status,
|
|
750
|
+
data: {
|
|
751
|
+
project_id: projectId,
|
|
752
|
+
version,
|
|
753
|
+
base_version: body?.base_version || '',
|
|
754
|
+
is_iteration: isIteration,
|
|
755
|
+
status,
|
|
756
|
+
},
|
|
757
|
+
})
|
|
758
|
+
|
|
759
|
+
if (isFirst) {
|
|
760
|
+
const projectTypeId = await resolveTypeId('item', 'cil_project')
|
|
761
|
+
const { data: projects, error: pErr } = await adminDb
|
|
762
|
+
.from('items')
|
|
763
|
+
.select('id, data')
|
|
764
|
+
.eq('type_id', projectTypeId)
|
|
765
|
+
.eq('id', projectId)
|
|
766
|
+
.limit(1)
|
|
767
|
+
if (pErr || !projects || projects.length === 0) throw new Error(`Project not found: ${projectId}`)
|
|
768
|
+
const project = projects[0]
|
|
769
|
+
const updateCtx = { ...ctx, query: { ...ctx.query, entity: 'items', id: projectId } }
|
|
770
|
+
await adminUpdate(updateCtx, {
|
|
771
|
+
data: {
|
|
772
|
+
...project.data,
|
|
773
|
+
active_version_id: versionRecord.id,
|
|
774
|
+
default_version_id: versionRecord.id,
|
|
775
|
+
},
|
|
776
|
+
})
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
return { version: versionRecord }
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
if (action === 'set_active_version') {
|
|
784
|
+
const projectId = body?.project_id || ctx.query?.id
|
|
785
|
+
const versionId = body?.version_id
|
|
786
|
+
if (!projectId) throw new Error('project_id is required')
|
|
787
|
+
if (!versionId) throw new Error('version_id is required')
|
|
788
|
+
|
|
789
|
+
const projectTypeId = await resolveTypeId('item', 'cil_project')
|
|
790
|
+
const versionTypeId = await resolveTypeId('item', 'cil_version')
|
|
791
|
+
|
|
792
|
+
const { data: projectRows, error: pErr } = await adminDb
|
|
793
|
+
.from('items')
|
|
794
|
+
.select('id, data')
|
|
795
|
+
.eq('type_id', projectTypeId)
|
|
796
|
+
.eq('id', projectId)
|
|
797
|
+
.limit(1)
|
|
798
|
+
if (pErr || !projectRows || projectRows.length === 0) throw new Error(`Project not found: ${projectId}`)
|
|
799
|
+
const project = projectRows[0]
|
|
800
|
+
|
|
801
|
+
const { data: targetRows, error: tErr } = await adminDb
|
|
802
|
+
.from('items')
|
|
803
|
+
.select('id, data, status, is_active')
|
|
804
|
+
.eq('type_id', versionTypeId)
|
|
805
|
+
.eq('id', versionId)
|
|
806
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
807
|
+
.limit(1)
|
|
808
|
+
if (tErr || !targetRows || targetRows.length === 0) throw new Error(`Version not found: ${versionId}`)
|
|
809
|
+
const targetVersion = targetRows[0]
|
|
810
|
+
|
|
811
|
+
const { data: otherVersions, error: oErr } = await adminDb
|
|
812
|
+
.from('items')
|
|
813
|
+
.select('id, data, status, is_active')
|
|
814
|
+
.eq('type_id', versionTypeId)
|
|
815
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
816
|
+
.neq('id', versionId)
|
|
817
|
+
if (oErr) throw new Error(`Failed to list versions: ${oErr.message}`)
|
|
818
|
+
|
|
819
|
+
for (const v of otherVersions || []) {
|
|
820
|
+
if (v.data?.status === 'active') {
|
|
821
|
+
await adminDb.from('items').update({
|
|
822
|
+
status: 'inactive',
|
|
823
|
+
data: { ...v.data, status: 'inactive' },
|
|
824
|
+
}).eq('id', v.id)
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
await adminDb.from('items').update({
|
|
829
|
+
status: 'active',
|
|
830
|
+
data: { ...targetVersion.data, status: 'active' },
|
|
831
|
+
}).eq('id', versionId)
|
|
832
|
+
|
|
833
|
+
const updateCtx = { ...ctx, query: { ...ctx.query, entity: 'items', id: projectId } }
|
|
834
|
+
const result = await adminUpdate(updateCtx, {
|
|
835
|
+
data: {
|
|
836
|
+
...project.data,
|
|
837
|
+
active_version_id: versionId,
|
|
838
|
+
},
|
|
839
|
+
})
|
|
840
|
+
|
|
841
|
+
return { project: result, version_id: versionId }
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
|
|
845
|
+
if (action === 'publish_version') {
|
|
846
|
+
const projectId = body?.project_id
|
|
847
|
+
const version = body?.version
|
|
848
|
+
if (!projectId) throw new Error('project_id is required')
|
|
849
|
+
if (!version) throw new Error('version is required')
|
|
850
|
+
if (!semver.valid(version)) throw new Error(`Invalid semver version: ${version}`)
|
|
496
851
|
|
|
852
|
+
const projectTypeId = await resolveTypeId('item', 'cil_project')
|
|
853
|
+
const versionTypeId = await resolveTypeId('item', 'cil_version')
|
|
854
|
+
|
|
855
|
+
const { data: projectRows, error: pErr } = await adminDb
|
|
856
|
+
.from('items')
|
|
857
|
+
.select('id, data, title')
|
|
858
|
+
.eq('type_id', projectTypeId)
|
|
859
|
+
.eq('id', projectId)
|
|
860
|
+
.limit(1)
|
|
861
|
+
if (pErr || !projectRows || projectRows.length === 0) throw new Error(`Project not found: ${projectId}`)
|
|
862
|
+
const project = projectRows[0]
|
|
863
|
+
|
|
864
|
+
const versionRecord = await adminCreate(ctx, {
|
|
865
|
+
entity: 'items',
|
|
866
|
+
type_slug: 'cil_version',
|
|
867
|
+
title: version,
|
|
868
|
+
status: 'active',
|
|
869
|
+
data: {
|
|
870
|
+
project_id: projectId,
|
|
871
|
+
version,
|
|
872
|
+
base_version: body?.base_version || '',
|
|
873
|
+
parent_version_id: project.data?.active_version_id || '',
|
|
874
|
+
npm_name: project.data?.npm_name || '',
|
|
875
|
+
npm_version: version,
|
|
876
|
+
is_iteration: false,
|
|
877
|
+
is_customer: false,
|
|
878
|
+
status: 'active',
|
|
879
|
+
manifest: null,
|
|
880
|
+
diff: null,
|
|
881
|
+
},
|
|
882
|
+
})
|
|
883
|
+
|
|
884
|
+
const manifest = await buildVersionManifest(projectId)
|
|
885
|
+
const parentVersionId = versionRecord.data.parent_version_id
|
|
886
|
+
const { data: parentVersionRows } = parentVersionId
|
|
887
|
+
? await adminDb.from('items').select('id, data').eq('id', parentVersionId).maybeSingle()
|
|
888
|
+
: { data: null }
|
|
889
|
+
const parentManifest = parentVersionRows?.data?.manifest || null
|
|
890
|
+
const diff = buildVersionDiff(parentManifest, manifest)
|
|
891
|
+
await adminDb.from('items').update({ data: { ...versionRecord.data, manifest, diff } }).eq('id', versionRecord.id)
|
|
892
|
+
versionRecord.data = { ...versionRecord.data, manifest, diff }
|
|
893
|
+
|
|
894
|
+
const { data: allVersions, error: vErr } = await adminDb
|
|
895
|
+
.from('items')
|
|
896
|
+
.select('id, data, status, is_active')
|
|
897
|
+
.eq('type_id', versionTypeId)
|
|
898
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
899
|
+
.neq('id', versionRecord.id)
|
|
900
|
+
if (vErr) throw new Error(`Failed to list versions: ${vErr.message}`)
|
|
901
|
+
|
|
902
|
+
for (const v of allVersions || []) {
|
|
903
|
+
if (v.data?.status !== 'inactive') {
|
|
904
|
+
await adminDb.from('items').update({
|
|
905
|
+
status: 'inactive',
|
|
906
|
+
data: { ...v.data, status: 'inactive' },
|
|
907
|
+
}).eq('id', v.id)
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
if (body?.base_version) {
|
|
912
|
+
const baseVersion = body.base_version
|
|
913
|
+
const { data: iterations, error: iErr } = await adminDb
|
|
914
|
+
.from('items')
|
|
915
|
+
.select('id, data, status, is_active')
|
|
916
|
+
.eq('type_id', versionTypeId)
|
|
917
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
918
|
+
.filter('data->>base_version', 'eq', baseVersion)
|
|
919
|
+
.filter('data->>is_iteration', 'eq', 'true')
|
|
920
|
+
if (iErr) throw new Error(`Failed to list iterations: ${iErr.message}`)
|
|
921
|
+
|
|
922
|
+
for (const iter of iterations || []) {
|
|
923
|
+
if (iter.data?.status !== 'inactive') {
|
|
924
|
+
await adminDb.from('items').update({
|
|
925
|
+
status: 'inactive',
|
|
926
|
+
data: { ...iter.data, status: 'inactive' },
|
|
927
|
+
}).eq('id', iter.id)
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
const activeIteration = (iterations || []).find((i: any) => i.data?.status === 'active' || !i.data?.published_version_id)
|
|
932
|
+
|| (iterations || [])[0]
|
|
933
|
+
if (activeIteration) {
|
|
934
|
+
await adminDb.from('items').update({
|
|
935
|
+
data: { ...activeIteration.data, published_version_id: versionRecord.id },
|
|
936
|
+
}).eq('id', activeIteration.id)
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
const updateCtx = { ...ctx, query: { ...ctx.query, entity: 'items', id: projectId } }
|
|
941
|
+
const result = await adminUpdate(updateCtx, {
|
|
942
|
+
data: {
|
|
943
|
+
...project.data,
|
|
944
|
+
active_version_id: versionRecord.id,
|
|
945
|
+
default_version_id: versionRecord.id,
|
|
946
|
+
},
|
|
947
|
+
})
|
|
948
|
+
|
|
949
|
+
return { version: versionRecord, project: result }
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
if (action === 'mark_versions_inactive') {
|
|
954
|
+
const projectId = body?.project_id
|
|
955
|
+
const versionPattern = body?.version_pattern
|
|
956
|
+
if (!projectId) throw new Error('project_id is required')
|
|
957
|
+
if (!versionPattern) throw new Error('version_pattern is required')
|
|
958
|
+
|
|
959
|
+
const versionTypeId = await resolveTypeId('item', 'cil_version')
|
|
960
|
+
const { data: matches, error } = await adminDb
|
|
961
|
+
.from('items')
|
|
962
|
+
.select('id, data, status, is_active')
|
|
963
|
+
.eq('type_id', versionTypeId)
|
|
964
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
965
|
+
.ilike('data->>version', `%${versionPattern}%`)
|
|
966
|
+
if (error) throw new Error(`Failed to find versions: ${error.message}`)
|
|
967
|
+
|
|
968
|
+
const updatedIds: string[] = []
|
|
969
|
+
for (const v of matches || []) {
|
|
970
|
+
await adminDb.from('items').update({
|
|
971
|
+
status: 'inactive',
|
|
972
|
+
data: { ...v.data, status: 'inactive' },
|
|
973
|
+
}).eq('id', v.id)
|
|
974
|
+
updatedIds.push(v.id)
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
return { updated_ids: updatedIds, count: updatedIds.length }
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
|
|
981
|
+
if (action === 'archive_versions') {
|
|
982
|
+
const projectId = body?.project_id
|
|
983
|
+
const keepLastN = parseInt(body?.keep_last_n, 10)
|
|
984
|
+
if (!projectId) throw new Error('project_id is required')
|
|
985
|
+
if (Number.isNaN(keepLastN) || keepLastN < 0) throw new Error('keep_last_n is required and must be a number >= 0')
|
|
986
|
+
|
|
987
|
+
const versionTypeId = await resolveTypeId('item', 'cil_version')
|
|
988
|
+
const { data: allVersions, error } = await adminDb
|
|
989
|
+
.from('items')
|
|
990
|
+
.select('id, data, status, is_active, created_at')
|
|
991
|
+
.eq('type_id', versionTypeId)
|
|
992
|
+
.filter('data->>project_id', 'eq', projectId)
|
|
993
|
+
.order('created_at', { ascending: true })
|
|
994
|
+
if (error) throw new Error(`Failed to list versions: ${error.message}`)
|
|
995
|
+
|
|
996
|
+
const activeVersionId = (allVersions || []).find((v: any) => v.data?.status === 'active')?.id
|
|
997
|
+
const inactiveVersions = (allVersions || []).filter((v: any) =>
|
|
998
|
+
v.data?.status === 'inactive' && v.id !== activeVersionId
|
|
999
|
+
)
|
|
1000
|
+
|
|
1001
|
+
const toArchive = inactiveVersions.slice(0, Math.max(0, inactiveVersions.length - keepLastN))
|
|
1002
|
+
const archivedIds: string[] = []
|
|
1003
|
+
|
|
1004
|
+
for (const v of toArchive) {
|
|
1005
|
+
await adminDb.from('items').update({
|
|
1006
|
+
is_active: false,
|
|
1007
|
+
status: 'archived',
|
|
1008
|
+
data: { ...v.data, status: 'archived' },
|
|
1009
|
+
}).eq('id', v.id)
|
|
1010
|
+
archivedIds.push(v.id)
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
return { archived_ids: archivedIds, count: archivedIds.length, kept: (allVersions || []).length - archivedIds.length }
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
throw new Error(`Unknown action: ${action}. Valid: list, get, create, update, delete, pipeline_progress, create_version, set_active_version, publish_version, mark_versions_inactive, archive_versions`)
|
|
1017
|
+
})
|
|
1018
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Netlify function handler for CIL project CRUD and version lifecycle actions'; No verified external callers; imports: .framework/functions/_shared/middleware.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/resolve-ids.ts"]
|
|
1019
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
1020
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
1021
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
1022
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
1023
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
1024
|
+
// CIL[END stable_id="~/.framework/functions/cil-project.ts:handler:constant"]
|
|
497
1025
|
|
|
498
1026
|
|
|
499
|
-
// CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_project_handler_1784235266"]
|