spine-framework 0.4.4 → 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 (283) 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/hash-api-key.ts +183 -79
  15. package/.framework/functions/_shared/logging.ts +562 -224
  16. package/.framework/functions/_shared/middleware.ts +47 -44
  17. package/.framework/functions/admin-data.ts +39 -28
  18. package/.framework/functions/ai-agents.ts +10 -6
  19. package/.framework/functions/api-keys.ts +301 -122
  20. package/.framework/functions/apps.ts +43 -26
  21. package/.framework/functions/cil-ingest.ts +48 -15
  22. package/.framework/functions/debug-auth.ts +14 -8
  23. package/.framework/functions/deliveries.ts +39 -12
  24. package/.framework/functions/embeddings.ts +145 -76
  25. package/.framework/functions/integration-outbound.ts +67 -27
  26. package/.framework/functions/integrations.ts +254 -127
  27. package/.framework/functions/logs.ts +273 -133
  28. package/.framework/functions/observability.ts +277 -147
  29. package/.framework/functions/pipeline-executions.ts +1 -1
  30. package/.framework/functions/pipelines.ts +14 -9
  31. package/.framework/functions/prompt-configs.ts +7 -4
  32. package/.framework/functions/roles.ts +8 -5
  33. package/.framework/functions/security.ts +30 -17
  34. package/.framework/functions/system-cron.ts +240 -127
  35. package/.framework/functions/tests.ts +7 -6
  36. package/.framework/functions/timers.ts +310 -107
  37. package/.framework/functions/triggers.ts +28 -13
  38. package/.framework/functions/types.ts +13 -10
  39. package/.framework/migrations/069_log_stats_window.sql +54 -0
  40. package/.framework/migrations/070_app_type_schema_rpcs.sql +166 -0
  41. package/.framework/migrations/071_timer_interval_keys.sql +96 -0
  42. package/.framework/migrations/072_slug_autofill.sql +77 -0
  43. package/.framework/migrations/073_seed_member_roles.sql +26 -0
  44. package/.framework/src/apps/admin/index.tsx +1141 -775
  45. package/.framework/src/components/ErrorBoundary.tsx +136 -0
  46. package/.framework/src/components/admin/AdminListPage.tsx +81 -73
  47. package/.framework/src/components/admin/AdminSidebar.tsx +88 -79
  48. package/.framework/src/components/admin/EntitySelect.tsx +181 -0
  49. package/.framework/src/components/admin/PageInstructions.tsx +86 -127
  50. package/.framework/src/components/app-shell/GenericDetailPage.tsx +37 -13
  51. package/.framework/src/components/app-shell/GenericListPage.tsx +28 -32
  52. package/.framework/src/components/layout/Sidebar.tsx +300 -177
  53. package/.framework/src/components/runtime/DataDetailPage.tsx +67 -35
  54. package/.framework/src/components/runtime/DataHeader.tsx +96 -48
  55. package/.framework/src/components/runtime/DataListPage.tsx +3 -26
  56. package/.framework/src/components/runtime/DataStats.tsx +10 -10
  57. package/.framework/src/components/runtime/DataTable.tsx +12 -10
  58. package/.framework/src/components/ui/sheet.tsx +24 -26
  59. package/.framework/src/components/ui/textarea.tsx +74 -48
  60. package/.framework/src/hooks/useEntityList.ts +12 -9
  61. package/.framework/src/hooks/useListSchema.ts +108 -58
  62. package/.framework/src/instructions/README.md +57 -0
  63. package/.framework/src/instructions/ai-agents.md +69 -0
  64. package/.framework/src/instructions/alerts.md +80 -0
  65. package/.framework/src/instructions/api-keys.md +87 -0
  66. package/.framework/src/instructions/apps.md +77 -0
  67. package/.framework/src/instructions/concepts/ai-and-prompts.md +150 -0
  68. package/.framework/src/instructions/concepts/apps-and-renderers.md +162 -0
  69. package/.framework/src/instructions/concepts/auth-and-api-keys.md +133 -0
  70. package/.framework/src/instructions/concepts/automation.md +186 -0
  71. package/.framework/src/instructions/concepts/concurrency-and-idempotency.md +125 -0
  72. package/.framework/src/instructions/concepts/core-vs-custom.md +124 -0
  73. package/.framework/src/instructions/concepts/design-schema.md +152 -0
  74. package/.framework/src/instructions/concepts/integrations-and-webhooks.md +127 -0
  75. package/.framework/src/instructions/concepts/observability.md +116 -0
  76. package/.framework/src/instructions/concepts/permissions.md +150 -0
  77. package/.framework/src/instructions/concepts/runtime-records.md +111 -0
  78. package/.framework/src/instructions/concepts/scope-and-accounts.md +112 -0
  79. package/.framework/src/instructions/concepts/spine-way.md +172 -0
  80. package/.framework/src/instructions/deliveries.md +59 -0
  81. package/.framework/src/instructions/guide/00-orientation.md +106 -0
  82. package/.framework/src/instructions/guide/01-install-and-first-run.md +253 -0
  83. package/.framework/src/instructions/guide/02-project-map.md +147 -0
  84. package/.framework/src/instructions/guide/03-domain-model.md +223 -0
  85. package/.framework/src/instructions/guide/04-first-app.md +227 -0
  86. package/.framework/src/instructions/guide/05-glossary.md +183 -0
  87. package/.framework/src/instructions/integrations.md +96 -0
  88. package/.framework/src/instructions/internal/cil-markers.md +83 -0
  89. package/.framework/src/instructions/invites.md +60 -0
  90. package/.framework/src/instructions/kb.md +80 -0
  91. package/.framework/src/instructions/logs.md +77 -0
  92. package/.framework/src/instructions/observability.md +61 -0
  93. package/.framework/src/instructions/operations/deployment.md +115 -0
  94. package/.framework/src/instructions/operations/migrations.md +125 -0
  95. package/.framework/src/instructions/operations/security-checklist.md +148 -0
  96. package/.framework/src/instructions/operations/troubleshooting.md +170 -0
  97. package/.framework/src/instructions/operations/upgrade.md +116 -0
  98. package/.framework/src/instructions/pipeline-executions.md +62 -0
  99. package/.framework/src/instructions/pipelines.md +78 -0
  100. package/.framework/src/instructions/prompts.md +95 -0
  101. package/.framework/src/instructions/reference/api/admin-data.md +162 -0
  102. package/.framework/src/instructions/reference/api/auth.md +113 -0
  103. package/.framework/src/instructions/reference/api/errors-and-envelopes.md +113 -0
  104. package/.framework/src/instructions/reference/app-manifest.md +150 -0
  105. package/.framework/src/instructions/reference/cli.md +124 -0
  106. package/.framework/src/instructions/reference/database.md +132 -0
  107. package/.framework/src/instructions/reference/design-schema.md +280 -0
  108. package/.framework/src/instructions/reference/env-vars.md +133 -0
  109. package/.framework/src/instructions/reference/functions/account-nodes.md +75 -0
  110. package/.framework/src/instructions/reference/functions/admin-data.md +195 -0
  111. package/.framework/src/instructions/reference/functions/admin-funnel.md +90 -0
  112. package/.framework/src/instructions/reference/functions/admin-install-funnel.md +107 -0
  113. package/.framework/src/instructions/reference/functions/admin-signals.md +102 -0
  114. package/.framework/src/instructions/reference/functions/ai-agents.md +148 -0
  115. package/.framework/src/instructions/reference/functions/ai-interactions.md +156 -0
  116. package/.framework/src/instructions/reference/functions/api-keys.md +130 -0
  117. package/.framework/src/instructions/reference/functions/apps.md +140 -0
  118. package/.framework/src/instructions/reference/functions/auth.md +99 -0
  119. package/.framework/src/instructions/reference/functions/debug-auth.md +91 -0
  120. package/.framework/src/instructions/reference/functions/deliveries.md +110 -0
  121. package/.framework/src/instructions/reference/functions/embeddings.md +166 -0
  122. package/.framework/src/instructions/reference/functions/eval-harness.md +149 -0
  123. package/.framework/src/instructions/reference/functions/index.md +103 -0
  124. package/.framework/src/instructions/reference/functions/integration-outbound.md +200 -0
  125. package/.framework/src/instructions/reference/functions/integration-routes.md +151 -0
  126. package/.framework/src/instructions/reference/functions/integrations.md +130 -0
  127. package/.framework/src/instructions/reference/functions/invites.md +182 -0
  128. package/.framework/src/instructions/reference/functions/item-progress.md +107 -0
  129. package/.framework/src/instructions/reference/functions/kb.md +166 -0
  130. package/.framework/src/instructions/reference/functions/logs.md +141 -0
  131. package/.framework/src/instructions/reference/functions/observability.md +105 -0
  132. package/.framework/src/instructions/reference/functions/pipeline-executions.md +132 -0
  133. package/.framework/src/instructions/reference/functions/pipeline-runner-background.md +121 -0
  134. package/.framework/src/instructions/reference/functions/pipelines.md +136 -0
  135. package/.framework/src/instructions/reference/functions/prompt-configs.md +121 -0
  136. package/.framework/src/instructions/reference/functions/roles.md +121 -0
  137. package/.framework/src/instructions/reference/functions/security.md +140 -0
  138. package/.framework/src/instructions/reference/functions/system-cron.md +136 -0
  139. package/.framework/src/instructions/reference/functions/system.md +106 -0
  140. package/.framework/src/instructions/reference/functions/tests.md +97 -0
  141. package/.framework/src/instructions/reference/functions/timers.md +117 -0
  142. package/.framework/src/instructions/reference/functions/trigger-scheduler.md +102 -0
  143. package/.framework/src/instructions/reference/functions/triggers.md +140 -0
  144. package/.framework/src/instructions/reference/functions/types.md +146 -0
  145. package/.framework/src/instructions/reference/seeds.md +126 -0
  146. package/.framework/src/instructions/reference/shared-modules.md +127 -0
  147. package/.framework/src/instructions/reference/spine-config.md +114 -0
  148. package/.framework/src/instructions/roles.md +80 -0
  149. package/.framework/src/instructions/runtime-detail.md +70 -0
  150. package/.framework/src/instructions/runtime-list.md +77 -0
  151. package/.framework/src/instructions/security.md +67 -0
  152. package/.framework/src/instructions/tasks/add-a-pipeline.md +110 -0
  153. package/.framework/src/instructions/tasks/add-a-role.md +96 -0
  154. package/.framework/src/instructions/tasks/add-a-timer.md +114 -0
  155. package/.framework/src/instructions/tasks/add-a-trigger.md +106 -0
  156. package/.framework/src/instructions/tasks/add-a-type.md +151 -0
  157. package/.framework/src/instructions/tasks/add-a-webhook.md +108 -0
  158. package/.framework/src/instructions/tasks/add-an-ai-agent.md +108 -0
  159. package/.framework/src/instructions/tasks/add-an-integration.md +124 -0
  160. package/.framework/src/instructions/tasks/build-a-custom-page.md +118 -0
  161. package/.framework/src/instructions/tasks/package-and-install-an-app.md +127 -0
  162. package/.framework/src/instructions/tasks/test-your-code.md +108 -0
  163. package/.framework/src/instructions/tasks/write-a-function.md +132 -0
  164. package/.framework/src/instructions/tasks/write-a-migration.md +110 -0
  165. package/.framework/src/instructions/testing.md +59 -0
  166. package/.framework/src/instructions/timers.md +82 -0
  167. package/.framework/src/instructions/triggers.md +69 -0
  168. package/.framework/src/instructions/types.md +93 -0
  169. package/.framework/src/pages/NotFoundPage.tsx +62 -31
  170. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +117 -106
  171. package/.framework/src/pages/admin/AIAgentsPage.tsx +86 -48
  172. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +153 -152
  173. package/.framework/src/pages/admin/APIKeysPage.tsx +91 -90
  174. package/.framework/src/pages/admin/AlertsConfigPage.tsx +29 -18
  175. package/.framework/src/pages/admin/AppDetailPage.tsx +6 -60
  176. package/.framework/src/pages/admin/AppsPage.tsx +104 -66
  177. package/.framework/src/pages/admin/DeliveriesPage.tsx +5 -5
  178. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +5 -23
  179. package/.framework/src/pages/admin/EmbeddingsPage.tsx +5 -26
  180. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +7 -7
  181. package/.framework/src/pages/admin/IntegrationsPage.tsx +85 -43
  182. package/.framework/src/pages/admin/LogsPage.tsx +144 -76
  183. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +223 -140
  184. package/.framework/src/pages/admin/PipelineDetailPage.tsx +134 -113
  185. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +108 -45
  186. package/.framework/src/pages/admin/PipelinesPage.tsx +160 -115
  187. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +96 -98
  188. package/.framework/src/pages/admin/PromptConfigsPage.tsx +101 -59
  189. package/.framework/src/pages/admin/RoleDetailPage.tsx +90 -79
  190. package/.framework/src/pages/admin/RolesPage.tsx +86 -43
  191. package/.framework/src/pages/admin/SecurityPage.tsx +1 -1
  192. package/.framework/src/pages/admin/TestingDashboard.tsx +16 -28
  193. package/.framework/src/pages/admin/TimerDetailPage.tsx +117 -100
  194. package/.framework/src/pages/admin/TimersPage.tsx +90 -62
  195. package/.framework/src/pages/admin/TriggerDetailPage.tsx +90 -83
  196. package/.framework/src/pages/admin/TriggersPage.tsx +124 -99
  197. package/.framework/src/pages/admin/TypeDetailPage.tsx +152 -138
  198. package/.framework/src/pages/admin/TypesPage.tsx +90 -48
  199. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +17 -25
  200. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +17 -27
  201. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +72 -40
  202. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +321 -129
  203. package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +18 -29
  204. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +26 -38
  205. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +34 -46
  206. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +189 -103
  207. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +246 -136
  208. package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +11 -22
  209. package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +9 -20
  210. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +26 -38
  211. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +7 -26
  212. package/.framework/templates/agent/AGENTS.md +150 -0
  213. package/.framework/templates/agent/skills/spine-add-ai-agent/SKILL.md +58 -0
  214. package/.framework/templates/agent/skills/spine-add-automation/SKILL.md +62 -0
  215. package/.framework/templates/agent/skills/spine-add-integration/SKILL.md +63 -0
  216. package/.framework/templates/agent/skills/spine-architect/SKILL.md +86 -0
  217. package/.framework/templates/agent/skills/spine-install-app/SKILL.md +72 -0
  218. package/.framework/templates/agent/skills/spine-migration/SKILL.md +75 -0
  219. package/.framework/templates/agent/skills/spine-new-app/SKILL.md +67 -0
  220. package/.framework/templates/agent/skills/spine-new-function/SKILL.md +65 -0
  221. package/.framework/templates/agent/skills/spine-new-type/SKILL.md +65 -0
  222. package/.framework/templates/agent/skills/spine-schema/SKILL.md +77 -0
  223. package/.framework/templates/agent/skills/spine-test/SKILL.md +67 -0
  224. package/.framework/templates/agent/skills/spine-troubleshoot/SKILL.md +74 -0
  225. package/.framework/templates/agent/skills/spine-upgrade/SKILL.md +69 -0
  226. package/.framework/templates/project.json +4 -1
  227. package/.framework/tests/unit/account-scoping-gates.test.ts +392 -0
  228. package/.framework/tests/unit/agent-files.test.ts +355 -0
  229. package/.framework/tests/unit/agent-runner.test.ts +479 -44
  230. package/.framework/tests/unit/api-keys-create-scope-gate.test.ts +160 -0
  231. package/.framework/tests/unit/api-keys-omit-secret-fields.test.ts +38 -0
  232. package/.framework/tests/unit/bootstrap.test.ts +242 -0
  233. package/.framework/tests/unit/cli-context-api-key.test.ts +114 -0
  234. package/.framework/tests/unit/debug-auth.test.ts +38 -0
  235. package/.framework/tests/unit/deliveries-account-scoping.test.ts +185 -0
  236. package/.framework/tests/unit/integration-outbound-credentials.test.ts +167 -0
  237. package/.framework/tests/unit/integrations-audit-redaction.test.ts +130 -0
  238. package/.framework/tests/unit/logging-app-id.test.ts +75 -0
  239. package/.framework/tests/unit/system-context-denial.test.ts +145 -0
  240. package/.framework/tests/unit/system-cron.test.ts +240 -0
  241. package/.framework/tests/unit/timers.test.ts +159 -0
  242. package/README.md +125 -166
  243. package/config/tsconfig.cli.json +2 -2
  244. package/package.json +15 -4
  245. package/templates/project/package-lock.json +2 -2
  246. package/.framework/docs/admin-routes.md +0 -76
  247. package/.framework/docs/api-docs-progress.md +0 -38
  248. package/.framework/docs/api-governance.md +0 -146
  249. package/.framework/docs/api-testing-results.md +0 -212
  250. package/.framework/docs/assembly-launch-guide.md +0 -138
  251. package/.framework/docs/audit-results.md +0 -590
  252. package/.framework/docs/db-api-inventory.md +0 -95
  253. package/.framework/docs/gap-remediation-backlog.md +0 -103
  254. package/.framework/docs/ui-adoption-verification.md +0 -111
  255. package/.framework/docs/ui-api-coverage.md +0 -84
  256. package/.framework/docs/v2-compatibility-audit.md +0 -228
  257. package/.framework/mcp/index.ts +0 -133
  258. package/.framework/mcp/load-env.ts +0 -60
  259. package/.framework/mcp/shared/app-manifest.ts +0 -275
  260. package/.framework/mcp/shared/db.ts +0 -477
  261. package/.framework/mcp/shared/kb.ts +0 -118
  262. package/.framework/mcp/tools/architect.ts +0 -431
  263. package/.framework/mcp/tools/cil/context.ts +0 -345
  264. package/.framework/mcp/tools/cil/graph.ts +0 -242
  265. package/.framework/mcp/tools/cil/ingest.ts +0 -1217
  266. package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +0 -693
  267. package/.framework/mcp/tools/cil/pipeline.ts +0 -767
  268. package/.framework/mcp/tools/cil/project.ts +0 -791
  269. package/.framework/mcp/tools/cil/retrieval.ts +0 -336
  270. package/.framework/mcp/tools/cil/search-core.ts +0 -454
  271. package/.framework/mcp/tools/cil/search.ts +0 -97
  272. package/.framework/mcp/tools/cil/suggest.ts +0 -186
  273. package/.framework/mcp/tools/cil/validate.ts +0 -1369
  274. package/.framework/mcp/tools/kb/delete.ts +0 -139
  275. package/.framework/mcp/tools/kb/index.ts +0 -52
  276. package/.framework/mcp/tools/kb/ingest.ts +0 -84
  277. package/.framework/mcp/tools/kb/list-types.ts +0 -102
  278. package/.framework/mcp/tools/kb/publish.ts +0 -100
  279. package/.framework/mcp/tools/kb/reindex.ts +0 -86
  280. package/.framework/mcp/tools/kb/revoke.ts +0 -85
  281. package/.framework/mcp/tools/kb/search.ts +0 -101
  282. package/.framework/mcp/tools/kb/upsert.ts +0 -125
  283. 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"]