spine-framework 0.3.144 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (451) hide show
  1. package/.env.example +76 -0
  2. package/.framework/.spine-manifest.json +19 -0
  3. package/.framework/cli/commands/agents.ts +61 -33
  4. package/.framework/cli/commands/auth.ts +60 -28
  5. package/.framework/cli/commands/create-app.ts +212 -80
  6. package/.framework/cli/commands/dev.ts +184 -68
  7. package/.framework/cli/commands/doctor.ts +324 -152
  8. package/.framework/cli/commands/generate.ts +119 -68
  9. package/.framework/cli/commands/init.ts +141 -242
  10. package/.framework/cli/commands/install-app.ts +1336 -314
  11. package/.framework/cli/commands/items.ts +31 -29
  12. package/.framework/cli/commands/migrate.ts +299 -156
  13. package/.framework/cli/commands/migrations.ts +62 -30
  14. package/.framework/cli/commands/pipelines.ts +31 -29
  15. package/.framework/cli/commands/status.ts +105 -45
  16. package/.framework/cli/commands/system.ts +47 -42
  17. package/.framework/cli/commands/test.ts +161 -102
  18. package/.framework/cli/commands/upgrade.ts +260 -0
  19. package/.framework/cli/commands/validate-app.ts +517 -161
  20. package/.framework/cli/context.ts +117 -85
  21. package/.framework/cli/env-loader.ts +74 -43
  22. package/.framework/cli/index.ts +70 -46
  23. package/.framework/cli/lib/project-files.ts +404 -0
  24. package/.framework/docs/guides/testing-guide.md +1 -1
  25. package/.framework/docs/runtime-types.md +72 -72
  26. package/.framework/functions/_shared/access.ts +84 -0
  27. package/.framework/functions/_shared/agent-runner.ts +5051 -1026
  28. package/.framework/functions/_shared/app-manifest.ts +214 -94
  29. package/.framework/functions/_shared/ast.ts +214 -0
  30. package/.framework/functions/_shared/audit.ts +91 -55
  31. package/.framework/functions/_shared/cil.ts +368 -127
  32. package/.framework/functions/_shared/db.ts +337 -68
  33. package/.framework/functions/_shared/funnel.ts +228 -0
  34. package/.framework/functions/_shared/geo.ts +105 -0
  35. package/.framework/functions/_shared/hash-api-key.ts +94 -17
  36. package/.framework/functions/_shared/index.ts +22 -224
  37. package/.framework/functions/_shared/kb.ts +832 -58
  38. package/.framework/functions/_shared/llm.ts +118 -18
  39. package/.framework/functions/_shared/logging.ts +317 -19
  40. package/.framework/functions/_shared/middleware.ts +701 -131
  41. package/.framework/functions/_shared/notify.ts +70 -0
  42. package/.framework/functions/_shared/outcomes.ts +34 -19
  43. package/.framework/functions/_shared/permissions.ts +501 -315
  44. package/.framework/functions/_shared/pipeline-runner.ts +704 -155
  45. package/.framework/functions/_shared/principal.ts +436 -263
  46. package/.framework/functions/_shared/rate-limit.ts +233 -0
  47. package/.framework/functions/_shared/resolve-credentials.ts +86 -19
  48. package/.framework/functions/_shared/resolve-ids.ts +203 -139
  49. package/.framework/functions/_shared/retry-deliveries.ts +51 -16
  50. package/.framework/functions/_shared/schema-utils.ts +602 -521
  51. package/.framework/functions/_shared/security.ts +345 -0
  52. package/.framework/functions/_shared/testing.ts +197 -172
  53. package/.framework/functions/_shared/tracing.ts +351 -21
  54. package/.framework/functions/_shared/trigger-engine.ts +425 -136
  55. package/.framework/functions/_shared/webhook-registration.ts +71 -70
  56. package/.framework/functions/_shared/webhook-registry.ts +126 -83
  57. package/.framework/functions/account-nodes.ts +30 -30
  58. package/.framework/functions/adapters/generic-webhook-inbound.ts +49 -16
  59. package/.framework/functions/adapters/generic-webhook-outbound.ts +17 -17
  60. package/.framework/functions/adapters/openai-outbound.ts +15 -16
  61. package/.framework/functions/admin-data.ts +596 -173
  62. package/.framework/functions/admin-funnel.ts +64 -60
  63. package/.framework/functions/admin-install-funnel.ts +84 -66
  64. package/.framework/functions/admin-signals.ts +69 -51
  65. package/.framework/functions/ai-agents.ts +431 -106
  66. package/.framework/functions/ai-interactions.ts +186 -112
  67. package/.framework/functions/api-keys.ts +107 -107
  68. package/.framework/functions/apps.ts +154 -136
  69. package/.framework/functions/auth.ts +83 -65
  70. package/.framework/functions/cil-agent-ingest.ts +189 -232
  71. package/.framework/functions/cil-agent.ts +433 -177
  72. package/.framework/functions/cil-callmap.ts +642 -430
  73. package/.framework/functions/cil-config.ts +139 -135
  74. package/.framework/functions/cil-context.ts +214 -127
  75. package/.framework/functions/cil-doc.ts +587 -458
  76. package/.framework/functions/cil-embeddings.ts +453 -364
  77. package/.framework/functions/cil-graph.ts +427 -142
  78. package/.framework/functions/cil-ingest.ts +1418 -1154
  79. package/.framework/functions/cil-pipeline.ts +276 -21
  80. package/.framework/functions/cil-project.ts +659 -132
  81. package/.framework/functions/cil-validate.ts +198 -164
  82. package/.framework/functions/debug-auth.ts +57 -55
  83. package/.framework/functions/deliveries.ts +80 -21
  84. package/.framework/functions/embeddings.ts +1023 -318
  85. package/.framework/functions/eval-harness.ts +146 -108
  86. package/.framework/functions/integration-outbound.ts +205 -75
  87. package/.framework/functions/integration-routes.ts +128 -23
  88. package/.framework/functions/integrations.ts +125 -100
  89. package/.framework/functions/invites.ts +1095 -460
  90. package/.framework/functions/item-progress.ts +158 -102
  91. package/.framework/functions/kb.ts +34 -10
  92. package/.framework/functions/logs.ts +133 -133
  93. package/.framework/functions/observability.ts +152 -122
  94. package/.framework/functions/pipeline-executions.ts +147 -132
  95. package/.framework/functions/pipelines.ts +134 -119
  96. package/.framework/functions/prompt-configs.ts +96 -80
  97. package/.framework/functions/roles.ts +112 -82
  98. package/.framework/functions/security.ts +450 -0
  99. package/.framework/functions/system-cron.ts +117 -80
  100. package/.framework/functions/system.ts +158 -98
  101. package/.framework/functions/tests.ts +29 -29
  102. package/.framework/functions/timers.ts +94 -95
  103. package/.framework/functions/trigger-scheduler.ts +10 -0
  104. package/.framework/functions/triggers.ts +179 -149
  105. package/.framework/functions/types.ts +137 -125
  106. package/.framework/mcp/index.ts +133 -0
  107. package/.framework/mcp/load-env.ts +60 -0
  108. package/.framework/mcp/shared/app-manifest.ts +275 -0
  109. package/.framework/mcp/shared/db.ts +477 -0
  110. package/.framework/mcp/shared/kb.ts +118 -0
  111. package/.framework/mcp/tools/architect.ts +431 -0
  112. package/.framework/mcp/tools/cil/context.ts +345 -0
  113. package/.framework/mcp/tools/cil/graph.ts +242 -0
  114. package/.framework/mcp/tools/cil/ingest.ts +1217 -0
  115. package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +693 -0
  116. package/.framework/mcp/tools/cil/pipeline.ts +767 -0
  117. package/.framework/mcp/tools/cil/project.ts +791 -0
  118. package/.framework/mcp/tools/cil/retrieval.ts +336 -0
  119. package/.framework/mcp/tools/cil/search-core.ts +454 -0
  120. package/.framework/mcp/tools/cil/search.ts +97 -0
  121. package/.framework/mcp/tools/cil/suggest.ts +186 -0
  122. package/.framework/mcp/tools/cil/validate.ts +1369 -0
  123. package/.framework/mcp/tools/kb/delete.ts +139 -0
  124. package/.framework/mcp/tools/kb/index.ts +52 -0
  125. package/.framework/mcp/tools/kb/ingest.ts +84 -0
  126. package/.framework/mcp/tools/kb/list-types.ts +102 -0
  127. package/.framework/mcp/tools/kb/publish.ts +100 -0
  128. package/.framework/mcp/tools/kb/reindex.ts +86 -0
  129. package/.framework/mcp/tools/kb/revoke.ts +85 -0
  130. package/.framework/mcp/tools/kb/search.ts +101 -0
  131. package/.framework/mcp/tools/kb/upsert.ts +125 -0
  132. package/.framework/mcp/tools/observability.ts +510 -0
  133. package/.framework/migrations/001_core_schema.sql +15 -0
  134. package/.framework/migrations/002_core_rls_and_functions.sql +15 -0
  135. package/.framework/migrations/003_core_system_data.sql +16 -1
  136. package/.framework/migrations/004_core_rpc_and_broker.sql +17 -1
  137. package/.framework/migrations/005_core_observability.sql +17 -1
  138. package/.framework/migrations/006_security_hardening_rls.sql +15 -0
  139. package/.framework/migrations/007_kb_article_list.sql +17 -1
  140. package/.framework/migrations/008_items_target.sql +15 -0
  141. package/.framework/migrations/009_roles_slug_unique.sql +15 -0
  142. package/.framework/migrations/010_auth_user_trigger.sql +15 -0
  143. package/.framework/migrations/011_spine_system_account.sql +16 -0
  144. package/.framework/migrations/012_service_role_grants.sql +16 -0
  145. package/.framework/migrations/013_get_account_apps_role_filter.sql +15 -0
  146. package/.framework/migrations/014_apps_required_roles.sql +16 -0
  147. package/.framework/migrations/015_types_kind_slug_unique.sql +20 -0
  148. package/.framework/migrations/016_cil_types.sql +281 -0
  149. package/.framework/migrations/017_cil_stable_ids.sql +37 -0
  150. package/.framework/migrations/018_runtime_tables.sql +129 -0
  151. package/.framework/migrations/019_agent_prompt_columns.sql +56 -0
  152. package/.framework/migrations/020_schema_reconciliation.sql +67 -0
  153. package/.framework/migrations/021_kb_embedding_lifecycle.sql +31 -0
  154. package/.framework/migrations/032_cil_status_migration.sql +73 -0
  155. package/.framework/migrations/033_cil_versioning.sql +73 -0
  156. package/.framework/migrations/034_match_embeddings_knn.sql +115 -0
  157. package/.framework/migrations/035_rate_limits.sql +55 -0
  158. package/.framework/migrations/036_demo_record_flags.sql +72 -0
  159. package/.framework/migrations/037_kb_types_canonical.sql +244 -0
  160. package/.framework/migrations/038_drop_demo_record_flags.sql +38 -0
  161. package/.framework/migrations/042_registration_hierarchy.sql +309 -0
  162. package/.framework/migrations/043_policy_actor_cleanup.sql +39 -0
  163. package/.framework/migrations/044_match_embeddings_filtered_knn.sql +151 -0
  164. package/.framework/migrations/045_security_critical_rls.sql +139 -0
  165. package/.framework/migrations/046_security_missing_rls.sql +79 -0
  166. package/.framework/migrations/047_people_updated_by.sql +27 -0
  167. package/.framework/migrations/048_watcher_last_seen_at.sql +24 -0
  168. package/.framework/migrations/049_security_blocklist.sql +148 -0
  169. package/.framework/migrations/050_notifications.sql +49 -0
  170. package/.framework/migrations/051_message_agent_fields.sql +74 -0
  171. package/.framework/migrations/052_registration_security.sql +421 -0
  172. package/.framework/migrations/053_builtin_action_seeds.sql +66 -0
  173. package/.framework/migrations/054_kb_ingest_lease.sql +157 -0
  174. package/.framework/migrations/055_type_id_drift_reconciliation.sql +33 -0
  175. package/.framework/migrations/056_slug_column_reconciliation.sql +38 -0
  176. package/.framework/migrations/057_pipelines_slug_identity.sql +14 -0
  177. package/.framework/migrations/058_account_data_field_declarations.sql +53 -0
  178. package/.framework/migrations/059_registration_placement_fixes.sql +269 -0
  179. package/.framework/migrations/060_account_person_record_permissions.sql +38 -0
  180. package/.framework/migrations/061_fk_dedup.sql +32 -0
  181. package/.framework/public/spine-logo.svg +10 -3
  182. package/.framework/scripts/app-install-cli.ts +190 -93
  183. package/.framework/scripts/assemble-frontend.sh +127 -44
  184. package/.framework/scripts/assemble-functions.sh +128 -30
  185. package/.framework/scripts/boundary-check.sh +6 -2
  186. package/.framework/scripts/build-manifest.sh +24 -68
  187. package/.framework/scripts/check-core-integrity.sh +15 -76
  188. package/.framework/scripts/checksum-manifest.mts +343 -0
  189. package/.framework/scripts/cil-migrate-markers.ts +403 -0
  190. package/.framework/scripts/fix-cil-markers.mjs +176 -0
  191. package/.framework/scripts/verify-integrity.sh +21 -57
  192. package/.framework/scripts/verify-manifest.mts +305 -0
  193. package/.framework/seeds/types/funnel_signal_use.json +74 -21
  194. package/.framework/seeds/types/spine_instance.json +73 -21
  195. package/.framework/src/App.tsx +118 -72
  196. package/.framework/src/apps/admin/index.tsx +855 -58
  197. package/.framework/src/components/AppWrapper.tsx +43 -45
  198. package/.framework/src/components/CustomAppLoader.tsx +160 -116
  199. package/.framework/src/components/admin/AdminListPage.tsx +46 -44
  200. package/.framework/src/components/admin/AdminSidebar.tsx +57 -47
  201. package/.framework/src/components/admin/AdminStatsCard.tsx +46 -44
  202. package/.framework/src/components/admin/PageInstructions.tsx +98 -2
  203. package/.framework/src/components/admin/SortableTableHeader.tsx +44 -45
  204. package/.framework/src/components/app-shell/GenericAppShell.tsx +64 -65
  205. package/.framework/src/components/app-shell/GenericDetailPage.tsx +44 -47
  206. package/.framework/src/components/app-shell/GenericListPage.tsx +45 -49
  207. package/.framework/src/components/app-sidebar.tsx +42 -45
  208. package/.framework/src/components/auth/ProtectedRoute.tsx +48 -41
  209. package/.framework/src/components/auth/TurnstileWidget.tsx +27 -0
  210. package/.framework/src/components/kb/KBArticleEditor.tsx +231 -22
  211. package/.framework/src/components/kb/KBArticleList.tsx +251 -10
  212. package/.framework/src/components/layout/AppShell.tsx +51 -45
  213. package/.framework/src/components/layout/Header.tsx +42 -43
  214. package/.framework/src/components/layout/Layout.tsx +46 -46
  215. package/.framework/src/components/layout/Sidebar.tsx +196 -96
  216. package/.framework/src/components/runtime/DataDetailHeader.tsx +55 -30
  217. package/.framework/src/components/runtime/DataDetailPage.tsx +31 -269
  218. package/.framework/src/components/runtime/DataFilters.tsx +49 -74
  219. package/.framework/src/components/runtime/DataHeader.tsx +53 -32
  220. package/.framework/src/components/runtime/DataListPage.tsx +51 -155
  221. package/.framework/src/components/runtime/DataStats.tsx +66 -44
  222. package/.framework/src/components/runtime/DataTable.tsx +49 -149
  223. package/.framework/src/components/runtime/SchemaDetailForm.tsx +45 -75
  224. package/.framework/src/components/runtime/index.ts +119 -16
  225. package/.framework/src/components/search-form.tsx +46 -29
  226. package/.framework/src/components/shared/AgentView.tsx +65 -48
  227. package/.framework/src/components/shared/FieldRenderer.tsx +144 -50
  228. package/.framework/src/components/shared/InviteManager.tsx +207 -97
  229. package/.framework/src/components/shared/MemberList.tsx +97 -0
  230. package/.framework/src/components/shared/SchemaFields.tsx +107 -86
  231. package/.framework/src/components/ui/DataTable.tsx +80 -68
  232. package/.framework/src/components/ui/Form.tsx +157 -146
  233. package/.framework/src/components/ui/ItemCard.tsx +74 -67
  234. package/.framework/src/components/ui/ItemListView.tsx +73 -68
  235. package/.framework/src/components/ui/LoadingSpinner.tsx +43 -48
  236. package/.framework/src/components/ui/Modal.tsx +78 -68
  237. package/.framework/src/components/ui/RichTextEditor.tsx +89 -69
  238. package/.framework/src/components/ui/accordion.tsx +85 -86
  239. package/.framework/src/components/ui/alert-dialog.tsx +197 -184
  240. package/.framework/src/components/ui/alert.tsx +105 -94
  241. package/.framework/src/components/ui/aspect-ratio.tsx +57 -43
  242. package/.framework/src/components/ui/avatar.tsx +122 -107
  243. package/.framework/src/components/ui/badge.tsx +60 -55
  244. package/.framework/src/components/ui/breadcrumb.tsx +127 -128
  245. package/.framework/src/components/ui/button-group.tsx +86 -72
  246. package/.framework/src/components/ui/button.tsx +71 -50
  247. package/.framework/src/components/ui/calendar.tsx +72 -57
  248. package/.framework/src/components/ui/card.tsx +136 -129
  249. package/.framework/src/components/ui/carousel.tsx +226 -107
  250. package/.framework/src/components/ui/chart.tsx +252 -147
  251. package/.framework/src/components/ui/checkbox.tsx +43 -44
  252. package/.framework/src/components/ui/collapsible.tsx +86 -71
  253. package/.framework/src/components/ui/combobox.tsx +282 -249
  254. package/.framework/src/components/ui/command.tsx +158 -146
  255. package/.framework/src/components/ui/context-menu.tsx +239 -240
  256. package/.framework/src/components/ui/dialog.tsx +174 -157
  257. package/.framework/src/components/ui/direction.tsx +72 -56
  258. package/.framework/src/components/ui/drawer.tsx +168 -169
  259. package/.framework/src/components/ui/dropdown-menu.tsx +254 -223
  260. package/.framework/src/components/ui/empty.tsx +131 -120
  261. package/.framework/src/components/ui/field.tsx +205 -173
  262. package/.framework/src/components/ui/hover-card.tsx +71 -72
  263. package/.framework/src/components/ui/input-group.tsx +148 -133
  264. package/.framework/src/components/ui/input-otp.tsx +99 -86
  265. package/.framework/src/components/ui/input.tsx +43 -41
  266. package/.framework/src/components/ui/item.tsx +207 -185
  267. package/.framework/src/components/ui/kbd.tsx +57 -56
  268. package/.framework/src/components/ui/label.tsx +45 -41
  269. package/.framework/src/components/ui/menubar.tsx +268 -236
  270. package/.framework/src/components/ui/native-select.tsx +85 -86
  271. package/.framework/src/components/ui/navigation-menu.tsx +166 -156
  272. package/.framework/src/components/ui/pagination.tsx +131 -141
  273. package/.framework/src/components/ui/popover.tsx +125 -128
  274. package/.framework/src/components/ui/progress.tsx +47 -44
  275. package/.framework/src/components/ui/radio-group.tsx +60 -55
  276. package/.framework/src/components/ui/resizable.tsx +85 -72
  277. package/.framework/src/components/ui/scroll-area.tsx +57 -58
  278. package/.framework/src/components/ui/select.tsx +182 -169
  279. package/.framework/src/components/ui/separator.tsx +42 -43
  280. package/.framework/src/components/ui/sheet.tsx +170 -159
  281. package/.framework/src/components/ui/sidebar.tsx +395 -398
  282. package/.framework/src/components/ui/skeleton.tsx +42 -43
  283. package/.framework/src/components/ui/slider.tsx +61 -44
  284. package/.framework/src/components/ui/sonner.tsx +44 -44
  285. package/.framework/src/components/ui/spinner.tsx +47 -42
  286. package/.framework/src/components/ui/switch.tsx +56 -42
  287. package/.framework/src/components/ui/table-primitives.tsx +272 -132
  288. package/.framework/src/components/ui/table.tsx +140 -142
  289. package/.framework/src/components/ui/tabs.tsx +110 -93
  290. package/.framework/src/components/ui/textarea.tsx +43 -44
  291. package/.framework/src/components/ui/toggle-group.tsx +87 -71
  292. package/.framework/src/components/ui/toggle.tsx +56 -56
  293. package/.framework/src/components/ui/tooltip.tsx +99 -85
  294. package/.framework/src/contexts/AppContext.tsx +166 -114
  295. package/.framework/src/contexts/AuthContext.tsx +232 -137
  296. package/.framework/src/hooks/use-mobile.ts +43 -44
  297. package/.framework/src/hooks/useApi.ts +185 -172
  298. package/.framework/src/hooks/useAppPath.ts +31 -29
  299. package/.framework/src/hooks/useApps.ts +77 -42
  300. package/.framework/src/hooks/useEntityList.ts +66 -29
  301. package/.framework/src/hooks/useEntityRecord.ts +76 -32
  302. package/.framework/src/hooks/useForm.ts +62 -30
  303. package/.framework/src/hooks/useListSchema.ts +60 -43
  304. package/.framework/src/hooks/useSchemaRecord.ts +115 -95
  305. package/.framework/src/lib/api.ts +258 -134
  306. package/.framework/src/lib/registration.ts +181 -0
  307. package/.framework/src/lib/supabase.ts +118 -81
  308. package/.framework/src/lib/utils.ts +266 -266
  309. package/.framework/src/main.tsx +43 -44
  310. package/.framework/src/pages/DashboardPage.tsx +44 -43
  311. package/.framework/src/pages/NoAppPage.tsx +50 -0
  312. package/.framework/src/pages/NotFoundPage.tsx +32 -29
  313. package/.framework/src/pages/SetupPage.tsx +34 -33
  314. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +69 -58
  315. package/.framework/src/pages/admin/AIAgentsPage.tsx +43 -40
  316. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +63 -55
  317. package/.framework/src/pages/admin/APIKeysPage.tsx +44 -42
  318. package/.framework/src/pages/admin/AlertsConfigPage.tsx +117 -94
  319. package/.framework/src/pages/admin/AppDetailPage.tsx +48 -42
  320. package/.framework/src/pages/admin/AppsPage.tsx +45 -42
  321. package/.framework/src/pages/admin/DeliveriesPage.tsx +49 -17
  322. package/.framework/src/pages/admin/DesignedPage.tsx +31 -30
  323. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +58 -0
  324. package/.framework/src/pages/admin/EmbeddingsPage.tsx +49 -0
  325. package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +31 -29
  326. package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +46 -29
  327. package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -29
  328. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +68 -55
  329. package/.framework/src/pages/admin/IntegrationsPage.tsx +45 -42
  330. package/.framework/src/pages/admin/InvitesPage.tsx +60 -44
  331. package/.framework/src/pages/admin/LogsPage.tsx +87 -137
  332. package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +31 -29
  333. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +150 -89
  334. package/.framework/src/pages/admin/PipelineDetailPage.tsx +77 -104
  335. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +44 -43
  336. package/.framework/src/pages/admin/PipelinesPage.tsx +59 -145
  337. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +53 -42
  338. package/.framework/src/pages/admin/PromptConfigsPage.tsx +47 -117
  339. package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +31 -44
  340. package/.framework/src/pages/admin/RoleDetailPage.tsx +49 -92
  341. package/.framework/src/pages/admin/RolesPage.tsx +47 -164
  342. package/.framework/src/pages/admin/SecurityPage.tsx +310 -0
  343. package/.framework/src/pages/admin/SelectTestPage.tsx +30 -32
  344. package/.framework/src/pages/admin/ShadcnTestPage.tsx +37 -44
  345. package/.framework/src/pages/admin/SimpleDashboard.tsx +32 -44
  346. package/.framework/src/pages/admin/TestRunDetailPage.tsx +97 -44
  347. package/.framework/src/pages/admin/TestingDashboard.tsx +126 -71
  348. package/.framework/src/pages/admin/TimerDetailPage.tsx +67 -55
  349. package/.framework/src/pages/admin/TimersPage.tsx +44 -42
  350. package/.framework/src/pages/admin/TriggerDetailPage.tsx +47 -42
  351. package/.framework/src/pages/admin/TriggersPage.tsx +58 -57
  352. package/.framework/src/pages/admin/TypeDetailPage.tsx +91 -55
  353. package/.framework/src/pages/admin/TypesPage.tsx +45 -42
  354. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +258 -128
  355. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +127 -123
  356. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +308 -235
  357. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +159 -110
  358. package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +432 -0
  359. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +200 -178
  360. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +286 -239
  361. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +211 -90
  362. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +156 -143
  363. package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +379 -0
  364. package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +337 -0
  365. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +219 -214
  366. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
  367. package/.framework/src/pages/auth/AuthConfirmPage.tsx +135 -65
  368. package/.framework/src/pages/auth/ForgotPasswordPage.tsx +39 -31
  369. package/.framework/src/pages/auth/LoginPage.tsx +38 -32
  370. package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -28
  371. package/.framework/src/pages/auth/RegisterPage.tsx +429 -155
  372. package/.framework/src/pages/spine-framework/APIPage.tsx +33 -30
  373. package/.framework/src/pages/spine-framework/CLIPage.tsx +32 -30
  374. package/.framework/src/types/auth.ts +101 -93
  375. package/.framework/src/types/types.ts +283 -262
  376. package/.framework/templates/project.json +87 -0
  377. package/.framework/templates/spine.config.neutral.json +7 -0
  378. package/.framework/tests/api/api-surface.test.ts +381 -0
  379. package/.framework/tests/fixtures/seed.ts +427 -0
  380. package/.framework/tests/fixtures/teardown.ts +228 -0
  381. package/.framework/tests/reporter.ts +351 -0
  382. package/.framework/tests/setup.ts +135 -0
  383. package/.framework/tests/ui/ui-sweep.ts +278 -0
  384. package/.framework/tests/unit/admin-data-logger.test.ts +310 -0
  385. package/.framework/tests/unit/agent-runner.test.ts +2389 -0
  386. package/.framework/tests/unit/ai-interactions.test.ts +81 -0
  387. package/.framework/tests/unit/app-manifest.test.ts +359 -0
  388. package/.framework/tests/unit/assembly-scripts.test.ts +172 -0
  389. package/.framework/tests/unit/cil-determinism.test.ts +85 -0
  390. package/.framework/tests/unit/core-isolation.test.ts +153 -0
  391. package/.framework/tests/unit/funnel-signals.test.ts +135 -0
  392. package/.framework/tests/unit/install-app.test.ts +1759 -0
  393. package/.framework/tests/unit/invites-security.test.ts +572 -0
  394. package/.framework/tests/unit/kb-ingest-lease.test.ts +287 -0
  395. package/.framework/tests/unit/kb-search.test.ts +119 -0
  396. package/.framework/tests/unit/migrate.test.ts +509 -0
  397. package/.framework/tests/unit/notify.test.ts +136 -0
  398. package/.framework/tests/unit/permissions.test.ts +269 -0
  399. package/.framework/tests/unit/pipeline-runner.test.ts +755 -0
  400. package/.framework/tests/unit/principal-cache.test.ts +138 -0
  401. package/.framework/tests/unit/retrieval-golden.test.ts +520 -0
  402. package/.framework/tests/unit/runtime-isolation.test.ts +642 -0
  403. package/.framework/tests/unit/schema-utils.test.ts +225 -0
  404. package/.framework/tests/unit/trigger-engine.test.ts +513 -0
  405. package/.framework/tests/unit/validate-app.test.ts +527 -0
  406. package/README.md +34 -3
  407. package/bin/spine-framework.cjs +1 -0
  408. package/config/tailwind.config.cjs +7 -0
  409. package/config/tsconfig.functions.json +42 -0
  410. package/config/tsconfig.json +37 -9
  411. package/config/vite.config.ts +31 -2
  412. package/netlify.toml +31 -3
  413. package/package.json +46 -29
  414. package/scripts/assemble-frontend.sh +127 -44
  415. package/scripts/assemble-functions.sh +127 -29
  416. package/scripts/boundary-check.sh +6 -2
  417. package/scripts/build-manifest.sh +24 -68
  418. package/scripts/checksum-manifest.mts +345 -0
  419. package/scripts/dev-clean.sh +86 -0
  420. package/scripts/dev-netlify.sh +49 -0
  421. package/scripts/netlify-dev-wrapper.sh +2 -0
  422. package/scripts/verify-install.ts +358 -0
  423. package/scripts/verify-integrity.sh +21 -57
  424. package/scripts/verify-manifest.mts +305 -0
  425. package/templates/project/gitignore +45 -0
  426. package/{config → templates/project}/package-lock.json +22335 -9366
  427. package/vitest.config.ts +46 -0
  428. package/.framework/public/spine.config.json +0 -91
  429. package/config/deno.lock +0 -108
  430. package/config/tsconfig.node.tsbuildinfo +0 -1
  431. package/config/tsconfig.tsbuildinfo +0 -1
  432. package/config/vite.config.d.ts +0 -2
  433. package/custom/.devin/AGENT.md +0 -357
  434. package/custom/.devin/skills/install-app/SKILL.md +0 -39
  435. package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +0 -39
  436. package/custom/.devin/skills/spine-workbench-idea/SKILL.md +0 -36
  437. package/custom/.devin/skills/spine-workbench-implement/SKILL.md +0 -46
  438. package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +0 -28
  439. package/custom/.devin/skills/spine-workbench-plan/SKILL.md +0 -38
  440. package/custom/.devin/workflows/app-install.yaml +0 -83
  441. package/custom/README.md +0 -79
  442. package/docs/README.md +0 -15
  443. package/scripts/app-install-cli.ts +0 -286
  444. package/scripts/check-core-integrity.sh +0 -82
  445. package/scripts/ingest-chunks.cjs +0 -202
  446. package/scripts/kb-chunk-parser.cjs +0 -312
  447. package/scripts/kb-chunk-parser.ts +0 -330
  448. package/scripts/kb-ingest-docs.ts +0 -203
  449. package/scripts/load-test-app-install.ts +0 -484
  450. package/scripts/test-login.js +0 -33
  451. package/spine.config.json +0 -91
@@ -0,0 +1,85 @@
1
+ // CIL[BEGIN stable_id="~/.framework/tests/unit/cil-determinism.test.ts:module_header:module_header" type="module_header" identity="module_header" parent="none"]
2
+ // CIL[DOC-MACRO purpose="Unit tests for CIL deterministic identity and content hashing utilities"]
3
+ // CIL[DOC-RESPONSIBILITY responsibility="Provide test coverage for CIL stable identity generation and content hash normalization"]
4
+ // CIL[DOC-CONTEXT module="cil-determinism.test.ts" layer="tests" related_files=".framework/functions/_shared/cil.ts"]
5
+ // CIL[DOC-CONTRACT inputs="vitest describe/it/expect, cil.ts computeContentHash/generateStableId/parseStableId" outputs="Passing unit test assertions" errors="AssertionError on deterministic/round-trip/hash mismatch failures" side_effects="none"]
6
+ // CIL[DOC-MICRO logic_summary="Imports utilities and sets up a Vitest test module" notable_decisions="[]"]
7
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
+ // CIL[DOC-STABILITY stability="stable"]
9
+ // CIL[DOC-AUDIENCE audience="test maintainers"]
10
+ import { describe, it, expect } from 'vitest'
11
+ import { computeContentHash, generateStableId, parseStableId } from '../../functions/_shared/cil.ts'
12
+ // CIL[DOC-VECTOR type="context" content="purpose='Unit tests for CIL deterministic identity and content hashing utilities'; No verified external callers; imports: .framework/functions/_shared/cil.ts"]
13
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
14
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
15
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
16
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
17
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
18
+ // CIL[END stable_id="~/.framework/tests/unit/cil-determinism.test.ts:module_header:module_header"]
19
+
20
+ // CIL[BEGIN stable_id="~/.framework/tests/unit/cil-determinism.test.ts:describe_cil_stable_identity:block" type="block" identity="describe_cil_stable_identity" parent="none"]
21
+ // CIL[DOC-MACRO purpose="Verify stable id generation and parsing are deterministic"]
22
+ // CIL[DOC-RESPONSIBILITY responsibility="Assert generateStableId and parseStableId behave predictably"]
23
+ // CIL[DOC-CONTEXT module="cil-determinism.test.ts" layer="tests" related_files=".framework/functions/_shared/cil.ts,.framework/tests/unit/cil-determinism.test.ts"]
24
+ // CIL[DOC-CONTRACT inputs="file path, identity, and type strings; stable id strings" outputs="Stable id string; parsed stable id object" errors="AssertionError if output does not match expected deterministic id or object" side_effects="none"]
25
+ // CIL[DOC-MICRO logic_summary="Tests deterministic stable id formatting and round-trip parsing" notable_decisions="[]"]
26
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
27
+ // CIL[DOC-STABILITY stability="stable"]
28
+ describe('CIL stable identity', () => {
29
+ it('generateStableId produces deterministic stable ids', () => {
30
+ expect(generateStableId('~/.framework/functions/auth.ts', 'getAccount', 'function'))
31
+ .toBe('~/.framework/functions/auth.ts:getAccount:function')
32
+ })
33
+
34
+ it('parseStableId round-trips stable ids', () => {
35
+ const id = generateStableId('~/.framework/functions/auth.ts', 'getAccount', 'function')
36
+ expect(parseStableId(id)).toEqual({
37
+ canonicalPath: '~/.framework/functions/auth.ts',
38
+ identity: 'getAccount',
39
+ type: 'function',
40
+ })
41
+ })
42
+ })
43
+ // CIL[DOC-VECTOR type="context" content="purpose='Verify stable id generation and parsing are deterministic'; No verified external callers; imports: .framework/functions/_shared/cil.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"]
49
+ // CIL[END stable_id="~/.framework/tests/unit/cil-determinism.test.ts:describe_cil_stable_identity:block"]
50
+
51
+ // CIL[BEGIN stable_id="~/.framework/tests/unit/cil-determinism.test.ts:describe_cil_content_hash:block" type="block" identity="describe_cil_content_hash" parent="none"]
52
+ // CIL[DOC-MACRO purpose="Verify content hash is deterministic and normalizes CIL markers"]
53
+ // CIL[DOC-RESPONSIBILITY responsibility="Assert computeContentHash produces consistent hashes and ignores CIL markers/blank lines"]
54
+ // CIL[DOC-CONTEXT module="cil-determinism.test.ts" layer="tests" related_files=".framework/functions/_shared/cil.ts,.framework/tests/unit/cil-determinism.test.ts"]
55
+ // CIL[DOC-CONTRACT inputs="JavaScript function source strings" outputs="32-character hexadecimal hash string" errors="AssertionError on hash mismatch or non-hex output" side_effects="none"]
56
+ // CIL[DOC-MICRO logic_summary="Tests hash determinism, CIL marker stripping, and sensitivity to code changes" notable_decisions="[]"]
57
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
58
+ // CIL[DOC-STABILITY stability="stable"]
59
+ describe('CIL content_hash', () => {
60
+ it('computeContentHash is deterministic for identical inputs', () => {
61
+ const h1 = computeContentHash('function foo() { return 1 }')
62
+ const h2 = computeContentHash('function foo() { return 1 }')
63
+ expect(h1).toBe(h2)
64
+ expect(h1).toMatch(/^[0-9a-f]{32}$/)
65
+ })
66
+
67
+ it('computeContentHash normalizes away CIL markers and blank lines', () => {
68
+ const withCil = '// CIL[BEGIN]\nfunction foo() { return 1 }\n// CIL[END]\n\n'
69
+ const without = 'function foo() { return 1 }'
70
+ expect(computeContentHash(withCil)).toBe(computeContentHash(without))
71
+ })
72
+
73
+ it('computeContentHash changes when code changes', () => {
74
+ const h1 = computeContentHash('function foo() { return 1 }')
75
+ const h2 = computeContentHash('function foo() { return 2 }')
76
+ expect(h1).not.toBe(h2)
77
+ })
78
+ })
79
+ // CIL[DOC-VECTOR type="context" content="purpose='Verify content hash is deterministic and normalizes CIL markers'; No verified external callers; imports: .framework/functions/_shared/cil.ts"]
80
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
81
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
82
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
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
+ // CIL[END stable_id="~/.framework/tests/unit/cil-determinism.test.ts:describe_cil_content_hash:block"]
@@ -0,0 +1,153 @@
1
+ // CIL[BEGIN stable_id="~/.framework/tests/unit/core-isolation.test.ts:module_header:module_header" type="module_header" identity="module_header" parent="none"]
2
+ // CIL[DOC-MACRO purpose="Test setup and imports for core isolation tests"]
3
+ // CIL[DOC-RESPONSIBILITY responsibility="Configure test environment for core isolation"]
4
+ // CIL[DOC-CONTEXT module="tests/unit/core-isolation" layer="test-unit" related_files=".framework/functions/_shared/app-manifest.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/webhook-registry.ts"]
5
+ // CIL[DOC-CONTRACT inputs="none" outputs="test imports" errors="none" side_effects="Imports vitest and core modules"]
6
+ // CIL[DOC-MICRO logic_summary="Imports vitest, db, webhook-registry, app-manifest, and middleware" notable_decisions="[]"]
7
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
+ // CIL[DOC-STABILITY stability="stable"]
9
+ // CIL[DOC-AUDIENCE audience="developers"]
10
+ import { describe, it, expect, beforeAll } from 'vitest'
11
+ import { adminDb } from '../../functions/_shared/db'
12
+ import { resolveHandler, lookupHandler } from '../../functions/_shared/webhook-registry'
13
+ import { loadManifest, discoverManifests } from '../../functions/_shared/app-manifest'
14
+ import { createHandler } from '../../functions/_shared/middleware'
15
+ // CIL[DOC-VECTOR type="context" content="purpose='Test setup and imports for core isolation tests'; No verified external callers; imports: .framework/functions/_shared/db.ts,.framework/functions/_shared/webhook-registry.ts,.framework/functions/_shared/app-manifest.ts"]
16
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
17
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
18
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
19
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
20
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
21
+ // CIL[END stable_id="~/.framework/tests/unit/core-isolation.test.ts:module_header:module_header"]
22
+
23
+ // CIL[BEGIN stable_id="~/.framework/tests/unit/core-isolation.test.ts:describe_CoreIsolation:block" type="block" identity="describe_CoreIsolation" parent="none"]
24
+ // CIL[DOC-MACRO purpose="Test core functionality works without custom code"]
25
+ // CIL[DOC-RESPONSIBILITY responsibility="Verify core independence from custom code"]
26
+ // CIL[DOC-CONTEXT module="tests/unit/core-isolation" layer="test-unit" related_files=".framework/functions/_shared/app-manifest.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/webhook-registry.ts,.framework/tests/unit/core-isolation.test.ts"]
27
+ // CIL[DOC-CONTRACT inputs="none" outputs="test assertions" errors="none" side_effects="Tests core modules"]
28
+ // CIL[DOC-MICRO logic_summary="Tests webhook registry, app manifests, DB access, handler creation, and permissions" notable_decisions="[]"]
29
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
30
+ // CIL[DOC-STABILITY stability="stable"]
31
+ describe('Core Isolation', () => {
32
+ describe('Webhook Registry', () => {
33
+ it('should have empty registry when no custom handlers registered', async () => {
34
+ const handlers = await lookupHandler('non-existent-handler')
35
+ expect(handlers).toBeNull()
36
+ })
37
+
38
+ it('should fail gracefully when resolving unknown handler', async () => {
39
+ const handler = await resolveHandler('unknown-handler')
40
+ expect(handler).toBeNull()
41
+ })
42
+
43
+ it('should not depend on custom_webhook-handlers.ts', async () => {
44
+ const registry = await import('../../functions/_shared/webhook-registry')
45
+ expect(registry.resolveHandler).toBeDefined()
46
+ expect(registry.lookupHandler).toBeDefined()
47
+ expect(registry.loadHandler).toBeDefined()
48
+ })
49
+ })
50
+
51
+ describe('App Manifest System', () => {
52
+ it('should discover manifests without error', () => {
53
+ const manifests = discoverManifests()
54
+ expect(Array.isArray(manifests)).toBe(true)
55
+ })
56
+
57
+ it('should handle missing manifest gracefully', () => {
58
+ const manifest = loadManifest('non/existent/manifest.json')
59
+ expect(manifest).toBeNull()
60
+ })
61
+
62
+ it('should load valid manifest if exists', () => {
63
+ const manifest = loadManifest('custom/apps/cortex/manifest.json')
64
+ if (manifest) {
65
+ expect(manifest.slug).toBeDefined()
66
+ expect(manifest.name).toBeDefined()
67
+ expect(Array.isArray(manifest.required_roles)).toBe(true)
68
+ }
69
+ })
70
+ })
71
+
72
+ // Live-DB probes — only meaningful when real credentials are configured
73
+ // (`.env.test` in the monorepo). The setup file stubs a placeholder URL for
74
+ // unit runs; hitting it would produce a fetch error, so gate on the stub.
75
+ const LIVE_DB =
76
+ !!process.env.SUPABASE_URL && !process.env.SUPABASE_URL.includes('test.supabase.co')
77
+
78
+ describe.runIf(LIVE_DB)('Database Access', () => {
79
+ it('should connect to database without custom code', async () => {
80
+ const { data, error } = await adminDb.from('accounts').select('id').limit(1)
81
+ expect(error).toBeNull()
82
+ })
83
+
84
+ it('should query apps without custom dependencies', async () => {
85
+ const { data, error } = await adminDb
86
+ .from('apps')
87
+ .select('slug, name, is_active')
88
+ .limit(1)
89
+
90
+ expect(error).toBeNull()
91
+ expect(Array.isArray(data) || data === null).toBe(true)
92
+ })
93
+ })
94
+
95
+ describe('Handler Creation', () => {
96
+ it('should create handler without custom imports', () => {
97
+ const handler = createHandler(async (event, ctx) => {
98
+ return { status: 'ok' }
99
+ })
100
+
101
+ expect(handler).toBeDefined()
102
+ expect(typeof handler).toBe('function')
103
+ })
104
+ })
105
+
106
+ describe('Permission System', () => {
107
+ it('should check permissions without custom code', async () => {
108
+ const { isSystemAdmin } = await import('../../functions/_shared/permissions')
109
+
110
+ const memberCtx = { principal: { id: 'test-user', account_id: 'test-account', roles: [] } }
111
+ const adminCtx = { principal: { id: 'admin-user', account_id: 'test-account', roles: [{ slug: 'system_admin' }] } }
112
+
113
+ expect(isSystemAdmin(memberCtx as any)).toBe(false)
114
+ expect(isSystemAdmin(adminCtx as any)).toBe(true)
115
+ })
116
+ })
117
+ })
118
+ // CIL[DOC-VECTOR type="context" content="purpose='Test core functionality works without custom code'; No verified external callers; imports: .framework/functions/_shared/db.ts,.framework/functions/_shared/webhook-registry.ts,.framework/functions/_shared/app-manifest.ts"]
119
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
120
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
121
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
122
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
123
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
124
+ // CIL[END stable_id="~/.framework/tests/unit/core-isolation.test.ts:describe_CoreIsolation:block"]
125
+
126
+ // CIL[BEGIN stable_id="~/.framework/tests/unit/core-isolation.test.ts:describe_NoCoreCustomImports:block" type="block" identity="describe_NoCoreCustomImports" parent="none"]
127
+ // CIL[DOC-MACRO purpose="Test core files don't import custom code"]
128
+ // CIL[DOC-RESPONSIBILITY responsibility="Verify static import boundaries"]
129
+ // CIL[DOC-CONTEXT module="tests/unit/core-isolation" layer="test-unit" related_files=".framework/functions/_shared/app-manifest.ts,.framework/functions/_shared/db.ts,.framework/functions/_shared/middleware.ts,.framework/functions/_shared/webhook-registry.ts,.framework/tests/unit/core-isolation.test.ts"]
130
+ // CIL[DOC-CONTRACT inputs="none" outputs="test assertions" errors="none" side_effects="Conceptual test only"]
131
+ // CIL[DOC-MICRO logic_summary="Documents expected clean files without actual file reading" notable_decisions="[]"]
132
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
133
+ // CIL[DOC-STABILITY stability="stable"]
134
+ describe('No Core→Custom Imports', () => {
135
+ it('should verify no static imports from custom/', async () => {
136
+ const expectedCleanFiles = [
137
+ '.framework/functions/integration-routes.ts',
138
+ '.framework/functions/apps.ts',
139
+ '.framework/src/hooks/useApps.ts'
140
+ ]
141
+
142
+ expectedCleanFiles.forEach(file => {
143
+ expect(file).toContain('.framework/')
144
+ })
145
+ })
146
+ })
147
+ // CIL[DOC-VECTOR type="context" content="purpose='Test core files don't import custom code'; No verified external callers; imports: .framework/functions/_shared/db.ts,.framework/functions/_shared/webhook-registry.ts,.framework/functions/_shared/app-manifest.ts"]
148
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
149
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
150
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
151
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
152
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
153
+ // CIL[END stable_id="~/.framework/tests/unit/core-isolation.test.ts:describe_NoCoreCustomImports:block"]
@@ -0,0 +1,135 @@
1
+ // CIL[DOC-MACRO purpose="Unit tests for emitSignal dedupe_scope behavior in _shared/funnel.ts"]
2
+ // CIL[DOC-RESPONSIBILITY responsibility="Assert the optional dedupe_scope narrows the dedupe lookup to (account_id, action_type, dedupe_scope), is stamped into the inserted row data, and that omitting it preserves the once-per-account default"]
3
+ // CIL[DOC-CONTEXT module="funnel-signals.test" layer="test-unit" related_files=".framework/functions/_shared/funnel.ts"]
4
+ // CIL[DOC-CONTRACT inputs="mocked adminDb + fireCreateTriggers" outputs="expect assertions on query filters and inserted payloads" errors="none" side_effects="registers vi.mock factories"]
5
+ // CIL[DOC-AUDIENCE audience="test"]
6
+ // CIL[DOC-STABILITY stability="stable"]
7
+ import { describe, it, expect, vi, beforeEach } from 'vitest'
8
+
9
+ vi.mock('../../functions/_shared/db.ts', () => ({
10
+ adminDb: { from: vi.fn(), rpc: vi.fn() },
11
+ }))
12
+ vi.mock('../../functions/_shared/trigger-engine.ts', () => ({
13
+ fireCreateTriggers: vi.fn().mockResolvedValue(undefined),
14
+ }))
15
+
16
+ import { adminDb } from '../../functions/_shared/db.ts'
17
+ import { emitSignal } from '../../functions/_shared/funnel.ts'
18
+
19
+ function ctx(): any {
20
+ return { accountId: 'acct-1', principal: { id: 'p-1', type: 'human' } }
21
+ }
22
+
23
+ /**
24
+ * Recording query builder — captures every chain call so tests can assert
25
+ * which filters were applied. `terminal` is the value single/maybeSingle/
26
+ * then resolve with.
27
+ */
28
+ function chain(calls: any[][], terminal: any): any {
29
+ const b: any = {}
30
+ const rec = (name: string) => (...args: any[]) => {
31
+ calls.push([name, ...args])
32
+ return b
33
+ }
34
+ for (const m of [
35
+ 'select', 'eq', 'in', 'or', 'is', 'not', 'order', 'insert', 'update',
36
+ 'delete', 'upsert', 'lt', 'gt', 'lte', 'gte', 'neq', 'contains', 'limit',
37
+ ]) b[m] = rec(m)
38
+ b.single = () => Promise.resolve(terminal)
39
+ b.maybeSingle = () => Promise.resolve(terminal)
40
+ b.then = (res: any, rej?: any) => Promise.resolve(terminal).then(res, rej)
41
+ return b
42
+ }
43
+
44
+ /**
45
+ * Wire adminDb so `types` resolves the signal type and `items` answers the
46
+ * dedupe lookup (first call) and the insert (second call). Returns the
47
+ * recorded call lists.
48
+ */
49
+ function mockDb(opts: { dedupeRows?: any[] } = {}) {
50
+ const itemsCalls: any[][] = []
51
+ let itemsCallIdx = 0
52
+ vi.mocked(adminDb.from).mockImplementation((table: string) => {
53
+ if (table === 'types') {
54
+ return chain([], { data: { id: 'type-demo-signal' }, error: null })
55
+ }
56
+ if (table === 'items') {
57
+ itemsCallIdx++
58
+ return chain(
59
+ itemsCalls,
60
+ itemsCallIdx === 1
61
+ ? { data: opts.dedupeRows ?? [], error: null }
62
+ : { data: { id: 'sig-1', type_id: 'type-demo-signal' }, error: null }
63
+ )
64
+ }
65
+ return chain([], { data: null, error: null })
66
+ })
67
+ return { itemsCalls }
68
+ }
69
+
70
+ describe('emitSignal — dedupe_scope', () => {
71
+ beforeEach(() => vi.clearAllMocks())
72
+
73
+ it('narrows the dedupe lookup by data.dedupe_scope and stamps it on the row', async () => {
74
+ const { itemsCalls } = mockDb()
75
+ const created = await emitSignal(ctx(), {
76
+ type_slug: 'demo_signal',
77
+ action: 'workflow_completed',
78
+ dedupe_scope: 'run-1',
79
+ data: { source: 'demo' },
80
+ })
81
+ expect(created?.id).toBe('sig-1')
82
+ // The dedupe query filters on the scope marker.
83
+ expect(itemsCalls).toContainEqual(['eq', 'data->>dedupe_scope', 'run-1'])
84
+ // The inserted row carries the scope so later lookups match.
85
+ const insert = itemsCalls.find((c) => c[0] === 'insert')
86
+ expect(insert?.[1]?.data?.dedupe_scope).toBe('run-1')
87
+ expect(insert?.[1]?.data?.action_type).toBe('workflow_completed')
88
+ })
89
+
90
+ it('omits the scope filter entirely when dedupe_scope is not set', async () => {
91
+ const { itemsCalls } = mockDb()
92
+ const created = await emitSignal(ctx(), {
93
+ type_slug: 'demo_signal',
94
+ action: 'demo_started',
95
+ data: { source: 'demo' },
96
+ })
97
+ expect(created?.id).toBe('sig-1')
98
+ expect(itemsCalls.some((c) => c[0] === 'eq' && c[1] === 'data->>dedupe_scope')).toBe(false)
99
+ const insert = itemsCalls.find((c) => c[0] === 'insert')
100
+ expect(insert?.[1]?.data).not.toHaveProperty('dedupe_scope')
101
+ })
102
+
103
+ it('skips the insert when a scoped signal already exists for the run', async () => {
104
+ const { itemsCalls } = mockDb({ dedupeRows: [{ id: 'existing' }] })
105
+ const created = await emitSignal(ctx(), {
106
+ type_slug: 'demo_signal',
107
+ action: 'workflow_completed',
108
+ dedupe_scope: 'run-1',
109
+ })
110
+ expect(created).toBeNull()
111
+ expect(itemsCalls.some((c) => c[0] === 'insert')).toBe(false)
112
+ })
113
+
114
+ it('skips the dedupe lookup entirely when dedupe is false', async () => {
115
+ const { itemsCalls } = mockDb()
116
+ await emitSignal(ctx(), {
117
+ type_slug: 'demo_signal',
118
+ action: 'demo_started',
119
+ dedupe: false,
120
+ })
121
+ expect(itemsCalls.some((c) => c[0] === 'eq' && c[1] === 'data->>action_type')).toBe(false)
122
+ expect(itemsCalls.some((c) => c[0] === 'insert')).toBe(true)
123
+ })
124
+
125
+ it('returns null when the signal type is not installed', async () => {
126
+ vi.mocked(adminDb.from).mockImplementation((table: string) =>
127
+ chain([], table === 'types' ? { data: null, error: null } : { data: [], error: null })
128
+ )
129
+ const created = await emitSignal(ctx(), {
130
+ type_slug: 'demo_signal',
131
+ action: 'demo_started',
132
+ })
133
+ expect(created).toBeNull()
134
+ })
135
+ })