spine-framework 0.3.145 → 0.4.0

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 (451) hide show
  1. package/.env.example +76 -0
  2. package/.framework/.spine-manifest.json +19 -0
  3. package/.framework/cli/commands/agents.ts +61 -33
  4. package/.framework/cli/commands/auth.ts +60 -28
  5. package/.framework/cli/commands/create-app.ts +212 -80
  6. package/.framework/cli/commands/dev.ts +184 -68
  7. package/.framework/cli/commands/doctor.ts +324 -152
  8. package/.framework/cli/commands/generate.ts +119 -68
  9. package/.framework/cli/commands/init.ts +141 -242
  10. package/.framework/cli/commands/install-app.ts +1336 -314
  11. package/.framework/cli/commands/items.ts +31 -29
  12. package/.framework/cli/commands/migrate.ts +299 -156
  13. package/.framework/cli/commands/migrations.ts +62 -30
  14. package/.framework/cli/commands/pipelines.ts +31 -29
  15. package/.framework/cli/commands/status.ts +105 -45
  16. package/.framework/cli/commands/system.ts +47 -42
  17. package/.framework/cli/commands/test.ts +161 -102
  18. package/.framework/cli/commands/upgrade.ts +260 -0
  19. package/.framework/cli/commands/validate-app.ts +517 -161
  20. package/.framework/cli/context.ts +117 -85
  21. package/.framework/cli/env-loader.ts +74 -43
  22. package/.framework/cli/index.ts +70 -46
  23. package/.framework/cli/lib/project-files.ts +404 -0
  24. package/.framework/docs/guides/testing-guide.md +1 -1
  25. package/.framework/docs/runtime-types.md +72 -72
  26. package/.framework/functions/_shared/access.ts +84 -0
  27. package/.framework/functions/_shared/agent-runner.ts +5051 -1026
  28. package/.framework/functions/_shared/app-manifest.ts +214 -94
  29. package/.framework/functions/_shared/ast.ts +214 -0
  30. package/.framework/functions/_shared/audit.ts +91 -55
  31. package/.framework/functions/_shared/cil.ts +368 -127
  32. package/.framework/functions/_shared/db.ts +337 -68
  33. package/.framework/functions/_shared/funnel.ts +228 -0
  34. package/.framework/functions/_shared/geo.ts +105 -0
  35. package/.framework/functions/_shared/hash-api-key.ts +94 -17
  36. package/.framework/functions/_shared/index.ts +22 -224
  37. package/.framework/functions/_shared/kb.ts +832 -58
  38. package/.framework/functions/_shared/llm.ts +118 -18
  39. package/.framework/functions/_shared/logging.ts +317 -19
  40. package/.framework/functions/_shared/middleware.ts +701 -131
  41. package/.framework/functions/_shared/notify.ts +70 -0
  42. package/.framework/functions/_shared/outcomes.ts +34 -19
  43. package/.framework/functions/_shared/permissions.ts +501 -315
  44. package/.framework/functions/_shared/pipeline-runner.ts +704 -155
  45. package/.framework/functions/_shared/principal.ts +436 -263
  46. package/.framework/functions/_shared/rate-limit.ts +233 -0
  47. package/.framework/functions/_shared/resolve-credentials.ts +86 -19
  48. package/.framework/functions/_shared/resolve-ids.ts +203 -139
  49. package/.framework/functions/_shared/retry-deliveries.ts +51 -16
  50. package/.framework/functions/_shared/schema-utils.ts +602 -521
  51. package/.framework/functions/_shared/security.ts +345 -0
  52. package/.framework/functions/_shared/testing.ts +197 -172
  53. package/.framework/functions/_shared/tracing.ts +351 -21
  54. package/.framework/functions/_shared/trigger-engine.ts +425 -136
  55. package/.framework/functions/_shared/webhook-registration.ts +71 -70
  56. package/.framework/functions/_shared/webhook-registry.ts +126 -83
  57. package/.framework/functions/account-nodes.ts +30 -30
  58. package/.framework/functions/adapters/generic-webhook-inbound.ts +49 -16
  59. package/.framework/functions/adapters/generic-webhook-outbound.ts +17 -17
  60. package/.framework/functions/adapters/openai-outbound.ts +15 -16
  61. package/.framework/functions/admin-data.ts +596 -173
  62. package/.framework/functions/admin-funnel.ts +64 -60
  63. package/.framework/functions/admin-install-funnel.ts +84 -66
  64. package/.framework/functions/admin-signals.ts +69 -51
  65. package/.framework/functions/ai-agents.ts +431 -106
  66. package/.framework/functions/ai-interactions.ts +186 -112
  67. package/.framework/functions/api-keys.ts +107 -107
  68. package/.framework/functions/apps.ts +154 -136
  69. package/.framework/functions/auth.ts +83 -65
  70. package/.framework/functions/cil-agent-ingest.ts +189 -232
  71. package/.framework/functions/cil-agent.ts +433 -177
  72. package/.framework/functions/cil-callmap.ts +642 -430
  73. package/.framework/functions/cil-config.ts +139 -135
  74. package/.framework/functions/cil-context.ts +214 -127
  75. package/.framework/functions/cil-doc.ts +587 -458
  76. package/.framework/functions/cil-embeddings.ts +453 -364
  77. package/.framework/functions/cil-graph.ts +427 -142
  78. package/.framework/functions/cil-ingest.ts +1418 -1154
  79. package/.framework/functions/cil-pipeline.ts +276 -21
  80. package/.framework/functions/cil-project.ts +659 -132
  81. package/.framework/functions/cil-validate.ts +198 -164
  82. package/.framework/functions/debug-auth.ts +57 -55
  83. package/.framework/functions/deliveries.ts +80 -21
  84. package/.framework/functions/embeddings.ts +1023 -318
  85. package/.framework/functions/eval-harness.ts +146 -108
  86. package/.framework/functions/integration-outbound.ts +205 -75
  87. package/.framework/functions/integration-routes.ts +128 -23
  88. package/.framework/functions/integrations.ts +125 -100
  89. package/.framework/functions/invites.ts +1095 -460
  90. package/.framework/functions/item-progress.ts +158 -102
  91. package/.framework/functions/kb.ts +34 -10
  92. package/.framework/functions/logs.ts +133 -133
  93. package/.framework/functions/observability.ts +152 -122
  94. package/.framework/functions/pipeline-executions.ts +147 -132
  95. package/.framework/functions/pipelines.ts +134 -119
  96. package/.framework/functions/prompt-configs.ts +96 -80
  97. package/.framework/functions/roles.ts +112 -82
  98. package/.framework/functions/security.ts +450 -0
  99. package/.framework/functions/system-cron.ts +117 -80
  100. package/.framework/functions/system.ts +158 -98
  101. package/.framework/functions/tests.ts +29 -29
  102. package/.framework/functions/timers.ts +94 -95
  103. package/.framework/functions/trigger-scheduler.ts +10 -0
  104. package/.framework/functions/triggers.ts +179 -149
  105. package/.framework/functions/types.ts +137 -125
  106. package/.framework/mcp/index.ts +133 -0
  107. package/.framework/mcp/load-env.ts +60 -0
  108. package/.framework/mcp/shared/app-manifest.ts +275 -0
  109. package/.framework/mcp/shared/db.ts +477 -0
  110. package/.framework/mcp/shared/kb.ts +118 -0
  111. package/.framework/mcp/tools/architect.ts +431 -0
  112. package/.framework/mcp/tools/cil/context.ts +345 -0
  113. package/.framework/mcp/tools/cil/graph.ts +242 -0
  114. package/.framework/mcp/tools/cil/ingest.ts +1217 -0
  115. package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +693 -0
  116. package/.framework/mcp/tools/cil/pipeline.ts +767 -0
  117. package/.framework/mcp/tools/cil/project.ts +791 -0
  118. package/.framework/mcp/tools/cil/retrieval.ts +336 -0
  119. package/.framework/mcp/tools/cil/search-core.ts +454 -0
  120. package/.framework/mcp/tools/cil/search.ts +97 -0
  121. package/.framework/mcp/tools/cil/suggest.ts +186 -0
  122. package/.framework/mcp/tools/cil/validate.ts +1369 -0
  123. package/.framework/mcp/tools/kb/delete.ts +139 -0
  124. package/.framework/mcp/tools/kb/index.ts +52 -0
  125. package/.framework/mcp/tools/kb/ingest.ts +84 -0
  126. package/.framework/mcp/tools/kb/list-types.ts +102 -0
  127. package/.framework/mcp/tools/kb/publish.ts +100 -0
  128. package/.framework/mcp/tools/kb/reindex.ts +86 -0
  129. package/.framework/mcp/tools/kb/revoke.ts +85 -0
  130. package/.framework/mcp/tools/kb/search.ts +101 -0
  131. package/.framework/mcp/tools/kb/upsert.ts +125 -0
  132. package/.framework/mcp/tools/observability.ts +510 -0
  133. package/.framework/migrations/001_core_schema.sql +15 -0
  134. package/.framework/migrations/002_core_rls_and_functions.sql +15 -0
  135. package/.framework/migrations/003_core_system_data.sql +16 -1
  136. package/.framework/migrations/004_core_rpc_and_broker.sql +17 -1
  137. package/.framework/migrations/005_core_observability.sql +17 -1
  138. package/.framework/migrations/006_security_hardening_rls.sql +15 -0
  139. package/.framework/migrations/007_kb_article_list.sql +17 -1
  140. package/.framework/migrations/008_items_target.sql +15 -0
  141. package/.framework/migrations/009_roles_slug_unique.sql +15 -0
  142. package/.framework/migrations/010_auth_user_trigger.sql +15 -0
  143. package/.framework/migrations/011_spine_system_account.sql +16 -0
  144. package/.framework/migrations/012_service_role_grants.sql +16 -0
  145. package/.framework/migrations/013_get_account_apps_role_filter.sql +15 -0
  146. package/.framework/migrations/014_apps_required_roles.sql +16 -0
  147. package/.framework/migrations/015_types_kind_slug_unique.sql +15 -0
  148. package/.framework/migrations/016_cil_types.sql +281 -0
  149. package/.framework/migrations/017_cil_stable_ids.sql +37 -0
  150. package/.framework/migrations/018_runtime_tables.sql +129 -0
  151. package/.framework/migrations/019_agent_prompt_columns.sql +56 -0
  152. package/.framework/migrations/020_schema_reconciliation.sql +67 -0
  153. package/.framework/migrations/021_kb_embedding_lifecycle.sql +31 -0
  154. package/.framework/migrations/032_cil_status_migration.sql +73 -0
  155. package/.framework/migrations/033_cil_versioning.sql +73 -0
  156. package/.framework/migrations/034_match_embeddings_knn.sql +115 -0
  157. package/.framework/migrations/035_rate_limits.sql +55 -0
  158. package/.framework/migrations/036_demo_record_flags.sql +72 -0
  159. package/.framework/migrations/037_kb_types_canonical.sql +244 -0
  160. package/.framework/migrations/038_drop_demo_record_flags.sql +38 -0
  161. package/.framework/migrations/042_registration_hierarchy.sql +309 -0
  162. package/.framework/migrations/043_policy_actor_cleanup.sql +39 -0
  163. package/.framework/migrations/044_match_embeddings_filtered_knn.sql +151 -0
  164. package/.framework/migrations/045_security_critical_rls.sql +139 -0
  165. package/.framework/migrations/046_security_missing_rls.sql +79 -0
  166. package/.framework/migrations/047_people_updated_by.sql +27 -0
  167. package/.framework/migrations/048_watcher_last_seen_at.sql +24 -0
  168. package/.framework/migrations/049_security_blocklist.sql +148 -0
  169. package/.framework/migrations/050_notifications.sql +49 -0
  170. package/.framework/migrations/051_message_agent_fields.sql +74 -0
  171. package/.framework/migrations/052_registration_security.sql +421 -0
  172. package/.framework/migrations/053_builtin_action_seeds.sql +66 -0
  173. package/.framework/migrations/054_kb_ingest_lease.sql +157 -0
  174. package/.framework/migrations/055_type_id_drift_reconciliation.sql +33 -0
  175. package/.framework/migrations/056_slug_column_reconciliation.sql +38 -0
  176. package/.framework/migrations/057_pipelines_slug_identity.sql +14 -0
  177. package/.framework/migrations/058_account_data_field_declarations.sql +53 -0
  178. package/.framework/migrations/059_registration_placement_fixes.sql +269 -0
  179. package/.framework/migrations/060_account_person_record_permissions.sql +38 -0
  180. package/.framework/migrations/061_fk_dedup.sql +32 -0
  181. package/.framework/public/spine-logo.svg +10 -3
  182. package/.framework/scripts/app-install-cli.ts +190 -93
  183. package/.framework/scripts/assemble-frontend.sh +127 -44
  184. package/.framework/scripts/assemble-functions.sh +128 -30
  185. package/.framework/scripts/boundary-check.sh +6 -2
  186. package/.framework/scripts/build-manifest.sh +24 -68
  187. package/.framework/scripts/check-core-integrity.sh +15 -76
  188. package/.framework/scripts/checksum-manifest.mts +343 -0
  189. package/.framework/scripts/cil-migrate-markers.ts +403 -0
  190. package/.framework/scripts/fix-cil-markers.mjs +176 -0
  191. package/.framework/scripts/verify-integrity.sh +21 -57
  192. package/.framework/scripts/verify-manifest.mts +305 -0
  193. package/.framework/seeds/types/funnel_signal_use.json +74 -21
  194. package/.framework/seeds/types/spine_instance.json +73 -21
  195. package/.framework/src/App.tsx +118 -72
  196. package/.framework/src/apps/admin/index.tsx +855 -58
  197. package/.framework/src/components/AppWrapper.tsx +43 -45
  198. package/.framework/src/components/CustomAppLoader.tsx +160 -116
  199. package/.framework/src/components/admin/AdminListPage.tsx +46 -44
  200. package/.framework/src/components/admin/AdminSidebar.tsx +57 -47
  201. package/.framework/src/components/admin/AdminStatsCard.tsx +46 -44
  202. package/.framework/src/components/admin/PageInstructions.tsx +98 -2
  203. package/.framework/src/components/admin/SortableTableHeader.tsx +44 -45
  204. package/.framework/src/components/app-shell/GenericAppShell.tsx +64 -65
  205. package/.framework/src/components/app-shell/GenericDetailPage.tsx +44 -47
  206. package/.framework/src/components/app-shell/GenericListPage.tsx +45 -49
  207. package/.framework/src/components/app-sidebar.tsx +42 -45
  208. package/.framework/src/components/auth/ProtectedRoute.tsx +48 -41
  209. package/.framework/src/components/auth/TurnstileWidget.tsx +27 -0
  210. package/.framework/src/components/kb/KBArticleEditor.tsx +231 -22
  211. package/.framework/src/components/kb/KBArticleList.tsx +251 -10
  212. package/.framework/src/components/layout/AppShell.tsx +51 -45
  213. package/.framework/src/components/layout/Header.tsx +42 -43
  214. package/.framework/src/components/layout/Layout.tsx +46 -46
  215. package/.framework/src/components/layout/Sidebar.tsx +196 -96
  216. package/.framework/src/components/runtime/DataDetailHeader.tsx +55 -30
  217. package/.framework/src/components/runtime/DataDetailPage.tsx +31 -269
  218. package/.framework/src/components/runtime/DataFilters.tsx +49 -74
  219. package/.framework/src/components/runtime/DataHeader.tsx +53 -32
  220. package/.framework/src/components/runtime/DataListPage.tsx +51 -155
  221. package/.framework/src/components/runtime/DataStats.tsx +66 -44
  222. package/.framework/src/components/runtime/DataTable.tsx +49 -149
  223. package/.framework/src/components/runtime/SchemaDetailForm.tsx +45 -75
  224. package/.framework/src/components/runtime/index.ts +119 -16
  225. package/.framework/src/components/search-form.tsx +46 -29
  226. package/.framework/src/components/shared/AgentView.tsx +65 -48
  227. package/.framework/src/components/shared/FieldRenderer.tsx +144 -50
  228. package/.framework/src/components/shared/InviteManager.tsx +207 -97
  229. package/.framework/src/components/shared/MemberList.tsx +97 -0
  230. package/.framework/src/components/shared/SchemaFields.tsx +107 -86
  231. package/.framework/src/components/ui/DataTable.tsx +80 -68
  232. package/.framework/src/components/ui/Form.tsx +157 -146
  233. package/.framework/src/components/ui/ItemCard.tsx +74 -67
  234. package/.framework/src/components/ui/ItemListView.tsx +73 -68
  235. package/.framework/src/components/ui/LoadingSpinner.tsx +43 -48
  236. package/.framework/src/components/ui/Modal.tsx +78 -68
  237. package/.framework/src/components/ui/RichTextEditor.tsx +89 -69
  238. package/.framework/src/components/ui/accordion.tsx +85 -86
  239. package/.framework/src/components/ui/alert-dialog.tsx +197 -184
  240. package/.framework/src/components/ui/alert.tsx +105 -94
  241. package/.framework/src/components/ui/aspect-ratio.tsx +57 -43
  242. package/.framework/src/components/ui/avatar.tsx +122 -107
  243. package/.framework/src/components/ui/badge.tsx +60 -55
  244. package/.framework/src/components/ui/breadcrumb.tsx +127 -128
  245. package/.framework/src/components/ui/button-group.tsx +86 -72
  246. package/.framework/src/components/ui/button.tsx +71 -50
  247. package/.framework/src/components/ui/calendar.tsx +72 -57
  248. package/.framework/src/components/ui/card.tsx +136 -129
  249. package/.framework/src/components/ui/carousel.tsx +226 -107
  250. package/.framework/src/components/ui/chart.tsx +252 -147
  251. package/.framework/src/components/ui/checkbox.tsx +43 -44
  252. package/.framework/src/components/ui/collapsible.tsx +86 -71
  253. package/.framework/src/components/ui/combobox.tsx +282 -249
  254. package/.framework/src/components/ui/command.tsx +158 -146
  255. package/.framework/src/components/ui/context-menu.tsx +239 -240
  256. package/.framework/src/components/ui/dialog.tsx +174 -157
  257. package/.framework/src/components/ui/direction.tsx +72 -56
  258. package/.framework/src/components/ui/drawer.tsx +168 -169
  259. package/.framework/src/components/ui/dropdown-menu.tsx +254 -223
  260. package/.framework/src/components/ui/empty.tsx +131 -120
  261. package/.framework/src/components/ui/field.tsx +205 -173
  262. package/.framework/src/components/ui/hover-card.tsx +71 -72
  263. package/.framework/src/components/ui/input-group.tsx +148 -133
  264. package/.framework/src/components/ui/input-otp.tsx +99 -86
  265. package/.framework/src/components/ui/input.tsx +43 -41
  266. package/.framework/src/components/ui/item.tsx +207 -185
  267. package/.framework/src/components/ui/kbd.tsx +57 -56
  268. package/.framework/src/components/ui/label.tsx +45 -41
  269. package/.framework/src/components/ui/menubar.tsx +268 -236
  270. package/.framework/src/components/ui/native-select.tsx +85 -86
  271. package/.framework/src/components/ui/navigation-menu.tsx +166 -156
  272. package/.framework/src/components/ui/pagination.tsx +131 -141
  273. package/.framework/src/components/ui/popover.tsx +125 -128
  274. package/.framework/src/components/ui/progress.tsx +47 -44
  275. package/.framework/src/components/ui/radio-group.tsx +60 -55
  276. package/.framework/src/components/ui/resizable.tsx +85 -72
  277. package/.framework/src/components/ui/scroll-area.tsx +57 -58
  278. package/.framework/src/components/ui/select.tsx +182 -169
  279. package/.framework/src/components/ui/separator.tsx +42 -43
  280. package/.framework/src/components/ui/sheet.tsx +170 -159
  281. package/.framework/src/components/ui/sidebar.tsx +395 -398
  282. package/.framework/src/components/ui/skeleton.tsx +42 -43
  283. package/.framework/src/components/ui/slider.tsx +61 -44
  284. package/.framework/src/components/ui/sonner.tsx +44 -44
  285. package/.framework/src/components/ui/spinner.tsx +47 -42
  286. package/.framework/src/components/ui/switch.tsx +56 -42
  287. package/.framework/src/components/ui/table-primitives.tsx +272 -132
  288. package/.framework/src/components/ui/table.tsx +140 -142
  289. package/.framework/src/components/ui/tabs.tsx +110 -93
  290. package/.framework/src/components/ui/textarea.tsx +43 -44
  291. package/.framework/src/components/ui/toggle-group.tsx +87 -71
  292. package/.framework/src/components/ui/toggle.tsx +56 -56
  293. package/.framework/src/components/ui/tooltip.tsx +99 -85
  294. package/.framework/src/contexts/AppContext.tsx +166 -114
  295. package/.framework/src/contexts/AuthContext.tsx +232 -137
  296. package/.framework/src/hooks/use-mobile.ts +43 -44
  297. package/.framework/src/hooks/useApi.ts +185 -172
  298. package/.framework/src/hooks/useAppPath.ts +31 -29
  299. package/.framework/src/hooks/useApps.ts +77 -42
  300. package/.framework/src/hooks/useEntityList.ts +66 -29
  301. package/.framework/src/hooks/useEntityRecord.ts +76 -32
  302. package/.framework/src/hooks/useForm.ts +62 -30
  303. package/.framework/src/hooks/useListSchema.ts +60 -43
  304. package/.framework/src/hooks/useSchemaRecord.ts +115 -95
  305. package/.framework/src/lib/api.ts +258 -134
  306. package/.framework/src/lib/registration.ts +181 -0
  307. package/.framework/src/lib/supabase.ts +118 -81
  308. package/.framework/src/lib/utils.ts +266 -266
  309. package/.framework/src/main.tsx +43 -44
  310. package/.framework/src/pages/DashboardPage.tsx +44 -43
  311. package/.framework/src/pages/NoAppPage.tsx +50 -0
  312. package/.framework/src/pages/NotFoundPage.tsx +32 -29
  313. package/.framework/src/pages/SetupPage.tsx +34 -33
  314. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +69 -58
  315. package/.framework/src/pages/admin/AIAgentsPage.tsx +43 -40
  316. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +63 -55
  317. package/.framework/src/pages/admin/APIKeysPage.tsx +44 -42
  318. package/.framework/src/pages/admin/AlertsConfigPage.tsx +117 -94
  319. package/.framework/src/pages/admin/AppDetailPage.tsx +48 -42
  320. package/.framework/src/pages/admin/AppsPage.tsx +45 -42
  321. package/.framework/src/pages/admin/DeliveriesPage.tsx +49 -17
  322. package/.framework/src/pages/admin/DesignedPage.tsx +31 -30
  323. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +58 -0
  324. package/.framework/src/pages/admin/EmbeddingsPage.tsx +49 -0
  325. package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +31 -29
  326. package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +46 -29
  327. package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -29
  328. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +68 -55
  329. package/.framework/src/pages/admin/IntegrationsPage.tsx +45 -42
  330. package/.framework/src/pages/admin/InvitesPage.tsx +60 -44
  331. package/.framework/src/pages/admin/LogsPage.tsx +87 -137
  332. package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +31 -29
  333. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +150 -89
  334. package/.framework/src/pages/admin/PipelineDetailPage.tsx +77 -104
  335. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +44 -43
  336. package/.framework/src/pages/admin/PipelinesPage.tsx +59 -145
  337. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +53 -42
  338. package/.framework/src/pages/admin/PromptConfigsPage.tsx +47 -117
  339. package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +31 -44
  340. package/.framework/src/pages/admin/RoleDetailPage.tsx +49 -92
  341. package/.framework/src/pages/admin/RolesPage.tsx +47 -164
  342. package/.framework/src/pages/admin/SecurityPage.tsx +310 -0
  343. package/.framework/src/pages/admin/SelectTestPage.tsx +30 -32
  344. package/.framework/src/pages/admin/ShadcnTestPage.tsx +37 -44
  345. package/.framework/src/pages/admin/SimpleDashboard.tsx +32 -44
  346. package/.framework/src/pages/admin/TestRunDetailPage.tsx +97 -44
  347. package/.framework/src/pages/admin/TestingDashboard.tsx +126 -71
  348. package/.framework/src/pages/admin/TimerDetailPage.tsx +67 -55
  349. package/.framework/src/pages/admin/TimersPage.tsx +44 -42
  350. package/.framework/src/pages/admin/TriggerDetailPage.tsx +47 -42
  351. package/.framework/src/pages/admin/TriggersPage.tsx +58 -57
  352. package/.framework/src/pages/admin/TypeDetailPage.tsx +91 -55
  353. package/.framework/src/pages/admin/TypesPage.tsx +45 -42
  354. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +258 -128
  355. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +127 -123
  356. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +308 -235
  357. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +159 -110
  358. package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +432 -0
  359. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +200 -178
  360. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +286 -239
  361. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +211 -90
  362. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +156 -143
  363. package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +379 -0
  364. package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +337 -0
  365. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +219 -214
  366. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
  367. package/.framework/src/pages/auth/AuthConfirmPage.tsx +135 -65
  368. package/.framework/src/pages/auth/ForgotPasswordPage.tsx +39 -31
  369. package/.framework/src/pages/auth/LoginPage.tsx +38 -32
  370. package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -28
  371. package/.framework/src/pages/auth/RegisterPage.tsx +429 -155
  372. package/.framework/src/pages/spine-framework/APIPage.tsx +33 -30
  373. package/.framework/src/pages/spine-framework/CLIPage.tsx +32 -30
  374. package/.framework/src/types/auth.ts +101 -93
  375. package/.framework/src/types/types.ts +283 -262
  376. package/.framework/templates/project.json +87 -0
  377. package/.framework/templates/spine.config.neutral.json +7 -0
  378. package/.framework/tests/api/api-surface.test.ts +381 -0
  379. package/.framework/tests/fixtures/seed.ts +427 -0
  380. package/.framework/tests/fixtures/teardown.ts +228 -0
  381. package/.framework/tests/reporter.ts +351 -0
  382. package/.framework/tests/setup.ts +135 -0
  383. package/.framework/tests/ui/ui-sweep.ts +278 -0
  384. package/.framework/tests/unit/admin-data-logger.test.ts +310 -0
  385. package/.framework/tests/unit/agent-runner.test.ts +2389 -0
  386. package/.framework/tests/unit/ai-interactions.test.ts +81 -0
  387. package/.framework/tests/unit/app-manifest.test.ts +359 -0
  388. package/.framework/tests/unit/assembly-scripts.test.ts +172 -0
  389. package/.framework/tests/unit/cil-determinism.test.ts +85 -0
  390. package/.framework/tests/unit/core-isolation.test.ts +153 -0
  391. package/.framework/tests/unit/funnel-signals.test.ts +135 -0
  392. package/.framework/tests/unit/install-app.test.ts +1759 -0
  393. package/.framework/tests/unit/invites-security.test.ts +572 -0
  394. package/.framework/tests/unit/kb-ingest-lease.test.ts +287 -0
  395. package/.framework/tests/unit/kb-search.test.ts +119 -0
  396. package/.framework/tests/unit/migrate.test.ts +509 -0
  397. package/.framework/tests/unit/notify.test.ts +136 -0
  398. package/.framework/tests/unit/permissions.test.ts +269 -0
  399. package/.framework/tests/unit/pipeline-runner.test.ts +755 -0
  400. package/.framework/tests/unit/principal-cache.test.ts +138 -0
  401. package/.framework/tests/unit/retrieval-golden.test.ts +520 -0
  402. package/.framework/tests/unit/runtime-isolation.test.ts +642 -0
  403. package/.framework/tests/unit/schema-utils.test.ts +225 -0
  404. package/.framework/tests/unit/trigger-engine.test.ts +513 -0
  405. package/.framework/tests/unit/validate-app.test.ts +527 -0
  406. package/README.md +34 -3
  407. package/bin/spine-framework.cjs +1 -0
  408. package/config/tailwind.config.cjs +7 -0
  409. package/config/tsconfig.functions.json +42 -0
  410. package/config/tsconfig.json +37 -9
  411. package/config/vite.config.ts +31 -2
  412. package/netlify.toml +31 -3
  413. package/package.json +46 -29
  414. package/scripts/assemble-frontend.sh +127 -44
  415. package/scripts/assemble-functions.sh +127 -29
  416. package/scripts/boundary-check.sh +6 -2
  417. package/scripts/build-manifest.sh +24 -68
  418. package/scripts/checksum-manifest.mts +345 -0
  419. package/scripts/dev-clean.sh +86 -0
  420. package/scripts/dev-netlify.sh +49 -0
  421. package/scripts/netlify-dev-wrapper.sh +2 -0
  422. package/scripts/verify-install.ts +358 -0
  423. package/scripts/verify-integrity.sh +21 -57
  424. package/scripts/verify-manifest.mts +305 -0
  425. package/templates/project/gitignore +45 -0
  426. package/{config → templates/project}/package-lock.json +22335 -9366
  427. package/vitest.config.ts +46 -0
  428. package/.framework/public/spine.config.json +0 -91
  429. package/config/deno.lock +0 -108
  430. package/config/tsconfig.node.tsbuildinfo +0 -1
  431. package/config/tsconfig.tsbuildinfo +0 -1
  432. package/config/vite.config.d.ts +0 -2
  433. package/custom/.devin/AGENT.md +0 -357
  434. package/custom/.devin/skills/install-app/SKILL.md +0 -39
  435. package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +0 -39
  436. package/custom/.devin/skills/spine-workbench-idea/SKILL.md +0 -36
  437. package/custom/.devin/skills/spine-workbench-implement/SKILL.md +0 -46
  438. package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +0 -28
  439. package/custom/.devin/skills/spine-workbench-plan/SKILL.md +0 -38
  440. package/custom/.devin/workflows/app-install.yaml +0 -83
  441. package/custom/README.md +0 -79
  442. package/docs/README.md +0 -15
  443. package/scripts/app-install-cli.ts +0 -286
  444. package/scripts/check-core-integrity.sh +0 -82
  445. package/scripts/ingest-chunks.cjs +0 -202
  446. package/scripts/kb-chunk-parser.cjs +0 -312
  447. package/scripts/kb-chunk-parser.ts +0 -330
  448. package/scripts/kb-ingest-docs.ts +0 -203
  449. package/scripts/load-test-app-install.ts +0 -484
  450. package/scripts/test-login.js +0 -33
  451. package/spine.config.json +0 -91
@@ -1,3 +1,13 @@
1
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/cli/commands/validate-app.ts"]
2
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
3
+ // CIL[DOC-MACRO purpose="Provide module-level imports for the validate-app CLI command"]
4
+ // CIL[DOC-RESPONSIBILITY responsibility="Load required modules for CLI execution, filesystem inspection, path resolution and URL helpers"]
5
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
6
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
7
+ // CIL[DOC-MICRO logic_summary="Imports Command from commander, fs utilities, path helpers and url helpers" notable_decisions=""]
8
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
9
+ // CIL[DOC-STABILITY stable]
10
+
1
11
 
2
12
 
3
13
 
@@ -8,36 +18,88 @@
8
18
 
9
19
 
10
20
 
11
- // CIL[BEGIN chunk_id="validate-app_moduleheader_1784068794" type="module_header" identity="imports" parent="none"]
12
- // CIL[DOC-MACRO purpose="Import dependencies and define validation types"]
13
- // CIL[DOC-RESPONSIBILITY responsibility="Load required modules and define interfaces"]
14
- // CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[\".framework/functions/_shared/schema-utils.ts\",\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/functions/_shared/principal.ts\",\"\\\"]"]
15
- // CIL[DOC-CONTRACT inputs="none" outputs="loaded_modules" errors="none" side_effects="none"]
16
- // CIL[DOC-MICRO logic_summary="Imports file system, path utilities, Commander, and defines validation types" notable_decisions="[]"]
17
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
18
- // CIL[DOC-STABILITY stability="stable"]
19
- // CIL[DOC-AUDIENCE audience="developer"]
20
- // CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/functions/_shared/principal.ts, \."]
21
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
22
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
23
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
24
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
25
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
26
21
  import { Command } from 'commander'
27
- import { readFileSync, existsSync, readdirSync, statSync } from 'fs'
28
- import { join, dirname } from 'path'
22
+ import { readFileSync, existsSync, readdirSync, statSync, realpathSync } from 'fs'
23
+ import { join, dirname, resolve, isAbsolute, sep } from 'path'
29
24
  import { fileURLToPath } from 'url'
25
+ // CIL[DOC-VECTOR type="context" content="purpose='Provide module-level imports for the validate-app CLI command'; No verified external callers; imports: none"]
26
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
27
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
28
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
29
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
30
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
31
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:module_header:module_header"]
30
32
 
33
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:__filename:constant" type="constant" identity="__filename" parent="~/.framework/cli/commands/validate-app.ts"]
34
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
35
+ // CIL[DOC-MACRO purpose="Expose the current module filename for path resolution"]
36
+ // CIL[DOC-RESPONSIBILITY responsibility="Derive __filename from import.meta.url"]
37
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
38
+ // CIL[DOC-CONTRACT inputs="none" outputs="string" errors="none" side_effects="none"]
39
+ // CIL[DOC-MICRO logic_summary="Use fileURLToPath to convert import.meta.url to an absolute file path" notable_decisions=""]
40
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
41
+ // CIL[DOC-STABILITY stable]
31
42
  const __filename = fileURLToPath(import.meta.url)
43
+ // CIL[DOC-VECTOR type="context" content="purpose='Expose the current module filename for path resolution'; No verified external callers; imports: none"]
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/cli/commands/validate-app.ts:__filename:constant"]
50
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:__dirname:constant" type="constant" identity="__dirname" parent="~/.framework/cli/commands/validate-app.ts"]
51
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
52
+ // CIL[DOC-MACRO purpose="Expose the current module directory for path resolution"]
53
+ // CIL[DOC-RESPONSIBILITY responsibility="Derive __dirname from __filename"]
54
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
55
+ // CIL[DOC-CONTRACT inputs="none" outputs="string" errors="none" side_effects="none"]
56
+ // CIL[DOC-MICRO logic_summary="Use dirname to get the directory portion of __filename" notable_decisions=""]
57
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
58
+ // CIL[DOC-STABILITY stable]
32
59
  const __dirname = dirname(__filename)
60
+ // CIL[DOC-VECTOR type="context" content="purpose='Expose the current module directory for path resolution'; No verified external callers; imports: none"]
61
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
62
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
63
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
64
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
65
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
66
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:__dirname:constant"]
33
67
 
68
+
69
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:SeedEntry:interface" type="interface" identity="SeedEntry" parent="~/.framework/cli/commands/validate-app.ts"]
70
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
71
+ // CIL[DOC-MACRO purpose="Define the shape of a manifest seed entry"]
72
+ // CIL[DOC-RESPONSIBILITY responsibility="Declare the TypeScript interface for a single seed configuration used by validate-app"]
73
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
74
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
75
+ // CIL[DOC-MICRO logic_summary="Declares file, table, conflict and optional inject_app_id/permissions_patch fields" notable_decisions=""]
76
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
77
+ // CIL[DOC-STABILITY stable]
34
78
  interface SeedEntry {
35
79
  file: string
36
80
  table: string
37
81
  conflict: string
38
82
  inject_app_id?: boolean
83
+ permissions_patch?: boolean
39
84
  }
85
+ // CIL[DOC-VECTOR type="context" content="purpose='Define the shape of a manifest seed entry'; No verified external callers; imports: none"]
86
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
87
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
88
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
89
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
90
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
91
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:SeedEntry:interface"]
92
+
40
93
 
94
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:Manifest:interface" type="interface" identity="Manifest" parent="~/.framework/cli/commands/validate-app.ts"]
95
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
96
+ // CIL[DOC-MACRO purpose="Define the shape of an app manifest"]
97
+ // CIL[DOC-RESPONSIBILITY responsibility="Declare the TypeScript interface for the manifest.json structure used by validate-app"]
98
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
99
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
100
+ // CIL[DOC-MICRO logic_summary="Declares app metadata, type, entry points, seed, owned_types, registration and routing fields" notable_decisions=""]
101
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
102
+ // CIL[DOC-STABILITY stable]
41
103
  interface Manifest {
42
104
  name: string
43
105
  slug: string
@@ -46,15 +108,44 @@ interface Manifest {
46
108
  entry_point?: string
47
109
  sidebar_component?: string
48
110
  seed?: SeedEntry[]
111
+ owned_types?: string[]
112
+ config?: {
113
+ knowledge?: {
114
+ account?: boolean | { scope?: string; item_types?: string[] }
115
+ platform?: boolean | { sources?: string[] }
116
+ cil?: boolean | { project_ids?: string[] }
117
+ }
118
+ [key: string]: any
119
+ }
49
120
  registration?: {
50
121
  enabled?: boolean
122
+ app_type?: 'full' | 'ui' | 'backend' | 'data'
51
123
  default_role?: string
52
124
  redirect_path?: string
53
125
  account_strategy?: 'existing' | 'new' | 'choice'
54
126
  target_account?: string
127
+ parent_account?: string
128
+ default_workspace_name?: boolean
55
129
  }
56
130
  }
131
+ // CIL[DOC-VECTOR type="context" content="purpose='Define the shape of an app manifest'; No verified external callers; imports: none"]
132
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
133
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
134
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
135
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
136
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
137
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:Manifest:interface"]
138
+
57
139
 
140
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:PackageJson:interface" type="interface" identity="PackageJson" parent="~/.framework/cli/commands/validate-app.ts"]
141
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
142
+ // CIL[DOC-MACRO purpose="Define the shape of a package.json with spine configuration"]
143
+ // CIL[DOC-RESPONSIBILITY responsibility="Declare the TypeScript interface for package.json consumed by validate-app"]
144
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
145
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
146
+ // CIL[DOC-MICRO logic_summary="Declares name, version, files and the optional spine block fields" notable_decisions=""]
147
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
148
+ // CIL[DOC-STABILITY stable]
58
149
  interface PackageJson {
59
150
  name: string
60
151
  version: string
@@ -69,28 +160,47 @@ interface PackageJson {
69
160
  manifest?: string
70
161
  }
71
162
  }
163
+ // CIL[DOC-VECTOR type="context" content="purpose='Define the shape of a package.json with spine configuration'; No verified external callers; imports: none"]
164
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
165
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
166
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
167
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
168
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
169
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:PackageJson:interface"]
170
+
72
171
 
172
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:ValidationError:class" type="class" identity="ValidationError" parent="~/.framework/cli/commands/validate-app.ts"]
173
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
174
+ // CIL[DOC-MACRO purpose="Custom error type for app validation failures"]
175
+ // CIL[DOC-RESPONSIBILITY responsibility="Instantiate typed validation errors that identify validation problems"]
176
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
177
+ // CIL[DOC-CONTRACT inputs="message: string" outputs="ValidationError instance" errors="none" side_effects="none"]
178
+ // CIL[DOC-MICRO logic_summary="Extends Error and sets the name property to ValidationError" notable_decisions=""]
179
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
180
+ // CIL[DOC-STABILITY stable]
73
181
  class ValidationError extends Error {
74
182
  constructor(message: string) {
75
183
  super(message)
76
184
  this.name = 'ValidationError'
77
185
  }
78
186
  }
79
- // CIL[END chunk_id="validate-app_moduleheader_1784068794"]
80
- // CIL[BEGIN chunk_id="validate-app_validatemanifest_1784068794" type="function" identity="validateManifest" parent="none"]
81
- // CIL[DOC-MACRO purpose="Validate manifest.json structure and required fields"]
82
- // CIL[DOC-RESPONSIBILITY responsibility="Parse and validate manifest file"]
83
- // CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/functions/_shared/db.ts\",\".framework/functions/_shared/schema-utils.ts\",\"\\\"]"]
84
- // CIL[DOC-CONTRACT inputs="none" outputs="manifest" errors="validation_errors" side_effects="none"]
85
- // CIL[DOC-MICRO logic_summary="Validates JSON format, required fields, and app_type values" notable_decisions="[]"]
86
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
87
- // CIL[DOC-STABILITY stability="stable"]
88
- // CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, .framework/src/pages/admin/IntegrationsPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/functions/_shared/db.ts, .framework/functions/_shared/schema-utils.ts, \."]
89
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
90
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
91
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
187
+ // CIL[DOC-VECTOR type="context" content="purpose='Custom error type for app validation failures'; No verified external callers; imports: none"]
188
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
189
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
190
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
92
191
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
93
192
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
193
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:ValidationError:class"]
194
+
195
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:validateManifest:function" type="function" identity="validateManifest" parent="~/.framework/cli/commands/validate-app.ts"]
196
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
197
+ // CIL[DOC-MACRO purpose="Validate the presence and content of an app manifest.json"]
198
+ // CIL[DOC-RESPONSIBILITY responsibility="Check that manifest.json exists, is valid JSON, has required fields and a valid app_type"]
199
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
200
+ // CIL[DOC-CONTRACT inputs="appPath: string" outputs="Manifest" errors="ValidationError on missing file, invalid JSON or invalid fields" side_effects="none"]
201
+ // CIL[DOC-MICRO logic_summary="Resolve manifest path, read and parse, reject non-object roots, enforce required fields and allowed app_type values" notable_decisions=""]
202
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
203
+ // CIL[DOC-STABILITY stable]
94
204
  function validateManifest(appPath: string): Manifest {
95
205
  const manifestPath = join(appPath, 'manifest.json')
96
206
 
@@ -104,13 +214,25 @@ function validateManifest(appPath: string): Manifest {
104
214
  } catch (err) {
105
215
  throw new ValidationError('❌ manifest.json is not valid JSON')
106
216
  }
107
-
217
+
218
+ if (!manifest || typeof manifest !== 'object' || Array.isArray(manifest)) {
219
+ throw new ValidationError('❌ manifest.json must contain a JSON object')
220
+ }
221
+
222
+ if (manifest.app_type === undefined && manifest.registration?.app_type !== undefined) {
223
+ manifest.app_type = manifest.registration.app_type
224
+ }
225
+
108
226
  const requiredFields = ['name', 'slug', 'version', 'app_type']
109
227
  for (const field of requiredFields) {
110
228
  if (!manifest[field]) {
111
229
  throw new ValidationError(`❌ manifest.json missing required field: ${field}`)
112
230
  }
113
231
  }
232
+
233
+ if (typeof manifest.name !== 'string' || !manifest.name.trim()) {
234
+ throw new ValidationError(`❌ manifest.json missing required field: name`)
235
+ }
114
236
 
115
237
  const validAppTypes = ['full', 'ui', 'backend', 'data']
116
238
  if (!validAppTypes.includes(manifest.app_type)) {
@@ -119,21 +241,23 @@ function validateManifest(appPath: string): Manifest {
119
241
 
120
242
  return manifest
121
243
  }
122
- // CIL[END chunk_id="validate-app_validatemanifest_1784068794"]
123
- // CIL[BEGIN chunk_id="validate-app_validatepackagejson_1784068794" type="function" identity="validatePackageJson" parent="none"]
124
- // CIL[DOC-MACRO purpose="Validate package.json structure and version consistency"]
125
- // CIL[DOC-RESPONSIBILITY responsibility="Parse and validate package file"]
126
- // CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/components/ui/dialog.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\"\\\"]"]
127
- // CIL[DOC-CONTRACT inputs="none" outputs="package_json" errors="validation_errors" side_effects="none"]
128
- // CIL[DOC-MICRO logic_summary="Validates JSON format and version match with manifest" notable_decisions="[]"]
129
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
130
- // CIL[DOC-STABILITY stability="stable"]
131
- // CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, .framework/src/pages/admin/IntegrationsPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/components/ui/dialog.tsx, .framework/src/pages/admin/RolesPage.tsx, \."]
132
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
133
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
134
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
244
+ // CIL[DOC-VECTOR type="context" content="purpose='Validate the presence and content of an app manifest.json'; No verified external callers; imports: none"]
245
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
246
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
247
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
135
248
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
136
249
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
250
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:validateManifest:function"]
251
+
252
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:validatePackageJson:function" type="function" identity="validatePackageJson" parent="~/.framework/cli/commands/validate-app.ts"]
253
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
254
+ // CIL[DOC-MACRO purpose="Validate the presence and version of an app package.json"]
255
+ // CIL[DOC-RESPONSIBILITY responsibility="Check that package.json exists, is valid JSON and its version matches the manifest"]
256
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
257
+ // CIL[DOC-CONTRACT inputs="appPath: string, manifest: Manifest" outputs="PackageJson" errors="ValidationError on missing file, invalid JSON or version mismatch" side_effects="none"]
258
+ // CIL[DOC-MICRO logic_summary="Resolve package path, read and parse, compare package version to manifest version" notable_decisions=""]
259
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
260
+ // CIL[DOC-STABILITY stable]
137
261
  function validatePackageJson(appPath: string, manifest: Manifest): PackageJson {
138
262
  const packagePath = join(appPath, 'package.json')
139
263
 
@@ -154,21 +278,23 @@ function validatePackageJson(appPath: string, manifest: Manifest): PackageJson {
154
278
 
155
279
  return packageJson
156
280
  }
157
- // CIL[END chunk_id="validate-app_validatepackagejson_1784068794"]
158
- // CIL[BEGIN chunk_id="validate-app_validaterequiredfiles_1784068794" type="function" identity="validateRequiredFiles" parent="none"]
159
- // CIL[DOC-MACRO purpose="Validate required files and directories for app type"]
160
- // CIL[DOC-RESPONSIBILITY responsibility="Check existence of required app structure"]
161
- // CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/migrations/015_simplify_apps_table.sql\",\"\\\"]"]
162
- // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="validation_errors" side_effects="none"]
163
- // CIL[DOC-MICRO logic_summary="Validates presence of index.tsx, pages/, and functions/ based on app_type" notable_decisions="[]"]
164
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
165
- // CIL[DOC-STABILITY stability="stable"]
166
- // CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, .framework/migrations/015_simplify_apps_table.sql, \."]
167
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
168
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
169
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
281
+ // CIL[DOC-VECTOR type="context" content="purpose='Validate the presence and version of an app package.json'; No verified external callers; imports: none"]
282
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
283
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
284
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
170
285
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
171
286
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
287
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:validatePackageJson:function"]
288
+
289
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:validateRequiredFiles:function" type="function" identity="validateRequiredFiles" parent="~/.framework/cli/commands/validate-app.ts"]
290
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
291
+ // CIL[DOC-MACRO purpose="Validate the presence of files and directories required by the app type"]
292
+ // CIL[DOC-RESPONSIBILITY responsibility="Check for index.tsx, pages/ and functions/ depending on app_type"]
293
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
294
+ // CIL[DOC-CONTRACT inputs="appPath: string, manifest: Manifest" outputs="void" errors="ValidationError on missing required files or directories" side_effects="none"]
295
+ // CIL[DOC-MICRO logic_summary="Switch on app_type and assert existence of index.tsx, pages/ and/or functions/" notable_decisions=""]
296
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
297
+ // CIL[DOC-STABILITY stable]
172
298
  function validateRequiredFiles(appPath: string, manifest: Manifest): void {
173
299
  const { app_type } = manifest
174
300
 
@@ -190,25 +316,28 @@ function validateRequiredFiles(appPath: string, manifest: Manifest): void {
190
316
  }
191
317
  }
192
318
  }
193
- // CIL[END chunk_id="validate-app_validaterequiredfiles_1784068794"]
194
- // CIL[BEGIN chunk_id="validate-app_validatealloweddirectories_1784068794" type="function" identity="validateAllowedDirectories" parent="none"]
195
- // CIL[DOC-MACRO purpose="Validate only allowed directories exist in app"]
196
- // CIL[DOC-RESPONSIBILITY responsibility="Check for unauthorized directory names"]
197
- // CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[\".framework/migrations/015_simplify_apps_table.sql\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/functions/_shared/principal.ts\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"\\\"]"]
198
- // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="validation_errors" side_effects="none"]
199
- // CIL[DOC-MICRO logic_summary="Ensures only standard directories plus optional .devin/ exist" notable_decisions="[]"]
200
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
201
- // CIL[DOC-STABILITY stability="stable"]
202
- // CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: .framework/migrations/015_simplify_apps_table.sql, custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/functions/_shared/principal.ts, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
203
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
204
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
205
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
319
+ // CIL[DOC-VECTOR type="context" content="purpose='Validate the presence of files and directories required by the app type'; No verified external callers; imports: none"]
320
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
321
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
322
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
206
323
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
207
324
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
325
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:validateRequiredFiles:function"]
326
+
327
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:validateAllowedDirectories:function" type="function" identity="validateAllowedDirectories" parent="~/.framework/cli/commands/validate-app.ts"]
328
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
329
+ // CIL[DOC-MACRO purpose="Validate that the app root contains only allowed directories"]
330
+ // CIL[DOC-RESPONSIBILITY responsibility="Scan top-level directories and reject any not in the allow list"]
331
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
332
+ // CIL[DOC-CONTRACT inputs="appPath: string" outputs="void" errors="ValidationError on disallowed directories" side_effects="none"]
333
+ // CIL[DOC-MICRO logic_summary="Read app root directories and compare against an allow list of generic app features including optional .devin" notable_decisions=""]
334
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
335
+ // CIL[DOC-STABILITY stable]
208
336
  function validateAllowedDirectories(appPath: string): void {
209
337
  const allowedDirs = [
210
- 'pages', 'components', 'hooks', 'utils', 'functions',
211
- 'seed', 'public'
338
+ 'pages', 'components', 'hooks', 'utils', 'functions',
339
+ 'seed', 'public', 'lib', 'views', 'docs', 'mcp',
340
+ 'migrations', 'migrations-archive', 'tests'
212
341
  ]
213
342
 
214
343
  const entries = readdirSync(appPath, { withFileTypes: true })
@@ -221,21 +350,23 @@ function validateAllowedDirectories(appPath: string): void {
221
350
  throw new ValidationError(`❌ Unknown directories found: ${unknownDirs.join(', ')}. Allowed directories: ${allowedDirs.join(', ')} (plus optional .devin/)`)
222
351
  }
223
352
  }
224
- // CIL[END chunk_id="validate-app_validatealloweddirectories_1784068794"]
225
- // CIL[BEGIN chunk_id="validate-app_validatedevindirectory_1784068794" type="function" identity="validateDevinDirectory" parent="none"]
226
- // CIL[DOC-MACRO purpose="Validate .devin directory structure if present"]
227
- // CIL[DOC-RESPONSIBILITY responsibility="Check AGENTS.md and skills structure"]
228
- // CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[]"]
229
- // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="validation_errors" side_effects="console_output"]
230
- // CIL[DOC-MICRO logic_summary="Validates AGENTS.md presence and skills directory structure" notable_decisions="[]"]
231
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
232
- // CIL[DOC-STABILITY stability="stable"]
233
- // CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: none."]
234
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
235
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
236
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
353
+ // CIL[DOC-VECTOR type="context" content="purpose='Validate that the app root contains only allowed directories'; No verified external callers; imports: none"]
354
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
355
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
356
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
237
357
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
238
358
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
359
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:validateAllowedDirectories:function"]
360
+
361
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:validateDevinDirectory:function" type="function" identity="validateDevinDirectory" parent="~/.framework/cli/commands/validate-app.ts"]
362
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
363
+ // CIL[DOC-MACRO purpose="Validate the optional .devin/ directory structure"]
364
+ // CIL[DOC-RESPONSIBILITY responsibility="Check that .devin/ contains AGENTS.md and that every skill has SKILL.md"]
365
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
366
+ // CIL[DOC-CONTRACT inputs="appPath: string" outputs="void" errors="ValidationError on missing AGENTS.md or missing SKILL.md" side_effects="logs to stdout"]
367
+ // CIL[DOC-MICRO logic_summary="If .devin exists, verify AGENTS.md and each skill subdirectory has SKILL.md" notable_decisions=""]
368
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
369
+ // CIL[DOC-STABILITY stable]
239
370
  function validateDevinDirectory(appPath: string): void {
240
371
  const devinPath = join(appPath, '.devin')
241
372
 
@@ -265,21 +396,23 @@ function validateDevinDirectory(appPath: string): void {
265
396
  console.log(`✅ .devin/ directory not present (optional)`)
266
397
  }
267
398
  }
268
- // CIL[END chunk_id="validate-app_validatedevindirectory_1784068794"]
269
- // CIL[BEGIN chunk_id="validate-app_validateroutes_1784068794" type="function" identity="validateRoutes" parent="none"]
270
- // CIL[DOC-MACRO purpose="Validate route and navigation item paths"]
271
- // CIL[DOC-RESPONSIBILITY responsibility="Check route prefix and path formatting"]
272
- // CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[]"]
273
- // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="validation_errors" side_effects="console_output"]
274
- // CIL[DOC-MICRO logic_summary="Validates routes and nav_items are root-relative and properly formatted" notable_decisions="[]"]
275
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="complex_dependencies"]
276
- // CIL[DOC-STABILITY stability="stable"]
277
- // CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: none."]
278
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
279
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
280
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
399
+ // CIL[DOC-VECTOR type="context" content="purpose='Validate the optional .devin/ directory structure'; No verified external callers; imports: none"]
400
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
401
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
402
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
281
403
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
282
404
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
405
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:validateDevinDirectory:function"]
406
+
407
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:validateRoutes:function" type="function" identity="validateRoutes" parent="~/.framework/cli/commands/validate-app.ts"]
408
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
409
+ // CIL[DOC-MACRO purpose="Validate route and nav_item paths in the manifest"]
410
+ // CIL[DOC-RESPONSIBILITY responsibility="Check that routes are root-relative and do not repeat the route_prefix"]
411
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
412
+ // CIL[DOC-CONTRACT inputs="appPath: string, manifest: Manifest" outputs="void" errors="ValidationError on route prefix duplication or missing leading slash" side_effects="logs warnings to stdout"]
413
+ // CIL[DOC-MICRO logic_summary="If route_prefix is set, ensure routes and nav_items do not include it and start with /" notable_decisions=""]
414
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
415
+ // CIL[DOC-STABILITY stable]
283
416
  function validateRoutes(appPath: string, manifest: Manifest): void {
284
417
  if (!manifest.route_prefix) {
285
418
  console.warn('⚠️ manifest.json is missing route_prefix — install-app will default to /{slug}')
@@ -317,33 +450,66 @@ function validateRoutes(appPath: string, manifest: Manifest): void {
317
450
  for (const item of (manifest as any).nav_items) checkNavItem(item)
318
451
  }
319
452
  }
320
- // CIL[END chunk_id="validate-app_validateroutes_1784068794"]
321
- // CIL[BEGIN chunk_id="validate-app_validatemanifestcomponents_1784068794" type="function" identity="validateManifestComponents" parent="none"]
322
- // CIL[DOC-MACRO purpose="Validate manifest component references exist"]
323
- // CIL[DOC-RESPONSIBILITY responsibility="Check entry_point and sidebar_component files"]
324
- // CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[]"]
325
- // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="validation_errors" side_effects="none"]
326
- // CIL[DOC-MICRO logic_summary="Validates referenced files exist and registration config is consistent" notable_decisions="[]"]
327
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
328
- // CIL[DOC-STABILITY stability="stable"]
329
- // CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: none."]
330
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
331
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
332
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
453
+ // CIL[DOC-VECTOR type="context" content="purpose='Validate route and nav_item paths in the manifest'; No verified external callers; imports: none"]
454
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
455
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
456
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
333
457
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
334
458
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
459
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:validateRoutes:function"]
460
+
461
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:canonicalfilewithin:function" type="function" identity="canonicalFileWithin" parent="~/.framework/cli/commands/validate-app.ts"]
462
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
463
+ // CIL[DOC-MACRO purpose="Resolve a root-contained file path for manifest-referenced files"]
464
+ // CIL[DOC-RESPONSIBILITY responsibility="Return the canonical path of an existing regular file inside the app root, or null"]
465
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
466
+ // CIL[DOC-CONTRACT inputs="appPath: string, relPath: string" outputs="string canonical path or null" errors="none" side_effects="reads filesystem metadata via realpathSync and statSync"]
467
+ // CIL[DOC-MICRO logic_summary="Rejects absolute paths, lexical escapes, symlink escapes, and non-file targets by canonicalizing app root and target with realpathSync" notable_decisions=""]
468
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
469
+ // CIL[DOC-STABILITY stable]
470
+ function canonicalFileWithin(appPath: string, relPath: string): string | null {
471
+ try {
472
+ if (isAbsolute(relPath)) return null
473
+ const root = realpathSync(appPath)
474
+ const lexical = resolve(root, relPath)
475
+ if (lexical !== root && !lexical.startsWith(root + sep)) return null
476
+ const canonical = realpathSync(lexical)
477
+ if (canonical !== root && !canonical.startsWith(root + sep)) return null
478
+ if (!statSync(canonical).isFile()) return null
479
+ return canonical
480
+ } catch {
481
+ return null
482
+ }
483
+ }
484
+ // CIL[DOC-VECTOR type="context" content="purpose='Resolve a root-contained file path for manifest-referenced files'; No verified external callers; imports: none"]
485
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
486
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
487
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
488
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
489
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
490
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:canonicalfilewithin:function"]
491
+
492
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:validateManifestComponents:function" type="function" identity="validateManifestComponents" parent="~/.framework/cli/commands/validate-app.ts"]
493
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
494
+ // CIL[DOC-MACRO purpose="Validate manifest references to component files and registration constraints"]
495
+ // CIL[DOC-RESPONSIBILITY responsibility="Check entry_point, sidebar_component and account strategy fields"]
496
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
497
+ // CIL[DOC-CONTRACT inputs="appPath: string, manifest: Manifest" outputs="void" errors="ValidationError on missing referenced files or inconsistent registration" side_effects="reads filesystem metadata for root-contained files via canonicalFileWithin"]
498
+ // CIL[DOC-MICRO logic_summary="Verify referenced files exist as root-contained regular files via canonicalFileWithin and that existing account strategy has target_account" notable_decisions=""]
499
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
500
+ // CIL[DOC-STABILITY stable]
335
501
  function validateManifestComponents(appPath: string, manifest: Manifest): void {
336
502
  if (manifest.entry_point) {
337
503
  const ep = manifest.entry_point.replace(/^\.\//, '')
338
- if (!existsSync(join(appPath, ep))) {
339
- throw new ValidationError(`❌ manifest.json entry_point "${manifest.entry_point}" does not exist`)
504
+ if (!canonicalFileWithin(appPath, ep)) {
505
+ throw new ValidationError(`❌ manifest.json entry_point "${manifest.entry_point}" does not exist or escapes the app root`)
340
506
  }
341
507
  }
342
508
 
343
509
  if (manifest.sidebar_component) {
344
510
  const sc = manifest.sidebar_component.replace(/^\.\//, '')
345
- if (!existsSync(join(appPath, sc))) {
346
- throw new ValidationError(`❌ manifest.json sidebar_component "${manifest.sidebar_component}" does not exist`)
511
+ if (!canonicalFileWithin(appPath, sc)) {
512
+ throw new ValidationError(`❌ manifest.json sidebar_component "${manifest.sidebar_component}" does not exist or escapes the app root`)
347
513
  }
348
514
  }
349
515
 
@@ -351,21 +517,23 @@ function validateManifestComponents(appPath: string, manifest: Manifest): void {
351
517
  throw new ValidationError(`❌ manifest.json registration.account_strategy is "existing" but target_account is not set`)
352
518
  }
353
519
  }
354
- // CIL[END chunk_id="validate-app_validatemanifestcomponents_1784068794"]
355
- // CIL[BEGIN chunk_id="validate-app_validateseedblock_1784068794" type="function" identity="validateSeedBlock" parent="none"]
356
- // CIL[DOC-MACRO purpose="Validate seed data configuration"]
357
- // CIL[DOC-RESPONSIBILITY responsibility="Check seed files and configuration"]
358
- // CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[]"]
359
- // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="validation_errors" side_effects="none"]
360
- // CIL[DOC-MICRO logic_summary="Validates seed array structure and SQL file existence" notable_decisions="[]"]
361
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
362
- // CIL[DOC-STABILITY stability="stable"]
363
- // CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: none."]
364
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
365
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
366
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
520
+ // CIL[DOC-VECTOR type="context" content="purpose='Validate manifest references to component files and registration constraints'; No verified external callers; imports: none"]
521
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
522
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
523
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
367
524
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
368
525
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
526
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:validateManifestComponents:function"]
527
+
528
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:validateSeedBlock:function" type="function" identity="validateSeedBlock" parent="~/.framework/cli/commands/validate-app.ts"]
529
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
530
+ // CIL[DOC-MACRO purpose="Validate the seed block in the manifest"]
531
+ // CIL[DOC-RESPONSIBILITY responsibility="Check that seed entries are well-formed and reference root-contained .json files containing an array of object records"]
532
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
533
+ // CIL[DOC-CONTRACT inputs="appPath: string, manifest: Manifest" outputs="void" errors="ValidationError on malformed seed entries, missing seed files, path escapes, or non-object rows" side_effects="none"]
534
+ // CIL[DOC-MICRO logic_summary="Assert seed is an array of objects; each entry needs nonempty-trimmed file/table/conflict strings; entry.file is relative to the app root, must resolve to a root-contained regular .json file via canonicalFileWithin, and must parse to a JSON array of non-null objects" notable_decisions=""]
535
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
536
+ // CIL[DOC-STABILITY stable]
369
537
  function validateSeedBlock(appPath: string, manifest: Manifest): void {
370
538
  if (!manifest.seed) return
371
539
 
@@ -374,36 +542,214 @@ function validateSeedBlock(appPath: string, manifest: Manifest): void {
374
542
  }
375
543
 
376
544
  for (const entry of manifest.seed) {
377
- if (!entry.file || !entry.table || !entry.conflict) {
545
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
546
+ throw new ValidationError('❌ manifest.json seed entries must be objects')
547
+ }
548
+ if (typeof entry.file !== 'string' || !entry.file.trim() || typeof entry.table !== 'string' || !entry.table.trim() || typeof entry.conflict !== 'string' || !entry.conflict.trim()) {
378
549
  throw new ValidationError('❌ manifest.json seed entries must have file, table, and conflict fields')
379
550
  }
380
551
 
381
- const seedFile = join(appPath, 'seed', entry.file)
382
- if (!existsSync(seedFile)) {
383
- throw new ValidationError(`❌ Seed file not found: seed/${entry.file}`)
552
+ if (isAbsolute(entry.file) || !existsSync(join(appPath, entry.file))) {
553
+ throw new ValidationError(`❌ Seed file not found: ${entry.file}`)
554
+ }
555
+
556
+ const seedFile = canonicalFileWithin(appPath, entry.file)
557
+ if (!seedFile) {
558
+ throw new ValidationError(`❌ Seed file escapes the app root: ${entry.file}`)
559
+ }
560
+
561
+ if (!seedFile.endsWith('.json')) {
562
+ throw new ValidationError(`❌ Seed file must be .json: ${entry.file}`)
384
563
  }
385
564
 
386
- if (!seedFile.endsWith('.sql')) {
387
- throw new ValidationError(`❌ Seed file must be .sql: seed/${entry.file}`)
565
+ let rows: unknown
566
+ try {
567
+ rows = JSON.parse(readFileSync(seedFile, 'utf8'))
568
+ } catch {
569
+ throw new ValidationError(`❌ Seed file is not valid JSON: ${entry.file}`)
570
+ }
571
+
572
+ if (!Array.isArray(rows)) {
573
+ throw new ValidationError(`❌ Seed file must contain a JSON array of records: ${entry.file}`)
574
+ }
575
+
576
+ for (const row of rows) {
577
+ if (!row || typeof row !== 'object' || Array.isArray(row)) {
578
+ throw new ValidationError(`❌ Seed file must contain only non-null object records: ${entry.file}`)
579
+ }
388
580
  }
389
581
  }
390
582
  }
391
- // CIL[END chunk_id="validate-app_validateseedblock_1784068794"]
392
- // CIL[BEGIN chunk_id="validate-app_validateappstructure_1784068794" type="function" identity="validateAppStructure" parent="none"]
393
- // CIL[DOC-MACRO purpose="Run complete app structure validation"]
394
- // CIL[DOC-RESPONSIBILITY responsibility="Execute all validation checks"]
395
- // CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[]"]
396
- // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="validation_errors" side_effects="console_output"]
397
- // CIL[DOC-MICRO logic_summary="Runs all validation functions in sequence and reports success" notable_decisions="[]"]
398
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
583
+ // CIL[DOC-VECTOR type="context" content="purpose='Validate the seed block in the manifest'; No verified external callers; imports: none"]
584
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
585
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
586
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
587
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
588
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
589
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:validateSeedBlock:function"]
590
+
591
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:validateownedtypes:function" type="function" identity="validateOwnedTypes" parent="~/.framework/cli/commands/validate-app.ts"]
592
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
593
+ // CIL[DOC-MACRO purpose="Validate the optional owned_types manifest declaration"]
594
+ // CIL[DOC-RESPONSIBILITY responsibility="Require owned_types to be an array of non-empty strings where each slug resolves to a record in the app's types seed (seed/types.json)"]
595
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/install-app.ts"]
596
+ // CIL[DOC-CONTRACT inputs="appPath: string, manifest: Manifest" outputs="void" errors="ValidationError on a malformed owned_types array or a slug absent from the types seed" side_effects="reads types seed files"]
597
+ // CIL[DOC-MICRO logic_summary="Return early when owned_types is absent; shape-check the array, then collect slugs from every declared non-patch types seed entry plus the conventional seed/types.json default and reject undeclared slugs" notable_decisions="absent owned_types is a valid optional field; install-app --reconcile-owned-types trusts the same resolution set"]
598
+ // CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"]
399
599
  // CIL[DOC-STABILITY stability="stable"]
400
- // CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: none."]
401
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
402
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
403
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
600
+ function validateOwnedTypes(appPath: string, manifest: Manifest): void {
601
+ const owned = manifest.owned_types
602
+ if (owned === undefined) return
603
+
604
+ if (!Array.isArray(owned) || owned.some(s => typeof s !== 'string' || !s.trim())) {
605
+ throw new ValidationError('❌ manifest.json owned_types must be an array of non-empty strings')
606
+ }
607
+
608
+ // Resolve declared slugs against every types seed this app ships: declared
609
+ // non-patch seed entries for the types table, plus the conventional
610
+ // seed/types.json the installer applies by default.
611
+ const typeSlugs = new Set<string>()
612
+ const collectFrom = (relPath: string) => {
613
+ const file = canonicalFileWithin(appPath, relPath)
614
+ if (!file) return
615
+ try {
616
+ const rows: unknown = JSON.parse(readFileSync(file, 'utf8'))
617
+ if (Array.isArray(rows)) {
618
+ for (const row of rows) {
619
+ if (row && typeof row === 'object' && typeof (row as any).slug === 'string') typeSlugs.add((row as any).slug)
620
+ }
621
+ }
622
+ } catch { /* malformed declared files already failed in validateSeedBlock */ }
623
+ }
624
+ for (const entry of manifest.seed ?? []) {
625
+ if (entry && typeof entry === 'object' && !Array.isArray(entry)
626
+ && entry.table === 'types' && entry.permissions_patch !== true && typeof entry.file === 'string') {
627
+ collectFrom(entry.file)
628
+ }
629
+ }
630
+ collectFrom('seed/types.json')
631
+
632
+ for (const slug of owned) {
633
+ if (!typeSlugs.has(slug)) {
634
+ throw new ValidationError(`❌ manifest.json owned_types declares "${slug}" but no type record with that slug exists in the app's types seed (seed/types.json)`)
635
+ }
636
+ }
637
+ }
638
+ // CIL[DOC-VECTOR type="context" content="purpose='Validate the optional owned_types manifest declaration'; No verified external callers; imports: none"]
639
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
640
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
641
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
404
642
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
405
643
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
406
- function validateAppStructure(appPath: string): void {
644
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:validateownedtypes:function"]
645
+ // CIL[DOC-MACRO purpose="Validate the manifest knowledge envelope and seed prompt-config picks"]
646
+ // CIL[DOC-RESPONSIBILITY responsibility="Check config.knowledge shape and verify seeded prompt_configs' retrieval_policy picks stay inside the envelope — an agent may narrow the app envelope but never widen it"]
647
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/functions/_shared/kb.ts"]
648
+ // CIL[DOC-CONTRACT inputs="appPath: string, manifest: Manifest" outputs="void" errors="ValidationError on malformed envelope or out-of-envelope picks" side_effects="none"]
649
+ // CIL[DOC-MICRO logic_summary="Shape-check account/platform/cil blocks, then intersect each seeded prompt config's item_types and cil project_ids against the envelope; warns when agents would get no access (deny-by-default)" notable_decisions="trailing-* prefix patterns supported in item_types/sources"]
650
+ // CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"]
651
+ // CIL[DOC-STABILITY stability="experimental"]
652
+ function validateKnowledgeEnvelope(appPath: string, manifest: Manifest): void {
653
+ const envelope = manifest.config?.knowledge
654
+ if (envelope === undefined) {
655
+ console.warn('⚠️ manifest.json config.knowledge is absent — agents and KB search will be denied (deny-by-default)')
656
+ return
657
+ }
658
+ if (envelope === null || typeof envelope !== 'object' || Array.isArray(envelope)) {
659
+ throw new ValidationError('❌ manifest.json config.knowledge must be an object')
660
+ }
661
+
662
+ const isPatternList = (v: any) => Array.isArray(v) && v.every((s) => typeof s === 'string' && s.length > 0)
663
+
664
+ if (envelope.account !== undefined) {
665
+ const a = envelope.account
666
+ if (a !== true && a !== false && (typeof a !== 'object' || a === null || Array.isArray(a))) {
667
+ throw new ValidationError('❌ config.knowledge.account must be a boolean or an object')
668
+ }
669
+ if (a && typeof a === 'object') {
670
+ if (a.scope !== undefined && !['self', 'self_and_descendants'].includes(a.scope)) {
671
+ throw new ValidationError(`❌ config.knowledge.account.scope must be "self" or "self_and_descendants", got "${a.scope}"`)
672
+ }
673
+ if (a.item_types !== undefined && !isPatternList(a.item_types)) {
674
+ throw new ValidationError('❌ config.knowledge.account.item_types must be an array of item_type slugs or "prefix*" patterns')
675
+ }
676
+ }
677
+ }
678
+ if (envelope.platform !== undefined) {
679
+ const p = envelope.platform
680
+ if (p !== true && p !== false && (typeof p !== 'object' || p === null || Array.isArray(p))) {
681
+ throw new ValidationError('❌ config.knowledge.platform must be a boolean or an object')
682
+ }
683
+ if (p && typeof p === 'object' && p.sources !== undefined && !isPatternList(p.sources)) {
684
+ throw new ValidationError('❌ config.knowledge.platform.sources must be an array of item_type slugs')
685
+ }
686
+ }
687
+ if (envelope.cil !== undefined) {
688
+ const c = envelope.cil
689
+ if (c !== true && c !== false && (typeof c !== 'object' || c === null || Array.isArray(c))) {
690
+ throw new ValidationError('❌ config.knowledge.cil must be a boolean or an object')
691
+ }
692
+ if (c && typeof c === 'object' && c.project_ids !== undefined && !isPatternList(c.project_ids)) {
693
+ throw new ValidationError('❌ config.knowledge.cil.project_ids must be an array of project UUIDs')
694
+ }
695
+ if (c === true) {
696
+ console.warn('⚠️ config.knowledge.cil is enabled without project_ids — CIL access requires a non-empty project list to resolve at runtime')
697
+ }
698
+ }
699
+
700
+ // Cross-check seeded prompt-config picks against the envelope.
701
+ const seedPath = join(appPath, 'seed', 'prompt-configs.json')
702
+ if (!existsSync(seedPath)) return
703
+ let configs: any[] = []
704
+ try {
705
+ const parsed = JSON.parse(readFileSync(seedPath, 'utf8'))
706
+ configs = Array.isArray(parsed) ? parsed : (parsed.prompt_configs || parsed.items || [])
707
+ } catch {
708
+ return
709
+ }
710
+ const accountPatterns = envelope.account && envelope.account !== true ? (envelope.account.item_types ?? null) : (envelope.account ? null : [])
711
+ const platformPatterns = envelope.platform && envelope.platform !== true ? (envelope.platform.sources ?? null) : (envelope.platform ? null : [])
712
+ const matchAny = (patterns: string[] | null, t: string) =>
713
+ patterns == null ? true : patterns.some((p) => p === '*' || (p.endsWith('*') ? t.startsWith(p.slice(0, -1)) : p === t))
714
+ const envCilIds = envelope.cil && envelope.cil !== true ? (envelope.cil.project_ids ?? null) : null
715
+
716
+ for (const cfg of configs) {
717
+ const pick = cfg?.metadata?.retrieval_policy?.item_types || []
718
+ const label = cfg.slug || cfg.name || '(unnamed)'
719
+ const outside = pick.filter((t: string) =>
720
+ !(t === 'cil_chunk' && !!envelope.cil) && !matchAny(accountPatterns, t) && !matchAny(platformPatterns, t)
721
+ )
722
+ if (outside.length) {
723
+ throw new ValidationError(
724
+ `❌ seed/prompt-configs.json "${label}" picks item_types outside the knowledge envelope: ${outside.join(', ')}`
725
+ )
726
+ }
727
+ const pickCil = cfg?.metadata?.cil_config?.project_ids || []
728
+ if (pickCil.length) {
729
+ if (!envelope.cil) {
730
+ throw new ValidationError(`❌ prompt config "${label}" sets cil_config.project_ids but config.knowledge.cil is not enabled`)
731
+ }
732
+ if (envCilIds) {
733
+ const bad = pickCil.filter((id: string) => !envCilIds.includes(id))
734
+ if (bad.length) {
735
+ throw new ValidationError(`❌ prompt config "${label}" cil project_ids outside envelope: ${bad.join(', ')}`)
736
+ }
737
+ }
738
+ }
739
+ }
740
+ }
741
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:validateknowledgeenvelope:function"]
742
+
743
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:validateAppStructure:function" type="function" identity="validateAppStructure" parent="~/.framework/cli/commands/validate-app.ts"]
744
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
745
+ // CIL[DOC-MACRO purpose="Run the full app structure validation pipeline"]
746
+ // CIL[DOC-RESPONSIBILITY responsibility="Orchestrate manifest, package, required files, directories, devin, routes, components, seed and owned_types checks"]
747
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
748
+ // CIL[DOC-CONTRACT inputs="appPath: string" outputs="void" errors="ValidationError from any sub-validator" side_effects="logs validation result to stdout"]
749
+ // CIL[DOC-MICRO logic_summary="Call each validator in sequence — including validateOwnedTypes after validateSeedBlock so declared seed files are already proven well-formed — and log success" notable_decisions=""]
750
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
751
+ // CIL[DOC-STABILITY stable]
752
+ export function validateAppStructure(appPath: string): void {
407
753
  const manifest = validateManifest(appPath)
408
754
  validatePackageJson(appPath, manifest)
409
755
  validateRequiredFiles(appPath, manifest)
@@ -412,23 +758,27 @@ function validateAppStructure(appPath: string): void {
412
758
  validateRoutes(appPath, manifest)
413
759
  validateManifestComponents(appPath, manifest)
414
760
  validateSeedBlock(appPath, manifest)
761
+ validateOwnedTypes(appPath, manifest)
762
+ validateKnowledgeEnvelope(appPath, manifest)
415
763
  console.log(`✅ App structure is valid`)
416
764
  }
417
- // CIL[END chunk_id="validate-app_validateappstructure_1784068794"]
418
- // CIL[BEGIN chunk_id="validate-app_registervalidateappcommands_1784068794" type="function" identity="registerValidateAppCommands" parent="none"]
419
- // CIL[DOC-MACRO purpose="Register validate-app command with CLI program"]
420
- // CIL[DOC-RESPONSIBILITY responsibility="Configure app validation command interface"]
421
- // CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[]"]
422
- // CIL[DOC-CONTRACT inputs="none" outputs="validate_app_command" errors="command_errors" side_effects="process_exit"]
423
- // CIL[DOC-MICRO logic_summary="Registers validate-app command with path option and error handling" notable_decisions="[]"]
424
- // CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
425
- // CIL[DOC-STABILITY stability="stable"]
426
- // CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: none."]
427
- // CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
428
- // CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
429
- // CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
765
+ // CIL[DOC-VECTOR type="context" content="purpose='Run the full app structure validation pipeline'; No verified external callers; imports: none"]
766
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
767
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
768
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
430
769
  // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
431
770
  // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
771
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:validateAppStructure:function"]
772
+
773
+ // CIL[BEGIN stable_id="~/.framework/cli/commands/validate-app.ts:registerValidateAppCommands:function" type="function" identity="registerValidateAppCommands" parent="~/.framework/cli/commands/validate-app.ts"]
774
+ // CIL[DOC-AUDIENCE audience="CLI engineers and framework maintainers"]
775
+ // CIL[DOC-MACRO purpose="Register the validate-app CLI subcommand and run validation"]
776
+ // CIL[DOC-RESPONSIBILITY responsibility="Add a validate-app command to a Commander program that validates a local app directory"]
777
+ // CIL[DOC-CONTEXT module="validate-app" layer="cli" related_files=".framework/cli/commands/validate-app.ts"]
778
+ // CIL[DOC-CONTRACT inputs="program: Command" outputs="none" errors="process.exit(1) on validation or unexpected errors" side_effects="logs to stdout and stderr, may exit process"]
779
+ // CIL[DOC-MICRO logic_summary="Define the validate-app command, resolve the app path, call validateAppStructure and handle errors" notable_decisions=""]
780
+ // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
781
+ // CIL[DOC-STABILITY stable]
432
782
  export function registerValidateAppCommands(program: Command) {
433
783
  program
434
784
  .command('validate-app [path]')
@@ -451,4 +801,10 @@ export function registerValidateAppCommands(program: Command) {
451
801
  }
452
802
  })
453
803
  }
454
- // CIL[END chunk_id="validate-app_registervalidateappcommands_1784068794"]
804
+ // CIL[DOC-VECTOR type="context" content="purpose='Register the validate-app CLI subcommand and run validation'; No verified external callers; imports: none"]
805
+ // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
806
+ // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
807
+ // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
808
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
809
+ // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
810
+ // CIL[END stable_id="~/.framework/cli/commands/validate-app.ts:registerValidateAppCommands:function"]