spine-framework 0.3.145 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (451) hide show
  1. package/.env.example +76 -0
  2. package/.framework/.spine-manifest.json +19 -0
  3. package/.framework/cli/commands/agents.ts +61 -33
  4. package/.framework/cli/commands/auth.ts +60 -28
  5. package/.framework/cli/commands/create-app.ts +212 -80
  6. package/.framework/cli/commands/dev.ts +184 -68
  7. package/.framework/cli/commands/doctor.ts +324 -152
  8. package/.framework/cli/commands/generate.ts +119 -68
  9. package/.framework/cli/commands/init.ts +141 -242
  10. package/.framework/cli/commands/install-app.ts +1336 -314
  11. package/.framework/cli/commands/items.ts +31 -29
  12. package/.framework/cli/commands/migrate.ts +299 -156
  13. package/.framework/cli/commands/migrations.ts +62 -30
  14. package/.framework/cli/commands/pipelines.ts +31 -29
  15. package/.framework/cli/commands/status.ts +105 -45
  16. package/.framework/cli/commands/system.ts +47 -42
  17. package/.framework/cli/commands/test.ts +161 -102
  18. package/.framework/cli/commands/upgrade.ts +260 -0
  19. package/.framework/cli/commands/validate-app.ts +517 -161
  20. package/.framework/cli/context.ts +117 -85
  21. package/.framework/cli/env-loader.ts +74 -43
  22. package/.framework/cli/index.ts +70 -46
  23. package/.framework/cli/lib/project-files.ts +404 -0
  24. package/.framework/docs/guides/testing-guide.md +1 -1
  25. package/.framework/docs/runtime-types.md +72 -72
  26. package/.framework/functions/_shared/access.ts +84 -0
  27. package/.framework/functions/_shared/agent-runner.ts +5067 -1026
  28. package/.framework/functions/_shared/app-manifest.ts +214 -94
  29. package/.framework/functions/_shared/ast.ts +214 -0
  30. package/.framework/functions/_shared/audit.ts +91 -55
  31. package/.framework/functions/_shared/cil.ts +368 -127
  32. package/.framework/functions/_shared/db.ts +337 -68
  33. package/.framework/functions/_shared/funnel.ts +228 -0
  34. package/.framework/functions/_shared/geo.ts +105 -0
  35. package/.framework/functions/_shared/hash-api-key.ts +94 -17
  36. package/.framework/functions/_shared/index.ts +22 -224
  37. package/.framework/functions/_shared/kb.ts +832 -58
  38. package/.framework/functions/_shared/llm.ts +118 -18
  39. package/.framework/functions/_shared/logging.ts +317 -19
  40. package/.framework/functions/_shared/middleware.ts +701 -131
  41. package/.framework/functions/_shared/notify.ts +70 -0
  42. package/.framework/functions/_shared/outcomes.ts +34 -19
  43. package/.framework/functions/_shared/permissions.ts +501 -315
  44. package/.framework/functions/_shared/pipeline-runner.ts +704 -155
  45. package/.framework/functions/_shared/principal.ts +436 -263
  46. package/.framework/functions/_shared/rate-limit.ts +233 -0
  47. package/.framework/functions/_shared/resolve-credentials.ts +86 -19
  48. package/.framework/functions/_shared/resolve-ids.ts +203 -139
  49. package/.framework/functions/_shared/retry-deliveries.ts +51 -16
  50. package/.framework/functions/_shared/schema-utils.ts +602 -521
  51. package/.framework/functions/_shared/security.ts +345 -0
  52. package/.framework/functions/_shared/testing.ts +197 -172
  53. package/.framework/functions/_shared/tracing.ts +351 -21
  54. package/.framework/functions/_shared/trigger-engine.ts +425 -136
  55. package/.framework/functions/_shared/webhook-registration.ts +71 -70
  56. package/.framework/functions/_shared/webhook-registry.ts +126 -83
  57. package/.framework/functions/account-nodes.ts +30 -30
  58. package/.framework/functions/adapters/generic-webhook-inbound.ts +49 -16
  59. package/.framework/functions/adapters/generic-webhook-outbound.ts +17 -17
  60. package/.framework/functions/adapters/openai-outbound.ts +15 -16
  61. package/.framework/functions/admin-data.ts +596 -173
  62. package/.framework/functions/admin-funnel.ts +64 -60
  63. package/.framework/functions/admin-install-funnel.ts +84 -66
  64. package/.framework/functions/admin-signals.ts +69 -51
  65. package/.framework/functions/ai-agents.ts +431 -106
  66. package/.framework/functions/ai-interactions.ts +186 -112
  67. package/.framework/functions/api-keys.ts +107 -107
  68. package/.framework/functions/apps.ts +154 -136
  69. package/.framework/functions/auth.ts +83 -65
  70. package/.framework/functions/cil-agent-ingest.ts +189 -232
  71. package/.framework/functions/cil-agent.ts +433 -177
  72. package/.framework/functions/cil-callmap.ts +642 -430
  73. package/.framework/functions/cil-config.ts +139 -135
  74. package/.framework/functions/cil-context.ts +214 -127
  75. package/.framework/functions/cil-doc.ts +587 -458
  76. package/.framework/functions/cil-embeddings.ts +453 -364
  77. package/.framework/functions/cil-graph.ts +427 -142
  78. package/.framework/functions/cil-ingest.ts +1418 -1154
  79. package/.framework/functions/cil-pipeline.ts +276 -21
  80. package/.framework/functions/cil-project.ts +659 -132
  81. package/.framework/functions/cil-validate.ts +198 -164
  82. package/.framework/functions/debug-auth.ts +57 -55
  83. package/.framework/functions/deliveries.ts +80 -21
  84. package/.framework/functions/embeddings.ts +1023 -318
  85. package/.framework/functions/eval-harness.ts +146 -108
  86. package/.framework/functions/integration-outbound.ts +205 -75
  87. package/.framework/functions/integration-routes.ts +128 -23
  88. package/.framework/functions/integrations.ts +125 -100
  89. package/.framework/functions/invites.ts +1095 -460
  90. package/.framework/functions/item-progress.ts +158 -102
  91. package/.framework/functions/kb.ts +34 -10
  92. package/.framework/functions/logs.ts +133 -133
  93. package/.framework/functions/observability.ts +152 -122
  94. package/.framework/functions/pipeline-executions.ts +147 -132
  95. package/.framework/functions/pipelines.ts +134 -119
  96. package/.framework/functions/prompt-configs.ts +96 -80
  97. package/.framework/functions/roles.ts +112 -82
  98. package/.framework/functions/security.ts +450 -0
  99. package/.framework/functions/system-cron.ts +117 -80
  100. package/.framework/functions/system.ts +158 -98
  101. package/.framework/functions/tests.ts +29 -29
  102. package/.framework/functions/timers.ts +94 -95
  103. package/.framework/functions/trigger-scheduler.ts +10 -0
  104. package/.framework/functions/triggers.ts +179 -149
  105. package/.framework/functions/types.ts +137 -125
  106. package/.framework/mcp/index.ts +133 -0
  107. package/.framework/mcp/load-env.ts +60 -0
  108. package/.framework/mcp/shared/app-manifest.ts +275 -0
  109. package/.framework/mcp/shared/db.ts +477 -0
  110. package/.framework/mcp/shared/kb.ts +118 -0
  111. package/.framework/mcp/tools/architect.ts +431 -0
  112. package/.framework/mcp/tools/cil/context.ts +345 -0
  113. package/.framework/mcp/tools/cil/graph.ts +242 -0
  114. package/.framework/mcp/tools/cil/ingest.ts +1217 -0
  115. package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +693 -0
  116. package/.framework/mcp/tools/cil/pipeline.ts +767 -0
  117. package/.framework/mcp/tools/cil/project.ts +791 -0
  118. package/.framework/mcp/tools/cil/retrieval.ts +336 -0
  119. package/.framework/mcp/tools/cil/search-core.ts +454 -0
  120. package/.framework/mcp/tools/cil/search.ts +97 -0
  121. package/.framework/mcp/tools/cil/suggest.ts +186 -0
  122. package/.framework/mcp/tools/cil/validate.ts +1369 -0
  123. package/.framework/mcp/tools/kb/delete.ts +139 -0
  124. package/.framework/mcp/tools/kb/index.ts +52 -0
  125. package/.framework/mcp/tools/kb/ingest.ts +84 -0
  126. package/.framework/mcp/tools/kb/list-types.ts +102 -0
  127. package/.framework/mcp/tools/kb/publish.ts +100 -0
  128. package/.framework/mcp/tools/kb/reindex.ts +86 -0
  129. package/.framework/mcp/tools/kb/revoke.ts +85 -0
  130. package/.framework/mcp/tools/kb/search.ts +101 -0
  131. package/.framework/mcp/tools/kb/upsert.ts +125 -0
  132. package/.framework/mcp/tools/observability.ts +510 -0
  133. package/.framework/migrations/001_core_schema.sql +15 -0
  134. package/.framework/migrations/002_core_rls_and_functions.sql +15 -0
  135. package/.framework/migrations/003_core_system_data.sql +16 -1
  136. package/.framework/migrations/004_core_rpc_and_broker.sql +17 -1
  137. package/.framework/migrations/005_core_observability.sql +17 -1
  138. package/.framework/migrations/006_security_hardening_rls.sql +15 -0
  139. package/.framework/migrations/007_kb_article_list.sql +17 -1
  140. package/.framework/migrations/008_items_target.sql +15 -0
  141. package/.framework/migrations/009_roles_slug_unique.sql +15 -0
  142. package/.framework/migrations/010_auth_user_trigger.sql +15 -0
  143. package/.framework/migrations/011_spine_system_account.sql +16 -0
  144. package/.framework/migrations/012_service_role_grants.sql +16 -0
  145. package/.framework/migrations/013_get_account_apps_role_filter.sql +15 -0
  146. package/.framework/migrations/014_apps_required_roles.sql +16 -0
  147. package/.framework/migrations/015_types_kind_slug_unique.sql +15 -0
  148. package/.framework/migrations/016_cil_types.sql +281 -0
  149. package/.framework/migrations/017_cil_stable_ids.sql +37 -0
  150. package/.framework/migrations/018_runtime_tables.sql +129 -0
  151. package/.framework/migrations/019_agent_prompt_columns.sql +56 -0
  152. package/.framework/migrations/020_schema_reconciliation.sql +67 -0
  153. package/.framework/migrations/021_kb_embedding_lifecycle.sql +31 -0
  154. package/.framework/migrations/032_cil_status_migration.sql +73 -0
  155. package/.framework/migrations/033_cil_versioning.sql +73 -0
  156. package/.framework/migrations/034_match_embeddings_knn.sql +115 -0
  157. package/.framework/migrations/035_rate_limits.sql +55 -0
  158. package/.framework/migrations/036_demo_record_flags.sql +72 -0
  159. package/.framework/migrations/037_kb_types_canonical.sql +244 -0
  160. package/.framework/migrations/038_drop_demo_record_flags.sql +38 -0
  161. package/.framework/migrations/042_registration_hierarchy.sql +309 -0
  162. package/.framework/migrations/043_policy_actor_cleanup.sql +39 -0
  163. package/.framework/migrations/044_match_embeddings_filtered_knn.sql +151 -0
  164. package/.framework/migrations/045_security_critical_rls.sql +139 -0
  165. package/.framework/migrations/046_security_missing_rls.sql +79 -0
  166. package/.framework/migrations/047_people_updated_by.sql +27 -0
  167. package/.framework/migrations/048_watcher_last_seen_at.sql +24 -0
  168. package/.framework/migrations/049_security_blocklist.sql +148 -0
  169. package/.framework/migrations/050_notifications.sql +49 -0
  170. package/.framework/migrations/051_message_agent_fields.sql +74 -0
  171. package/.framework/migrations/052_registration_security.sql +421 -0
  172. package/.framework/migrations/053_builtin_action_seeds.sql +66 -0
  173. package/.framework/migrations/054_kb_ingest_lease.sql +157 -0
  174. package/.framework/migrations/055_type_id_drift_reconciliation.sql +33 -0
  175. package/.framework/migrations/056_slug_column_reconciliation.sql +38 -0
  176. package/.framework/migrations/057_pipelines_slug_identity.sql +14 -0
  177. package/.framework/migrations/058_account_data_field_declarations.sql +53 -0
  178. package/.framework/migrations/059_registration_placement_fixes.sql +269 -0
  179. package/.framework/migrations/060_account_person_record_permissions.sql +38 -0
  180. package/.framework/migrations/061_fk_dedup.sql +32 -0
  181. package/.framework/public/spine-logo.svg +10 -3
  182. package/.framework/scripts/app-install-cli.ts +190 -93
  183. package/.framework/scripts/assemble-frontend.sh +127 -44
  184. package/.framework/scripts/assemble-functions.sh +128 -30
  185. package/.framework/scripts/boundary-check.sh +6 -2
  186. package/.framework/scripts/build-manifest.sh +24 -68
  187. package/.framework/scripts/check-core-integrity.sh +15 -76
  188. package/.framework/scripts/checksum-manifest.mts +343 -0
  189. package/.framework/scripts/cil-migrate-markers.ts +403 -0
  190. package/.framework/scripts/fix-cil-markers.mjs +176 -0
  191. package/.framework/scripts/verify-integrity.sh +21 -57
  192. package/.framework/scripts/verify-manifest.mts +305 -0
  193. package/.framework/seeds/types/funnel_signal_use.json +74 -21
  194. package/.framework/seeds/types/spine_instance.json +73 -21
  195. package/.framework/src/App.tsx +118 -72
  196. package/.framework/src/apps/admin/index.tsx +855 -58
  197. package/.framework/src/components/AppWrapper.tsx +43 -45
  198. package/.framework/src/components/CustomAppLoader.tsx +160 -116
  199. package/.framework/src/components/admin/AdminListPage.tsx +46 -44
  200. package/.framework/src/components/admin/AdminSidebar.tsx +57 -47
  201. package/.framework/src/components/admin/AdminStatsCard.tsx +46 -44
  202. package/.framework/src/components/admin/PageInstructions.tsx +98 -2
  203. package/.framework/src/components/admin/SortableTableHeader.tsx +44 -45
  204. package/.framework/src/components/app-shell/GenericAppShell.tsx +64 -65
  205. package/.framework/src/components/app-shell/GenericDetailPage.tsx +44 -47
  206. package/.framework/src/components/app-shell/GenericListPage.tsx +45 -49
  207. package/.framework/src/components/app-sidebar.tsx +42 -45
  208. package/.framework/src/components/auth/ProtectedRoute.tsx +48 -41
  209. package/.framework/src/components/auth/TurnstileWidget.tsx +27 -0
  210. package/.framework/src/components/kb/KBArticleEditor.tsx +231 -22
  211. package/.framework/src/components/kb/KBArticleList.tsx +251 -10
  212. package/.framework/src/components/layout/AppShell.tsx +51 -45
  213. package/.framework/src/components/layout/Header.tsx +42 -43
  214. package/.framework/src/components/layout/Layout.tsx +46 -46
  215. package/.framework/src/components/layout/Sidebar.tsx +196 -96
  216. package/.framework/src/components/runtime/DataDetailHeader.tsx +55 -30
  217. package/.framework/src/components/runtime/DataDetailPage.tsx +31 -269
  218. package/.framework/src/components/runtime/DataFilters.tsx +49 -74
  219. package/.framework/src/components/runtime/DataHeader.tsx +53 -32
  220. package/.framework/src/components/runtime/DataListPage.tsx +51 -155
  221. package/.framework/src/components/runtime/DataStats.tsx +66 -44
  222. package/.framework/src/components/runtime/DataTable.tsx +49 -149
  223. package/.framework/src/components/runtime/SchemaDetailForm.tsx +45 -75
  224. package/.framework/src/components/runtime/index.ts +119 -16
  225. package/.framework/src/components/search-form.tsx +46 -29
  226. package/.framework/src/components/shared/AgentView.tsx +65 -48
  227. package/.framework/src/components/shared/FieldRenderer.tsx +144 -50
  228. package/.framework/src/components/shared/InviteManager.tsx +207 -97
  229. package/.framework/src/components/shared/MemberList.tsx +97 -0
  230. package/.framework/src/components/shared/SchemaFields.tsx +107 -86
  231. package/.framework/src/components/ui/DataTable.tsx +80 -68
  232. package/.framework/src/components/ui/Form.tsx +157 -146
  233. package/.framework/src/components/ui/ItemCard.tsx +74 -67
  234. package/.framework/src/components/ui/ItemListView.tsx +73 -68
  235. package/.framework/src/components/ui/LoadingSpinner.tsx +43 -48
  236. package/.framework/src/components/ui/Modal.tsx +78 -68
  237. package/.framework/src/components/ui/RichTextEditor.tsx +89 -69
  238. package/.framework/src/components/ui/accordion.tsx +85 -86
  239. package/.framework/src/components/ui/alert-dialog.tsx +197 -184
  240. package/.framework/src/components/ui/alert.tsx +105 -94
  241. package/.framework/src/components/ui/aspect-ratio.tsx +57 -43
  242. package/.framework/src/components/ui/avatar.tsx +122 -107
  243. package/.framework/src/components/ui/badge.tsx +60 -55
  244. package/.framework/src/components/ui/breadcrumb.tsx +127 -128
  245. package/.framework/src/components/ui/button-group.tsx +86 -72
  246. package/.framework/src/components/ui/button.tsx +71 -50
  247. package/.framework/src/components/ui/calendar.tsx +72 -57
  248. package/.framework/src/components/ui/card.tsx +136 -129
  249. package/.framework/src/components/ui/carousel.tsx +226 -107
  250. package/.framework/src/components/ui/chart.tsx +252 -147
  251. package/.framework/src/components/ui/checkbox.tsx +43 -44
  252. package/.framework/src/components/ui/collapsible.tsx +86 -71
  253. package/.framework/src/components/ui/combobox.tsx +282 -249
  254. package/.framework/src/components/ui/command.tsx +158 -146
  255. package/.framework/src/components/ui/context-menu.tsx +239 -240
  256. package/.framework/src/components/ui/dialog.tsx +174 -157
  257. package/.framework/src/components/ui/direction.tsx +72 -56
  258. package/.framework/src/components/ui/drawer.tsx +168 -169
  259. package/.framework/src/components/ui/dropdown-menu.tsx +254 -223
  260. package/.framework/src/components/ui/empty.tsx +131 -120
  261. package/.framework/src/components/ui/field.tsx +205 -173
  262. package/.framework/src/components/ui/hover-card.tsx +71 -72
  263. package/.framework/src/components/ui/input-group.tsx +148 -133
  264. package/.framework/src/components/ui/input-otp.tsx +99 -86
  265. package/.framework/src/components/ui/input.tsx +43 -41
  266. package/.framework/src/components/ui/item.tsx +207 -185
  267. package/.framework/src/components/ui/kbd.tsx +57 -56
  268. package/.framework/src/components/ui/label.tsx +45 -41
  269. package/.framework/src/components/ui/menubar.tsx +268 -236
  270. package/.framework/src/components/ui/native-select.tsx +85 -86
  271. package/.framework/src/components/ui/navigation-menu.tsx +166 -156
  272. package/.framework/src/components/ui/pagination.tsx +131 -141
  273. package/.framework/src/components/ui/popover.tsx +125 -128
  274. package/.framework/src/components/ui/progress.tsx +47 -44
  275. package/.framework/src/components/ui/radio-group.tsx +60 -55
  276. package/.framework/src/components/ui/resizable.tsx +85 -72
  277. package/.framework/src/components/ui/scroll-area.tsx +57 -58
  278. package/.framework/src/components/ui/select.tsx +182 -169
  279. package/.framework/src/components/ui/separator.tsx +42 -43
  280. package/.framework/src/components/ui/sheet.tsx +170 -159
  281. package/.framework/src/components/ui/sidebar.tsx +395 -398
  282. package/.framework/src/components/ui/skeleton.tsx +42 -43
  283. package/.framework/src/components/ui/slider.tsx +61 -44
  284. package/.framework/src/components/ui/sonner.tsx +44 -44
  285. package/.framework/src/components/ui/spinner.tsx +47 -42
  286. package/.framework/src/components/ui/switch.tsx +56 -42
  287. package/.framework/src/components/ui/table-primitives.tsx +272 -132
  288. package/.framework/src/components/ui/table.tsx +140 -142
  289. package/.framework/src/components/ui/tabs.tsx +110 -93
  290. package/.framework/src/components/ui/textarea.tsx +43 -44
  291. package/.framework/src/components/ui/toggle-group.tsx +87 -71
  292. package/.framework/src/components/ui/toggle.tsx +56 -56
  293. package/.framework/src/components/ui/tooltip.tsx +99 -85
  294. package/.framework/src/contexts/AppContext.tsx +166 -114
  295. package/.framework/src/contexts/AuthContext.tsx +232 -137
  296. package/.framework/src/hooks/use-mobile.ts +43 -44
  297. package/.framework/src/hooks/useApi.ts +185 -172
  298. package/.framework/src/hooks/useAppPath.ts +31 -29
  299. package/.framework/src/hooks/useApps.ts +77 -42
  300. package/.framework/src/hooks/useEntityList.ts +66 -29
  301. package/.framework/src/hooks/useEntityRecord.ts +76 -32
  302. package/.framework/src/hooks/useForm.ts +62 -30
  303. package/.framework/src/hooks/useListSchema.ts +60 -43
  304. package/.framework/src/hooks/useSchemaRecord.ts +115 -95
  305. package/.framework/src/lib/api.ts +258 -134
  306. package/.framework/src/lib/registration.ts +181 -0
  307. package/.framework/src/lib/supabase.ts +118 -81
  308. package/.framework/src/lib/utils.ts +266 -266
  309. package/.framework/src/main.tsx +43 -44
  310. package/.framework/src/pages/DashboardPage.tsx +44 -43
  311. package/.framework/src/pages/NoAppPage.tsx +50 -0
  312. package/.framework/src/pages/NotFoundPage.tsx +32 -29
  313. package/.framework/src/pages/SetupPage.tsx +34 -33
  314. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +69 -58
  315. package/.framework/src/pages/admin/AIAgentsPage.tsx +43 -40
  316. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +63 -55
  317. package/.framework/src/pages/admin/APIKeysPage.tsx +44 -42
  318. package/.framework/src/pages/admin/AlertsConfigPage.tsx +117 -94
  319. package/.framework/src/pages/admin/AppDetailPage.tsx +48 -42
  320. package/.framework/src/pages/admin/AppsPage.tsx +45 -42
  321. package/.framework/src/pages/admin/DeliveriesPage.tsx +49 -17
  322. package/.framework/src/pages/admin/DesignedPage.tsx +31 -30
  323. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +58 -0
  324. package/.framework/src/pages/admin/EmbeddingsPage.tsx +49 -0
  325. package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +31 -29
  326. package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +46 -29
  327. package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -29
  328. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +68 -55
  329. package/.framework/src/pages/admin/IntegrationsPage.tsx +45 -42
  330. package/.framework/src/pages/admin/InvitesPage.tsx +60 -44
  331. package/.framework/src/pages/admin/LogsPage.tsx +87 -137
  332. package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +31 -29
  333. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +150 -89
  334. package/.framework/src/pages/admin/PipelineDetailPage.tsx +77 -104
  335. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +44 -43
  336. package/.framework/src/pages/admin/PipelinesPage.tsx +59 -145
  337. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +53 -42
  338. package/.framework/src/pages/admin/PromptConfigsPage.tsx +47 -117
  339. package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +31 -44
  340. package/.framework/src/pages/admin/RoleDetailPage.tsx +49 -92
  341. package/.framework/src/pages/admin/RolesPage.tsx +47 -164
  342. package/.framework/src/pages/admin/SecurityPage.tsx +310 -0
  343. package/.framework/src/pages/admin/SelectTestPage.tsx +30 -32
  344. package/.framework/src/pages/admin/ShadcnTestPage.tsx +37 -44
  345. package/.framework/src/pages/admin/SimpleDashboard.tsx +32 -44
  346. package/.framework/src/pages/admin/TestRunDetailPage.tsx +97 -44
  347. package/.framework/src/pages/admin/TestingDashboard.tsx +126 -71
  348. package/.framework/src/pages/admin/TimerDetailPage.tsx +67 -55
  349. package/.framework/src/pages/admin/TimersPage.tsx +44 -42
  350. package/.framework/src/pages/admin/TriggerDetailPage.tsx +47 -42
  351. package/.framework/src/pages/admin/TriggersPage.tsx +58 -57
  352. package/.framework/src/pages/admin/TypeDetailPage.tsx +91 -55
  353. package/.framework/src/pages/admin/TypesPage.tsx +45 -42
  354. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +258 -128
  355. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +127 -123
  356. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +308 -235
  357. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +159 -110
  358. package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +432 -0
  359. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +200 -178
  360. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +286 -239
  361. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +211 -90
  362. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +156 -143
  363. package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +379 -0
  364. package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +337 -0
  365. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +219 -214
  366. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
  367. package/.framework/src/pages/auth/AuthConfirmPage.tsx +135 -65
  368. package/.framework/src/pages/auth/ForgotPasswordPage.tsx +39 -31
  369. package/.framework/src/pages/auth/LoginPage.tsx +38 -32
  370. package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -28
  371. package/.framework/src/pages/auth/RegisterPage.tsx +429 -155
  372. package/.framework/src/pages/spine-framework/APIPage.tsx +33 -30
  373. package/.framework/src/pages/spine-framework/CLIPage.tsx +32 -30
  374. package/.framework/src/types/auth.ts +101 -93
  375. package/.framework/src/types/types.ts +283 -262
  376. package/.framework/templates/project.json +87 -0
  377. package/.framework/templates/spine.config.neutral.json +7 -0
  378. package/.framework/tests/api/api-surface.test.ts +381 -0
  379. package/.framework/tests/fixtures/seed.ts +427 -0
  380. package/.framework/tests/fixtures/teardown.ts +228 -0
  381. package/.framework/tests/reporter.ts +351 -0
  382. package/.framework/tests/setup.ts +135 -0
  383. package/.framework/tests/ui/ui-sweep.ts +278 -0
  384. package/.framework/tests/unit/admin-data-logger.test.ts +310 -0
  385. package/.framework/tests/unit/agent-runner.test.ts +2389 -0
  386. package/.framework/tests/unit/ai-interactions.test.ts +81 -0
  387. package/.framework/tests/unit/app-manifest.test.ts +359 -0
  388. package/.framework/tests/unit/assembly-scripts.test.ts +172 -0
  389. package/.framework/tests/unit/cil-determinism.test.ts +85 -0
  390. package/.framework/tests/unit/core-isolation.test.ts +153 -0
  391. package/.framework/tests/unit/funnel-signals.test.ts +135 -0
  392. package/.framework/tests/unit/install-app.test.ts +1759 -0
  393. package/.framework/tests/unit/invites-security.test.ts +572 -0
  394. package/.framework/tests/unit/kb-ingest-lease.test.ts +287 -0
  395. package/.framework/tests/unit/kb-search.test.ts +119 -0
  396. package/.framework/tests/unit/migrate.test.ts +509 -0
  397. package/.framework/tests/unit/notify.test.ts +136 -0
  398. package/.framework/tests/unit/permissions.test.ts +269 -0
  399. package/.framework/tests/unit/pipeline-runner.test.ts +755 -0
  400. package/.framework/tests/unit/principal-cache.test.ts +138 -0
  401. package/.framework/tests/unit/retrieval-golden.test.ts +520 -0
  402. package/.framework/tests/unit/runtime-isolation.test.ts +642 -0
  403. package/.framework/tests/unit/schema-utils.test.ts +225 -0
  404. package/.framework/tests/unit/trigger-engine.test.ts +513 -0
  405. package/.framework/tests/unit/validate-app.test.ts +527 -0
  406. package/README.md +34 -3
  407. package/bin/spine-framework.cjs +1 -0
  408. package/config/tailwind.config.cjs +7 -0
  409. package/config/tsconfig.functions.json +42 -0
  410. package/config/tsconfig.json +37 -9
  411. package/config/vite.config.ts +31 -2
  412. package/netlify.toml +31 -3
  413. package/package.json +46 -29
  414. package/scripts/assemble-frontend.sh +127 -44
  415. package/scripts/assemble-functions.sh +127 -29
  416. package/scripts/boundary-check.sh +6 -2
  417. package/scripts/build-manifest.sh +24 -68
  418. package/scripts/checksum-manifest.mts +345 -0
  419. package/scripts/dev-clean.sh +86 -0
  420. package/scripts/dev-netlify.sh +49 -0
  421. package/scripts/netlify-dev-wrapper.sh +2 -0
  422. package/scripts/verify-install.ts +358 -0
  423. package/scripts/verify-integrity.sh +21 -57
  424. package/scripts/verify-manifest.mts +305 -0
  425. package/templates/project/gitignore +45 -0
  426. package/{config → templates/project}/package-lock.json +22335 -9366
  427. package/vitest.config.ts +46 -0
  428. package/.framework/public/spine.config.json +0 -91
  429. package/config/deno.lock +0 -108
  430. package/config/tsconfig.node.tsbuildinfo +0 -1
  431. package/config/tsconfig.tsbuildinfo +0 -1
  432. package/config/vite.config.d.ts +0 -2
  433. package/custom/.devin/AGENT.md +0 -357
  434. package/custom/.devin/skills/install-app/SKILL.md +0 -39
  435. package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +0 -39
  436. package/custom/.devin/skills/spine-workbench-idea/SKILL.md +0 -36
  437. package/custom/.devin/skills/spine-workbench-implement/SKILL.md +0 -46
  438. package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +0 -28
  439. package/custom/.devin/skills/spine-workbench-plan/SKILL.md +0 -38
  440. package/custom/.devin/workflows/app-install.yaml +0 -83
  441. package/custom/README.md +0 -79
  442. package/docs/README.md +0 -15
  443. package/scripts/app-install-cli.ts +0 -286
  444. package/scripts/check-core-integrity.sh +0 -82
  445. package/scripts/ingest-chunks.cjs +0 -202
  446. package/scripts/kb-chunk-parser.cjs +0 -312
  447. package/scripts/kb-chunk-parser.ts +0 -330
  448. package/scripts/kb-ingest-docs.ts +0 -203
  449. package/scripts/load-test-app-install.ts +0 -484
  450. package/scripts/test-login.js +0 -33
  451. package/spine.config.json +0 -91
@@ -1,18 +1,13 @@
1
- // CIL[BEGIN chunk_id="cilagentpage_module_header_1784193942" type="module_header" identity="module_header" parent="none"]
2
- // CIL[DOC-MACRO purpose="Import dependencies and icons for the CIL agent page"]
3
- // CIL[DOC-RESPONSIBILITY responsibility="Provides module imports and icon references used by the page"]
4
- // CIL[DOC-CONTEXT module="cortex:cil-agent" 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="Sets up React hooks, router, apiFetch, app path hook, UI components, and lucide icons" notable_decisions="[]"]
7
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
1
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/src/pages/admin/cil/CILAgentPage.tsx"]
2
+ // CIL[DOC-MACRO purpose="Chat interface for the CIL agent that answers natural-language questions about indexed code"]
3
+ // CIL[DOC-RESPONSIBILITY responsibility="Provide a React page that lets users ask the CIL agent questions and view grounded answers with source chunk references"]
4
+ // CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/badge.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/components/ui/textarea.tsx,.framework/src/lib/api.ts"]
5
+ // CIL[DOC-CONTRACT inputs="project_id from URL and user question" outputs="Rendered chat UI with messages and source links" errors="API request failures render error message in chat" side_effects="Calls /api/cil-agent?action=prepare, /api/ai-agents?action=run, /api/admin-data?entity=messages, and /api/cil-project"]
6
+ // CIL[DOC-MICRO logic_summary="Imports dependencies, defines message types, markdown rendering, message bubble, suggestions, and the main page component." notable_decisions="[]"]
7
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
8
  // CIL[DOC-STABILITY stability="stable"]
9
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"]
10
+
16
11
  import { useState, useRef, useEffect, useCallback } from 'react'
17
12
  import { useParams } from 'react-router-dom'
18
13
  import { apiFetch } from '@core/lib/api'
@@ -37,48 +32,54 @@ import {
37
32
 
38
33
 
39
34
  import { PageInstructions } from '../../../components/admin/PageInstructions'
40
- // CIL[END chunk_id="cilagentpage_module_header_1784193942"]
41
- // CIL[BEGIN chunk_id="cilagentpage_message_1784193942" type="interface" identity="Message" parent="none"]
42
- // CIL[DOC-MACRO purpose="Define the shape of a chat message"]
43
- // CIL[DOC-RESPONSIBILITY responsibility="Declares the TypeScript interface for messages exchanged in the agent chat"]
44
- // CIL[DOC-CONTEXT module="cortex:cil-agent" layer="presentation" related_files="[\".framework/functions/_shared/principal.ts\",\".framework/migrations/025_retype_threads_messages.sql\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/functions/_shared/schema-utils.ts\",\"\\\"]"]
45
- // CIL[DOC-CONTRACT inputs="none" outputs="Message type contract" errors="none" side_effects="none"]
46
- // CIL[DOC-MICRO logic_summary="Describes id, role, content, optional sources, tool_calls_made, and loading flag" notable_decisions="[]"]
47
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
48
- // CIL[DOC-STABILITY stability="stable"]
49
- // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/principal.ts, .framework/migrations/025_retype_threads_messages.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/functions/_shared/schema-utils.ts, \."]
50
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
51
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
52
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
35
+
36
+ // CIL[DOC-VECTOR type="context" content="purpose='Chat interface for the CIL agent that answers natural-language questions about indexed code'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/button.tsx,.framework/src/components/ui/textarea.tsx"]
37
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
38
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
39
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
53
40
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
54
41
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
42
+ // CIL[END stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:module_header:module_header"]
43
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:Message:interface" type="interface" identity="Message" parent="~/.framework/src/pages/admin/cil/CILAgentPage.tsx"]
44
+ // CIL[DOC-MACRO purpose="Message shape for CIL agent chat exchanges"]
45
+ // CIL[DOC-RESPONSIBILITY responsibility="Describe the fields for a chat message including role, content, optional sources and tool calls"]
46
+ // CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/badge.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/components/ui/textarea.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILAgentPage.tsx"]
47
+ // CIL[DOC-CONTRACT inputs="none" outputs="TypeScript interface" errors="none" side_effects="none"]
48
+ // CIL[DOC-MICRO logic_summary="Defines id, role, content, sources, tool_calls_made, and loading fields." notable_decisions="[]"]
49
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
50
+ // CIL[DOC-STABILITY stability="stable"]
51
+
55
52
  interface Message {
56
53
  id: string
57
54
  role: 'user' | 'assistant' | 'system'
58
55
  content: string
59
- sources?: string[]
56
+ message_type?: string
57
+ tool?: string
58
+ sources?: { id: string; label: string }[]
60
59
  tool_calls_made?: string[]
61
60
  loading?: boolean
62
61
  }
62
+ // CIL[DOC-VECTOR type="context" content="purpose='Message shape for CIL agent chat exchanges'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/button.tsx,.framework/src/components/ui/textarea.tsx"]
63
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
64
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
65
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
66
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
67
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
68
+ // CIL[END stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:Message:interface"]
63
69
 
64
70
 
65
71
 
66
72
 
67
- // CIL[END chunk_id="cilagentpage_message_1784193942"]
68
- // CIL[BEGIN chunk_id="cilagentpage_rendermarkdown_1784193942" type="function" identity="renderMarkdown" parent="none"]
69
- // CIL[DOC-MACRO purpose="Render assistant message text with code blocks and inline formatting"]
70
- // CIL[DOC-RESPONSIBILITY responsibility="Convert plain text containing markdown-style formatting into React nodes"]
71
- // CIL[DOC-CONTEXT module="cortex:cil-agent" layer="presentation" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/functions/_shared/schema-utils.ts\",\".framework/migrations/025_retype_threads_messages.sql\",\".framework/src/pages/admin/RolesPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"\\\"]"]
72
- // CIL[DOC-CONTRACT inputs="none" outputs="React.ReactNode[]" errors="none" side_effects="none"]
73
- // CIL[DOC-MICRO logic_summary="Splits on triple-backtick blocks, renders pre/code, then applies inline code, bold, and newline processing" notable_decisions="[]"]
74
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
73
+
74
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:renderMarkdown:function" type="function" identity="renderMarkdown" parent="~/.framework/src/pages/admin/cil/CILAgentPage.tsx"]
75
+ // CIL[DOC-MACRO purpose="Convert assistant answer text with markdown-like code and emphasis markers into React nodes"]
76
+ // CIL[DOC-RESPONSIBILITY responsibility="Render inline code, bold text, code blocks, and line breaks safely for assistant messages"]
77
+ // CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/badge.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/components/ui/textarea.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILAgentPage.tsx"]
78
+ // CIL[DOC-CONTRACT inputs="text: string" outputs="Array of React nodes" errors="none" side_effects="none"]
79
+ // CIL[DOC-MICRO logic_summary="Splits text on code fences, then parses inline markers for code and bold." notable_decisions="[]"]
80
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
75
81
  // CIL[DOC-STABILITY stability="stable"]
76
- // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, .framework/functions/_shared/schema-utils.ts, .framework/migrations/025_retype_threads_messages.sql, .framework/src/pages/admin/RolesPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
77
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
78
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
79
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
80
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
81
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
82
+
82
83
  function renderMarkdown(text: string): React.ReactNode[] {
83
84
  const parts: React.ReactNode[] = []
84
85
  let key = 0
@@ -98,45 +99,54 @@ function renderMarkdown(text: string): React.ReactNode[] {
98
99
  )
99
100
  } else {
100
101
 
102
+
103
+
101
104
  const inline = seg.split(/(`[^`]+`|\*\*[^*]+\*\*|\n)/g).map((chunk, i) => {
102
105
  if (chunk.startsWith('`') && chunk.endsWith('`')) {
103
106
  return <code key={i} className="bg-muted px-1 py-0.5 rounded text-xs font-mono">{chunk.slice(1, -1)}</code>
104
107
  }
108
+
105
109
  if (chunk.startsWith('**') && chunk.endsWith('**')) {
106
110
  return <strong key={i}>{chunk.slice(2, -2)}</strong>
107
111
  }
108
112
  if (chunk === '\n') return <br key={i} />
109
113
  return chunk
110
114
  })
115
+
111
116
  parts.push(<span key={key++}>{inline}</span>)
112
117
  }
118
+
113
119
  }
114
120
  return parts
115
121
  }
116
122
 
123
+ // CIL[DOC-VECTOR type="context" content="purpose='Convert assistant answer text with markdown-like code and emphasis markers into React nodes'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/button.tsx,.framework/src/components/ui/textarea.tsx"]
124
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
125
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
126
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
127
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
128
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
129
+ // CIL[END stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:renderMarkdown:function"]
130
+
117
131
 
118
132
 
119
- // CIL[END chunk_id="cilagentpage_rendermarkdown_1784193942"]
120
- // CIL[BEGIN chunk_id="cilagentpage_messagebubble_1784193942" type="function" identity="MessageBubble" parent="none"]
121
- // CIL[DOC-MACRO purpose="Render a single chat message bubble with metadata chips"]
122
- // CIL[DOC-RESPONSIBILITY responsibility="Display a user or assistant message, loading skeleton, and source or tool chips"]
123
- // CIL[DOC-CONTEXT module="cortex:cil-agent" layer="presentation" related_files="[\".framework/migrations/025_retype_threads_messages.sql\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/functions/_shared/schema-utils.ts\",\"\\\"]"]
124
- // CIL[DOC-CONTRACT inputs="none" outputs="JSX.Element" errors="none" side_effects="none"]
125
- // CIL[DOC-MICRO logic_summary="Determines user vs assistant layout, calls renderMarkdown for assistant content, and links to source chunks" notable_decisions="[]"]
126
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
133
+
134
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:MessageBubble:component" type="component" identity="MessageBubble" parent="~/.framework/src/pages/admin/cil/CILAgentPage.tsx"]
135
+ // CIL[DOC-MACRO purpose="Display a single chat message with avatar, markdown body, and optional tool and source chips"]
136
+ // CIL[DOC-RESPONSIBILITY responsibility="Render user or assistant message and link source chunks to the chunk detail page"]
137
+ // CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/badge.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/components/ui/textarea.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILAgentPage.tsx"]
138
+ // CIL[DOC-CONTRACT inputs="message, projectId, appPath" outputs="JSX message row" errors="none" side_effects="none"]
139
+ // CIL[DOC-MICRO logic_summary="Chooses avatar icon, renders markdown for assistant, and shows tool calls and source chips." notable_decisions="[]"]
140
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
127
141
  // CIL[DOC-STABILITY stability="stable"]
128
- // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: .framework/migrations/025_retype_threads_messages.sql, .framework/src/pages/admin/TypeDetailPage.tsx, custom/apps/portal/pages/ContentPage.tsx, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/functions/_shared/schema-utils.ts, \."]
129
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
130
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
131
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
132
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
133
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
142
+
134
143
  function MessageBubble({ message, projectId, appPath }: {
135
144
  message: Message
136
145
  projectId: string
137
146
  appPath: (p: string) => string
138
147
  }) {
139
148
  const isUser = message.role === 'user'
149
+ const mt = message.message_type
140
150
 
141
151
  if (message.loading) {
142
152
  return (
@@ -153,6 +163,39 @@ function MessageBubble({ message, projectId, appPath }: {
153
163
  )
154
164
  }
155
165
 
166
+ // Intermediate research steps render as a compact left-aligned trail rather
167
+ // than full chat bubbles so the plan/tool activity is visually distinct from
168
+ // the agent's actual replies.
169
+ if (!isUser && (mt === 'plan' || mt === 'thinking' || mt === 'tool_call' || mt === 'tool_result')) {
170
+ return (
171
+ <div className="flex items-start gap-2.5 pl-8">
172
+ <div className="flex-1 min-w-0 text-xs">
173
+ {mt === 'tool_call' && (
174
+ <span className="inline-flex items-center gap-1.5 bg-amber-50 border border-amber-200 text-amber-700 rounded-full px-2.5 py-1">
175
+ <Wrench className="h-3 w-3" /> {message.tool || 'tool'} — running
176
+ </span>
177
+ )}
178
+ {mt === 'tool_result' && (
179
+ <span className="inline-flex items-center gap-1.5 bg-emerald-50 border border-emerald-200 text-emerald-700 rounded-full px-2.5 py-1">
180
+ <Wrench className="h-3 w-3" /> {message.tool || 'tool'} — done
181
+ </span>
182
+ )}
183
+ {(mt === 'plan' || mt === 'thinking') && (
184
+ <div className="text-muted-foreground italic border-l-2 border-indigo-200 pl-3 py-0.5">
185
+ <span className="text-[10px] uppercase tracking-wide text-indigo-400 not-italic font-medium mr-1.5">
186
+ {mt === 'plan' ? 'plan' : 'thinking'}
187
+ </span>
188
+ {renderMarkdown(message.content)}
189
+ </div>
190
+ )}
191
+ </div>
192
+ </div>
193
+ )
194
+ }
195
+
196
+ const isAwaiting = mt === 'awaiting_input'
197
+ const isError = mt === 'error'
198
+
156
199
  return (
157
200
  <div className={`flex items-start gap-2.5 ${isUser ? 'flex-row-reverse' : ''}`}>
158
201
  <div className={`h-6 w-6 rounded-full flex items-center justify-center shrink-0 mt-0.5 ${isUser ? 'bg-slate-200' : 'bg-indigo-100'}`}>
@@ -160,14 +203,22 @@ function MessageBubble({ message, projectId, appPath }: {
160
203
  ? <User className="h-3.5 w-3.5 text-slate-600" />
161
204
  : <Bot className="h-3.5 w-3.5 text-indigo-600" />
162
205
  }
206
+
163
207
  </div>
164
208
 
165
209
  <div className={`flex-1 min-w-0 ${isUser ? 'items-end' : 'items-start'} flex flex-col`}>
166
210
  <div className={`rounded-xl px-3.5 py-2.5 max-w-[85%] text-sm leading-relaxed ${
167
211
  isUser
168
212
  ? 'bg-slate-900 text-white rounded-tr-sm'
169
- : 'bg-muted rounded-tl-sm'
213
+ : isError
214
+ ? 'bg-red-50 border border-red-200 text-red-700 rounded-tl-sm'
215
+ : isAwaiting
216
+ ? 'bg-indigo-50 border border-indigo-200 rounded-tl-sm'
217
+ : 'bg-muted rounded-tl-sm'
170
218
  }`}>
219
+ {isAwaiting && (
220
+ <div className="text-[10px] uppercase tracking-wide text-indigo-500 font-medium mb-1">Needs your input</div>
221
+ )}
171
222
  {isUser
172
223
  ? <span className="whitespace-pre-wrap">{message.content}</span>
173
224
  : <div className="prose-sm">{renderMarkdown(message.content)}</div>
@@ -184,12 +235,12 @@ function MessageBubble({ message, projectId, appPath }: {
184
235
  ))}
185
236
  {(message.sources || []).map((src, i) => (
186
237
  <a
187
- key={`src-${src}-${i}`}
188
- href={appPath(projectId ? `/cil/${projectId}/chunks/${src}` : `/cil/chunks/${src}`)}
238
+ key={`src-${src.id}-${i}`}
239
+ href={appPath(projectId ? `/cil/${projectId}/chunks/${src.id}` : `/cil/chunks/${src.id}`)}
189
240
  className="inline-flex items-center gap-1 text-xs bg-indigo-50 border border-indigo-200 text-indigo-700 rounded-full px-2 py-0.5 hover:bg-indigo-100 transition-colors"
190
- title={`Open chunk: ${src}`}
241
+ title={`Open chunk: ${src.label}`}
191
242
  >
192
- <Code2 className="h-2.5 w-2.5" /> {src}
243
+ <Code2 className="h-2.5 w-2.5" /> {src.label}
193
244
  </a>
194
245
  ))}
195
246
  </div>
@@ -199,23 +250,25 @@ function MessageBubble({ message, projectId, appPath }: {
199
250
  )
200
251
  }
201
252
 
253
+ // CIL[DOC-VECTOR type="context" content="purpose='Display a single chat message with avatar, markdown body, and optional tool and source chips'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/button.tsx,.framework/src/components/ui/textarea.tsx"]
254
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
255
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
256
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
257
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
258
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
259
+ // CIL[END stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:MessageBubble:component"]
202
260
 
203
261
 
204
- // CIL[END chunk_id="cilagentpage_messagebubble_1784193942"]
205
- // CIL[BEGIN chunk_id="cilagentpage_suggestions_1784193942" type="constant" identity="SUGGESTIONS" parent="none"]
206
- // CIL[DOC-MACRO purpose="Provide default example questions for the CIL agent chat"]
207
- // CIL[DOC-RESPONSIBILITY responsibility="Supplies a constant list of sample user queries for the empty state"]
208
- // CIL[DOC-CONTEXT module="cortex:cil-agent" 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\",\"\\\"]"]
209
- // CIL[DOC-CONTRACT inputs="none" outputs="readonly string[]" errors="none" side_effects="none"]
210
- // CIL[DOC-MICRO logic_summary="Array of natural-language questions covering auth, embeddings, refactoring, and undocumented chunks" notable_decisions="[]"]
211
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
262
+
263
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:SUGGESTIONS:constant" type="constant" identity="SUGGESTIONS" parent="~/.framework/src/pages/admin/cil/CILAgentPage.tsx"]
264
+ // CIL[DOC-MACRO purpose="Preset example prompts for the CIL agent chat"]
265
+ // CIL[DOC-RESPONSIBILITY responsibility="Provide ready-made questions users can click to start a conversation"]
266
+ // CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/badge.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/components/ui/textarea.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILAgentPage.tsx"]
267
+ // CIL[DOC-CONTRACT inputs="none" outputs="Array of prompt strings" errors="none" side_effects="none"]
268
+ // CIL[DOC-MICRO logic_summary="Static list of questions covering authentication, embeddings, refactor safety, side effects, and undocumented chunks." notable_decisions="[]"]
269
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
212
270
  // CIL[DOC-STABILITY stability="stable"]
213
- // 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, \."]
214
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
215
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
216
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
217
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
218
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
271
+
219
272
  const SUGGESTIONS = [
220
273
  'What does the authentication middleware do?',
221
274
  'Which functions write to the embeddings table?',
@@ -225,23 +278,57 @@ const SUGGESTIONS = [
225
278
  'Show me undocumented chunks in this project',
226
279
  ]
227
280
 
228
-
229
-
230
- // CIL[END chunk_id="cilagentpage_suggestions_1784193942"]
231
- // CIL[BEGIN chunk_id="cilagentpage_cilagentpage_1784193942" type="component" identity="CILAgentPage" parent="none"]
232
- // CIL[DOC-MACRO purpose="Render the interactive CIL agent chat page"]
233
- // CIL[DOC-RESPONSIBILITY responsibility="Manage chat state, send questions to the CIL agent API, and render the conversation UI"]
234
- // CIL[DOC-CONTEXT module="cortex:cil-agent" layer="presentation" related_files="[]"]
235
- // CIL[DOC-CONTRACT inputs="none" outputs="JSX.Element" errors="Displays API errors as assistant messages" side_effects="Calls /api/cil-agent and /api/cil-project; updates messages and input state"]
236
- // CIL[DOC-MICRO logic_summary="Loads project title, maintains messages/input/sending refs, sends messages via apiFetch, scrolls to bottom, and renders messages and input area" notable_decisions="[]"]
237
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
238
- // CIL[DOC-STABILITY stability="stable"]
239
- // CIL[DOC-VECTOR type="context" content="Layer: presentation. Direct callers: 0. Direct calls: 0. Related files: none."]
240
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
241
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
242
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
281
+ // CIL[DOC-VECTOR type="context" content="purpose='Preset example prompts for the CIL agent chat'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/button.tsx,.framework/src/components/ui/textarea.tsx"]
282
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
283
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
284
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
243
285
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
244
286
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
287
+ // CIL[END stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:SUGGESTIONS:constant"]
288
+
289
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:mapRecordToMessage:function" type="function" identity="mapRecordToMessage" parent="~/.framework/src/pages/admin/cil/CILAgentPage.tsx"]
290
+ // CIL[DOC-MACRO purpose="Map a persisted thread message record into the chat display Message shape"]
291
+ // CIL[DOC-RESPONSIBILITY responsibility="Translate message_type, tool, and retrieved_sources fields from a messages row into a renderable Message"]
292
+ // CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/pages/admin/cil/CILAgentPage.tsx"]
293
+ // CIL[DOC-CONTRACT inputs="rec: messages record" outputs="Message" errors="none" side_effects="none"]
294
+ // CIL[DOC-MICRO logic_summary="Derives role from message_type, sources from retrieved_sources, and surfaces tool name for tool_call/tool_result rows." notable_decisions="[]"]
295
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
296
+ // CIL[DOC-STABILITY stability="stable"]
297
+ function mapRecordToMessage(rec: any): Message {
298
+ const mt = rec?.data?.message_type || 'agent'
299
+ const role: Message['role'] = mt === 'human' ? 'user' : (mt === 'system' ? 'system' : 'assistant')
300
+ const rawSources = Array.isArray(rec?.data?.cited_sources) && rec.data.cited_sources.length
301
+ ? rec.data.cited_sources
302
+ : (rec?.data?.retrieved_sources || [])
303
+ const sources = rawSources
304
+ .map((s: any) => ({ id: s.document_id, label: s.chunk_name || s.title || s.document_id }))
305
+ .filter((s: any) => s.id)
306
+ return {
307
+ id: rec.id,
308
+ role,
309
+ content: rec.content || '',
310
+ message_type: mt,
311
+ tool: rec?.data?.tool,
312
+ sources,
313
+ }
314
+ }
315
+ // CIL[DOC-VECTOR type="context" content="purpose='Map a persisted thread message record into the chat display Message shape'; imports: none"]
316
+ // CIL[DOC-VECTOR type="blast_radius" content="Local impact only; used by CILAgentPage.loadMessages"]
317
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
318
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
319
+ // CIL[END stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:mapRecordToMessage:function"]
320
+
321
+ const TERMINAL_STATUSES = ['complete', 'awaiting_input', 'failed']
322
+ const MAX_STEPS = 20
323
+
324
+ // CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:CILAgentPage:component" type="component" identity="CILAgentPage" parent="~/.framework/src/pages/admin/cil/CILAgentPage.tsx"]
325
+ // CIL[DOC-MACRO purpose="Main admin page for the CIL agent chat"]
326
+ // CIL[DOC-RESPONSIBILITY responsibility="Manage chat state, call the CIL agent API, render messages, suggestions, and input"]
327
+ // CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/badge.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/components/ui/textarea.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILAgentPage.tsx"]
328
+ // CIL[DOC-CONTRACT inputs="project_id from URL and user typed question" outputs="Rendered chat UI with message history and source links" errors="API request failures render error message in chat" side_effects="Calls /api/cil-agent?action=prepare, /api/ai-agents?action=run, /api/admin-data?entity=messages, and /api/cil-project"]
329
+ // CIL[DOC-MICRO logic_summary="Fetches project title, scrolls to new messages, sends question to API, and renders conversation with suggestions." notable_decisions="[]"]
330
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
331
+ // CIL[DOC-STABILITY stability="stable"]
245
332
  export default function CILAgentPage() {
246
333
  const { id: projectId } = useParams<{ id: string }>()
247
334
  const appPath = (path: string) => '/spine-framework/admin' + (path.startsWith('/') ? path : '/' + path)
@@ -249,6 +336,12 @@ export default function CILAgentPage() {
249
336
  const [input, setInput] = useState('')
250
337
  const [sending, setSending] = useState(false)
251
338
  const [projectTitle, setProjectTitle] = useState('')
339
+ const [threadId, setThreadId] = useState<string | null>(null)
340
+ const conversationIdRef = useRef<string | null>(
341
+ (typeof localStorage !== 'undefined' && projectId)
342
+ ? localStorage.getItem(`cil-agent-conversation:${projectId}`)
343
+ : null
344
+ )
252
345
  const bottomRef = useRef<HTMLDivElement>(null)
253
346
  const textareaRef = useRef<HTMLTextAreaElement>(null)
254
347
 
@@ -269,54 +362,80 @@ export default function CILAgentPage() {
269
362
  bottomRef.current?.scrollIntoView({ behavior: 'smooth' })
270
363
  }, [messages])
271
364
 
272
- const sendMessage = useCallback(async (text: string) => {
273
- if (!text.trim() || sending) return
274
-
275
- const userMsg: Message = {
276
- id: crypto.randomUUID(),
277
- role: 'user',
278
- content: text.trim(),
279
- }
280
- const loadingMsg: Message = {
281
- id: crypto.randomUUID(),
282
- role: 'assistant',
283
- content: '',
284
- loading: true,
365
+ const loadMessages = useCallback(async (tid: string) => {
366
+ const res = await apiFetch(`/api/admin-data?action=list&entity=messages&thread_id=${tid}&sort_field=created_at&sort_direction=asc&limit=200`)
367
+ const json = await res.json()
368
+ const recs = Array.isArray(json?.data) ? json.data : (Array.isArray(json) ? json : [])
369
+ setMessages(recs.map(mapRecordToMessage))
370
+ }, [])
371
+
372
+ const ensureThread = useCallback(async (): Promise<string> => {
373
+ if (!conversationIdRef.current) {
374
+ conversationIdRef.current = crypto.randomUUID()
375
+ if (projectId && typeof localStorage !== 'undefined') {
376
+ localStorage.setItem(`cil-agent-conversation:${projectId}`, conversationIdRef.current)
377
+ }
285
378
  }
379
+ const prep = await apiFetch('/api/cil-agent?action=prepare', {
380
+ method: 'POST',
381
+ headers: { 'Content-Type': 'application/json' },
382
+ body: JSON.stringify({
383
+ project_id: projectId,
384
+ conversation_id: conversationIdRef.current,
385
+ }),
386
+ }).then(r => r.json())
387
+ const tid = prep?.thread_id || prep?.data?.thread_id
388
+ if (!tid) throw new Error('Failed to prepare CIL agent thread')
389
+ setThreadId(tid)
390
+ return tid
391
+ }, [projectId])
286
392
 
287
- setMessages(prev => [...prev, userMsg, loadingMsg])
393
+ // Restore an existing conversation thread + history only when a persisted
394
+ // conversation_id already exists — a brand-new session stays lazy until the
395
+ // first message so we don't create empty threads.
396
+ useEffect(() => {
397
+ if (!projectId || threadId || !conversationIdRef.current) return
398
+ let cancelled = false
399
+ ensureThread()
400
+ .then(tid => { if (!cancelled) return loadMessages(tid) })
401
+ .catch(() => {})
402
+ return () => { cancelled = true }
403
+ }, [projectId, threadId, ensureThread, loadMessages])
404
+
405
+ const sendMessage = useCallback(async (text: string) => {
406
+ const trimmed = text.trim()
407
+ if (!trimmed || sending) return
408
+
409
+ setMessages(prev => [
410
+ ...prev,
411
+ { id: crypto.randomUUID(), role: 'user', content: trimmed },
412
+ { id: crypto.randomUUID(), role: 'assistant', content: '', loading: true },
413
+ ])
288
414
  setInput('')
289
415
  setSending(true)
290
416
 
291
417
  try {
292
- const res = await apiFetch('/api/cil-agent?action=ask', {
293
- method: 'POST',
294
- headers: { 'Content-Type': 'application/json' },
295
- body: JSON.stringify({
296
- question: text.trim(),
297
- project_id: projectId,
298
- }),
299
- })
300
- const data = await res.json()
301
- const r = data?.data || data
302
- const answer = r?.answer || 'Sorry, I could not generate a response.'
303
-
304
- setMessages(prev => [
305
- ...prev.slice(0, -1),
306
- {
307
- id: crypto.randomUUID(),
308
- role: 'assistant',
309
- content: answer,
310
- sources: r?.sources || [],
311
- tool_calls_made: r?.tool_calls_made || [],
312
- },
313
- ])
418
+ const tid = threadId || (await ensureThread())
419
+
420
+ let userMessage: string = trimmed
421
+ for (let i = 0; i < MAX_STEPS; i++) {
422
+ const res = await apiFetch('/api/ai-agents?action=run', {
423
+ method: 'POST',
424
+ headers: { 'Content-Type': 'application/json' },
425
+ body: JSON.stringify({ thread_id: tid, user_message: userMessage, mode: 'step' }),
426
+ }).then(r => r.json())
427
+ userMessage = ''
428
+ await loadMessages(tid)
429
+ const status = res?.status || res?.data?.status
430
+ if (TERMINAL_STATUSES.includes(status)) break
431
+ }
314
432
  } catch (err) {
315
433
  setMessages(prev => [
316
- ...prev.slice(0, -1),
434
+ ...prev.filter(m => !m.loading),
317
435
  {
318
436
  id: crypto.randomUUID(),
319
437
  role: 'assistant',
438
+ message_type: 'error',
320
439
  content: `Error: ${err instanceof Error ? err.message : String(err)}`,
321
440
  },
322
441
  ])
@@ -324,7 +443,7 @@ export default function CILAgentPage() {
324
443
  setSending(false)
325
444
  setTimeout(() => textareaRef.current?.focus(), 50)
326
445
  }
327
- }, [projectId, sending])
446
+ }, [projectId, sending, threadId, ensureThread, loadMessages])
328
447
 
329
448
  const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
330
449
  if (e.key === 'Enter' && !e.shiftKey) {
@@ -334,6 +453,11 @@ export default function CILAgentPage() {
334
453
  }
335
454
 
336
455
  const clearConversation = () => {
456
+ conversationIdRef.current = null
457
+ if (projectId && typeof localStorage !== 'undefined') {
458
+ localStorage.removeItem(`cil-agent-conversation:${projectId}`)
459
+ }
460
+ setThreadId(null)
337
461
  setMessages([])
338
462
  setInput('')
339
463
  textareaRef.current?.focus()
@@ -462,4 +586,10 @@ export default function CILAgentPage() {
462
586
  )
463
587
  }
464
588
 
465
- // CIL[END chunk_id="cilagentpage_cilagentpage_1784193942"]
589
+ // CIL[DOC-VECTOR type="context" content="purpose='Main admin page for the CIL agent chat'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/button.tsx,.framework/src/components/ui/textarea.tsx"]
590
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
591
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
592
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
593
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
594
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
595
+ // CIL[END stable_id="~/.framework/src/pages/admin/cil/CILAgentPage.tsx:CILAgentPage:component"]