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.
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 +5067 -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 +15 -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,135 @@
1
+ // CIL[BEGIN stable_id="~/.framework/tests/setup.ts:file_header:constant" type="constant" identity="file_header" parent="~/.framework/tests/setup.ts"]
2
+ // CIL[DOC-MACRO purpose="Documentation header for the Vitest setup file."]
3
+ // CIL[DOC-RESPONSIBILITY responsibility="Describes the setup file's role, audience, and environment stubbing strategy."]
4
+ // CIL[DOC-CONTEXT module="tests/setup" layer="test-infrastructure" related_files=".framework/tests/setup.ts"]
5
+ // CIL[DOC-CONTRACT inputs="none" outputs="JSDoc module metadata" errors="" side_effects="none"]
6
+ // CIL[DOC-MICRO logic_summary="Provides a module-level JSDoc header for the test setup file." notable_decisions=""]
7
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
+ // CIL[DOC-STABILITY stability="stable"]
9
+ /// <reference types="node" />
10
+ /**
11
+ * @module tests/setup
12
+ * @audience core-contributor
13
+ * @layer test-infrastructure
14
+ * @stability stable
15
+ *
16
+ * Global Vitest setup file — runs before every test file via
17
+ * `vitest.config.ts → setupFiles`.
18
+ *
19
+ * Stubs the three required Supabase env vars (`SUPABASE_URL`,
20
+ * `SUPABASE_ANON_KEY`, `SUPABASE_SERVICE_ROLE_KEY`) so modules that call
21
+ * `createClient()` at import time (`principal.ts`, `db.ts`) don't crash
22
+ * with "supabaseUrl is required" in unit test runs.
23
+ *
24
+ * Integration tests load real values from `.xenv.test` via
25
+ * `tests/integration/helpers.ts` and override these stubs.
26
+ */
27
+ // CIL[DOC-VECTOR type="context" content="purpose='Documentation header for the Vitest setup file.'; No verified external callers; imports: none"]
28
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
29
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
30
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
31
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
32
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
33
+ // CIL[END stable_id="~/.framework/tests/setup.ts:file_header:constant"]
34
+
35
+ // CIL[BEGIN stable_id="~/.framework/tests/setup.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/tests/setup.ts"]
36
+ // CIL[DOC-MACRO purpose="Imports required Node.js utilities for path and file resolution."]
37
+ // CIL[DOC-RESPONSIBILITY responsibility="Makes fs, path, and url utilities available for the setup module."]
38
+ // CIL[DOC-CONTEXT module="tests/setup" layer="test-infrastructure" related_files=".framework/tests/setup.ts"]
39
+ // CIL[DOC-CONTRACT inputs="" outputs="Imported modules" errors="" side_effects=""]
40
+ // CIL[DOC-MICRO logic_summary="Imports fs, path, and url modules for ESM setup." notable_decisions=""]
41
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
42
+ // CIL[DOC-STABILITY stability="stable"]
43
+ // CIL[DOC-AUDIENCE audience="core-contributor"]
44
+ import { readFileSync, existsSync } from 'fs'
45
+ import { resolve, dirname } from 'path'
46
+ import { fileURLToPath } from 'url'
47
+ // CIL[DOC-VECTOR type="context" content="purpose='Imports required Node.js utilities for path and file resolution.'; No verified external callers; imports: none"]
48
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
49
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
50
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
51
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
52
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
53
+ // CIL[END stable_id="~/.framework/tests/setup.ts:module_header:module_header"]
54
+
55
+ // CIL[BEGIN stable_id="~/.framework/tests/setup.ts:__filename:constant" type="constant" identity="__filename" parent="~/.framework/tests/setup.ts"]
56
+ // CIL[DOC-MACRO purpose="Derive a stable __filename reference for the ESM module."]
57
+ // CIL[DOC-RESPONSIBILITY responsibility="Computes the current file's path from import.meta.url."]
58
+ // CIL[DOC-CONTEXT module="tests/setup" layer="test-infrastructure" related_files=".framework/tests/setup.ts"]
59
+ // CIL[DOC-CONTRACT inputs="import.meta.url" outputs="__filename" errors="" side_effects="none"]
60
+ // CIL[DOC-MICRO logic_summary="Converts import.meta.url to a filesystem path using fileURLToPath." notable_decisions=""]
61
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
62
+ // CIL[DOC-STABILITY stability="stable"]
63
+ const __filename = fileURLToPath(import.meta.url)
64
+ // CIL[DOC-VECTOR type="context" content="purpose='Derive a stable __filename reference for the ESM module.'; No verified external callers; imports: none"]
65
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
66
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
67
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
68
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
69
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
70
+ // CIL[END stable_id="~/.framework/tests/setup.ts:__filename:constant"]
71
+ // CIL[BEGIN stable_id="~/.framework/tests/setup.ts:__dirname:constant" type="constant" identity="__dirname" parent="~/.framework/tests/setup.ts"]
72
+ // CIL[DOC-MACRO purpose="Derive __dirname from the computed __filename."]
73
+ // CIL[DOC-RESPONSIBILITY responsibility="Extracts the directory portion of the current file path."]
74
+ // CIL[DOC-CONTEXT module="tests/setup" layer="test-infrastructure" related_files=".framework/tests/setup.ts"]
75
+ // CIL[DOC-CONTRACT inputs="__filename" outputs="__dirname" errors="" side_effects="none"]
76
+ // CIL[DOC-MICRO logic_summary="Computes __dirname by passing __filename to the path dirname function." notable_decisions=""]
77
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
78
+ // CIL[DOC-STABILITY stability="stable"]
79
+ const __dirname = dirname(__filename)
80
+ // CIL[DOC-VECTOR type="context" content="purpose='Derive __dirname from the computed __filename.'; No verified external callers; imports: none"]
81
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
82
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
83
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
84
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
85
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
86
+ // CIL[END stable_id="~/.framework/tests/setup.ts:__dirname:constant"]
87
+
88
+ // Load .xenv.test before stubs so integration tests get real DB credentials
89
+ // before db.ts evaluates its createClient() calls at module load time.
90
+ // CIL[BEGIN stable_id="~/.framework/tests/setup.ts:xenvTestPath:constant" type="constant" identity="xenvTestPath" parent="~/.framework/tests/setup.ts"]
91
+ // CIL[DOC-MACRO purpose="Resolve the absolute path to the .xenv.test file."]
92
+ // CIL[DOC-RESPONSIBILITY responsibility="Provides the location of the local test environment file."]
93
+ // CIL[DOC-CONTEXT module="tests/setup" layer="test-infrastructure" related_files=".framework/tests/setup.ts"]
94
+ // CIL[DOC-CONTRACT inputs="__dirname" outputs="xenvTestPath" errors="" side_effects="none"]
95
+ // CIL[DOC-MICRO logic_summary="Builds the absolute .xenv.test path relative to the setup file directory." notable_decisions=""]
96
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
97
+ // CIL[DOC-STABILITY stability="stable"]
98
+ const xenvTestPath = resolve(__dirname, '../.xenv.test')
99
+ // CIL[DOC-VECTOR type="context" content="purpose='Resolve the absolute path to the .xenv.test file.'; No verified external callers; imports: none"]
100
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
101
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
102
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
103
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
104
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
105
+ // CIL[END stable_id="~/.framework/tests/setup.ts:xenvTestPath:constant"]
106
+ // CIL[BEGIN stable_id="~/.framework/tests/setup.ts:setup_env:variable" type="variable" identity="setup_env" parent="~/.framework/tests/setup.ts"]
107
+ // CIL[DOC-MACRO purpose="Load .xenv.test and set default Supabase test environment variables."]
108
+ // CIL[DOC-RESPONSIBILITY responsibility="Ensures required Supabase environment variables are present before test modules import client code."]
109
+ // CIL[DOC-CONTEXT module="tests/setup" layer="test-infrastructure" related_files=".framework/tests/setup.ts"]
110
+ // CIL[DOC-CONTRACT inputs="xenvTestPath, process.env" outputs="process.env with SUPABASE_URL, SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY" errors="none" side_effects="Mutates process.env"]
111
+ // CIL[DOC-MICRO logic_summary="Parses .xenv.test line-by-line and applies default Supabase test credentials." notable_decisions="Skips blank and commented lines; preserves existing env values; strips surrounding quotes."]
112
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
113
+ // CIL[DOC-STABILITY stability="stable"]
114
+ if (existsSync(xenvTestPath)) {
115
+ for (const line of readFileSync(xenvTestPath, 'utf8').split('\n')) {
116
+ const trimmed = line.trim()
117
+ if (!trimmed || trimmed.startsWith('#')) continue
118
+ const eqIdx = trimmed.indexOf('=')
119
+ if (eqIdx === -1) continue
120
+ const key = trimmed.slice(0, eqIdx).trim()
121
+ const value = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, '')
122
+ if (!process.env[key]) process.env[key] = value
123
+ }
124
+ }
125
+
126
+ process.env.SUPABASE_URL = process.env.SUPABASE_URL || 'https://test.supabase.co'
127
+ process.env.SUPABASE_ANON_KEY = process.env.SUPABASE_ANON_KEY || 'test-anon-key'
128
+ process.env.SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY || 'test-service-key'
129
+ // CIL[DOC-VECTOR type="context" content="purpose='Load .xenv.test and set default Supabase test environment variables.'; No verified external callers; imports: none"]
130
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
131
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
132
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
133
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
134
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
135
+ // CIL[END stable_id="~/.framework/tests/setup.ts:setup_env:variable"]
@@ -0,0 +1,278 @@
1
+ // CIL[BEGIN stable_id="~/.framework/tests/ui/ui-sweep.ts:file_header:constant" type="constant" identity="file_header" parent="~/.framework/tests/ui/ui-sweep.ts"]
2
+ // CIL[DOC-MACRO purpose="Provide file-level documentation and usage notes for the UI sweep test."]
3
+ // CIL[DOC-RESPONSIBILITY responsibility="Describe the test purpose, run command, dependencies, and exit codes."]
4
+ // CIL[DOC-CONTEXT module="tests/ui/ui-sweep" layer="test-ui" related_files=".framework/tests/reporter.ts,.framework/tests/ui/ui-sweep.ts"]
5
+ // CIL[DOC-CONTRACT inputs="none" outputs="file header comments" errors="none" side_effects="none"]
6
+ // CIL[DOC-MICRO logic_summary="JSDoc block with module metadata and run instructions." notable_decisions="Uses exit codes 0 for all passed and 1 for failures."]
7
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
+ // CIL[DOC-STABILITY stability="stable"]
9
+ /**
10
+ * @module tests/ui/ui-sweep
11
+ * @audience core-contributor
12
+ * @layer test-ui
13
+ * @stability stable
14
+ *
15
+ * Playwright UI sweep for all admin routes. Navigates each route, waits for
16
+ * the page to settle, asserts zero console errors, and checks for expected
17
+ * landmark elements. Writes results to public.test_runs via reporter.ts.
18
+ *
19
+ * Run via: tsx v2-core/tests/ui/ui-sweep.ts
20
+ * Requires: Netlify dev server running at SPINE_DEV_URL (default http://localhost:8888)
21
+ *
22
+ * Exit codes:
23
+ * 0 — all routes passed
24
+ * 1 — one or more routes failed
25
+ *
26
+ * @seeAlso tests/reporter.ts (writeRunResults)
27
+ * @seeAlso .windsurf/workflows/ui-test.md
28
+ */
29
+ // CIL[DOC-VECTOR type="context" content="purpose='Provide file-level documentation and usage notes for the UI sweep test.'; No verified external callers; imports: .framework/tests/reporter.ts"]
30
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
31
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
32
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
33
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
34
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
35
+ // CIL[END stable_id="~/.framework/tests/ui/ui-sweep.ts:file_header:constant"]
36
+
37
+ // CIL[BEGIN stable_id="~/.framework/tests/ui/ui-sweep.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/tests/ui/ui-sweep.ts"]
38
+ // CIL[DOC-MACRO purpose="Load environment variables and import dependencies for the Playwright UI sweep."]
39
+ // CIL[DOC-RESPONSIBILITY responsibility="Read .xenv files and import the modules required to run the sweep."]
40
+ // CIL[DOC-CONTEXT module="tests/ui/ui-sweep" layer="test-ui" related_files=".framework/tests/reporter.ts"]
41
+ // CIL[DOC-CONTRACT inputs="process.env and .xenv/.xenv.test files" outputs="loaded environment and imported modules" errors="Import or file read errors propagate" side_effects="Reads .xenv files and sets process.env for missing keys"]
42
+ // CIL[DOC-MICRO logic_summary="Resolves the current directory and attempts to load .xenv.test then .xenv before importing Playwright and the reporter." notable_decisions="Only sets process.env keys that are not already defined; stops after the first found env file."]
43
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
44
+ // CIL[DOC-STABILITY stability="stable"]
45
+ // CIL[DOC-AUDIENCE audience="core-contributor"]
46
+ import { readFileSync, existsSync } from 'fs'
47
+ import { resolve, dirname } from 'path'
48
+ import { fileURLToPath } from 'url'
49
+ import { chromium } from 'playwright'
50
+
51
+ const __filename = fileURLToPath(import.meta.url)
52
+ const __dirname = dirname(__filename)
53
+
54
+ function loadEnv() {
55
+ for (const name of ['.xenv.test', '.xenv']) {
56
+ const p = resolve(__dirname, '../../', name)
57
+ if (existsSync(p)) {
58
+ const lines = readFileSync(p, 'utf8').split('\n')
59
+ for (const line of lines) {
60
+ const t = line.trim()
61
+ if (!t || t.startsWith('#')) continue
62
+ const eq = t.indexOf('=')
63
+ if (eq === -1) continue
64
+ const k = t.slice(0, eq).trim()
65
+ const v = t.slice(eq + 1).trim().replace(/^["']|["']$/g, '')
66
+ if (!process.env[k]) process.env[k] = v
67
+ }
68
+ break
69
+ }
70
+ }
71
+ }
72
+
73
+ loadEnv()
74
+
75
+ import { writeRunResults } from '../reporter.ts'
76
+ import type { TestCaseResult } from '../reporter.ts'
77
+ // CIL[DOC-VECTOR type="context" content="purpose='Load environment variables and import dependencies for the Playwright UI sweep.'; No verified external callers; imports: .framework/tests/reporter.ts"]
78
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
79
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
80
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
81
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
82
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
83
+ // CIL[END stable_id="~/.framework/tests/ui/ui-sweep.ts:module_header:module_header"]
84
+
85
+ // CIL[BEGIN stable_id="~/.framework/tests/ui/ui-sweep.ts:BASE_URL:constant" type="constant" identity="BASE_URL" parent="~/.framework/tests/ui/ui-sweep.ts"]
86
+ // CIL[DOC-MACRO purpose="Define the base URL used for all sweep navigation."]
87
+ // CIL[DOC-RESPONSIBILITY responsibility="Resolve the dev server URL from the environment or default."]
88
+ // CIL[DOC-CONTEXT module="tests/ui/ui-sweep" layer="test-ui" related_files=".framework/tests/reporter.ts,.framework/tests/ui/ui-sweep.ts"]
89
+ // CIL[DOC-CONTRACT inputs="process.env.SPINE_DEV_URL" outputs="BASE_URL string" errors="none" side_effects="none"]
90
+ // CIL[DOC-MICRO logic_summary="Fallback to localhost:8888 when SPINE_DEV_URL is unset." notable_decisions="Default is hardcoded."]
91
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
92
+ // CIL[DOC-STABILITY stability="stable"]
93
+ const BASE_URL = process.env.SPINE_DEV_URL || 'http://localhost:8888'
94
+ // CIL[DOC-VECTOR type="context" content="purpose='Define the base URL used for all sweep navigation.'; No verified external callers; imports: .framework/tests/reporter.ts"]
95
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
96
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
97
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
98
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
99
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
100
+ // CIL[END stable_id="~/.framework/tests/ui/ui-sweep.ts:BASE_URL:constant"]
101
+
102
+ // ─── ROUTE REGISTRY ──────────────────────────────────────────────────────────
103
+
104
+ // CIL[BEGIN stable_id="~/.framework/tests/ui/ui-sweep.ts:RouteSpec:interface" type="interface" identity="RouteSpec" parent="~/.framework/tests/ui/ui-sweep.ts"]
105
+ // CIL[DOC-MACRO purpose="Declare the shape of a route specification."]
106
+ // CIL[DOC-RESPONSIBILITY responsibility="Define the fields used to describe an admin route under test."]
107
+ // CIL[DOC-CONTEXT module="tests/ui/ui-sweep" layer="test-ui" related_files=".framework/tests/reporter.ts,.framework/tests/ui/ui-sweep.ts"]
108
+ // CIL[DOC-CONTRACT inputs="none" outputs="RouteSpec TypeScript interface" errors="none" side_effects="none"]
109
+ // CIL[DOC-MICRO logic_summary="Optional waitFor text, expected text, and suite classification." notable_decisions="waitFor and expectText are optional."]
110
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
111
+ // CIL[DOC-STABILITY stability="stable"]
112
+ interface RouteSpec {
113
+ path: string
114
+ waitFor?: string // text or aria label to wait for
115
+ expectText?: string[] // text that should appear on the page
116
+ suite: 'runtime' | 'configs' | 'observability' | 'testing'
117
+ }
118
+ // CIL[DOC-VECTOR type="context" content="purpose='Declare the shape of a route specification.'; No verified external callers; imports: .framework/tests/reporter.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/ui/ui-sweep.ts:RouteSpec:interface"]
125
+
126
+ // CIL[BEGIN stable_id="~/.framework/tests/ui/ui-sweep.ts:ROUTES:constant" type="constant" identity="ROUTES" parent="~/.framework/tests/ui/ui-sweep.ts"]
127
+ // CIL[DOC-MACRO purpose="Define the list of admin routes to sweep."]
128
+ // CIL[DOC-RESPONSIBILITY responsibility="Provide the canonical route registry for the UI sweep."]
129
+ // CIL[DOC-CONTEXT module="tests/ui/ui-sweep" layer="test-ui" related_files=".framework/tests/reporter.ts,.framework/tests/ui/ui-sweep.ts"]
130
+ // CIL[DOC-CONTRACT inputs="none" outputs="ROUTES array of RouteSpec" errors="none" side_effects="none"]
131
+ // CIL[DOC-MICRO logic_summary="Constant array of routes grouped by runtime, configs, observability, and testing suites." notable_decisions="Each route includes a waitFor string to verify page load."]
132
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
133
+ // CIL[DOC-STABILITY stability="stable"]
134
+ const ROUTES: RouteSpec[] = [
135
+ // Runtime
136
+ { path: '/admin/runtime/accounts', waitFor: 'Accounts', suite: 'runtime' },
137
+ { path: '/admin/runtime/people', waitFor: 'People', suite: 'runtime' },
138
+ { path: '/admin/runtime/items', waitFor: 'Items', suite: 'runtime' },
139
+ { path: '/admin/runtime/threads', waitFor: 'Threads', suite: 'runtime' },
140
+ { path: '/admin/runtime/messages', waitFor: 'Messages', suite: 'runtime' },
141
+ { path: '/admin/runtime/links', waitFor: 'Links', suite: 'runtime' },
142
+ { path: '/admin/runtime/attachments', waitFor: 'Attachments', suite: 'runtime' },
143
+ { path: '/admin/runtime/watchers', waitFor: 'Watchers', suite: 'runtime' },
144
+ // Configs
145
+ { path: '/admin/configs/types', waitFor: 'Types', suite: 'configs' },
146
+ { path: '/admin/configs/apps', waitFor: 'Apps', suite: 'configs' },
147
+ { path: '/admin/configs/roles', waitFor: 'Roles', suite: 'configs' },
148
+ { path: '/admin/configs/pipelines', waitFor: 'Pipelines', suite: 'configs' },
149
+ { path: '/admin/configs/triggers', waitFor: 'Triggers', suite: 'configs' },
150
+ // Observability
151
+ { path: '/admin/observability', waitFor: 'Observability', suite: 'observability' },
152
+ { path: '/admin/observability/logs', waitFor: 'Logs', suite: 'observability' },
153
+ // Testing
154
+ { path: '/admin/testing', waitFor: 'Testing', suite: 'testing' },
155
+ ]
156
+ // CIL[DOC-VECTOR type="context" content="purpose='Define the list of admin routes to sweep.'; No verified external callers; imports: .framework/tests/reporter.ts"]
157
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
158
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
159
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
160
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
161
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
162
+ // CIL[END stable_id="~/.framework/tests/ui/ui-sweep.ts:ROUTES:constant"]
163
+
164
+ // ─── SWEEP ───────────────────────────────────────────────────────────────────
165
+
166
+ // CIL[BEGIN stable_id="~/.framework/tests/ui/ui-sweep.ts:sweep:function" type="function" identity="sweep" parent="~/.framework/tests/ui/ui-sweep.ts"]
167
+ // CIL[DOC-MACRO purpose="Run the Playwright UI sweep across all admin routes."]
168
+ // CIL[DOC-RESPONSIBILITY responsibility="Launch a headless browser, navigate each route, detect console errors, record pass/fail results, and exit with the appropriate code."]
169
+ // CIL[DOC-CONTEXT module="tests/ui/ui-sweep" layer="test-ui" related_files=".framework/tests/reporter.ts,.framework/tests/ui/ui-sweep.ts"]
170
+ // CIL[DOC-CONTRACT inputs="BASE_URL and ROUTES" outputs="console log summary and test results persisted via writeRunResults" errors="Navigation timeout, console errors, or writeRunResults failure" side_effects="Spawns browser process, loads pages, writes results, calls process.exit"]
171
+ // CIL[DOC-MICRO logic_summary="Iterates ROUTES, captures console errors, awaits title, pushes TestCaseResult objects, then closes the browser and writes run results." notable_decisions="Uses networkidle wait and an 8s selector timeout; reports up to three console errors per route."]
172
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
173
+ // CIL[DOC-STABILITY stability="stable"]
174
+ async function sweep() {
175
+ const startMs = Date.now()
176
+ console.log(`\n🔍 UI Sweep — ${BASE_URL}\n`)
177
+
178
+ const browser = await chromium.launch({ headless: true })
179
+ const context = await browser.newContext()
180
+ const page = await context.newPage()
181
+
182
+ const results: TestCaseResult[] = []
183
+ let passed = 0, failed = 0
184
+
185
+ for (const route of ROUTES) {
186
+ const url = `${BASE_URL}${route.path}`
187
+ const testName = `navigate ${route.path}`
188
+ const testStart = Date.now()
189
+
190
+ try {
191
+ const consoleErrors: string[] = []
192
+ const handler = (msg: any) => {
193
+ if (msg.type() === 'error') consoleErrors.push(msg.text())
194
+ }
195
+ page.on('console', handler)
196
+
197
+ await page.goto(url, { waitUntil: 'networkidle', timeout: 15000 })
198
+
199
+ if (route.waitFor) {
200
+ await page.waitForSelector(`text=${route.waitFor}`, { timeout: 8000 }).catch(() => {})
201
+ }
202
+
203
+ const title = await page.title()
204
+
205
+ if (consoleErrors.length > 0) {
206
+ const errorText = consoleErrors.slice(0, 3).join(' | ')
207
+ console.log(` ✗ ${route.path} [${consoleErrors.length} console errors]`)
208
+ results.push({
209
+ suite: 'ui',
210
+ file: `ui-sweep/${route.suite}`,
211
+ name: testName,
212
+ status: 'failed',
213
+ duration_ms: Date.now() - testStart,
214
+ error: `Console errors: ${errorText}`
215
+ })
216
+ failed++
217
+ } else {
218
+ console.log(` ✓ ${route.path} (${title})`)
219
+ results.push({
220
+ suite: 'ui',
221
+ file: `ui-sweep/${route.suite}`,
222
+ name: testName,
223
+ status: 'passed',
224
+ duration_ms: Date.now() - testStart
225
+ })
226
+ passed++
227
+ }
228
+
229
+ page.off('console', handler)
230
+ } catch (err: any) {
231
+ console.log(` ✗ ${route.path} [${err.message?.slice(0, 80)}]`)
232
+ results.push({
233
+ suite: 'ui',
234
+ file: `ui-sweep/${route.suite}`,
235
+ name: testName,
236
+ status: 'failed',
237
+ duration_ms: Date.now() - testStart,
238
+ error: err.message
239
+ })
240
+ failed++
241
+ }
242
+ }
243
+
244
+ await browser.close()
245
+
246
+ const durationMs = Date.now() - startMs
247
+ console.log(`\n${passed}✓ ${failed}✗ ${durationMs}ms total\n`)
248
+
249
+ await writeRunResults('ui', results, durationMs)
250
+
251
+ process.exit(failed > 0 ? 1 : 0)
252
+ }
253
+ // CIL[DOC-VECTOR type="context" content="purpose='Run the Playwright UI sweep across all admin routes.'; No verified external callers; imports: .framework/tests/reporter.ts"]
254
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
255
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
256
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
257
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
258
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
259
+ // CIL[END stable_id="~/.framework/tests/ui/ui-sweep.ts:sweep:function"]
260
+ // CIL[BEGIN stable_id="~/.framework/tests/ui/ui-sweep.ts:sweep_invocation:variable" type="variable" identity="sweep_invocation" parent="~/.framework/tests/ui/ui-sweep.ts"]
261
+ // CIL[DOC-MACRO purpose="Start the UI sweep and handle uncaught errors."]
262
+ // CIL[DOC-RESPONSIBILITY responsibility="Invoke the sweep and exit the process on unhandled failure."]
263
+ // CIL[DOC-CONTEXT module="tests/ui/ui-sweep" layer="test-ui" related_files=".framework/tests/reporter.ts,.framework/tests/ui/ui-sweep.ts"]
264
+ // CIL[DOC-CONTRACT inputs="none" outputs="process exit" errors="uncaught sweep rejection" side_effects="calls sweep(); logs to stderr; process.exit(1) on failure"]
265
+ // CIL[DOC-MICRO logic_summary="Top-level call to sweep with a catch handler that logs and exits." notable_decisions="Only called once when the script is executed."]
266
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
267
+ // CIL[DOC-STABILITY stability="stable"]
268
+ sweep().catch(err => {
269
+ console.error('UI sweep failed:', err)
270
+ process.exit(1)
271
+ })
272
+ // CIL[DOC-VECTOR type="context" content="purpose='Start the UI sweep and handle uncaught errors.'; No verified external callers; imports: .framework/tests/reporter.ts"]
273
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
274
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
275
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
276
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
277
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
278
+ // CIL[END stable_id="~/.framework/tests/ui/ui-sweep.ts:sweep_invocation:variable"]