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
@@ -20,6 +20,8 @@ import {
20
20
  mergePackageJson,
21
21
  writeFrozenManifest,
22
22
  sanitizePackageName,
23
+ syncAgentFiles,
24
+ collectAgentFileHashes,
23
25
  } from '../lib/project-files.ts'
24
26
  // CIL[END stable_id="~/.framework/cli/commands/init.ts:module_header:module_header"]
25
27
 
@@ -137,11 +139,23 @@ export function registerInitCommands(program: Command) {
137
139
  console.log(' ✓ spine.config.json written (neutral template)')
138
140
  }
139
141
 
140
- // 8. Frozen integrity manifest — version + framework-owned dep inventory
142
+ // 8. Agent assets — AGENTS.md framework block + .devin/skills/spine-*
143
+ const agentActions = syncAgentFiles({
144
+ pkgRoot: PACKAGE_ROOT,
145
+ projectRoot: target,
146
+ entries: profile.agent_files ?? [],
147
+ version: frameworkVersion,
148
+ })
149
+ for (const a of agentActions) {
150
+ console.log(` ✓ ${a.rel} (${a.action}${a.detail ? ` — ${a.detail}` : ''})`)
151
+ }
152
+
153
+ // 9. Frozen integrity manifest — version + framework-owned dep inventory
141
154
  const manifest = writeFrozenManifest({
142
155
  projectRoot: target,
143
156
  frameworkVersion,
144
157
  frameworkDeps: merged.frameworkDeps,
158
+ agentFiles: collectAgentFileHashes(target, profile.agent_files ?? []),
145
159
  })
146
160
  console.log(` ✓ .spine-manifest.json written (${manifest.fileCount} protected files, frozen)`)
147
161
 
@@ -158,6 +172,11 @@ export function registerInitCommands(program: Command) {
158
172
  console.log(' 5. npx spine-framework migrate')
159
173
  console.log(' 6. npm run dev:netlify')
160
174
  console.log()
175
+ console.log('Docs + agent assets:')
176
+ console.log(' - Instruction book: .framework/src/instructions/README.md')
177
+ console.log(' - Agent rules: AGENTS.md (framework block refreshes on upgrade)')
178
+ console.log(' - Agent skills: .devin/skills/spine-*')
179
+ console.log()
161
180
  } catch (err: any) {
162
181
  console.error('\n❌ Init failed:', err.message)
163
182
  if (process.env.SPINE_CLI_DEBUG) console.error(err.stack)
@@ -22,15 +22,14 @@ import type { Command } from 'commander'
22
22
  import { existsSync, readdirSync, readFileSync } from 'fs'
23
23
  import { resolve, dirname, join } from 'path'
24
24
  import { fileURLToPath } from 'url'
25
+ // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:module_header:module_header"]
25
26
  // CIL[DOC-VECTOR type="context" content="purpose='Provides the migrate command for applying database migrations to a Supabase project.'; No verified external callers; imports: none"]
26
27
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
27
28
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
28
29
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
29
30
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
30
31
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
31
- // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:module_header:module_header"]
32
32
 
33
- // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:__filename:constant" type="constant" identity="__filename" parent="~/.framework/cli/commands/migrate.ts"]
34
33
  // CIL[DOC-MACRO purpose="Defines the current module file path."]
35
34
  // CIL[DOC-RESPONSIBILITY responsibility="Derives __filename from the module import meta URL."]
36
35
  // CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
@@ -39,6 +38,7 @@ import { fileURLToPath } from 'url'
39
38
  // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
40
39
  // CIL[DOC-MICRO logic_summary="Converts import.meta.url to a file path and assigns to __filename." notable_decisions="none"]
41
40
  // CIL[DOC-AUDIENCE audience="engineers"]
41
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:__filename:constant" type="constant" identity="__filename" parent="~/.framework/cli/commands/migrate.ts"]
42
42
  const __filename = fileURLToPath(import.meta.url)
43
43
  // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:__filename:constant"]
44
44
  // CIL[DOC-CONTEXT module="unknown" layer="unknown" related_files=".framework/cli/commands/migrate.ts"]
@@ -48,7 +48,6 @@ const __filename = fileURLToPath(import.meta.url)
48
48
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
49
49
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
50
50
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
51
- // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:__dirname:constant" type="constant" identity="__dirname" parent="~/.framework/cli/commands/migrate.ts"]
52
51
  // CIL[DOC-MACRO purpose="Defines the current module directory."]
53
52
  // CIL[DOC-RESPONSIBILITY responsibility="Derives __dirname from __filename."]
54
53
  // CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
@@ -57,9 +56,9 @@ const __filename = fileURLToPath(import.meta.url)
57
56
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
58
57
  // CIL[DOC-MICRO logic_summary="Computes the directory of the current file and assigns to __dirname." notable_decisions="none"]
59
58
  // CIL[DOC-AUDIENCE audience="engineers"]
59
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:__dirname:constant" type="constant" identity="__dirname" parent="~/.framework/cli/commands/migrate.ts"]
60
60
  const __dirname = dirname(__filename)
61
61
  // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:__dirname:constant"]
62
- // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:PACKAGE_ROOT:constant" type="constant" identity="PACKAGE_ROOT" parent="~/.framework/cli/commands/migrate.ts"]
63
62
  // CIL[DOC-VECTOR type="context" content="purpose='Defines the current module directory.'; No verified external callers; imports: none"]
64
63
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
65
64
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
@@ -74,6 +73,7 @@ const __dirname = dirname(__filename)
74
73
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
75
74
  // CIL[DOC-STABILITY stability="stable"]
76
75
  // CIL[DOC-AUDIENCE audience="engineers"]
76
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:PACKAGE_ROOT:constant" type="constant" identity="PACKAGE_ROOT" parent="~/.framework/cli/commands/migrate.ts"]
77
77
  const PACKAGE_ROOT = resolve(__dirname, '../../../')
78
78
  // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:PACKAGE_ROOT:constant"]
79
79
  // CIL[DOC-VECTOR type="context" content="purpose='Defines the package root path.'; No verified external callers; imports: none"]
@@ -82,7 +82,6 @@ const PACKAGE_ROOT = resolve(__dirname, '../../../')
82
82
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
83
83
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
84
84
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
85
- // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:PROJECT_ROOT:constant" type="constant" identity="PROJECT_ROOT" parent="~/.framework/cli/commands/migrate.ts"]
86
85
  // CIL[DOC-MACRO purpose="Defines the project root path."]
87
86
  // CIL[DOC-RESPONSIBILITY responsibility="Uses the current working directory as the project root."]
88
87
  // CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
@@ -91,17 +90,17 @@ const PACKAGE_ROOT = resolve(__dirname, '../../../')
91
90
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
92
91
  // CIL[DOC-STABILITY stability="stable"]
93
92
  // CIL[DOC-AUDIENCE audience="engineers"]
93
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:PROJECT_ROOT:constant" type="constant" identity="PROJECT_ROOT" parent="~/.framework/cli/commands/migrate.ts"]
94
94
  const PROJECT_ROOT = process.cwd()
95
+ // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:PROJECT_ROOT:constant"]
95
96
  // CIL[DOC-VECTOR type="context" content="purpose='Defines the project root path.'; No verified external callers; imports: none"]
96
97
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
97
98
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
98
99
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
99
100
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
100
101
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
101
- // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:PROJECT_ROOT:constant"]
102
102
 
103
103
 
104
- // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:MigrateOptions:interface" type="interface" identity="MigrateOptions" parent="~/.framework/cli/commands/migrate.ts"]
105
104
  // CIL[DOC-MACRO purpose="Declares the migrate command options."]
106
105
  // CIL[DOC-RESPONSIBILITY responsibility="Types the CLI flags and optional db password."]
107
106
  // CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
@@ -110,20 +109,20 @@ const PROJECT_ROOT = process.cwd()
110
109
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
111
110
  // CIL[DOC-STABILITY stability="stable"]
112
111
  // CIL[DOC-AUDIENCE audience="engineers"]
112
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:MigrateOptions:interface" type="interface" identity="MigrateOptions" parent="~/.framework/cli/commands/migrate.ts"]
113
113
  interface MigrateOptions {
114
114
  dbPassword?: string
115
115
  dryRun: boolean
116
116
  frameworkOnly: boolean
117
117
  }
118
+ // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:MigrateOptions:interface"]
118
119
  // CIL[DOC-VECTOR type="context" content="purpose='Declares the migrate command options.'; No verified external callers; imports: none"]
119
120
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
120
121
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
121
122
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
122
123
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
123
124
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
124
- // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:MigrateOptions:interface"]
125
125
 
126
- // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:runMigrations:function" type="function" identity="runMigrations" parent="~/.framework/cli/commands/migrate.ts"]
127
126
  // CIL[DOC-MACRO purpose="Applies pending SQL migration files to the Supabase database and tracks which have been applied."]
128
127
  // CIL[DOC-RESPONSIBILITY responsibility="Executes migrations safely in transactions and records them in the tracking table."]
129
128
  // CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
@@ -132,6 +131,7 @@ interface MigrateOptions {
132
131
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
133
132
  // CIL[DOC-STABILITY stability="stable"]
134
133
  // CIL[DOC-AUDIENCE audience="engineers"]
134
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:runMigrations:function" type="function" identity="runMigrations" parent="~/.framework/cli/commands/migrate.ts"]
135
135
  export async function runMigrations(opts: { frameworkOnly?: boolean } = {}): Promise<{ applied: number; skipped: number; failed: number } | null> {
136
136
  const supabaseUrl = process.env.SUPABASE_URL
137
137
  if (!supabaseUrl || supabaseUrl.includes('placeholder') || supabaseUrl.includes('your-project')) {
@@ -139,7 +139,7 @@ export async function runMigrations(opts: { frameworkOnly?: boolean } = {}): Pro
139
139
  }
140
140
 
141
141
  const dbPassword = process.env.SUPABASE_DB_PASSWORD
142
- if (!dbPassword) {
142
+ if (!dbPassword && !process.env.SUPABASE_DB_URL) {
143
143
  return null
144
144
  }
145
145
 
@@ -167,13 +167,17 @@ export async function runMigrations(opts: { frameworkOnly?: boolean } = {}): Pro
167
167
  if (migrationFiles.length === 0) return { applied: 0, skipped: 0, failed: 0 }
168
168
 
169
169
  const { default: pg } = await import('pg')
170
- const client = new pg.Client({
171
- user: 'postgres',
172
- password: dbPassword,
173
- host: `db.${projectRef}.supabase.co`,
174
- port: 5432,
175
- database: 'postgres',
176
- })
170
+ const client = new pg.Client(
171
+ process.env.SUPABASE_DB_URL
172
+ ? { connectionString: process.env.SUPABASE_DB_URL }
173
+ : {
174
+ user: 'postgres',
175
+ password: dbPassword,
176
+ host: `db.${projectRef}.supabase.co`,
177
+ port: 5432,
178
+ database: 'postgres',
179
+ }
180
+ )
177
181
  await client.connect()
178
182
 
179
183
  let applied = 0, skipped = 0, failed = 0
@@ -224,15 +228,14 @@ export async function runMigrations(opts: { frameworkOnly?: boolean } = {}): Pro
224
228
 
225
229
  return { applied, skipped, failed }
226
230
  }
231
+ // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:runMigrations:function"]
227
232
  // CIL[DOC-VECTOR type="context" content="purpose='Applies pending SQL migration files to the Supabase database and tracks which have been applied.'; No verified external callers; imports: none"]
228
233
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
229
234
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
230
235
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
231
236
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
232
237
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
233
- // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:runMigrations:function"]
234
238
 
235
- // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:migrateCommand:function" type="function" identity="migrateCommand" parent="~/.framework/cli/commands/migrate.ts"]
236
239
  // CIL[DOC-MACRO purpose="CLI action that collects, optionally dry-runs, and applies framework migrations."]
237
240
  // CIL[DOC-RESPONSIBILITY responsibility="Validates environment, loads .env, handles dry run, and prints result."]
238
241
  // CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
@@ -241,6 +244,7 @@ export async function runMigrations(opts: { frameworkOnly?: boolean } = {}): Pro
241
244
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
242
245
  // CIL[DOC-STABILITY stability="stable"]
243
246
  // CIL[DOC-AUDIENCE audience="engineers"]
247
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:migrateCommand:function" type="function" identity="migrateCommand" parent="~/.framework/cli/commands/migrate.ts"]
244
248
  async function migrateCommand(options: MigrateOptions): Promise<void> {
245
249
  console.log('\nRunning Spine Framework migrations...\n')
246
250
 
@@ -265,13 +269,14 @@ async function migrateCommand(options: MigrateOptions): Promise<void> {
265
269
  }
266
270
 
267
271
  const dbPassword = options.dbPassword || process.env.SUPABASE_DB_PASSWORD
268
- if (!dbPassword) {
272
+ if (!dbPassword && !process.env.SUPABASE_DB_URL) {
269
273
  console.error('❌ SUPABASE_DB_PASSWORD is not set.\n')
270
274
  if (!envExists) {
271
275
  console.error(' No .env file found. Run: npx spine-framework init')
272
276
  } else {
273
277
  console.error(' Edit .env and add: SUPABASE_DB_PASSWORD=your-db-password')
274
278
  console.error(' Or pass it directly: npx spine-framework migrate --db-password <password>')
279
+ console.error(' Or a full connection string (pooler/IPv4): SUPABASE_DB_URL=postgres://postgres.<ref>:<pw>@aws-0-<region>.pooler.supabase.com:5432/postgres')
275
280
  }
276
281
  console.error('\n Get it from: https://supabase.com/dashboard/project/_/settings/database')
277
282
  process.exit(1)
@@ -313,12 +318,12 @@ async function migrateCommand(options: MigrateOptions): Promise<void> {
313
318
 
314
319
  console.log('\n✅ All migrations applied successfully!\n')
315
320
  console.log('Next steps:')
316
- console.log(' npx spine-framework install-app <app-package>')
317
- console.log(' npm install && npm run assemble && netlify dev\n')
321
+ console.log(' npm install && npm run dev:netlify')
322
+ console.log(' (optional) npx spine-framework install-app <app-package> — only for')
323
+ console.log(' additional app packs; core/admin apps are already seeded\n')
318
324
  }
319
325
  // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:migrateCommand:function"]
320
326
 
321
- // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:registerMigrateCommands:function" type="function" identity="registerMigrateCommands" parent="~/.framework/cli/commands/migrate.ts"]
322
327
  // CIL[DOC-VECTOR type="context" content="purpose='CLI action that collects, optionally dry-runs, and applies framework migrations.'; No verified external callers; imports: none"]
323
328
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
324
329
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
@@ -333,6 +338,7 @@ async function migrateCommand(options: MigrateOptions): Promise<void> {
333
338
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
334
339
  // CIL[DOC-STABILITY stability="stable"]
335
340
  // CIL[DOC-AUDIENCE audience="engineers"]
341
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:registerMigrateCommands:function" type="function" identity="registerMigrateCommands" parent="~/.framework/cli/commands/migrate.ts"]
336
342
  export function registerMigrateCommands(program: Command) {
337
343
  program
338
344
  .command('migrate')
@@ -350,15 +356,14 @@ export function registerMigrateCommands(program: Command) {
350
356
  }
351
357
  })
352
358
  }
359
+ // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:registerMigrateCommands:function"]
353
360
  // CIL[DOC-VECTOR type="context" content="purpose='Registers the migrate command with the Commander program.'; No verified external callers; imports: none"]
354
361
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
355
362
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
356
363
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
357
364
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
358
365
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
359
- // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:registerMigrateCommands:function"]
360
366
 
361
- // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:loadEnv:function" type="function" identity="loadEnv" parent="~/.framework/cli/commands/migrate.ts"]
362
367
  // CIL[DOC-MACRO purpose="Loads key=value pairs from the project .env file into process.env."]
363
368
  // CIL[DOC-RESPONSIBILITY responsibility="Reads .env without overwriting existing environment variables."]
364
369
  // CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
@@ -367,6 +372,7 @@ export function registerMigrateCommands(program: Command) {
367
372
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
368
373
  // CIL[DOC-STABILITY stability="stable"]
369
374
  // CIL[DOC-AUDIENCE audience="engineers"]
375
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:loadEnv:function" type="function" identity="loadEnv" parent="~/.framework/cli/commands/migrate.ts"]
370
376
  function loadEnv() {
371
377
  const envPath = join(PROJECT_ROOT, '.env')
372
378
  if (!existsSync(envPath)) return
@@ -381,15 +387,14 @@ function loadEnv() {
381
387
  if (key && !(key in process.env)) process.env[key] = val
382
388
  }
383
389
  }
390
+ // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:loadEnv:function"]
384
391
  // CIL[DOC-VECTOR type="context" content="purpose='Loads key=value pairs from the project .env file into process.env.'; No verified external callers; imports: none"]
385
392
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
386
393
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
387
394
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
388
395
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
389
396
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
390
- // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:loadEnv:function"]
391
397
 
392
- // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:collectMigrations:function" type="function" identity="collectMigrations" parent="~/.framework/cli/commands/migrate.ts"]
393
398
  // CIL[DOC-MACRO purpose="Collects SQL migration files from framework and custom directories."]
394
399
  // CIL[DOC-RESPONSIBILITY responsibility="Sorts and returns file paths for pending migrations, optionally including custom migrations."]
395
400
  // CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
@@ -398,6 +403,7 @@ function loadEnv() {
398
403
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
399
404
  // CIL[DOC-STABILITY stability="stable"]
400
405
  // CIL[DOC-AUDIENCE audience="engineers"]
406
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:collectMigrations:function" type="function" identity="collectMigrations" parent="~/.framework/cli/commands/migrate.ts"]
401
407
  export function collectMigrations(frameworkOnly: boolean): { name: string; path: string }[] {
402
408
  const files: { name: string; path: string }[] = []
403
409
 
@@ -426,15 +432,14 @@ export function collectMigrations(frameworkOnly: boolean): { name: string; path:
426
432
 
427
433
  return files
428
434
  }
435
+ // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:collectMigrations:function"]
429
436
  // CIL[DOC-VECTOR type="context" content="purpose='Collects SQL migration files from framework and custom directories.'; No verified external callers; imports: none"]
430
437
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
431
438
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
432
439
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
433
440
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
434
441
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
435
- // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:collectMigrations:function"]
436
442
 
437
- // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:splitSqlStatements:function" type="function" identity="splitSqlStatements" parent="~/.framework/cli/commands/migrate.ts"]
438
443
  // CIL[DOC-MACRO purpose="Splits SQL into executable statements while preserving dollar-quoted blocks."]
439
444
  // CIL[DOC-RESPONSIBILITY responsibility="Removes single-line comments, splits on semicolons, restores protected dollar-quoted blocks, and returns trimmed statements."]
440
445
  // CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
@@ -443,6 +448,7 @@ export function collectMigrations(frameworkOnly: boolean): { name: string; path:
443
448
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
444
449
  // CIL[DOC-STABILITY stability="stable"]
445
450
  // CIL[DOC-AUDIENCE audience="engineers"]
451
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:splitSqlStatements:function" type="function" identity="splitSqlStatements" parent="~/.framework/cli/commands/migrate.ts"]
446
452
  export function splitSqlStatements(sql: string): string[] {
447
453
  // Single-pass scanner: a ; only ends a statement in normal state. Comments
448
454
  // are dropped; string literals, quoted identifiers, and dollar-quoted blocks
@@ -497,10 +503,10 @@ export function splitSqlStatements(sql: string): string[] {
497
503
  if (tail) statements.push(tail + ';')
498
504
  return statements
499
505
  }
506
+ // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:splitSqlStatements:function"]
500
507
  // CIL[DOC-VECTOR type="context" content="purpose='Splits SQL into executable statements while preserving dollar-quoted blocks.'; No verified external callers; imports: none"]
501
508
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
502
509
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
503
510
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
504
511
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
505
512
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
506
- // CIL[END stable_id="~/.framework/cli/commands/migrate.ts:splitSqlStatements:function"]
@@ -12,11 +12,9 @@
12
12
 
13
13
 
14
14
  import type { Command } from 'commander'
15
- import { readdirSync, existsSync } from 'fs'
16
- import { resolve, dirname } from 'path'
17
- import { fileURLToPath } from 'url'
18
15
  import { buildCliContext, printResult, handleError } from '../context.ts'
19
16
  import { adminDb } from '../../functions/_shared/index.ts'
17
+ import { collectMigrations } from './migrate.ts'
20
18
  // CIL[DOC-VECTOR type="context" content="purpose='CLI migration inspection commands for listing applied migrations and comparing local SQL files'; No verified external callers; imports: .framework/cli/context.ts,.framework/functions/_shared/index.ts"]
21
19
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
22
20
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
@@ -25,42 +23,10 @@ import { adminDb } from '../../functions/_shared/index.ts'
25
23
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
26
24
  // CIL[END stable_id="~/.framework/cli/commands/migrations.ts:module_header:module_header"]
27
25
 
28
- // CIL[BEGIN stable_id="~/.framework/cli/commands/migrations.ts:__filename:constant" type="constant" identity="__filename" parent="~/.framework/cli/commands/migrations.ts"]
29
- // CIL[DOC-MACRO purpose="Resolve the current module filename from import.meta.url"]
30
- // CIL[DOC-RESPONSIBILITY responsibility="Provide a CommonJS-style __filename value in ESM"]
31
- // CIL[DOC-CONTEXT module="cli/commands/migrations" layer="utility" related_files=".framework/cli/commands/migrations.ts,.framework/cli/context.ts,.framework/functions/_shared/index.ts"]
32
- // CIL[DOC-CONTRACT inputs="import.meta.url" outputs="absolute __filename" errors="none" side_effects="none"]
33
- // CIL[DOC-MICRO logic_summary="call fileURLToPath on import.meta.url" notable_decisions="[]"]
34
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
35
- // CIL[DOC-STABILITY stability="stable"]
36
- const __filename = fileURLToPath(import.meta.url)
37
- // CIL[DOC-VECTOR type="context" content="purpose='Resolve the current module filename from import.meta.url'; No verified external callers; imports: .framework/cli/context.ts,.framework/functions/_shared/index.ts"]
38
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
39
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
40
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
41
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
42
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
43
- // CIL[END stable_id="~/.framework/cli/commands/migrations.ts:__filename:constant"]
44
- // CIL[BEGIN stable_id="~/.framework/cli/commands/migrations.ts:__dirname:constant" type="constant" identity="__dirname" parent="~/.framework/cli/commands/migrations.ts"]
45
- // CIL[DOC-MACRO purpose="Resolve the current module directory name"]
46
- // CIL[DOC-RESPONSIBILITY responsibility="Provide a CommonJS-style __dirname value in ESM"]
47
- // CIL[DOC-CONTEXT module="cli/commands/migrations" layer="utility" related_files=".framework/cli/commands/migrations.ts,.framework/cli/context.ts,.framework/functions/_shared/index.ts"]
48
- // CIL[DOC-CONTRACT inputs="__filename" outputs="absolute __dirname" errors="none" side_effects="none"]
49
- // CIL[DOC-MICRO logic_summary="call dirname on the resolved __filename" notable_decisions="[]"]
50
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
51
- // CIL[DOC-STABILITY stability="stable"]
52
- const __dirname = dirname(__filename)
53
- // CIL[DOC-VECTOR type="context" content="purpose='Resolve the current module directory name'; No verified external callers; imports: .framework/cli/context.ts,.framework/functions/_shared/index.ts"]
54
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
55
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
56
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
57
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
58
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
59
- // CIL[END stable_id="~/.framework/cli/commands/migrations.ts:__dirname:constant"]
60
26
 
61
27
  // CIL[BEGIN stable_id="~/.framework/cli/commands/migrations.ts:registerMigrationCommands:function" type="function" identity="registerMigrationCommands" parent="~/.framework/cli/commands/migrations.ts"]
62
28
  // CIL[DOC-MACRO purpose="Register migration list and status CLI subcommands"]
63
- // CIL[DOC-RESPONSIBILITY responsibility="Expose commands that query supabase_migrations and compare local SQL files"]
29
+ // CIL[DOC-RESPONSIBILITY responsibility="Expose commands that query _spine_migrations and compare local SQL files"]
64
30
  // CIL[DOC-CONTEXT module="cli/commands/migrations" layer="cli" related_files=".framework/cli/commands/migrations.ts,.framework/cli/context.ts,.framework/functions/_shared/index.ts"]
65
31
  // CIL[DOC-CONTRACT inputs="program: Command" outputs="void" errors="Throws on missing migrations directory or failed DB queries" side_effects="Adds commands and options to the Commander program"]
66
32
  // CIL[DOC-MICRO logic_summary="Define migrations command, add list and status subcommands with options, perform DB calls and console output" notable_decisions="[]"]
@@ -73,17 +39,16 @@ export function registerMigrationCommands(program: Command) {
73
39
 
74
40
  migrations
75
41
  .command('list')
76
- .description('List applied migrations from supabase schema_migrations')
42
+ .description('List applied migrations from _spine_migrations')
77
43
  .option('--json', 'Output as JSON')
78
44
  .action(async (opts) => {
79
45
  try {
80
46
  await buildCliContext()
81
47
 
82
48
  const { data, error } = await adminDb
83
- .schema('supabase_migrations' as any)
84
- .from('schema_migrations' as any)
85
- .select('version, name, executed_at')
86
- .order('version', { ascending: true })
49
+ .from('_spine_migrations' as any)
50
+ .select('filename, applied_at')
51
+ .order('filename', { ascending: true })
87
52
 
88
53
  if (error) {
89
54
  throw new Error(
@@ -106,34 +71,29 @@ export function registerMigrationCommands(program: Command) {
106
71
  try {
107
72
  await buildCliContext()
108
73
 
109
- const migrationsDir = resolve(__dirname, '../../migrations')
74
+ const migrationFiles = collectMigrations(false)
110
75
 
111
- if (!existsSync(migrationsDir)) {
112
- throw new Error(`Migrations directory not found: ${migrationsDir}`)
76
+ if (migrationFiles.length === 0) {
77
+ throw new Error('Migrations directory not found (.framework/migrations)')
113
78
  }
114
79
 
115
- const localFiles = readdirSync(migrationsDir)
116
- .filter((f: string) => f.endsWith('.sql'))
117
- .sort()
118
-
119
80
  const { data: applied, error } = await adminDb
120
- .schema('supabase_migrations' as any)
121
- .from('schema_migrations' as any)
122
- .select('version')
81
+ .from('_spine_migrations' as any)
82
+ .select('filename')
123
83
 
124
84
  if (error) {
125
85
  throw new Error(`Could not query migrations: ${error.message}`)
126
86
  }
127
87
 
128
88
  const appliedVersions = new Set(
129
- (applied || []).map((r: any) => r.version)
89
+ (applied || []).map((r: any) => r.filename)
130
90
  )
131
91
 
132
- const status = localFiles.map((file: string) => {
133
- const version = file.replace('.sql', '')
134
- const isApplied = appliedVersions.has(version)
92
+ const status = migrationFiles.map(({ name }) => {
93
+ const version = name.replace('.sql', '')
94
+ const isApplied = appliedVersions.has(name)
135
95
  return {
136
- file,
96
+ file: name,
137
97
  version,
138
98
  status: isApplied ? 'applied' : 'pending'
139
99
  }
@@ -22,6 +22,8 @@ import {
22
22
  mergePackageJson,
23
23
  writeFrozenManifest,
24
24
  cmpSemver,
25
+ syncAgentFiles,
26
+ collectAgentFileHashes,
25
27
  } from '../lib/project-files.ts'
26
28
  // CIL[END stable_id="~/.framework/cli/commands/upgrade.ts:module_header:module_header"]
27
29
 
@@ -167,11 +169,27 @@ function runUpgrade(opts: { dryRun: boolean; force: boolean }): void {
167
169
  .filter((rel) => rel.startsWith('.framework/migrations/') && rel.endsWith('.sql') && !(rel in oldFiles))
168
170
 
169
171
  console.log(`\n ${added.length} added · ${changed.length} changed · ${removed.length} removed · ${kept} unchanged`)
172
+
173
+ // Agent assets are computed before the dry-run exit so the report is complete:
174
+ // AGENTS.md gets its marker-delimited framework block refreshed in place
175
+ // (customer content outside the markers is preserved); .devin/skills/spine-*
176
+ // dirs are replaced wholesale (customer-owned sibling dirs untouched).
177
+ const agentActions = syncAgentFiles({
178
+ pkgRoot: PACKAGE_ROOT,
179
+ projectRoot: PROJECT_ROOT,
180
+ entries: profile.agent_files ?? [],
181
+ version: newVersion,
182
+ dryRun: true,
183
+ })
184
+
170
185
  if (opts.dryRun) {
171
186
  for (const f of added) console.log(` + ${f}`)
172
187
  for (const f of changed) console.log(` ~ ${f}`)
173
188
  for (const f of removed) console.log(` - ${f}`)
174
189
  for (const f of staleOutside) console.log(` ? ${f} (dropped upstream, left in place)`)
190
+ for (const a of agentActions) {
191
+ if (a.action !== 'unchanged') console.log(` ~ ${a.rel} (agent asset: ${a.action})`)
192
+ }
175
193
  if (newMigrations.length > 0) {
176
194
  console.log(`\n New migrations in this version (${newMigrations.length}):`)
177
195
  for (const rel of newMigrations) console.log(` ${rel.split('/').pop()}`)
@@ -186,6 +204,22 @@ function runUpgrade(opts: { dryRun: boolean; force: boolean }): void {
186
204
  for (const rel of staleOutside) console.log(` ⚠ ${rel} is no longer shipped upstream — left in place`)
187
205
  console.log(` ✓ framework files synced (${files.length})`)
188
206
 
207
+ // 4b. Apply agent assets (the dry-run pass above reported; this one writes)
208
+ const applied = syncAgentFiles({
209
+ pkgRoot: PACKAGE_ROOT,
210
+ projectRoot: PROJECT_ROOT,
211
+ entries: profile.agent_files ?? [],
212
+ version: newVersion,
213
+ })
214
+ for (const a of applied) {
215
+ if (a.action === 'prepended') {
216
+ console.log(` ⚠ ${a.rel} had no spine-framework markers — fresh framework block prepended`)
217
+ } else if (a.action !== 'unchanged') {
218
+ console.log(` ✓ ${a.rel} (${a.action})`)
219
+ }
220
+ }
221
+ console.log(' ✓ agent assets synced (AGENTS.md + .devin/skills/spine-*)')
222
+
189
223
  // 5. package.json — framework scripts/deps, exact pin
190
224
  const pkgPath = join(PROJECT_ROOT, 'package.json')
191
225
  const existingPkg = existsSync(pkgPath) ? JSON.parse(readFileSync(pkgPath, 'utf8')) : {}
@@ -222,6 +256,7 @@ function runUpgrade(opts: { dryRun: boolean; force: boolean }): void {
222
256
  projectRoot: PROJECT_ROOT,
223
257
  frameworkVersion: newVersion,
224
258
  frameworkDeps: merged.frameworkDeps,
259
+ agentFiles: collectAgentFileHashes(PROJECT_ROOT, profile.agent_files ?? []),
225
260
  })
226
261
  console.log(` ✓ .spine-manifest.json regenerated (${manifest.fileCount} files)`)
227
262