spine-framework 0.3.145 → 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 +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
@@ -7,71 +7,157 @@
7
7
 
8
8
 
9
9
 
10
- // CIL[BEGIN chunk_id="app-install-cli_module_header_1783931090" type="module_header" identity="imports" parent="none"]
11
- // CIL[DOC-MACRO purpose="Import Node.js modules for CLI app installation tool"]
12
- // CIL[DOC-RESPONSIBILITY responsibility="Manage all external module imports for CLI operations"]
13
- // CIL[DOC-CONTEXT module="app-install-cli" layer="cli" related_files="[\".framework/migrations/015_simplify_apps_table.sql\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"\\\"]"]
14
- // CIL[DOC-CONTRACT inputs="none" outputs="Imported modules and utilities" errors="Import failures" side_effects="Module loading"]
15
- // CIL[DOC-MICRO logic_summary="Imports file system, CLI, YAML validation, and ES modules utilities" notable_decisions="[]"]
16
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
10
+ // CIL[BEGIN stable_id="~/.framework/scripts/app-install-cli.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/scripts/app-install-cli.ts"]
11
+ // CIL[DOC-MACRO purpose="Module entry point for the app-install CLI tool"]
12
+ // CIL[DOC-RESPONSIBILITY responsibility="Import dependencies and expose the CLI script"]
13
+ // CIL[DOC-CONTEXT module=".framework/scripts" layer="script" related_files=".framework/scripts/app-install-cli.ts"]
14
+ // CIL[DOC-CONTRACT inputs="none" outputs="loaded modules and configured execution environment" errors="none at import time" side_effects="none"]
15
+ // CIL[DOC-MICRO logic_summary="Imports Node.js fs, path, commander, js-yaml, ajv, and url helpers" notable_decisions="[]"]
16
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
17
17
  // CIL[DOC-STABILITY stability="stable"]
18
- // CIL[DOC-AUDIENCE audience="developer"]
19
- // CIL[DOC-VECTOR type="context" content="Layer: cli. Direct callers: 0. Direct calls: 0. Related files: .framework/migrations/015_simplify_apps_table.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, custom/apps/portal/pages/ContentPage.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
20
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
21
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
22
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
23
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
24
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
18
+ // CIL[DOC-AUDIENCE audience="engineers using or extending the app install CLI"]
25
19
  import { readFileSync, existsSync, writeFileSync } from 'fs'
26
20
  import { resolve, dirname } from 'path'
27
21
  import { program } from 'commander'
28
22
  import yaml from 'js-yaml'
29
23
  import Ajv from 'ajv'
30
24
  import { fileURLToPath } from 'url'
31
- // CIL[END chunk_id="app-install-cli_module_header_1783931090"]
32
- // CIL[BEGIN chunk_id="app-install-cli_setup_1783931090" type="setup" identity="setup" parent="none"]
33
- // CIL[DOC-MACRO purpose="Initialize CLI environment, schema validation, and type definitions"]
34
- // CIL[DOC-RESPONSIBILITY responsibility="Set up file paths, schema validator, and installation context"]
35
- // CIL[DOC-CONTEXT module="app-install-cli" layer="cli" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/functions/_shared/schema-utils.ts\",\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/functions/_shared/db.ts\",\"\\\"]"]
36
- // CIL[DOC-CONTRACT inputs="none" outputs="Schema validator, file paths, context interface" errors="Schema loading failures" side_effects="File system reads"]
37
- // CIL[DOC-MICRO logic_summary="Resolves paths, loads schema, creates validator, defines context interface" notable_decisions="['schema_loading', 'ajv_validation']"]
38
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="external_symbols_unknown"]
39
- // CIL[DOC-STABILITY stability="stable"]
40
- // CIL[DOC-VECTOR type="context" content="Layer: cli. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/schema-utils.ts, custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/functions/_shared/db.ts, \."]
41
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
42
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
43
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
25
+ // CIL[DOC-VECTOR type="context" content="purpose='Module entry point for the app-install CLI tool'; No verified external callers; imports: none"]
26
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
27
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
28
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
44
29
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
45
30
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
31
+ // CIL[END stable_id="~/.framework/scripts/app-install-cli.ts:module_header:module_header"]
32
+ // CIL[BEGIN stable_id="~/.framework/scripts/app-install-cli.ts:__filename:constant" type="constant" identity="__filename" parent="~/.framework/scripts/app-install-cli.ts"]
33
+ // CIL[DOC-MACRO purpose="Declares and initializes the __filename constant for the CLI"]
34
+ // CIL[DOC-RESPONSIBILITY responsibility="Hold the value of __filename for use by the script"]
35
+ // CIL[DOC-CONTEXT module=".framework/scripts" layer="script" related_files=".framework/scripts/app-install-cli.ts"]
36
+ // CIL[DOC-CONTRACT inputs="none" outputs="the __filename constant value" errors="none" side_effects="none"]
37
+ // CIL[DOC-MICRO logic_summary="Assigns an initial value to the __filename constant" notable_decisions="[]"]
38
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
39
+ // CIL[DOC-STABILITY stability="stable"]
46
40
  const __filename = fileURLToPath(import.meta.url)
41
+ // CIL[DOC-VECTOR type="context" content="purpose='Declares and initializes the __filename constant for the CLI'; No verified external callers; imports: none"]
42
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
43
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
44
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
45
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
46
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
47
+ // CIL[END stable_id="~/.framework/scripts/app-install-cli.ts:__filename:constant"]
48
+ // CIL[BEGIN stable_id="~/.framework/scripts/app-install-cli.ts:__dirname:constant" type="constant" identity="__dirname" parent="~/.framework/scripts/app-install-cli.ts"]
49
+ // CIL[DOC-MACRO purpose="Declares and initializes the __dirname constant for the CLI"]
50
+ // CIL[DOC-RESPONSIBILITY responsibility="Hold the value of __dirname for use by the script"]
51
+ // CIL[DOC-CONTEXT module=".framework/scripts" layer="script" related_files=".framework/scripts/app-install-cli.ts"]
52
+ // CIL[DOC-CONTRACT inputs="none" outputs="the __dirname constant value" errors="none" side_effects="none"]
53
+ // CIL[DOC-MICRO logic_summary="Assigns an initial value to the __dirname constant" notable_decisions="[]"]
54
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
55
+ // CIL[DOC-STABILITY stability="stable"]
47
56
  const __dirname = dirname(__filename)
57
+ // CIL[DOC-VECTOR type="context" content="purpose='Declares and initializes the __dirname constant for the CLI'; No verified external callers; imports: none"]
58
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
59
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
60
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
61
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
62
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
63
+ // CIL[END stable_id="~/.framework/scripts/app-install-cli.ts:__dirname:constant"]
48
64
 
65
+ // CIL[BEGIN stable_id="~/.framework/scripts/app-install-cli.ts:schemaPath:constant" type="constant" identity="schemaPath" parent="~/.framework/scripts/app-install-cli.ts"]
66
+ // CIL[DOC-MACRO purpose="Declares and initializes the schemaPath constant for the CLI"]
67
+ // CIL[DOC-RESPONSIBILITY responsibility="Hold the value of schemaPath for use by the script"]
68
+ // CIL[DOC-CONTEXT module=".framework/scripts" layer="script" related_files=".framework/scripts/app-install-cli.ts"]
69
+ // CIL[DOC-CONTRACT inputs="none" outputs="the schemaPath constant value" errors="none" side_effects="none"]
70
+ // CIL[DOC-MICRO logic_summary="Assigns an initial value to the schemaPath constant" notable_decisions="[]"]
71
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
72
+ // CIL[DOC-STABILITY stability="stable"]
49
73
  const schemaPath = resolve(__dirname, '../docs/app-installation/schema.json')
74
+ // CIL[DOC-VECTOR type="context" content="purpose='Declares and initializes the schemaPath constant for the CLI'; No verified external callers; imports: none"]
75
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
76
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
77
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
78
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
79
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
80
+ // CIL[END stable_id="~/.framework/scripts/app-install-cli.ts:schemaPath:constant"]
81
+ // CIL[BEGIN stable_id="~/.framework/scripts/app-install-cli.ts:schema:constant" type="constant" identity="schema" parent="~/.framework/scripts/app-install-cli.ts"]
82
+ // CIL[DOC-MACRO purpose="Declares and initializes the schema constant for the CLI"]
83
+ // CIL[DOC-RESPONSIBILITY responsibility="Hold the value of schema for use by the script"]
84
+ // CIL[DOC-CONTEXT module=".framework/scripts" layer="script" related_files=".framework/scripts/app-install-cli.ts"]
85
+ // CIL[DOC-CONTRACT inputs="none" outputs="the schema constant value" errors="none" side_effects="none"]
86
+ // CIL[DOC-MICRO logic_summary="Assigns an initial value to the schema constant" notable_decisions="[]"]
87
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
88
+ // CIL[DOC-STABILITY stability="stable"]
50
89
  const schema = JSON.parse(readFileSync(schemaPath, 'utf8'))
90
+ // CIL[DOC-VECTOR type="context" content="purpose='Declares and initializes the schema constant for the CLI'; No verified external callers; imports: none"]
91
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
92
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
93
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
94
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
95
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
96
+ // CIL[END stable_id="~/.framework/scripts/app-install-cli.ts:schema:constant"]
51
97
 
98
+ // CIL[BEGIN stable_id="~/.framework/scripts/app-install-cli.ts:ajv:constant" type="constant" identity="ajv" parent="~/.framework/scripts/app-install-cli.ts"]
99
+ // CIL[DOC-MACRO purpose="Declares and initializes the ajv constant for the CLI"]
100
+ // CIL[DOC-RESPONSIBILITY responsibility="Hold the value of ajv for use by the script"]
101
+ // CIL[DOC-CONTEXT module=".framework/scripts" layer="script" related_files=".framework/scripts/app-install-cli.ts"]
102
+ // CIL[DOC-CONTRACT inputs="none" outputs="the ajv constant value" errors="none" side_effects="none"]
103
+ // CIL[DOC-MICRO logic_summary="Assigns an initial value to the ajv constant" notable_decisions="[]"]
104
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
105
+ // CIL[DOC-STABILITY stability="stable"]
52
106
  const ajv = new Ajv()
107
+ // CIL[DOC-VECTOR type="context" content="purpose='Declares and initializes the ajv constant for the CLI'; No verified external callers; imports: none"]
108
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
109
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
110
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
111
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
112
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
113
+ // CIL[END stable_id="~/.framework/scripts/app-install-cli.ts:ajv:constant"]
114
+ // CIL[BEGIN stable_id="~/.framework/scripts/app-install-cli.ts:validate:constant" type="constant" identity="validate" parent="~/.framework/scripts/app-install-cli.ts"]
115
+ // CIL[DOC-MACRO purpose="Declares and initializes the validate constant for the CLI"]
116
+ // CIL[DOC-RESPONSIBILITY responsibility="Hold the value of validate for use by the script"]
117
+ // CIL[DOC-CONTEXT module=".framework/scripts" layer="script" related_files=".framework/scripts/app-install-cli.ts"]
118
+ // CIL[DOC-CONTRACT inputs="none" outputs="the validate constant value" errors="none" side_effects="none"]
119
+ // CIL[DOC-MICRO logic_summary="Assigns an initial value to the validate constant" notable_decisions="[]"]
120
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
121
+ // CIL[DOC-STABILITY stability="stable"]
53
122
  const validate = ajv.compile(schema)
123
+ // CIL[DOC-VECTOR type="context" content="purpose='Declares and initializes the validate constant for the CLI'; No verified external callers; imports: none"]
124
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
125
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
126
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
127
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
128
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
129
+ // CIL[END stable_id="~/.framework/scripts/app-install-cli.ts:validate:constant"]
54
130
 
131
+ // CIL[BEGIN stable_id="~/.framework/scripts/app-install-cli.ts:InstallationContext:interface" type="interface" identity="InstallationContext" parent="~/.framework/scripts/app-install-cli.ts"]
132
+ // CIL[DOC-MACRO purpose="Defines the TypeScript contract for InstallationContext"]
133
+ // CIL[DOC-RESPONSIBILITY responsibility="Structural type definition used across the CLI"]
134
+ // CIL[DOC-CONTEXT module=".framework/scripts" layer="script" related_files=".framework/scripts/app-install-cli.ts"]
135
+ // CIL[DOC-CONTRACT inputs="none" outputs="type definition for InstallationContext" errors="none" side_effects="none"]
136
+ // CIL[DOC-MICRO logic_summary="Declares the fields of the InstallationContext interface" notable_decisions="[]"]
137
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
138
+ // CIL[DOC-STABILITY stability="stable"]
55
139
  interface InstallationContext {
56
140
  TARGET_ACCOUNT_ID?: string
57
141
  PACK_INSTALLATION_ID?: string
58
142
  [key: string]: string | undefined
59
143
  }
60
- // CIL[END chunk_id="app-install-cli_setup_1783931090"]
61
- // CIL[BEGIN chunk_id="app-install-cli_substitutevariables_1783931090" type="function" identity="substituteVariables" parent="none"]
62
- // CIL[DOC-MACRO purpose="Recursively substitute ${VAR} placeholders with context values"]
63
- // CIL[DOC-RESPONSIBILITY responsibility="Variable template substitution engine for installation configs"]
64
- // CIL[DOC-CONTEXT module="app-install-cli" layer="cli" related_files="[\".framework/functions/_shared/schema-utils.ts\",\".framework/src/components/ui/dialog.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/functions/_shared/db.ts\",\".framework/src/components/ui/table-primitives.tsx\",\"\\\"]"]
65
- // CIL[DOC-CONTRACT inputs="none" outputs="substituted object" errors="none" side_effects="none"]
66
- // CIL[DOC-MICRO logic_summary="Handles strings, arrays, and objects recursively with regex replacement" notable_decisions="['recursive_substitution', 'fallback_to_match']"]
67
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
68
- // CIL[DOC-STABILITY stability="stable"]
69
- // CIL[DOC-VECTOR type="context" content="Layer: cli. Direct callers: 2. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, .framework/src/components/ui/dialog.tsx, .framework/functions/_shared/principal.ts, .framework/functions/_shared/db.ts, .framework/src/components/ui/table-primitives.tsx, \."]
70
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 2. Total affected: 2."]
71
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
72
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
144
+ // CIL[DOC-VECTOR type="context" content="purpose='Defines the TypeScript contract for InstallationContext'; No verified external callers; imports: none"]
145
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
146
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
147
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
73
148
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
74
149
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
150
+ // CIL[END stable_id="~/.framework/scripts/app-install-cli.ts:InstallationContext:interface"]
151
+ // CIL[BEGIN stable_id="~/.framework/scripts/app-install-cli.ts:substituteVariables:function" type="function" identity="substituteVariables" parent="~/.framework/scripts/app-install-cli.ts"]
152
+ // CIL[DOC-MACRO purpose="Implements the substituteVariables function"]
153
+ // CIL[DOC-RESPONSIBILITY responsibility="Execute the substituteVariables logic and return or exit"]
154
+ // CIL[DOC-CONTEXT module=".framework/scripts" layer="script" related_files=".framework/scripts/app-install-cli.ts"]
155
+ // CIL[DOC-CONTRACT inputs="obj, context" outputs="return value or void" errors="may throw or exit on invalid input" side_effects="console output and file system access as applicable"]
156
+ // CIL[DOC-MICRO logic_summary="Performs substituteVariables with validation and execution flow" notable_decisions="[]"]
157
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
158
+ // CIL[DOC-STABILITY stability="stable"]
159
+ // CIL[DOC-PARAM name="obj" type="any" description="Parameter obj"]
160
+ // CIL[DOC-PARAM name="context" type="InstallationContext" description="Parameter context"]
75
161
  function substituteVariables(obj: any, context: InstallationContext): any {
76
162
  if (typeof obj === 'string') {
77
163
  return obj.replace(/\$\{([^}]+)\}/g, (match, varName) => {
@@ -88,21 +174,22 @@ function substituteVariables(obj: any, context: InstallationContext): any {
88
174
  }
89
175
  return obj
90
176
  }
91
- // CIL[END chunk_id="app-install-cli_substitutevariables_1783931090"]
92
- // CIL[BEGIN chunk_id="app-install-cli_validateinstructionfile_1783931090" type="function" identity="validateInstructionFile" parent="none"]
93
- // CIL[DOC-MACRO purpose="Validate YAML instruction files against JSON schema"]
94
- // CIL[DOC-RESPONSIBILITY responsibility="Schema validation and file existence checking"]
95
- // CIL[DOC-CONTEXT module="app-install-cli" layer="cli" related_files="[\".framework/functions/_shared/schema-utils.ts\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"\\\"]"]
96
- // CIL[DOC-CONTRACT inputs="none" outputs="validation result" errors="File not found, validation failures" side_effects="Console output, process.exit"]
97
- // CIL[DOC-MICRO logic_summary="Checks file existence, loads YAML, validates against schema, exits on failure" notable_decisions="['process_exit_on_failure', 'schema_validation']"]
98
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="external_symbols_unknown"]
99
- // CIL[DOC-STABILITY stability="stable"]
100
- // CIL[DOC-VECTOR type="context" content="Layer: cli. Direct callers: 1. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
101
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 1. Total affected: 1."]
102
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
103
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
177
+ // CIL[DOC-VECTOR type="context" content="purpose='Implements the substituteVariables function'; No verified external callers; imports: none"]
178
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
179
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
180
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
104
181
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
105
182
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
183
+ // CIL[END stable_id="~/.framework/scripts/app-install-cli.ts:substituteVariables:function"]
184
+ // CIL[BEGIN stable_id="~/.framework/scripts/app-install-cli.ts:validateInstructionFile:function" type="function" identity="validateInstructionFile" parent="~/.framework/scripts/app-install-cli.ts"]
185
+ // CIL[DOC-MACRO purpose="Implements the validateInstructionFile function"]
186
+ // CIL[DOC-RESPONSIBILITY responsibility="Execute the validateInstructionFile logic and return or exit"]
187
+ // CIL[DOC-CONTEXT module=".framework/scripts" layer="script" related_files=".framework/scripts/app-install-cli.ts"]
188
+ // CIL[DOC-CONTRACT inputs="filePath" outputs="return value or void" errors="may throw or exit on invalid input" side_effects="console output and file system access as applicable"]
189
+ // CIL[DOC-MICRO logic_summary="Performs validateInstructionFile with validation and execution flow" notable_decisions="[]"]
190
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
191
+ // CIL[DOC-STABILITY stability="stable"]
192
+ // CIL[DOC-PARAM name="filePath" type="string" description="Parameter filePath"]
106
193
  async function validateInstructionFile(filePath: string): Promise<void> {
107
194
  try {
108
195
  console.log(`🔍 Validating ${filePath}...`)
@@ -127,21 +214,23 @@ async function validateInstructionFile(filePath: string): Promise<void> {
127
214
  process.exit(1)
128
215
  }
129
216
  }
130
- // CIL[END chunk_id="app-install-cli_validateinstructionfile_1783931090"]
131
- // CIL[BEGIN chunk_id="app-install-cli_executeinstallation_1783931090" type="function" identity="executeInstallation" parent="none"]
132
- // CIL[DOC-MACRO purpose="Execute multi-step app installation from instruction files"]
133
- // CIL[DOC-RESPONSIBILITY responsibility="Orchestrate complete app installation workflow"]
134
- // CIL[DOC-CONTEXT module="app-install-cli" layer="cli" related_files="[\".framework/migrations/015_simplify_apps_table.sql\",\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\"\\\"]"]
135
- // CIL[DOC-CONTRACT inputs="none" outputs="installation result" errors="Installation failures" side_effects="Console output, process.exit"]
136
- // CIL[DOC-MICRO logic_summary="Validates, sets context, simulates pack install, creates apps, runs migrations, verifies" notable_decisions="['simulated_installation', 'step_by_step_execution']"]
137
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="complex_dependencies"]
138
- // CIL[DOC-STABILITY stability="stable"]
139
- // CIL[DOC-VECTOR type="context" content="Layer: cli. Direct callers: 0. Direct calls: 0. Related files: .framework/migrations/015_simplify_apps_table.sql, custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, custom/apps/cortex/functions/custom_cil-embeddings.ts, \."]
140
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
141
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
142
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
217
+ // CIL[DOC-VECTOR type="context" content="purpose='Implements the validateInstructionFile function'; No verified external callers; imports: none"]
218
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
219
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
220
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
143
221
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
144
222
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
223
+ // CIL[END stable_id="~/.framework/scripts/app-install-cli.ts:validateInstructionFile:function"]
224
+ // CIL[BEGIN stable_id="~/.framework/scripts/app-install-cli.ts:executeInstallation:function" type="function" identity="executeInstallation" parent="~/.framework/scripts/app-install-cli.ts"]
225
+ // CIL[DOC-MACRO purpose="Implements the executeInstallation function"]
226
+ // CIL[DOC-RESPONSIBILITY responsibility="Execute the executeInstallation logic and return or exit"]
227
+ // CIL[DOC-CONTEXT module=".framework/scripts" layer="script" related_files=".framework/scripts/app-install-cli.ts"]
228
+ // CIL[DOC-CONTRACT inputs="filePath, options" outputs="return value or void" errors="may throw or exit on invalid input" side_effects="console output and file system access as applicable"]
229
+ // CIL[DOC-MICRO logic_summary="Performs executeInstallation with validation and execution flow" notable_decisions="[]"]
230
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
231
+ // CIL[DOC-STABILITY stability="stable"]
232
+ // CIL[DOC-PARAM name="filePath" type="string" description="Parameter filePath"]
233
+ // CIL[DOC-PARAM name="options" type="any" description="Parameter options"]
145
234
  async function executeInstallation(filePath: string, options: any): Promise<void> {
146
235
  try {
147
236
  console.log(`🚀 Executing installation from ${filePath}...`)
@@ -210,21 +299,23 @@ async function executeInstallation(filePath: string, options: any): Promise<void
210
299
  process.exit(1)
211
300
  }
212
301
  }
213
- // CIL[END chunk_id="app-install-cli_executeinstallation_1783931090"]
214
- // CIL[BEGIN chunk_id="app-install-cli_generatetemplate_1783931090" type="function" identity="generateTemplate" parent="none"]
215
- // CIL[DOC-MACRO purpose="Generate YAML templates for app installations or migrations"]
216
- // CIL[DOC-RESPONSIBILITY responsibility="Template generation and file output management"]
217
- // CIL[DOC-CONTEXT module="app-install-cli" layer="cli" related_files="[]"]
218
- // CIL[DOC-CONTRACT inputs="none" outputs="template content" errors="Template loading failures" side_effects="File writes, console output"]
219
- // CIL[DOC-MICRO logic_summary="Resolves template paths, loads files, outputs to file or stdout" notable_decisions="['template_type_switching', 'output_option_handling']"]
220
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="external_symbols_unknown"]
221
- // CIL[DOC-STABILITY stability="stable"]
222
- // CIL[DOC-VECTOR type="context" content="Layer: cli. Direct callers: 0. Direct calls: 0. Related files: none."]
223
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
224
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
225
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
302
+ // CIL[DOC-VECTOR type="context" content="purpose='Implements the executeInstallation function'; No verified external callers; imports: none"]
303
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
304
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
305
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
226
306
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
227
307
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
308
+ // CIL[END stable_id="~/.framework/scripts/app-install-cli.ts:executeInstallation:function"]
309
+ // CIL[BEGIN stable_id="~/.framework/scripts/app-install-cli.ts:generateTemplate:function" type="function" identity="generateTemplate" parent="~/.framework/scripts/app-install-cli.ts"]
310
+ // CIL[DOC-MACRO purpose="Implements the generateTemplate function"]
311
+ // CIL[DOC-RESPONSIBILITY responsibility="Execute the generateTemplate logic and return or exit"]
312
+ // CIL[DOC-CONTEXT module=".framework/scripts" layer="script" related_files=".framework/scripts/app-install-cli.ts"]
313
+ // CIL[DOC-CONTRACT inputs="type, options" outputs="return value or void" errors="may throw or exit on invalid input" side_effects="console output and file system access as applicable"]
314
+ // CIL[DOC-MICRO logic_summary="Performs generateTemplate with validation and execution flow" notable_decisions="[]"]
315
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
316
+ // CIL[DOC-STABILITY stability="stable"]
317
+ // CIL[DOC-PARAM name="type" type="string" description="Parameter type"]
318
+ // CIL[DOC-PARAM name="options" type="any" description="Parameter options"]
228
319
  async function generateTemplate(type: string, options: any): Promise<void> {
229
320
  try {
230
321
  const templateDir = resolve(__dirname, '../docs/app-installation/templates')
@@ -255,21 +346,21 @@ async function generateTemplate(type: string, options: any): Promise<void> {
255
346
  process.exit(1)
256
347
  }
257
348
  }
258
- // CIL[END chunk_id="app-install-cli_generatetemplate_1783931090"]
259
- // CIL[BEGIN chunk_id="app-install-cli_cli_setup_1783931090" type="cli_setup" identity="cli_setup" parent="none"]
260
- // CIL[DOC-MACRO purpose="Define CLI commands and argument parsing"]
261
- // CIL[DOC-RESPONSIBILITY responsibility="Set up commander.js CLI interface with commands and options"]
262
- // CIL[DOC-CONTEXT module="app-install-cli" layer="cli" related_files="[]"]
263
- // CIL[DOC-CONTRACT inputs="none" outputs="CLI interface" errors="Command parsing errors" side_effects="CLI execution"]
264
- // CIL[DOC-MICRO logic_summary="Configures validate, install, and template commands with arguments and options" notable_decisions="['commander_setup', 'action_binding']"]
265
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
266
- // CIL[DOC-STABILITY stability="stable"]
267
- // CIL[DOC-VECTOR type="context" content="Layer: cli. Direct callers: 0. Direct calls: 0. Related files: none."]
268
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
269
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
270
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
349
+ // CIL[DOC-VECTOR type="context" content="purpose='Implements the generateTemplate function'; No verified external callers; imports: none"]
350
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
351
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
352
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
271
353
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
272
354
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
355
+ // CIL[END stable_id="~/.framework/scripts/app-install-cli.ts:generateTemplate:function"]
356
+ // CIL[BEGIN stable_id="~/.framework/scripts/app-install-cli.ts:cli:variable" type="variable" identity="cli" parent="~/.framework/scripts/app-install-cli.ts"]
357
+ // CIL[DOC-MACRO purpose="Configures the cli CLI program and its command wiring"]
358
+ // CIL[DOC-RESPONSIBILITY responsibility="Wire commander commands to the appropriate action handlers"]
359
+ // CIL[DOC-CONTEXT module=".framework/scripts" layer="script" related_files=".framework/scripts/app-install-cli.ts"]
360
+ // CIL[DOC-CONTRACT inputs="command-line arguments" outputs="parsed command dispatch" errors="exits on unknown command or invalid arguments" side_effects="console output and invokes validate, install, or template handlers"]
361
+ // CIL[DOC-MICRO logic_summary="Builds commander program with validate, install, and template commands" notable_decisions="[]"]
362
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
363
+ // CIL[DOC-STABILITY stability="stable"]
273
364
  program
274
365
  .name('app-install-cli')
275
366
  .description('Spine App Installation CLI - Validate and execute app installation instructions')
@@ -297,4 +388,10 @@ program
297
388
  .action(generateTemplate)
298
389
 
299
390
  program.parse()
300
- // CIL[END chunk_id="app-install-cli_cli_setup_1783931090"]
391
+ // CIL[DOC-VECTOR type="context" content="purpose='Configures the cli CLI program and its command wiring'; No verified external callers; imports: none"]
392
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
393
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
394
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
395
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
396
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
397
+ // CIL[END stable_id="~/.framework/scripts/app-install-cli.ts:cli:variable"]
@@ -1,89 +1,172 @@
1
1
  #!/usr/bin/env bash
2
2
 
3
- # Frontend Assembly - Merge .framework/src + custom/apps/*/src → .assembled/src
3
+ # CIL[BEGIN stable_id="~/.framework/scripts/assemble-frontend.sh:module:script" type="script" identity="assemble-frontend" parent="~/.framework/scripts/assemble-frontend.sh"]
4
+ # CIL[DOC-MACRO purpose="Assemble .framework/src base layer + each custom app under .assembled/src/<app-slug>/ and merge public assets with collision detection, for the Vite build."]
5
+ # CIL[DOC-RESPONSIBILITY responsibility="Stage core src, per-app dirs (verbatim, no basename flattening), index.html path fix, _redirects, and public assets; then mtime-preserving rsync into .assembled/src and public/."]
6
+ # CIL[DOC-CONTEXT module="assembly" layer="build" related_files="scripts/assemble-functions.sh,scripts/assemble.sh,config/vite.config.ts,.framework/src/components/CustomAppLoader.tsx"]
7
+ # CIL[DOC-CONTRACT inputs=".framework/src,.framework/public,custom/apps/*,spine.config.json; env SPINE_PROJECT_ROOT (fixture override for tests)" outputs=".assembled/src + merged public/; exit 1 on public-path collision" errors="hard error naming both sources when two public assets share a relative path with different content" side_effects="rewrites .assembled/src and public/"]
8
+ # CIL[DOC-MICRO logic_summary="Temp-dir staging → core copy → per-app rsync with excludes (functions/seed/public/node_modules/dist/dotfiles) → public manifest-tracked collision check → rsync -rlc (no -t) publish." notable_decisions="identical duplicate public assets skip silently; root spine.config.json wins over framework template; no .gitkeep rsync exclude so --delete can remove stale dirs"]
9
+ # CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"]
10
+ # CIL[DOC-STABILITY stability="stable"]
11
+ # CIL[DOC-NOTE type="invariant" content="import.meta.glob('../../../custom/apps/*/index.tsx') in CustomAppLoader must keep resolving — app dirs are copied verbatim under src/<slug>/, never flattened by basename."]
12
+ # CIL[END stable_id="~/.framework/scripts/assemble-frontend.sh:module:script"]
13
+
14
+ # Frontend Assembly - Merge .framework/src + custom/apps/* → .assembled/src
4
15
  #
5
16
  # Purpose: Create unified frontend source directory for Vite build process.
6
- # - .framework/src is the canonical Spine frontend
7
- # - custom/apps/*/src are your application sources
8
- # - Vite expects a single src directory, so we assemble at build time
17
+ # - .framework/src is the canonical Spine frontend (base layer at root)
18
+ # - each custom/apps/<app> is copied to .assembled/src/<app-slug>/ VERBATIM —
19
+ # no basename flattening (two apps' components/ must never merge silently)
20
+ # - custom app index resolution uses import.meta.glob('../../../custom/apps/*/index.tsx')
21
+ # in .framework/src/components/CustomAppLoader.tsx — assembled app dirs exist
22
+ # for @/(@core)-style imports and layout consistency, not for the glob
9
23
  #
10
24
  # Process:
11
- # 1. Clean target directory
12
- # 2. Copy core src files
13
- # 3. Overlay custom src files (overwrites existing)
25
+ # 1. Assemble into temp directory first
26
+ # 2. Copy core src files (base layer)
27
+ # 3. Copy each app to <app-slug>/, excluding functions/, seed/, public/,
28
+ # node_modules, dist, and dotfiles
29
+ # 4. Merge public assets with same-relative-path collision detection
30
+ # 5. rsync -c into target so unchanged files keep their mtimes — Vite then only
31
+ # reloads modules that actually changed instead of every file
32
+ #
33
+ # SPINE_PROJECT_ROOT (optional): override the project root — used by the
34
+ # fixture-based unit tests; production use leaves it unset.
14
35
  #
15
- # Dependencies: standard bash utilities, find, cp, rsync
36
+ # Dependencies: standard bash utilities, find, cp, rsync, cmp
16
37
 
17
38
  set -euo pipefail
18
39
 
19
40
  SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
20
- PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
41
+ # Canonicalize (-P resolves symlinks) — consistent with assemble-functions.sh
42
+ # and safe when the repo itself is reached through a symlinked path.
43
+ PROJECT_ROOT="$(cd "${SPINE_PROJECT_ROOT:-$(dirname "$SCRIPT_DIR")}" && pwd -P)"
21
44
 
22
45
  CORE_SRC_DIR="$PROJECT_ROOT/.framework/src"
23
46
  CUSTOM_SRC_DIR="$PROJECT_ROOT/custom/apps"
24
47
  TARGET_SRC_DIR="$PROJECT_ROOT/.assembled/src"
48
+ VITE_PUBLIC_DIR="$PROJECT_ROOT/public"
49
+ TMP_ROOT="$PROJECT_ROOT/.frontend-assemble-tmp"
50
+ TMP_SRC_DIR="$TMP_ROOT/src"
51
+ TMP_PUBLIC_DIR="$TMP_ROOT/public"
52
+ # rel-path → source-file map for public-asset collision errors
53
+ PUBLIC_MANIFEST="$TMP_ROOT/public-manifest.tsv"
25
54
 
26
55
  echo "🔧 Assembling frontend → $TARGET_SRC_DIR"
27
56
 
28
- # 1. Clean target (except .gitkeep if exists)
29
- if [ -d "$TARGET_SRC_DIR" ]; then
30
- find "$TARGET_SRC_DIR" -mindepth 1 -not -name '.gitkeep' -delete 2>/dev/null || true
31
- else
32
- mkdir -p "$TARGET_SRC_DIR"
33
- fi
57
+ # 1. Stage into temp dir
58
+ rm -rf "$TMP_ROOT"
59
+ mkdir -p "$TMP_SRC_DIR" "$TMP_PUBLIC_DIR"
60
+ : > "$PUBLIC_MANIFEST"
34
61
 
35
62
  # 2. Copy core src (base layer)
36
63
  if [ -d "$CORE_SRC_DIR" ]; then
37
- # Ensure subdirectories are copied properly
38
- cp -r "$CORE_SRC_DIR"/* "$TARGET_SRC_DIR"/ 2>/dev/null || true
64
+ cp -r "$CORE_SRC_DIR"/* "$TMP_SRC_DIR"/ 2>/dev/null || true
39
65
  echo " ✓ Core: $(find "$CORE_SRC_DIR" -name '*.tsx' -o -name '*.ts' -o -name '*.css' | wc -l | tr -d ' ') files"
40
66
  else
41
67
  echo " ⚠ Core: $CORE_SRC_DIR not found"
42
68
  fi
43
69
 
44
- # 4. Copy public files from .framework
70
+ # 3. Copy index.html, fixing the script src path for assembled structure
45
71
  if [ -f "$PROJECT_ROOT/.framework/index.html" ]; then
46
- # Copy and fix the script src path for assembled structure
47
- sed 's|/src/main.tsx|./main.tsx|g' "$PROJECT_ROOT/.framework/index.html" > "$TARGET_SRC_DIR/index.html"
72
+ sed 's|/src/main.tsx|./main.tsx|g' "$PROJECT_ROOT/.framework/index.html" > "$TMP_SRC_DIR/index.html"
48
73
  echo " ✓ Core: index.html (paths fixed)"
49
74
  fi
50
75
 
51
- # 3. Copy public assets from .framework
52
- # Vite's publicDir is set to PROJECT_ROOT/public (i.e. ../public relative to .assembled/src)
53
- # so static files must go there to be served at the root URL
54
- VITE_PUBLIC_DIR="$PROJECT_ROOT/public"
76
+ # 4. Stage a public-asset source dir into TMP_PUBLIC_DIR with collision
77
+ # detection. The SAME relative path may never come from two different sources:
78
+ # - identical content → skip silently (duplicate copy is harmless)
79
+ # - differing content → hard error naming both source files
80
+ stage_public_dir() {
81
+ local src_dir="$1"
82
+ local f rel staged prev
83
+ while IFS= read -r -d '' f; do
84
+ rel="${f#"$src_dir"/}"
85
+ staged="$TMP_PUBLIC_DIR/$rel"
86
+ if [ -e "$staged" ]; then
87
+ if cmp -s "$f" "$staged"; then
88
+ continue
89
+ fi
90
+ prev="$(awk -F '\t' -v r="$rel" '$1 == r { print $2; exit }' "$PUBLIC_MANIFEST")"
91
+ echo " ✗ Public asset collision: '$rel' is provided by both" >&2
92
+ echo " - $prev" >&2
93
+ echo " - $f" >&2
94
+ echo " Rename one of them — public/ merges flat, last-wins is forbidden." >&2
95
+ exit 1
96
+ fi
97
+ mkdir -p "$(dirname "$staged")"
98
+ cp "$f" "$staged"
99
+ printf '%s\t%s\n' "$rel" "$f" >> "$PUBLIC_MANIFEST"
100
+ done < <(find "$src_dir" -type f ! -name '.*' -print0 | sort -z)
101
+ }
102
+
103
+ # 5. Framework public assets merge first — Vite's publicDir is
104
+ # PROJECT_ROOT/public, so static files must land there to be served at root URL
55
105
  if [ -d "$PROJECT_ROOT/.framework/public" ]; then
56
- mkdir -p "$VITE_PUBLIC_DIR"
57
- cp -r "$PROJECT_ROOT/.framework/public"/* "$VITE_PUBLIC_DIR/" 2>/dev/null || true
106
+ stage_public_dir "$PROJECT_ROOT/.framework/public"
58
107
  echo " ✓ Core: $(find "$PROJECT_ROOT/.framework/public" -type f | wc -l | tr -d ' ') public files"
59
108
  fi
60
109
 
61
- # 3.5. Copy _redirects to Vite-served root for Netlify dev (served from .assembled/src root)
110
+ # 6. Copy _redirects to Vite-served root for Netlify dev (served from .assembled/src root)
62
111
  if [ -f "$PROJECT_ROOT/.framework/public/_redirects" ]; then
63
- cp "$PROJECT_ROOT/.framework/public/_redirects" "$TARGET_SRC_DIR/_redirects"
112
+ cp "$PROJECT_ROOT/.framework/public/_redirects" "$TMP_SRC_DIR/_redirects"
64
113
  echo " ✓ Core: _redirects copied to Vite-served directory for Netlify dev"
65
114
  fi
66
115
 
67
- # 3.6. Copy spine.config.json to Vite publicDir so it's served at /spine.config.json
116
+ # 7. Per-app copy: custom/apps/<app> → .assembled/src/<app-slug>/ verbatim.
117
+ # Excluded: functions (goes to .assembled/netlify/functions), seed, public
118
+ # (merged into /public above), node_modules, dist, dotfiles.
119
+ CUSTOM_COUNT=0
120
+ if [ -d "$CUSTOM_SRC_DIR" ]; then
121
+ for app_dir in "$CUSTOM_SRC_DIR"/*/; do
122
+ [ -d "$app_dir" ] || continue
123
+ slug="$(basename "$app_dir")"
124
+
125
+ rsync -a \
126
+ --exclude='functions' \
127
+ --exclude='seed' \
128
+ --exclude='public' \
129
+ --exclude='node_modules' \
130
+ --exclude='dist' \
131
+ --exclude='.*' \
132
+ "$app_dir" "$TMP_SRC_DIR/$slug/"
133
+
134
+ # App public assets merge into /public AFTER framework public; a same
135
+ # relative path in two sources (or vs framework) is a hard error above.
136
+ if [ -d "$app_dir/public" ]; then
137
+ stage_public_dir "$app_dir/public"
138
+ fi
139
+
140
+ app_count=$(find "$TMP_SRC_DIR/$slug" -name '*.tsx' -o -name '*.ts' -o -name '*.css' 2>/dev/null | wc -l | tr -d ' ')
141
+ CUSTOM_COUNT=$((CUSTOM_COUNT + app_count))
142
+ echo " ✓ $slug: $app_count files → src/$slug/"
143
+ done
144
+ fi
145
+ if [ "$CUSTOM_COUNT" -eq 0 ]; then
146
+ echo " ○ Custom: (empty)"
147
+ fi
148
+
149
+ # 8. spine.config.json → staged public (root config, served at /spine.config.json).
150
+ # The ROOT copy is the instance config and intentionally wins over the
151
+ # framework template of the same name (framework/public/spine.config.json).
68
152
  if [ -f "$PROJECT_ROOT/spine.config.json" ]; then
69
- mkdir -p "$VITE_PUBLIC_DIR"
70
- cp "$PROJECT_ROOT/spine.config.json" "$VITE_PUBLIC_DIR/spine.config.json"
153
+ cp -f "$PROJECT_ROOT/spine.config.json" "$TMP_PUBLIC_DIR/spine.config.json"
71
154
  echo " ✓ Config: spine.config.json copied to public/"
72
155
  fi
73
156
 
74
- # 6. Overlay custom src (overrides + additions)
75
- if [ -d "$CUSTOM_SRC_DIR" ]; then
76
- # Copy files and subdirectories
77
- cp -r "$CUSTOM_SRC_DIR"/* "$TARGET_SRC_DIR"/ 2>/dev/null || true
78
-
79
- # Handle subdirectories properly
80
- find "$CUSTOM_SRC_DIR" -mindepth 1 -type d -exec sh -c 'dir="$1"; base=$(basename "$dir"); mkdir -p "'"$TARGET_SRC_DIR"'/$base" && cp -r "$dir"/* "'"$TARGET_SRC_DIR"'/$base/"' _ {} \; 2>/dev/null || true
81
-
82
- CUSTOM_COUNT=$(find "$CUSTOM_SRC_DIR" -name '*.tsx' -o -name '*.ts' -o -name '*.css' 2>/dev/null | wc -l | tr -d ' ')
83
- echo " ✓ Custom: $CUSTOM_COUNT files"
84
- else
85
- echo " ○ Custom: (empty)"
86
- fi
157
+ # 9. Publish staged public assets. -c compares content checksums; deliberately
158
+ # NO -t so unchanged files keep mtimes (see final sync note below).
159
+ mkdir -p "$VITE_PUBLIC_DIR"
160
+ rsync -rlc "$TMP_PUBLIC_DIR"/ "$VITE_PUBLIC_DIR"/
161
+
162
+ # 10. Sync temp into place. -c compares content checksums; deliberately NO -t —
163
+ # otherwise rsync "corrects" mtimes of unchanged files to the fresh temp-copy
164
+ # time and Vite reloads the entire module graph on every assemble.
165
+ mkdir -p "$TARGET_SRC_DIR"
166
+ # No .gitkeep exclusion: .assembled/ is gitignored, and leftover .gitkeep
167
+ # files inside stale dirs would make --delete treat them as non-empty.
168
+ rsync -rlc --delete "$TMP_SRC_DIR"/ "$TARGET_SRC_DIR"/
169
+ rm -rf "$TMP_ROOT"
87
170
 
88
171
  echo " ✓ Assembled: $(find "$TARGET_SRC_DIR" -name '*.tsx' -o -name '*.ts' -o -name '*.css' | wc -l | tr -d ' ') total files"
89
172
  echo "✅ Done"