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
@@ -1,26 +1,37 @@
1
+ // CIL[BEGIN stable_id="~/.framework/functions/_shared/app-manifest.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/functions/_shared/app-manifest.ts"]
2
+ // CIL[DOC-MACRO purpose="Shared manifest loader for Spine apps"]
3
+ // CIL[DOC-RESPONSIBILITY responsibility="Defines AppManifest and NavItem interfaces and provides manifest loading, caching, merging, and discovery helpers"]
4
+ // CIL[DOC-CONTEXT module="functions/_shared" layer="shared" related_files=".framework/functions/_shared/app-manifest.ts"]
5
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
6
+ // CIL[DOC-MICRO logic_summary="Module-level entry point; no runtime logic" notable_decisions="[]"]
7
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
+ // CIL[DOC-STABILITY stability="stable"]
9
+ // CIL[DOC-AUDIENCE audience="developers"]
1
10
 
2
11
 
3
12
 
4
13
 
5
14
 
6
- // CIL[BEGIN chunk_id="app-manifest_moduleheader_1784066609" type="module_header" identity="module_header" parent="none"]
7
- // CIL[DOC-MACRO purpose="App manifest loading and management"]
8
- // CIL[DOC-RESPONSIBILITY responsibility="Load and merge app configuration manifests"]
9
- // CIL[DOC-CONTEXT module="_shared/app-manifest" layer="infrastructure" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/src/pages/admin/RolesPage.tsx\",\"\\\"]"]
10
- // CIL[DOC-CONTRACT inputs="none" outputs="manifest utilities" errors="none" side_effects="file system access"]
11
- // CIL[DOC-MICRO logic_summary="Defines AppManifest, NavItem interfaces and manifest cache" notable_decisions="[]"]
12
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
13
- // CIL[DOC-STABILITY stability="stable"]
14
- // CIL[DOC-AUDIENCE audience="developer"]
15
- // CIL[DOC-VECTOR type="context" content="Layer: infrastructure. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/src/pages/admin/RolesPage.tsx, \."]
16
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
17
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
18
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
15
+
16
+ import { readFileSync, realpathSync, readdirSync, statSync } from 'fs'
17
+ import { resolve, join, sep } from 'path'
18
+ // CIL[DOC-VECTOR type="context" content="purpose='Shared manifest loader for Spine apps'; No verified external callers; imports: none"]
19
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
20
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
21
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
19
22
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
20
23
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
21
- import { readFileSync } from 'fs'
22
- import { resolve } from 'path'
24
+ // CIL[END stable_id="~/.framework/functions/_shared/app-manifest.ts:module_header:module_header"]
23
25
 
26
+
27
+ // CIL[BEGIN stable_id="~/.framework/functions/_shared/app-manifest.ts:AppManifest:interface" type="interface" identity="AppManifest" parent="~/.framework/functions/_shared/app-manifest.ts"]
28
+ // CIL[DOC-MACRO purpose="Describes the runtime configuration shape of a Spine app manifest"]
29
+ // CIL[DOC-RESPONSIBILITY responsibility="Declare the AppManifest type fields used by loaders and renderers"]
30
+ // CIL[DOC-CONTEXT module="functions/_shared" layer="shared" related_files=".framework/functions/_shared/app-manifest.ts"]
31
+ // CIL[DOC-CONTRACT inputs="none" outputs="AppManifest type definition" errors="none" side_effects="none"]
32
+ // CIL[DOC-MICRO logic_summary="Optional and required fields for app metadata, routing, roles, and domains" notable_decisions="[]"]
33
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
34
+ // CIL[DOC-STABILITY stability="stable"]
24
35
  export interface AppManifest {
25
36
  name: string
26
37
  slug: string
@@ -39,7 +50,23 @@ export interface AppManifest {
39
50
  preview_domain?: string
40
51
  prod_domain?: string
41
52
  }
53
+ // CIL[DOC-VECTOR type="context" content="purpose='Describes the runtime configuration shape of a Spine app manifest'; No verified external callers; imports: none"]
54
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
55
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
56
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
57
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
58
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
59
+ // CIL[END stable_id="~/.framework/functions/_shared/app-manifest.ts:AppManifest:interface"]
42
60
 
61
+
62
+ // CIL[BEGIN stable_id="~/.framework/functions/_shared/app-manifest.ts:NavItem:interface" type="interface" identity="NavItem" parent="~/.framework/functions/_shared/app-manifest.ts"]
63
+ // CIL[DOC-MACRO purpose="Describes the shape of a navigation item in an app manifest"]
64
+ // CIL[DOC-RESPONSIBILITY responsibility="Declare the NavItem type used for app navigation trees"]
65
+ // CIL[DOC-CONTEXT module="functions/_shared" layer="shared" related_files=".framework/functions/_shared/app-manifest.ts"]
66
+ // CIL[DOC-CONTRACT inputs="none" outputs="NavItem type definition" errors="none" side_effects="none"]
67
+ // CIL[DOC-MICRO logic_summary="Title, path, icon, order, and optional nested children" notable_decisions="[]"]
68
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
69
+ // CIL[DOC-STABILITY stability="stable"]
43
70
  export interface NavItem {
44
71
  title: string
45
72
  path: string
@@ -47,108 +74,169 @@ export interface NavItem {
47
74
  order?: number
48
75
  children?: NavItem[]
49
76
  }
77
+ // CIL[DOC-VECTOR type="context" content="purpose='Describes the shape of a navigation item in an app manifest'; No verified external callers; imports: none"]
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/functions/_shared/app-manifest.ts:NavItem:interface"]
84
+
85
+
86
+
87
+
88
+
50
89
 
51
- const manifestCache = new Map<string, AppManifest>()
52
90
 
53
- // CIL[END chunk_id="app-manifest_moduleheader_1784066609"]
54
- // CIL[BEGIN chunk_id="app-manifest_loadmanifest_1784066609" type="function" identity="loadManifest" parent="none"]
55
- // CIL[DOC-MACRO purpose="Load app manifest from file"]
56
- // CIL[DOC-RESPONSIBILITY responsibility="Read and parse manifest JSON with caching"]
57
- // CIL[DOC-CONTEXT module="_shared/app-manifest" layer="infrastructure" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\"\\\"]"]
58
- // CIL[DOC-CONTRACT inputs="none" outputs="AppManifest or null" errors="file system errors" side_effects="file reads"]
59
- // CIL[DOC-MICRO logic_summary="Loads manifest from disk with validation and caching" notable_decisions="[]"]
60
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
91
+
92
+
93
+
94
+
95
+
96
+
97
+ // CIL[BEGIN stable_id="~/.framework/functions/_shared/app-manifest.ts:manifestCache:constant" type="constant" identity="manifestCache" parent="~/.framework/functions/_shared/app-manifest.ts"]
98
+ // CIL[DOC-MACRO purpose="Cache loaded manifests by file path to avoid repeated disk reads"]
99
+ // CIL[DOC-RESPONSIBILITY responsibility="Hold in-memory Map of manifest paths to AppManifest objects"]
100
+ // CIL[DOC-CONTEXT module="functions/_shared" layer="shared" related_files=".framework/functions/_shared/app-manifest.ts"]
101
+ // CIL[DOC-CONTRACT inputs="canonical manifest path string key" outputs="AppManifest or undefined" errors="none" side_effects="Cache state is mutable module state"]
102
+ // CIL[DOC-MICRO logic_summary="Instantiated once at module load; keyed by canonical manifest path" notable_decisions="[]"]
103
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
61
104
  // CIL[DOC-STABILITY stability="stable"]
62
- // CIL[DOC-VECTOR type="context" content="Layer: infrastructure. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, custom/apps/cortex/functions/custom_cil-embeddings.ts, \."]
63
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
64
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
65
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
105
+ const manifestCache = new Map<string, AppManifest>()
106
+ // CIL[DOC-VECTOR type="context" content="purpose='Cache loaded manifests by file path to avoid repeated disk reads'; No verified external callers; imports: none"]
107
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
108
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
109
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
66
110
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
67
111
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
68
- export function loadManifest(manifestPath: string): AppManifest | null {
69
- if (manifestCache.has(manifestPath)) {
70
- return manifestCache.get(manifestPath)!
71
- }
112
+ // CIL[END stable_id="~/.framework/functions/_shared/app-manifest.ts:manifestCache:constant"]
72
113
 
114
+
115
+
116
+ // CIL[BEGIN stable_id="~/.framework/functions/_shared/app-manifest.ts:loadManifest:function" type="function" identity="loadManifest" parent="~/.framework/functions/_shared/app-manifest.ts"]
117
+ // CIL[DOC-MACRO purpose="Read, parse, and cache a Spine app manifest JSON file"]
118
+ // CIL[DOC-RESPONSIBILITY responsibility="Load manifest from disk, validate required fields, cache, and return it"]
119
+ // CIL[DOC-CONTEXT module="functions/_shared" layer="shared" related_files=".framework/functions/_shared/app-manifest.ts"]
120
+ // CIL[DOC-CONTRACT inputs="manifestPath: relative or absolute path to manifest JSON, projectRoot: optional root (defaults to REPO_PATH or cwd)" outputs="AppManifest or null" errors="Returns null on path escapes, missing or invalid fields, or read/parse errors and logs to console" side_effects="Reads from filesystem and updates manifestCache keyed by canonical path"]
121
+ // CIL[DOC-MICRO logic_summary="Canonicalizes project root and manifest path with realpathSync, rejects lexical or symlink escapes, parses JSON, validates object shape, nonempty name, slug charset, and required_roles array, then caches by canonical path" notable_decisions="[]"]
122
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
123
+ // CIL[DOC-STABILITY stability="stable"]
124
+ export function loadManifest(
125
+ manifestPath: string,
126
+ projectRoot: string = resolve(process.env.REPO_PATH || process.cwd())
127
+ ): AppManifest | null {
73
128
  try {
74
- const projectRoot = resolve(__dirname, '../../../..')
75
- const fullPath = resolve(projectRoot, manifestPath)
76
-
77
- const content = readFileSync(fullPath, 'utf-8')
129
+ const root = realpathSync(resolve(projectRoot))
130
+ const lexical = resolve(root, manifestPath)
131
+ if (lexical !== root && !lexical.startsWith(root + sep)) {
132
+ console.error(`[app-manifest] Manifest path escapes project root: ${manifestPath}`)
133
+ return null
134
+ }
135
+ const canonical = realpathSync(lexical)
136
+ if (canonical !== root && !canonical.startsWith(root + sep)) {
137
+ console.error(`[app-manifest] Manifest resolves outside project root: ${manifestPath}`)
138
+ return null
139
+ }
140
+
141
+ if (manifestCache.has(canonical)) {
142
+ return manifestCache.get(canonical)!
143
+ }
144
+
145
+ const content = readFileSync(canonical, 'utf-8')
78
146
  const manifest: AppManifest = JSON.parse(content)
79
-
80
- if (!manifest.slug || !manifest.name) {
81
- console.error(`[app-manifest] Invalid manifest at ${manifestPath}: missing slug or name`)
147
+
148
+ if (!manifest || typeof manifest !== 'object' || Array.isArray(manifest)) {
149
+ console.error(`[app-manifest] Invalid manifest at ${manifestPath}: root must be an object`)
150
+ return null
151
+ }
152
+
153
+ if (typeof manifest.name !== 'string' || !manifest.name.trim()) {
154
+ console.error(`[app-manifest] Invalid manifest at ${manifestPath}: missing name`)
155
+ return null
156
+ }
157
+
158
+ if (typeof manifest.slug !== 'string' || !/^[a-z][a-z0-9-]*$/.test(manifest.slug)) {
159
+ console.error(`[app-manifest] Invalid manifest at ${manifestPath}: missing or invalid slug`)
82
160
  return null
83
161
  }
84
-
85
- if (!manifest.required_roles) {
162
+
163
+ if (manifest.required_roles === undefined || manifest.required_roles === null) {
86
164
  manifest.required_roles = []
165
+ } else if (!Array.isArray(manifest.required_roles) || manifest.required_roles.some((r) => typeof r !== 'string' || !r.trim())) {
166
+ console.error(`[app-manifest] Invalid manifest at ${manifestPath}: required_roles must be an array of nonempty strings`)
167
+ return null
87
168
  }
88
-
89
- manifestCache.set(manifestPath, manifest)
90
-
169
+
170
+ manifestCache.set(canonical, manifest)
171
+
91
172
  return manifest
92
173
  } catch (err) {
93
174
  console.error(`[app-manifest] Failed to load ${manifestPath}:`, err)
94
175
  return null
95
176
  }
96
177
  }
97
- // CIL[END chunk_id="app-manifest_loadmanifest_1784066609"]
98
- // CIL[BEGIN chunk_id="app-manifest_clearmanifestcache_1784066609" type="function" identity="clearManifestCache" parent="none"]
99
- // CIL[DOC-MACRO purpose="Clear manifest cache"]
100
- // CIL[DOC-RESPONSIBILITY responsibility="Reset cached manifest data"]
101
- // CIL[DOC-CONTEXT module="_shared/app-manifest" layer="infrastructure" related_files="[\"\\\"]"]
102
- // CIL[DOC-CONTRACT inputs="none" outputs="void" errors="none" side_effects="cache clearing"]
103
- // CIL[DOC-MICRO logic_summary="Clears all cached manifest entries" notable_decisions="[]"]
104
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
105
- // CIL[DOC-STABILITY stability="stable"]
106
- // CIL[DOC-VECTOR type="context" content="Layer: infrastructure. Direct callers: 0. Direct calls: 0. Related files: \."]
107
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
108
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
109
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
178
+ // CIL[DOC-VECTOR type="context" content="purpose='Read, parse, and cache a Spine app manifest JSON file'; No verified external callers; imports: none"]
179
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
180
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
181
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
110
182
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
111
183
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
184
+ // CIL[END stable_id="~/.framework/functions/_shared/app-manifest.ts:loadManifest:function"]
185
+
186
+ // CIL[BEGIN stable_id="~/.framework/functions/_shared/app-manifest.ts:clearManifestCache:function" type="function" identity="clearManifestCache" parent="~/.framework/functions/_shared/app-manifest.ts"]
187
+ // CIL[DOC-MACRO purpose="Clear the manifest cache"]
188
+ // CIL[DOC-RESPONSIBILITY responsibility="Reset the manifestCache Map"]
189
+ // CIL[DOC-CONTEXT module="functions/_shared" layer="shared" related_files=".framework/functions/_shared/app-manifest.ts"]
190
+ // CIL[DOC-CONTRACT inputs="none" outputs="void" errors="none" side_effects="Empties manifestCache"]
191
+ // CIL[DOC-MICRO logic_summary="Calls Map.clear on the module-level cache" notable_decisions="[]"]
192
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
193
+ // CIL[DOC-STABILITY stability="stable"]
112
194
  export function clearManifestCache(): void {
113
195
  manifestCache.clear()
114
196
  }
115
- // CIL[END chunk_id="app-manifest_clearmanifestcache_1784066609"]
116
- // CIL[BEGIN chunk_id="app-manifest_mergewithmanifest_1784066609" type="function" identity="mergeWithManifest" parent="none"]
117
- // CIL[DOC-MACRO purpose="Merge database record with manifest"]
118
- // CIL[DOC-RESPONSIBILITY responsibility="Combine DB and manifest configuration"]
119
- // CIL[DOC-CONTEXT module="_shared/app-manifest" layer="infrastructure" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/functions/_shared/schema-utils.ts\",\".framework/src/components/ui/dialog.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\"\\\"]"]
120
- // CIL[DOC-CONTRACT inputs="none" outputs="merged record" errors="manifest load errors" side_effects="file reads"]
121
- // CIL[DOC-MICRO logic_summary="Merges database record with manifest file data" notable_decisions="[]"]
122
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
123
- // CIL[DOC-STABILITY stability="stable"]
124
- // CIL[DOC-VECTOR type="context" content="Layer: infrastructure. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/schema-utils.ts, .framework/src/components/ui/dialog.tsx, .framework/functions/_shared/principal.ts, .framework/src/pages/admin/IntegrationsPage.tsx, \."]
125
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
126
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
127
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
197
+ // CIL[DOC-VECTOR type="context" content="purpose='Clear the manifest cache'; No verified external callers; imports: none"]
198
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
199
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
200
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
128
201
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
129
202
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
203
+ // CIL[END stable_id="~/.framework/functions/_shared/app-manifest.ts:clearManifestCache:function"]
204
+
205
+ // CIL[BEGIN stable_id="~/.framework/functions/_shared/app-manifest.ts:mergeWithManifest:function" type="function" identity="mergeWithManifest" parent="~/.framework/functions/_shared/app-manifest.ts"]
206
+ // CIL[DOC-MACRO purpose="Merge a database app record with its manifest file values"]
207
+ // CIL[DOC-RESPONSIBILITY responsibility="When config_source is manifest, load and overlay manifest fields onto the database record"]
208
+ // CIL[DOC-CONTEXT module="functions/_shared" layer="shared" related_files=".framework/functions/_shared/app-manifest.ts"]
209
+ // CIL[DOC-CONTRACT inputs="dbRecord: any database app row object" outputs="merged app object or null" errors="Falls back to database record if manifest missing or invalid, logging a warning" side_effects="Calls loadManifest which may read from disk and cache"]
210
+ // CIL[DOC-MICRO logic_summary="Returns DB-derived fallback when no manifest config, preserving an existing required_roles array and deriving from min_role only when absent; otherwise loads manifest and overlays manifest-authoritative fields on the full DB record" notable_decisions="[]"]
211
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
212
+ // CIL[DOC-STABILITY stability="stable"]
130
213
  export function mergeWithManifest(dbRecord: any): any {
131
214
  if (!dbRecord) return null
132
-
215
+
216
+ const fallbackRoles = Array.isArray(dbRecord.required_roles)
217
+ ? dbRecord.required_roles
218
+ : dbRecord.min_role ? [dbRecord.min_role] : []
219
+
133
220
  if (!dbRecord.manifest_path || dbRecord.config_source !== 'manifest') {
134
221
  return {
135
222
  ...dbRecord,
136
- required_roles: dbRecord.min_role ? [dbRecord.min_role] : [],
223
+ required_roles: fallbackRoles,
137
224
  _source: 'database'
138
225
  }
139
226
  }
140
-
227
+
141
228
  const manifest = loadManifest(dbRecord.manifest_path)
142
229
  if (!manifest) {
143
230
  console.warn(`[app-manifest] Could not load manifest for ${dbRecord.slug}, falling back to DB`)
144
231
  return {
145
232
  ...dbRecord,
146
- required_roles: dbRecord.min_role ? [dbRecord.min_role] : [],
233
+ required_roles: fallbackRoles,
147
234
  _source: 'database (manifest missing)'
148
235
  }
149
236
  }
150
-
237
+
151
238
  return {
239
+ ...dbRecord,
152
240
  id: dbRecord.id,
153
241
  slug: manifest.slug,
154
242
  name: manifest.name,
@@ -171,25 +259,57 @@ export function mergeWithManifest(dbRecord: any): any {
171
259
  _manifest_path: dbRecord.manifest_path
172
260
  }
173
261
  }
174
- // CIL[END chunk_id="app-manifest_mergewithmanifest_1784066609"]
175
- // CIL[BEGIN chunk_id="app-manifest_discovermanifests_1784066609" type="function" identity="discoverManifests" parent="none"]
176
- // CIL[DOC-MACRO purpose="Discover available app manifests"]
177
- // CIL[DOC-RESPONSIBILITY responsibility="Return list of known manifest paths"]
178
- // CIL[DOC-CONTEXT module="_shared/app-manifest" layer="infrastructure" related_files="[]"]
179
- // CIL[DOC-CONTRACT inputs="none" outputs="manifest list" errors="none" side_effects="none"]
180
- // CIL[DOC-MICRO logic_summary="Returns hardcoded list of app manifest locations" notable_decisions="[]"]
181
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
182
- // CIL[DOC-STABILITY stability="stable"]
183
- // CIL[DOC-VECTOR type="context" content="Layer: infrastructure. Direct callers: 0. Direct calls: 0. Related files: none."]
184
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
185
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
186
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
262
+ // CIL[DOC-VECTOR type="context" content="purpose='Merge a database app record with its manifest file values'; No verified external callers; imports: none"]
263
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
264
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
265
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
187
266
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
188
267
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
189
- export function discoverManifests(): Array<{slug: string, path: string}> {
190
- return [
191
- { slug: 'cortex', path: 'custom/apps/cortex/manifest.json' },
192
- { slug: 'customer-portal', path: 'custom/apps/customer-portal/manifest.json' }
193
- ]
268
+ // CIL[END stable_id="~/.framework/functions/_shared/app-manifest.ts:mergeWithManifest:function"]
269
+
270
+ // CIL[BEGIN stable_id="~/.framework/functions/_shared/app-manifest.ts:discoverManifests:function" type="function" identity="discoverManifests" parent="~/.framework/functions/_shared/app-manifest.ts"]
271
+ // CIL[DOC-MACRO purpose="Discover app manifests by enumerating custom/apps directories"]
272
+ // CIL[DOC-RESPONSIBILITY responsibility="Enumerate custom/apps children, load and validate each manifest, and return slug/path entries for directories whose name matches the manifest slug"]
273
+ // CIL[DOC-CONTEXT module="functions/_shared" layer="shared" related_files=".framework/functions/_shared/app-manifest.ts"]
274
+ // CIL[DOC-CONTRACT inputs="projectRoot?: string defaults to REPO_PATH or cwd" outputs="Array of {slug, path} objects sorted lexically by directory name" errors="Returns [] when custom/apps is absent or unreadable" side_effects="Reads the filesystem and may populate the manifest cache"]
275
+ // CIL[DOC-MICRO logic_summary="Canonicalizes the project root, lists custom/apps entries sorted lexically, skips non-directories and external symlink escapes via loadManifest containment, and keeps entries whose directory name equals the validated manifest slug" notable_decisions="[]"]
276
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
277
+ // CIL[DOC-STABILITY stability="stable"]
278
+ export function discoverManifests(
279
+ projectRoot: string = resolve(process.env.REPO_PATH || process.cwd())
280
+ ): Array<{slug: string, path: string}> {
281
+ try {
282
+ const root = realpathSync(resolve(projectRoot))
283
+ const appsDir = join(root, 'custom', 'apps')
284
+ const names = readdirSync(appsDir, { withFileTypes: true })
285
+ .map((d) => d.name)
286
+ .sort()
287
+
288
+ const found: Array<{slug: string, path: string}> = []
289
+ for (const name of names) {
290
+ const dirPath = join(appsDir, name)
291
+ let isDir = false
292
+ try {
293
+ isDir = statSync(dirPath).isDirectory()
294
+ } catch {
295
+ continue
296
+ }
297
+ if (!isDir) continue
298
+
299
+ const rel = `custom/apps/${name}/manifest.json`
300
+ const manifest = loadManifest(rel, root)
301
+ if (!manifest || manifest.slug !== name) continue
302
+ found.push({ slug: manifest.slug, path: rel })
303
+ }
304
+ return found
305
+ } catch {
306
+ return []
307
+ }
194
308
  }
195
- // CIL[END chunk_id="app-manifest_discovermanifests_1784066609"]
309
+ // CIL[DOC-VECTOR type="context" content="purpose='Discover app manifests by enumerating custom/apps directories'; No verified external callers; imports: none"]
310
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
311
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
312
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
313
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
314
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
315
+ // CIL[END stable_id="~/.framework/functions/_shared/app-manifest.ts:discoverManifests:function"]
@@ -0,0 +1,214 @@
1
+ // CIL[BEGIN stable_id="~/.framework/functions/_shared/ast.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/functions/_shared/ast.ts"]
2
+ // CIL[DOC-MACRO purpose="Provides the TypeScript compiler API import for AST identity extraction"]
3
+ // CIL[DOC-RESPONSIBILITY responsibility="Declare the typescript dependency and serve as the module-level CIL header"]
4
+ // CIL[DOC-CONTEXT module=".framework/functions/_shared/ast.ts" layer="shared" related_files=".framework/functions/_shared/ast.ts"]
5
+ // CIL[DOC-CONTRACT inputs="" outputs="" errors="" side_effects=""]
6
+ // CIL[DOC-MICRO logic_summary="Imports the entire typescript namespace as ts"]
7
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
+ // CIL[DOC-STABILITY stable]
9
+ // CIL[DOC-AUDIENCE audience="cil pipeline"]
10
+ import * as ts from 'typescript'
11
+ // CIL[DOC-VECTOR type="context" content="purpose='Provides the TypeScript compiler API import for AST identity extraction'; No verified external callers; imports: none"]
12
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
13
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
14
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
15
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
16
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
17
+ // CIL[END stable_id="~/.framework/functions/_shared/ast.ts:module_header:module_header"]
18
+
19
+
20
+ // CIL[BEGIN stable_id="~/.framework/functions/_shared/ast.ts:IdentityProposal:interface" type="interface" identity="IdentityProposal" parent="~/.framework/functions/_shared/ast.ts"]
21
+ // CIL[DOC-MACRO purpose="Defines the shape of an extracted code identity proposal"]
22
+ // CIL[DOC-RESPONSIBILITY responsibility="Model an identity proposal with identity, type, parent, line range and text"]
23
+ // CIL[DOC-CONTEXT module=".framework/functions/_shared/ast.ts" layer="shared" related_files=".framework/functions/_shared/ast.ts"]
24
+ // CIL[DOC-CONTRACT inputs="none (structural interface)" outputs="none (structural interface)" errors="none" side_effects="none"]
25
+ // CIL[DOC-MICRO logic_summary="Simple TypeScript interface describing a proposed chunk identity"]
26
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
27
+ // CIL[DOC-STABILITY stable]
28
+ export interface IdentityProposal {
29
+ identity: string
30
+ type: string
31
+ parent: string
32
+ line_start: number
33
+ line_end: number
34
+ text: string
35
+ }
36
+ // CIL[DOC-VECTOR type="context" content="purpose='Defines the shape of an extracted code identity proposal'; No verified external callers; imports: none"]
37
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
38
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
39
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
40
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
41
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
42
+ // CIL[END stable_id="~/.framework/functions/_shared/ast.ts:IdentityProposal:interface"]
43
+
44
+
45
+ // CIL[BEGIN stable_id="~/.framework/functions/_shared/ast.ts:isCapitalized:function" type="function" identity="isCapitalized" parent="~/.framework/functions/_shared/ast.ts"]
46
+ // CIL[DOC-MACRO purpose="Check whether a string begins with an uppercase letter"]
47
+ // CIL[DOC-STABILITY stability="internal"]
48
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
49
+ // CIL[DOC-CONTEXT module="ast" layer="functions" related_files=".framework/functions/_shared/ast.ts"]
50
+ // CIL[DOC-RESPONSIBILITY responsibility="Determine capitalization of an identifier to classify React components"]
51
+ // CIL[DOC-CONTRACT inputs="name: string" outputs="boolean" errors="" side_effects="none"]
52
+ // CIL[DOC-MICRO logic_summary="Returns true when the first character is the same as its uppercase form"]
53
+ function isCapitalized(name: string): boolean {
54
+ return name.length > 0 && name[0] === name[0].toUpperCase()
55
+ }
56
+ // CIL[END stable_id="~/.framework/functions/_shared/ast.ts:isCapitalized:function"]
57
+
58
+
59
+ // CIL[DOC-VECTOR type="context" content="purpose='Check whether a string begins with an uppercase letter'; No verified external callers; imports: none"]
60
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
61
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
62
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
63
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
64
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
65
+ // CIL[BEGIN stable_id="~/.framework/functions/_shared/ast.ts:isHook:function" type="function" identity="isHook" parent="~/.framework/functions/_shared/ast.ts"]
66
+ // CIL[DOC-MACRO purpose="Validation function for identifying React Hook names"]
67
+ // CIL[DOC-RESPONSIBILITY responsibility="Decide if a string is a valid React hook name by convention"]
68
+ // CIL[DOC-CONTEXT module=".framework/functions/_shared/ast.ts" layer="shared" related_files=".framework/functions/_shared/ast.ts"]
69
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
70
+ // CIL[DOC-CONTRACT inputs="name: string" outputs="boolean" errors="" side_effects="none"]
71
+ // CIL[DOC-MICRO logic_summary="Checks if the name starts with 'use', has length greater than 3, and the fourth character is uppercase"]
72
+ // CIL[DOC-STABILITY stable]
73
+ function isHook(name: string): boolean {
74
+ return name.startsWith('use') && name.length > 3 && name[3] === name[3].toUpperCase()
75
+ }
76
+ // CIL[END stable_id="~/.framework/functions/_shared/ast.ts:isHook:function"]
77
+ // CIL[DOC-VECTOR type="context" content="purpose='Validation function for identifying React Hook names'; No verified external callers; imports: none"]
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
+
84
+
85
+ // CIL[BEGIN stable_id="~/.framework/functions/_shared/ast.ts:lineOf:function" type="function" identity="lineOf" parent="~/.framework/functions/_shared/ast.ts"]
86
+ // CIL[DOC-MACRO purpose="Compute the 1-based line number of a TypeScript AST node"]
87
+ // CIL[DOC-RESPONSIBILITY responsibility="Convert a node's start position to a human-readable line number"]
88
+ // CIL[DOC-CONTEXT module=".framework/functions/_shared/ast.ts" layer="shared" related_files=".framework/functions/_shared/ast.ts"]
89
+ // CIL[DOC-CONTRACT inputs="sourceFile: ts.SourceFile, node: ts.Node" outputs="number" errors="" side_effects="none"]
90
+ // CIL[DOC-MICRO logic_summary="Uses sourceFile.getLineAndCharacterOfPosition and adds 1"]
91
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
92
+ // CIL[DOC-STABILITY stable]
93
+ function lineOf(sourceFile: ts.SourceFile, node: ts.Node): number {
94
+ return sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1
95
+ }
96
+ // CIL[DOC-VECTOR type="context" content="purpose='Compute the 1-based line number of a TypeScript AST node'; No verified external callers; imports: none"]
97
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
98
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
99
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
100
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
101
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
102
+ // CIL[END stable_id="~/.framework/functions/_shared/ast.ts:lineOf:function"]
103
+
104
+
105
+ // CIL[BEGIN stable_id="~/.framework/functions/_shared/ast.ts:extractIdentities:function" type="function" identity="extractIdentities" parent="~/.framework/functions/_shared/ast.ts"]
106
+ // CIL[DOC-MACRO purpose="Extract candidate code identities from a TypeScript source file"]
107
+ // CIL[DOC-RESPONSIBILITY responsibility="Walk the TypeScript AST and build a list of IdentityProposal objects for CIL chunking"]
108
+ // CIL[DOC-CONTEXT module=".framework/functions/_shared/ast.ts" layer="shared" related_files=".framework/functions/_shared/ast.ts"]
109
+ // CIL[DOC-CONTRACT inputs="sourceFile: ts.SourceFile, fileStableId: string" outputs="IdentityProposal[]" errors="" side_effects="none"]
110
+ // CIL[DOC-MICRO logic_summary="Traverses declarations, class members, interfaces, type aliases, variable statements and export assignments; determines types using isHook, isCapitalized; increments anonymousCounter for default exports"]
111
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
112
+ // CIL[DOC-STABILITY stable]
113
+ export function extractIdentities(sourceFile: ts.SourceFile, fileStableId: string): IdentityProposal[] {
114
+ const proposals: IdentityProposal[] = []
115
+
116
+ proposals.push({
117
+ identity: 'module_header',
118
+ type: 'module_header',
119
+ parent: fileStableId,
120
+ line_start: 1,
121
+ line_end: sourceFile.getLineAndCharacterOfPosition(sourceFile.getFullStart() + sourceFile.getFullWidth()).line + 1,
122
+ text: sourceFile.text,
123
+ })
124
+
125
+ proposals.push({
126
+ identity: 'file',
127
+ type: 'file',
128
+ parent: 'none',
129
+ line_start: 1,
130
+ line_end: sourceFile.getLineAndCharacterOfPosition(sourceFile.getFullStart() + sourceFile.getFullWidth()).line + 1,
131
+ text: sourceFile.text,
132
+ })
133
+
134
+ let anonymousCounter = 0
135
+
136
+ function visit(node: ts.Node, parentId: string) {
137
+ const startLine = lineOf(sourceFile, node)
138
+ const endLine = lineOf(sourceFile, node) + sourceFile.text.slice(node.getStart(), node.getEnd()).split('\n').length - 1
139
+ const text = sourceFile.text.slice(node.getStart(), node.getEnd())
140
+
141
+ if (ts.isFunctionDeclaration(node) && node.name) {
142
+ const name = node.name.text
143
+ const type = isHook(name) ? 'hook' : isCapitalized(name) ? 'component' : 'function'
144
+ proposals.push({ identity: name, type, parent: parentId, line_start: startLine, line_end: endLine, text })
145
+ ts.forEachChild(node, child => visit(child, `${parentId}:${name}:${type}`))
146
+ return
147
+ }
148
+
149
+ if (ts.isClassDeclaration(node) && node.name) {
150
+ const className = node.name.text
151
+ const classId = `${parentId}:${className}:class`
152
+ proposals.push({ identity: className, type: 'class', parent: parentId, line_start: startLine, line_end: endLine, text })
153
+ node.members.forEach(member => {
154
+ if (ts.isMethodDeclaration(member) && member.name) {
155
+ const methodName = ts.isIdentifier(member.name) ? member.name.text : ts.isStringLiteral(member.name) ? member.name.text : String(member.name.getText(sourceFile))
156
+ proposals.push({
157
+ identity: `${className}.${methodName}`,
158
+ type: 'method',
159
+ parent: classId,
160
+ line_start: lineOf(sourceFile, member),
161
+ line_end: lineOf(sourceFile, member) + text.slice(member.getStart(), member.getEnd()).split('\n').length - 1,
162
+ text: sourceFile.text.slice(member.getStart(), member.getEnd()),
163
+ })
164
+ }
165
+ })
166
+ return
167
+ }
168
+
169
+ if (ts.isInterfaceDeclaration(node) && node.name) {
170
+ proposals.push({ identity: node.name.text, type: 'interface', parent: parentId, line_start: startLine, line_end: endLine, text })
171
+ return
172
+ }
173
+
174
+ if (ts.isTypeAliasDeclaration(node) && node.name) {
175
+ proposals.push({ identity: node.name.text, type: 'type', parent: parentId, line_start: startLine, line_end: endLine, text })
176
+ return
177
+ }
178
+
179
+ if (ts.isVariableStatement(node)) {
180
+ for (const decl of node.declarationList.declarations) {
181
+ if (ts.isIdentifier(decl.name)) {
182
+ const name = decl.name.text
183
+ const isConst = Boolean(node.declarationList.flags & ts.NodeFlags.Const)
184
+ let type = isConst ? 'constant' : 'variable'
185
+ if (decl.initializer) {
186
+ if (ts.isArrowFunction(decl.initializer) || ts.isFunctionExpression(decl.initializer)) {
187
+ type = isHook(name) ? 'hook' : isCapitalized(name) ? 'component' : 'function'
188
+ }
189
+ }
190
+ proposals.push({ identity: name, type, parent: parentId, line_start: startLine, line_end: endLine, text })
191
+ }
192
+ }
193
+ return
194
+ }
195
+
196
+ if (ts.isExportAssignment(node)) {
197
+ anonymousCounter += 1
198
+ proposals.push({ identity: 'default', type: 'function', parent: parentId, line_start: startLine, line_end: endLine, text })
199
+ return
200
+ }
201
+
202
+ ts.forEachChild(node, child => visit(child, parentId))
203
+ }
204
+
205
+ visit(sourceFile, fileStableId)
206
+ return proposals
207
+ }
208
+ // CIL[DOC-VECTOR type="context" content="purpose='Extract candidate code identities from a TypeScript source file'; No verified external callers; imports: none"]
209
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
210
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
211
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
212
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
213
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
214
+ // CIL[END stable_id="~/.framework/functions/_shared/ast.ts:extractIdentities:function"]