spine-framework 0.4.3 → 0.5.0-rc.4

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 (320) hide show
  1. package/.env.example +13 -3
  2. package/.framework/cli/commands/bootstrap.ts +392 -0
  3. package/.framework/cli/commands/dev.ts +91 -218
  4. package/.framework/cli/commands/doctor.ts +132 -26
  5. package/.framework/cli/commands/generate.ts +38 -298
  6. package/.framework/cli/commands/init.ts +20 -1
  7. package/.framework/cli/commands/migrate.ts +36 -30
  8. package/.framework/cli/commands/migrations.ts +16 -56
  9. package/.framework/cli/commands/upgrade.ts +35 -0
  10. package/.framework/cli/commands/validate-schema.ts +147 -0
  11. package/.framework/cli/context.ts +223 -110
  12. package/.framework/cli/index.ts +6 -0
  13. package/.framework/cli/lib/project-files.ts +241 -1
  14. package/.framework/functions/_shared/agent-runner.ts +1000 -81
  15. package/.framework/functions/_shared/cil.ts +2 -1
  16. package/.framework/functions/_shared/db.ts +3 -6
  17. package/.framework/functions/_shared/hash-api-key.ts +183 -79
  18. package/.framework/functions/_shared/kb.ts +61 -7
  19. package/.framework/functions/_shared/logging.ts +562 -224
  20. package/.framework/functions/_shared/message-sequence.ts +53 -0
  21. package/.framework/functions/_shared/middleware.ts +47 -44
  22. package/.framework/functions/_shared/pipeline-runner.ts +150 -37
  23. package/.framework/functions/_shared/principal.ts +9 -6
  24. package/.framework/functions/_shared/trigger-engine.ts +149 -40
  25. package/.framework/functions/admin-data.ts +48 -31
  26. package/.framework/functions/ai-agents.ts +103 -33
  27. package/.framework/functions/api-keys.ts +301 -122
  28. package/.framework/functions/apps.ts +43 -26
  29. package/.framework/functions/cil-ingest.ts +48 -15
  30. package/.framework/functions/debug-auth.ts +14 -8
  31. package/.framework/functions/deliveries.ts +39 -12
  32. package/.framework/functions/embeddings.ts +145 -76
  33. package/.framework/functions/integration-outbound.ts +67 -27
  34. package/.framework/functions/integrations.ts +254 -127
  35. package/.framework/functions/logs.ts +273 -133
  36. package/.framework/functions/observability.ts +277 -147
  37. package/.framework/functions/pipeline-executions.ts +1 -1
  38. package/.framework/functions/pipeline-runner-background.ts +120 -0
  39. package/.framework/functions/pipelines.ts +14 -9
  40. package/.framework/functions/prompt-configs.ts +7 -4
  41. package/.framework/functions/roles.ts +8 -5
  42. package/.framework/functions/security.ts +30 -17
  43. package/.framework/functions/system-cron.ts +250 -128
  44. package/.framework/functions/tests.ts +7 -6
  45. package/.framework/functions/timers.ts +310 -107
  46. package/.framework/functions/trigger-scheduler.ts +65 -5
  47. package/.framework/functions/triggers.ts +28 -13
  48. package/.framework/functions/types.ts +13 -10
  49. package/.framework/migrations/064_episode_leases.sql +196 -0
  50. package/.framework/migrations/065_execution_tables_updated_at.sql +20 -0
  51. package/.framework/migrations/066_episode_steal_thread_merge.sql +148 -0
  52. package/.framework/migrations/067_episode_lease_stale_steal.sql +93 -0
  53. package/.framework/migrations/068_cron_schedule_timer_rpcs.sql +251 -0
  54. package/.framework/migrations/069_log_stats_window.sql +54 -0
  55. package/.framework/migrations/070_app_type_schema_rpcs.sql +166 -0
  56. package/.framework/migrations/071_timer_interval_keys.sql +96 -0
  57. package/.framework/migrations/072_slug_autofill.sql +77 -0
  58. package/.framework/migrations/073_seed_member_roles.sql +26 -0
  59. package/.framework/schemas/spine.config.schema.json +62 -0
  60. package/.framework/src/App.tsx +3 -1
  61. package/.framework/src/apps/admin/index.tsx +1141 -775
  62. package/.framework/src/components/ErrorBoundary.tsx +136 -0
  63. package/.framework/src/components/admin/AdminListPage.tsx +81 -73
  64. package/.framework/src/components/admin/AdminSidebar.tsx +92 -81
  65. package/.framework/src/components/admin/EntitySelect.tsx +181 -0
  66. package/.framework/src/components/admin/PageInstructions.tsx +86 -127
  67. package/.framework/src/components/app-shell/GenericAppShell.tsx +3 -1
  68. package/.framework/src/components/app-shell/GenericDetailPage.tsx +37 -13
  69. package/.framework/src/components/app-shell/GenericListPage.tsx +28 -32
  70. package/.framework/src/components/auth/TurnstileWidget.tsx +9 -6
  71. package/.framework/src/components/kb/KBArticleEditor.tsx +49 -6
  72. package/.framework/src/components/layout/Layout.tsx +4 -2
  73. package/.framework/src/components/layout/Sidebar.tsx +304 -179
  74. package/.framework/src/components/runtime/DataDetailPage.tsx +67 -35
  75. package/.framework/src/components/runtime/DataHeader.tsx +96 -48
  76. package/.framework/src/components/runtime/DataListPage.tsx +3 -26
  77. package/.framework/src/components/runtime/DataStats.tsx +10 -10
  78. package/.framework/src/components/runtime/DataTable.tsx +12 -10
  79. package/.framework/src/components/ui/sheet.tsx +24 -26
  80. package/.framework/src/components/ui/textarea.tsx +74 -48
  81. package/.framework/src/hooks/useBranding.ts +47 -0
  82. package/.framework/src/hooks/useEntityList.ts +12 -9
  83. package/.framework/src/hooks/useListSchema.ts +108 -58
  84. package/.framework/src/instructions/README.md +57 -0
  85. package/.framework/src/instructions/ai-agents.md +69 -0
  86. package/.framework/src/instructions/alerts.md +80 -0
  87. package/.framework/src/instructions/api-keys.md +87 -0
  88. package/.framework/src/instructions/apps.md +77 -0
  89. package/.framework/src/instructions/concepts/ai-and-prompts.md +150 -0
  90. package/.framework/src/instructions/concepts/apps-and-renderers.md +162 -0
  91. package/.framework/src/instructions/concepts/auth-and-api-keys.md +133 -0
  92. package/.framework/src/instructions/concepts/automation.md +186 -0
  93. package/.framework/src/instructions/concepts/concurrency-and-idempotency.md +125 -0
  94. package/.framework/src/instructions/concepts/core-vs-custom.md +124 -0
  95. package/.framework/src/instructions/concepts/design-schema.md +152 -0
  96. package/.framework/src/instructions/concepts/integrations-and-webhooks.md +127 -0
  97. package/.framework/src/instructions/concepts/observability.md +116 -0
  98. package/.framework/src/instructions/concepts/permissions.md +150 -0
  99. package/.framework/src/instructions/concepts/runtime-records.md +111 -0
  100. package/.framework/src/instructions/concepts/scope-and-accounts.md +112 -0
  101. package/.framework/src/instructions/concepts/spine-way.md +172 -0
  102. package/.framework/src/instructions/deliveries.md +59 -0
  103. package/.framework/src/instructions/guide/00-orientation.md +106 -0
  104. package/.framework/src/instructions/guide/01-install-and-first-run.md +253 -0
  105. package/.framework/src/instructions/guide/02-project-map.md +147 -0
  106. package/.framework/src/instructions/guide/03-domain-model.md +223 -0
  107. package/.framework/src/instructions/guide/04-first-app.md +227 -0
  108. package/.framework/src/instructions/guide/05-glossary.md +183 -0
  109. package/.framework/src/instructions/integrations.md +96 -0
  110. package/.framework/src/instructions/internal/cil-markers.md +83 -0
  111. package/.framework/src/instructions/invites.md +60 -0
  112. package/.framework/src/instructions/kb.md +80 -0
  113. package/.framework/src/instructions/logs.md +77 -0
  114. package/.framework/src/instructions/observability.md +61 -0
  115. package/.framework/src/instructions/operations/deployment.md +115 -0
  116. package/.framework/src/instructions/operations/migrations.md +125 -0
  117. package/.framework/src/instructions/operations/security-checklist.md +148 -0
  118. package/.framework/src/instructions/operations/troubleshooting.md +170 -0
  119. package/.framework/src/instructions/operations/upgrade.md +116 -0
  120. package/.framework/src/instructions/pipeline-executions.md +62 -0
  121. package/.framework/src/instructions/pipelines.md +78 -0
  122. package/.framework/src/instructions/prompts.md +95 -0
  123. package/.framework/src/instructions/reference/api/admin-data.md +162 -0
  124. package/.framework/src/instructions/reference/api/auth.md +113 -0
  125. package/.framework/src/instructions/reference/api/errors-and-envelopes.md +113 -0
  126. package/.framework/src/instructions/reference/app-manifest.md +150 -0
  127. package/.framework/src/instructions/reference/cli.md +124 -0
  128. package/.framework/src/instructions/reference/database.md +132 -0
  129. package/.framework/src/instructions/reference/design-schema.md +280 -0
  130. package/.framework/src/instructions/reference/env-vars.md +133 -0
  131. package/.framework/src/instructions/reference/functions/account-nodes.md +75 -0
  132. package/.framework/src/instructions/reference/functions/admin-data.md +195 -0
  133. package/.framework/src/instructions/reference/functions/admin-funnel.md +90 -0
  134. package/.framework/src/instructions/reference/functions/admin-install-funnel.md +107 -0
  135. package/.framework/src/instructions/reference/functions/admin-signals.md +102 -0
  136. package/.framework/src/instructions/reference/functions/ai-agents.md +148 -0
  137. package/.framework/src/instructions/reference/functions/ai-interactions.md +156 -0
  138. package/.framework/src/instructions/reference/functions/api-keys.md +130 -0
  139. package/.framework/src/instructions/reference/functions/apps.md +140 -0
  140. package/.framework/src/instructions/reference/functions/auth.md +99 -0
  141. package/.framework/src/instructions/reference/functions/debug-auth.md +91 -0
  142. package/.framework/src/instructions/reference/functions/deliveries.md +110 -0
  143. package/.framework/src/instructions/reference/functions/embeddings.md +166 -0
  144. package/.framework/src/instructions/reference/functions/eval-harness.md +149 -0
  145. package/.framework/src/instructions/reference/functions/index.md +103 -0
  146. package/.framework/src/instructions/reference/functions/integration-outbound.md +200 -0
  147. package/.framework/src/instructions/reference/functions/integration-routes.md +151 -0
  148. package/.framework/src/instructions/reference/functions/integrations.md +130 -0
  149. package/.framework/src/instructions/reference/functions/invites.md +182 -0
  150. package/.framework/src/instructions/reference/functions/item-progress.md +107 -0
  151. package/.framework/src/instructions/reference/functions/kb.md +166 -0
  152. package/.framework/src/instructions/reference/functions/logs.md +141 -0
  153. package/.framework/src/instructions/reference/functions/observability.md +105 -0
  154. package/.framework/src/instructions/reference/functions/pipeline-executions.md +132 -0
  155. package/.framework/src/instructions/reference/functions/pipeline-runner-background.md +121 -0
  156. package/.framework/src/instructions/reference/functions/pipelines.md +136 -0
  157. package/.framework/src/instructions/reference/functions/prompt-configs.md +121 -0
  158. package/.framework/src/instructions/reference/functions/roles.md +121 -0
  159. package/.framework/src/instructions/reference/functions/security.md +140 -0
  160. package/.framework/src/instructions/reference/functions/system-cron.md +136 -0
  161. package/.framework/src/instructions/reference/functions/system.md +106 -0
  162. package/.framework/src/instructions/reference/functions/tests.md +97 -0
  163. package/.framework/src/instructions/reference/functions/timers.md +117 -0
  164. package/.framework/src/instructions/reference/functions/trigger-scheduler.md +102 -0
  165. package/.framework/src/instructions/reference/functions/triggers.md +140 -0
  166. package/.framework/src/instructions/reference/functions/types.md +146 -0
  167. package/.framework/src/instructions/reference/seeds.md +126 -0
  168. package/.framework/src/instructions/reference/shared-modules.md +127 -0
  169. package/.framework/src/instructions/reference/spine-config.md +114 -0
  170. package/.framework/src/instructions/roles.md +80 -0
  171. package/.framework/src/instructions/runtime-detail.md +70 -0
  172. package/.framework/src/instructions/runtime-list.md +77 -0
  173. package/.framework/src/instructions/security.md +67 -0
  174. package/.framework/src/instructions/tasks/add-a-pipeline.md +110 -0
  175. package/.framework/src/instructions/tasks/add-a-role.md +96 -0
  176. package/.framework/src/instructions/tasks/add-a-timer.md +114 -0
  177. package/.framework/src/instructions/tasks/add-a-trigger.md +106 -0
  178. package/.framework/src/instructions/tasks/add-a-type.md +151 -0
  179. package/.framework/src/instructions/tasks/add-a-webhook.md +108 -0
  180. package/.framework/src/instructions/tasks/add-an-ai-agent.md +108 -0
  181. package/.framework/src/instructions/tasks/add-an-integration.md +124 -0
  182. package/.framework/src/instructions/tasks/build-a-custom-page.md +118 -0
  183. package/.framework/src/instructions/tasks/package-and-install-an-app.md +127 -0
  184. package/.framework/src/instructions/tasks/test-your-code.md +108 -0
  185. package/.framework/src/instructions/tasks/write-a-function.md +132 -0
  186. package/.framework/src/instructions/tasks/write-a-migration.md +110 -0
  187. package/.framework/src/instructions/testing.md +59 -0
  188. package/.framework/src/instructions/timers.md +82 -0
  189. package/.framework/src/instructions/triggers.md +69 -0
  190. package/.framework/src/instructions/types.md +93 -0
  191. package/.framework/src/lib/branding.ts +128 -0
  192. package/.framework/src/pages/NoAppPage.tsx +3 -1
  193. package/.framework/src/pages/NotFoundPage.tsx +62 -31
  194. package/.framework/src/pages/SetupPage.tsx +5 -2
  195. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +117 -106
  196. package/.framework/src/pages/admin/AIAgentsPage.tsx +86 -48
  197. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +153 -152
  198. package/.framework/src/pages/admin/APIKeysPage.tsx +91 -90
  199. package/.framework/src/pages/admin/AlertsConfigPage.tsx +29 -18
  200. package/.framework/src/pages/admin/AppDetailPage.tsx +6 -60
  201. package/.framework/src/pages/admin/AppsPage.tsx +104 -66
  202. package/.framework/src/pages/admin/DeliveriesPage.tsx +5 -5
  203. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +5 -23
  204. package/.framework/src/pages/admin/EmbeddingsPage.tsx +5 -26
  205. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +7 -7
  206. package/.framework/src/pages/admin/IntegrationsPage.tsx +85 -43
  207. package/.framework/src/pages/admin/LogsPage.tsx +144 -76
  208. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +223 -140
  209. package/.framework/src/pages/admin/PipelineDetailPage.tsx +134 -113
  210. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +108 -45
  211. package/.framework/src/pages/admin/PipelinesPage.tsx +160 -115
  212. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +96 -98
  213. package/.framework/src/pages/admin/PromptConfigsPage.tsx +101 -59
  214. package/.framework/src/pages/admin/RoleDetailPage.tsx +90 -79
  215. package/.framework/src/pages/admin/RolesPage.tsx +86 -43
  216. package/.framework/src/pages/admin/SecurityPage.tsx +1 -1
  217. package/.framework/src/pages/admin/TestingDashboard.tsx +16 -28
  218. package/.framework/src/pages/admin/TimerDetailPage.tsx +117 -100
  219. package/.framework/src/pages/admin/TimersPage.tsx +90 -62
  220. package/.framework/src/pages/admin/TriggerDetailPage.tsx +90 -83
  221. package/.framework/src/pages/admin/TriggersPage.tsx +124 -99
  222. package/.framework/src/pages/admin/TypeDetailPage.tsx +152 -138
  223. package/.framework/src/pages/admin/TypesPage.tsx +90 -48
  224. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +17 -25
  225. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +17 -27
  226. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +72 -40
  227. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +321 -129
  228. package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +18 -29
  229. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +26 -38
  230. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +34 -46
  231. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +189 -103
  232. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +246 -136
  233. package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +11 -22
  234. package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +9 -20
  235. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +26 -38
  236. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +7 -26
  237. package/.framework/src/pages/auth/AuthConfirmPage.tsx +3 -1
  238. package/.framework/src/pages/auth/ForgotPasswordPage.tsx +3 -1
  239. package/.framework/src/pages/auth/LoginPage.tsx +4 -2
  240. package/.framework/src/pages/auth/RegisterPage.tsx +3 -1
  241. package/.framework/templates/agent/AGENTS.md +150 -0
  242. package/.framework/templates/agent/skills/spine-add-ai-agent/SKILL.md +58 -0
  243. package/.framework/templates/agent/skills/spine-add-automation/SKILL.md +62 -0
  244. package/.framework/templates/agent/skills/spine-add-integration/SKILL.md +63 -0
  245. package/.framework/templates/agent/skills/spine-architect/SKILL.md +86 -0
  246. package/.framework/templates/agent/skills/spine-install-app/SKILL.md +72 -0
  247. package/.framework/templates/agent/skills/spine-migration/SKILL.md +75 -0
  248. package/.framework/templates/agent/skills/spine-new-app/SKILL.md +67 -0
  249. package/.framework/templates/agent/skills/spine-new-function/SKILL.md +65 -0
  250. package/.framework/templates/agent/skills/spine-new-type/SKILL.md +65 -0
  251. package/.framework/templates/agent/skills/spine-schema/SKILL.md +77 -0
  252. package/.framework/templates/agent/skills/spine-test/SKILL.md +67 -0
  253. package/.framework/templates/agent/skills/spine-troubleshoot/SKILL.md +74 -0
  254. package/.framework/templates/agent/skills/spine-upgrade/SKILL.md +69 -0
  255. package/.framework/templates/project.json +5 -1
  256. package/.framework/tests/unit/account-scoping-gates.test.ts +392 -0
  257. package/.framework/tests/unit/agent-files.test.ts +355 -0
  258. package/.framework/tests/unit/agent-runner.test.ts +496 -47
  259. package/.framework/tests/unit/api-keys-create-scope-gate.test.ts +160 -0
  260. package/.framework/tests/unit/api-keys-omit-secret-fields.test.ts +38 -0
  261. package/.framework/tests/unit/bootstrap.test.ts +242 -0
  262. package/.framework/tests/unit/cli-context-api-key.test.ts +114 -0
  263. package/.framework/tests/unit/debug-auth.test.ts +38 -0
  264. package/.framework/tests/unit/deliveries-account-scoping.test.ts +185 -0
  265. package/.framework/tests/unit/episode-lease.test.ts +695 -0
  266. package/.framework/tests/unit/integration-outbound-credentials.test.ts +167 -0
  267. package/.framework/tests/unit/integrations-audit-redaction.test.ts +130 -0
  268. package/.framework/tests/unit/kb-ingest-lease.test.ts +19 -0
  269. package/.framework/tests/unit/logging-app-id.test.ts +75 -0
  270. package/.framework/tests/unit/pipeline-runner-background.test.ts +120 -0
  271. package/.framework/tests/unit/pipeline-runner.test.ts +153 -1
  272. package/.framework/tests/unit/principal-cache.test.ts +15 -0
  273. package/.framework/tests/unit/system-context-denial.test.ts +145 -0
  274. package/.framework/tests/unit/system-cron.test.ts +240 -0
  275. package/.framework/tests/unit/timers.test.ts +159 -0
  276. package/.framework/tests/unit/trigger-engine.test.ts +278 -91
  277. package/.framework/tests/unit/trigger-scheduler.test.ts +78 -0
  278. package/README.md +125 -166
  279. package/config/tsconfig.cli.json +2 -2
  280. package/netlify.toml +5 -0
  281. package/package.json +15 -4
  282. package/templates/project/package-lock.json +2 -2
  283. package/.framework/docs/admin-routes.md +0 -76
  284. package/.framework/docs/api-docs-progress.md +0 -38
  285. package/.framework/docs/api-governance.md +0 -146
  286. package/.framework/docs/api-testing-results.md +0 -212
  287. package/.framework/docs/assembly-launch-guide.md +0 -138
  288. package/.framework/docs/audit-results.md +0 -590
  289. package/.framework/docs/db-api-inventory.md +0 -95
  290. package/.framework/docs/gap-remediation-backlog.md +0 -103
  291. package/.framework/docs/ui-adoption-verification.md +0 -111
  292. package/.framework/docs/ui-api-coverage.md +0 -84
  293. package/.framework/docs/v2-compatibility-audit.md +0 -228
  294. package/.framework/mcp/index.ts +0 -133
  295. package/.framework/mcp/load-env.ts +0 -60
  296. package/.framework/mcp/shared/app-manifest.ts +0 -275
  297. package/.framework/mcp/shared/db.ts +0 -477
  298. package/.framework/mcp/shared/kb.ts +0 -118
  299. package/.framework/mcp/tools/architect.ts +0 -431
  300. package/.framework/mcp/tools/cil/context.ts +0 -345
  301. package/.framework/mcp/tools/cil/graph.ts +0 -242
  302. package/.framework/mcp/tools/cil/ingest.ts +0 -1217
  303. package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +0 -693
  304. package/.framework/mcp/tools/cil/pipeline.ts +0 -767
  305. package/.framework/mcp/tools/cil/project.ts +0 -791
  306. package/.framework/mcp/tools/cil/retrieval.ts +0 -336
  307. package/.framework/mcp/tools/cil/search-core.ts +0 -454
  308. package/.framework/mcp/tools/cil/search.ts +0 -97
  309. package/.framework/mcp/tools/cil/suggest.ts +0 -186
  310. package/.framework/mcp/tools/cil/validate.ts +0 -1369
  311. package/.framework/mcp/tools/kb/delete.ts +0 -139
  312. package/.framework/mcp/tools/kb/index.ts +0 -52
  313. package/.framework/mcp/tools/kb/ingest.ts +0 -84
  314. package/.framework/mcp/tools/kb/list-types.ts +0 -102
  315. package/.framework/mcp/tools/kb/publish.ts +0 -100
  316. package/.framework/mcp/tools/kb/reindex.ts +0 -86
  317. package/.framework/mcp/tools/kb/revoke.ts +0 -85
  318. package/.framework/mcp/tools/kb/search.ts +0 -101
  319. package/.framework/mcp/tools/kb/upsert.ts +0 -125
  320. package/.framework/mcp/tools/observability.ts +0 -510
@@ -1,345 +0,0 @@
1
- // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/context.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/mcp/tools/cil/context.ts"]
2
- // CIL[DOC-MACRO purpose="MCP tool module that exposes CIL context and post-edit helpers for named chunks"]
3
- // CIL[DOC-RESPONSIBILITY responsibility="Register MCP tools providing pre-edit context briefs and post-edit next steps"]
4
- // CIL[DOC-CONTEXT module="mcp-cil-context" layer="tools" related_files=".framework/mcp/shared/db.ts"]
5
- // CIL[DOC-CONTRACT inputs="McpServer instance" outputs="registered tools" errors="none" side_effects="registers three tools on the server"]
6
- // CIL[DOC-MICRO logic_summary="Imports SDK, zod, and shared DB helpers; no runtime logic" notable_decisions="[]"]
7
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
- // CIL[DOC-STABILITY stability="stable"]
9
- // CIL[DOC-AUDIENCE audience="internal"]
10
-
11
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
12
- import { z } from 'zod'
13
- import { adminDb, resolveLinkTypeId } from '../../shared/db.js'
14
- // CIL[DOC-VECTOR type="context" content="purpose='MCP tool module that exposes CIL context and post-edit helpers for named chunks'; 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/context.ts:module_header:module_header"]
21
-
22
- // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/context.ts:getChunkById:function" type="function" identity="getChunkById" parent="~/.framework/mcp/tools/cil/context.ts"]
23
- // CIL[DOC-MACRO purpose="Fetch a CIL chunk row by its primary id"]
24
- // CIL[DOC-RESPONSIBILITY responsibility="Return raw chunk data for a given id"]
25
- // CIL[DOC-CONTEXT module="mcp-cil-context" layer="data-access" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/context.ts"]
26
- // CIL[DOC-CONTRACT inputs="id: string" outputs="chunk data or undefined" errors="none" side_effects="queries adminDb"]
27
- // CIL[DOC-MICRO logic_summary="Selects from items table by id" notable_decisions="[]"]
28
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
29
- // CIL[DOC-STABILITY stability="stable"]
30
- async function getChunkById(id: string) {
31
- const { data } = await adminDb.from('items').select('id, title, data')
32
- .eq('id', id).maybeSingle()
33
- return data
34
- }
35
- // CIL[DOC-VECTOR type="context" content="purpose='Fetch a CIL chunk row by its primary id'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
36
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
37
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
38
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
39
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
40
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
41
- // CIL[END stable_id="~/.framework/mcp/tools/cil/context.ts:getChunkById:function"]
42
-
43
- // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/context.ts:getChunkByStableId:function" type="function" identity="getChunkByStableId" parent="~/.framework/mcp/tools/cil/context.ts"]
44
- // CIL[DOC-MACRO purpose="Fetch an active CIL chunk by project and stable id"]
45
- // CIL[DOC-RESPONSIBILITY responsibility="Return the matching chunk or undefined"]
46
- // CIL[DOC-CONTEXT module="mcp-cil-context" layer="data-access" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/context.ts"]
47
- // CIL[DOC-CONTRACT inputs="projectId: string, stableId: string, versionId?: string" outputs="chunk data" errors="none" side_effects="queries adminDb with filters"]
48
- // CIL[DOC-MICRO logic_summary="Builds a filtered Supabase query and returns maybeSingle result" notable_decisions="[]"]
49
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
50
- // CIL[DOC-STABILITY stability="stable"]
51
- async function getChunkByStableId(projectId: string, stableId: string, versionId?: string) {
52
- let q = adminDb.from('items').select('id, title, data')
53
- .filter('data->>kb_type', 'eq', 'cil_chunk')
54
- .filter('data->>project_id', 'eq', projectId)
55
- .filter('data->>stable_id', 'eq', stableId)
56
- .eq('is_active', true)
57
- if (versionId) q = (q as any).filter('data->>version_id', 'eq', versionId)
58
- const { data } = await (q as any).maybeSingle()
59
- return data
60
- }
61
- // CIL[DOC-VECTOR type="context" content="purpose='Fetch an active CIL chunk by project and stable id'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
62
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
63
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
64
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
65
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
66
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
67
- // CIL[END stable_id="~/.framework/mcp/tools/cil/context.ts:getChunkByStableId:function"]
68
-
69
- // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/context.ts:findChunkByName:function" type="function" identity="findChunkByName" parent="~/.framework/mcp/tools/cil/context.ts"]
70
- // CIL[DOC-MACRO purpose="Find an active CIL chunk by chunk name"]
71
- // CIL[DOC-RESPONSIBILITY responsibility="Return the first matching chunk by name"]
72
- // CIL[DOC-STABILITY stability="internal"]
73
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
74
- // CIL[DOC-CONTEXT module="mcp-cil-context" layer="data-access" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/context.ts"]
75
- // CIL[DOC-CONTRACT inputs="name: string, projectId?: string" outputs="chunk data" errors="none" side_effects="queries adminDb"]
76
- // CIL[DOC-MICRO logic_summary="Filters by chunk_name and optional project, returns first result" notable_decisions="[]"]
77
- async function findChunkByName(name: string, projectId?: string) {
78
- let q = adminDb.from('items').select('id, title, data')
79
- .filter('data->>kb_type', 'eq', 'cil_chunk')
80
- .filter('data->>chunk_name', 'eq', name)
81
- .eq('is_active', true)
82
- if (projectId) q = (q as any).filter('data->>project_id', 'eq', projectId)
83
- const { data } = await (q as any).limit(1).maybeSingle()
84
- return data
85
- }
86
- // CIL[END stable_id="~/.framework/mcp/tools/cil/context.ts:findChunkByName:function"]
87
-
88
- // CIL[DOC-VECTOR type="context" content="purpose='Find an active CIL chunk by chunk name'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
89
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
90
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
91
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
92
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
93
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
94
- // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/context.ts:blastRadiusBFS:function" type="function" identity="blastRadiusBFS" parent="~/.framework/mcp/tools/cil/context.ts"]
95
- // CIL[DOC-MACRO purpose="Compute transitive callers of a chunk up to a max depth"]
96
- // CIL[DOC-RESPONSIBILITY responsibility="Return a list of caller chunks with depth metadata"]
97
- // CIL[DOC-CONTEXT module="mcp-cil-context" layer="analysis" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/context.ts"]
98
- // CIL[DOC-CONTRACT inputs="chunkId, maxDepth, callsLinkTypeId" outputs="caller records" errors="none" side_effects="queries links and items tables"]
99
- // CIL[DOC-MICRO logic_summary="Breadth-first search over cil_calls links in reverse direction" notable_decisions="[]"]
100
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
101
- // CIL[DOC-STABILITY stability="stable"]
102
- async function blastRadiusBFS(
103
- chunkId: string, maxDepth: number, callsLinkTypeId: string
104
- ): Promise<{ chunk_id: string; chunk_name: string; file_path: string; depth: number }[]> {
105
- const visited = new Set([chunkId])
106
- const queue: { id: string; depth: number }[] = [{ id: chunkId, depth: 0 }]
107
- const result: { chunk_id: string; chunk_name: string; file_path: string; depth: number }[] = []
108
-
109
- while (queue.length > 0) {
110
- const { id, depth } = queue.shift()!
111
- if (depth >= maxDepth) continue
112
- const { data: callerLinks } = await adminDb.from('links').select('source_id')
113
- .eq('link_type_id', callsLinkTypeId).eq('target_id', id)
114
- for (const link of callerLinks || []) {
115
- if (visited.has(link.source_id)) continue
116
- visited.add(link.source_id)
117
- const c = await getChunkById(link.source_id)
118
- if (!c) continue
119
- result.push({ chunk_id: c.id, chunk_name: c.data?.chunk_name || '', file_path: c.data?.file_path || '', depth: depth + 1 })
120
- queue.push({ id: c.id, depth: depth + 1 })
121
- }
122
- }
123
- return result
124
- }
125
- // CIL[END stable_id="~/.framework/mcp/tools/cil/context.ts:blastRadiusBFS:function"]
126
-
127
- // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/context.ts:safetyVerdict:function" type="function" identity="safetyVerdict" parent="~/.framework/mcp/tools/cil/context.ts"]
128
- // CIL[DOC-VECTOR type="context" content="purpose='Compute transitive callers of a chunk up to a max depth'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
129
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
130
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
131
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
132
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
133
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
134
- // CIL[DOC-MACRO purpose="Assess edit safety for a chunk based on stability, blast radius, docs, and config dependencies"]
135
- // CIL[DOC-RESPONSIBILITY responsibility="Return a safety level and list of risk flags"]
136
- // CIL[DOC-CONTEXT module="mcp-cil-context" layer="analysis" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/context.ts"]
137
- // CIL[DOC-CONTRACT inputs="chunk, blastRadius, configDeps" outputs="{level, flags, summary}" errors="none" side_effects="none"]
138
- // CIL[DOC-MICRO logic_summary="Inspects chunk data and derived metrics to classify risk" notable_decisions="[]"]
139
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
140
- // CIL[DOC-STABILITY stability="stable"]
141
- function safetyVerdict(chunk: any, blastRadius: any[], configDeps: any[]) {
142
- const d = chunk.data || {}
143
- const flags: string[] = []
144
- if (d.stability === 'stable') flags.push('stability=stable: downstream consumers may break on signature changes')
145
- if (blastRadius.length >= 10) flags.push(`high blast radius: ${blastRadius.length} transitive callers`)
146
- else if (blastRadius.length >= 3) flags.push(`moderate blast radius: ${blastRadius.length} callers`)
147
- if (configDeps.length > 0) flags.push(`reads ${configDeps.length} config field(s)`)
148
- if (!d.macro && !d.micro) flags.push('no contract documentation')
149
- if (d.is_dead_code) flags.push('flagged as dead code')
150
- const level = flags.length === 0 ? 'safe' : (d.stability === 'stable' || blastRadius.length >= 10) ? 'risky' : 'caution'
151
- return { level, flags, summary: level === 'safe' ? 'Low risk.' : `${level === 'risky' ? 'High' : 'Moderate'} risk — review flags before editing.` }
152
- }
153
- // CIL[DOC-VECTOR type="context" content="purpose='Assess edit safety for a chunk based on stability, blast radius, docs, and config dependencies'; No verified external callers; imports: .framework/mcp/shared/db.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/context.ts:safetyVerdict:function"]
160
-
161
- // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/context.ts:buildBrief:function" type="function" identity="buildBrief" parent="~/.framework/mcp/tools/cil/context.ts"]
162
- // CIL[DOC-MACRO purpose="Assemble a full pre-edit context brief for a chunk"]
163
- // CIL[DOC-RESPONSIBILITY responsibility="Return contract, blast radius, callees, tests, config deps, and safety verdict"]
164
- // CIL[DOC-CONTEXT module="mcp-cil-context" layer="analysis" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/context.ts"]
165
- // CIL[DOC-CONTRACT inputs="chunk: any, maxDepth: number = 4" outputs="context brief object" errors="none" side_effects="queries multiple link and item tables"]
166
- // CIL[DOC-MICRO logic_summary="Resolves link types, computes blast radius, gathers callees, tests, and config dependencies" notable_decisions="[]"]
167
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
168
- // CIL[DOC-STABILITY stability="stable"]
169
- async function buildBrief(chunk: any, maxDepth = 4) {
170
- const d = chunk.data || {}
171
- const [callsId, testedById, configuresId] = await Promise.all([
172
- resolveLinkTypeId('cil_calls').catch(() => null),
173
- resolveLinkTypeId('cil_tested_by').catch(() => null),
174
- resolveLinkTypeId('cil_configures').catch(() => null),
175
- ])
176
-
177
- const blastRadius = callsId ? await blastRadiusBFS(chunk.id, maxDepth, callsId) : []
178
-
179
- const callees: any[] = []
180
- if (callsId) {
181
- const { data: ls } = await adminDb.from('links').select('target_id').eq('link_type_id', callsId).eq('source_id', chunk.id)
182
- for (const l of ls || []) {
183
- const c = await getChunkById(l.target_id)
184
- if (c) callees.push({ chunk_id: c.id, chunk_name: c.data?.chunk_name || '', file_path: c.data?.file_path || '' })
185
- }
186
- }
187
-
188
- const testPaths: { path: string; is_e2e: boolean }[] = []
189
- if (testedById) {
190
- const { data: ls } = await adminDb.from('links').select('target_id, metadata').eq('link_type_id', testedById).eq('source_id', chunk.id)
191
- for (const l of ls || []) testPaths.push({ path: l.metadata?.test_path || '', is_e2e: l.metadata?.is_e2e || false })
192
- }
193
- if (testPaths.length === 0) {
194
- if (d.test_unit_path) testPaths.push({ path: d.test_unit_path, is_e2e: false })
195
- if (d.test_e2e_path) testPaths.push({ path: d.test_e2e_path, is_e2e: true })
196
- }
197
-
198
- const configDeps: { field_name: string; config_id: string }[] = []
199
- if (configuresId) {
200
- const { data: ls } = await adminDb.from('links').select('source_id, metadata').eq('link_type_id', configuresId).eq('target_id', chunk.id)
201
- for (const l of ls || []) {
202
- const ci = await getChunkById(l.source_id)
203
- if (ci) configDeps.push({ field_name: ci.data?.field_name || '', config_id: l.source_id })
204
- }
205
- }
206
-
207
- return {
208
- chunk_id: chunk.id,
209
- chunk_name: d.chunk_name || '',
210
- file_path: d.file_path || '',
211
- line_start: d.line_start || null,
212
- line_end: d.line_end || null,
213
- chunk_type: d.chunk_type || '',
214
- source_set_id: d.source_set_id || null,
215
- layer: d.layer || null,
216
- contract: {
217
- description: d.description || '',
218
- module: d.module || '',
219
- audience: d.audience || '',
220
- macro: d.macro || '',
221
- micro: d.micro || '',
222
- input_spec: d.input_spec || '',
223
- output_spec: d.output_spec || '',
224
- side_effects: d.side_effects || '',
225
- throws: d.throws || '',
226
- stability: d.stability || 'unknown',
227
- called_by: d.called_by || '',
228
- calls: d.calls || '',
229
- tags: d.tags || '',
230
- complexity: d.complexity || '',
231
- error_handling: d.error_handling || '',
232
- related_files: d.related_files || d.see_also || '',
233
- depends_on: d.depends_on || [],
234
- depended_by: d.depended_by || [],
235
- doc_confidence: d.doc_confidence || 'unverified_legacy',
236
- validation_errors: d.doc_validation_errors || [],
237
- },
238
- hash: { stored_hash: d.stored_hash || null, hash_updated_at: d.hash_updated_at || null },
239
- blast_radius: { direct_caller_count: blastRadius.filter(r => r.depth === 1).length, total_affected: blastRadius.length, callers: blastRadius },
240
- calls: callees,
241
- test_paths: testPaths,
242
- config_dependencies: configDeps,
243
- edit_safety: safetyVerdict(chunk, blastRadius, configDeps),
244
- }
245
- }
246
- // CIL[DOC-VECTOR type="context" content="purpose='Assemble a full pre-edit context brief for a chunk'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
247
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
248
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
249
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
250
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
251
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
252
- // CIL[END stable_id="~/.framework/mcp/tools/cil/context.ts:buildBrief:function"]
253
-
254
- // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/context.ts:register:function" type="function" identity="register" parent="~/.framework/mcp/tools/cil/context.ts"]
255
- // CIL[DOC-MACRO purpose="Register CIL context tools on an MCP server"]
256
- // CIL[DOC-RESPONSIBILITY responsibility="Expose spine_cil_find_context, spine_cil_get_context, and spine_cil_post_edit"]
257
- // CIL[DOC-CONTEXT module="mcp-cil-context" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/context.ts"]
258
- // CIL[DOC-CONTRACT inputs="server: McpServer" outputs="none" errors="none" side_effects="registers three tools"]
259
- // CIL[DOC-MICRO logic_summary="Calls server.registerTool for find context, get context, and post edit handlers" notable_decisions="[]"]
260
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
261
- // CIL[DOC-STABILITY stability="stable"]
262
- export function register(server: McpServer) {
263
-
264
- server.registerTool(
265
- 'spine_cil_find_context',
266
- {
267
- description: 'Get a full pre-edit context brief for a chunk by name. Call this BEFORE editing any named chunk. Returns contract, blast radius, test paths, config dependencies, and an edit_safety verdict (safe/caution/risky).',
268
- inputSchema: z.object({
269
- stable_id: z.string().describe('Exact stable_id of the chunk'),
270
- project_id: z.string().uuid().describe('The cil_project UUID'),
271
- version_id: z.string().optional().describe('Optional version UUID to scope the lookup'),
272
- max_depth: z.number().int().min(1).max(6).default(4).optional().describe('BFS depth for blast radius traversal'),
273
- }),
274
- },
275
- async ({ stable_id, project_id, version_id, max_depth }) => {
276
- const chunk = await getChunkByStableId(project_id, stable_id, version_id)
277
- if (!chunk) {
278
- return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `No chunk with stable_id "${stable_id}" found`, hint: 'Use spine_cil_search_chunks to find chunks by description' }) }] }
279
- }
280
- const brief = await buildBrief(chunk, max_depth ?? 4)
281
- return { content: [{ type: 'text', text: JSON.stringify({ ok: true, brief }, null, 2) }] }
282
- }
283
- )
284
-
285
- server.registerTool(
286
- 'spine_cil_get_context',
287
- {
288
- description: 'Get a full pre-edit context brief for a chunk by its stable_id. Returns contract, blast radius, test paths, config dependencies, and edit_safety verdict.',
289
- inputSchema: z.object({
290
- project_id: z.string().uuid().describe('The cil_project UUID'),
291
- stable_id: z.string().describe('The chunk stable_id'),
292
- version_id: z.string().optional().describe('Optional version UUID to scope the lookup'),
293
- max_depth: z.number().int().min(1).max(6).default(4).optional(),
294
- }),
295
- },
296
- async ({ project_id, stable_id, version_id, max_depth }) => {
297
- const chunk = await getChunkByStableId(project_id, stable_id, version_id)
298
- if (!chunk) return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `Chunk not found: ${stable_id}` }) }] }
299
- const brief = await buildBrief(chunk, max_depth ?? 4)
300
- return { content: [{ type: 'text', text: JSON.stringify({ ok: true, brief }, null, 2) }] }
301
- }
302
- )
303
-
304
- server.registerTool(
305
- 'spine_cil_post_edit',
306
- {
307
- description: 'Call this AFTER editing a chunk. Returns its stored hash status and exact next_steps commands to reindex and validate the change.',
308
- inputSchema: z.object({
309
- project_id: z.string().uuid().describe('The cil_project UUID'),
310
- stable_id: z.string().describe('The stable_id of the chunk you just edited'),
311
- version_id: z.string().optional().describe('Optional version UUID to scope the lookup'),
312
- }),
313
- },
314
- async ({ project_id, stable_id, version_id }) => {
315
- const chunk = await getChunkByStableId(project_id, stable_id, version_id)
316
- if (!chunk) return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `Chunk not found: ${stable_id}` }) }] }
317
- const d = chunk.data || {}
318
- const result = {
319
- ok: true,
320
- stable_id,
321
- project_id,
322
- version_id: version_id || d.version_id || null,
323
- chunk_name: d.chunk_name || '',
324
- file_path: d.file_path || '',
325
- stored_hash: d.stored_hash || null,
326
- hash_updated_at: d.hash_updated_at || null,
327
- action_required: d.stored_hash
328
- ? 'Run spine_cil_reindex_chunk to refresh the stored hash after your edit, then spine_cil_validate_file to confirm drift is resolved.'
329
- : 'No stored hash yet — run spine_cil_reindex_chunk or Pass 2 ingestion.',
330
- next_steps: [
331
- `spine_cil_reindex_chunk({ project_id: "${d.project_id || project_id}", stable_id: "${stable_id}", version_id: "${version_id || d.version_id || ''}", also_embed: true })`,
332
- `spine_cil_validate_file({ project_id: "${d.project_id || project_id}", file_path: "${d.file_path || ''}" })`,
333
- ],
334
- }
335
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }
336
- }
337
- )
338
- }
339
- // CIL[DOC-VECTOR type="context" content="purpose='Register CIL context tools on an MCP server'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
340
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
341
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
342
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
343
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
344
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
345
- // CIL[END stable_id="~/.framework/mcp/tools/cil/context.ts:register:function"]
@@ -1,242 +0,0 @@
1
- // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/graph.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/mcp/tools/cil/graph.ts"]
2
- // CIL[DOC-MACRO purpose="Import dependencies and set up the CIL graph MCP tool module"]
3
- // CIL[DOC-RESPONSIBILITY responsibility="Declare module-level imports for the MCP CIL graph tool"]
4
- // CIL[DOC-CONTEXT module="mcp-tools-cil" layer="tools" related_files=".framework/mcp/shared/db.ts"]
5
- // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
6
- // CIL[DOC-MICRO logic_summary="Import McpServer SDK, zod, and shared database helpers" notable_decisions="none"]
7
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
- // CIL[DOC-STABILITY stability="stable"]
9
- // CIL[DOC-AUDIENCE audience="maintainer"]
10
-
11
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
12
- import { z } from 'zod'
13
- import { adminDb, resolveLinkTypeId, fetchFunction } from '../../shared/db.js'
14
- // CIL[DOC-VECTOR type="context" content="purpose='Import dependencies and set up the CIL graph MCP tool module'; 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/graph.ts:module_header:module_header"]
21
-
22
- // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/graph.ts:getChunkById:function" type="function" identity="getChunkById" parent="~/.framework/mcp/tools/cil/graph.ts"]
23
- // CIL[DOC-MACRO purpose="Fetch a single CIL chunk by its primary item id"]
24
- // CIL[DOC-RESPONSIBILITY responsibility="Load a chunk record from the items table by id"]
25
- // CIL[DOC-CONTEXT module="mcp-tools-cil" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/graph.ts"]
26
- // CIL[DOC-CONTRACT inputs="id: string" outputs="chunk record or null" errors="none" side_effects="database read"]
27
- // CIL[DOC-MICRO logic_summary="Query adminDb items table for id, title, data matching the given id and return the data" notable_decisions="Uses maybeSingle to return null when no match"]
28
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
29
- // CIL[DOC-STABILITY stability="stable"]
30
- async function getChunkById(id: string) {
31
- const { data } = await adminDb.from('items').select('id, title, data')
32
- .eq('id', id).maybeSingle()
33
- return data
34
- }
35
- // CIL[DOC-VECTOR type="context" content="purpose='Fetch a single CIL chunk by its primary item id'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
36
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
37
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
38
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
39
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
40
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
41
- // CIL[END stable_id="~/.framework/mcp/tools/cil/graph.ts:getChunkById:function"]
42
-
43
- // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/graph.ts:getChunkByStableId:function" type="function" identity="getChunkByStableId" parent="~/.framework/mcp/tools/cil/graph.ts"]
44
- // CIL[DOC-MACRO purpose="Fetch a CIL chunk by its stable_id within a project and optional version"]
45
- // CIL[DOC-RESPONSIBILITY responsibility="Locate a unique active CIL chunk by stable_id"]
46
- // CIL[DOC-CONTEXT module="mcp-tools-cil" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/graph.ts"]
47
- // CIL[DOC-CONTRACT inputs="projectId: string, stableId: string, versionId?: string" outputs="chunk record or null" errors="none" side_effects="database read"]
48
- // CIL[DOC-MICRO logic_summary="Filter items by kb_type, project_id, stable_id, is_active and optional version_id, then return data" notable_decisions="Casts query to any when adding the optional version filter"]
49
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
50
- // CIL[DOC-STABILITY stability="stable"]
51
- async function getChunkByStableId(projectId: string, stableId: string, versionId?: string) {
52
- let q = adminDb.from('items').select('id, title, data')
53
- .filter('data->>kb_type', 'eq', 'cil_chunk')
54
- .filter('data->>project_id', 'eq', projectId)
55
- .filter('data->>stable_id', 'eq', stableId)
56
- .eq('is_active', true)
57
- if (versionId) q = (q as any).filter('data->>version_id', 'eq', versionId)
58
- const { data } = await (q as any).maybeSingle()
59
- return data
60
- }
61
- // CIL[DOC-VECTOR type="context" content="purpose='Fetch a CIL chunk by its stable_id within a project and optional version'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
62
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
63
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
64
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
65
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
66
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
67
- // CIL[END stable_id="~/.framework/mcp/tools/cil/graph.ts:getChunkByStableId:function"]
68
-
69
- // CIL[BEGIN stable_id="~/.framework/mcp/tools/cil/graph.ts:register:function" type="function" identity="register" parent="~/.framework/mcp/tools/cil/graph.ts"]
70
- // CIL[DOC-MACRO purpose="Register CIL graph query tools on an MCP server"]
71
- // CIL[DOC-RESPONSIBILITY responsibility="Wire up MCP tools for blast radius, callers, file chunks and graph diff"]
72
- // CIL[DOC-CONTEXT module="mcp-tools-cil" layer="tools" related_files=".framework/mcp/shared/db.ts,.framework/mcp/tools/cil/graph.ts"]
73
- // CIL[DOC-CONTRACT inputs="server: McpServer" outputs="registered tool handlers" errors="throws if cil_calls link type or chunk is not found" side_effects="registers tools on the server and queries the database and links table"]
74
- // CIL[DOC-MICRO logic_summary="Use server.registerTool to expose four CIL graph introspection endpoints backed by Supabase items and links" notable_decisions="Returns JSON-stringified content; uses BFS for blast radius; filters symbol references for direct callers; delegates graph_diff to fetchFunction"]
75
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
76
- // CIL[DOC-STABILITY stability="stable"]
77
- export function register(server: McpServer) {
78
-
79
- server.registerTool(
80
- 'spine_cil_blast_radius',
81
- {
82
- description: 'Find all chunks that transitively call a given chunk (BFS traversal). Use this before refactoring to understand how many callers will be affected.',
83
- inputSchema: z.object({
84
- project_id: z.string().uuid().describe('The cil_project UUID'),
85
- stable_id: z.string().describe('The chunk stable_id to analyse'),
86
- version_id: z.string().optional().describe('Optional version UUID to scope the lookup'),
87
- max_depth: z.number().int().min(1).max(6).default(4).optional().describe('Maximum BFS hop depth'),
88
- }),
89
- },
90
- async ({ project_id, stable_id, version_id, max_depth = 4 }) => {
91
- let callsId: string
92
- try { callsId = await resolveLinkTypeId('cil_calls') }
93
- catch { return { content: [{ type: 'text', text: JSON.stringify({ error: 'cil_calls link type not found — run Pass 4b first' }) }] } }
94
-
95
- const chunk = await getChunkByStableId(project_id, stable_id, version_id)
96
- if (!chunk) return { content: [{ type: 'text', text: JSON.stringify({ error: `Chunk not found: ${stable_id}` }) }] }
97
-
98
- const startId = chunk.id
99
- const visited = new Set([startId])
100
- const queue: { id: string; depth: number }[] = [{ id: startId, depth: 0 }]
101
- const callers: { stable_id: string; chunk_name: string; file_path: string; depth: number }[] = []
102
-
103
- while (queue.length > 0) {
104
- const { id, depth } = queue.shift()!
105
- if (depth >= max_depth) continue
106
- const { data: links } = await adminDb.from('links').select('source_id')
107
- .eq('link_type_id', callsId).eq('target_id', id)
108
- for (const l of links || []) {
109
- if (visited.has(l.source_id)) continue
110
- visited.add(l.source_id)
111
- const c = await getChunkById(l.source_id)
112
- if (!c) continue
113
- callers.push({ stable_id: c.data?.stable_id || c.id, chunk_name: c.data?.chunk_name || '', file_path: c.data?.file_path || '', depth: depth + 1 })
114
- queue.push({ id: c.id, depth: depth + 1 })
115
- }
116
- }
117
-
118
- const result = {
119
- stable_id,
120
- chunk_name: chunk.data?.chunk_name || '',
121
- file_path: chunk.data?.file_path || '',
122
- max_depth,
123
- direct_callers: callers.filter(c => c.depth === 1).length,
124
- total_affected: callers.length,
125
- callers,
126
- }
127
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }
128
- }
129
- )
130
-
131
- server.registerTool(
132
- 'spine_cil_get_callers',
133
- {
134
- description: 'Get the direct callers and symbol references (imports/references) of a chunk (depth-1 only). Faster than spine_cil_blast_radius when you just need to know what directly uses a chunk.',
135
- inputSchema: z.object({
136
- project_id: z.string().uuid().describe('The cil_project UUID'),
137
- stable_id: z.string().describe('The chunk stable_id'),
138
- version_id: z.string().optional().describe('Optional version UUID to scope the lookup'),
139
- }),
140
- },
141
- async ({ project_id, stable_id, version_id }) => {
142
- let callsId: string
143
- try { callsId = await resolveLinkTypeId('cil_calls') }
144
- catch { return { content: [{ type: 'text', text: JSON.stringify({ error: 'cil_calls link type not found' }) }] } }
145
-
146
- const chunk = await getChunkByStableId(project_id, stable_id, version_id)
147
- if (!chunk) return { content: [{ type: 'text', text: JSON.stringify({ error: `Chunk not found: ${stable_id}` }) }] }
148
-
149
- const { data: links } = await adminDb.from('links').select('source_id, data, metadata')
150
- .eq('link_type_id', callsId).eq('target_id', chunk.id)
151
-
152
- const callers = []
153
- for (const l of links || []) {
154
- const c = await getChunkById(l.source_id)
155
- if (c) callers.push({ stable_id: c.data?.stable_id || c.id, chunk_name: c.data?.chunk_name || '', file_path: c.data?.file_path || '' })
156
- }
157
-
158
- return { content: [{ type: 'text', text: JSON.stringify({ stable_id, caller_count: callers.length, callers }, null, 2) }] }
159
- }
160
- )
161
-
162
- server.registerTool(
163
- 'spine_cil_get_file_chunks',
164
- {
165
- description: 'List all indexed chunks for a file, sorted by line number. Useful for understanding the structure of a file before editing.',
166
- inputSchema: z.object({
167
- project_id: z.string().uuid().describe('The cil_project UUID'),
168
- file_path: z.string().describe('Relative file path from repo root, e.g. ".framework/cli/commands/auth.ts"'),
169
- }),
170
- },
171
- async ({ project_id, file_path }) => {
172
- const { data: chunks } = await adminDb.from('items').select('id, title, data')
173
- .filter('data->>kb_type', 'eq', 'cil_chunk')
174
- .filter('data->>project_id', 'eq', project_id)
175
- .filter('data->>file_path', 'eq', file_path)
176
- .eq('is_active', true)
177
-
178
- if (!chunks || chunks.length === 0) {
179
- return { content: [{ type: 'text', text: JSON.stringify({ error: `No chunks found for file: ${file_path}` }) }] }
180
- }
181
-
182
- const sorted = chunks
183
- .map((c: any) => ({
184
- id: c.id,
185
- stable_id: c.data?.stable_id || '',
186
- version_id: c.data?.version_id || '',
187
- chunk_name: c.data?.chunk_name || '',
188
- chunk_type: c.data?.chunk_type || '',
189
- line_start: c.data?.line_start || 0,
190
- line_end: c.data?.line_end || 0,
191
- macro: c.data?.macro || '',
192
- doc_confidence: c.data?.doc_confidence || 'unverified_legacy',
193
- is_dead_code: c.data?.is_dead_code || false,
194
- stability: c.data?.stability || '',
195
- }))
196
- .sort((a: any, b: any) => a.line_start - b.line_start)
197
-
198
- return {
199
- content: [{
200
- type: 'text',
201
- text: JSON.stringify({
202
- project_id,
203
- file_path,
204
- chunk_count: sorted.length,
205
- chunks: sorted,
206
- }, null, 2),
207
- }],
208
- }
209
- }
210
- )
211
-
212
- server.registerTool(
213
- 'spine_cil_graph_diff',
214
- {
215
- description: 'Compare the CIL call and import graph between two project versions. Returns added, removed, and unchanged edges keyed by stable IDs and file paths.',
216
- inputSchema: z.object({
217
- project_id: z.string().uuid().describe('The cil_project UUID'),
218
- from_version_id: z.string().uuid().describe('The source version UUID to diff from'),
219
- to_version_id: z.string().uuid().describe('The target version UUID to diff to'),
220
- }),
221
- },
222
- async ({ project_id, from_version_id, to_version_id }) => {
223
- try {
224
- const result = await fetchFunction('cil-graph', 'graph_diff', {
225
- project_id,
226
- from_version_id,
227
- to_version_id,
228
- })
229
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }
230
- } catch (err: any) {
231
- return { content: [{ type: 'text', text: JSON.stringify({ error: err?.message || String(err) }) }] }
232
- }
233
- }
234
- )
235
- }
236
- // CIL[DOC-VECTOR type="context" content="purpose='Register CIL graph query tools on an MCP server'; No verified external callers; imports: .framework/mcp/shared/db.ts"]
237
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
238
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
239
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
240
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
241
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
242
- // CIL[END stable_id="~/.framework/mcp/tools/cil/graph.ts:register:function"]