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
@@ -0,0 +1,693 @@
1
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
2
+ // CIL[DOC-MACRO purpose="Provides MCP tools for monitoring and managing the CIL pipeline state across files"]
3
+ // CIL[DOC-RESPONSIBILITY responsibility="Register MCP tools that expose pipeline status, file readiness, bottleneck analysis, and state updates"]
4
+ // CIL[DOC-CONTEXT module="mcp" layer="tools" related_files=".framework/mcp/shared/db.ts"]
5
+ // CIL[DOC-CONTRACT inputs="McpServer instance" outputs="Registered tools" errors="Database query failures, invalid project or step" side_effects="None"]
6
+ // CIL[DOC-MICRO logic_summary="Imports MCP server and adminDb, defines pipeline step constants and types, then exposes tool registrations" notable_decisions="[]"]
7
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
+ // CIL[DOC-STABILITY stability="stable"]
9
+ // CIL[DOC-AUDIENCE audience="system"]
10
+
11
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
12
+ import { z } from 'zod'
13
+ import { adminDb } from '../../shared/db.js'
14
+ // CIL[DOC-VECTOR type="context" content="purpose='Provides MCP tools for monitoring and managing the CIL pipeline state across files'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
15
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
16
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
17
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
18
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
19
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
20
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:module_header:module_header"]
21
+
22
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:PIPELINE_STEPS:constant" type="constant" identity="PIPELINE_STEPS" parent="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
23
+ // CIL[DOC-MACRO purpose="Defines the ordered sequence of CIL pipeline processing stages"]
24
+ // CIL[DOC-RESPONSIBILITY responsibility="Provide a static, type-safe lookup of pipeline step metadata including prerequisites and target status strings"]
25
+ // CIL[DOC-CONTEXT module="mcp" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
26
+ // CIL[DOC-CONTRACT inputs="None" outputs="Constant step definition object" errors="None" side_effects="None"]
27
+ // CIL[DOC-MICRO logic_summary="Maps each step number to a name, prerequisite array, and target status string" notable_decisions="[]"]
28
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
29
+ // CIL[DOC-STABILITY stability="stable"]
30
+
31
+ const PIPELINE_STEPS = {
32
+ 0: { name: 'discover', prerequisites: [], target_status: '0-discovered' },
33
+ 1: { name: 'select', prerequisites: [0], target_status: '1-selected' },
34
+ 2: { name: 'chunk', prerequisites: [1], target_status: '2-chunked' },
35
+ 3: { name: 'document', prerequisites: [2], target_status: '3-documented' },
36
+ 4: { name: 'validate-chunks', prerequisites: [3], target_status: '4-chunk-validated' },
37
+ 5: { name: 'validate-docs', prerequisites: [4], target_status: '5-doc-validated' },
38
+ 6: { name: 'enrich', prerequisites: [5], target_status: '6-enriched' },
39
+ 7: { name: 'embed-and-map', prerequisites: [6], target_status: '7-embedded-mapped' },
40
+ 8: { name: 'publish', prerequisites: [7], target_status: '8-published' },
41
+ } as const
42
+ // CIL[DOC-VECTOR type="context" content="purpose='Defines the ordered sequence of CIL pipeline processing stages'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
43
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
44
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
45
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
46
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
47
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
48
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:PIPELINE_STEPS:constant"]
49
+
50
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:PipelineStep:type" type="type" identity="PipelineStep" parent="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
51
+ // CIL[DOC-MACRO purpose="Provides a type-safe union of valid pipeline step identifiers"]
52
+ // CIL[DOC-RESPONSIBILITY responsibility="Constrain step references to the keys of the PIPELINE_STEPS object"]
53
+ // CIL[DOC-CONTEXT module="mcp" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
54
+ // CIL[DOC-CONTRACT inputs="None" outputs="PipelineStep union type" errors="None" side_effects="None"]
55
+ // CIL[DOC-MICRO logic_summary="Derives step keys from the PIPELINE_STEPS constant" notable_decisions="[]"]
56
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
57
+ // CIL[DOC-STABILITY stability="stable"]
58
+
59
+ /**
60
+ * PipelineStep represents a key of the PIPELINE_STEPS object, defining the various steps in a data processing pipeline. It exists to provide a type-safe way to reference these steps throughout the module.
61
+ *
62
+ * @sideEffects none
63
+ * @stability stable
64
+ * @cil-generated
65
+ */
66
+ type PipelineStep = keyof typeof PIPELINE_STEPS
67
+ // CIL[DOC-VECTOR type="context" content="purpose='Provides a type-safe union of valid pipeline step identifiers'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
68
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
69
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
70
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
71
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
72
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
73
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:PipelineStep:type"]
74
+
75
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:FilePipelineState:interface" type="interface" identity="FilePipelineState" parent="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
76
+ // CIL[DOC-MACRO purpose="Defines the structure for tracking a single file's progress through the pipeline"]
77
+ // CIL[DOC-RESPONSIBILITY responsibility="Type the per-file pipeline state returned by status and readiness tools"]
78
+ // CIL[DOC-CONTEXT module="mcp" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
79
+ // CIL[DOC-CONTRACT inputs="None" outputs="FilePipelineState interface" errors="None" side_effects="None"]
80
+ // CIL[DOC-MICRO logic_summary="Lists file path, current status, completed/ready/blocked step arrays, and progress percentage" notable_decisions="[]"]
81
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
82
+ // CIL[DOC-STABILITY stability="stable"]
83
+
84
+ /**
85
+ * The FilePipelineState interface represents the state of a file processing pipeline, including its path, current status, and progress. It is used to track the steps completed, those that are ready to proceed, and any that are blocked.
86
+ *
87
+ * @sideEffects none
88
+ * @stability stable
89
+ * @cil-generated
90
+ */
91
+ interface FilePipelineState {
92
+ file_path: string
93
+ current_status: string
94
+ completed_steps: PipelineStep[]
95
+ ready_for: PipelineStep[]
96
+ blocked_by: PipelineStep[]
97
+ progress_percentage: number
98
+ }
99
+ // CIL[DOC-VECTOR type="context" content="purpose='Defines the structure for tracking a single file's progress through the pipeline'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
100
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
101
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
102
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
103
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
104
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
105
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:FilePipelineState:interface"]
106
+
107
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:PipelineStatus:interface" type="interface" identity="PipelineStatus" parent="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
108
+ // CIL[DOC-MACRO purpose="Defines the aggregate pipeline status returned for a whole project"]
109
+ // CIL[DOC-RESPONSIBILITY responsibility="Type the project-level status object containing all file states, step summaries, and overall progress"]
110
+ // CIL[DOC-CONTEXT module="mcp" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
111
+ // CIL[DOC-CONTRACT inputs="None" outputs="PipelineStatus interface" errors="None" side_effects="None"]
112
+ // CIL[DOC-MICRO logic_summary="Groups project id, file state array, per-step counts, and overall progress percentage" notable_decisions="[]"]
113
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
114
+ // CIL[DOC-STABILITY stability="stable"]
115
+
116
+ /**
117
+ * The PipelineStatus interface defines the structure for tracking the status of a pipeline, including project identification, file states, step summaries, and overall progress. It exists to provide a comprehensive overview of the pipeline's execution state.
118
+ *
119
+ * @sideEffects none
120
+ * @stability stable
121
+ * @cil-generated
122
+ */
123
+ interface PipelineStatus {
124
+ project_id: string
125
+ files: FilePipelineState[]
126
+ step_summary: Record<PipelineStep, { completed: number; pending: number; in_progress: number }>
127
+ overall_progress: number
128
+ }
129
+ // CIL[DOC-VECTOR type="context" content="purpose='Defines the aggregate pipeline status returned for a whole project'; No verified external callers; imports: .framework/mcp/shared/db.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
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:PipelineStatus:interface"]
136
+
137
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:register:function" type="function" identity="register" parent="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
138
+ // CIL[DOC-MACRO purpose="Registers all CIL pipeline MCP tools with a server instance"]
139
+ // CIL[DOC-RESPONSIBILITY responsibility="Bind tool handlers for get_pipeline_status, get_files_ready_for_step, update_file_pipeline_state, and get_pipeline_bottlenecks"]
140
+ // CIL[DOC-CONTEXT module="mcp" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
141
+ // CIL[DOC-CONTRACT inputs="server: McpServer" outputs="Tool registrations on the server" errors="Database failures, invalid project or step" side_effects="Queries adminDb and returns JSON tool responses"]
142
+ // CIL[DOC-MICRO logic_summary="Defines four tool registrations that read or update project file_statuses and compute step readiness or bottleneck summaries" notable_decisions="[]"]
143
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
144
+ // CIL[DOC-STABILITY stability="stable"]
145
+
146
+ export function register(server: McpServer) {
147
+
148
+ server.registerTool(
149
+ 'spine_cil_get_pipeline_status',
150
+ {
151
+ description: 'Get comprehensive pipeline status showing file-by-file progress, dependencies, and readiness for next steps.',
152
+ inputSchema: z.object({
153
+ project_id: z.string().uuid().describe('The cil_project UUID'),
154
+ }),
155
+ },
156
+ async ({ project_id }) => {
157
+ const { data: project } = await adminDb.from('items').select('data')
158
+ .eq('id', project_id).maybeSingle()
159
+
160
+ if (!project) {
161
+ return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `Project not found: ${project_id}` }) }] }
162
+ }
163
+
164
+ const fileStatuses: Record<string, string> = project.data?.file_statuses || {}
165
+ const files = Object.entries(fileStatuses).map(([file_path, status]) => ({
166
+ file_path,
167
+ current_status: status,
168
+ completed_steps: getCompletedSteps(status),
169
+ ready_for: getReadySteps(status),
170
+ blocked_by: getBlockedSteps(status),
171
+ progress_percentage: calculateProgress(status)
172
+ }))
173
+
174
+ const stepSummary: Record<PipelineStep, { completed: number; pending: number; in_progress: number }> = {}
175
+ for (const step of Object.keys(PIPELINE_STEPS) as PipelineStep[]) {
176
+ const stepNum = step as unknown as number
177
+ stepSummary[step] = {
178
+ completed: files.filter(f => f.completed_steps.includes(stepNum)).length,
179
+ pending: files.filter(f => f.ready_for.includes(stepNum)).length,
180
+ in_progress: files.filter(f => f.current_status === PIPELINE_STEPS[step].target_status).length
181
+ }
182
+ }
183
+
184
+ const overallProgress = files.reduce((sum, file) => sum + file.progress_percentage, 0) / files.length
185
+
186
+ return {
187
+ content: [{
188
+ type: 'text',
189
+ text: JSON.stringify({
190
+ project_id,
191
+ files,
192
+ step_summary: stepSummary,
193
+ overall_progress: Math.round(overallProgress)
194
+ }, null, 2)
195
+ }],
196
+ }
197
+ }
198
+ )
199
+
200
+ server.registerTool(
201
+ 'spine_cil_get_files_ready_for_step',
202
+ {
203
+ description: 'Get files that are ready to process for a specific pipeline step, considering dependencies.',
204
+ inputSchema: z.object({
205
+ project_id: z.string().uuid().describe('The cil_project UUID'),
206
+ step: z.number().min(0).max(8).describe('Pipeline step number (0-8)'),
207
+ include_blocking_info: z.boolean().default(false).describe('Include information about what blocks each file'),
208
+ }),
209
+ },
210
+ async ({ project_id, step, include_blocking_info }) => {
211
+ const stepKey = step as PipelineStep
212
+ if (!PIPELINE_STEPS[stepKey]) {
213
+ return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `Invalid step: ${step}` }) }] }
214
+ }
215
+
216
+ const { data: project } = await adminDb.from('items').select('data')
217
+ .eq('id', project_id).maybeSingle()
218
+
219
+ if (!project) {
220
+ return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `Project not found: ${project_id}` }) }] }
221
+ }
222
+
223
+ const fileStatuses: Record<string, string> = project.data?.file_statuses || {}
224
+ const allFiles = Object.entries(fileStatuses)
225
+
226
+ const readyFiles = allFiles.filter(([file_path, status]) => {
227
+ const completedSteps = getCompletedSteps(status)
228
+ return PIPELINE_STEPS[stepKey].prerequisites.every(prereq => completedSteps.includes(prereq))
229
+ })
230
+
231
+ const filePaths = readyFiles.map(([file_path]) => file_path)
232
+ const { data: chunks } = await adminDb.from('items').select('data')
233
+ .filter('data->>kb_type', 'eq', 'cil_chunk')
234
+ .filter('data->>project_id', 'eq', project_id)
235
+ .eq('is_active', true)
236
+ .in('data->>file_path' as any, filePaths)
237
+
238
+ const chunkCountByFile: Record<string, number> = {}
239
+ for (const c of chunks || []) {
240
+ const fp = c.data?.file_path
241
+ if (fp) chunkCountByFile[fp] = (chunkCountByFile[fp] || 0) + 1
242
+ }
243
+
244
+ const files = readyFiles.map(([file_path, status]) => {
245
+ const fileInfo = {
246
+ file_path,
247
+ status,
248
+ chunk_count: chunkCountByFile[file_path] || 0,
249
+ completed_steps: getCompletedSteps(status),
250
+ ready_for: getReadySteps(status),
251
+ blocked_by: getBlockedSteps(status)
252
+ }
253
+
254
+ if (include_blocking_info) {
255
+ return {
256
+ ...fileInfo,
257
+ blocking_reasons: getBlockingReasons(status, stepKey),
258
+ can_proceed: fileInfo.ready_for.includes(stepKey)
259
+ }
260
+ }
261
+
262
+ return fileInfo
263
+ })
264
+
265
+ return {
266
+ content: [{
267
+ type: 'text',
268
+ text: JSON.stringify({
269
+ ok: true,
270
+ project_id,
271
+ step: stepKey,
272
+ step_name: PIPELINE_STEPS[stepKey].name,
273
+ prerequisites: PIPELINE_STEPS[stepKey].prerequisites,
274
+ target_status: PIPELINE_STEPS[stepKey].target_status,
275
+ file_count: files.length,
276
+ files
277
+ }, null, 2)
278
+ }],
279
+ }
280
+ }
281
+ )
282
+
283
+ server.registerTool(
284
+ 'spine_cil_update_file_pipeline_state',
285
+ {
286
+ description: 'Update pipeline state for a specific file, supporting incremental progress tracking.',
287
+ inputSchema: z.object({
288
+ project_id: z.string().uuid().describe('The cil_project UUID'),
289
+ file_path: z.string().describe('File path relative to repo root'),
290
+ step_completed: z.number().min(0).max(8).describe('Pipeline step that was just completed'),
291
+ new_status: z.string().describe('New pipeline status for the file'),
292
+ }),
293
+ },
294
+ async ({ project_id, file_path, step_completed, new_status }) => {
295
+
296
+ const { data: project } = await adminDb.from('items').select('data')
297
+ .eq('id', project_id).maybeSingle()
298
+
299
+ if (!project) {
300
+ return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `Project not found: ${project_id}` }) }] }
301
+ }
302
+
303
+ const fileStatuses = project.data?.file_statuses || {}
304
+ fileStatuses[file_path] = new_status
305
+
306
+ const { error } = await adminDb.from('items')
307
+ .update({
308
+ data: {
309
+ ...project.data,
310
+ file_statuses: fileStatuses,
311
+ last_ingested_at: new Date().toISOString()
312
+ }
313
+ })
314
+ .eq('id', project_id)
315
+
316
+ if (error) {
317
+ return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: error.message }) }] }
318
+ }
319
+
320
+ const updatedState = {
321
+ file_path,
322
+ previous_status: project.data?.file_statuses?.[file_path],
323
+ new_status,
324
+ step_completed,
325
+ completed_steps: getCompletedSteps(new_status),
326
+ ready_for: getReadySteps(new_status),
327
+ progress_percentage: calculateProgress(new_status)
328
+ }
329
+
330
+ return {
331
+ content: [{
332
+ type: 'text',
333
+ text: JSON.stringify({ ok: true, ...updatedState }, null, 2)
334
+ }],
335
+ }
336
+ }
337
+ )
338
+
339
+ server.registerTool(
340
+ 'spine_cil_get_pipeline_bottlenecks',
341
+ {
342
+ description: 'Analyze pipeline bottlenecks and suggest optimal processing order.',
343
+ inputSchema: z.object({
344
+ project_id: z.string().uuid().describe('The cil_project UUID'),
345
+ }),
346
+ },
347
+ async ({ project_id }) => {
348
+ const { data: project } = await adminDb.from('items').select('data')
349
+ .eq('id', project_id).maybeSingle()
350
+
351
+ if (!project) {
352
+ return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `Project not found: ${project_id}` }) }] }
353
+ }
354
+
355
+ const fileStatuses: Record<string, string> = project.data?.file_statuses || {}
356
+ const files = Object.entries(fileStatuses)
357
+
358
+ const bottlenecks = []
359
+ const recommendations = []
360
+
361
+ for (const step of Object.keys(PIPELINE_STEPS) as PipelineStep[]) {
362
+ const stepNum = step as unknown as number
363
+ const readyCount = files.filter(([_, status]) => {
364
+ const completedSteps = getCompletedSteps(status)
365
+ return PIPELINE_STEPS[step].prerequisites.every(prereq => completedSteps.includes(prereq))
366
+ }).length
367
+
368
+ const totalCount = files.length
369
+ const blockedCount = totalCount - readyCount
370
+
371
+ if (blockedCount > 0) {
372
+ bottlenecks.push({
373
+ step: stepNum,
374
+ step_name: PIPELINE_STEPS[step].name,
375
+ ready: readyCount,
376
+ blocked: blockedCount,
377
+ blocking_reasons: getStepBlockingReasons(files, step)
378
+ })
379
+
380
+ recommendations.push({
381
+ step: stepNum,
382
+ action: `Process ${blockedCount} files through prerequisite steps first`,
383
+ priority: step === 8 ? 'high' : 'medium'
384
+ })
385
+ }
386
+ }
387
+
388
+ const optimalOrder = getOptimalProcessingOrder(files)
389
+
390
+ return {
391
+ content: [{
392
+ type: 'text',
393
+ text: JSON.stringify({
394
+ project_id,
395
+ bottlenecks,
396
+ recommendations: recommendations.sort((a, b) => {
397
+ const priorityOrder = { high: 3, medium: 2, low: 1 }
398
+ return priorityOrder[b.priority as keyof typeof priorityOrder] - priorityOrder[a.priority as keyof typeof priorityOrder]
399
+ }),
400
+ optimal_processing_order: optimalOrder,
401
+ summary: {
402
+ total_files: files.length,
403
+ bottleneck_count: bottlenecks.length,
404
+ ready_for_processing: files.filter(([_, status]) =>
405
+ getCompletedSteps(status).length >= 3
406
+ ).length
407
+ }
408
+ }, null, 2)
409
+ }],
410
+ }
411
+ }
412
+ )
413
+ }
414
+ // CIL[DOC-VECTOR type="context" content="purpose='Registers all CIL pipeline MCP tools with a server instance'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
415
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
416
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
417
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
418
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
419
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
420
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:register:function"]
421
+
422
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:getCompletedSteps:function" type="function" identity="getCompletedSteps" parent="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
423
+ // CIL[DOC-MACRO purpose="Converts a pipeline status string into the set of completed step numbers"]
424
+ // CIL[DOC-RESPONSIBILITY responsibility="Determine which steps have already been completed for a file given its current status"]
425
+ // CIL[DOC-CONTEXT module="mcp" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
426
+ // CIL[DOC-CONTRACT inputs="status: string" outputs="number[] of completed step numbers" errors="Returns empty array for unknown status" side_effects="None"]
427
+ // CIL[DOC-MICRO logic_summary="Maps status string to rank, then collects all step numbers less than or equal to that rank" notable_decisions="[]"]
428
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
429
+ // CIL[DOC-STABILITY stability="stable"]
430
+
431
+ function getCompletedSteps(status: string): number[] {
432
+ const stepMap: Record<string, number> = {
433
+ '0-discovered': 0,
434
+ '1-selected': 1,
435
+ '2-chunked': 2,
436
+ '3-documented': 3,
437
+ '4-chunk-validated': 4,
438
+ '5-doc-validated': 5,
439
+ '6-enriched': 6,
440
+ '7-embedded-mapped': 7,
441
+ '8-published': 8,
442
+ }
443
+
444
+ const rank = stepMap[status]
445
+ if (rank === undefined) return []
446
+
447
+ const completed: number[] = []
448
+ for (const step of Object.keys(PIPELINE_STEPS) as PipelineStep[]) {
449
+ const stepNum = parseInt(step, 10)
450
+ if (stepNum <= rank) completed.push(stepNum)
451
+ }
452
+ return completed
453
+ }
454
+ // CIL[DOC-VECTOR type="context" content="purpose='Converts a pipeline status string into the set of completed step numbers'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
455
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
456
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
457
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
458
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
459
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
460
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:getCompletedSteps:function"]
461
+
462
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:getReadySteps:function" type="function" identity="getReadySteps" parent="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
463
+ // CIL[DOC-MACRO purpose="Identifies pipeline steps whose prerequisites are satisfied by a file's completed steps"]
464
+ // CIL[DOC-RESPONSIBILITY responsibility="Compute the next steps a file can immediately progress to"]
465
+ // CIL[DOC-CONTEXT module="mcp" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
466
+ // CIL[DOC-CONTRACT inputs="status: string" outputs="PipelineStep[] of ready step numbers" errors="None" side_effects="None"]
467
+ // CIL[DOC-MICRO logic_summary="Gathers completed steps, then iterates remaining steps and keeps those whose prerequisites are all present" notable_decisions="[]"]
468
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
469
+ // CIL[DOC-STABILITY stability="stable"]
470
+
471
+ /**
472
+ * Retrieves the steps that are ready to be executed based on the current status by checking completed prerequisites. This function helps in orchestrating the pipeline execution flow.
473
+ *
474
+ * @macro Function that identifies ready pipeline steps based on their prerequisites.
475
+ * @micro Iterates through defined pipeline steps and checks if their prerequisites are met by the completed steps.
476
+ * @inputSpec
477
+ * status: string (required) — the current status of the pipeline to determine completed steps.
478
+ * @outputSpec PipelineStep[] — an array of steps that are ready for execution.
479
+ * @sideEffects none
480
+ * @stability stable
481
+ * @calls getCompletedSteps
482
+ * @cil-generated
483
+ */
484
+ function getReadySteps(status: string): PipelineStep[] {
485
+ const completed = getCompletedSteps(status)
486
+ const ready: PipelineStep[] = []
487
+
488
+ for (const [stepNum, stepDef] of Object.entries(PIPELINE_STEPS)) {
489
+ const num = parseInt(stepNum, 10) as PipelineStep
490
+ if (completed.includes(num)) continue
491
+ if (stepDef.prerequisites.every(prereq => completed.includes(prereq))) {
492
+ ready.push(num)
493
+ }
494
+ }
495
+
496
+ return ready
497
+ }
498
+ // CIL[DOC-VECTOR type="context" content="purpose='Identifies pipeline steps whose prerequisites are satisfied by a file's completed steps'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
499
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
500
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
501
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
502
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
503
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
504
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:getReadySteps:function"]
505
+
506
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:getBlockedSteps:function" type="function" identity="getBlockedSteps" parent="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
507
+ // CIL[DOC-MACRO purpose="Identifies pipeline steps whose prerequisites are not yet satisfied"]
508
+ // CIL[DOC-RESPONSIBILITY responsibility="Compute which steps a file cannot yet proceed to"]
509
+ // CIL[DOC-CONTEXT module="mcp" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
510
+ // CIL[DOC-CONTRACT inputs="status: string" outputs="PipelineStep[] of blocked step numbers" errors="None" side_effects="None"]
511
+ // CIL[DOC-MICRO logic_summary="Collects completed steps, then returns every step whose prerequisites are not fully met" notable_decisions="[]"]
512
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
513
+ // CIL[DOC-STABILITY stability="stable"]
514
+
515
+ /**
516
+ * Identifies and returns the steps in a pipeline that are blocked due to unmet prerequisites. This function is essential for determining which steps cannot proceed based on the current status.
517
+ *
518
+ * @macro Function that evaluates pipeline steps based on their prerequisites.
519
+ * @micro Iterates through predefined pipeline steps, checking if all prerequisites are met against completed steps.
520
+ * @inputSpec
521
+ * status: string (required) — the current status of the pipeline to evaluate against.
522
+ * @outputSpec PipelineStep[] — an array of blocked pipeline step numbers.
523
+ * @sideEffects none
524
+ * @stability stable
525
+ * @calls getCompletedSteps
526
+ * @cil-generated
527
+ */
528
+ function getBlockedSteps(status: string): PipelineStep[] {
529
+ const completed = getCompletedSteps(status)
530
+ const blocked: PipelineStep[] = []
531
+
532
+ for (const [stepNum, stepDef] of Object.entries(PIPELINE_STEPS)) {
533
+ const num = parseInt(stepNum) as PipelineStep
534
+ if (!stepDef.prerequisites.every(prereq => completed.includes(prereq))) {
535
+ blocked.push(num)
536
+ }
537
+ }
538
+
539
+ return blocked
540
+ }
541
+ // CIL[DOC-VECTOR type="context" content="purpose='Identifies pipeline steps whose prerequisites are not yet satisfied'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
542
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
543
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
544
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
545
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
546
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
547
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:getBlockedSteps:function"]
548
+
549
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:calculateProgress:function" type="function" identity="calculateProgress" parent="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
550
+ // CIL[DOC-MACRO purpose="Calculates a percentage completion value for a given pipeline status"]
551
+ // CIL[DOC-RESPONSIBILITY responsibility="Convert a file's status into a 0-100 progress percentage"]
552
+ // CIL[DOC-CONTEXT module="mcp" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
553
+ // CIL[DOC-CONTRACT inputs="status: string" outputs="number percentage" errors="Returns 0 for unknown status" side_effects="None"]
554
+ // CIL[DOC-MICRO logic_summary="Counts completed steps and divides by total steps, multiplying by 100" notable_decisions="[]"]
555
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
556
+ // CIL[DOC-STABILITY stability="stable"]
557
+
558
+ /**
559
+ * Calculates the progress of a pipeline based on the number of completed steps relative to the total steps. This function is essential for tracking the advancement of tasks within the pipeline.
560
+ *
561
+ * @inputSpec
562
+ * status: string (required) — the current status of the pipeline to determine completed steps.
563
+ * @outputSpec number — a percentage representing the progress of the pipeline.
564
+ * @sideEffects none
565
+ * @stability stable
566
+ * @calls getCompletedSteps
567
+ * @cil-generated
568
+ */
569
+ function calculateProgress(status: string): number {
570
+ const completed = getCompletedSteps(status)
571
+ const totalSteps = Object.keys(PIPELINE_STEPS).length
572
+ return (completed.length / totalSteps) * 100
573
+ }
574
+ // CIL[DOC-VECTOR type="context" content="purpose='Calculates a percentage completion value for a given pipeline status'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
575
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
576
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
577
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
578
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
579
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
580
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:calculateProgress:function"]
581
+
582
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:getBlockingReasons:function" type="function" identity="getBlockingReasons" parent="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
583
+ // CIL[DOC-MACRO purpose="Generates human-readable reasons for a specific step being blocked"]
584
+ // CIL[DOC-RESPONSIBILITY responsibility="List missing prerequisite steps that prevent a file from starting a given pipeline step"]
585
+ // CIL[DOC-CONTEXT module="mcp" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
586
+ // CIL[DOC-CONTRACT inputs="status: string, step: PipelineStep" outputs="string[] of missing prerequisite messages" errors="None" side_effects="None"]
587
+ // CIL[DOC-MICRO logic_summary="Checks each prerequisite of the target step against completed steps and returns messages for those not yet completed" notable_decisions="[]"]
588
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
589
+ // CIL[DOC-STABILITY stability="stable"]
590
+
591
+ /**
592
+ * The function retrieves the reasons why a specific pipeline step is blocked based on its prerequisites. It checks the completed steps against the required prerequisites and generates a list of missing steps.
593
+ *
594
+ * @inputSpec
595
+ * status: string (required) — the current status of the pipeline.
596
+ * step: PipelineStep (required) — the specific step in the pipeline to check prerequisites for.
597
+ * @outputSpec string[] — an array of strings detailing the missing prerequisite steps.
598
+ * @sideEffects none
599
+ * @stability stable
600
+ * @calls getCompletedSteps
601
+ * @cil-generated
602
+ */
603
+ function getBlockingReasons(status: string, step: PipelineStep): string[] {
604
+ const completed = getCompletedSteps(status)
605
+ const reasons: string[] = []
606
+
607
+ for (const prereq of PIPELINE_STEPS[step].prerequisites) {
608
+ if (!completed.includes(prereq)) {
609
+ reasons.push(`Missing prerequisite step ${prereq} (${PIPELINE_STEPS[prereq].name})`)
610
+ }
611
+ }
612
+
613
+ return reasons
614
+ }
615
+ // CIL[DOC-VECTOR type="context" content="purpose='Generates human-readable reasons for a specific step being blocked'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
616
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
617
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
618
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
619
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
620
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
621
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:getBlockingReasons:function"]
622
+
623
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:getStepBlockingReasons:function" type="function" identity="getStepBlockingReasons" parent="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
624
+ // CIL[DOC-MACRO purpose="Aggregates per-file blocking reasons for a specific pipeline step"]
625
+ // CIL[DOC-RESPONSIBILITY responsibility="Collect file-level messages indicating which prerequisites are missing for a given step"]
626
+ // CIL[DOC-CONTEXT module="mcp" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
627
+ // CIL[DOC-CONTRACT inputs="files: Array<[string, string]>, step: PipelineStep" outputs="string[] of unique blocking reasons" errors="None" side_effects="None"]
628
+ // CIL[DOC-MICRO logic_summary="Iterates project files, checks step prerequisites, and gathers unique missing-prerequisite messages" notable_decisions="[]"]
629
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
630
+ // CIL[DOC-STABILITY stability="stable"]
631
+
632
+ function getStepBlockingReasons(files: Array<[string, string]>, step: PipelineStep): string[] {
633
+ const blockingReasons: string[] = []
634
+
635
+ for (const [file_path, status] of files) {
636
+ const completed = getCompletedSteps(status)
637
+ if (!PIPELINE_STEPS[step].prerequisites.every(prereq => completed.includes(prereq))) {
638
+ for (const prereq of PIPELINE_STEPS[step].prerequisites) {
639
+ if (!completed.includes(prereq)) {
640
+ blockingReasons.push(`${file_path}: missing step ${prereq}`)
641
+ }
642
+ }
643
+ }
644
+ }
645
+
646
+ return [...new Set(blockingReasons)]
647
+ }
648
+ // CIL[DOC-VECTOR type="context" content="purpose='Aggregates per-file blocking reasons for a specific pipeline step'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
649
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
650
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
651
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
652
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
653
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
654
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:getStepBlockingReasons:function"]
655
+
656
+ // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:getOptimalProcessingOrder:function" type="function" identity="getOptimalProcessingOrder" parent="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
657
+ // CIL[DOC-MACRO purpose="Sorts project files by processing priority for the bottleneck tool"]
658
+ // CIL[DOC-RESPONSIBILITY responsibility="Produce a prioritized list of files and their next suggested step"]
659
+ // CIL[DOC-CONTEXT module="mcp" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/pipeline-orchestrator.ts"]
660
+ // CIL[DOC-CONTRACT inputs="files: Array<[string, string]>" outputs="Array of {file_path, suggested_next_step} in priority order" errors="None" side_effects="None"]
661
+ // CIL[DOC-MICRO logic_summary="Computes completed and ready steps for each file, sorts by most ready then least completed, and picks the first ready step" notable_decisions="[]"]
662
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
663
+ // CIL[DOC-STABILITY stability="stable"]
664
+
665
+ function getOptimalProcessingOrder(files: Array<[string, string]>): Array<{file_path: string, suggested_next_step: PipelineStep}> {
666
+ const fileStates = files.map(([file_path, status]) => ({
667
+ file_path,
668
+ status,
669
+ completed_steps: getCompletedSteps(status),
670
+ ready_for: getReadySteps(status)
671
+ }))
672
+
673
+ return fileStates
674
+ .sort((a, b) => {
675
+
676
+ if (a.ready_for.length !== b.ready_for.length) {
677
+ return b.ready_for.length - a.ready_for.length
678
+ }
679
+
680
+ return a.completed_steps.length - b.completed_steps.length
681
+ })
682
+ .map(({ file_path, ready_for }) => ({
683
+ file_path,
684
+ suggested_next_step: ready_for[0] || null
685
+ }))
686
+ }
687
+ // CIL[DOC-VECTOR type="context" content="purpose='Sorts project files by processing priority for the bottleneck tool'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
688
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
689
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
690
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
691
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
692
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
693
+ // CIL[END stable_id="~/.framework/mcp/tools/cil/pipeline-orchestrator.ts:getOptimalProcessingOrder:function"]