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
@@ -0,0 +1,181 @@
1
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/EntitySelect.tsx:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/src/components/admin/EntitySelect.tsx"]
2
+ /**
3
+ * @module EntitySelect
4
+ * @audience both
5
+ * @layer shared-core
6
+ * @stability stable
7
+ *
8
+ * This module provides a React component for selecting entities within the admin interface, leveraging a native select dropdown. It fetches data from an API to populate the selection options, ensuring that the component reflects the current state of available entities.
9
+ * INVARIANT: The component must always receive valid API response data to function correctly.
10
+ *
11
+ * @seeAlso native-select (provides the UI component for selection).
12
+ * @seeAlso api (handles the data fetching required for populating the select options).
13
+ *
14
+ * @cil-generated
15
+ */
16
+
17
+ import React, { useEffect, useState } from 'react'
18
+ import { NativeSelect } from '../ui/native-select'
19
+ import { apiFetch } from '../../lib/api'
20
+ // CIL[END stable_id="~/.framework/src/components/admin/EntitySelect.tsx:module_header:module_header"]
21
+
22
+
23
+
24
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/EntitySelect.tsx:Option:interface" type="interface" identity="Option" parent="~/.framework/src/components/admin/EntitySelect.tsx"]
25
+ /**
26
+ * The Option interface defines the structure for an option item used in selection components. It provides a standardized way to represent selectable items with a value and a label.
27
+ *
28
+ * @sideEffects none
29
+ * @stability internal
30
+ * @cil-generated
31
+ */
32
+ interface Option {
33
+ value: string
34
+ label: string
35
+ }
36
+ // CIL[END stable_id="~/.framework/src/components/admin/EntitySelect.tsx:Option:interface"]
37
+
38
+
39
+
40
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/EntitySelect.tsx:EntitySelectProps:interface" type="interface" identity="EntitySelectProps" parent="~/.framework/src/components/admin/EntitySelect.tsx"]
41
+ /**
42
+ * EntitySelectProps defines the properties required for the EntitySelect component, facilitating the selection of entities from a specified endpoint. It allows for customization of the selection behavior and appearance.
43
+ *
44
+ * @sideEffects none
45
+ * @stability internal
46
+ * @cil-generated
47
+ */
48
+ interface EntitySelectProps {
49
+ endpoint: string
50
+ value: string
51
+ onChange: (value: string) => void
52
+ placeholder?: string
53
+ mapOption?: (row: any) => Option
54
+ className?: string
55
+ }
56
+ // CIL[END stable_id="~/.framework/src/components/admin/EntitySelect.tsx:EntitySelectProps:interface"]
57
+
58
+
59
+
60
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/EntitySelect.tsx:defaultMap:function" type="function" identity="defaultMap" parent="~/.framework/src/components/admin/EntitySelect.tsx"]
61
+ /**
62
+ * The defaultMap function transforms a row object into an Option object, providing a standard way to represent entities with a value and label. This is useful for creating dropdowns or selection lists in the admin interface.
63
+ *
64
+ * @inputSpec
65
+ * row: any (required) — the row object containing entity data.
66
+ * @outputSpec Option — an object with 'value' and 'label' properties.
67
+ * @sideEffects none
68
+ * @stability internal
69
+ * @cil-generated
70
+ */
71
+ const defaultMap = (row: any): Option => ({
72
+ value: row.id,
73
+ label: row.name || row.title || row.slug || row.id,
74
+ })
75
+ // CIL[END stable_id="~/.framework/src/components/admin/EntitySelect.tsx:defaultMap:function"]
76
+
77
+
78
+
79
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/EntitySelect.tsx:EntitySelect:component" type="component" identity="EntitySelect" parent="~/.framework/src/components/admin/EntitySelect.tsx"]
80
+ /**
81
+ * EntitySelect is a component that allows users to select an entity from a dynamically fetched list of options. It handles API data retrieval and state management to provide a user-friendly interface for entity selection.
82
+ *
83
+ * @macro Dropdown component for selecting entities from an API-driven list.
84
+ * @micro Fetches options from a specified endpoint and maps them using a provided mapping function.
85
+ * @inputSpec
86
+ * endpoint: string (required) — the API endpoint to fetch options from.
87
+ * value: string (optional) — the currently selected value.
88
+ * onChange: function (required) — callback function to handle value changes.
89
+ * placeholder: string (optional) — placeholder text for the dropdown.
90
+ * mapOption: function (optional) — function to map API response items to dropdown options.
91
+ * className: string (optional) — additional CSS class names for styling.
92
+ * @outputSpec JSX.Element — renders a NativeSelect component with options.
93
+ * @sideEffects fetches data from an external API endpoint.
94
+ * @stability internal
95
+ * @calls apiFetch
96
+ * @errorHandling sets options to an empty array on fetch failure.
97
+ * @cil-generated
98
+ */
99
+ export function EntitySelect({
100
+ endpoint,
101
+ value,
102
+ onChange,
103
+ placeholder = 'Select…',
104
+ mapOption = defaultMap,
105
+ className,
106
+ }: EntitySelectProps) {
107
+ const [options, setOptions] = useState<Option[]>([])
108
+
109
+ useEffect(() => {
110
+ apiFetch(endpoint)
111
+ .then(r => r.json())
112
+ .then(data => {
113
+ const rows: any[] = data?.data || data?.items || data?.projects || data || []
114
+ setOptions(rows.map(mapOption))
115
+ })
116
+ .catch(() => setOptions([]))
117
+ // eslint-disable-next-line react-hooks/exhaustive-deps
118
+ }, [endpoint])
119
+
120
+ const known = options.some(o => o.value === value)
121
+
122
+ return (
123
+ <NativeSelect
124
+ value={value || ''}
125
+ // CIL[END stable_id="~/.framework/src/components/admin/EntitySelect.tsx:EntitySelect:component"]
126
+
127
+ onChange={e => onChange(e.target.value)}
128
+ className={className}
129
+ >
130
+ <option value="">{placeholder}</option>
131
+ {value && !known && <option value={value}>{value}</option>}
132
+ {options.map(o => (
133
+ <option key={o.value} value={o.value}>
134
+ {o.label}
135
+ </option>
136
+ ))}
137
+ </NativeSelect>
138
+ )
139
+ }
140
+
141
+
142
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/EntitySelect.tsx:AppSelect:component" type="component" identity="AppSelect" parent="~/.framework/src/components/admin/EntitySelect.tsx"]
143
+ /**
144
+ * AppSelect is a specialized component for selecting applications in the admin interface, providing a predefined endpoint and placeholder to streamline the selection process.
145
+ *
146
+ * @macro Component that facilitates app selection in the admin panel.
147
+ * @micro Uses a fixed API endpoint to fetch a list of applications.
148
+ * @inputSpec
149
+ * props: Omit<EntitySelectProps, 'endpoint' | 'placeholder'> — properties for the EntitySelect component.
150
+ * @outputSpec JSX.Element — renders the EntitySelect component.
151
+ * @sideEffects none
152
+ * @stability internal
153
+ * @calls EntitySelect
154
+ * @cil-generated
155
+ */
156
+ export function AppSelect(props: Omit<EntitySelectProps, 'endpoint' | 'placeholder'>) {
157
+ return <EntitySelect endpoint="/api/apps?action=list" placeholder="No app (global)" {...props} />
158
+ }
159
+ // CIL[END stable_id="~/.framework/src/components/admin/EntitySelect.tsx:AppSelect:component"]
160
+
161
+
162
+
163
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/EntitySelect.tsx:PipelineSelect:component" type="component" identity="PipelineSelect" parent="~/.framework/src/components/admin/EntitySelect.tsx"]
164
+ /**
165
+ * PipelineSelect is a component that provides a dropdown for selecting a pipeline from a predefined list. It simplifies the usage of the EntitySelect component by pre-configuring the endpoint and placeholder specific to pipelines.
166
+ *
167
+ * @macro Component that renders a selection interface for pipelines.
168
+ * @micro Uses the EntitySelect component with a fixed API endpoint for fetching pipeline data.
169
+ * @inputSpec
170
+ * props: Omit<EntitySelectProps, 'endpoint' | 'placeholder'> — properties for the EntitySelect component excluding endpoint and placeholder.
171
+ * @outputSpec JSX.Element — renders the EntitySelect component.
172
+ * @sideEffects none
173
+ * @stability internal
174
+ * @calls EntitySelect
175
+ * @cil-generated
176
+ */
177
+ export function PipelineSelect(props: Omit<EntitySelectProps, 'endpoint' | 'placeholder'>) {
178
+ return <EntitySelect endpoint="/api/pipelines?action=list" placeholder="Select a pipeline…" {...props} />
179
+ }
180
+ // CIL[END stable_id="~/.framework/src/components/admin/EntitySelect.tsx:PipelineSelect:component"]
181
+
@@ -1,145 +1,104 @@
1
- // CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:module_header:module_header"]
2
- // CIL[DOC-MACRO purpose="Top-level module header for the PageInstructions React component."]
3
- // CIL[DOC-RESPONSIBILITY responsibility="Declare imports, exports, and the public surface of this module."]
4
- // CIL[DOC-CONTEXT module="admin" layer="components" related_files=".framework/src/components/ui/card.tsx,.framework/src/components/ui/collapsible.tsx"]
5
- // CIL[DOC-CONTRACT inputs="none" outputs="module exports" errors="none" side_effects="none"]
6
- // CIL[DOC-MICRO logic_summary="Aggregates imports and exports for the collapsible page instructions UI component." notable_decisions="[]"]
7
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
- // CIL[DOC-STABILITY stability="stable"]
9
- // CIL[DOC-AUDIENCE audience="module authors and consumers"]
10
-
1
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
11
2
  import * as React from 'react'
12
- import { ChevronDown } from 'lucide-react'
13
- import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '../ui/collapsible'
14
- import { Card, CardContent } from '../ui/card'
15
-
16
- // CIL[DOC-VECTOR type="context" content="purpose='Top-level module header for the PageInstructions React component.'; No verified external callers; imports: .framework/src/components/ui/collapsible.tsx,.framework/src/components/ui/card.tsx"]
17
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
18
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
19
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
20
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
21
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
3
+ import { BookOpen } from 'lucide-react'
4
+ import ReactMarkdown from 'react-markdown'
5
+ import remarkGfm from 'remark-gfm'
6
+ import { Button } from '../ui/button'
7
+ import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger } from '../ui/sheet'
22
8
  // CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:module_header:module_header"]
23
9
 
24
- // CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:cleancilmarkers:function"]
25
- // CIL[DOC-MACRO purpose="Remove CIL marker comments from rendered text nodes."]
26
- // CIL[DOC-RESPONSIBILITY responsibility="Sanitize raw content before rendering so CIL tags do not leak into the UI."]
27
- // CIL[DOC-CONTEXT module="admin" layer="components" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/collapsible.tsx"]
28
- // CIL[DOC-CONTRACT inputs="content: React.ReactNode" outputs="React.ReactNode with CIL comment lines removed" errors="none" side_effects="none"]
29
- // CIL[DOC-MICRO logic_summary="Returns non-string content unchanged; for strings, removes lines starting with // CIL[, collapses excess blank lines, and trims." notable_decisions="[]"]
30
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
31
- // CIL[DOC-STABILITY stability="stable"]
10
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:instructionModules:constant" type="constant" identity="instructionModules" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
11
+ const instructionModules = import.meta.glob('../../instructions/**/*.md', {
12
+ query: '?raw',
13
+ import: 'default',
14
+ eager: true,
15
+ }) as Record<string, string>
16
+ // CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:instructionModules:constant"]
32
17
 
33
- function cleanCilMarkers(content: React.ReactNode): React.ReactNode {
34
- if (typeof content !== 'string') return content
35
- return content
36
- .split('\n')
37
- .filter(line => !line.trim().startsWith('// CIL['))
38
- .join('\n')
39
- .replace(/\n{3,}/g, '\n\n')
40
- .trim()
18
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:instructionDocs:constant" type="constant" identity="instructionDocs" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
19
+ const instructionDocs: Record<string, string> = {}
20
+ // CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:instructionDocs:constant"]
21
+ for (const [path, content] of Object.entries(instructionModules)) {
22
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:key:constant" type="constant" identity="key" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
23
+ const key = path.replace(/^.*instructions\//, '').replace(/\.md$/, '')
24
+ // CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:key:constant"]
25
+ if (key) instructionDocs[key] = content
41
26
  }
42
27
 
43
- // CIL[DOC-VECTOR type="context" content="purpose='Remove CIL marker comments from rendered text nodes.'; No verified external callers; imports: .framework/src/components/ui/collapsible.tsx,.framework/src/components/ui/card.tsx"]
44
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
45
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
46
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
47
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
48
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
49
- // CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:cleancilmarkers:function"]
50
-
51
- // CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:pageinstructionssection:interface"]
52
- // CIL[DOC-MACRO purpose="Type contract for a single collapsible section inside PageInstructions."]
53
- // CIL[DOC-RESPONSIBILITY responsibility="Define the title and content shape expected by the PageInstructions component."]
54
- // CIL[DOC-CONTEXT module="admin" layer="components" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/collapsible.tsx"]
55
- // CIL[DOC-CONTRACT inputs="none" outputs="TypeScript interface" errors="none" side_effects="none"]
56
- // CIL[DOC-MICRO logic_summary="Declares a section with a string title and arbitrary React content." notable_decisions="[]"]
57
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
58
- // CIL[DOC-STABILITY stability="stable"]
59
-
60
- export interface PageInstructionsSection {
61
- title: string
62
- content: React.ReactNode
28
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:PAGE_TITLES:constant" type="constant" identity="PAGE_TITLES" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
29
+ const PAGE_TITLES: Record<string, string> = {
30
+ types: 'Types',
31
+ apps: 'Apps',
32
+ pipelines: 'Pipelines',
33
+ triggers: 'Triggers',
34
+ 'ai-agents': 'AI Agents',
35
+ timers: 'Timers',
36
+ integrations: 'Integrations',
37
+ roles: 'Roles',
38
+ prompts: 'Prompt Configs',
39
+ 'api-keys': 'API Keys',
40
+ deliveries: 'Deliveries',
41
+ 'runtime-list': 'Records',
42
+ 'runtime-detail': 'Record',
63
43
  }
44
+ // CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:PAGE_TITLES:constant"]
64
45
 
65
- // CIL[DOC-VECTOR type="context" content="purpose='Type contract for a single collapsible section inside PageInstructions.'; No verified external callers; imports: .framework/src/components/ui/collapsible.tsx,.framework/src/components/ui/card.tsx"]
66
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
67
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
68
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
69
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
70
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
71
- // CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:pageinstructionssection:interface"]
46
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:displayTitle:function" type="function" identity="displayTitle" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
47
+ function displayTitle(pageKey: string): string {
48
+ return (
49
+ PAGE_TITLES[pageKey] ??
50
+ pageKey
51
+ .split(/[-_]/)
52
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
53
+ .join(' ')
54
+ )
55
+ }
56
+ // CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:displayTitle:function"]
72
57
 
73
- // CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:pageinstructionsprops:interface"]
74
- // CIL[DOC-MACRO purpose="Props interface for the PageInstructions component."]
75
- // CIL[DOC-RESPONSIBILITY responsibility="Document the public configuration options accepted by PageInstructions."]
76
- // CIL[DOC-CONTEXT module="admin" layer="components" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/collapsible.tsx"]
77
- // CIL[DOC-CONTRACT inputs="none" outputs="TypeScript interface" errors="none" side_effects="none"]
78
- // CIL[DOC-MICRO logic_summary="Optional title, description node, and an array of sections." notable_decisions="[]"]
79
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
80
- // CIL[DOC-STABILITY stability="stable"]
58
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:cleanMarkdown:function" type="function" identity="cleanMarkdown" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
59
+ function cleanMarkdown(markdown: string): string {
60
+ return markdown
61
+ .split('\n')
62
+ .filter((line) => !line.trim().startsWith('// CIL['))
63
+ .join('\n')
64
+ .trim()
65
+ }
66
+ // CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:cleanMarkdown:function"]
81
67
 
68
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:PageInstructionsProps:interface" type="interface" identity="PageInstructionsProps" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
82
69
  export interface PageInstructionsProps {
70
+ pageKey: string
83
71
  title?: string
84
- description?: React.ReactNode
85
- sections?: PageInstructionsSection[]
86
72
  }
73
+ // CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:PageInstructionsProps:interface"]
87
74
 
88
- // CIL[DOC-VECTOR type="context" content="purpose='Props interface for the PageInstructions component.'; No verified external callers; imports: .framework/src/components/ui/collapsible.tsx,.framework/src/components/ui/card.tsx"]
89
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
90
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
91
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
92
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
93
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
94
- // CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:pageinstructionsprops:interface"]
95
-
96
- // CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:pageinstructions:function"]
97
- // CIL[DOC-MACRO purpose="Render a collapsible card containing optional description and instruction sections."]
98
- // CIL[DOC-RESPONSIBILITY responsibility="Display page-level help or instructions in a collapsible UI widget."]
99
- // CIL[DOC-CONTEXT module="admin" layer="components" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/collapsible.tsx"]
100
- // CIL[DOC-CONTRACT inputs="props: PageInstructionsProps" outputs="JSX element or null" errors="none" side_effects="renders UI"]
101
- // CIL[DOC-MICRO logic_summary="Returns null when no content is provided; otherwise renders a Card with a Collapsible trigger and filtered description/section content." notable_decisions="[]"]
102
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
103
- // CIL[DOC-STABILITY stability="stable"]
104
-
105
- export function PageInstructions({
106
- title = 'Page instructions',
107
- description,
108
- sections,
109
- }: PageInstructionsProps) {
110
- if (!description && (!sections || sections.length === 0)) return null
75
+ // CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:PageInstructions:component" type="component" identity="PageInstructions" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
76
+ export function PageInstructions({ pageKey, title }: PageInstructionsProps) {
77
+ const markdown = instructionDocs[pageKey]
78
+ if (!markdown) return null
111
79
 
112
80
  return (
113
- <Card>
114
- <CardContent className="p-4">
115
- <Collapsible>
116
- <CollapsibleTrigger className="group flex w-full items-center justify-between text-sm font-medium text-slate-700">
117
- <span>{title}</span>
118
- <ChevronDown className="h-4 w-4 transition-transform group-data-[state=open]:rotate-180" />
119
- </CollapsibleTrigger>
120
- <CollapsibleContent className="space-y-4 pt-4">
121
- {description && <div className="text-sm text-slate-600">{cleanCilMarkers(description)}</div>}
122
- {sections && sections.length > 0 && (
123
- <div className="space-y-3">
124
- {sections.map((section, i) => (
125
- <div key={i}>
126
- <div className="text-sm font-semibold text-slate-700">{section.title}</div>
127
- <div className="mt-1 text-sm text-slate-600">{cleanCilMarkers(section.content)}</div>
128
- </div>
129
- ))}
130
- </div>
131
- )}
132
- </CollapsibleContent>
133
- </Collapsible>
134
- </CardContent>
135
- </Card>
81
+ <Sheet>
82
+ <SheetTrigger asChild>
83
+ <Button variant="ghost" size="sm" className="h-7 gap-1.5 px-2.5 text-xs text-muted-foreground hover:text-foreground">
84
+ <BookOpen className="h-3.5 w-3.5" />
85
+ Instructions
86
+ </Button>
87
+ </SheetTrigger>
88
+ <SheetContent side="right" className="w-full sm:max-w-xl">
89
+ <SheetHeader className="border-b pr-12">
90
+ <SheetTitle>{title ?? displayTitle(pageKey)}</SheetTitle>
91
+ <SheetDescription className="sr-only">
92
+ Instructions and reference for this page
93
+ </SheetDescription>
94
+ </SheetHeader>
95
+ <div className="min-h-0 flex-1 overflow-y-auto px-6 py-4">
96
+ <div className="prose prose-sm prose-slate max-w-none">
97
+ <ReactMarkdown remarkPlugins={[remarkGfm]}>{cleanMarkdown(markdown)}</ReactMarkdown>
98
+ </div>
99
+ </div>
100
+ </SheetContent>
101
+ </Sheet>
136
102
  )
137
103
  }
138
-
139
- // CIL[DOC-VECTOR type="context" content="purpose='Render a collapsible card containing optional description and instruction sections.'; No verified external callers; imports: .framework/src/components/ui/collapsible.tsx,.framework/src/components/ui/card.tsx"]
140
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
141
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
142
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
143
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
144
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
145
- // CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:pageinstructions:function"]
104
+ // CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:PageInstructions:component"]
@@ -12,6 +12,7 @@ import { Routes, Route, Navigate, useNavigate, useLocation } from 'react-router-
12
12
  import { AppRecord } from '../../hooks/useApps'
13
13
  import { GenericListPage } from './GenericListPage'
14
14
  import { GenericDetailPage } from './GenericDetailPage'
15
+ import { useBranding } from '../../hooks/useBranding'
15
16
  // CIL[DOC-VECTOR type="context" content="purpose='Module imports and re-exports for the GenericAppShell component'; No verified external callers; imports: .framework/src/hooks/useApps.ts,.framework/src/components/app-shell/GenericListPage.tsx,.framework/src/components/app-shell/GenericDetailPage.tsx"]
16
17
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
17
18
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
@@ -76,6 +77,7 @@ export function GenericAppShell({ app }: GenericAppShellProps) {
76
77
  const navigate = useNavigate()
77
78
  const location = useLocation()
78
79
  const [sidebarOpen, setSidebarOpen] = useState(false)
80
+ const branding = useBranding()
79
81
 
80
82
  const navItems: NavItem[] = (app.nav_items || []) as NavItem[]
81
83
 
@@ -98,7 +100,7 @@ export function GenericAppShell({ app }: GenericAppShellProps) {
98
100
  ${sidebarOpen ? 'translate-x-0' : '-translate-x-full'}
99
101
  `}>
100
102
  <div className="flex items-center gap-3 h-16 px-6 border-b border-slate-200">
101
- <img src="/spine-logo.svg" alt="Spine Framework" className="h-8 w-auto shrink-0" />
103
+ <img src={branding.logo_url} alt={branding.app_name} className="h-8 w-auto shrink-0" />
102
104
  <div>
103
105
  <h2 className="font-semibold text-slate-900 text-sm">{app.name}</h2>
104
106
  {app.description && (
@@ -10,17 +10,17 @@
10
10
 
11
11
  import { useState, useEffect } from 'react'
12
12
  import { useParams, useSearchParams, useNavigate } from 'react-router-dom'
13
+ import { apiFetch } from '../../lib/api'
13
14
  import { useEntityRecord } from '../../hooks/useEntityRecord'
14
15
  import { DataDetailHeader } from '../runtime/DataDetailHeader'
15
16
  import { SchemaDetailForm } from '../runtime/SchemaDetailForm'
17
+ // CIL[END stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:module_header:module_header"]
16
18
  // CIL[DOC-VECTOR type="context" content="purpose='Imports and module setup for the generic detail page'; No verified external callers; imports: .framework/src/hooks/useEntityRecord.ts,.framework/src/components/runtime/DataDetailHeader.tsx,.framework/src/components/runtime/SchemaDetailForm.tsx"]
17
19
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
18
20
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
19
21
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
20
22
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
21
23
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
22
- // CIL[END stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:module_header:module_header"]
23
- // CIL[BEGIN stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPageProps:interface" type="interface" identity="GenericDetailPageProps" parent="~/.framework/src/components/app-shell/GenericDetailPage.tsx"]
24
24
  // CIL[DOC-MACRO purpose="Props interface for GenericDetailPage"]
25
25
  // CIL[DOC-RESPONSIBILITY responsibility="Define the expected props for the detail page"]
26
26
  // CIL[DOC-CONTEXT module="app-shell" layer="framework" related_files=".framework/src/components/app-shell/GenericDetailPage.tsx,.framework/src/components/runtime/DataDetailHeader.tsx,.framework/src/components/runtime/SchemaDetailForm.tsx,.framework/src/hooks/useEntityRecord.ts"]
@@ -28,21 +28,21 @@ import { SchemaDetailForm } from '../runtime/SchemaDetailForm'
28
28
  // CIL[DOC-MICRO logic_summary="TypeScript interface describing typeSlug, viewSlug, and isCreating" notable_decisions="[]"]
29
29
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
30
30
  // CIL[DOC-STABILITY stability="stable"]
31
+ // CIL[BEGIN stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPageProps:interface" type="interface" identity="GenericDetailPageProps" parent="~/.framework/src/components/app-shell/GenericDetailPage.tsx"]
31
32
  interface GenericDetailPageProps {
32
33
  typeSlug: string
33
34
  viewSlug?: string
34
35
  isCreating?: boolean
35
36
  }
37
+ // CIL[END stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPageProps:interface"]
36
38
  // CIL[DOC-VECTOR type="context" content="purpose='Props interface for GenericDetailPage'; No verified external callers; imports: .framework/src/hooks/useEntityRecord.ts,.framework/src/components/runtime/DataDetailHeader.tsx,.framework/src/components/runtime/SchemaDetailForm.tsx"]
37
39
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
38
40
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
39
41
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
40
42
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
41
43
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
42
- // CIL[END stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPageProps:interface"]
43
44
 
44
45
 
45
- // CIL[BEGIN stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPage:component" type="component" identity="GenericDetailPage" parent="~/.framework/src/components/app-shell/GenericDetailPage.tsx"]
46
46
  // CIL[DOC-MACRO purpose="Render the generic detail page for an app type"]
47
47
  // CIL[DOC-RESPONSIBILITY responsibility="Display, edit, create, and delete records driven by a design schema"]
48
48
  // CIL[DOC-CONTEXT module="app-shell" layer="framework" related_files=".framework/src/components/app-shell/GenericDetailPage.tsx,.framework/src/components/runtime/DataDetailHeader.tsx,.framework/src/components/runtime/SchemaDetailForm.tsx,.framework/src/hooks/useEntityRecord.ts"]
@@ -50,6 +50,7 @@ interface GenericDetailPageProps {
50
50
  // CIL[DOC-MICRO logic_summary="Load record with useEntityRecord, resolve detail view, initialize form data, and render DataDetailHeader and SchemaDetailForm" notable_decisions="[]"]
51
51
  // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
52
52
  // CIL[DOC-STABILITY stability="stable"]
53
+ // CIL[BEGIN stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPage:component" type="component" identity="GenericDetailPage" parent="~/.framework/src/components/app-shell/GenericDetailPage.tsx"]
53
54
  export function GenericDetailPage({ typeSlug, viewSlug, isCreating: forceCreate }: GenericDetailPageProps) {
54
55
  const { id } = useParams<{ id: string }>()
55
56
  const navigate = useNavigate()
@@ -83,10 +84,31 @@ export function GenericDetailPage({ typeSlug, viewSlug, isCreating: forceCreate
83
84
  deleting
84
85
  } = useEntityRecord('items', id, config)
85
86
 
86
-
87
- const schema = record?.design_schema || null
88
- const resolvedDetailView = viewSlug
89
- ? schema?.views?.[viewSlug] || schema?.views?.default_detail
87
+ // In create mode there is no record to take a stamped design_schema from —
88
+ // resolve it from the type instead (get_type_schema RPC via /api/types).
89
+ const [typeSchema, setTypeSchema] = useState<any>(null)
90
+ const [schemaLoading, setSchemaLoading] = useState(false)
91
+ useEffect(() => {
92
+ if (!isCreating) return
93
+ let cancelled = false
94
+ setSchemaLoading(true)
95
+ apiFetch(`/api/types?action=schema&kind=item&slug=${encodeURIComponent(typeSlug)}`)
96
+ .then(async (res) => {
97
+ const result = await res.json()
98
+ const ds = (result.data ?? result)?.design_schema
99
+ if (!cancelled) setTypeSchema(ds && Object.keys(ds).length ? ds : null)
100
+ })
101
+ .catch(() => { if (!cancelled) setTypeSchema(null) })
102
+ .finally(() => { if (!cancelled) setSchemaLoading(false) })
103
+ return () => { cancelled = true }
104
+ }, [isCreating, typeSlug])
105
+
106
+ const schema = record?.design_schema || typeSchema || null
107
+ // nav_item `view` is a single slug shared by list + detail pages; a
108
+ // list-shaped view (fields, no sections) must not resolve here.
109
+ const namedView = viewSlug ? schema?.views?.[viewSlug] : null
110
+ const resolvedDetailView = namedView && (namedView.type === 'detail' || namedView.sections)
111
+ ? namedView
90
112
  : schema?.views?.default_detail
91
113
  const view = resolvedDetailView || null
92
114
 
@@ -175,7 +197,7 @@ export function GenericDetailPage({ typeSlug, viewSlug, isCreating: forceCreate
175
197
  }
176
198
  }
177
199
 
178
- if (loading) {
200
+ if (loading || schemaLoading) {
179
201
  return (
180
202
  <div className="p-8 text-center">
181
203
  <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto"></div>
@@ -193,11 +215,13 @@ export function GenericDetailPage({ typeSlug, viewSlug, isCreating: forceCreate
193
215
  )
194
216
  }
195
217
 
196
- if (!schema && !isCreating) {
218
+ if (!schema) {
197
219
  return (
198
220
  <div className="p-8 text-center">
199
221
  <h2 className="text-lg font-medium text-slate-900">No schema available</h2>
200
- <p className="mt-2 text-sm text-slate-500">This record does not have a design_schema.</p>
222
+ <p className="mt-2 text-sm text-slate-500">
223
+ {isCreating ? `No design_schema found for type "${typeSlug}".` : 'This record does not have a design_schema.'}
224
+ </p>
201
225
  </div>
202
226
  )
203
227
  }
@@ -233,10 +257,10 @@ export function GenericDetailPage({ typeSlug, viewSlug, isCreating: forceCreate
233
257
  </div>
234
258
  )
235
259
  }
260
+ // CIL[END stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPage:component"]
236
261
  // CIL[DOC-VECTOR type="context" content="purpose='Render the generic detail page for an app type'; No verified external callers; imports: .framework/src/hooks/useEntityRecord.ts,.framework/src/components/runtime/DataDetailHeader.tsx,.framework/src/components/runtime/SchemaDetailForm.tsx"]
237
262
  // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
238
263
  // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
239
264
  // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
240
265
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
241
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
242
- // CIL[END stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPage:component"]
266
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]