spine-framework 0.3.125 → 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 +169 -97
  6. package/.framework/cli/commands/generate.ts +82 -160
  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} +147 -54
  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 +222 -347
  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 +162 -14
  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 +687 -533
  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 +173 -145
  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 +192 -115
  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 +3 -3
  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,787 @@
1
+ // CIL[BEGIN chunk_id="cilchunkdetailpage_module_header_1784193942" type="module_header" identity="module_header" parent="none"]
2
+ // CIL[DOC-MACRO purpose="Import dependencies and icons for the CIL chunk detail page"]
3
+ // CIL[DOC-RESPONSIBILITY responsibility="Provides React hooks, router, apiFetch, app path hook, UI components, and lucide icons used by the page"]
4
+ // CIL[DOC-CONTEXT module="cortex:cil-chunk-detail" layer="presentation" related_files="[\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/functions/_shared/principal.ts\",\"\\\"]"]
5
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
6
+ // CIL[DOC-MICRO logic_summary="Imports useEffect, useState, useCallback, useParams, apiFetch, useAppPath, card/button/badge/skeleton/textarea/label/select/tabs components, 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, custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/functions/_shared/principal.ts, \."]
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 } 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 { Textarea } from '@core/components/ui/textarea'
24
+ import { Label } from '@core/components/ui/label'
25
+ import {
26
+ Select,
27
+ SelectContent,
28
+ SelectItem,
29
+ SelectTrigger,
30
+ SelectValue,
31
+ } from '@core/components/ui/select'
32
+ import {
33
+ Tabs,
34
+ TabsContent,
35
+ TabsList,
36
+ TabsTrigger,
37
+ } from '@core/components/ui/tabs'
38
+ import {
39
+ CheckCircle2,
40
+ XCircle,
41
+ AlertTriangle,
42
+ ChevronRight,
43
+ ArrowRight,
44
+ RefreshCw,
45
+ Save,
46
+ Zap,
47
+ FileCode2,
48
+ Hash,
49
+ TestTube2,
50
+ } from 'lucide-react'
51
+
52
+
53
+
54
+ import { PageInstructions } from '../../../components/admin/PageInstructions'
55
+ // CIL[END chunk_id="cilchunkdetailpage_module_header_1784193942"]
56
+ // CIL[BEGIN chunk_id="cilchunkdetailpage_chunkcontract_1784193942" type="interface" identity="ChunkContract" parent="none"]
57
+ // CIL[DOC-MACRO purpose="Define the shape of a chunk contract"]
58
+ // CIL[DOC-RESPONSIBILITY responsibility="Declare the TypeScript interface representing an ingested code chunk and its metadata"]
59
+ // CIL[DOC-CONTEXT module="cortex:cil-chunk-detail" layer="presentation" related_files="[\".framework/functions/_shared/principal.ts\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/functions/_shared/schema-utils.ts\",\".framework/migrations/015_simplify_apps_table.sql\",\"\\\"]"]
60
+ // CIL[DOC-CONTRACT inputs="none" outputs="ChunkContract type definition" errors="none" side_effects="none"]
61
+ // CIL[DOC-MICRO logic_summary="Describes id, name, file path, line range, type, macro/micro docs, input/output specs, side effects, stability, test paths, confidence fields, hash, dead-code flag, and caller/callee lists" notable_decisions="[]"]
62
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
63
+ // CIL[DOC-STABILITY stability="stable"]
64
+ // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/principal.ts, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/functions/_shared/schema-utils.ts, .framework/migrations/015_simplify_apps_table.sql, \."]
65
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
66
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
67
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
68
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
69
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
70
+ interface ChunkContract {
71
+ id: string
72
+ chunk_name: string
73
+ file_path: string
74
+ line_start: number
75
+ line_end: number
76
+ chunk_type: string
77
+ macro: string
78
+ micro: string
79
+ input_spec: string
80
+ output_spec: string
81
+ side_effects: string
82
+ stability: string
83
+ test_unit_path: string | null
84
+ test_e2e_path: string | null
85
+ doc_confidence: string
86
+ boundary_confidence: string
87
+ stored_hash: string | null
88
+ hash_status: string
89
+ is_dead_code: boolean
90
+ callers: { chunk_id: string; chunk_name: string; file_path: string }[]
91
+ callees: { chunk_id: string; chunk_name: string; file_path: string }[]
92
+ }
93
+
94
+ // CIL[END chunk_id="cilchunkdetailpage_chunkcontract_1784193942"]
95
+ // CIL[BEGIN chunk_id="cilchunkdetailpage_embeddingstatus_1784193942" type="interface" identity="EmbeddingStatus" parent="none"]
96
+ // CIL[DOC-MACRO purpose="Define the shape of embedding coverage status"]
97
+ // CIL[DOC-RESPONSIBILITY responsibility="Provide a TypeScript type contract for chunk embedding coverage"]
98
+ // CIL[DOC-CONTEXT module="cortex:cil-chunk-detail" layer="presentation" related_files="[\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/src/pages/admin/RolesPage.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"\\\"]"]
99
+ // CIL[DOC-CONTRACT inputs="none" outputs="EmbeddingStatus type definition" errors="none" side_effects="none"]
100
+ // CIL[DOC-MICRO logic_summary="Declares coverage percentage and counts of embedded vs total chunks" 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: presentation. Direct callers: 0. Direct calls: 0. Related files: custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/src/pages/admin/RolesPage.tsx, .framework/functions/_shared/principal.ts, .framework/src/pages/admin/IntegrationsPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
104
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
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
+ interface EmbeddingStatus {
110
+ coverage_pct: number
111
+ embedded_chunks: number
112
+ total_chunks: number
113
+ }
114
+
115
+
116
+
117
+ // CIL[END chunk_id="cilchunkdetailpage_embeddingstatus_1784193942"]
118
+ // CIL[BEGIN chunk_id="cilchunkdetailpage_doc_confidence_config_1784193942" type="constant" identity="DOC_CONFIDENCE_CONFIG" parent="none"]
119
+ // CIL[DOC-MACRO purpose="Map doc-confidence levels to badge labels, colors, and icons"]
120
+ // CIL[DOC-RESPONSIBILITY responsibility="Provide display metadata for human_verified, ai_generated, and unverified_legacy confidence states"]
121
+ // CIL[DOC-CONTEXT module="cortex:cil-chunk-detail" layer="presentation" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/src/components/ui/table-primitives.tsx\",\"\\\"]"]
122
+ // CIL[DOC-CONTRACT inputs="none" outputs="Record<string, { label, color, icon }>" errors="none" side_effects="none"]
123
+ // CIL[DOC-MICRO logic_summary="Associates each confidence key with a UI label, Tailwind color class, and lucide icon component" notable_decisions="[]"]
124
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
125
+ // CIL[DOC-STABILITY stability="stable"]
126
+ // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, .framework/src/pages/admin/RolesPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/src/components/ui/table-primitives.tsx, \."]
127
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
128
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
129
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
130
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
131
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
132
+ const DOC_CONFIDENCE_CONFIG: Record<string, { label: string; color: string; icon: React.ElementType }> = {
133
+ human_verified: { label: 'Human Verified', color: 'text-green-600', icon: CheckCircle2 },
134
+ ai_generated: { label: 'AI Generated', color: 'text-blue-600', icon: Zap },
135
+ unverified_legacy: { label: 'Unverified', color: 'text-amber-600', icon: AlertTriangle },
136
+ }
137
+
138
+ // CIL[END chunk_id="cilchunkdetailpage_doc_confidence_config_1784193942"]
139
+ // CIL[BEGIN chunk_id="cilchunkdetailpage_stability_badge_1784193942" type="constant" identity="STABILITY_BADGE" parent="none"]
140
+ // CIL[DOC-MACRO purpose="Map stability levels to badge variants"]
141
+ // CIL[DOC-RESPONSIBILITY responsibility="Provide Badge variant values for stable, internal, and experimental stability states"]
142
+ // CIL[DOC-CONTEXT module="cortex:cil-chunk-detail" layer="presentation" related_files="[\".framework/src/pages/admin/RolesPage.tsx\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/migrations/025_retype_threads_messages.sql\",\"\\\"]"]
143
+ // CIL[DOC-CONTRACT inputs="none" outputs="Record<string, Badge variant union>" errors="none" side_effects="none"]
144
+ // CIL[DOC-MICRO logic_summary="Maps stable to default, internal to secondary, and experimental to outline variant names" notable_decisions="[]"]
145
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
146
+ // CIL[DOC-STABILITY stability="stable"]
147
+ // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/RolesPage.tsx, custom/apps/cortex/functions/custom_cil-embeddings.ts, custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/migrations/025_retype_threads_messages.sql, \."]
148
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
149
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
150
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
151
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
152
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
153
+ const STABILITY_BADGE: Record<string, 'default' | 'secondary' | 'outline'> = {
154
+ stable: 'default',
155
+ internal: 'secondary',
156
+ experimental: 'outline',
157
+ }
158
+
159
+ // CIL[END chunk_id="cilchunkdetailpage_stability_badge_1784193942"]
160
+ // CIL[BEGIN chunk_id="cilchunkdetailpage_hashstatusbadge_1784193942" type="function" identity="HashStatusBadge" parent="none"]
161
+ // CIL[DOC-MACRO purpose="Render a badge indicating the current hash validation status"]
162
+ // CIL[DOC-RESPONSIBILITY responsibility="Display current, drift_detected, or unknown hash status as a Badge with icon"]
163
+ // CIL[DOC-CONTEXT module="cortex:cil-chunk-detail" layer="presentation" related_files="[]"]
164
+ // CIL[DOC-CONTRACT inputs="none" outputs="JSX.Element" errors="none" side_effects="none"]
165
+ // CIL[DOC-MICRO logic_summary="Returns a green Current badge, a destructive Drift Detected badge, or a muted Unknown badge based on status value" notable_decisions="[]"]
166
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
167
+ // CIL[DOC-STABILITY stability="stable"]
168
+ // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
169
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
170
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
171
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
172
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
173
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
174
+ function HashStatusBadge({ status }: { status: string }) {
175
+ if (status === 'current') return (
176
+ <Badge variant="default" className="bg-green-600 text-white gap-1">
177
+ <CheckCircle2 className="h-3 w-3" /> Current
178
+ </Badge>
179
+ )
180
+ if (status === 'drift_detected') return (
181
+ <Badge variant="destructive" className="gap-1">
182
+ <XCircle className="h-3 w-3" /> Drift Detected
183
+ </Badge>
184
+ )
185
+ return (
186
+ <Badge variant="outline" className="gap-1 text-muted-foreground">
187
+ <Hash className="h-3 w-3" /> Unknown
188
+ </Badge>
189
+ )
190
+ }
191
+
192
+
193
+
194
+ // CIL[END chunk_id="cilchunkdetailpage_hashstatusbadge_1784193942"]
195
+ // CIL[BEGIN chunk_id="cilchunkdetailpage_chunklinkcard_1784193942" type="function" identity="ChunkLinkCard" parent="none"]
196
+ // CIL[DOC-MACRO purpose="Render a navigable card linking to another chunk"]
197
+ // CIL[DOC-RESPONSIBILITY responsibility="Display chunk name and file path and link to the chunk detail route"]
198
+ // CIL[DOC-CONTEXT module="cortex:cil-chunk-detail" layer="presentation" related_files="[]"]
199
+ // CIL[DOC-CONTRACT inputs="none" outputs="JSX.Element" errors="none" side_effects="none"]
200
+ // CIL[DOC-MICRO logic_summary="Builds a route via useAppPath and renders an anchor with icon, name, path, and hover arrow" notable_decisions="[]"]
201
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
202
+ // CIL[DOC-STABILITY stability="stable"]
203
+ // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
204
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
205
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
206
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
207
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
208
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
209
+ function ChunkLinkCard({
210
+ chunk,
211
+ label,
212
+ projectId,
213
+ }: {
214
+ chunk: { chunk_id: string; chunk_name: string; file_path: string }
215
+ label: string
216
+ projectId: string
217
+ }) {
218
+ const appPath = (path: string) => '/spine-framework/admin' + (path.startsWith('/') ? path : '/' + path)
219
+ return (
220
+ <a
221
+ href={appPath(`/cil/${projectId}/chunks/${chunk.chunk_id}`)}
222
+ className="flex items-center gap-2 p-2 rounded-md border hover:bg-muted/50 transition-colors group text-sm"
223
+ >
224
+ <FileCode2 className="h-3.5 w-3.5 text-muted-foreground shrink-0" />
225
+ <div className="flex-1 min-w-0">
226
+ <div className="font-mono font-medium truncate">{chunk.chunk_name}</div>
227
+ <div className="text-xs text-muted-foreground truncate">{chunk.file_path}</div>
228
+ </div>
229
+ <ArrowRight className="h-3 w-3 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity shrink-0" />
230
+ </a>
231
+ )
232
+ }
233
+
234
+
235
+
236
+ // CIL[END chunk_id="cilchunkdetailpage_chunklinkcard_1784193942"]
237
+ // CIL[BEGIN chunk_id="cilchunkdetailpage_contracteditor_1784193942" type="function" identity="ContractEditor" parent="none"]
238
+ // CIL[DOC-MACRO purpose="Render and edit a chunk contract form"]
239
+ // CIL[DOC-RESPONSIBILITY responsibility="Provide a UI to edit macro, micro, specs, stability, test paths, and doc confidence, then persist via API"]
240
+ // CIL[DOC-CONTEXT module="cortex:cil-chunk-detail" layer="presentation" related_files="[]"]
241
+ // CIL[DOC-CONTRACT inputs="none" outputs="JSX.Element" errors="none" side_effects="PATCH /api/admin-data; calls onSave callback to update parent contract"]
242
+ // CIL[DOC-MICRO logic_summary="Initializes form from contract, renders textarea fields and stability/confidence selects, saves changes, and shows saving/saved feedback" notable_decisions="[]"]
243
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
244
+ // CIL[DOC-STABILITY stability="stable"]
245
+ // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
246
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
247
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
248
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
249
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
250
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
251
+ function ContractEditor({
252
+ contract,
253
+ projectId,
254
+ onSave,
255
+ }: {
256
+ contract: ChunkContract
257
+ projectId: string
258
+ onSave: (updated: Partial<ChunkContract>) => void
259
+ }) {
260
+ const [form, setForm] = useState({
261
+ macro: contract.macro || '',
262
+ micro: contract.micro || '',
263
+ input_spec: contract.input_spec || '',
264
+ output_spec: contract.output_spec || '',
265
+ side_effects: contract.side_effects || '',
266
+ stability: contract.stability || 'internal',
267
+ test_unit_path: contract.test_unit_path || '',
268
+ test_e2e_path: contract.test_e2e_path || '',
269
+ doc_confidence: contract.doc_confidence || 'unverified_legacy',
270
+ })
271
+ const [saving, setSaving] = useState(false)
272
+ const [saved, setSaved] = useState(false)
273
+
274
+ const handleSave = async () => {
275
+ setSaving(true)
276
+ try {
277
+ const res = await apiFetch(`/api/admin-data?id=${contract.id}`, {
278
+ method: 'PATCH',
279
+ headers: { 'Content-Type': 'application/json' },
280
+ body: JSON.stringify({
281
+ entity: 'items',
282
+ data: {
283
+ ...form,
284
+ test_unit_path: form.test_unit_path || null,
285
+ test_e2e_path: form.test_e2e_path || null,
286
+ },
287
+ }),
288
+ })
289
+ if (res.ok) {
290
+ setSaved(true)
291
+ onSave(form)
292
+ setTimeout(() => setSaved(false), 2000)
293
+ }
294
+ } finally {
295
+ setSaving(false)
296
+ }
297
+ }
298
+
299
+ const field = (
300
+ key: keyof typeof form,
301
+ label: string,
302
+ placeholder: string,
303
+ rows = 2
304
+ ) => (
305
+ <div className="space-y-1">
306
+ <Label className="text-xs font-medium">{label}</Label>
307
+ <Textarea
308
+ value={form[key] as string}
309
+ onChange={e => setForm(f => ({ ...f, [key]: e.target.value }))}
310
+ placeholder={placeholder}
311
+ rows={rows}
312
+ className="text-sm font-mono resize-none"
313
+ />
314
+ </div>
315
+ )
316
+
317
+ return (
318
+ <div className="space-y-4">
319
+ {field('macro', 'Macro (Purpose — one sentence)', 'What this chunk IS and its primary responsibility', 2)}
320
+ {field('micro', 'Micro (Implementation detail)', 'How it does it — key algorithm, pattern, or approach', 2)}
321
+ {field('input_spec', 'Inputs', 'Parameter names, types, constraints (one per line)', 3)}
322
+ {field('output_spec', 'Returns', 'Return type and shape description', 2)}
323
+ {field('side_effects', 'Side Effects', 'DB writes, API calls, file I/O, mutations, thrown errors', 2)}
324
+ {field('test_unit_path', 'Unit Test Path', 'Relative path to unit test file (e.g. src/__tests__/foo.test.ts)', 1)}
325
+ {field('test_e2e_path', 'E2E Test Path', 'Relative path to e2e test file', 1)}
326
+
327
+ <div className="grid grid-cols-2 gap-3">
328
+ <div className="space-y-1">
329
+ <Label className="text-xs font-medium">Stability</Label>
330
+ <Select value={form.stability} onValueChange={v => setForm(f => ({ ...f, stability: v }))}>
331
+ <SelectTrigger className="h-8 text-sm">
332
+ <SelectValue />
333
+ </SelectTrigger>
334
+ <SelectContent>
335
+ <SelectItem value="stable">Stable</SelectItem>
336
+ <SelectItem value="internal">Internal</SelectItem>
337
+ <SelectItem value="experimental">Experimental</SelectItem>
338
+ </SelectContent>
339
+ </Select>
340
+ </div>
341
+ <div className="space-y-1">
342
+ <Label className="text-xs font-medium">Doc Confidence</Label>
343
+ <Select value={form.doc_confidence} onValueChange={v => setForm(f => ({ ...f, doc_confidence: v }))}>
344
+ <SelectTrigger className="h-8 text-sm">
345
+ <SelectValue />
346
+ </SelectTrigger>
347
+ <SelectContent>
348
+ <SelectItem value="human_verified">Human Verified</SelectItem>
349
+ <SelectItem value="ai_generated">AI Generated</SelectItem>
350
+ <SelectItem value="unverified_legacy">Unverified Legacy</SelectItem>
351
+ </SelectContent>
352
+ </Select>
353
+ </div>
354
+ </div>
355
+
356
+ <Button onClick={handleSave} disabled={saving} className="w-full">
357
+ {saving ? (
358
+ <><RefreshCw className="h-3 w-3 mr-2 animate-spin" /> Saving…</>
359
+ ) : saved ? (
360
+ <><CheckCircle2 className="h-3 w-3 mr-2 text-green-400" /> Saved</>
361
+ ) : (
362
+ <><Save className="h-3 w-3 mr-2" /> Save Contract</>
363
+ )}
364
+ </Button>
365
+ </div>
366
+ )
367
+ }
368
+
369
+
370
+
371
+ // CIL[END chunk_id="cilchunkdetailpage_contracteditor_1784193942"]
372
+ // CIL[BEGIN chunk_id="cilchunkdetailpage_cilchunkdetailpage_1784193942" type="component" identity="CILChunkDetailPage" parent="none"]
373
+ // CIL[DOC-MACRO purpose="Render the CIL chunk detail page"]
374
+ // CIL[DOC-RESPONSIBILITY responsibility="Fetch and display a single chunk contract, code content, graph, and blast radius; support hash validation, embedding, and contract editing"]
375
+ // CIL[DOC-CONTEXT module="cortex:cil-chunk-detail" layer="presentation" related_files="[]"]
376
+ // CIL[DOC-CONTRACT inputs="none" outputs="JSX.Element" errors="Renders loading skeleton or not found message; API errors swallowed" side_effects="GET /api/cil-graph, GET /api/admin-data, POST /api/cil-validate, POST /api/cil-embeddings; updates local contract, codeContent, hashStatus, embedResult, blastRadius"]
377
+ // CIL[DOC-MICRO logic_summary="Loads chunk contract and stored code, renders header with stability/hash/doc badges, action buttons, and Tabs for contract, graph, code, and blast radius; uses HashStatusBadge, ChunkLinkCard, and ContractEditor subcomponents" notable_decisions="[]"]
378
+ // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
379
+ // CIL[DOC-STABILITY stability="stable"]
380
+ // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
381
+ // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
382
+ // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
383
+ // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
384
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
385
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
386
+ export default function CILChunkDetailPage() {
387
+ const { id: projectId, chunkId } = useParams<{ id: string; chunkId: string }>()
388
+ const appPath = (path: string) => '/spine-framework/admin' + (path.startsWith('/') ? path : '/' + path)
389
+ const [contract, setContract] = useState<ChunkContract | null>(null)
390
+ const [codeContent, setCodeContent] = useState<string>('')
391
+ const [loading, setLoading] = useState(true)
392
+ const [validating, setValidating] = useState(false)
393
+ const [hashStatus, setHashStatus] = useState<string>('unknown')
394
+ const [embedding, setEmbedding] = useState(false)
395
+ const [embedResult, setEmbedResult] = useState<string | null>(null)
396
+ const [blastRadius, setBlastRadius] = useState<any[] | null>(null)
397
+ const [loadingBlast, setLoadingBlast] = useState(false)
398
+
399
+ const loadChunk = useCallback(async () => {
400
+ if (!chunkId) return
401
+ setLoading(true)
402
+ try {
403
+ const res = await apiFetch(`/api/cil-graph?action=get_chunk_contract&chunk_id=${chunkId}`)
404
+ const data = await res.json()
405
+ const c = data?.contract || data?.data?.contract
406
+ if (c) {
407
+ setContract(c)
408
+ setHashStatus(c.hash_status || 'unknown')
409
+ }
410
+
411
+
412
+ const itemRes = await apiFetch(`/api/admin-data?action=get&entity=items&id=${c.id}`)
413
+ const itemData = await itemRes.json()
414
+ const item = itemData?.data || itemData
415
+ setCodeContent(item?.data?.code_content || '')
416
+ } catch {
417
+ } finally {
418
+ setLoading(false)
419
+ }
420
+ }, [chunkId])
421
+
422
+ useEffect(() => { loadChunk() }, [loadChunk])
423
+
424
+ const handleValidate = async () => {
425
+ if (!chunkId || !contract || !codeContent) return
426
+ setValidating(true)
427
+ try {
428
+ const res = await apiFetch('/api/cil-validate?action=validate', {
429
+ method: 'POST',
430
+ headers: { 'Content-Type': 'application/json' },
431
+ body: JSON.stringify({
432
+ chunks: [{ chunk_id: contract.id, chunk_name: contract.chunk_name, content: codeContent }],
433
+ }),
434
+ })
435
+ const data = await res.json()
436
+ const result = (data?.results || data?.data?.results)?.[0]
437
+ if (result) setHashStatus(result.status)
438
+ } finally {
439
+ setValidating(false)
440
+ }
441
+ }
442
+
443
+ const handleEmbed = async () => {
444
+ if (!chunkId) return
445
+ setEmbedding(true)
446
+ setEmbedResult(null)
447
+ try {
448
+ const res = await apiFetch('/api/cil-embeddings?action=embed_chunk', {
449
+ method: 'POST',
450
+ headers: { 'Content-Type': 'application/json' },
451
+ body: JSON.stringify({ chunk_id: contract?.id || chunkId, force_regenerate: false }),
452
+ })
453
+ const data = await res.json()
454
+ const r = data?.data || data
455
+ if (r?.created?.length) {
456
+ setEmbedResult(`Generated ${r.created.length} vector(s): ${r.created.join(', ')}`)
457
+ } else if (r?.skipped?.length) {
458
+ setEmbedResult(`Already current — ${r.skipped.length} vector(s) unchanged`)
459
+ } else {
460
+ setEmbedResult('Embedding complete')
461
+ }
462
+ } catch (err) {
463
+ setEmbedResult(`Error: ${err}`)
464
+ } finally {
465
+ setEmbedding(false)
466
+ }
467
+ }
468
+
469
+ const handleBlastRadius = async () => {
470
+ if (!chunkId) return
471
+ setLoadingBlast(true)
472
+ try {
473
+ const res = await apiFetch(`/api/cil-graph?action=get_blast_radius&chunk_id=${contract?.id || chunkId}&max_depth=3`)
474
+ const data = await res.json()
475
+ setBlastRadius((data?.affected || data?.data?.affected) ?? [])
476
+ } finally {
477
+ setLoadingBlast(false)
478
+ }
479
+ }
480
+
481
+ if (loading) {
482
+ return (
483
+ <div className="p-6 space-y-4">
484
+ <Skeleton className="h-6 w-48" />
485
+ <Skeleton className="h-8 w-96" />
486
+ <div className="grid grid-cols-3 gap-4">
487
+ <Skeleton className="h-32" />
488
+ <Skeleton className="h-32" />
489
+ <Skeleton className="h-32" />
490
+ </div>
491
+ </div>
492
+ )
493
+ }
494
+
495
+ if (!contract) {
496
+ return <div className="p-6 text-muted-foreground text-center">Chunk not found.</div>
497
+ }
498
+
499
+ const docCfg = DOC_CONFIDENCE_CONFIG[contract.doc_confidence] || DOC_CONFIDENCE_CONFIG.unverified_legacy
500
+ const DocIcon = docCfg.icon
501
+
502
+ return (
503
+ <div className="p-6 space-y-5 max-w-5xl">
504
+ {}
505
+ <div className="flex items-center gap-2 text-sm text-muted-foreground flex-wrap">
506
+ <a href={appPath('/cil')} className="hover:underline">Code Intelligence</a>
507
+ <ChevronRight className="h-3 w-3" />
508
+ <a href={appPath(`/cil/${projectId}/ingest`)} className="hover:underline">Project</a>
509
+ <ChevronRight className="h-3 w-3" />
510
+ <span className="font-mono">{contract.chunk_name}</span>
511
+ </div>
512
+
513
+ {}
514
+ <div className="flex items-start justify-between gap-4 flex-wrap">
515
+ <div>
516
+ <h1 className="text-xl font-bold font-mono">{contract.chunk_name}</h1>
517
+ <p className="text-xs text-muted-foreground mt-0.5 font-mono">
518
+ {contract.file_path} · L{contract.line_start}–{contract.line_end}
519
+ </p>
520
+ </div>
521
+ <div className="flex items-center gap-2 flex-wrap">
522
+ <Badge variant={STABILITY_BADGE[contract.stability] || 'outline'}>
523
+ {contract.stability}
524
+ </Badge>
525
+ <Badge variant="secondary">{contract.chunk_type}</Badge>
526
+ <Badge variant={contract.is_dead_code ? 'destructive' : 'outline'}>
527
+ {contract.is_dead_code ? 'Dead Code' : 'Active'}
528
+ </Badge>
529
+ <span className={`flex items-center gap-1 text-xs ${docCfg.color}`}>
530
+ <DocIcon className="h-3.5 w-3.5" />
531
+ {docCfg.label}
532
+ </span>
533
+ </div>
534
+ </div>
535
+
536
+ <PageInstructions
537
+ description="Inspect a single CIL chunk, its contract, and its relationships."
538
+ sections={[
539
+ { title: 'What this page is for', content: 'This page displays one indexed code chunk, including its contract, code, call graph, and hash/embed status.' },
540
+ { title: 'How to read this page', content: 'The Contract tab shows macro and micro summaries plus documentation status. The Graph tab lists callers and callees. The Code tab shows the source. Blast Radius appears after calculation.' },
541
+ { title: 'How to use this page', content: 'Click Validate Hash to confirm the stored hash matches the current file contents. Click Embed Chunk to regenerate its vector embeddings. Click Blast Radius to see impacted chunks.' },
542
+ { title: 'Important notes', content: 'Dead-code chunks are marked with a destructive badge. Documentation coverage is shown as AI-generated, human-verified, or undocumented.' },
543
+ ]}
544
+ />
545
+
546
+ {}
547
+ <div className="flex items-center gap-3 flex-wrap">
548
+ <HashStatusBadge status={hashStatus} />
549
+ <Button
550
+ size="sm"
551
+ variant="outline"
552
+ onClick={handleValidate}
553
+ disabled={validating || !codeContent}
554
+ className="h-7 text-xs"
555
+ >
556
+ {validating ? <RefreshCw className="h-3 w-3 mr-1 animate-spin" /> : <Hash className="h-3 w-3 mr-1" />}
557
+ Validate Hash
558
+ </Button>
559
+ <Button
560
+ size="sm"
561
+ variant="outline"
562
+ onClick={handleEmbed}
563
+ disabled={embedding}
564
+ className="h-7 text-xs"
565
+ >
566
+ {embedding ? <RefreshCw className="h-3 w-3 mr-1 animate-spin" /> : <Zap className="h-3 w-3 mr-1" />}
567
+ Embed Chunk
568
+ </Button>
569
+ <Button
570
+ size="sm"
571
+ variant="outline"
572
+ onClick={handleBlastRadius}
573
+ disabled={loadingBlast}
574
+ className="h-7 text-xs"
575
+ >
576
+ {loadingBlast ? <RefreshCw className="h-3 w-3 mr-1 animate-spin" /> : <AlertTriangle className="h-3 w-3 mr-1" />}
577
+ Blast Radius
578
+ </Button>
579
+ {embedResult && (
580
+ <span className="text-xs text-muted-foreground">{embedResult}</span>
581
+ )}
582
+ </div>
583
+
584
+ <Tabs defaultValue="contract">
585
+ <TabsList>
586
+ <TabsTrigger value="contract">Contract</TabsTrigger>
587
+ <TabsTrigger value="graph">
588
+ Graph
589
+ {(contract.callers.length + contract.callees.length) > 0 && (
590
+ <span className="ml-1.5 bg-primary/15 text-primary text-xs rounded-full px-1.5 py-0.5 leading-none">
591
+ {contract.callers.length + contract.callees.length}
592
+ </span>
593
+ )}
594
+ </TabsTrigger>
595
+ <TabsTrigger value="code">Code</TabsTrigger>
596
+ {blastRadius !== null && (
597
+ <TabsTrigger value="blast">
598
+ Blast Radius
599
+ {blastRadius.length > 0 && (
600
+ <span className="ml-1.5 bg-red-100 text-red-700 text-xs rounded-full px-1.5 py-0.5 leading-none">
601
+ {blastRadius.length}
602
+ </span>
603
+ )}
604
+ </TabsTrigger>
605
+ )}
606
+ </TabsList>
607
+
608
+ {}
609
+ <TabsContent value="contract" className="mt-4 space-y-4">
610
+ {}
611
+ {(contract.macro || contract.micro) && (
612
+ <Card>
613
+ <CardContent className="pt-4 space-y-2">
614
+ {contract.macro && (
615
+ <p className="text-sm"><span className="font-medium text-muted-foreground">Purpose: </span>{contract.macro}</p>
616
+ )}
617
+ {contract.micro && (
618
+ <p className="text-sm"><span className="font-medium text-muted-foreground">Detail: </span>{contract.micro}</p>
619
+ )}
620
+ </CardContent>
621
+ </Card>
622
+ )}
623
+
624
+ {}
625
+ {(contract.input_spec || contract.output_spec || contract.side_effects) && (
626
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
627
+ {contract.input_spec && (
628
+ <Card>
629
+ <CardHeader className="pb-1 pt-3">
630
+ <CardTitle className="text-xs text-muted-foreground uppercase tracking-wide">Inputs</CardTitle>
631
+ </CardHeader>
632
+ <CardContent className="pb-3">
633
+ <pre className="text-xs font-mono whitespace-pre-wrap">{contract.input_spec}</pre>
634
+ </CardContent>
635
+ </Card>
636
+ )}
637
+ {contract.output_spec && (
638
+ <Card>
639
+ <CardHeader className="pb-1 pt-3">
640
+ <CardTitle className="text-xs text-muted-foreground uppercase tracking-wide">Returns</CardTitle>
641
+ </CardHeader>
642
+ <CardContent className="pb-3">
643
+ <pre className="text-xs font-mono whitespace-pre-wrap">{contract.output_spec}</pre>
644
+ </CardContent>
645
+ </Card>
646
+ )}
647
+ {contract.side_effects && (
648
+ <Card>
649
+ <CardHeader className="pb-1 pt-3">
650
+ <CardTitle className="text-xs text-muted-foreground uppercase tracking-wide">Side Effects</CardTitle>
651
+ </CardHeader>
652
+ <CardContent className="pb-3">
653
+ <pre className="text-xs font-mono whitespace-pre-wrap">{contract.side_effects}</pre>
654
+ </CardContent>
655
+ </Card>
656
+ )}
657
+ </div>
658
+ )}
659
+
660
+ {}
661
+ {(contract.test_unit_path || contract.test_e2e_path) && (
662
+ <Card>
663
+ <CardHeader className="pb-1 pt-3">
664
+ <CardTitle className="text-xs text-muted-foreground uppercase tracking-wide flex items-center gap-1">
665
+ <TestTube2 className="h-3 w-3" /> Tests
666
+ </CardTitle>
667
+ </CardHeader>
668
+ <CardContent className="pb-3 space-y-1">
669
+ {contract.test_unit_path && (
670
+ <p className="text-xs font-mono">Unit: {contract.test_unit_path}</p>
671
+ )}
672
+ {contract.test_e2e_path && (
673
+ <p className="text-xs font-mono">E2E: {contract.test_e2e_path}</p>
674
+ )}
675
+ </CardContent>
676
+ </Card>
677
+ )}
678
+
679
+ {}
680
+ <Card>
681
+ <CardHeader className="pb-2">
682
+ <CardTitle className="text-sm">Edit Contract</CardTitle>
683
+ </CardHeader>
684
+ <CardContent>
685
+ <ContractEditor
686
+ contract={contract}
687
+ projectId={projectId!}
688
+ onSave={updated => setContract(c => c ? { ...c, ...updated } : c)}
689
+ />
690
+ </CardContent>
691
+ </Card>
692
+ </TabsContent>
693
+
694
+ {}
695
+ <TabsContent value="graph" className="mt-4">
696
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
697
+ <Card>
698
+ <CardHeader className="pb-2">
699
+ <CardTitle className="text-sm">Called By ({contract.callers.length})</CardTitle>
700
+ </CardHeader>
701
+ <CardContent className="space-y-1.5">
702
+ {contract.callers.length === 0 ? (
703
+ <p className="text-xs text-muted-foreground">No callers recorded — may be an entrypoint or dead code</p>
704
+ ) : (
705
+ contract.callers.map(c => (
706
+ <ChunkLinkCard key={c.chunk_id} chunk={c} label="caller" projectId={projectId!} />
707
+ ))
708
+ )}
709
+ </CardContent>
710
+ </Card>
711
+
712
+ <Card>
713
+ <CardHeader className="pb-2">
714
+ <CardTitle className="text-sm">Calls ({contract.callees.length})</CardTitle>
715
+ </CardHeader>
716
+ <CardContent className="space-y-1.5">
717
+ {contract.callees.length === 0 ? (
718
+ <p className="text-xs text-muted-foreground">No outgoing calls recorded</p>
719
+ ) : (
720
+ contract.callees.map(c => (
721
+ <ChunkLinkCard key={c.chunk_id} chunk={c} label="callee" projectId={projectId!} />
722
+ ))
723
+ )}
724
+ </CardContent>
725
+ </Card>
726
+ </div>
727
+ </TabsContent>
728
+
729
+ {}
730
+ <TabsContent value="code" className="mt-4">
731
+ <Card>
732
+ <CardHeader className="pb-2">
733
+ <div className="flex items-center justify-between">
734
+ <CardTitle className="text-sm font-mono">{contract.chunk_name}</CardTitle>
735
+ <span className="text-xs text-muted-foreground">
736
+ L{contract.line_start}–{contract.line_end} · {contract.chunk_type}
737
+ </span>
738
+ </div>
739
+ </CardHeader>
740
+ <CardContent>
741
+ {codeContent ? (
742
+ <pre className="text-xs font-mono bg-muted rounded-md p-3 overflow-auto max-h-[60vh] whitespace-pre">
743
+ {codeContent}
744
+ </pre>
745
+ ) : (
746
+ <p className="text-xs text-muted-foreground">
747
+ Code content not stored — run Pass 2 ingestion to capture chunk source.
748
+ </p>
749
+ )}
750
+ </CardContent>
751
+ </Card>
752
+ </TabsContent>
753
+
754
+ {}
755
+ {blastRadius !== null && (
756
+ <TabsContent value="blast" className="mt-4">
757
+ <Card>
758
+ <CardHeader className="pb-2">
759
+ <CardTitle className="text-sm">
760
+ Blast Radius — {blastRadius.length} chunk{blastRadius.length !== 1 ? 's' : ''} affected
761
+ </CardTitle>
762
+ </CardHeader>
763
+ <CardContent>
764
+ {blastRadius.length === 0 ? (
765
+ <p className="text-xs text-muted-foreground">No callers — change to this chunk has no upstream blast radius</p>
766
+ ) : (
767
+ <div className="space-y-1.5">
768
+ {blastRadius.map((item: any) => (
769
+ <div key={item.chunk_id} className="flex items-center gap-2 text-sm">
770
+ <span className="text-xs bg-red-100 text-red-700 rounded px-1.5 py-0.5 font-mono shrink-0">
771
+ depth {item.depth}
772
+ </span>
773
+ <ChunkLinkCard chunk={item} label="affected" projectId={projectId!} />
774
+ </div>
775
+ ))}
776
+ </div>
777
+ )}
778
+ </CardContent>
779
+ </Card>
780
+ </TabsContent>
781
+ )}
782
+ </Tabs>
783
+ </div>
784
+ )
785
+ }
786
+
787
+ // CIL[END chunk_id="cilchunkdetailpage_cilchunkdetailpage_1784193942"]