spine-framework 0.3.144 → 0.4.0

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 +5051 -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 +20 -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
@@ -0,0 +1,767 @@
1
+ /**
2
+ * @module pipeline
3
+ * @audience internal
4
+ * @layer app-specific
5
+ * @stability stable
6
+ *
7
+ * This module implements the pipeline for processing MCP (Model Context Protocol) requests, utilizing various utilities for data handling and validation. It serves as a core component in the server architecture, facilitating interactions with the database and file system. INVARIANT: All requests must be properly authenticated before reaching this module.
8
+ *
9
+ * @seeAlso adminDb (provides database access for administrative tasks).
10
+ * @seeAlso computeContentHash (used for content integrity verification).
11
+ * @seeAlso McpServer (the main server interface for handling MCP requests).
12
+ *
13
+ * @cil-generated
14
+ */
15
+
16
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
17
+ // CIL[DOC-MACRO purpose="This module implements the pipeline for processing MCP (Model Context Protocol) requests, utilizing various utilities..."]
18
+ // CIL[DOC-RESPONSIBILITY responsibility="This module implements the pipeline for processing MCP (Model Context Protocol) requests, utilizing various utilities..."]
19
+ // CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts"]
20
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
21
+ // CIL[DOC-MICRO logic_summary="This module implements the pipeline for processing MCP (Model Context Protocol) requests, utilizing various utilities..." notable_decisions="[]"]
22
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
23
+ // CIL[DOC-STABILITY stability="stable"]
24
+ // CIL[DOC-AUDIENCE audience="internal"]
25
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
26
+ import { z } from 'zod'
27
+ import { adminDb, resolveTypeRecord } from '../../shared/db.js'
28
+ import * as fs from 'fs'
29
+ import * as path from 'path'
30
+ import * as crypto from 'node:crypto'
31
+ import { toCanonicalPath, computeContentHash } from '../../../functions/_shared/cil.js'
32
+ // CIL[DOC-VECTOR type="context" content="purpose='This module implements the pipeline for processing MCP (Model Context Protocol) requests, utilizing various utilities...'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
33
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
34
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
35
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
36
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
37
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
38
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:module_header:module_header"]
39
+
40
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:computeFileHash:function" type="function" identity="computeFileHash" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
41
+ // CIL[DOC-MACRO purpose="Computes the SHA-256 hash of a given string content."]
42
+ // CIL[DOC-RESPONSIBILITY responsibility="Computes the SHA-256 hash of a given string content."]
43
+ // CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
44
+ // CIL[DOC-CONTRACT inputs="content: string (required) — the content to hash." outputs="string — the resulting SHA-256 hash in hexadecimal format." errors="none" side_effects="none"]
45
+ // CIL[DOC-MICRO logic_summary="Computes the SHA-256 hash of a given string content." notable_decisions="[]"]
46
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
47
+ // CIL[DOC-STABILITY stability="stable"]
48
+ /**
49
+ * Computes the SHA-256 hash of a given string content. This function is used for generating a unique identifier for file contents based on their content.
50
+ *
51
+ * @inputSpec
52
+ * content: string (required) — the content to hash.
53
+ * @outputSpec string — the resulting SHA-256 hash in hexadecimal format.
54
+ * @sideEffects none
55
+ * @stability stable
56
+ * @calls crypto.createHash
57
+ * @cil-generated
58
+ */
59
+ function computeFileHash(content: string): string {
60
+ return crypto.createHash('sha256').update(content, 'utf8').digest('hex')
61
+ }
62
+ // CIL[DOC-VECTOR type="context" content="purpose='Computes the SHA-256 hash of a given string content.'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
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/mcp/tools/cil/pipeline.ts:computeFileHash:function"]
69
+
70
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:estimateTokens:function" type="function" identity="estimateTokens" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
71
+ // CIL[DOC-MACRO purpose="Estimates the number of tokens required for a given text based on its length."]
72
+ // CIL[DOC-RESPONSIBILITY responsibility="Estimates the number of tokens required for a given text based on its length."]
73
+ // CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
74
+ // CIL[DOC-CONTRACT inputs="text: string (required) — the input text for which to estimate tokens." outputs="number — the estimated number of tokens." errors="none" side_effects="none"]
75
+ // CIL[DOC-MICRO logic_summary="Estimates the number of tokens required for a given text based on its length." notable_decisions="[]"]
76
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
77
+ // CIL[DOC-STABILITY stability="stable"]
78
+ /**
79
+ * Estimates the number of tokens required for a given text based on its length. This function is useful for determining resource allocation in text processing tasks.
80
+ *
81
+ * @inputSpec
82
+ * text: string (required) — the input text for which to estimate tokens.
83
+ * @outputSpec number — the estimated number of tokens.
84
+ * @sideEffects none
85
+ * @stability stable
86
+ * @cil-generated
87
+ */
88
+ function estimateTokens(text: string): number {
89
+ return Math.ceil(text.length / 4)
90
+ }
91
+ // CIL[DOC-VECTOR type="context" content="purpose='Estimates the number of tokens required for a given text based on its length.'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
92
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
93
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
94
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
95
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
96
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
97
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:estimateTokens:function"]
98
+
99
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:parseAgentAttributes:function" type="function" identity="parseAgentAttributes" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
100
+ // CIL[DOC-MACRO purpose="Parser for agent attributes in key-value format."]
101
+ // CIL[DOC-RESPONSIBILITY responsibility="Uses a regular expression to match and extract key-value pairs from the input string."]
102
+ // CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
103
+ // CIL[DOC-CONTRACT inputs="attrString: string (required) — a string containing agent attributes in key-value format." outputs="Record<string, string> — a record mapping attribute names to their corresponding values." errors="none" side_effects="none"]
104
+ // CIL[DOC-MICRO logic_summary="Uses a regular expression to match and extract key-value pairs from the input string." notable_decisions="[]"]
105
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
106
+ // CIL[DOC-STABILITY stability="stable"]
107
+ /**
108
+ * Parses a string of agent attributes formatted as key-value pairs and returns them as a record. This function is useful for extracting structured data from a raw attribute string.
109
+ *
110
+ * @macro Parser for agent attributes in key-value format.
111
+ * @micro Uses a regular expression to match and extract key-value pairs from the input string.
112
+ * @inputSpec
113
+ * - attrString: string (required) — a string containing agent attributes in key-value format.
114
+ * @outputSpec Record<string, string> — a record mapping attribute names to their corresponding values.
115
+ * @sideEffects none
116
+ * @stability stable
117
+ * @cil-generated
118
+ */
119
+ function parseAgentAttributes(attrString: string): Record<string, string> {
120
+ const attrs: Record<string, string> = {}
121
+ const regex = /(\w+)="([^"]*)"/g
122
+ let match: RegExpExecArray | null
123
+ while ((match = regex.exec(attrString)) !== null) {
124
+ attrs[match[1]] = match[2]
125
+ }
126
+ return attrs
127
+ }
128
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:parseAgentAttributes:function"]
129
+ // CIL[DOC-VECTOR type="context" content="purpose='Parser for agent attributes in key-value format.'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
130
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
131
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
132
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
133
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
134
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
135
+
136
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:AgentParsedMarker:interface" type="interface" identity="AgentParsedMarker" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
137
+ // CIL[DOC-MACRO purpose="Defines AgentParsedMarker"]
138
+ // CIL[DOC-RESPONSIBILITY responsibility="AgentParsedMarker implementation"]
139
+ // CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
140
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
141
+ // CIL[DOC-MICRO logic_summary="" notable_decisions="[]"]
142
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
143
+ // CIL[DOC-STABILITY stability="stable"]
144
+ interface AgentParsedMarker {
145
+ stable_id: string
146
+ start_line: number
147
+ end_line: number
148
+ type: string
149
+ identity: string
150
+ parent: string
151
+ attributes?: Record<string, string>
152
+ }
153
+ // CIL[DOC-VECTOR type="context" content="purpose='Defines AgentParsedMarker'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
154
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
155
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
156
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
157
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
158
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
159
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:AgentParsedMarker:interface"]
160
+
161
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:parseAgentCilMarkers:function" type="function" identity="parseAgentCilMarkers" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
162
+ // CIL[DOC-MACRO purpose="Defines parseAgentCilMarkers"]
163
+ // CIL[DOC-RESPONSIBILITY responsibility="parseAgentCilMarkers implementation"]
164
+ // CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
165
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
166
+ // CIL[DOC-MICRO logic_summary="" notable_decisions="[]"]
167
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
168
+ // CIL[DOC-STABILITY stability="stable"]
169
+ function parseAgentCilMarkers(lines: string[]): AgentParsedMarker[] {
170
+ const markers: AgentParsedMarker[] = []
171
+ const stack: { line: number; attrs: Record<string, string> }[] = []
172
+
173
+ for (let i = 0; i < lines.length; i++) {
174
+ const trimmed = lines[i].trim()
175
+ const beginMatch = trimmed.match(/^(?:\/\/|--|#)\s*CIL\[BEGIN\s+(.+)\]$/) || trimmed.match(/^<!--\s*CIL\[BEGIN\s+(.+)\]\s*-->$/)
176
+ const endMatch = trimmed.match(/^(?:\/\/|--|#)\s*CIL\[END\s+stable_id="([^"]+)"\]$/) || trimmed.match(/^<!--\s*CIL\[END\s+stable_id="([^"]+)"\]\s*-->$/)
177
+
178
+ if (beginMatch) {
179
+ const attrs = parseAgentAttributes(beginMatch[1])
180
+ stack.push({ line: i + 1, attrs })
181
+ } else if (endMatch && stack.length > 0) {
182
+ const opened = stack.pop()!
183
+ markers.push({
184
+ stable_id: endMatch[1],
185
+ start_line: opened.line,
186
+ end_line: i + 1,
187
+ type: opened.attrs.type || 'unknown',
188
+ identity: opened.attrs.identity || '',
189
+ parent: opened.attrs.parent || 'none',
190
+ attributes: opened.attrs,
191
+ })
192
+ }
193
+ }
194
+
195
+ return markers
196
+ }
197
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:parseAgentCilMarkers:function"]
198
+ // CIL[DOC-VECTOR type="context" content="purpose='Defines parseAgentCilMarkers'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
199
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
200
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
201
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
202
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
203
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
204
+
205
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:AgentParsedDocs:interface" type="interface" identity="AgentParsedDocs" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
206
+ // CIL[DOC-MACRO purpose="The AgentParsedDocs interface defines the structure for parsed documentation related to agents, encapsulating various..."]
207
+ // CIL[DOC-RESPONSIBILITY responsibility="The AgentParsedDocs interface defines the structure for parsed documentation related to agents, encapsulating various..."]
208
+ // CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
209
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
210
+ // CIL[DOC-MICRO logic_summary="The AgentParsedDocs interface defines the structure for parsed documentation related to agents, encapsulating various..." notable_decisions="[]"]
211
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
212
+ // CIL[DOC-STABILITY stability="stable"]
213
+ /**
214
+ * The AgentParsedDocs interface defines the structure for parsed documentation related to agents, encapsulating various attributes that describe their functionality and context. It serves as a schema for organizing agent-related information in a consistent manner.
215
+ *
216
+ * @sideEffects none
217
+ * @stability stable
218
+ * @cil-generated
219
+ */
220
+ interface AgentParsedDocs {
221
+ macro?: string
222
+ responsibility?: string
223
+ context?: Record<string, any>
224
+ contract?: Record<string, any>
225
+ micro?: Record<string, any>
226
+ confidence?: { pass: string; score: number; flags: string[] }
227
+ stability?: string
228
+ audience?: string
229
+ vectors?: Record<string, { content: string; status: string }>
230
+ notes?: Array<Record<string, any>>
231
+ learnings?: Array<Record<string, any>>
232
+ raw: Record<string, string>
233
+ }
234
+ // CIL[DOC-VECTOR type="context" content="purpose='The AgentParsedDocs interface defines the structure for parsed documentation related to agents, encapsulating various...'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
235
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
236
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
237
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
238
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
239
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
240
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:AgentParsedDocs:interface"]
241
+
242
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:parseAgentCilDocs:function" type="function" identity="parseAgentCilDocs" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
243
+ // CIL[DOC-MACRO purpose="Documentation parser for agent CIL comments."]
244
+ // CIL[DOC-RESPONSIBILITY responsibility="Iterates through specified line ranges, applying regex to extract structured documentation attributes."]
245
+ // CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
246
+ // CIL[DOC-CONTRACT inputs="lines: string[] (required), startLine: number (required), endLine: number (required)" outputs="AgentParsedDocs — an object containing parsed documentation attributes." errors="none" side_effects="none"]
247
+ // CIL[DOC-MICRO logic_summary="Iterates through specified line ranges, applying regex to extract structured documentation attributes." notable_decisions="[]"]
248
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
249
+ // CIL[DOC-STABILITY stability="stable"]
250
+ /**
251
+ * Parses lines of documentation comments for agent CIL and organizes them into a structured format. This function extracts specific documentation keys and their associated content for further processing.
252
+ *
253
+ * @macro Documentation parser for agent CIL comments.
254
+ * @micro Iterates through specified line ranges, applying regex to extract structured documentation attributes.
255
+ * @inputSpec
256
+ * - lines: string[] (required) — array of lines containing documentation comments.
257
+ * - startLine: number (required) — the starting line number for parsing.
258
+ * - endLine: number (required) — the ending line number for parsing.
259
+ * @outputSpec AgentParsedDocs — an object containing parsed documentation attributes.
260
+ * @sideEffects none
261
+ * @stability stable
262
+ * @calls parseAgentAttributes
263
+ * @cil-generated
264
+ */
265
+ function parseAgentCilDocs(lines: string[], startLine: number, endLine: number): AgentParsedDocs {
266
+ const docs: AgentParsedDocs = { raw: {} }
267
+ for (let i = startLine - 1; i < endLine - 1; i++) {
268
+ const trimmed = lines[i].trim()
269
+ const match = trimmed.match(/^(?:\/\/|--|#)\s*CIL\[DOC-(\w+)\s+(.+)\]$/) || trimmed.match(/^<!--\s*CIL\[DOC-(\w+)\s+(.+)\]\s*-->$/)
270
+ if (!match) continue
271
+ const key = match[1]
272
+ const content = match[2]
273
+ docs.raw[key] = content
274
+
275
+ const attrs = parseAgentAttributes(content)
276
+
277
+ switch (key) {
278
+ case 'MACRO':
279
+ docs.macro = attrs.purpose || content.replace(/^purpose="|"$/g, '')
280
+ break
281
+ case 'RESPONSIBILITY':
282
+ docs.responsibility = attrs.responsibility || content.replace(/^responsibility="|"$/g, '')
283
+ break
284
+ case 'CONTEXT':
285
+ docs.context = attrs
286
+ break
287
+ case 'CONTRACT':
288
+ docs.contract = attrs
289
+ break
290
+ case 'MICRO':
291
+ docs.micro = attrs
292
+ break
293
+ case 'CONFIDENCE':
294
+ docs.confidence = {
295
+ pass: attrs.pass || 'first',
296
+ score: parseFloat(attrs.score || '0'),
297
+ flags: attrs.flags ? attrs.flags.split(',').map((s: string) => s.trim()).filter(Boolean) : [],
298
+ }
299
+ break
300
+ case 'VECTOR':
301
+ if (attrs.type) {
302
+ if (!docs.vectors) docs.vectors = {}
303
+ docs.vectors[attrs.type] = {
304
+ content: attrs.content || '',
305
+ status: attrs.status || 'ready',
306
+ }
307
+ }
308
+ break
309
+ case 'STABILITY':
310
+ docs.stability = attrs.stability || content.replace(/^stability="|"$/g, '')
311
+ break
312
+ case 'AUDIENCE':
313
+ docs.audience = attrs.audience || content.replace(/^audience="|"$/g, '')
314
+ break
315
+ case 'NOTE':
316
+ if (!docs.notes) docs.notes = []
317
+ docs.notes.push(attrs)
318
+ break
319
+ case 'LEARNING':
320
+ if (!docs.learnings) docs.learnings = []
321
+ docs.learnings.push(attrs)
322
+ break
323
+ }
324
+ }
325
+ return docs
326
+ }
327
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:parseAgentCilDocs:function"]
328
+
329
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:mapAgentDocsToChunkData:function" type="function" identity="mapAgentDocsToChunkData" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
330
+ // CIL[DOC-VECTOR type="context" content="purpose='Documentation parser for agent CIL comments.'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
331
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
332
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
333
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
334
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
335
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
336
+ // CIL[DOC-MACRO purpose="Defines mapAgentDocsToChunkData"]
337
+ // CIL[DOC-RESPONSIBILITY responsibility="mapAgentDocsToChunkData implementation"]
338
+ // CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
339
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
340
+ // CIL[DOC-MICRO logic_summary="" notable_decisions="[]"]
341
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
342
+ // CIL[DOC-STABILITY stability="stable"]
343
+ function mapAgentDocsToChunkData(docs: AgentParsedDocs): Record<string, any> {
344
+ const pendingVectors = docs.vectors
345
+ ? Object.entries(docs.vectors).filter(([, v]) => v.status === 'pending_human_input').map(([k]) => k)
346
+ : []
347
+
348
+ return {
349
+ macro: docs.macro || docs.raw.MACRO || '',
350
+ micro: docs.micro?.logic_summary || docs.responsibility || '',
351
+ description: docs.macro || '',
352
+ input_spec: docs.contract?.inputs?.replace(/\\n/g, '\n') || '',
353
+ output_spec: docs.contract?.outputs || '',
354
+ side_effects: docs.contract?.side_effects || '',
355
+ throws: docs.contract?.errors || '',
356
+ module: docs.context?.module || '',
357
+ layer: docs.context?.layer || '',
358
+ doc_confidence: docs.confidence?.pass === 'second' ? 'ai_generated' : 'from_source',
359
+ confidence_score: docs.confidence?.score || 0,
360
+ confidence_flags: docs.confidence?.flags || [],
361
+ related_files: docs.context?.related_files || '',
362
+ tags: docs.micro?.notable_decisions || '',
363
+ depends_on: docs.contract?.dependencies || '',
364
+ stability: docs.stability || '',
365
+ audience: docs.audience || '',
366
+ vector_content: docs.vectors || {},
367
+ vectors_pending_human_review: pendingVectors,
368
+ notes: docs.notes || [],
369
+ learnings: docs.learnings || [],
370
+ }
371
+ }
372
+ // CIL[DOC-VECTOR type="context" content="purpose='Defines mapAgentDocsToChunkData'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
373
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
374
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
375
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
376
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
377
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
378
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:mapAgentDocsToChunkData:function"]
379
+
380
+ /**
381
+ * Registers tools for testing authentication and updating pipeline statuses in the MCP server. This module facilitates the management of file statuses within a project pipeline.
382
+ *
383
+ * @macro Tool registration function for MCP server.
384
+ * @micro Utilizes asynchronous database operations to update project file statuses based on input parameters.
385
+ * @inputSpec
386
+ * - server: McpServer (required) — The MCP server instance to register tools with.
387
+ * @outputSpec Promise<void> — No specific return value.
388
+ * @sideEffects Database writes to update project file statuses.
389
+ * @stability stable
390
+ * @calls adminDb.from, adminDb.update
391
+ * @cil-generated
392
+ */
393
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline.ts:register:function" type="function" identity="register" parent="~/.framework/mcp/tools/cil/pipeline.ts"]
394
+ // CIL[DOC-MACRO purpose="Tool registration function for MCP server."]
395
+ // CIL[DOC-RESPONSIBILITY responsibility="Utilizes asynchronous database operations to update project file statuses based on input parameters."]
396
+ // CIL[DOC-CONTEXT module="pipeline" layer="app-specific" related_files=".framework/functions/_shared/cil.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline.ts"]
397
+ // CIL[DOC-CONTRACT inputs="server: McpServer (required) — The MCP server instance to register tools with." outputs="Promise<void> — No specific return value." errors="none" side_effects="Database writes to update project file statuses."]
398
+ // CIL[DOC-MICRO logic_summary="Utilizes asynchronous database operations to update project file statuses based on input parameters." notable_decisions="[]"]
399
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
400
+ // CIL[DOC-STABILITY stability="stable"]
401
+ export function register(server: McpServer) {
402
+
403
+ server.registerTool(
404
+ 'spine_cil_test_auth',
405
+ {
406
+ description: 'Test authentication and module loading',
407
+ inputSchema: z.object({}),
408
+ },
409
+ async () => {
410
+ return {
411
+ content: [{
412
+ type: 'text',
413
+ text: JSON.stringify({ success: true, message: 'Pipeline tools loaded successfully' }, null, 2),
414
+ }],
415
+ }
416
+ }
417
+ )
418
+
419
+ server.registerTool(
420
+ 'spine_cil_update_pipeline_status',
421
+ {
422
+ description: 'Update a file\'s pipeline status. Call at the end of each agent-run step. Standard statuses follow the 0–8 pipeline, but custom temporary statuses are also allowed.',
423
+ inputSchema: z.object({
424
+ project_id: z.string().uuid().describe('The cil_project UUID'),
425
+ file_path: z.string().describe('Relative file path within the repository'),
426
+ status: z.string().describe('File status — standard statuses follow the 0–8 pipeline, but custom temporary statuses are allowed'),
427
+ metadata: z.object({}).passthrough().optional().describe('Additional metadata to store with the status update'),
428
+ }),
429
+ },
430
+ async ({ project_id, file_path, status, metadata = {} }) => {
431
+ const [projectRes] = await Promise.allSettled([
432
+ adminDb.from('items').select('id, title, data').eq('id', project_id).maybeSingle(),
433
+ ])
434
+
435
+ const project = projectRes.status === 'fulfilled' ? projectRes.value.data : null
436
+ if (!project) {
437
+ return { content: [{ type: 'text', text: JSON.stringify({ error: 'Project not found' }, null, 2) }] }
438
+ }
439
+
440
+ const pipelineData = project.data || {}
441
+ const fileStatuses = pipelineData.file_statuses || {}
442
+
443
+ fileStatuses[file_path] = status
444
+ fileStatuses[`${file_path}_updated`] = new Date().toISOString()
445
+ if (Object.keys(metadata).length > 0) {
446
+ Object.assign(fileStatuses, { [`${file_path}_meta`]: metadata })
447
+ }
448
+
449
+ const [updateRes] = await Promise.allSettled([
450
+ adminDb.from('items').update({
451
+ data: { ...pipelineData, file_statuses: fileStatuses },
452
+ }).eq('id', project_id).select()
453
+ ])
454
+
455
+ if (updateRes.status === 'rejected' || !updateRes.value.data) {
456
+ return { content: [{ type: 'text', text: JSON.stringify({ error: 'Failed to update status' }, null, 2) }] }
457
+ }
458
+
459
+ return {
460
+ content: [{
461
+ type: 'text',
462
+ text: JSON.stringify({
463
+ success: true,
464
+ project_id,
465
+ file_path,
466
+ new_status: status,
467
+ updated_at: fileStatuses[`${file_path}_updated`],
468
+ }, null, 2),
469
+ }],
470
+ }
471
+ }
472
+ )
473
+
474
+ server.registerTool(
475
+ 'spine_cil_store_markers',
476
+ {
477
+ description: `Parse CIL[BEGIN]/CIL[END] markers and DOC tags from a source file and upsert chunk records in the DB. The file must already be saved to disk before calling this.
478
+
479
+ Key constraints:
480
+ - file_path must be relative from repo root — never absolute
481
+ - file_hash must be the SHA256 of the current file content on disk (shasum -a 256 {path} | awk '{print $1}')
482
+ - start_line/end_line are the 1-based line numbers of the CIL[BEGIN]/CIL[END] lines themselves
483
+ - stable_id format: {canonical_path}:{identity_lowercase}:{type}
484
+ - parent: stable_id of direct parent, or "none" for top-level chunks
485
+
486
+ Returns: { ok, created, updated, results[] } — verify ok: true and counts match before continuing.`,
487
+ inputSchema: z.object({
488
+ project_id: z.string().uuid().describe('The cil_project UUID'),
489
+ file_path: z.string().describe('Relative path from repo root'),
490
+ file_hash: z.string().optional().describe('SHA256 of the current file content'),
491
+ markers: z.array(z.object({
492
+ stable_id: z.string().describe('Stable chunk ID'),
493
+ chunk_id: z.string().optional().describe('Legacy chunk ID (old format)'),
494
+ start_line: z.number().int().min(1),
495
+ end_line: z.number().int().min(1),
496
+ type: z.string(),
497
+ identity: z.string(),
498
+ parent: z.string(),
499
+ })).optional().describe('Chunk boundaries extracted from the annotated source — if omitted, all CIL[BEGIN/END] markers found in the file are used'),
500
+ }),
501
+ },
502
+ async ({ project_id, file_path, file_hash, markers }) => {
503
+ const { data: projectRows } = await adminDb.from('items').select('id, data, account_id')
504
+ .filter('data->>kb_type', 'eq', 'cil_project')
505
+ .eq('id', project_id)
506
+ .eq('is_active', true)
507
+ const projectItem = (projectRows || [])[0]
508
+ if (!projectItem) {
509
+ return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `Project not found: ${project_id}` }) }] }
510
+ }
511
+
512
+ const accountId: string = projectItem.account_id || ''
513
+ if (!accountId) {
514
+ return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: 'Project has no account_id — cannot stamp chunks' }) }] }
515
+ }
516
+
517
+ const repoPath: string = projectItem.data?.repo_path || ''
518
+ if (!repoPath) {
519
+ return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: 'Project has no repo_path configured' }) }] }
520
+ }
521
+
522
+ const absolutePath = path.join(repoPath, file_path.replace(/^\//, ''))
523
+ if (!fs.existsSync(absolutePath)) {
524
+ return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `Source file not found on disk: ${absolutePath}` }) }] }
525
+ }
526
+
527
+ const content = fs.readFileSync(absolutePath, 'utf-8')
528
+ const computedHash = computeFileHash(content)
529
+ if (file_hash && computedHash !== file_hash) {
530
+ return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `Hash mismatch: provided ${file_hash} != computed ${computedHash}` }) }] }
531
+ }
532
+
533
+ const lines = content.split('\n')
534
+ const parsed = parseAgentCilMarkers(lines)
535
+ const parsedById = new Map(parsed.map(m => [m.stable_id, m]))
536
+
537
+ const markersToStore = (markers && markers.length > 0) ? markers : parsed
538
+ const providedIds = new Set(markersToStore.map(m => m.stable_id))
539
+ const sourceIds = new Set(parsed.map(m => m.stable_id))
540
+ const missingInSource = markersToStore.filter(m => !sourceIds.has(m.stable_id))
541
+ const extraInSource = parsed.filter(m => !providedIds.has(m.stable_id))
542
+ if (missingInSource.length > 0 || extraInSource.length > 0) {
543
+ return {
544
+ content: [{
545
+ type: 'text',
546
+ text: JSON.stringify({
547
+ ok: false,
548
+ error: `Marker mismatch: missing_in_source=[${missingInSource.map(m => m.stable_id).join(',')}], extra_in_source=[${extraInSource.map(m => m.stable_id).join(',')}]`,
549
+ }),
550
+ }],
551
+ }
552
+ }
553
+
554
+ let chunkTypeId: string, chunkDesignSchema: Record<string, any>, chunkValidationSchema: Record<string, any>
555
+ let fileTypeId: string, fileDesignSchema: Record<string, any>, fileValidationSchema: Record<string, any>
556
+ try {
557
+ const [chunkTypeRecord, fileTypeRecord] = await Promise.all([
558
+ resolveTypeRecord('item', 'cil_chunk'),
559
+ resolveTypeRecord('item', 'cil_file')
560
+ ])
561
+ chunkTypeId = chunkTypeRecord.id
562
+ chunkDesignSchema = chunkTypeRecord.design_schema
563
+ chunkValidationSchema = chunkTypeRecord.validation_schema
564
+ fileTypeId = fileTypeRecord.id
565
+ fileDesignSchema = fileTypeRecord.design_schema
566
+ fileValidationSchema = fileTypeRecord.validation_schema
567
+ } catch (e: any) {
568
+ return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `CIL type not found — run migrations first: ${e.message}` }) }] }
569
+ }
570
+
571
+ const now = new Date().toISOString()
572
+ const versionId = projectItem.data?.active_version_id || '0.1.0'
573
+
574
+ const { data: existingFile } = await adminDb.from('items').select('id, data')
575
+ .filter('data->>kb_type', 'eq', 'cil_file')
576
+ .filter('data->>project_id', 'eq', project_id)
577
+ .filter('data->>file_path', 'eq', file_path)
578
+ .eq('is_active', true)
579
+ .maybeSingle()
580
+
581
+ let fileId: string
582
+ if (existingFile) {
583
+ fileId = existingFile.id
584
+ try {
585
+ const updatedFileData = {
586
+ ...existingFile.data,
587
+ file_hash: computedHash,
588
+ version_id: versionId,
589
+ updated_at: now,
590
+ }
591
+ await adminDb.from('items')
592
+ .update({ data: updatedFileData, updated_at: now })
593
+ .eq('id', fileId)
594
+ } catch {
595
+ // File metadata update is best-effort; continue with chunk sync
596
+ }
597
+ } else {
598
+ const fileStableId = toCanonicalPath(repoPath, absolutePath)
599
+ const fileData = {
600
+ kb_type: 'cil_file',
601
+ project_id,
602
+ file_path,
603
+ file_hash,
604
+ stable_id: fileStableId,
605
+ version_id: versionId,
606
+ status: '2-chunked', // Files reach this status after chunking
607
+ last_status_at: now,
608
+ }
609
+ const { data: newFile, error: fileError } = await adminDb.from('items')
610
+ .insert({
611
+ title: file_path,
612
+ type_id: fileTypeId,
613
+ account_id: accountId,
614
+ design_schema: fileDesignSchema,
615
+ validation_schema: fileValidationSchema,
616
+ is_active: true,
617
+ data: fileData,
618
+ })
619
+ .select('id')
620
+ .maybeSingle()
621
+ if (fileError || !newFile) {
622
+ return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `Failed to create cil_file item: ${fileError?.message || 'unknown'}` }) }] }
623
+ }
624
+ fileId = newFile.id
625
+ }
626
+
627
+ const { data: existingChunks } = await adminDb.from('items').select('id, data')
628
+ .filter('data->>kb_type', 'eq', 'cil_chunk')
629
+ .filter('data->>project_id', 'eq', project_id)
630
+ .filter('data->>file_path', 'eq', file_path)
631
+ .eq('is_active', true)
632
+ .limit(1000)
633
+ const existingByChunkId = new Map((existingChunks || []).map((c: any) => [c.data?.stable_id || c.data?.legacy_chunk_id || c.data?.chunk_id || c.id, c]))
634
+ const existingIds = new Set((existingChunks || []).map((c: any) => c.id))
635
+
636
+ const results: any[] = []
637
+ const errors: string[] = []
638
+ const usedIds = new Set<string>()
639
+
640
+ for (const m of markersToStore) {
641
+ const _parsed = parsedById.get(m.stable_id)!
642
+ const codeContent = lines.slice(m.start_line, m.end_line - 1).join('\n')
643
+ const docs = parseAgentCilDocs(lines, m.start_line, m.end_line)
644
+ const docFields = mapAgentDocsToChunkData(docs)
645
+ const fullContentHash = computeContentHash(codeContent)
646
+ const tokenCount = estimateTokens(codeContent)
647
+
648
+ const mm = m as any
649
+ const parentStableId = mm.parent === 'none' ? null : mm.parent
650
+ const baseData = {
651
+ kb_type: 'cil_chunk',
652
+ stable_id: mm.stable_id,
653
+ chunk_name: m.identity,
654
+ project_id,
655
+ file_path,
656
+ file_id: fileId, // Link to parent file item for existing embedding/mapping functions
657
+ chunk_type: m.type,
658
+ parent_id: parentStableId,
659
+ parent_stable_id: parentStableId,
660
+ version_id: versionId,
661
+ line_start: m.start_line,
662
+ line_end: m.end_line,
663
+ stored_hash: fullContentHash,
664
+ content_hash: fullContentHash,
665
+ code_content: codeContent,
666
+ token_count: tokenCount,
667
+ is_dead_code: false,
668
+ review_status: 'approved',
669
+ boundary_confidence: 'high',
670
+ boundary_source: 'agent_markers',
671
+ ...docFields,
672
+ }
673
+
674
+ const existing: any = existingByChunkId.get(m.stable_id)
675
+ if (existing) {
676
+ try {
677
+ const newData = { ...existing.data, ...baseData, updated_at: now }
678
+ const { error } = await adminDb.from('items')
679
+ .update({ data: newData, title: `${file_path}::${m.identity}`, updated_at: now })
680
+ .eq('id', existing.id)
681
+ if (error) errors.push(`${m.stable_id}: ${error.message}`)
682
+ else {
683
+ usedIds.add(existing.id)
684
+ results.push({ stable_id: m.stable_id, action: 'updated', id: existing.id })
685
+ }
686
+ } catch (err: any) {
687
+ errors.push(`${m.stable_id}: ${err?.message || String(err)}`)
688
+ }
689
+ } else {
690
+ try {
691
+ const { data: newChunk, error } = await adminDb.from('items')
692
+ .insert({
693
+ title: `${file_path}::${m.identity}`,
694
+ type_id: chunkTypeId,
695
+ account_id: accountId,
696
+ design_schema: chunkDesignSchema,
697
+ validation_schema: chunkValidationSchema,
698
+ is_active: true,
699
+ data: baseData,
700
+ })
701
+ .select('id')
702
+ .maybeSingle()
703
+ if (error) errors.push(`${m.stable_id}: ${error.message}`)
704
+ else {
705
+ if (newChunk?.id) usedIds.add(newChunk.id)
706
+ results.push({ stable_id: m.stable_id, action: 'created', id: newChunk?.id })
707
+ }
708
+ } catch (err: any) {
709
+ errors.push(`${m.stable_id}: ${err?.message || String(err)}`)
710
+ }
711
+ }
712
+ }
713
+
714
+ const idsToDeactivate = [...existingIds].filter((id: any) => !usedIds.has(id))
715
+ for (const orphanId of idsToDeactivate) {
716
+ try {
717
+ const { error: deactError } = await adminDb.from('items')
718
+ .update({ is_active: false, updated_at: now })
719
+ .eq('id', orphanId)
720
+ if (deactError) errors.push(`deactivate orphan ${orphanId}: ${deactError.message}`)
721
+ } catch (err: any) {
722
+ errors.push(`deactivate orphan ${orphanId}: ${err?.message || String(err)}`)
723
+ }
724
+ }
725
+
726
+ const { count: liveChunkCount } = await adminDb.from('items')
727
+ .select('*', { count: 'exact', head: true })
728
+ .filter('data->>kb_type', 'eq', 'cil_chunk')
729
+ .filter('data->>project_id', 'eq', project_id)
730
+ .eq('is_active', true)
731
+ if (liveChunkCount !== null) {
732
+ try {
733
+ await adminDb.from('items')
734
+ .update({ data: { ...projectItem.data, chunk_count: liveChunkCount } })
735
+ .eq('id', project_id)
736
+ } catch (err: any) {
737
+ errors.push(`project count update: ${err?.message || String(err)}`)
738
+ }
739
+ }
740
+
741
+ return {
742
+ content: [{
743
+ type: 'text',
744
+ text: JSON.stringify({
745
+ ok: errors.length === 0,
746
+ project_id,
747
+ file_path,
748
+ file_id: fileId,
749
+ file_hash: computedHash,
750
+ chunk_count: markersToStore.length,
751
+ created: results.filter(r => r.action === 'created').length,
752
+ updated: results.filter(r => r.action === 'updated').length,
753
+ errors: errors.length > 0 ? errors : undefined,
754
+ results,
755
+ }, null, 2),
756
+ }],
757
+ }
758
+ }
759
+ )
760
+ }
761
+ // CIL[DOC-VECTOR type="context" content="purpose='Tool registration function for MCP server.'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/functions/_shared/cil.ts"]
762
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
763
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
764
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
765
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
766
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
767
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline.ts:register:function"]