spine-framework 0.3.124 → 0.3.126

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 (319) hide show
  1. package/.framework/cli/commands/agents.ts +35 -37
  2. package/.framework/cli/commands/auth.ts +35 -34
  3. package/.framework/cli/commands/create-app.ts +104 -40
  4. package/.framework/cli/commands/dev.ts +104 -69
  5. package/.framework/cli/commands/doctor.ts +179 -69
  6. package/.framework/cli/commands/generate.ts +83 -143
  7. package/.framework/cli/commands/init.ts +72 -34
  8. package/.framework/cli/commands/install-app.ts +260 -125
  9. package/.framework/cli/commands/items.ts +33 -44
  10. package/.framework/cli/commands/migrate.ts +122 -40
  11. package/.framework/cli/commands/migrations.ts +33 -40
  12. package/.framework/cli/commands/pipelines.ts +31 -39
  13. package/.framework/cli/commands/status.ts +47 -23
  14. package/.framework/cli/commands/system.ts +47 -37
  15. package/.framework/cli/commands/test.ts +112 -68
  16. package/.framework/cli/commands/validate-app.ts +215 -121
  17. package/.framework/cli/context.ts +112 -130
  18. package/.framework/cli/env-loader.ts +47 -18
  19. package/.framework/cli/index.ts +81 -42
  20. package/.framework/docs/runtime-types.md +1024 -0
  21. package/.framework/functions/_shared/agent-runner.ts +1296 -961
  22. package/.framework/functions/_shared/app-manifest.ts +82 -68
  23. package/.framework/functions/_shared/audit.ts +135 -83
  24. package/.framework/functions/_shared/{cil-state.ts → cil.ts} +158 -56
  25. package/.framework/functions/_shared/db.ts +80 -126
  26. package/.framework/functions/_shared/hash-api-key.ts +63 -0
  27. package/.framework/functions/_shared/index.ts +224 -335
  28. package/.framework/functions/_shared/kb.ts +319 -0
  29. package/.framework/functions/_shared/llm.ts +92 -0
  30. package/.framework/functions/_shared/logging.ts +288 -0
  31. package/.framework/functions/_shared/middleware.ts +329 -365
  32. package/.framework/functions/_shared/outcomes.ts +36 -0
  33. package/.framework/functions/_shared/permissions.ts +359 -643
  34. package/.framework/functions/_shared/pipeline-runner.ts +243 -316
  35. package/.framework/functions/_shared/principal.ts +376 -468
  36. package/.framework/functions/_shared/resolve-credentials.ts +102 -0
  37. package/.framework/functions/_shared/resolve-ids.ts +188 -16
  38. package/.framework/functions/_shared/retry-deliveries.ts +104 -0
  39. package/.framework/functions/_shared/schema-utils.ts +611 -373
  40. package/.framework/functions/_shared/testing.ts +207 -137
  41. package/.framework/functions/_shared/tracing.ts +276 -0
  42. package/.framework/functions/_shared/trigger-engine.ts +159 -211
  43. package/.framework/functions/_shared/webhook-registration.ts +95 -81
  44. package/.framework/functions/_shared/webhook-registry.ts +153 -75
  45. package/.framework/functions/account-nodes.ts +31 -53
  46. package/.framework/functions/adapters/generic-webhook-inbound.ts +56 -0
  47. package/.framework/functions/adapters/generic-webhook-outbound.ts +43 -0
  48. package/.framework/functions/adapters/openai-outbound.ts +40 -0
  49. package/.framework/functions/admin-data.ts +685 -537
  50. package/.framework/functions/admin-funnel.ts +31 -20
  51. package/.framework/functions/admin-install-funnel.ts +47 -28
  52. package/.framework/functions/admin-signals.ts +47 -29
  53. package/.framework/functions/ai-agents.ts +122 -147
  54. package/.framework/functions/ai-interactions.ts +180 -90
  55. package/.framework/functions/api-keys.ts +250 -192
  56. package/.framework/functions/apps.ts +203 -197
  57. package/.framework/functions/auth.ts +98 -91
  58. package/.framework/functions/cil-agent-ingest.ts +773 -0
  59. package/.framework/functions/cil-agent.ts +592 -0
  60. package/.framework/functions/cil-callmap.ts +1227 -0
  61. package/.framework/functions/cil-config.ts +583 -0
  62. package/.framework/functions/cil-context.ts +445 -0
  63. package/.framework/functions/cil-doc.ts +1752 -0
  64. package/.framework/functions/cil-embeddings.ts +1202 -0
  65. package/.framework/functions/cil-graph.ts +585 -0
  66. package/.framework/functions/cil-ingest.ts +2416 -0
  67. package/.framework/functions/cil-pipeline.ts +318 -0
  68. package/.framework/functions/cil-project.ts +499 -0
  69. package/.framework/functions/cil-validate.ts +469 -0
  70. package/.framework/functions/debug-auth.ts +73 -53
  71. package/.framework/functions/deliveries.ts +117 -0
  72. package/.framework/functions/embeddings.ts +528 -516
  73. package/.framework/functions/eval-harness.ts +158 -106
  74. package/.framework/functions/integration-outbound.ts +311 -0
  75. package/.framework/functions/integration-routes.ts +240 -466
  76. package/.framework/functions/integrations.ts +132 -140
  77. package/.framework/functions/invites.ts +401 -201
  78. package/.framework/functions/item-progress.ts +113 -53
  79. package/.framework/functions/kb.ts +28 -0
  80. package/.framework/functions/logs.ts +239 -222
  81. package/.framework/functions/observability.ts +308 -259
  82. package/.framework/functions/pipeline-executions.ts +179 -235
  83. package/.framework/functions/pipelines.ts +163 -205
  84. package/.framework/functions/prompt-configs.ts +109 -156
  85. package/.framework/functions/roles.ts +97 -147
  86. package/.framework/functions/system-cron.ts +132 -218
  87. package/.framework/functions/system.ts +112 -52
  88. package/.framework/functions/tests.ts +32 -28
  89. package/.framework/functions/timers.ts +162 -210
  90. package/.framework/functions/triggers.ts +282 -346
  91. package/.framework/functions/types.ts +283 -400
  92. package/.framework/migrations/001_core_schema.sql +630 -0
  93. package/.framework/migrations/002_core_rls_and_functions.sql +532 -0
  94. package/.framework/migrations/{003_system_data.sql → 003_core_system_data.sql} +26 -153
  95. package/.framework/migrations/004_core_rpc_and_broker.sql +421 -0
  96. package/.framework/migrations/005_core_observability.sql +598 -0
  97. package/.framework/migrations/006_security_hardening_rls.sql +97 -0
  98. package/.framework/migrations/007_kb_article_list.sql +237 -0
  99. package/.framework/migrations/008_items_target.sql +8 -0
  100. package/.framework/migrations/009_roles_slug_unique.sql +11 -0
  101. package/.framework/public/spine.config.json +91 -0
  102. package/.framework/scripts/app-install-cli.ts +112 -98
  103. package/.framework/src/App.tsx +67 -20
  104. package/.framework/src/apps/admin/index.tsx +97 -27
  105. package/.framework/src/components/AppWrapper.tsx +50 -11
  106. package/.framework/src/components/CustomAppLoader.tsx +131 -22
  107. package/.framework/src/components/admin/AdminListPage.tsx +75 -8
  108. package/.framework/src/components/admin/AdminSidebar.tsx +148 -36
  109. package/.framework/src/components/admin/AdminStatsCard.tsx +48 -29
  110. package/.framework/src/components/admin/PageInstructions.tsx +49 -0
  111. package/.framework/src/components/admin/SortableTableHeader.tsx +49 -2
  112. package/.framework/src/components/app-shell/GenericAppShell.tsx +69 -11
  113. package/.framework/src/components/app-shell/GenericDetailPage.tsx +55 -10
  114. package/.framework/src/components/app-shell/GenericListPage.tsx +76 -9
  115. package/.framework/src/components/app-sidebar.tsx +50 -3
  116. package/.framework/src/components/auth/ProtectedRoute.tsx +53 -45
  117. package/.framework/src/components/kb/KBArticleEditor.tsx +409 -0
  118. package/.framework/src/components/kb/KBArticleList.tsx +557 -0
  119. package/.framework/src/components/layout/AppShell.tsx +54 -16
  120. package/.framework/src/components/layout/Header.tsx +50 -38
  121. package/.framework/src/components/layout/Layout.tsx +48 -32
  122. package/.framework/src/components/layout/Sidebar.tsx +167 -16
  123. package/.framework/src/components/runtime/DataDetailHeader.tsx +33 -1
  124. package/.framework/src/components/runtime/DataDetailPage.tsx +289 -4
  125. package/.framework/src/components/runtime/DataFilters.tsx +78 -1
  126. package/.framework/src/components/runtime/DataHeader.tsx +32 -29
  127. package/.framework/src/components/runtime/DataListPage.tsx +161 -2
  128. package/.framework/src/components/runtime/DataStats.tsx +48 -1
  129. package/.framework/src/components/runtime/DataTable.tsx +153 -1
  130. package/.framework/src/components/runtime/SchemaDetailForm.tsx +77 -46
  131. package/.framework/src/components/runtime/index.ts +16 -9
  132. package/.framework/src/components/search-form.tsx +33 -1
  133. package/.framework/src/components/shared/AgentView.tsx +48 -51
  134. package/.framework/src/components/shared/FieldRenderer.tsx +84 -67
  135. package/.framework/src/components/shared/InviteManager.tsx +113 -52
  136. package/.framework/src/components/shared/MemberList.tsx +182 -0
  137. package/.framework/src/components/shared/SchemaFields.tsx +96 -78
  138. package/.framework/src/components/ui/DataTable.tsx +86 -56
  139. package/.framework/src/components/ui/Form.tsx +188 -109
  140. package/.framework/src/components/ui/ItemCard.tsx +86 -58
  141. package/.framework/src/components/ui/ItemListView.tsx +88 -61
  142. package/.framework/src/components/ui/LoadingSpinner.tsx +52 -27
  143. package/.framework/src/components/ui/Modal.tsx +81 -4
  144. package/.framework/src/components/ui/RichTextEditor.tsx +101 -9
  145. package/.framework/src/components/ui/accordion.tsx +97 -5
  146. package/.framework/src/components/ui/alert-dialog.tsx +225 -13
  147. package/.framework/src/components/ui/alert.tsx +113 -6
  148. package/.framework/src/components/ui/aspect-ratio.tsx +49 -2
  149. package/.framework/src/components/ui/avatar.tsx +129 -7
  150. package/.framework/src/components/ui/badge.tsx +65 -3
  151. package/.framework/src/components/ui/breadcrumb.tsx +145 -8
  152. package/.framework/src/components/ui/button-group.tsx +81 -4
  153. package/.framework/src/components/ui/button.tsx +49 -2
  154. package/.framework/src/components/ui/calendar.tsx +65 -3
  155. package/.framework/src/components/ui/card.tsx +145 -8
  156. package/.framework/src/components/ui/carousel.tsx +129 -7
  157. package/.framework/src/components/ui/chart.tsx +161 -10
  158. package/.framework/src/components/ui/checkbox.tsx +49 -2
  159. package/.framework/src/components/ui/collapsible.tsx +81 -5
  160. package/.framework/src/components/ui/combobox.tsx +305 -20
  161. package/.framework/src/components/ui/command.tsx +177 -11
  162. package/.framework/src/components/ui/context-menu.tsx +273 -17
  163. package/.framework/src/components/ui/dialog.tsx +209 -27
  164. package/.framework/src/components/ui/direction.tsx +64 -4
  165. package/.framework/src/components/ui/drawer.tsx +193 -12
  166. package/.framework/src/components/ui/dropdown-menu.tsx +273 -18
  167. package/.framework/src/components/ui/empty.tsx +145 -9
  168. package/.framework/src/components/ui/field.tsx +209 -14
  169. package/.framework/src/components/ui/hover-card.tsx +81 -4
  170. package/.framework/src/components/ui/input-group.tsx +162 -10
  171. package/.framework/src/components/ui/input-otp.tsx +98 -5
  172. package/.framework/src/components/ui/input.tsx +49 -2
  173. package/.framework/src/components/ui/item.tsx +225 -13
  174. package/.framework/src/components/ui/kbd.tsx +65 -3
  175. package/.framework/src/components/ui/label.tsx +49 -2
  176. package/.framework/src/components/ui/menubar.tsx +289 -17
  177. package/.framework/src/components/ui/native-select.tsx +97 -5
  178. package/.framework/src/components/ui/navigation-menu.tsx +177 -10
  179. package/.framework/src/components/ui/pagination.tsx +161 -9
  180. package/.framework/src/components/ui/popover.tsx +145 -8
  181. package/.framework/src/components/ui/progress.tsx +49 -2
  182. package/.framework/src/components/ui/radio-group.tsx +65 -3
  183. package/.framework/src/components/ui/resizable.tsx +82 -4
  184. package/.framework/src/components/ui/scroll-area.tsx +65 -3
  185. package/.framework/src/components/ui/select.tsx +193 -11
  186. package/.framework/src/components/ui/separator.tsx +49 -2
  187. package/.framework/src/components/ui/sheet.tsx +193 -11
  188. package/.framework/src/components/ui/sidebar.tsx +481 -38
  189. package/.framework/src/components/ui/skeleton.tsx +49 -2
  190. package/.framework/src/components/ui/slider.tsx +49 -2
  191. package/.framework/src/components/ui/sonner.tsx +49 -2
  192. package/.framework/src/components/ui/spinner.tsx +49 -2
  193. package/.framework/src/components/ui/switch.tsx +49 -2
  194. package/.framework/src/components/ui/table-primitives.tsx +160 -33
  195. package/.framework/src/components/ui/table.tsx +161 -9
  196. package/.framework/src/components/ui/tabs.tsx +113 -6
  197. package/.framework/src/components/ui/textarea.tsx +49 -2
  198. package/.framework/src/components/ui/toggle-group.tsx +81 -4
  199. package/.framework/src/components/ui/toggle.tsx +65 -3
  200. package/.framework/src/components/ui/tooltip.tsx +97 -5
  201. package/.framework/src/contexts/AppContext.tsx +129 -45
  202. package/.framework/src/contexts/AuthContext.tsx +187 -144
  203. package/.framework/src/hooks/use-mobile.ts +48 -2
  204. package/.framework/src/hooks/useApi.ts +208 -159
  205. package/.framework/src/hooks/useAppPath.ts +32 -23
  206. package/.framework/src/hooks/useApps.ts +51 -20
  207. package/.framework/src/hooks/useEntityList.ts +32 -78
  208. package/.framework/src/hooks/useEntityRecord.ts +35 -96
  209. package/.framework/src/hooks/useForm.ts +32 -92
  210. package/.framework/src/hooks/useListSchema.ts +49 -78
  211. package/.framework/src/hooks/useSchemaRecord.ts +114 -105
  212. package/.framework/src/lib/api.ts +195 -116
  213. package/.framework/src/lib/supabase.ts +98 -64
  214. package/.framework/src/lib/utils.ts +287 -151
  215. package/.framework/src/main.tsx +49 -3
  216. package/.framework/src/pages/DashboardPage.tsx +52 -29
  217. package/.framework/src/pages/NotFoundPage.tsx +32 -10
  218. package/.framework/src/pages/SetupPage.tsx +32 -12
  219. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +119 -10
  220. package/.framework/src/pages/admin/AIAgentsPage.tsx +48 -19
  221. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +187 -17
  222. package/.framework/src/pages/admin/APIKeysPage.tsx +98 -22
  223. package/.framework/src/pages/admin/AlertsConfigPage.tsx +113 -26
  224. package/.framework/src/pages/admin/AppDetailPage.tsx +125 -8
  225. package/.framework/src/pages/admin/AppsPage.tsx +49 -2
  226. package/.framework/src/pages/admin/DeliveriesPage.tsx +196 -0
  227. package/.framework/src/pages/admin/DesignedPage.tsx +32 -18
  228. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +215 -484
  229. package/.framework/src/pages/admin/EmbeddingsPage.tsx +116 -319
  230. package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +34 -9
  231. package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +34 -9
  232. package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -16
  233. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +183 -26
  234. package/.framework/src/pages/admin/IntegrationsPage.tsx +48 -19
  235. package/.framework/src/pages/admin/InvitesPage.tsx +48 -14
  236. package/.framework/src/pages/admin/LogsPage.tsx +422 -75
  237. package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +34 -9
  238. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +113 -24
  239. package/.framework/src/pages/admin/PipelineDetailPage.tsx +206 -34
  240. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +50 -17
  241. package/.framework/src/pages/admin/PipelinesPage.tsx +160 -21
  242. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +378 -88
  243. package/.framework/src/pages/admin/PromptConfigsPage.tsx +125 -16
  244. package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +49 -10
  245. package/.framework/src/pages/admin/RoleDetailPage.tsx +130 -10
  246. package/.framework/src/pages/admin/RolesPage.tsx +171 -18
  247. package/.framework/src/pages/admin/SelectTestPage.tsx +34 -9
  248. package/.framework/src/pages/admin/ShadcnTestPage.tsx +49 -11
  249. package/.framework/src/pages/admin/SimpleDashboard.tsx +49 -10
  250. package/.framework/src/pages/admin/TestRunDetailPage.tsx +49 -4
  251. package/.framework/src/pages/admin/TestingDashboard.tsx +98 -28
  252. package/.framework/src/pages/admin/TimerDetailPage.tsx +143 -33
  253. package/.framework/src/pages/admin/TimersPage.tsx +48 -20
  254. package/.framework/src/pages/admin/TriggerDetailPage.tsx +118 -30
  255. package/.framework/src/pages/admin/TriggersPage.tsx +64 -19
  256. package/.framework/src/pages/admin/TypeDetailPage.tsx +138 -15
  257. package/.framework/src/pages/admin/TypesPage.tsx +48 -20
  258. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +465 -0
  259. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +787 -0
  260. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +699 -0
  261. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +647 -0
  262. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +616 -0
  263. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +1402 -0
  264. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +614 -0
  265. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +571 -0
  266. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +731 -0
  267. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
  268. package/.framework/src/pages/auth/AuthConfirmPage.tsx +52 -51
  269. package/.framework/src/pages/auth/ForgotPasswordPage.tsx +31 -22
  270. package/.framework/src/pages/auth/LoginPage.tsx +50 -23
  271. package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -15
  272. package/.framework/src/pages/auth/RegisterPage.tsx +281 -317
  273. package/.framework/src/pages/spine-framework/APIPage.tsx +33 -0
  274. package/.framework/src/pages/spine-framework/CLIPage.tsx +33 -0
  275. package/.framework/src/types/auth.ts +128 -71
  276. package/.framework/src/types/types.ts +373 -157
  277. package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +39 -0
  278. package/custom/.devin/skills/spine-workbench-idea/SKILL.md +36 -0
  279. package/custom/.devin/skills/spine-workbench-implement/SKILL.md +46 -0
  280. package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +28 -0
  281. package/custom/.devin/skills/spine-workbench-plan/SKILL.md +38 -0
  282. package/docs/README.md +9 -130
  283. package/netlify.toml +5 -2
  284. package/package.json +13 -25
  285. package/scripts/kb-ingest-docs.ts +203 -0
  286. package/spine.config.json +65 -4
  287. package/.framework/migrations/001_schema.sql +0 -425
  288. package/.framework/migrations/002_rls_and_functions.sql +0 -763
  289. package/.framework/migrations/004_enhancements.sql +0 -43
  290. package/.framework/migrations/005_auth_user_trigger.sql +0 -105
  291. package/.framework/migrations/006_fix_current_actor_id.sql +0 -21
  292. package/.framework/migrations/016_invites.sql +0 -27
  293. package/.framework/migrations/017_fix_get_account_apps.sql +0 -78
  294. package/.framework/migrations/018_apps_required_roles.sql +0 -17
  295. package/.framework/migrations/019_triggers_unique_constraint.sql +0 -13
  296. package/.framework/migrations/020_get_account_apps_role_filter.sql +0 -117
  297. package/.framework/migrations/021_app_domains.sql +0 -112
  298. package/.framework/migrations/022_route_prefix_domain_unique.sql +0 -21
  299. package/.framework/migrations/023_match_embeddings_rpc.sql +0 -78
  300. package/.framework/migrations/024_messages_account_id.sql +0 -9
  301. package/.framework/migrations/025_retype_threads_messages.sql +0 -240
  302. package/.framework/migrations/026_fix_rls_policies.sql +0 -47
  303. package/.framework/migrations/027_embedding_lifecycle.sql +0 -176
  304. package/.framework/migrations/028_fix_message_data_permissions.sql +0 -49
  305. package/.framework/migrations/029_tighten_support_triage_prompt.sql +0 -41
  306. package/.framework/migrations/030_messages_updated_by.sql +0 -6
  307. package/.framework/migrations/031_seed_upsert_constraints.sql +0 -35
  308. package/docs/APPS.md +0 -232
  309. package/docs/ARCHITECTURE.md +0 -246
  310. package/docs/INSTALL.md +0 -155
  311. package/docs/design-schema-spec.md +0 -1837
  312. package/docs/dev-guides/01-create-an-app.md +0 -183
  313. package/docs/dev-guides/02-create-a-function.md +0 -178
  314. package/docs/dev-guides/03-create-a-component.md +0 -178
  315. package/docs/dev-guides/04-webhook-handlers.md +0 -129
  316. package/docs/dev-guides/05-testing.md +0 -168
  317. package/docs/dev-guides/README.md +0 -40
  318. package/docs/npm-packages-plan.md +0 -288
  319. package/docs/spine-core--api-reference.md +0 -822
@@ -0,0 +1,1227 @@
1
+
2
+ const MAP_SOURCE_STATUS: Record<'first' | 'second', { prior: string; target: string }> = {
3
+ first: { prior: '6-embedded', target: '7-mapped' },
4
+ second: { prior: '9-embedded', target: '10-mapped' },
5
+ }
6
+
7
+ function getMapSourceFilePaths(projectItem: any, secondPass: boolean): string[] {
8
+ const fileStatuses: Record<string, string> = projectItem?.data?.file_statuses || {}
9
+ const { prior } = secondPass ? MAP_SOURCE_STATUS.second : MAP_SOURCE_STATUS.first
10
+ return Object.entries(fileStatuses)
11
+ .filter(([, status]) => status === prior)
12
+ .map(([filePath]) => filePath)
13
+ }
14
+
15
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_module_header_1784235266" type="module_header" identity="module_header" parent="none"]
16
+ // CIL[DOC-MACRO purpose="Module header and top-level exports for cortex.functions.custom_cil-callmap"]
17
+ // CIL[DOC-RESPONSIBILITY responsibility="Own module-level imports, exports, and configuration for cortex.functions.custom_cil-callmap"]
18
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[\".framework/migrations/015_simplify_apps_table.sql\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/components/ui/table-primitives.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"\\\"]"]
19
+ // CIL[DOC-CONTRACT inputs="none" outputs="module exports and side effects" errors="none" side_effects="none"]
20
+ // CIL[DOC-MICRO logic_summary="Declares module scope, imports dependencies, and exports public surface of cortex.functions.custom_cil-callmap" notable_decisions="[]"]
21
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
22
+ // CIL[DOC-STABILITY stability="stable"]
23
+ // CIL[DOC-AUDIENCE audience="developer"]
24
+ // CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: .framework/migrations/015_simplify_apps_table.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, custom/apps/portal/pages/ContentPage.tsx, .framework/src/components/ui/table-primitives.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
25
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
26
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
27
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
28
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
29
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
30
+
31
+
32
+
33
+
34
+
35
+ import { createHandler } from './_shared/middleware'
36
+ import { adminDb } from './_shared/db'
37
+ import { resolveLinkTypeId } from './_shared/resolve-ids'
38
+ import { create as adminCreate, update as adminUpdate } from './admin-data'
39
+ import { FileStatus, FileTreeNode, isSelectedPath, getFileStatus, updateTreeNodeStatus, saveProjectTree } from './_shared/cil'
40
+ import * as fs from 'fs'
41
+ import * as path from 'path'
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_module_header_1784235266"]
52
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_status_rank_1784235266" type="variable" identity="status_rank" parent="none"]
53
+ // CIL[DOC-MACRO purpose="Defines status_rank configuration or state in cortex.functions.custom_cil-callmap"]
54
+ // CIL[DOC-RESPONSIBILITY responsibility="Hold the value and default configuration for status_rank"]
55
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/functions/_shared/principal.ts\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\"custom/apps/portal/pages/ContentPage.tsx\",\"\\\"]"]
56
+ // CIL[DOC-CONTRACT inputs="none" outputs="value of status_rank" errors="none" side_effects="none"]
57
+ // CIL[DOC-MICRO logic_summary="Declares status_rank with initial value or constant binding used by cortex.functions.custom_cil-callmap" notable_decisions="[]"]
58
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
59
+ // CIL[DOC-STABILITY stability="stable"]
60
+ // CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/principal.ts, custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/src/pages/admin/IntegrationsPage.tsx, custom/apps/portal/pages/ContentPage.tsx, \."]
61
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
62
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
63
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
64
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
65
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
66
+ const STATUS_RANK: Record<string, number> = {
67
+ '2-discovered': 2,
68
+ '3-selected': 3,
69
+ '4-chunked': 4,
70
+ '5-documented': 5,
71
+ '6-embedded': 6,
72
+ '7-mapped': 7,
73
+ '8-enriched': 8,
74
+ '9-embedded': 9,
75
+ '10-mapped': 10,
76
+
77
+ 'pass2_complete': 4,
78
+ 'pass3_complete': 5,
79
+ 'pass4_complete': 6,
80
+ 'pass4b_complete': 7,
81
+ 'pass6_complete': 8,
82
+ 'pass7_complete': 9,
83
+ 'pass8_complete': 10,
84
+ }
85
+
86
+ // Keep REST URL length under the ~8k character limit for UUID IN clauses.
87
+ const UUID_IN_LIMIT = 100
88
+
89
+
90
+
91
+
92
+
93
+
94
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_status_rank_1784235266"]
95
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_rank_1784235266" type="function" identity="rank" parent="none"]
96
+ // CIL[DOC-MACRO purpose="Implements rank logic in cortex.functions.custom_cil-callmap"]
97
+ // CIL[DOC-RESPONSIBILITY responsibility="Execute rank and return its computed result"]
98
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/functions/_shared/principal.ts\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/migrations/015_simplify_apps_table.sql\",\"\\\"]"]
99
+ // CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
100
+ // CIL[DOC-MICRO logic_summary="Provides rank with rank(status: string | undefined inputs, handling internal flow and returning a result" notable_decisions="[]"]
101
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
102
+ // CIL[DOC-STABILITY stability="stable"]
103
+ // CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 2. Direct calls: 0. Related files: custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/functions/_shared/principal.ts, .framework/src/pages/admin/TypeDetailPage.tsx, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/migrations/015_simplify_apps_table.sql, \."]
104
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 2. Total affected: 2."]
105
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
106
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
107
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
108
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
109
+ function rank(status: string | undefined): number {
110
+ return status ? STATUS_RANK[status] || 0 : 0
111
+ }
112
+
113
+
114
+
115
+
116
+
117
+
118
+
119
+
120
+
121
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_rank_1784235266"]
122
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractedimport_1784235266" type="interface" identity="extractedimport" parent="none"]
123
+ // CIL[DOC-MACRO purpose="Defines the extractedimport type contract in cortex.functions.custom_cil-callmap"]
124
+ // CIL[DOC-RESPONSIBILITY responsibility="Describe the shape and allowed fields for extractedimport"]
125
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/migrations/015_simplify_apps_table.sql\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"\\\"]"]
126
+ // CIL[DOC-CONTRACT inputs="none" outputs="type definition for extractedimport" errors="none" side_effects="none"]
127
+ // CIL[DOC-MICRO logic_summary="Declares TypeScript type/interface extractedimport with member definitions" notable_decisions="[]"]
128
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
129
+ // CIL[DOC-STABILITY stability="stable"]
130
+ // CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/principal.ts, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/migrations/015_simplify_apps_table.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
131
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
132
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
133
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
134
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
135
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
136
+ interface ExtractedImport {
137
+ from_path: string
138
+ symbols: string[]
139
+ is_default: boolean
140
+ }
141
+
142
+
143
+
144
+
145
+
146
+
147
+
148
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractedimport_1784235266"]
149
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractedcall_1784235266" type="interface" identity="extractedcall" parent="none"]
150
+ // CIL[DOC-MACRO purpose="Defines the extractedcall type contract in cortex.functions.custom_cil-callmap"]
151
+ // CIL[DOC-RESPONSIBILITY responsibility="Describe the shape and allowed fields for extractedcall"]
152
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/migrations/015_simplify_apps_table.sql\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"\\\"]"]
153
+ // CIL[DOC-CONTRACT inputs="none" outputs="type definition for extractedcall" errors="none" side_effects="none"]
154
+ // CIL[DOC-MICRO logic_summary="Declares TypeScript type/interface extractedcall with member definitions" notable_decisions="[]"]
155
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
156
+ // CIL[DOC-STABILITY stability="stable"]
157
+ // CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/principal.ts, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/migrations/015_simplify_apps_table.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
158
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
159
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
160
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
161
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
162
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
163
+ interface ExtractedCall {
164
+ callee_name: string
165
+ is_await: boolean
166
+ }
167
+
168
+
169
+
170
+
171
+
172
+
173
+
174
+
175
+
176
+
177
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractedcall_1784235266"]
178
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractimports_1784235266" type="function" identity="extractimports" parent="none"]
179
+ // CIL[DOC-MACRO purpose="Implements extractimports logic in cortex.functions.custom_cil-callmap"]
180
+ // CIL[DOC-RESPONSIBILITY responsibility="Execute extractimports and return its computed result"]
181
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
182
+ // CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
183
+ // CIL[DOC-MICRO logic_summary="Provides extractimports with extractImports(source: string inputs, handling internal flow and returning a result" notable_decisions="[]"]
184
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
185
+ // CIL[DOC-STABILITY stability="stable"]
186
+ // CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
187
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
188
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
189
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
190
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
191
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
192
+ export function extractImports(source: string): ExtractedImport[] {
193
+ const results: ExtractedImport[] = []
194
+
195
+ const importRe = /^import\s+([\s\S]*?)\s+from\s+['"]([^'"]+)['"]/gm
196
+ let m: RegExpExecArray | null
197
+ while ((m = importRe.exec(source)) !== null) {
198
+ const specifierBlock = m[1].trim()
199
+ const fromPath = m[2]
200
+
201
+ let symbols: string[] = []
202
+ let isDefault = false
203
+
204
+ if (specifierBlock.startsWith('{')) {
205
+
206
+ const inner = specifierBlock.replace(/^\{|\}$/g, '').trim()
207
+ symbols = inner.split(',').map(s => {
208
+ const parts = s.trim().split(/\s+as\s+/)
209
+ return (parts[parts.length - 1] || '').trim()
210
+ }).filter(Boolean)
211
+ } else if (specifierBlock.startsWith('*')) {
212
+
213
+ const asMatch = specifierBlock.match(/\*\s+as\s+(\w+)/)
214
+ if (asMatch) symbols = [asMatch[1]]
215
+ } else {
216
+
217
+ const defaultMatch = specifierBlock.match(/^(\w+)/)
218
+ if (defaultMatch) { symbols = [defaultMatch[1]]; isDefault = true }
219
+ const namedMatch = specifierBlock.match(/\{([^}]+)\}/)
220
+ if (namedMatch) {
221
+ const named = namedMatch[1].split(',').map(s => s.trim().split(/\s+as\s+/).pop()!.trim()).filter(Boolean)
222
+ symbols = [...symbols, ...named]
223
+ }
224
+ }
225
+
226
+ results.push({ from_path: fromPath, symbols, is_default: isDefault })
227
+ }
228
+ return results
229
+ }
230
+
231
+
232
+
233
+
234
+
235
+
236
+
237
+
238
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractimports_1784235266"]
239
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractcalls_1784235266" type="function" identity="extractcalls" parent="none"]
240
+ // CIL[DOC-MACRO purpose="Implements extractcalls logic in cortex.functions.custom_cil-callmap"]
241
+ // CIL[DOC-RESPONSIBILITY responsibility="Execute extractcalls and return its computed result"]
242
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
243
+ // CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
244
+ // CIL[DOC-MICRO logic_summary="Provides extractcalls with extractCalls(source: string inputs, handling internal flow and returning a result" notable_decisions="[]"]
245
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
246
+ // CIL[DOC-STABILITY stability="stable"]
247
+ // CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
248
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
249
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
250
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
251
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
252
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
253
+ export function extractCalls(source: string): ExtractedCall[] {
254
+ const seen = new Set<string>()
255
+ const results: ExtractedCall[] = []
256
+
257
+
258
+ const callRe = /(await\s+)?(?:[\w$]+\.)*?([\w$]{2,})\s*\(/g
259
+ let m: RegExpExecArray | null
260
+ while ((m = callRe.exec(source)) !== null) {
261
+ const isAwait = !!m[1]
262
+ const calleeName = m[2]
263
+
264
+
265
+ if (['if', 'for', 'while', 'switch', 'catch', 'return', 'new', 'typeof', 'instanceof', 'function'].includes(calleeName)) continue
266
+ if (calleeName.length < 3) continue
267
+
268
+
269
+ if (['ctx', 'req', 'res', 'data', 'props', 'state', 'params', 'config', 'options', 'args'].includes(calleeName)) continue
270
+
271
+ if (seen.has(calleeName)) continue
272
+ seen.add(calleeName)
273
+ results.push({ callee_name: calleeName, is_await: isAwait })
274
+ }
275
+ return results
276
+ }
277
+
278
+
279
+
280
+
281
+
282
+
283
+
284
+
285
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractcalls_1784235266"]
286
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractsymbolreferences_1784235266" type="function" identity="extractsymbolreferences" parent="none"]
287
+ // CIL[DOC-MACRO purpose="Find symbol/name references from one chunk to other chunk identities"]
288
+ // CIL[DOC-RESPONSIBILITY responsibility="Detect non-call references to exported chunk names/types to enrich the call graph"]
289
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
290
+ // CIL[DOC-CONTRACT inputs="source string, candidate symbol list" outputs="matching symbol names" errors="none" side_effects="none"]
291
+ // CIL[DOC-MICRO logic_summary="Builds a single regex from chunk identities and returns the set of names found as whole-word tokens in the source" notable_decisions="[]"]
292
+ // CIL[DOC-CONFIDENCE pass="first" score="0.85" flags="possible_false_positives"]
293
+ // CIL[DOC-STABILITY stability="experimental"]
294
+ function escapeRegex(s: string): string {
295
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
296
+ }
297
+
298
+ function extractSymbolReferences(source: string, candidateNames: string[], ownName?: string): string[] {
299
+ const reserved = new Set(['if','for','while','switch','catch','return','new','typeof','instanceof','function','const','let','var','class','interface','type','enum','export','import','from','await','async','true','false','null','undefined','this','super','extends','implements','as','in','of','with','yield'])
300
+ const candidates = candidateNames
301
+ .filter(n => n && n !== ownName && n.length >= 2 && !reserved.has(n))
302
+ .sort((a, b) => b.length - a.length)
303
+ if (candidates.length === 0) return []
304
+
305
+ const pattern = new RegExp(`(?:^|[^A-Za-z0-9_$])(${candidates.map(escapeRegex).join('|')})(?=[^A-Za-z0-9_$]|$)`, 'g')
306
+ const seen = new Set<string>()
307
+ let m: RegExpExecArray | null
308
+ while ((m = pattern.exec(source)) !== null) {
309
+ seen.add(m[1])
310
+ }
311
+ return [...seen]
312
+ }
313
+
314
+
315
+
316
+
317
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractsymbolreferences_1784235266"]
318
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractexports_1784235266" type="function" identity="extractexports" parent="none"]
319
+ // CIL[DOC-MACRO purpose="Implements extractexports logic in cortex.functions.custom_cil-callmap"]
320
+ // CIL[DOC-RESPONSIBILITY responsibility="Execute extractexports and return its computed result"]
321
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
322
+ // CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
323
+ // CIL[DOC-MICRO logic_summary="Provides extractexports with extractExports(source: string inputs, handling internal flow and returning a result" notable_decisions="[]"]
324
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
325
+ // CIL[DOC-STABILITY stability="stable"]
326
+ // CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
327
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
328
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
329
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
330
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
331
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
332
+ export function extractExports(source: string): string[] {
333
+ const exports: string[] = []
334
+
335
+ const exportRe = /^export\s+(?:default\s+)?(?:async\s+)?(?:function|class|const|let|var|type|interface|enum)\s+(\w+)/gm
336
+ let m: RegExpExecArray | null
337
+ while ((m = exportRe.exec(source)) !== null) {
338
+ exports.push(m[1])
339
+ }
340
+
341
+ const namedRe = /^export\s+\{([^}]+)\}/gm
342
+ while ((m = namedRe.exec(source)) !== null) {
343
+ const named = m[1].split(',').map(s => s.trim().split(/\s+as\s+/).pop()!.trim()).filter(Boolean)
344
+ exports.push(...named)
345
+ }
346
+ return [...new Set(exports)]
347
+ }
348
+
349
+
350
+
351
+
352
+
353
+
354
+
355
+
356
+
357
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_extractexports_1784235266"]
358
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_resolveimportpath_1784235266" type="function" identity="resolveimportpath" parent="none"]
359
+ // CIL[DOC-MACRO purpose="Implements resolveimportpath logic in cortex.functions.custom_cil-callmap"]
360
+ // CIL[DOC-RESPONSIBILITY responsibility="Execute resolveimportpath and return its computed result"]
361
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
362
+ // CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
363
+ // CIL[DOC-MICRO logic_summary="Provides resolveimportpath with resolveImportPath(fromFilePath: string, importSpecifier: string inputs, handling internal flow and returning a result" notable_decisions="[]"]
364
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
365
+ // CIL[DOC-STABILITY stability="stable"]
366
+ // CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
367
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
368
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
369
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
370
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
371
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
372
+ function resolveImportPath(fromFilePath: string, importSpecifier: string): string | null {
373
+
374
+ if (!importSpecifier.startsWith('.')) return null
375
+
376
+ const fromDir = fromFilePath.split('/').slice(0, -1).join('/')
377
+ const segments = `${fromDir}/${importSpecifier}`.split('/')
378
+ const resolved: string[] = []
379
+
380
+ for (const seg of segments) {
381
+ if (seg === '..') resolved.pop()
382
+ else if (seg !== '.') resolved.push(seg)
383
+ }
384
+
385
+ const base = resolved.join('/')
386
+
387
+ return base
388
+ }
389
+
390
+
391
+
392
+
393
+
394
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_resolveimportpath_1784235266"]
395
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_upsertlink_1784235266" type="function" identity="upsertlink" parent="none"]
396
+ // CIL[DOC-MACRO purpose="Implements upsertlink logic in cortex.functions.custom_cil-callmap"]
397
+ // CIL[DOC-RESPONSIBILITY responsibility="Execute upsertlink and return its computed result"]
398
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
399
+ // CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
400
+ // CIL[DOC-MICRO logic_summary="Provides upsertlink with upsertLink( inputs, handling internal flow and returning a result" notable_decisions="[]"]
401
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
402
+ // CIL[DOC-STABILITY stability="stable"]
403
+ // CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
404
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
405
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
406
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
407
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
408
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
409
+ export async function upsertLink(
410
+ ctx: any,
411
+ sourceItem: any,
412
+ targetItem: any,
413
+ linkTypeId: string,
414
+ metadata: Record<string, any> = {}
415
+ ): Promise<boolean> {
416
+
417
+ const { data: existing } = await adminDb
418
+ .from('links')
419
+ .select('id')
420
+ .eq('source_id', sourceItem.id)
421
+ .eq('target_id', targetItem.id)
422
+ .eq('link_type_id', linkTypeId)
423
+ .maybeSingle()
424
+
425
+ if (existing) return false
426
+
427
+ const sourceType = sourceItem.data?.kb_type
428
+ const targetType = targetItem.data?.kb_type
429
+ if (!sourceType || !targetType) return false
430
+
431
+ try {
432
+ await adminCreate(ctx, {
433
+ entity: 'links',
434
+ type_slug: 'link',
435
+ source_id: sourceItem.id,
436
+ source_type: sourceType,
437
+ target_id: targetItem.id,
438
+ target_type: targetType,
439
+ link_type_id: linkTypeId,
440
+ metadata,
441
+ })
442
+ return true
443
+ } catch (err: any) {
444
+ console.error('upsertLink failed:', err?.message || err)
445
+ return false
446
+ }
447
+ }
448
+
449
+
450
+
451
+
452
+
453
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_upsertlink_1784235266"]
454
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_clearprojectlinks_1784235266" type="function" identity="clearprojectlinks" parent="none"]
455
+ async function clearProjectLinks(projectId: string, linkTypeIds: string[]): Promise<number> {
456
+ const [{ data: fileItems }, { data: chunkItems }] = await Promise.all([
457
+ adminDb
458
+ .from('items')
459
+ .select('id')
460
+ .filter('data->>project_id', 'eq', projectId)
461
+ .filter('data->>kb_type', 'eq', 'cil_file')
462
+ .eq('is_active', true),
463
+ adminDb
464
+ .from('items')
465
+ .select('id')
466
+ .filter('data->>project_id', 'eq', projectId)
467
+ .filter('data->>kb_type', 'eq', 'cil_chunk')
468
+ .eq('is_active', true),
469
+ ])
470
+
471
+ const ids = [
472
+ ...(fileItems || []).map((f: any) => f.id),
473
+ ...(chunkItems || []).map((c: any) => c.id),
474
+ ]
475
+ if (!ids.length) return 0
476
+
477
+ let deleted = 0
478
+ for (const ltId of linkTypeIds.filter(Boolean)) {
479
+ for (let i = 0; i < ids.length; i += UUID_IN_LIMIT) {
480
+ const { data: deletedRows } = await adminDb
481
+ .from('links')
482
+ .delete()
483
+ .eq('link_type_id', ltId)
484
+ .in('source_id', ids.slice(i, i + UUID_IN_LIMIT))
485
+ .select('id')
486
+ deleted += (deletedRows || []).length
487
+ }
488
+ }
489
+ return deleted
490
+ }
491
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_clearprojectlinks_1784235266"]
492
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_mapfile_1784235266" type="function" identity="mapfile" parent="none"]
493
+ // CIL[DOC-MACRO purpose="Implements mapfile logic in cortex.functions.custom_cil-callmap"]
494
+ // CIL[DOC-RESPONSIBILITY responsibility="Execute mapfile and return its computed result"]
495
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
496
+ // CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
497
+ // CIL[DOC-MICRO logic_summary="Provides mapfile with mapFile( inputs, handling internal flow and returning a result" notable_decisions="[]"]
498
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
499
+ // CIL[DOC-STABILITY stability="stable"]
500
+ // CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
501
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
502
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
503
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
504
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
505
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
506
+ export async function mapFile(
507
+ ctx: any,
508
+ fileItem: any,
509
+ projectId: string,
510
+ allChunksByFile: Map<string, any[]>,
511
+ chunksByName: Map<string, any>,
512
+ fileItemsByPath: Map<string, any>,
513
+ importsLinkTypeId: string,
514
+ callsLinkTypeId: string,
515
+ exportsLinkTypeId: string
516
+ ): Promise<{ imports_created: number; calls_created: number; exports_created: number }> {
517
+ let importsCreated = 0, callsCreated = 0, exportsCreated = 0
518
+
519
+ const filePath: string = fileItem.data?.file_path || fileItem.title
520
+ const chunksInFile = allChunksByFile.get(fileItem.id) || []
521
+
522
+
523
+ const allChunkNames = Array.from(chunksByName.keys())
524
+
525
+ for (const chunk of chunksInFile) {
526
+ const codeContent: string = chunk.data?.code_content || ''
527
+ if (!codeContent) continue
528
+
529
+
530
+ const calls = extractCalls(codeContent)
531
+ for (const call of calls) {
532
+ const targetChunk = chunksByName.get(call.callee_name)
533
+ if (!targetChunk || targetChunk.id === chunk.id) continue
534
+ const created = await upsertLink(ctx, chunk, targetChunk, callsLinkTypeId, {
535
+ callee_name: call.callee_name,
536
+ is_await: call.is_await,
537
+ })
538
+ if (created) callsCreated++
539
+ }
540
+
541
+
542
+ const symbolRefs = extractSymbolReferences(codeContent, allChunkNames, chunk.data?.chunk_name || '')
543
+ for (const refName of symbolRefs) {
544
+ const targetChunk = chunksByName.get(refName)
545
+ if (!targetChunk || targetChunk.id === chunk.id) continue
546
+ const created = await upsertLink(ctx, chunk, targetChunk, callsLinkTypeId, {
547
+ callee_name: refName,
548
+ is_symbol_reference: true,
549
+ })
550
+ if (created) callsCreated++
551
+ }
552
+ }
553
+
554
+
555
+
556
+ const fullFileContent = chunksInFile.map((c: any) => c.data?.code_content || '').join('\n')
557
+ const imports = extractImports(fullFileContent)
558
+
559
+ for (const imp of imports) {
560
+ const resolvedBase = resolveImportPath(filePath, imp.from_path)
561
+ if (!resolvedBase) continue
562
+
563
+
564
+ const targetFile =
565
+ fileItemsByPath.get(resolvedBase) ||
566
+ fileItemsByPath.get(resolvedBase + '.ts') ||
567
+ fileItemsByPath.get(resolvedBase + '.tsx') ||
568
+ fileItemsByPath.get(resolvedBase + '/index.ts') ||
569
+ fileItemsByPath.get(resolvedBase + '/index.tsx')
570
+
571
+ if (!targetFile || targetFile.id === fileItem.id) continue
572
+
573
+ const created = await upsertLink(ctx, fileItem, targetFile, importsLinkTypeId, {
574
+ symbols: imp.symbols,
575
+ is_default: imp.is_default,
576
+ specifier: imp.from_path,
577
+ })
578
+ if (created) importsCreated++
579
+ }
580
+
581
+
582
+ const exportedNames = extractExports(fullFileContent)
583
+ for (const exportedName of exportedNames) {
584
+ const chunk = chunksByName.get(exportedName)
585
+ if (!chunk) continue
586
+ const created = await upsertLink(ctx, chunk, fileItem, exportsLinkTypeId, {
587
+ exported_name: exportedName,
588
+ })
589
+ if (created) exportsCreated++
590
+ }
591
+
592
+ return { imports_created: importsCreated, calls_created: callsCreated, exports_created: exportsCreated }
593
+ }
594
+
595
+
596
+
597
+
598
+
599
+
600
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_mapfile_1784235266"]
601
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_markfilepass4bcomplete_1784235266" type="function" identity="markfilepass4bcomplete" parent="none"]
602
+ // CIL[DOC-MACRO purpose="Implements markfilepass4bcomplete logic in cortex.functions.custom_cil-callmap"]
603
+ // CIL[DOC-RESPONSIBILITY responsibility="Execute markfilepass4bcomplete and return its computed result"]
604
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
605
+ // CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
606
+ // CIL[DOC-MICRO logic_summary="Provides markfilepass4bcomplete with markFilePass4bComplete( inputs, handling internal flow and returning a result" notable_decisions="[]"]
607
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
608
+ // CIL[DOC-STABILITY stability="stable"]
609
+ // CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
610
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
611
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
612
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
613
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
614
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
615
+ async function markFilePass4bComplete(
616
+ ctx: any,
617
+ fileItem: any,
618
+ tree: FileTreeNode | null,
619
+ secondPass = false,
620
+ projectItem?: any
621
+ ): Promise<void> {
622
+ const cil_file_status = secondPass ? 'pass8_complete' : 'pass4b_complete'
623
+ const pipeline_status = secondPass ? '10-mapped' : '7-mapped'
624
+ const currentFileStatus = getFileStatus(fileItem)
625
+ const filePath: string = fileItem.data?.file_path
626
+
627
+
628
+ if (rank(currentFileStatus) < rank(cil_file_status)) {
629
+ const updateCtx = { ...ctx, query: { ...(ctx.query || {}), entity: 'items', id: fileItem.id } }
630
+ await adminUpdate(updateCtx, {
631
+ data: {
632
+ ...fileItem.data,
633
+ status: cil_file_status,
634
+ last_status_at: new Date().toISOString(),
635
+ },
636
+ }).catch((e: any) => console.error(`mark ${cil_file_status} failed:`, e.message))
637
+ }
638
+ if (tree) updateTreeNodeStatus(tree, fileItem.id, cil_file_status)
639
+
640
+
641
+ const projectId: string = fileItem.data?.project_id
642
+ if (!filePath || !projectId) return
643
+
644
+ let projItem = projectItem
645
+ if (!projItem) {
646
+ const { data } = await adminDb.from('items').select('id, data').eq('id', projectId).maybeSingle()
647
+ projItem = data
648
+ }
649
+ if (!projItem) return
650
+
651
+ const currentPipelineStatus = projItem.data?.file_statuses?.[filePath]
652
+ if (rank(currentPipelineStatus) >= rank(pipeline_status)) return
653
+
654
+ const fileStatuses = { ...(projItem.data?.file_statuses || {}) }
655
+ fileStatuses[filePath] = pipeline_status
656
+ fileStatuses[`${filePath}_updated`] = new Date().toISOString()
657
+ const { data: updateResult, error: updateErr } = await adminDb.from('items')
658
+ .update({ data: { ...projItem.data, file_statuses: fileStatuses } })
659
+ .eq('id', projectId)
660
+ .select('id')
661
+ if (updateErr) {
662
+ console.error(`pipeline status advance to ${pipeline_status} failed:`, updateErr.message)
663
+ return
664
+ }
665
+ console.log(`pipeline status advance to ${pipeline_status} result:`, JSON.stringify(updateResult))
666
+
667
+
668
+ if (projectItem) {
669
+ if (!projectItem.data) projectItem.data = {}
670
+ projectItem.data.file_statuses = fileStatuses
671
+ }
672
+ }
673
+
674
+
675
+
676
+
677
+
678
+
679
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_markfilepass4bcomplete_1784235266"]
680
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_istestfile_1784235266" type="function" identity="istestfile" parent="none"]
681
+ // CIL[DOC-MACRO purpose="Implements istestfile logic in cortex.functions.custom_cil-callmap"]
682
+ // CIL[DOC-RESPONSIBILITY responsibility="Execute istestfile and return its computed result"]
683
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
684
+ // CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
685
+ // CIL[DOC-MICRO logic_summary="Provides istestfile with isTestFile(filePath: string inputs, handling internal flow and returning a result" notable_decisions="[]"]
686
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
687
+ // CIL[DOC-STABILITY stability="stable"]
688
+ // CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
689
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
690
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
691
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
692
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
693
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
694
+ function isTestFile(filePath: string): boolean {
695
+ return /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filePath) ||
696
+ /\/__tests__\//.test(filePath) ||
697
+ /\/tests?\//.test(filePath)
698
+ }
699
+
700
+
701
+
702
+
703
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_istestfile_1784235266"]
704
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_maptests_1784235266" type="function" identity="maptests" parent="none"]
705
+ // CIL[DOC-MACRO purpose="Implements maptests logic in cortex.functions.custom_cil-callmap"]
706
+ // CIL[DOC-RESPONSIBILITY responsibility="Execute maptests and return its computed result"]
707
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
708
+ // CIL[DOC-CONTRACT inputs="none" outputs="return value from function execution" errors="throws on invalid input or runtime failure" side_effects="none"]
709
+ // CIL[DOC-MICRO logic_summary="Provides maptests with mapTests( inputs, handling internal flow and returning a result" notable_decisions="[]"]
710
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
711
+ // CIL[DOC-STABILITY stability="stable"]
712
+ // CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
713
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
714
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
715
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
716
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
717
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
718
+ async function mapTests(
719
+ ctx: any,
720
+ projectId: string,
721
+ repoPath: string,
722
+ testedByLinkTypeId: string,
723
+ chunksByName: Map<string, any>
724
+ ): Promise<{ test_files_scanned: number; tested_by_links_created: number; chunks_updated: number; errors: string[] }> {
725
+ const errors: string[] = []
726
+ let testFilesScanned = 0, linksCreated = 0, chunksUpdated = 0
727
+
728
+ const { data: allFiles } = await adminDb
729
+ .from('items').select('id, title, data')
730
+ .filter('data->>project_id', 'eq', projectId)
731
+ .filter('data->>kb_type', 'eq', 'cil_file')
732
+ .eq('is_active', true)
733
+
734
+ const testFiles = (allFiles || []).filter((f: any) => isTestFile(f.data?.file_path || f.title))
735
+
736
+ const matchesByFile = new Map<string, Set<string>>()
737
+ const allMatchedNames = new Set<string>()
738
+
739
+ for (const testFileItem of testFiles) {
740
+ const relPath: string = testFileItem.data?.file_path || testFileItem.title
741
+ const absPath = path.join(repoPath, relPath)
742
+
743
+ try {
744
+ if (!fs.existsSync(absPath)) continue
745
+ const source = fs.readFileSync(absPath, 'utf-8')
746
+ testFilesScanned++
747
+
748
+ const matchedChunkNames = new Set<string>()
749
+
750
+ const importRe = /import\s+\{([^}]+)\}/g
751
+ let m: RegExpExecArray | null
752
+ while ((m = importRe.exec(source)) !== null) {
753
+ const names = m[1].split(',').map(s => s.trim().split(/\s+as\s+/).shift()!.trim()).filter(Boolean)
754
+ for (const n of names) {
755
+ if (chunksByName.has(n)) matchedChunkNames.add(n)
756
+ }
757
+ }
758
+
759
+ const stringRe = /(?:describe|it|test|beforeEach|afterEach)\s*\(\s*['"`]([^'"`]+)['"`]/g
760
+ while ((m = stringRe.exec(source)) !== null) {
761
+ const words = m[1].split(/\W+/)
762
+ for (const word of words) {
763
+ if (chunksByName.has(word)) matchedChunkNames.add(word)
764
+ }
765
+ }
766
+
767
+ const callRe = /\b(\w{3,})\s*\(/g
768
+ while ((m = callRe.exec(source)) !== null) {
769
+ const name = m[1]
770
+ if (chunksByName.has(name)) matchedChunkNames.add(name)
771
+ }
772
+
773
+ matchesByFile.set(relPath, matchedChunkNames)
774
+ for (const name of matchedChunkNames) allMatchedNames.add(name)
775
+ } catch (err) {
776
+ errors.push(`${relPath}: ${err instanceof Error ? err.message : String(err)}`)
777
+ }
778
+ }
779
+
780
+ const matchedIds = [...allMatchedNames]
781
+ .map(name => chunksByName.get(name)?.id)
782
+ .filter(Boolean)
783
+ const fullChunksByName = new Map<string, any>()
784
+ for (let i = 0; i < matchedIds.length; i += UUID_IN_LIMIT) {
785
+ const { data } = await adminDb
786
+ .from('items')
787
+ .select('id, title, data')
788
+ .in('id', matchedIds.slice(i, i + UUID_IN_LIMIT))
789
+ for (const c of data || []) {
790
+ const name = c.data?.chunk_name
791
+ if (name) fullChunksByName.set(name, c)
792
+ }
793
+ }
794
+
795
+ for (const testFileItem of testFiles) {
796
+ const relPath: string = testFileItem.data?.file_path || testFileItem.title
797
+ const absPath = path.join(repoPath, relPath)
798
+ const isE2E = /e2e|cypress|playwright|integration/.test(relPath)
799
+ const matchedChunkNames = matchesByFile.get(relPath)
800
+ if (!matchedChunkNames) continue
801
+
802
+ for (const chunkName of matchedChunkNames) {
803
+ const chunk = fullChunksByName.get(chunkName)
804
+ if (!chunk) continue
805
+ const cd = chunk.data || {}
806
+
807
+ const created = await upsertLink(ctx, chunk, testFileItem, testedByLinkTypeId, {
808
+ test_path: relPath,
809
+ is_e2e: isE2E,
810
+ })
811
+ if (created) linksCreated++
812
+
813
+ const pathField = isE2E ? 'test_e2e_path' : 'test_unit_path'
814
+ const existingPath = cd[pathField]
815
+ if (!existingPath || existingPath === relPath) {
816
+ await adminUpdate({ ...ctx, query: { ...(ctx.query || {}), entity: 'items', id: chunk.id } } as any, {
817
+ data: { ...cd, [pathField]: relPath },
818
+ })
819
+ chunksUpdated++
820
+ }
821
+ }
822
+ }
823
+
824
+ return { test_files_scanned: testFilesScanned, tested_by_links_created: linksCreated, chunks_updated: chunksUpdated, errors }
825
+ }
826
+
827
+
828
+
829
+
830
+
831
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_maptests_1784235266"]
832
+ // CIL[BEGIN chunk_id="custom_apps_cortex_functions_custom_cil_callmap_handler_1784235266" type="variable" identity="handler" parent="none"]
833
+ // CIL[DOC-MACRO purpose="Defines handler configuration or state in cortex.functions.custom_cil-callmap"]
834
+ // CIL[DOC-RESPONSIBILITY responsibility="Hold the value and default configuration for handler"]
835
+ // CIL[DOC-CONTEXT module="cortex.functions.custom_cil-callmap" layer="function" related_files="[]"]
836
+ // CIL[DOC-CONTRACT inputs="none" outputs="value of handler" errors="none" side_effects="none"]
837
+ // CIL[DOC-MICRO logic_summary="Declares handler with initial value or constant binding used by cortex.functions.custom_cil-callmap" notable_decisions="[]"]
838
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
839
+ // CIL[DOC-STABILITY stability="stable"]
840
+ // CIL[DOC-VECTOR type="context" content="Layer: function. Direct callers: 0. Direct calls: 0. Related files: none."]
841
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
842
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
843
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
844
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
845
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
846
+ export const handler = createHandler(async (ctx, body) => {
847
+ const action = ctx.query?.action
848
+
849
+
850
+ if (action === 'status') {
851
+ const projectId = ctx.query?.project_id || body?.project_id
852
+ if (!projectId) throw new Error('project_id is required')
853
+
854
+ const [importsTypeId, callsTypeId, exportsTypeId, testedByTypeId] = await Promise.all([
855
+ resolveLinkTypeId('cil_imports').catch(() => null),
856
+ resolveLinkTypeId('cil_calls').catch(() => null),
857
+ resolveLinkTypeId('cil_exports').catch(() => null),
858
+ resolveLinkTypeId('cil_tested_by').catch(() => null),
859
+ ])
860
+
861
+ const { data: fileItems } = await adminDb
862
+ .from('items')
863
+ .select('id')
864
+ .filter('data->>project_id', 'eq', projectId)
865
+ .filter('data->>kb_type', 'eq', 'cil_file')
866
+
867
+ const { data: chunkItems } = await adminDb
868
+ .from('items')
869
+ .select('id')
870
+ .filter('data->>project_id', 'eq', projectId)
871
+ .filter('data->>kb_type', 'eq', 'cil_chunk')
872
+
873
+ const fileIds = (fileItems || []).map((f: any) => f.id)
874
+ const chunkIds = (chunkItems || []).map((c: any) => c.id)
875
+
876
+ async function countLinksForIds(typeId: string, ids: string[]): Promise<number> {
877
+ if (!typeId || !ids.length) return 0
878
+ let total = 0
879
+ for (let i = 0; i < ids.length; i += UUID_IN_LIMIT) {
880
+ const { count } = await adminDb.from('links').select('id', { count: 'exact' })
881
+ .eq('link_type_id', typeId).in('source_id', ids.slice(i, i + UUID_IN_LIMIT))
882
+ total += count || 0
883
+ }
884
+ return total
885
+ }
886
+
887
+ const importCount = await countLinksForIds(importsTypeId, fileIds)
888
+ const callCount = await countLinksForIds(callsTypeId, chunkIds)
889
+ const exportCount = await countLinksForIds(exportsTypeId, chunkIds)
890
+ const testedByCount = await countLinksForIds(testedByTypeId, chunkIds)
891
+
892
+ return {
893
+ project_id: projectId,
894
+ total_files: (fileItems || []).length,
895
+ total_chunks: (chunkItems || []).length,
896
+ import_links: importCount,
897
+ call_links: callCount,
898
+ export_links: exportCount,
899
+ tested_by_links: testedByCount,
900
+ total_links: importCount + callCount + exportCount + testedByCount,
901
+ }
902
+ }
903
+
904
+
905
+ if (action === 'clear') {
906
+ const projectId = body?.project_id
907
+ if (!projectId) throw new Error('project_id is required')
908
+
909
+ const [importsTypeId, callsTypeId, exportsTypeId] = await Promise.all([
910
+ resolveLinkTypeId('cil_imports').catch(() => null),
911
+ resolveLinkTypeId('cil_calls').catch(() => null),
912
+ resolveLinkTypeId('cil_exports').catch(() => null),
913
+ ])
914
+
915
+ const { data: chunkItems } = await adminDb
916
+ .from('items').select('id')
917
+ .filter('data->>project_id', 'eq', projectId)
918
+ .filter('data->>kb_type', 'in', '(cil_chunk,cil_file)')
919
+
920
+ const ids = (chunkItems || []).map((c: any) => c.id)
921
+ let deleted = 0
922
+
923
+ for (const ltId of [importsTypeId, callsTypeId, exportsTypeId].filter(Boolean)) {
924
+ if (!ids.length) continue
925
+ for (let i = 0; i < ids.length; i += UUID_IN_LIMIT) {
926
+ const { data: deletedRows } = await adminDb.from('links')
927
+ .delete().eq('link_type_id', ltId!).in('source_id', ids.slice(i, i + UUID_IN_LIMIT)).select('id')
928
+ deleted += (deletedRows || []).length
929
+ }
930
+ }
931
+
932
+
933
+ const { data: projectItem } = await adminDb.from('items').select('id, data').eq('id', projectId).maybeSingle()
934
+ const fileTree = (projectItem?.data?.file_tree as FileTreeNode) || null
935
+ const { data: fileItems } = await adminDb
936
+ .from('items')
937
+ .select('id, data')
938
+ .filter('data->>project_id', 'eq', projectId)
939
+ .filter('data->>kb_type', 'eq', 'cil_file')
940
+ .eq('is_active', true)
941
+
942
+ let resetCount = 0
943
+ for (const fileItem of fileItems || []) {
944
+ if (getFileStatus(fileItem) === 'pass4b_complete') {
945
+ const updateCtx = { ...ctx, query: { ...(ctx.query || {}), entity: 'items', id: fileItem.id } }
946
+ await adminUpdate(updateCtx, {
947
+ data: {
948
+ ...fileItem.data,
949
+ status: 'pass3_complete',
950
+ last_status_at: new Date().toISOString(),
951
+ },
952
+ }).catch((e: any) => console.error(`reset status ${fileItem.id}: ${e.message}`))
953
+ if (fileTree) updateTreeNodeStatus(fileTree, fileItem.id, 'pass3_complete')
954
+ resetCount++
955
+ }
956
+ }
957
+ if (fileTree && projectItem) {
958
+ await saveProjectTree(ctx, projectId, fileTree, { last_ingested_at: new Date().toISOString() })
959
+ }
960
+
961
+ return { project_id: projectId, deleted_links: deleted, reset_files: resetCount }
962
+ }
963
+
964
+
965
+ if (action === 'map_file') {
966
+ const fileId = body?.file_id
967
+ if (!fileId) throw new Error('file_id is required')
968
+
969
+ const { data: fileItem } = await adminDb
970
+ .from('items').select('id, title, data').eq('id', fileId).maybeSingle()
971
+ if (!fileItem) throw new Error(`File not found: ${fileId}`)
972
+
973
+ const projectId = fileItem.data?.project_id
974
+ if (!projectId) throw new Error('File has no project_id')
975
+
976
+ const [importsTypeId, callsTypeId, exportsTypeId] = await Promise.all([
977
+ resolveLinkTypeId('cil_imports'),
978
+ resolveLinkTypeId('cil_calls'),
979
+ resolveLinkTypeId('cil_exports'),
980
+ ])
981
+
982
+
983
+ const { data: allFiles } = await adminDb
984
+ .from('items').select('id, title, data')
985
+ .filter('data->>project_id', 'eq', projectId)
986
+ .filter('data->>kb_type', 'eq', 'cil_file').eq('is_active', true)
987
+
988
+ const { data: allChunks } = await adminDb
989
+ .from('items').select('id, title, data')
990
+ .filter('data->>project_id', 'eq', projectId)
991
+ .filter('data->>kb_type', 'eq', 'cil_chunk').eq('is_active', true)
992
+
993
+ const fileItemsByPath = new Map((allFiles || []).map((f: any) => [f.data?.file_path || f.title, f]))
994
+ const chunksByName = new Map((allChunks || []).map((c: any) => [c.data?.chunk_name || '', c]))
995
+ const allChunksByFile = new Map<string, any[]>()
996
+ for (const c of allChunks || []) {
997
+ const fid = c.data?.file_id
998
+ if (!fid) continue
999
+ if (!allChunksByFile.has(fid)) allChunksByFile.set(fid, [])
1000
+ allChunksByFile.get(fid)!.push(c)
1001
+ }
1002
+
1003
+ const result = await mapFile(
1004
+ fileItem, projectId,
1005
+ allChunksByFile, chunksByName, fileItemsByPath,
1006
+ importsTypeId, callsTypeId, exportsTypeId
1007
+ )
1008
+
1009
+ return { file_id: fileId, ...result }
1010
+ }
1011
+
1012
+
1013
+ if (action === 'map_tests') {
1014
+ const projectId = body?.project_id
1015
+ if (!projectId) throw new Error('project_id is required')
1016
+
1017
+
1018
+ const { data: projectItem } = await adminDb
1019
+ .from('items').select('data').eq('id', projectId).maybeSingle()
1020
+ const repoPath: string = projectItem?.data?.repo_path || body?.repo_path || ''
1021
+ if (!repoPath) throw new Error('Project has no repo_path — pass repo_path in body')
1022
+
1023
+ const testedByTypeId = await resolveLinkTypeId('cil_tested_by')
1024
+ const { data: allChunks } = await adminDb
1025
+ .from('items')
1026
+ .select('id, data->>chunk_name, data->>kb_type')
1027
+ .filter('data->>project_id', 'eq', projectId)
1028
+ .filter('data->>kb_type', 'eq', 'cil_chunk')
1029
+ .eq('is_active', true)
1030
+ const chunksByName = new Map<string, any>()
1031
+ for (const c of allChunks || []) {
1032
+ const name = c.chunk_name
1033
+ if (name) chunksByName.set(name, { id: c.id, data: { chunk_name: c.chunk_name, kb_type: c.kb_type || 'cil_chunk' } })
1034
+ }
1035
+ const result = await mapTests(ctx, projectId, repoPath, testedByTypeId, chunksByName)
1036
+ return { project_id: projectId, repo_path: repoPath, ...result }
1037
+ }
1038
+
1039
+
1040
+
1041
+
1042
+
1043
+
1044
+
1045
+ if (action === 'map_project') {
1046
+ const projectId = body?.project_id
1047
+ if (!projectId) throw new Error('project_id is required')
1048
+
1049
+ const pageLimit = Math.min(parseInt(body?.limit || '5', 10), 15)
1050
+ const pageOffset = parseInt(body?.offset || '0', 10)
1051
+ const filePath = body?.file_path || undefined
1052
+ const force = body?.force_regenerate ?? body?.force ?? false
1053
+ const secondPass = body?.second_pass ?? false
1054
+
1055
+ const targetPipelineStatus = secondPass ? '10-mapped' : '7-mapped'
1056
+
1057
+ const [importsTypeId, callsTypeId, exportsTypeId, testedByTypeId] = await Promise.all([
1058
+ resolveLinkTypeId('cil_imports'),
1059
+ resolveLinkTypeId('cil_calls'),
1060
+ resolveLinkTypeId('cil_exports'),
1061
+ resolveLinkTypeId('cil_tested_by').catch(() => null),
1062
+ ])
1063
+
1064
+ if (force && pageOffset === 0) {
1065
+ await clearProjectLinks(projectId, [importsTypeId, callsTypeId, exportsTypeId, testedByTypeId])
1066
+ }
1067
+
1068
+
1069
+ const { data: projectItem } = await adminDb.from('items').select('id, data').eq('id', projectId).maybeSingle()
1070
+ const selectedExtensions = body?.selected_extensions || (projectItem?.data?.selected_extensions as string[] | undefined)
1071
+ const selectedPaths: string[] = body?.selected_paths || projectItem?.data?.selected_paths || []
1072
+ const fileTree = (projectItem?.data?.file_tree as FileTreeNode) || null
1073
+
1074
+
1075
+ const sourceFilePaths = filePath
1076
+ ? [filePath]
1077
+ : force
1078
+ ? selectedPaths
1079
+ : getMapSourceFilePaths(projectItem, secondPass)
1080
+
1081
+ let filesQ = adminDb.from('items').select('id, title, data')
1082
+ .filter('data->>project_id', 'eq', projectId)
1083
+ .filter('data->>kb_type', 'eq', 'cil_file').eq('is_active', true)
1084
+ .order('id')
1085
+ if (filePath) filesQ = filesQ.filter('data->>file_path', 'eq', filePath)
1086
+
1087
+ const [filesResult, allChunksMinimalResult] = await Promise.all([
1088
+ filesQ,
1089
+ adminDb.from('items').select('id, data->>chunk_name, data->>kb_type')
1090
+ .filter('data->>project_id', 'eq', projectId)
1091
+ .filter('data->>kb_type', 'eq', 'cil_chunk')
1092
+ .eq('is_active', true),
1093
+ ])
1094
+
1095
+ const allFiles = filesResult.data || []
1096
+ const allChunksMinimal = allChunksMinimalResult.data || []
1097
+
1098
+ const fileItemsByPath = new Map(allFiles.map((f: any) => [f.data?.file_path || f.title, f]))
1099
+
1100
+ const chunksByName = new Map<string, any>()
1101
+ for (const c of allChunksMinimal) {
1102
+ const name = c.chunk_name
1103
+ if (name) chunksByName.set(name, { id: c.id, data: { chunk_name: c.chunk_name, kb_type: c.kb_type || 'cil_chunk' } })
1104
+ }
1105
+
1106
+ const mappedFileStatus = secondPass ? 'pass8_complete' : 'pass4b_complete'
1107
+ const syncFiles = allFiles.filter((f: any) => {
1108
+ const fp = f.data?.file_path || f.title
1109
+ const status = getFileStatus(f)
1110
+ const ext = f.data?.extension as string || ''
1111
+ const extMatch = (selectedExtensions || []).length === 0 || (selectedExtensions || []).includes(ext)
1112
+ return status === mappedFileStatus
1113
+ && rank(projectItem?.data?.file_statuses?.[fp]) < rank(targetPipelineStatus)
1114
+ && isSelectedPath(fp, selectedPaths)
1115
+ && extMatch
1116
+ })
1117
+ for (const fileItem of syncFiles) {
1118
+ await markFilePass4bComplete(ctx, fileItem, fileTree, secondPass, projectItem)
1119
+ }
1120
+
1121
+ const eligibleFiles = allFiles.filter((f: any) => {
1122
+ const fp = f.data?.file_path || f.title
1123
+ const ext = f.data?.extension as string || ''
1124
+ const extMatch = (selectedExtensions || []).length === 0 || (selectedExtensions || []).includes(ext)
1125
+ if (filePath && fp !== filePath) return false
1126
+ return sourceFilePaths.includes(fp) && isSelectedPath(fp, selectedPaths) && extMatch
1127
+ })
1128
+
1129
+ const totalFiles = eligibleFiles.length
1130
+ const pageFiles = eligibleFiles.slice(pageOffset, pageOffset + pageLimit)
1131
+
1132
+ const pageFilePaths = pageFiles.map(f => f.data?.file_path || f.title)
1133
+ let pageChunks: any[] = []
1134
+ if (pageFilePaths.length > 0) {
1135
+ const { data } = await adminDb.from('items').select('id, title, data')
1136
+ .filter('data->>project_id', 'eq', projectId)
1137
+ .filter('data->>kb_type', 'eq', 'cil_chunk')
1138
+ .eq('is_active', true)
1139
+ .in('data->>file_path' as any, pageFilePaths)
1140
+ pageChunks = data || []
1141
+ }
1142
+
1143
+ const allChunksByFile = new Map<string, any[]>()
1144
+ for (const c of pageChunks) {
1145
+ const name = c.data?.chunk_name || ''
1146
+ if (name) chunksByName.set(name, c)
1147
+ const fid = c.data?.file_id
1148
+ if (!fid) continue
1149
+ if (!allChunksByFile.has(fid)) allChunksByFile.set(fid, [])
1150
+ allChunksByFile.get(fid)!.push(c)
1151
+ }
1152
+
1153
+ if (!chunksByName.size) {
1154
+ return { project_id: projectId, file_path: filePath || null, message: 'No chunks found — run Pass 1 + Pass 2 first', imports_created: 0, calls_created: 0, exports_created: 0, has_more: false }
1155
+ }
1156
+
1157
+ let totalImports = 0, totalCalls = 0, totalExports = 0
1158
+ const errors: string[] = []
1159
+
1160
+ for (const fileItem of pageFiles) {
1161
+ try {
1162
+ const result = await mapFile(
1163
+ ctx, fileItem, projectId,
1164
+ allChunksByFile, chunksByName, fileItemsByPath,
1165
+ importsTypeId, callsTypeId, exportsTypeId
1166
+ )
1167
+ totalImports += result.imports_created
1168
+ totalCalls += result.calls_created
1169
+ totalExports += result.exports_created
1170
+
1171
+
1172
+ await markFilePass4bComplete(ctx, fileItem, fileTree, secondPass, projectItem)
1173
+ } catch (err) {
1174
+ errors.push(`${fileItem.data?.file_path || fileItem.id}: ${err instanceof Error ? err.message : String(err)}`)
1175
+ }
1176
+ }
1177
+
1178
+ const nextOffset = pageOffset + pageFiles.length
1179
+ const isLastPage = pageFiles.length === 0 || pageFiles.length < pageLimit || nextOffset >= totalFiles
1180
+
1181
+
1182
+ let testResult: { test_files_scanned: number; tested_by_links_created: number; chunks_updated: number; errors: string[] } | null = null
1183
+ if (isLastPage) {
1184
+ const repoPath: string = projectItem?.data?.repo_path || ''
1185
+ if (repoPath) {
1186
+ try {
1187
+ const testedByTypeId = await resolveLinkTypeId('cil_tested_by').catch(() => null)
1188
+ if (testedByTypeId) {
1189
+ testResult = await mapTests(ctx, projectId, repoPath, testedByTypeId, chunksByName)
1190
+ errors.push(...(testResult.errors || []))
1191
+ }
1192
+ } catch {
1193
+ }
1194
+ }
1195
+ }
1196
+
1197
+
1198
+ if (fileTree) {
1199
+ await saveProjectTree(ctx, projectId, fileTree, { last_ingested_at: new Date().toISOString() }, projectItem)
1200
+ }
1201
+
1202
+ return {
1203
+ project_id: projectId,
1204
+ file_path: filePath || null,
1205
+ total_files: totalFiles,
1206
+ files_processed: pageFiles.length,
1207
+ imports_created: totalImports,
1208
+ calls_created: totalCalls,
1209
+ exports_created: totalExports,
1210
+ tested_by_links_created: testResult?.tested_by_links_created ?? 0,
1211
+ test_files_scanned: testResult?.test_files_scanned ?? 0,
1212
+ chunks_updated_with_test_paths: testResult?.chunks_updated ?? 0,
1213
+ total_links_created: totalImports + totalCalls + totalExports + (testResult?.tested_by_links_created ?? 0),
1214
+ errors,
1215
+ has_more: !isLastPage,
1216
+ next_offset: !isLastPage ? nextOffset : null,
1217
+ done_total: pageOffset + pageFiles.length,
1218
+ }
1219
+ }
1220
+
1221
+ throw new Error(`Unknown action: ${action}. Valid: map_project, map_file, map_tests, status, clear`)
1222
+ })
1223
+
1224
+
1225
+
1226
+
1227
+ // CIL[END chunk_id="custom_apps_cortex_functions_custom_cil_callmap_handler_1784235266"]