spine-framework 0.4.4 → 0.5.0-rc.5

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 (305) 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/install-app.ts +183 -13
  8. package/.framework/cli/commands/migrate.ts +36 -30
  9. package/.framework/cli/commands/migrations.ts +16 -56
  10. package/.framework/cli/commands/upgrade.ts +35 -0
  11. package/.framework/cli/commands/validate-app.ts +127 -1
  12. package/.framework/cli/commands/validate-schema.ts +147 -0
  13. package/.framework/cli/context.ts +223 -110
  14. package/.framework/cli/index.ts +6 -0
  15. package/.framework/cli/lib/project-files.ts +241 -1
  16. package/.framework/functions/_shared/app-manifest.ts +2 -0
  17. package/.framework/functions/_shared/hash-api-key.ts +183 -79
  18. package/.framework/functions/_shared/logging.ts +562 -224
  19. package/.framework/functions/_shared/middleware.ts +47 -44
  20. package/.framework/functions/_shared/permissions.ts +4 -0
  21. package/.framework/functions/admin-data.ts +51 -28
  22. package/.framework/functions/ai-agents.ts +10 -6
  23. package/.framework/functions/api-keys.ts +301 -122
  24. package/.framework/functions/apps.ts +63 -29
  25. package/.framework/functions/cil-ingest.ts +48 -15
  26. package/.framework/functions/debug-auth.ts +14 -8
  27. package/.framework/functions/deliveries.ts +39 -12
  28. package/.framework/functions/embeddings.ts +149 -78
  29. package/.framework/functions/integration-outbound.ts +67 -27
  30. package/.framework/functions/integrations.ts +254 -127
  31. package/.framework/functions/logs.ts +273 -133
  32. package/.framework/functions/observability.ts +278 -148
  33. package/.framework/functions/pipeline-executions.ts +1 -1
  34. package/.framework/functions/pipelines.ts +14 -9
  35. package/.framework/functions/prompt-configs.ts +7 -4
  36. package/.framework/functions/roles.ts +8 -5
  37. package/.framework/functions/security.ts +30 -17
  38. package/.framework/functions/system-cron.ts +240 -127
  39. package/.framework/functions/tests.ts +7 -6
  40. package/.framework/functions/timers.ts +310 -107
  41. package/.framework/functions/triggers.ts +28 -13
  42. package/.framework/functions/types.ts +13 -10
  43. package/.framework/migrations/069_log_stats_window.sql +54 -0
  44. package/.framework/migrations/070_app_type_schema_rpcs.sql +166 -0
  45. package/.framework/migrations/071_timer_interval_keys.sql +96 -0
  46. package/.framework/migrations/072_slug_autofill.sql +77 -0
  47. package/.framework/migrations/073_seed_member_roles.sql +26 -0
  48. package/.framework/migrations/074_app_route_prefix_domains.sql +168 -0
  49. package/.framework/migrations/075_security_definer_grants.sql +157 -0
  50. package/.framework/src/apps/admin/index.tsx +1141 -775
  51. package/.framework/src/components/ErrorBoundary.tsx +136 -0
  52. package/.framework/src/components/admin/AdminListPage.tsx +81 -73
  53. package/.framework/src/components/admin/AdminSidebar.tsx +88 -79
  54. package/.framework/src/components/admin/EntitySelect.tsx +181 -0
  55. package/.framework/src/components/admin/PageInstructions.tsx +86 -127
  56. package/.framework/src/components/app-shell/GenericDetailPage.tsx +37 -13
  57. package/.framework/src/components/app-shell/GenericListPage.tsx +28 -32
  58. package/.framework/src/components/layout/Sidebar.tsx +300 -177
  59. package/.framework/src/components/runtime/DataDetailPage.tsx +67 -35
  60. package/.framework/src/components/runtime/DataHeader.tsx +96 -48
  61. package/.framework/src/components/runtime/DataListPage.tsx +3 -26
  62. package/.framework/src/components/runtime/DataStats.tsx +10 -10
  63. package/.framework/src/components/runtime/DataTable.tsx +12 -10
  64. package/.framework/src/components/ui/sheet.tsx +24 -26
  65. package/.framework/src/components/ui/textarea.tsx +74 -48
  66. package/.framework/src/contexts/AppContext.tsx +5 -12
  67. package/.framework/src/contexts/AuthContext.tsx +17 -9
  68. package/.framework/src/hooks/useApps.ts +18 -22
  69. package/.framework/src/hooks/useEntityList.ts +12 -9
  70. package/.framework/src/hooks/useListSchema.ts +108 -58
  71. package/.framework/src/instructions/README.md +74 -0
  72. package/.framework/src/instructions/accounts.md +97 -0
  73. package/.framework/src/instructions/ai-agents.md +69 -0
  74. package/.framework/src/instructions/alerts.md +80 -0
  75. package/.framework/src/instructions/api-keys.md +87 -0
  76. package/.framework/src/instructions/apps.md +77 -0
  77. package/.framework/src/instructions/concepts/ai-and-prompts.md +150 -0
  78. package/.framework/src/instructions/concepts/apps-and-renderers.md +228 -0
  79. package/.framework/src/instructions/concepts/auth-and-api-keys.md +133 -0
  80. package/.framework/src/instructions/concepts/automation.md +186 -0
  81. package/.framework/src/instructions/concepts/concurrency-and-idempotency.md +125 -0
  82. package/.framework/src/instructions/concepts/core-vs-custom.md +124 -0
  83. package/.framework/src/instructions/concepts/design-schema.md +152 -0
  84. package/.framework/src/instructions/concepts/integrations-and-webhooks.md +127 -0
  85. package/.framework/src/instructions/concepts/observability.md +116 -0
  86. package/.framework/src/instructions/concepts/permissions.md +150 -0
  87. package/.framework/src/instructions/concepts/runtime-records.md +111 -0
  88. package/.framework/src/instructions/concepts/scope-and-accounts.md +112 -0
  89. package/.framework/src/instructions/concepts/spine-way.md +172 -0
  90. package/.framework/src/instructions/deliveries.md +59 -0
  91. package/.framework/src/instructions/guide/00-orientation.md +106 -0
  92. package/.framework/src/instructions/guide/01-install-and-first-run.md +253 -0
  93. package/.framework/src/instructions/guide/02-project-map.md +147 -0
  94. package/.framework/src/instructions/guide/03-domain-model.md +223 -0
  95. package/.framework/src/instructions/guide/04-first-app.md +227 -0
  96. package/.framework/src/instructions/guide/05-glossary.md +183 -0
  97. package/.framework/src/instructions/integrations.md +96 -0
  98. package/.framework/src/instructions/internal/cil-markers.md +83 -0
  99. package/.framework/src/instructions/internal/docs-contract.md +158 -0
  100. package/.framework/src/instructions/invites.md +60 -0
  101. package/.framework/src/instructions/kb.md +80 -0
  102. package/.framework/src/instructions/logs.md +77 -0
  103. package/.framework/src/instructions/notifications.md +77 -0
  104. package/.framework/src/instructions/observability.md +61 -0
  105. package/.framework/src/instructions/operations/deployment.md +115 -0
  106. package/.framework/src/instructions/operations/migrations.md +125 -0
  107. package/.framework/src/instructions/operations/security-checklist.md +170 -0
  108. package/.framework/src/instructions/operations/troubleshooting.md +170 -0
  109. package/.framework/src/instructions/operations/upgrade.md +116 -0
  110. package/.framework/src/instructions/people.md +91 -0
  111. package/.framework/src/instructions/pipeline-executions.md +62 -0
  112. package/.framework/src/instructions/pipelines.md +78 -0
  113. package/.framework/src/instructions/prompts.md +95 -0
  114. package/.framework/src/instructions/reference/api/admin-data.md +162 -0
  115. package/.framework/src/instructions/reference/api/auth.md +113 -0
  116. package/.framework/src/instructions/reference/api/errors-and-envelopes.md +113 -0
  117. package/.framework/src/instructions/reference/app-manifest.md +184 -0
  118. package/.framework/src/instructions/reference/cli.md +124 -0
  119. package/.framework/src/instructions/reference/database.md +132 -0
  120. package/.framework/src/instructions/reference/design-schema.md +280 -0
  121. package/.framework/src/instructions/reference/env-vars.md +133 -0
  122. package/.framework/src/instructions/reference/frontend-sdk.md +207 -0
  123. package/.framework/src/instructions/reference/functions/account-nodes.md +75 -0
  124. package/.framework/src/instructions/reference/functions/admin-data.md +197 -0
  125. package/.framework/src/instructions/reference/functions/admin-funnel.md +90 -0
  126. package/.framework/src/instructions/reference/functions/admin-install-funnel.md +107 -0
  127. package/.framework/src/instructions/reference/functions/admin-signals.md +102 -0
  128. package/.framework/src/instructions/reference/functions/ai-agents.md +148 -0
  129. package/.framework/src/instructions/reference/functions/ai-interactions.md +156 -0
  130. package/.framework/src/instructions/reference/functions/api-keys.md +130 -0
  131. package/.framework/src/instructions/reference/functions/apps.md +140 -0
  132. package/.framework/src/instructions/reference/functions/auth.md +99 -0
  133. package/.framework/src/instructions/reference/functions/debug-auth.md +91 -0
  134. package/.framework/src/instructions/reference/functions/deliveries.md +110 -0
  135. package/.framework/src/instructions/reference/functions/embeddings.md +166 -0
  136. package/.framework/src/instructions/reference/functions/eval-harness.md +149 -0
  137. package/.framework/src/instructions/reference/functions/index.md +103 -0
  138. package/.framework/src/instructions/reference/functions/integration-outbound.md +200 -0
  139. package/.framework/src/instructions/reference/functions/integration-routes.md +151 -0
  140. package/.framework/src/instructions/reference/functions/integrations.md +130 -0
  141. package/.framework/src/instructions/reference/functions/invites.md +182 -0
  142. package/.framework/src/instructions/reference/functions/item-progress.md +107 -0
  143. package/.framework/src/instructions/reference/functions/kb.md +166 -0
  144. package/.framework/src/instructions/reference/functions/logs.md +141 -0
  145. package/.framework/src/instructions/reference/functions/observability.md +105 -0
  146. package/.framework/src/instructions/reference/functions/pipeline-executions.md +132 -0
  147. package/.framework/src/instructions/reference/functions/pipeline-runner-background.md +121 -0
  148. package/.framework/src/instructions/reference/functions/pipelines.md +136 -0
  149. package/.framework/src/instructions/reference/functions/prompt-configs.md +121 -0
  150. package/.framework/src/instructions/reference/functions/roles.md +121 -0
  151. package/.framework/src/instructions/reference/functions/security.md +140 -0
  152. package/.framework/src/instructions/reference/functions/system-cron.md +136 -0
  153. package/.framework/src/instructions/reference/functions/system.md +106 -0
  154. package/.framework/src/instructions/reference/functions/tests.md +97 -0
  155. package/.framework/src/instructions/reference/functions/timers.md +117 -0
  156. package/.framework/src/instructions/reference/functions/trigger-scheduler.md +102 -0
  157. package/.framework/src/instructions/reference/functions/triggers.md +140 -0
  158. package/.framework/src/instructions/reference/functions/types.md +146 -0
  159. package/.framework/src/instructions/reference/seeds.md +126 -0
  160. package/.framework/src/instructions/reference/shared-modules.md +127 -0
  161. package/.framework/src/instructions/reference/spine-config.md +114 -0
  162. package/.framework/src/instructions/roles.md +80 -0
  163. package/.framework/src/instructions/runtime-collaboration.md +106 -0
  164. package/.framework/src/instructions/runtime-detail.md +70 -0
  165. package/.framework/src/instructions/runtime-list.md +77 -0
  166. package/.framework/src/instructions/security.md +67 -0
  167. package/.framework/src/instructions/tasks/add-a-pipeline.md +110 -0
  168. package/.framework/src/instructions/tasks/add-a-role.md +96 -0
  169. package/.framework/src/instructions/tasks/add-a-timer.md +114 -0
  170. package/.framework/src/instructions/tasks/add-a-trigger.md +106 -0
  171. package/.framework/src/instructions/tasks/add-a-type.md +151 -0
  172. package/.framework/src/instructions/tasks/add-a-webhook.md +108 -0
  173. package/.framework/src/instructions/tasks/add-an-ai-agent.md +108 -0
  174. package/.framework/src/instructions/tasks/add-an-integration.md +124 -0
  175. package/.framework/src/instructions/tasks/build-a-custom-page.md +118 -0
  176. package/.framework/src/instructions/tasks/document-your-app.md +117 -0
  177. package/.framework/src/instructions/tasks/package-and-install-an-app.md +136 -0
  178. package/.framework/src/instructions/tasks/register-an-app.md +137 -0
  179. package/.framework/src/instructions/tasks/test-your-code.md +108 -0
  180. package/.framework/src/instructions/tasks/write-a-function.md +132 -0
  181. package/.framework/src/instructions/tasks/write-a-migration.md +110 -0
  182. package/.framework/src/instructions/testing.md +59 -0
  183. package/.framework/src/instructions/timers.md +84 -0
  184. package/.framework/src/instructions/triggers.md +69 -0
  185. package/.framework/src/instructions/types.md +93 -0
  186. package/.framework/src/lib/app-mount.ts +88 -0
  187. package/.framework/src/pages/NotFoundPage.tsx +62 -31
  188. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +117 -106
  189. package/.framework/src/pages/admin/AIAgentsPage.tsx +86 -48
  190. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +153 -152
  191. package/.framework/src/pages/admin/APIKeysPage.tsx +91 -90
  192. package/.framework/src/pages/admin/AlertsConfigPage.tsx +29 -18
  193. package/.framework/src/pages/admin/AppDetailPage.tsx +6 -60
  194. package/.framework/src/pages/admin/AppsPage.tsx +104 -66
  195. package/.framework/src/pages/admin/DeliveriesPage.tsx +5 -5
  196. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +5 -23
  197. package/.framework/src/pages/admin/EmbeddingsPage.tsx +5 -26
  198. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +7 -7
  199. package/.framework/src/pages/admin/IntegrationsPage.tsx +85 -43
  200. package/.framework/src/pages/admin/LogsPage.tsx +144 -76
  201. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +223 -140
  202. package/.framework/src/pages/admin/PipelineDetailPage.tsx +134 -113
  203. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +108 -45
  204. package/.framework/src/pages/admin/PipelinesPage.tsx +160 -115
  205. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +96 -98
  206. package/.framework/src/pages/admin/PromptConfigsPage.tsx +101 -59
  207. package/.framework/src/pages/admin/RoleDetailPage.tsx +90 -79
  208. package/.framework/src/pages/admin/RolesPage.tsx +86 -43
  209. package/.framework/src/pages/admin/SecurityPage.tsx +1 -1
  210. package/.framework/src/pages/admin/TestingDashboard.tsx +16 -28
  211. package/.framework/src/pages/admin/TimerDetailPage.tsx +117 -100
  212. package/.framework/src/pages/admin/TimersPage.tsx +90 -62
  213. package/.framework/src/pages/admin/TriggerDetailPage.tsx +90 -83
  214. package/.framework/src/pages/admin/TriggersPage.tsx +124 -99
  215. package/.framework/src/pages/admin/TypeDetailPage.tsx +152 -138
  216. package/.framework/src/pages/admin/TypesPage.tsx +90 -48
  217. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +17 -25
  218. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +17 -27
  219. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +72 -40
  220. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +321 -129
  221. package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +18 -29
  222. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +26 -38
  223. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +34 -46
  224. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +189 -103
  225. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +246 -136
  226. package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +11 -22
  227. package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +9 -20
  228. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +26 -38
  229. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +7 -26
  230. package/.framework/src/pages/auth/LoginPage.tsx +3 -2
  231. package/.framework/src/pages/auth/RegisterPage.tsx +16 -8
  232. package/.framework/templates/agent/AGENTS.md +167 -0
  233. package/.framework/templates/agent/skills/spine-add-ai-agent/SKILL.md +58 -0
  234. package/.framework/templates/agent/skills/spine-add-automation/SKILL.md +62 -0
  235. package/.framework/templates/agent/skills/spine-add-integration/SKILL.md +63 -0
  236. package/.framework/templates/agent/skills/spine-architect/SKILL.md +86 -0
  237. package/.framework/templates/agent/skills/spine-install-app/SKILL.md +79 -0
  238. package/.framework/templates/agent/skills/spine-migration/SKILL.md +75 -0
  239. package/.framework/templates/agent/skills/spine-new-app/SKILL.md +79 -0
  240. package/.framework/templates/agent/skills/spine-new-function/SKILL.md +71 -0
  241. package/.framework/templates/agent/skills/spine-new-type/SKILL.md +72 -0
  242. package/.framework/templates/agent/skills/spine-schema/SKILL.md +77 -0
  243. package/.framework/templates/agent/skills/spine-test/SKILL.md +67 -0
  244. package/.framework/templates/agent/skills/spine-troubleshoot/SKILL.md +74 -0
  245. package/.framework/templates/agent/skills/spine-upgrade/SKILL.md +69 -0
  246. package/.framework/templates/project.json +4 -1
  247. package/.framework/tests/unit/account-scoping-gates.test.ts +394 -0
  248. package/.framework/tests/unit/agent-files.test.ts +355 -0
  249. package/.framework/tests/unit/agent-runner.test.ts +479 -44
  250. package/.framework/tests/unit/api-keys-create-scope-gate.test.ts +160 -0
  251. package/.framework/tests/unit/api-keys-omit-secret-fields.test.ts +38 -0
  252. package/.framework/tests/unit/app-mount.test.ts +80 -0
  253. package/.framework/tests/unit/bootstrap.test.ts +242 -0
  254. package/.framework/tests/unit/cli-context-api-key.test.ts +114 -0
  255. package/.framework/tests/unit/debug-auth.test.ts +38 -0
  256. package/.framework/tests/unit/deliveries-account-scoping.test.ts +185 -0
  257. package/.framework/tests/unit/integration-outbound-credentials.test.ts +167 -0
  258. package/.framework/tests/unit/integrations-audit-redaction.test.ts +130 -0
  259. package/.framework/tests/unit/logging-app-id.test.ts +75 -0
  260. package/.framework/tests/unit/security-definer-grants.test.ts +154 -0
  261. package/.framework/tests/unit/system-context-denial.test.ts +145 -0
  262. package/.framework/tests/unit/system-cron.test.ts +240 -0
  263. package/.framework/tests/unit/timers.test.ts +159 -0
  264. package/README.md +125 -166
  265. package/config/tsconfig.cli.json +2 -2
  266. package/package.json +15 -4
  267. package/templates/project/package-lock.json +2 -2
  268. package/.framework/docs/admin-routes.md +0 -76
  269. package/.framework/docs/api-docs-progress.md +0 -38
  270. package/.framework/docs/api-governance.md +0 -146
  271. package/.framework/docs/api-testing-results.md +0 -212
  272. package/.framework/docs/assembly-launch-guide.md +0 -138
  273. package/.framework/docs/audit-results.md +0 -590
  274. package/.framework/docs/db-api-inventory.md +0 -95
  275. package/.framework/docs/gap-remediation-backlog.md +0 -103
  276. package/.framework/docs/ui-adoption-verification.md +0 -111
  277. package/.framework/docs/ui-api-coverage.md +0 -84
  278. package/.framework/docs/v2-compatibility-audit.md +0 -228
  279. package/.framework/mcp/index.ts +0 -133
  280. package/.framework/mcp/load-env.ts +0 -60
  281. package/.framework/mcp/shared/app-manifest.ts +0 -275
  282. package/.framework/mcp/shared/db.ts +0 -477
  283. package/.framework/mcp/shared/kb.ts +0 -118
  284. package/.framework/mcp/tools/architect.ts +0 -431
  285. package/.framework/mcp/tools/cil/context.ts +0 -345
  286. package/.framework/mcp/tools/cil/graph.ts +0 -242
  287. package/.framework/mcp/tools/cil/ingest.ts +0 -1217
  288. package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +0 -693
  289. package/.framework/mcp/tools/cil/pipeline.ts +0 -767
  290. package/.framework/mcp/tools/cil/project.ts +0 -791
  291. package/.framework/mcp/tools/cil/retrieval.ts +0 -336
  292. package/.framework/mcp/tools/cil/search-core.ts +0 -454
  293. package/.framework/mcp/tools/cil/search.ts +0 -97
  294. package/.framework/mcp/tools/cil/suggest.ts +0 -186
  295. package/.framework/mcp/tools/cil/validate.ts +0 -1369
  296. package/.framework/mcp/tools/kb/delete.ts +0 -139
  297. package/.framework/mcp/tools/kb/index.ts +0 -52
  298. package/.framework/mcp/tools/kb/ingest.ts +0 -84
  299. package/.framework/mcp/tools/kb/list-types.ts +0 -102
  300. package/.framework/mcp/tools/kb/publish.ts +0 -100
  301. package/.framework/mcp/tools/kb/reindex.ts +0 -86
  302. package/.framework/mcp/tools/kb/revoke.ts +0 -85
  303. package/.framework/mcp/tools/kb/search.ts +0 -101
  304. package/.framework/mcp/tools/kb/upsert.ts +0 -125
  305. package/.framework/mcp/tools/observability.ts +0 -510
@@ -1,431 +0,0 @@
1
- // CIL[BEGIN stable_id="~/.framework/mcp/tools/architect.ts:architect:file" type="file" identity="architect" parent="~/.framework/mcp/tools/architect.ts"]
2
- // CIL[DOC-MACRO purpose="Register architect MCP tools for Spine Way evaluation, design schema validation, and app manifest lookups."]
3
- // CIL[DOC-RESPONSIBILITY responsibility="Expose MCP tools that evaluate proposals against Spine fundamentals, validate design schemas, and query installed app manifests."]
4
- // CIL[DOC-CONTEXT module="mcp" layer="framework" related_files=".framework/mcp/shared/app-manifest.ts,.framework/mcp/shared/db.ts,.framework/mcp/tools/architect.ts"]
5
- // CIL[DOC-CONTRACT inputs="server: McpServer; tool-specific parameters for proposal, primitive, fundamental, design_schema, app slug/id" outputs="JSON content with assessment, placement, validation errors, or app record" errors="Unknown fundamental; invalid design schema; missing app; Supabase query failures" side_effects="Reads public.apps via adminDb; no writes"]
6
- // CIL[DOC-MICRO logic_summary="Registers six tools on the MCP server: evaluate proposals, core-vs-custom placement, get a fundamental, validate a design schema, list apps, and get an app merged with its manifest." notable_decisions="FUNDAMENTALS, DATA_TYPES, and DISPLAY_TYPES are hard-coded local maps; app queries use adminDb with manifest helper functions."]
7
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
- // CIL[DOC-STABILITY stability="stable"]
9
-
10
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
11
- import { z } from 'zod'
12
- import { adminDb } from '../shared/db.js'
13
- import { loadManifest, mergeWithManifest } from '../shared/app-manifest.js'
14
-
15
- export function register(server: McpServer) {
16
- server.registerTool(
17
- 'spine_architect_evaluate',
18
- {
19
- description: 'Evaluate a code or design proposal against the Spine Way fundamentals and return a structured assessment with observations and recommendations.',
20
- inputSchema: z.object({
21
- proposal: z.string().describe('The proposal or change description to evaluate'),
22
- against: z.array(z.string()).optional().describe('Specific fundamental names to evaluate against (optional)'),
23
- }),
24
- },
25
- async ({ proposal, against }) => {
26
-
27
-
28
- const observations = [
29
- 'Core-vs-custom boundary: framework primitives live in .framework/, product-specific behavior lives in custom/apps/.',
30
- 'Design schema completeness: every new runtime type needs fields, views, and record_permissions.',
31
- 'Permission design: record_permissions are the base grant; field permissions are overrides only.',
32
- 'CIL hygiene: code changes are followed by re-syncing CIL chunks, embeddings, and mappings.',
33
- ]
34
-
35
- if (against && against.length > 0) {
36
- // A richer implementation would filter to the requested fundamentals.
37
- }
38
-
39
- return {
40
- content: [{
41
- type: 'text',
42
- text: JSON.stringify({
43
- proposal,
44
- verdict: 'review',
45
- observations,
46
- recommendation: 'Re-read the Spine Way and the design-schema checklist before proceeding.',
47
- }, null, 2),
48
- }],
49
- }
50
- }
51
- )
52
-
53
- server.registerTool(
54
- 'spine_core_vs_custom_check',
55
- {
56
- description: 'Advise whether a change belongs in the core .framework/ layer or a custom app in custom/apps/.',
57
- inputSchema: z.object({
58
- description: z.string().describe('What the change does'),
59
- primitives: z.array(z.string()).optional().describe('Spine primitives it touches (e.g., types, roles, migrations, functions, components)'),
60
- }),
61
- },
62
- async ({ description, primitives }) => {
63
-
64
-
65
- const primitivesList = primitives?.join(', ') || 'none provided'
66
-
67
-
68
-
69
- const lower = (description + ' ' + primitivesList).toLowerCase()
70
-
71
-
72
-
73
-
74
-
75
- let placement = 'custom'
76
-
77
-
78
-
79
-
80
-
81
-
82
- let reason = 'This looks like product-specific behavior that should live in a custom app.'
83
-
84
-
85
- if (
86
- lower.includes('migration') ||
87
- lower.includes('rls') ||
88
- lower.includes('rpc') ||
89
- lower.includes('auth') ||
90
- lower.includes('permission') ||
91
- lower.includes('core primitive') ||
92
- lower.includes('design schema') ||
93
- lower.includes('shared component') ||
94
- lower.includes('admin-data')
95
- ) {
96
- placement = 'core'
97
- reason = 'This change touches framework-level primitives (data model, auth, permissions, migrations, shared runtime, or generic components) and should live in .framework/.'
98
- }
99
-
100
-
101
-
102
-
103
-
104
-
105
- return {
106
- content: [{
107
- type: 'text',
108
- text: JSON.stringify({
109
- description,
110
- primitives: primitivesList,
111
- placement,
112
- reason,
113
- boundary_rule: 'If it could be used by more than one app, it belongs in .framework/; if it is specific to one product workflow, it belongs in custom/apps/.',
114
- }, null, 2),
115
- }],
116
- }
117
- }
118
- )
119
-
120
-
121
-
122
- const FUNDAMENTALS: Record<string, { rule: string; guidance: string }> = {
123
- 'core-never-imports-from-custom': {
124
- rule: 'Core never imports from custom',
125
- guidance: '.framework/ must not contain imports from custom/ or hardcoded custom app slugs. Custom code extends core through data or custom functions.',
126
- },
127
- 'custom-uses-core-aliases': {
128
- rule: 'Custom code uses @core/* aliases, not relative paths into .framework/',
129
- guidance: 'From custom apps: import from "@core/...". From custom functions after assembly: import from "./_shared/...".',
130
- },
131
- 'apps-register-through-public-apps': {
132
- rule: 'Custom apps register through public.apps',
133
- guidance: 'A custom app is defined by a manifest.json, installed via install-app, and represented as a row in public.apps.',
134
- },
135
- 'runtime-crud-through-admin-data': {
136
- rule: 'Runtime record CRUD goes through /api/admin-data',
137
- guidance: 'Use /api/admin-data for items, threads, messages, links, attachments, watchers. Do not write custom Netlify wrappers for runtime CRUD.',
138
- },
139
- 'types-define-behavior-via-design-schema': {
140
- rule: 'Types define behavior via design_schema',
141
- guidance: 'Domain logic belongs in the type\'s design_schema (fields, views, permissions, functionality). validation_schema is generated from it.',
142
- },
143
- 'record-permissions-are-base-grant': {
144
- rule: 'record_permissions are the base grant; field permissions are overrides',
145
- guidance: 'Start with the most restrictive record_permissions per role. Add fields.<name>.permissions only to loosen or further restrict a specific field.',
146
- },
147
- 'rls-enabled-and-correct': {
148
- rule: 'RLS must be enabled with correct policies',
149
- guidance: 'Every tenant/account table must have RLS. Policies use current_actor_id() and get_accessible_accounts(). Use adminDb only when bypassing RLS is necessary.',
150
- },
151
- 'migrations-idempotent-and-ordered': {
152
- rule: 'Migrations are idempotent and ordered',
153
- guidance: 'File naming: NNN_description.sql with unique 3-digit prefixes. Use IF NOT EXISTS, DROP POLICY IF EXISTS, ON CONFLICT DO NOTHING, and conditional DO $$ blocks.',
154
- },
155
- 'field-storage-follows-system-flag': {
156
- rule: 'Field storage follows the system flag',
157
- guidance: 'system: true fields are top-level record columns; non-system fields live inside record.data.<field>. Send payloads accordingly to /api/admin-data.',
158
- },
159
- 'secrets-on-backend-only': {
160
- rule: 'Secrets and service keys stay on the backend',
161
- guidance: 'Browser code uses VITE_SUPABASE_ANON_KEY and VITE_SUPABASE_URL only. Service keys and app secrets never appear in frontend code or committed env files.',
162
- },
163
- }
164
-
165
-
166
-
167
- server.registerTool(
168
- 'spine_get_fundamental',
169
- {
170
- description: 'Return a named Spine Way fundamental rule and guidance.',
171
- inputSchema: z.object({
172
- name: z.string().describe('Fundamental name, e.g. "core-never-imports-from-custom" or "record-permissions-are-base-grant"'),
173
- }),
174
- },
175
- async ({ name }) => {
176
-
177
-
178
- const fundamental = FUNDAMENTALS[name]
179
-
180
- if (!fundamental) {
181
- return {
182
- content: [{
183
- type: 'text',
184
- text: JSON.stringify({
185
- ok: false,
186
- error: `Unknown fundamental: ${name}`,
187
- available: Object.keys(FUNDAMENTALS),
188
- }, null, 2),
189
- }],
190
- }
191
-
192
- }
193
- return {
194
- content: [{
195
- type: 'text',
196
- text: JSON.stringify({ ok: true, name, ...fundamental }, null, 2),
197
- }],
198
- }
199
- }
200
- )
201
-
202
-
203
-
204
- const DATA_TYPES = new Set([
205
- 'text', 'textarea', 'rich_text', 'email', 'phone', 'url', 'number', 'currency', 'range',
206
- 'date', 'datetime', 'boolean', 'checkbox', 'select', 'multiselect', 'radio', 'color',
207
- 'file', 'image', 'json', 'reference', 'address',
208
- ])
209
-
210
-
211
-
212
-
213
- const DISPLAY_TYPES = new Set([
214
- 'text', 'input', 'textarea', 'rich_text', 'select', 'multiselect', 'radio', 'checkbox',
215
- 'switch', 'date_picker', 'datetime_picker', 'color_picker', 'file_upload', 'image_upload',
216
- 'range_slider', 'badge', 'timestamp', 'currency', 'number',
217
- ])
218
-
219
-
220
-
221
- function validateDesignSchema(schema: any): { ok: boolean; errors: string[] } {
222
- const errors: string[] = []
223
- if (!schema || typeof schema !== 'object') {
224
- errors.push('design_schema must be an object')
225
- return { ok: false, errors }
226
- }
227
-
228
-
229
-
230
- const scope = schema.scope ?? 'account'
231
- if (scope !== 'account' && scope !== 'platform') {
232
- errors.push('scope must be "account" or "platform"')
233
- }
234
-
235
- if (!schema.fields || typeof schema.fields !== 'object' || Object.keys(schema.fields).length === 0) {
236
- errors.push('fields is required and must contain at least one field definition')
237
- }
238
-
239
- for (const [key, field] of Object.entries(schema.fields || {})) {
240
- if (!field || typeof field !== 'object') {
241
- errors.push(`fields.${key} must be an object`)
242
- continue
243
- }
244
- const f = field as any
245
- if (!f.data_type) errors.push(`fields.${key} is missing data_type`)
246
- else if (!DATA_TYPES.has(f.data_type)) errors.push(`fields.${key} has unknown data_type: ${f.data_type}`)
247
- if (!f.label) errors.push(`fields.${key} is missing label`)
248
- if (f.required === undefined) errors.push(`fields.${key} is missing required`)
249
- if (['select', 'multiselect', 'radio'].includes(f.data_type) && (!f.options || !Array.isArray(f.options) || f.options.length === 0)) {
250
- errors.push(`fields.${key} (${f.data_type}) requires options`)
251
- }
252
- }
253
-
254
- if (!schema.record_permissions || typeof schema.record_permissions !== 'object') {
255
- errors.push('record_permissions is required')
256
- } else if (!Object.keys(schema.record_permissions).includes('system-admin') && !Object.keys(schema.record_permissions).includes('system_admin')) {
257
- errors.push('record_permissions must grant at least system-admin or system_admin')
258
- }
259
-
260
- if (schema.views) {
261
- if (schema.views.default_list) {
262
- const list = schema.views.default_list
263
- if (list.type !== 'list') errors.push('views.default_list.type must be "list"')
264
- if (!list.fields || typeof list.fields !== 'object') errors.push('views.default_list.fields is required')
265
- if (!list.default_sort) errors.push('views.default_list.default_sort is required')
266
- }
267
- if (schema.views.default_detail) {
268
- const detail = schema.views.default_detail
269
- if (detail.type !== 'detail') errors.push('views.default_detail.type must be "detail"')
270
- }
271
- }
272
-
273
- return { ok: errors.length === 0, errors }
274
- }
275
-
276
- server.registerTool(
277
- 'spine_design_schema_validate',
278
- {
279
- description: 'Validate a proposed design_schema against the Spine design-schema rules. Returns ok and a list of errors.',
280
- inputSchema: z.object({
281
- design_schema: z.record(z.any()).describe('The design_schema object to validate'),
282
- check_views: z.boolean().default(true).optional().describe('Whether to require default_list and default_detail views'),
283
- }),
284
- },
285
- async ({ design_schema, check_views }) => {
286
-
287
-
288
- const result = validateDesignSchema(design_schema)
289
-
290
- if (check_views && !design_schema.views) {
291
- result.errors.push('views is required when check_views is true')
292
- }
293
-
294
- if (design_schema.views) {
295
- if (check_views && !design_schema.views.default_list) result.errors.push('views.default_list is required')
296
- if (check_views && !design_schema.views.default_detail) result.errors.push('views.default_detail is required')
297
- for (const [viewName, view] of Object.entries(design_schema.views || {})) {
298
-
299
-
300
- const v = view as any
301
-
302
- if (!v || typeof v !== 'object') continue
303
- for (const [fieldName, field] of Object.entries(v.fields || {})) {
304
-
305
-
306
- const f = field as any
307
-
308
- if (f && f.display_type && !DISPLAY_TYPES.has(f.display_type)) {
309
- result.errors.push(`views.${viewName}.fields.${fieldName} has unknown display_type: ${f.display_type}`)
310
- }
311
-
312
-
313
- }
314
- if (v.sections) {
315
- for (const section of v.sections) {
316
- for (const [fieldName, field] of Object.entries(section.fields || {})) {
317
-
318
-
319
- const f = field as any
320
-
321
- if (f && f.display_type && !DISPLAY_TYPES.has(f.display_type)) {
322
- result.errors.push(`views.${viewName}.sections.*.fields.${fieldName} has unknown display_type: ${f.display_type}`)
323
- }
324
-
325
- }
326
- }
327
- }
328
- }
329
- }
330
- return {
331
- content: [{
332
- type: 'text',
333
- text: JSON.stringify({
334
- ok: result.ok && result.errors.length === 0,
335
- error_count: result.errors.length,
336
- errors: result.errors,
337
- }, null, 2),
338
- }],
339
- }
340
- }
341
- )
342
-
343
- server.registerTool(
344
- 'spine_app_manifest_list',
345
- {
346
- description: 'List installed apps from the public.apps table.',
347
- inputSchema: z.object({
348
- include_manifest: z.boolean().default(false).optional().describe('Load and include each app manifest.json content'),
349
- }),
350
- },
351
- async ({ include_manifest }) => {
352
- const { data, error } = await adminDb.from('apps').select('id, slug, name, description, app_type, renderer, manifest_path, is_active, route_prefix').order('name')
353
- if (error) {
354
- return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: error.message }) }] }
355
- }
356
-
357
-
358
-
359
- const apps = (data || []).map((app: any) => {
360
- const base = {
361
- id: app.id,
362
- slug: app.slug,
363
- name: app.name,
364
- description: app.description || '',
365
- app_type: app.app_type || '',
366
- renderer: app.renderer || '',
367
- manifest_path: app.manifest_path || '',
368
- is_active: app.is_active ?? true,
369
- route_prefix: app.route_prefix || '',
370
- }
371
- if (include_manifest && app.manifest_path) {
372
- const manifest = loadManifest(app.manifest_path)
373
- return { ...base, manifest: manifest || null }
374
- }
375
- return base
376
- })
377
-
378
-
379
- return { content: [{ type: 'text', text: JSON.stringify({ ok: true, count: apps.length, apps }, null, 2) }] }
380
- }
381
-
382
- )
383
-
384
- server.registerTool(
385
- 'spine_app_manifest_get',
386
- {
387
- description: 'Get one installed app by slug or id, optionally merged with its manifest.json.',
388
- inputSchema: z.object({
389
- slug: z.string().optional().describe('App slug'),
390
- id: z.string().uuid().optional().describe('App UUID'),
391
- }),
392
- },
393
- async ({ slug, id }) => {
394
- if (!slug && !id) {
395
- return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: 'Provide either slug or id' }) }] }
396
- }
397
-
398
-
399
-
400
-
401
- let query = adminDb.from('apps').select('*')
402
-
403
-
404
- if (id) query = query.eq('id', id)
405
- else query = query.eq('slug', slug)
406
- const { data, error } = await query.maybeSingle()
407
- if (error) {
408
- return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: error.message }) }] }
409
- }
410
-
411
-
412
- if (!data) {
413
- return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: `App not found: ${slug || id}` }) }] }
414
- }
415
-
416
-
417
- const merged = mergeWithManifest(data)
418
-
419
- return { content: [{ type: 'text', text: JSON.stringify({ ok: true, app: merged }, null, 2) }] }
420
- }
421
-
422
- )
423
- }
424
-
425
- // CIL[DOC-VECTOR type="context" content="purpose='Register architect MCP tools for Spine Way evaluation, design schema validation, and app manifest lookups.'; No verified external callers; imports: .framework/mcp/shared/db.ts,.framework/mcp/shared/app-manifest.ts"]
426
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
427
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
428
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
429
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
430
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
431
- // CIL[END stable_id="~/.framework/mcp/tools/architect.ts:architect:file"]