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,647 @@
1
+ // CIL[BEGIN chunk_id="cilfilelistpage_module_header_1784193942" type="module_header" identity="module_header" parent="none"]
2
+ // CIL[DOC-MACRO purpose="Import React hooks, UI primitives and icons for the CIL file list page"]
3
+ // CIL[DOC-RESPONSIBILITY responsibility="Provide all external dependencies required to render and operate the file list"]
4
+ // CIL[DOC-CONTEXT module="cortex:cil-file-list" layer="presentation" related_files="[\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\"\\\"]"]
5
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
6
+ // CIL[DOC-MICRO logic_summary="ES module imports for React, router, internal API, shadcn UI and Lucide icons" notable_decisions="[]"]
7
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
8
+ // CIL[DOC-STABILITY stability="stable"]
9
+ // CIL[DOC-AUDIENCE audience="developer"]
10
+ // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: custom/apps/cortex/pages/operations/OperationsDashboard.tsx, custom/apps/portal/pages/ContentPage.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, .framework/src/pages/admin/RolesPage.tsx, \."]
11
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
12
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
13
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
14
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
15
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
16
+ import { useEffect, useState, useCallback } from 'react'
17
+ import { useParams, useNavigate } from 'react-router-dom'
18
+ import { apiFetch } from '@core/lib/api'
19
+ import { Card, CardContent, CardHeader, CardTitle } from '@core/components/ui/card'
20
+ import { Button } from '@core/components/ui/button'
21
+ import { Badge } from '@core/components/ui/badge'
22
+ import { Skeleton } from '@core/components/ui/skeleton'
23
+ import { Input } from '@core/components/ui/input'
24
+ import {
25
+ FileCode2,
26
+ CheckCircle2,
27
+ AlertTriangle,
28
+ Clock,
29
+ ShieldCheck,
30
+ ShieldAlert,
31
+ ArrowLeft,
32
+ RefreshCw,
33
+ Search,
34
+ Code2,
35
+ GitGraph,
36
+ Layers,
37
+ ChevronDown,
38
+ ChevronRight,
39
+ ExternalLink,
40
+ } from 'lucide-react'
41
+
42
+
43
+
44
+ import { PageInstructions } from '../../../components/admin/PageInstructions'
45
+ // CIL[END chunk_id="cilfilelistpage_module_header_1784193942"]
46
+ // CIL[BEGIN chunk_id="cilfilelistpage_cilfile_1784193942" type="interface" identity="CILFile" parent="none"]
47
+ // CIL[DOC-MACRO purpose="Describe the shape of a CIL file record displayed in the list"]
48
+ // CIL[DOC-RESPONSIBILITY responsibility="Type-check file metadata returned by the CIL ingestion backend"]
49
+ // CIL[DOC-CONTEXT module="cortex:cil-file-list" layer="presentation" related_files="[\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/functions/_shared/principal.ts\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"\\\"]"]
50
+ // CIL[DOC-CONTRACT inputs="none" outputs="CILFile type shape" errors="none" side_effects="none"]
51
+ // CIL[DOC-MICRO logic_summary="Interface covering id, title, data payload and updated_at timestamp" notable_decisions="[]"]
52
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
53
+ // CIL[DOC-STABILITY stability="stable"]
54
+ // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/functions/_shared/principal.ts, .framework/src/pages/admin/TypeDetailPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
55
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
56
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
57
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
58
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
59
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
60
+ interface CILFile {
61
+ id: string
62
+ title: string
63
+ data: {
64
+ file_path: string
65
+ language: string
66
+ project_id: string
67
+ ingestion_pass: number
68
+ chunk_count: number
69
+ line_count: number
70
+ stored_hash: string | null
71
+ is_dead_code: boolean
72
+ has_existing_markers: boolean
73
+ existing_marker_count: number
74
+ git_last_commit: string | null
75
+ }
76
+ updated_at: string
77
+ }
78
+
79
+ // CIL[END chunk_id="cilfilelistpage_cilfile_1784193942"]
80
+ // CIL[BEGIN chunk_id="cilfilelistpage_cilchunk_1784193942" type="interface" identity="CILChunk" parent="none"]
81
+ // CIL[DOC-MACRO purpose="Describe the shape of a single indexed CIL chunk"]
82
+ // CIL[DOC-RESPONSIBILITY responsibility="Type-check chunk metadata used when expanding a file's chunk list"]
83
+ // CIL[DOC-CONTEXT module="cortex:cil-file-list" layer="presentation" related_files="[\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"\\\"]"]
84
+ // CIL[DOC-CONTRACT inputs="none" outputs="CILChunk type shape" errors="none" side_effects="none"]
85
+ // CIL[DOC-MICRO logic_summary="Interface for chunk identity, type, line range, macro and confidence fields" notable_decisions="[]"]
86
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
87
+ // CIL[DOC-STABILITY stability="stable"]
88
+ // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: custom/apps/cortex/functions/custom_cil-embeddings.ts, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/functions/_shared/principal.ts, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
89
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
90
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
91
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
92
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
93
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
94
+ interface CILChunk {
95
+ id: string
96
+ chunk_name: string
97
+ chunk_type: string
98
+ line_start: number
99
+ line_end: number
100
+ macro: string
101
+ doc_confidence: string
102
+ boundary_confidence: string
103
+ stored_hash: string | null
104
+ is_dead_code: boolean
105
+ stability: string
106
+ file_path: string
107
+ project_id: string
108
+ }
109
+
110
+ // CIL[END chunk_id="cilfilelistpage_cilchunk_1784193942"]
111
+ // CIL[BEGIN chunk_id="cilfilelistpage_validationsummary_1784193942" type="interface" identity="ValidationSummary" parent="none"]
112
+ // CIL[DOC-MACRO purpose="Describe the shape of a file validation summary"]
113
+ // CIL[DOC-RESPONSIBILITY responsibility="Type-check counts and trust rating returned by the validate endpoint"]
114
+ // CIL[DOC-CONTEXT module="cortex:cil-file-list" layer="presentation" related_files="[\".framework/functions/_shared/schema-utils.ts\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/migrations/025_retype_threads_messages.sql\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"\\\"]"]
115
+ // CIL[DOC-CONTRACT inputs="none" outputs="ValidationSummary type shape" errors="none" side_effects="none"]
116
+ // CIL[DOC-MICRO logic_summary="Interface for total, current, drift_detected, not_found and trust_rating" notable_decisions="[]"]
117
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
118
+ // CIL[DOC-STABILITY stability="stable"]
119
+ // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/functions/_shared/principal.ts, .framework/migrations/025_retype_threads_messages.sql, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
120
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
121
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
122
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
123
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
124
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
125
+ interface ValidationSummary {
126
+ total: number
127
+ current: number
128
+ drift_detected: number
129
+ not_found: number
130
+ trust_rating: number
131
+ }
132
+
133
+ // CIL[END chunk_id="cilfilelistpage_validationsummary_1784193942"]
134
+ // CIL[BEGIN chunk_id="cilfilelistpage_filevalidation_1784193942" type="interface" identity="FileValidation" parent="none"]
135
+ // CIL[DOC-MACRO purpose="Describe the local validation state for a single file"]
136
+ // CIL[DOC-RESPONSIBILITY responsibility="Track loading, summary and error state while validating a file"]
137
+ // CIL[DOC-CONTEXT module="cortex:cil-file-list" layer="presentation" related_files="[\".framework/functions/_shared/schema-utils.ts\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/functions/_shared/principal.ts\",\"custom/apps/portal/pages/ContentPage.tsx\",\"\\\"]"]
138
+ // CIL[DOC-CONTRACT inputs="none" outputs="FileValidation type shape" errors="none" side_effects="none"]
139
+ // CIL[DOC-MICRO logic_summary="Interface bundling fileId, summary, loading flag and error string" notable_decisions="[]"]
140
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
141
+ // CIL[DOC-STABILITY stability="stable"]
142
+ // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, .framework/src/pages/admin/TypeDetailPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/functions/_shared/principal.ts, custom/apps/portal/pages/ContentPage.tsx, \."]
143
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
144
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
145
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
146
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
147
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
148
+ interface FileValidation {
149
+ fileId: string
150
+ summary: ValidationSummary | null
151
+ loading: boolean
152
+ error: string | null
153
+ }
154
+
155
+
156
+
157
+ // CIL[END chunk_id="cilfilelistpage_filevalidation_1784193942"]
158
+ // CIL[BEGIN chunk_id="cilfilelistpage_passbadge_1784193942" type="function" identity="PassBadge" parent="none"]
159
+ // CIL[DOC-MACRO purpose="Render a badge that shows a CIL file's ingestion pass status"]
160
+ // CIL[DOC-RESPONSIBILITY responsibility="Display a compact, color-coded label for the pass number"]
161
+ // CIL[DOC-CONTEXT module="cortex:cil-file-list" layer="presentation" related_files="[]"]
162
+ // CIL[DOC-CONTRACT inputs="none" outputs="Badge JSX element" errors="none" side_effects="none"]
163
+ // CIL[DOC-MICRO logic_summary="Returns outline, emerald or secondary Badge variants based on pass value" notable_decisions="[]"]
164
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
165
+ // CIL[DOC-STABILITY stability="stable"]
166
+ // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
167
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
168
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
169
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
170
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
171
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
172
+ function PassBadge({ pass }: { pass: number }) {
173
+ if (!pass || pass < 1) {
174
+ return <Badge variant="outline" className="text-xs text-muted-foreground">Not ingested</Badge>
175
+ }
176
+ if (pass >= 2) {
177
+ return <Badge variant="default" className="text-xs bg-emerald-600 hover:bg-emerald-700">Pass {pass} complete</Badge>
178
+ }
179
+ return <Badge variant="secondary" className="text-xs">Pass {pass}</Badge>
180
+ }
181
+
182
+
183
+
184
+ // CIL[END chunk_id="cilfilelistpage_passbadge_1784193942"]
185
+ // CIL[BEGIN chunk_id="cilfilelistpage_trustbadge_1784193942" type="function" identity="TrustBadge" parent="none"]
186
+ // CIL[DOC-MACRO purpose="Render a badge that shows validation trust and drift warnings"]
187
+ // CIL[DOC-RESPONSIBILITY responsibility="Display trust rating or drift count for a validated file"]
188
+ // CIL[DOC-CONTEXT module="cortex:cil-file-list" layer="presentation" related_files="[]"]
189
+ // CIL[DOC-CONTRACT inputs="none" outputs="Badge JSX element or null" errors="none" side_effects="none"]
190
+ // CIL[DOC-MICRO logic_summary="Shows ShieldCheck when trusted or ShieldAlert when drift is detected" notable_decisions="[]"]
191
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
192
+ // CIL[DOC-STABILITY stability="stable"]
193
+ // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
194
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
195
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
196
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
197
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
198
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
199
+ function TrustBadge({ summary }: { summary: ValidationSummary | null }) {
200
+ if (!summary) return null
201
+ const { trust_rating, drift_detected } = summary
202
+ if (drift_detected > 0) {
203
+ return (
204
+ <Badge variant="destructive" className="text-xs flex items-center gap-1">
205
+ <ShieldAlert className="h-3 w-3" />
206
+ {trust_rating}% ({drift_detected} drift)
207
+ </Badge>
208
+ )
209
+ }
210
+ return (
211
+ <Badge variant="outline" className="text-xs flex items-center gap-1 border-emerald-500 text-emerald-600">
212
+ <ShieldCheck className="h-3 w-3" />
213
+ {trust_rating}% trusted
214
+ </Badge>
215
+ )
216
+ }
217
+
218
+
219
+
220
+ // CIL[END chunk_id="cilfilelistpage_trustbadge_1784193942"]
221
+ // CIL[BEGIN chunk_id="cilfilelistpage_cilfilelistpage_1784193942" type="component" identity="CILFileListPage" parent="none"]
222
+ // CIL[DOC-MACRO purpose="Render the CIL file list page for a project"]
223
+ // CIL[DOC-RESPONSIBILITY responsibility="Fetch and display CIL files, run validation, and expand chunk details"]
224
+ // CIL[DOC-CONTEXT module="cortex:cil-file-list" layer="presentation" related_files="[]"]
225
+ // CIL[DOC-CONTRACT inputs="none" outputs="JSX page with file list" errors="silent fetch errors, validation errors" side_effects="GET project/files, GET/POST validate and graph endpoints, navigation"]
226
+ // CIL[DOC-MICRO logic_summary="Loads project and files, filters by search, validates files and toggles chunk expansion" notable_decisions="[]"]
227
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
228
+ // CIL[DOC-STABILITY stability="stable"]
229
+ // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
230
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
231
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
232
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
233
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
234
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
235
+ export default function CILFileListPage() {
236
+ const { id: projectId } = useParams<{ id: string }>()
237
+ const navigate = useNavigate()
238
+ const appPath = (path: string) => '/spine-framework/admin' + (path.startsWith('/') ? path : '/' + path)
239
+
240
+ const [project, setProject] = useState<{ id: string; title: string; data: any } | null>(null)
241
+ const [files, setFiles] = useState<CILFile[]>([])
242
+ const [loading, setLoading] = useState(true)
243
+ const [search, setSearch] = useState('')
244
+ const [validations, setValidations] = useState<Record<string, FileValidation>>({})
245
+ const [validatingAll, setValidatingAll] = useState(false)
246
+ const [expandedFiles, setExpandedFiles] = useState<Set<string>>(new Set())
247
+ const [fileChunks, setFileChunks] = useState<Record<string, { chunks: CILChunk[]; loading: boolean; loaded: boolean }>>({})
248
+
249
+
250
+ const fetchData = useCallback(() => {
251
+ if (!projectId) return
252
+ setLoading(true)
253
+
254
+ Promise.all([
255
+ apiFetch(`/api/cil-project?action=get&id=${projectId}`).then(r => r.json()),
256
+ apiFetch(`/api/admin-data?action=list&entity=items&type_slug=cil_file&limit=500`)
257
+ .then(r => r.json()),
258
+ ])
259
+ .then(([projData, filesData]) => {
260
+ setProject(projData?.project || projData?.data || null)
261
+ const allFiles: CILFile[] = filesData?.data || filesData?.items || []
262
+ setFiles(allFiles.filter(f => f.data?.project_id === projectId))
263
+ })
264
+ .catch(() => {})
265
+ .finally(() => setLoading(false))
266
+ }, [projectId])
267
+
268
+ useEffect(() => { fetchData() }, [fetchData])
269
+
270
+
271
+ const validateFile = useCallback(async (fileId: string) => {
272
+ setValidations(prev => ({
273
+ ...prev,
274
+ [fileId]: { fileId, summary: null, loading: true, error: null },
275
+ }))
276
+ try {
277
+ const res = await apiFetch(
278
+ `/api/cil-validate?action=validate_file&file_id=${fileId}`
279
+ )
280
+ const data = await res.json()
281
+ setValidations(prev => ({
282
+ ...prev,
283
+ [fileId]: {
284
+ fileId,
285
+ summary: data?.summary || null,
286
+ loading: false,
287
+ error: data?.error || null,
288
+ },
289
+ }))
290
+ } catch (err) {
291
+ setValidations(prev => ({
292
+ ...prev,
293
+ [fileId]: {
294
+ fileId,
295
+ summary: null,
296
+ loading: false,
297
+ error: err instanceof Error ? err.message : 'Validation failed',
298
+ },
299
+ }))
300
+ }
301
+ }, [])
302
+
303
+
304
+ const validateAll = useCallback(async () => {
305
+ const visible = filteredFiles
306
+ setValidatingAll(true)
307
+ for (const f of visible) {
308
+ await validateFile(f.id)
309
+ }
310
+ setValidatingAll(false)
311
+ }, [files, search])
312
+
313
+
314
+ const toggleFileChunks = useCallback(async (fileId: string) => {
315
+ const alreadyExpanded = expandedFiles.has(fileId)
316
+ setExpandedFiles(prev => {
317
+ const next = new Set(prev)
318
+ alreadyExpanded ? next.delete(fileId) : next.add(fileId)
319
+ return next
320
+ })
321
+ if (alreadyExpanded) return
322
+
323
+
324
+ if (fileChunks[fileId]?.loaded) return
325
+
326
+ setFileChunks(prev => ({ ...prev, [fileId]: { chunks: [], loading: true, loaded: false } }))
327
+ try {
328
+ const res = await apiFetch(`/api/cil-graph?action=get_file_chunks&file_id=${fileId}`)
329
+ const data = await res.json()
330
+ const chunks: CILChunk[] = data?.chunks || data?.data?.chunks || []
331
+ setFileChunks(prev => ({ ...prev, [fileId]: { chunks, loading: false, loaded: true } }))
332
+ } catch {
333
+ setFileChunks(prev => ({ ...prev, [fileId]: { chunks: [], loading: false, loaded: true } }))
334
+ }
335
+ }, [expandedFiles, fileChunks])
336
+
337
+
338
+ const filteredFiles = files.filter(f => {
339
+ if (!search) return true
340
+ const q = search.toLowerCase()
341
+ return (
342
+ (f.data?.file_path || '').toLowerCase().includes(q) ||
343
+ (f.data?.language || '').toLowerCase().includes(q)
344
+ )
345
+ })
346
+
347
+
348
+ const totalChunks = files.reduce((sum, f) => sum + (f.data?.chunk_count || 0), 0)
349
+ const fullyIngested = files.filter(f => (f.data?.ingestion_pass || 0) >= 2).length
350
+ const deadCodeFiles = files.filter(f => f.data?.is_dead_code).length
351
+ const validatedCount = Object.keys(validations).length
352
+ const driftCount = Object.values(validations).filter(v => (v.summary?.drift_detected || 0) > 0).length
353
+
354
+ if (loading) {
355
+ return (
356
+ <div className="p-6 space-y-4">
357
+ <Skeleton className="h-8 w-64" />
358
+ <Skeleton className="h-6 w-96" />
359
+ <div className="grid gap-3">
360
+ {[...Array(6)].map((_, i) => <Skeleton key={i} className="h-20 w-full" />)}
361
+ </div>
362
+ </div>
363
+ )
364
+ }
365
+
366
+ return (
367
+ <div className="p-6 space-y-6">
368
+
369
+ {}
370
+ <div className="flex items-center justify-between">
371
+ <div className="flex items-center gap-3">
372
+ <Button
373
+ variant="ghost"
374
+ size="sm"
375
+ onClick={() => navigate(appPath(`/cil/${projectId}`))}
376
+ className="flex items-center gap-1 text-muted-foreground"
377
+ >
378
+ <ArrowLeft className="h-4 w-4" />
379
+ Back
380
+ </Button>
381
+ <div>
382
+ <h1 className="text-xl font-bold flex items-center gap-2">
383
+ <Layers className="h-5 w-5 text-violet-500" />
384
+ File List
385
+ {project && (
386
+ <span className="text-muted-foreground font-normal text-base">— {project.title}</span>
387
+ )}
388
+ </h1>
389
+ <p className="text-sm text-muted-foreground mt-0.5">
390
+ {files.length} files · {totalChunks} total chunks
391
+ </p>
392
+ </div>
393
+ </div>
394
+ <div className="flex gap-2">
395
+ <Button variant="outline" size="sm" onClick={fetchData}>
396
+ <RefreshCw className="h-4 w-4 mr-1" />
397
+ Refresh
398
+ </Button>
399
+ <Button
400
+ variant="outline"
401
+ size="sm"
402
+ onClick={validateAll}
403
+ disabled={validatingAll || filteredFiles.length === 0}
404
+ >
405
+ <ShieldCheck className="h-4 w-4 mr-1" />
406
+ {validatingAll ? 'Validating…' : `Validate All (${filteredFiles.length})`}
407
+ </Button>
408
+ </div>
409
+ </div>
410
+
411
+ <PageInstructions
412
+ description="Browse indexed files and their chunks for a project."
413
+ sections={[
414
+ { title: 'What this page is for', content: 'This page lists all files discovered for a CIL project and shows their ingestion, drift, and dead-code status.' },
415
+ { title: 'How to read this page', content: 'The summary cards show Total Files, Fully Ingested, Dead Code, and Files with Drift. Each file card displays the path, language, chunk count, and status badges.' },
416
+ { title: 'How to use this page', content: 'Use the search box to filter by path or language. Click a file to view its chunks. Click Validate All to re-check hashes and drift for the filtered files.' },
417
+ { title: 'Important notes', content: 'Drift means the file changed since the last ingestion and stored hashes no longer match. Dead-code files are not called or imported by any other indexed file.' },
418
+ ]}
419
+ />
420
+
421
+ {}
422
+ <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
423
+ {[
424
+ { label: 'Total Files', value: files.length, icon: FileCode2, color: 'text-violet-500' },
425
+ { label: 'Fully Ingested', value: fullyIngested, icon: CheckCircle2, color: 'text-emerald-500' },
426
+ { label: 'Dead Code', value: deadCodeFiles, icon: AlertTriangle, color: 'text-amber-500' },
427
+ { label: 'Files w/ Drift', value: driftCount, icon: ShieldAlert, color: 'text-red-500' },
428
+ ].map(stat => (
429
+ <Card key={stat.label} className="p-3">
430
+ <div className="flex items-center gap-2">
431
+ <stat.icon className={`h-4 w-4 ${stat.color}`} />
432
+ <div>
433
+ <div className="text-xs text-muted-foreground">{stat.label}</div>
434
+ <div className="text-lg font-bold">{stat.value}</div>
435
+ </div>
436
+ </div>
437
+ </Card>
438
+ ))}
439
+ </div>
440
+
441
+ {}
442
+ <div className="relative max-w-md">
443
+ <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
444
+ <Input
445
+ className="pl-9"
446
+ placeholder="Filter by path or language…"
447
+ value={search}
448
+ onChange={e => setSearch(e.target.value)}
449
+ />
450
+ </div>
451
+
452
+ {}
453
+ {validatedCount > 0 && (
454
+ <div className="text-sm text-muted-foreground">
455
+ Validated {validatedCount} / {filteredFiles.length} files
456
+ {driftCount > 0 && (
457
+ <span className="ml-2 text-red-500 font-medium">· {driftCount} with drift</span>
458
+ )}
459
+ </div>
460
+ )}
461
+
462
+ {}
463
+ {filteredFiles.length === 0 ? (
464
+ <Card className="p-8 text-center text-muted-foreground">
465
+ {files.length === 0
466
+ ? 'No files ingested yet. Run Pass 1 from the Ingestion tab.'
467
+ : 'No files match the current filter.'}
468
+ </Card>
469
+ ) : (
470
+ <div className="space-y-2">
471
+ {filteredFiles.map(file => {
472
+ const d = file.data || {}
473
+ const filePath: string = d.file_path || file.title
474
+ const shortName = filePath.split('/').pop() || filePath
475
+ const dirPath = filePath.includes('/')
476
+ ? filePath.split('/').slice(0, -1).join('/')
477
+ : ''
478
+ const val = validations[file.id]
479
+ const isValidating = val?.loading === true
480
+
481
+ return (
482
+ <Card key={file.id} className="hover:bg-muted/30 transition-colors">
483
+ <CardContent className="p-4">
484
+ <div className="flex items-start justify-between gap-3">
485
+
486
+ {}
487
+ <div className="flex items-start gap-3 min-w-0 flex-1">
488
+ <FileCode2 className="h-4 w-4 mt-0.5 shrink-0 text-violet-400" />
489
+ <div className="min-w-0">
490
+ <div className="font-mono text-sm font-medium truncate">{shortName}</div>
491
+ {dirPath && (
492
+ <div className="text-xs text-muted-foreground font-mono truncate">{dirPath}/</div>
493
+ )}
494
+ <div className="flex flex-wrap items-center gap-1.5 mt-1.5">
495
+ <Badge variant="outline" className="text-xs font-mono">{d.language || 'unknown'}</Badge>
496
+ <PassBadge pass={d.ingestion_pass || 0} />
497
+ {d.chunk_count > 0 && (
498
+ <Badge variant="secondary" className="text-xs flex items-center gap-1">
499
+ <Code2 className="h-2.5 w-2.5" />
500
+ {d.chunk_count} chunks
501
+ </Badge>
502
+ )}
503
+ {d.line_count > 0 && (
504
+ <span className="text-xs text-muted-foreground">{d.line_count} lines</span>
505
+ )}
506
+ {d.is_dead_code && (
507
+ <Badge variant="outline" className="text-xs text-amber-600 border-amber-400">
508
+ Dead code
509
+ </Badge>
510
+ )}
511
+ {d.has_existing_markers && d.existing_marker_count > 0 && (
512
+ <span className="text-xs text-muted-foreground">
513
+ {d.existing_marker_count} prior markers
514
+ </span>
515
+ )}
516
+ {}
517
+ {val && !val.loading && val.summary && (
518
+ <TrustBadge summary={val.summary} />
519
+ )}
520
+ {val && !val.loading && val.error && (
521
+ <Badge variant="destructive" className="text-xs">Validate error</Badge>
522
+ )}
523
+ </div>
524
+ </div>
525
+ </div>
526
+
527
+ {}
528
+ <div className="flex items-center gap-1.5 shrink-0">
529
+ {}
530
+ {(d.chunk_count || 0) > 0 && (
531
+ <Button
532
+ size="sm"
533
+ variant="ghost"
534
+ className="px-2 h-8 text-xs"
535
+ onClick={() => toggleFileChunks(file.id)}
536
+ title={expandedFiles.has(file.id) ? 'Collapse chunks' : 'Show chunks'}
537
+ >
538
+ {expandedFiles.has(file.id)
539
+ ? <ChevronDown className="h-3.5 w-3.5" />
540
+ : <ChevronRight className="h-3.5 w-3.5" />
541
+ }
542
+ </Button>
543
+ )}
544
+ <Button
545
+ size="sm"
546
+ variant="ghost"
547
+ className="px-2 h-8 text-xs"
548
+ disabled={isValidating}
549
+ onClick={() => validateFile(file.id)}
550
+ title="Validate file hashes from disk"
551
+ >
552
+ {isValidating ? (
553
+ <RefreshCw className="h-3.5 w-3.5 animate-spin" />
554
+ ) : (
555
+ <ShieldCheck className="h-3.5 w-3.5" />
556
+ )}
557
+ </Button>
558
+ <Button
559
+ size="sm"
560
+ variant="ghost"
561
+ className="px-2 h-8"
562
+ onClick={() => navigate(appPath(`/cil/${projectId}/graph`))}
563
+ title="View call graph"
564
+ >
565
+ <GitGraph className="h-3.5 w-3.5" />
566
+ </Button>
567
+ </div>
568
+ </div>
569
+
570
+ {}
571
+ {val && !val.loading && val.summary && val.summary.drift_detected > 0 && (
572
+ <div className="mt-3 p-2.5 rounded bg-red-50 dark:bg-red-950/30 border border-red-200 dark:border-red-900 text-xs space-y-1">
573
+ <div className="font-medium text-red-700 dark:text-red-400 flex items-center gap-1">
574
+ <ShieldAlert className="h-3 w-3" />
575
+ {val.summary.drift_detected} chunk{val.summary.drift_detected !== 1 ? 's' : ''} have drifted since last ingestion
576
+ </div>
577
+ <div className="text-muted-foreground">
578
+ Run <code className="font-mono bg-muted px-1 rounded">reindex_chunk</code> or re-run Pass 2 with <code className="font-mono bg-muted px-1 rounded">force_reprocess: true</code> to update stored hashes.
579
+ </div>
580
+ </div>
581
+ )}
582
+
583
+ {}
584
+ {expandedFiles.has(file.id) && (() => {
585
+ const fc = fileChunks[file.id]
586
+ if (!fc || fc.loading) return (
587
+ <div className="mt-3 pt-3 border-t space-y-1.5">
588
+ {[...Array(3)].map((_, i) => (
589
+ <div key={i} className="h-6 rounded bg-muted animate-pulse" />
590
+ ))}
591
+ </div>
592
+ )
593
+ if (!fc.chunks.length) return (
594
+ <div className="mt-3 pt-3 border-t text-xs text-muted-foreground">No chunks indexed for this file.</div>
595
+ )
596
+
597
+ const CHUNK_TYPE_COLORS: Record<string, string> = {
598
+ function: 'bg-indigo-100 text-indigo-700',
599
+ class: 'bg-violet-100 text-violet-700',
600
+ interface: 'bg-emerald-100 text-emerald-700',
601
+ type: 'bg-cyan-100 text-cyan-700',
602
+ component: 'bg-amber-100 text-amber-700',
603
+ hook: 'bg-pink-100 text-pink-700',
604
+ route: 'bg-red-100 text-red-700',
605
+ }
606
+
607
+ return (
608
+ <div className="mt-3 pt-3 border-t space-y-1">
609
+ {fc.chunks.map(chunk => {
610
+ const typeClass = CHUNK_TYPE_COLORS[chunk.chunk_type] || 'bg-slate-100 text-slate-600'
611
+ return (
612
+ <a
613
+ key={chunk.id}
614
+ href={appPath(`/cil/${projectId}/chunks/${chunk.id}`)}
615
+ className="flex items-center gap-2 group rounded px-1.5 py-1 hover:bg-muted/60 transition-colors text-xs"
616
+ >
617
+ <Code2 className="h-3 w-3 shrink-0 text-muted-foreground" />
618
+ <span className="font-mono font-medium group-hover:text-indigo-600 transition-colors truncate flex-1">
619
+ {chunk.chunk_name}
620
+ </span>
621
+ <span className={`shrink-0 px-1.5 py-0.5 rounded text-xs ${typeClass}`}>
622
+ {chunk.chunk_type}
623
+ </span>
624
+ <span className="shrink-0 text-muted-foreground font-mono">
625
+ L{chunk.line_start}–{chunk.line_end}
626
+ </span>
627
+ {chunk.is_dead_code && (
628
+ <span className="shrink-0 text-amber-500 text-xs">dead</span>
629
+ )}
630
+ <ExternalLink className="h-3 w-3 shrink-0 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" />
631
+ </a>
632
+ )
633
+ })}
634
+ </div>
635
+ )
636
+ })()}
637
+ </CardContent>
638
+ </Card>
639
+ )
640
+ })}
641
+ </div>
642
+ )}
643
+ </div>
644
+ )
645
+ }
646
+
647
+ // CIL[END chunk_id="cilfilelistpage_cilfilelistpage_1784193942"]