spine-framework 0.3.125 → 0.3.126
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.
- package/.framework/cli/commands/agents.ts +35 -37
- package/.framework/cli/commands/auth.ts +35 -34
- package/.framework/cli/commands/create-app.ts +104 -40
- package/.framework/cli/commands/dev.ts +104 -69
- package/.framework/cli/commands/doctor.ts +169 -97
- package/.framework/cli/commands/generate.ts +82 -160
- package/.framework/cli/commands/init.ts +72 -34
- package/.framework/cli/commands/install-app.ts +260 -125
- package/.framework/cli/commands/items.ts +33 -44
- package/.framework/cli/commands/migrate.ts +122 -40
- package/.framework/cli/commands/migrations.ts +33 -40
- package/.framework/cli/commands/pipelines.ts +31 -39
- package/.framework/cli/commands/status.ts +47 -23
- package/.framework/cli/commands/system.ts +47 -37
- package/.framework/cli/commands/test.ts +112 -68
- package/.framework/cli/commands/validate-app.ts +215 -121
- package/.framework/cli/context.ts +112 -130
- package/.framework/cli/env-loader.ts +47 -18
- package/.framework/cli/index.ts +81 -42
- package/.framework/docs/runtime-types.md +1024 -0
- package/.framework/functions/_shared/agent-runner.ts +1296 -961
- package/.framework/functions/_shared/app-manifest.ts +82 -68
- package/.framework/functions/_shared/audit.ts +135 -83
- package/.framework/functions/_shared/{cil-state.ts → cil.ts} +147 -54
- package/.framework/functions/_shared/db.ts +80 -126
- package/.framework/functions/_shared/hash-api-key.ts +63 -0
- package/.framework/functions/_shared/index.ts +222 -347
- package/.framework/functions/_shared/kb.ts +319 -0
- package/.framework/functions/_shared/llm.ts +92 -0
- package/.framework/functions/_shared/logging.ts +288 -0
- package/.framework/functions/_shared/middleware.ts +329 -365
- package/.framework/functions/_shared/outcomes.ts +36 -0
- package/.framework/functions/_shared/permissions.ts +359 -643
- package/.framework/functions/_shared/pipeline-runner.ts +243 -316
- package/.framework/functions/_shared/principal.ts +376 -468
- package/.framework/functions/_shared/resolve-credentials.ts +102 -0
- package/.framework/functions/_shared/resolve-ids.ts +162 -14
- package/.framework/functions/_shared/retry-deliveries.ts +104 -0
- package/.framework/functions/_shared/schema-utils.ts +611 -373
- package/.framework/functions/_shared/testing.ts +207 -137
- package/.framework/functions/_shared/tracing.ts +276 -0
- package/.framework/functions/_shared/trigger-engine.ts +159 -211
- package/.framework/functions/_shared/webhook-registration.ts +95 -81
- package/.framework/functions/_shared/webhook-registry.ts +153 -75
- package/.framework/functions/account-nodes.ts +31 -53
- package/.framework/functions/adapters/generic-webhook-inbound.ts +56 -0
- package/.framework/functions/adapters/generic-webhook-outbound.ts +43 -0
- package/.framework/functions/adapters/openai-outbound.ts +40 -0
- package/.framework/functions/admin-data.ts +687 -533
- package/.framework/functions/admin-funnel.ts +31 -20
- package/.framework/functions/admin-install-funnel.ts +47 -28
- package/.framework/functions/admin-signals.ts +47 -29
- package/.framework/functions/ai-agents.ts +122 -147
- package/.framework/functions/ai-interactions.ts +180 -90
- package/.framework/functions/api-keys.ts +250 -192
- package/.framework/functions/apps.ts +203 -197
- package/.framework/functions/auth.ts +98 -91
- package/.framework/functions/cil-agent-ingest.ts +773 -0
- package/.framework/functions/cil-agent.ts +592 -0
- package/.framework/functions/cil-callmap.ts +1227 -0
- package/.framework/functions/cil-config.ts +583 -0
- package/.framework/functions/cil-context.ts +445 -0
- package/.framework/functions/cil-doc.ts +1752 -0
- package/.framework/functions/cil-embeddings.ts +1202 -0
- package/.framework/functions/cil-graph.ts +585 -0
- package/.framework/functions/cil-ingest.ts +2416 -0
- package/.framework/functions/cil-pipeline.ts +318 -0
- package/.framework/functions/cil-project.ts +499 -0
- package/.framework/functions/cil-validate.ts +469 -0
- package/.framework/functions/debug-auth.ts +73 -53
- package/.framework/functions/deliveries.ts +117 -0
- package/.framework/functions/embeddings.ts +528 -516
- package/.framework/functions/eval-harness.ts +158 -106
- package/.framework/functions/integration-outbound.ts +311 -0
- package/.framework/functions/integration-routes.ts +240 -466
- package/.framework/functions/integrations.ts +132 -140
- package/.framework/functions/invites.ts +401 -201
- package/.framework/functions/item-progress.ts +113 -53
- package/.framework/functions/kb.ts +28 -0
- package/.framework/functions/logs.ts +239 -222
- package/.framework/functions/observability.ts +308 -259
- package/.framework/functions/pipeline-executions.ts +179 -235
- package/.framework/functions/pipelines.ts +163 -205
- package/.framework/functions/prompt-configs.ts +109 -156
- package/.framework/functions/roles.ts +97 -147
- package/.framework/functions/system-cron.ts +132 -218
- package/.framework/functions/system.ts +112 -52
- package/.framework/functions/tests.ts +32 -28
- package/.framework/functions/timers.ts +162 -210
- package/.framework/functions/triggers.ts +282 -346
- package/.framework/functions/types.ts +283 -400
- package/.framework/migrations/001_core_schema.sql +630 -0
- package/.framework/migrations/002_core_rls_and_functions.sql +532 -0
- package/.framework/migrations/{003_system_data.sql → 003_core_system_data.sql} +26 -153
- package/.framework/migrations/004_core_rpc_and_broker.sql +421 -0
- package/.framework/migrations/005_core_observability.sql +598 -0
- package/.framework/migrations/006_security_hardening_rls.sql +97 -0
- package/.framework/migrations/007_kb_article_list.sql +237 -0
- package/.framework/migrations/008_items_target.sql +8 -0
- package/.framework/migrations/009_roles_slug_unique.sql +11 -0
- package/.framework/public/spine.config.json +91 -0
- package/.framework/scripts/app-install-cli.ts +112 -98
- package/.framework/src/App.tsx +67 -20
- package/.framework/src/apps/admin/index.tsx +97 -27
- package/.framework/src/components/AppWrapper.tsx +50 -11
- package/.framework/src/components/CustomAppLoader.tsx +131 -22
- package/.framework/src/components/admin/AdminListPage.tsx +75 -8
- package/.framework/src/components/admin/AdminSidebar.tsx +148 -36
- package/.framework/src/components/admin/AdminStatsCard.tsx +48 -29
- package/.framework/src/components/admin/PageInstructions.tsx +49 -0
- package/.framework/src/components/admin/SortableTableHeader.tsx +49 -2
- package/.framework/src/components/app-shell/GenericAppShell.tsx +69 -11
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +55 -10
- package/.framework/src/components/app-shell/GenericListPage.tsx +76 -9
- package/.framework/src/components/app-sidebar.tsx +50 -3
- package/.framework/src/components/auth/ProtectedRoute.tsx +53 -45
- package/.framework/src/components/kb/KBArticleEditor.tsx +409 -0
- package/.framework/src/components/kb/KBArticleList.tsx +557 -0
- package/.framework/src/components/layout/AppShell.tsx +54 -16
- package/.framework/src/components/layout/Header.tsx +50 -38
- package/.framework/src/components/layout/Layout.tsx +48 -32
- package/.framework/src/components/layout/Sidebar.tsx +167 -16
- package/.framework/src/components/runtime/DataDetailHeader.tsx +33 -1
- package/.framework/src/components/runtime/DataDetailPage.tsx +289 -4
- package/.framework/src/components/runtime/DataFilters.tsx +78 -1
- package/.framework/src/components/runtime/DataHeader.tsx +32 -29
- package/.framework/src/components/runtime/DataListPage.tsx +161 -2
- package/.framework/src/components/runtime/DataStats.tsx +48 -1
- package/.framework/src/components/runtime/DataTable.tsx +153 -1
- package/.framework/src/components/runtime/SchemaDetailForm.tsx +77 -46
- package/.framework/src/components/runtime/index.ts +16 -9
- package/.framework/src/components/search-form.tsx +33 -1
- package/.framework/src/components/shared/AgentView.tsx +48 -51
- package/.framework/src/components/shared/FieldRenderer.tsx +84 -67
- package/.framework/src/components/shared/InviteManager.tsx +113 -52
- package/.framework/src/components/shared/MemberList.tsx +182 -0
- package/.framework/src/components/shared/SchemaFields.tsx +96 -78
- package/.framework/src/components/ui/DataTable.tsx +86 -56
- package/.framework/src/components/ui/Form.tsx +188 -109
- package/.framework/src/components/ui/ItemCard.tsx +86 -58
- package/.framework/src/components/ui/ItemListView.tsx +88 -61
- package/.framework/src/components/ui/LoadingSpinner.tsx +52 -27
- package/.framework/src/components/ui/Modal.tsx +81 -4
- package/.framework/src/components/ui/RichTextEditor.tsx +101 -9
- package/.framework/src/components/ui/accordion.tsx +97 -5
- package/.framework/src/components/ui/alert-dialog.tsx +225 -13
- package/.framework/src/components/ui/alert.tsx +113 -6
- package/.framework/src/components/ui/aspect-ratio.tsx +49 -2
- package/.framework/src/components/ui/avatar.tsx +129 -7
- package/.framework/src/components/ui/badge.tsx +65 -3
- package/.framework/src/components/ui/breadcrumb.tsx +145 -8
- package/.framework/src/components/ui/button-group.tsx +81 -4
- package/.framework/src/components/ui/button.tsx +49 -2
- package/.framework/src/components/ui/calendar.tsx +65 -3
- package/.framework/src/components/ui/card.tsx +145 -8
- package/.framework/src/components/ui/carousel.tsx +129 -7
- package/.framework/src/components/ui/chart.tsx +161 -10
- package/.framework/src/components/ui/checkbox.tsx +49 -2
- package/.framework/src/components/ui/collapsible.tsx +81 -5
- package/.framework/src/components/ui/combobox.tsx +305 -20
- package/.framework/src/components/ui/command.tsx +177 -11
- package/.framework/src/components/ui/context-menu.tsx +273 -17
- package/.framework/src/components/ui/dialog.tsx +209 -27
- package/.framework/src/components/ui/direction.tsx +64 -4
- package/.framework/src/components/ui/drawer.tsx +193 -12
- package/.framework/src/components/ui/dropdown-menu.tsx +273 -18
- package/.framework/src/components/ui/empty.tsx +145 -9
- package/.framework/src/components/ui/field.tsx +209 -14
- package/.framework/src/components/ui/hover-card.tsx +81 -4
- package/.framework/src/components/ui/input-group.tsx +162 -10
- package/.framework/src/components/ui/input-otp.tsx +98 -5
- package/.framework/src/components/ui/input.tsx +49 -2
- package/.framework/src/components/ui/item.tsx +225 -13
- package/.framework/src/components/ui/kbd.tsx +65 -3
- package/.framework/src/components/ui/label.tsx +49 -2
- package/.framework/src/components/ui/menubar.tsx +289 -17
- package/.framework/src/components/ui/native-select.tsx +97 -5
- package/.framework/src/components/ui/navigation-menu.tsx +177 -10
- package/.framework/src/components/ui/pagination.tsx +161 -9
- package/.framework/src/components/ui/popover.tsx +145 -8
- package/.framework/src/components/ui/progress.tsx +49 -2
- package/.framework/src/components/ui/radio-group.tsx +65 -3
- package/.framework/src/components/ui/resizable.tsx +82 -4
- package/.framework/src/components/ui/scroll-area.tsx +65 -3
- package/.framework/src/components/ui/select.tsx +193 -11
- package/.framework/src/components/ui/separator.tsx +49 -2
- package/.framework/src/components/ui/sheet.tsx +193 -11
- package/.framework/src/components/ui/sidebar.tsx +481 -38
- package/.framework/src/components/ui/skeleton.tsx +49 -2
- package/.framework/src/components/ui/slider.tsx +49 -2
- package/.framework/src/components/ui/sonner.tsx +49 -2
- package/.framework/src/components/ui/spinner.tsx +49 -2
- package/.framework/src/components/ui/switch.tsx +49 -2
- package/.framework/src/components/ui/table-primitives.tsx +160 -33
- package/.framework/src/components/ui/table.tsx +161 -9
- package/.framework/src/components/ui/tabs.tsx +113 -6
- package/.framework/src/components/ui/textarea.tsx +49 -2
- package/.framework/src/components/ui/toggle-group.tsx +81 -4
- package/.framework/src/components/ui/toggle.tsx +65 -3
- package/.framework/src/components/ui/tooltip.tsx +97 -5
- package/.framework/src/contexts/AppContext.tsx +129 -45
- package/.framework/src/contexts/AuthContext.tsx +173 -145
- package/.framework/src/hooks/use-mobile.ts +48 -2
- package/.framework/src/hooks/useApi.ts +208 -159
- package/.framework/src/hooks/useAppPath.ts +32 -23
- package/.framework/src/hooks/useApps.ts +51 -20
- package/.framework/src/hooks/useEntityList.ts +32 -78
- package/.framework/src/hooks/useEntityRecord.ts +35 -96
- package/.framework/src/hooks/useForm.ts +32 -92
- package/.framework/src/hooks/useListSchema.ts +49 -78
- package/.framework/src/hooks/useSchemaRecord.ts +114 -105
- package/.framework/src/lib/api.ts +192 -115
- package/.framework/src/lib/supabase.ts +98 -64
- package/.framework/src/lib/utils.ts +287 -151
- package/.framework/src/main.tsx +49 -3
- package/.framework/src/pages/DashboardPage.tsx +52 -29
- package/.framework/src/pages/NotFoundPage.tsx +32 -10
- package/.framework/src/pages/SetupPage.tsx +32 -12
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +119 -10
- package/.framework/src/pages/admin/AIAgentsPage.tsx +48 -19
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +187 -17
- package/.framework/src/pages/admin/APIKeysPage.tsx +98 -22
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +113 -26
- package/.framework/src/pages/admin/AppDetailPage.tsx +125 -8
- package/.framework/src/pages/admin/AppsPage.tsx +49 -2
- package/.framework/src/pages/admin/DeliveriesPage.tsx +196 -0
- package/.framework/src/pages/admin/DesignedPage.tsx +32 -18
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +215 -484
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +116 -319
- package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -16
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +183 -26
- package/.framework/src/pages/admin/IntegrationsPage.tsx +48 -19
- package/.framework/src/pages/admin/InvitesPage.tsx +48 -14
- package/.framework/src/pages/admin/LogsPage.tsx +422 -75
- package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +113 -24
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +206 -34
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +50 -17
- package/.framework/src/pages/admin/PipelinesPage.tsx +160 -21
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +378 -88
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +125 -16
- package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +49 -10
- package/.framework/src/pages/admin/RoleDetailPage.tsx +130 -10
- package/.framework/src/pages/admin/RolesPage.tsx +171 -18
- package/.framework/src/pages/admin/SelectTestPage.tsx +34 -9
- package/.framework/src/pages/admin/ShadcnTestPage.tsx +49 -11
- package/.framework/src/pages/admin/SimpleDashboard.tsx +49 -10
- package/.framework/src/pages/admin/TestRunDetailPage.tsx +49 -4
- package/.framework/src/pages/admin/TestingDashboard.tsx +98 -28
- package/.framework/src/pages/admin/TimerDetailPage.tsx +143 -33
- package/.framework/src/pages/admin/TimersPage.tsx +48 -20
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +118 -30
- package/.framework/src/pages/admin/TriggersPage.tsx +64 -19
- package/.framework/src/pages/admin/TypeDetailPage.tsx +138 -15
- package/.framework/src/pages/admin/TypesPage.tsx +48 -20
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +465 -0
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +787 -0
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +699 -0
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +647 -0
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +616 -0
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +1402 -0
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +614 -0
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +571 -0
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +731 -0
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
- package/.framework/src/pages/auth/AuthConfirmPage.tsx +52 -51
- package/.framework/src/pages/auth/ForgotPasswordPage.tsx +31 -22
- package/.framework/src/pages/auth/LoginPage.tsx +50 -23
- package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -15
- package/.framework/src/pages/auth/RegisterPage.tsx +281 -317
- package/.framework/src/pages/spine-framework/APIPage.tsx +33 -0
- package/.framework/src/pages/spine-framework/CLIPage.tsx +33 -0
- package/.framework/src/types/auth.ts +128 -71
- package/.framework/src/types/types.ts +373 -157
- package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +39 -0
- package/custom/.devin/skills/spine-workbench-idea/SKILL.md +36 -0
- package/custom/.devin/skills/spine-workbench-implement/SKILL.md +46 -0
- package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +28 -0
- package/custom/.devin/skills/spine-workbench-plan/SKILL.md +38 -0
- package/docs/README.md +9 -130
- package/netlify.toml +3 -3
- package/package.json +13 -25
- package/scripts/kb-ingest-docs.ts +203 -0
- package/spine.config.json +65 -4
- package/.framework/migrations/001_schema.sql +0 -425
- package/.framework/migrations/002_rls_and_functions.sql +0 -763
- package/.framework/migrations/004_enhancements.sql +0 -43
- package/.framework/migrations/005_auth_user_trigger.sql +0 -105
- package/.framework/migrations/006_fix_current_actor_id.sql +0 -21
- package/.framework/migrations/016_invites.sql +0 -27
- package/.framework/migrations/017_fix_get_account_apps.sql +0 -78
- package/.framework/migrations/018_apps_required_roles.sql +0 -17
- package/.framework/migrations/019_triggers_unique_constraint.sql +0 -13
- package/.framework/migrations/020_get_account_apps_role_filter.sql +0 -117
- package/.framework/migrations/021_app_domains.sql +0 -112
- package/.framework/migrations/022_route_prefix_domain_unique.sql +0 -21
- package/.framework/migrations/023_match_embeddings_rpc.sql +0 -78
- package/.framework/migrations/024_messages_account_id.sql +0 -9
- package/.framework/migrations/025_retype_threads_messages.sql +0 -240
- package/.framework/migrations/026_fix_rls_policies.sql +0 -47
- package/.framework/migrations/027_embedding_lifecycle.sql +0 -176
- package/.framework/migrations/028_fix_message_data_permissions.sql +0 -49
- package/.framework/migrations/029_tighten_support_triage_prompt.sql +0 -41
- package/.framework/migrations/030_messages_updated_by.sql +0 -6
- package/.framework/migrations/031_seed_upsert_constraints.sql +0 -35
- package/docs/APPS.md +0 -232
- package/docs/ARCHITECTURE.md +0 -246
- package/docs/INSTALL.md +0 -155
- package/docs/design-schema-spec.md +0 -1837
- package/docs/dev-guides/01-create-an-app.md +0 -183
- package/docs/dev-guides/02-create-a-function.md +0 -178
- package/docs/dev-guides/03-create-a-component.md +0 -178
- package/docs/dev-guides/04-webhook-handlers.md +0 -129
- package/docs/dev-guides/05-testing.md +0 -168
- package/docs/dev-guides/README.md +0 -40
- package/docs/npm-packages-plan.md +0 -288
- package/docs/spine-core--api-reference.md +0 -822
|
@@ -1,5 +1,28 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
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"]
|
|
3
26
|
import { Command } from 'commander'
|
|
4
27
|
import { readFileSync, existsSync, readdirSync, statSync } from 'fs'
|
|
5
28
|
import { join, dirname } from 'path'
|
|
@@ -53,7 +76,21 @@ class ValidationError extends Error {
|
|
|
53
76
|
this.name = 'ValidationError'
|
|
54
77
|
}
|
|
55
78
|
}
|
|
56
|
-
|
|
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."]
|
|
92
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
93
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
57
94
|
function validateManifest(appPath: string): Manifest {
|
|
58
95
|
const manifestPath = join(appPath, 'manifest.json')
|
|
59
96
|
|
|
@@ -68,7 +105,6 @@ function validateManifest(appPath: string): Manifest {
|
|
|
68
105
|
throw new ValidationError('❌ manifest.json is not valid JSON')
|
|
69
106
|
}
|
|
70
107
|
|
|
71
|
-
// Required fields
|
|
72
108
|
const requiredFields = ['name', 'slug', 'version', 'app_type']
|
|
73
109
|
for (const field of requiredFields) {
|
|
74
110
|
if (!manifest[field]) {
|
|
@@ -76,7 +112,6 @@ function validateManifest(appPath: string): Manifest {
|
|
|
76
112
|
}
|
|
77
113
|
}
|
|
78
114
|
|
|
79
|
-
// Validate app_type
|
|
80
115
|
const validAppTypes = ['full', 'ui', 'backend', 'data']
|
|
81
116
|
if (!validAppTypes.includes(manifest.app_type)) {
|
|
82
117
|
throw new ValidationError(`❌ manifest.json app_type must be one of: ${validAppTypes.join(', ')}`)
|
|
@@ -84,7 +119,21 @@ function validateManifest(appPath: string): Manifest {
|
|
|
84
119
|
|
|
85
120
|
return manifest
|
|
86
121
|
}
|
|
87
|
-
|
|
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."]
|
|
135
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
136
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
88
137
|
function validatePackageJson(appPath: string, manifest: Manifest): PackageJson {
|
|
89
138
|
const packagePath = join(appPath, 'package.json')
|
|
90
139
|
|
|
@@ -99,39 +148,63 @@ function validatePackageJson(appPath: string, manifest: Manifest): PackageJson {
|
|
|
99
148
|
throw new ValidationError('❌ package.json is not valid JSON')
|
|
100
149
|
}
|
|
101
150
|
|
|
102
|
-
// Check version sync
|
|
103
151
|
if (packageJson.version !== manifest.version) {
|
|
104
152
|
throw new ValidationError(`❌ Version mismatch: package.json has ${packageJson.version} but manifest.json has ${manifest.version}`)
|
|
105
153
|
}
|
|
106
154
|
|
|
107
155
|
return packageJson
|
|
108
156
|
}
|
|
109
|
-
|
|
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."]
|
|
170
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
171
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
110
172
|
function validateRequiredFiles(appPath: string, manifest: Manifest): void {
|
|
111
173
|
const { app_type } = manifest
|
|
112
174
|
|
|
113
|
-
// index.tsx is required for full and ui apps
|
|
114
175
|
if (['full', 'ui'].includes(app_type)) {
|
|
115
176
|
if (!existsSync(join(appPath, 'index.tsx'))) {
|
|
116
177
|
throw new ValidationError('❌ index.tsx is required for full and ui apps')
|
|
117
178
|
}
|
|
118
179
|
}
|
|
119
180
|
|
|
120
|
-
// pages/ is required for full and ui apps
|
|
121
181
|
if (['full', 'ui'].includes(app_type)) {
|
|
122
182
|
if (!existsSync(join(appPath, 'pages'))) {
|
|
123
183
|
throw new ValidationError('❌ pages/ directory is required for full and ui apps')
|
|
124
184
|
}
|
|
125
185
|
}
|
|
126
186
|
|
|
127
|
-
// functions/ is required for full and backend apps
|
|
128
187
|
if (['full', 'backend'].includes(app_type)) {
|
|
129
188
|
if (!existsSync(join(appPath, 'functions'))) {
|
|
130
189
|
throw new ValidationError('❌ functions/ directory is required for full and backend apps')
|
|
131
190
|
}
|
|
132
191
|
}
|
|
133
192
|
}
|
|
134
|
-
|
|
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."]
|
|
206
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
207
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
135
208
|
function validateAllowedDirectories(appPath: string): void {
|
|
136
209
|
const allowedDirs = [
|
|
137
210
|
'pages', 'components', 'hooks', 'utils', 'functions',
|
|
@@ -142,14 +215,27 @@ function validateAllowedDirectories(appPath: string): void {
|
|
|
142
215
|
.filter(dirent => dirent.isDirectory())
|
|
143
216
|
.map(dirent => dirent.name)
|
|
144
217
|
|
|
145
|
-
// Filter out .devin/ since it's optional and handled separately
|
|
146
218
|
const unknownDirs = entries.filter(dir => !allowedDirs.includes(dir) && dir !== '.devin')
|
|
147
219
|
|
|
148
220
|
if (unknownDirs.length > 0) {
|
|
149
221
|
throw new ValidationError(`❌ Unknown directories found: ${unknownDirs.join(', ')}. Allowed directories: ${allowedDirs.join(', ')} (plus optional .devin/)`)
|
|
150
222
|
}
|
|
151
223
|
}
|
|
152
|
-
|
|
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."]
|
|
237
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
238
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
153
239
|
function validateDevinDirectory(appPath: string): void {
|
|
154
240
|
const devinPath = join(appPath, '.devin')
|
|
155
241
|
|
|
@@ -161,7 +247,6 @@ function validateDevinDirectory(appPath: string): void {
|
|
|
161
247
|
throw new ValidationError('❌ .devin/ directory exists but AGENTS.md is missing. If .devin/ exists, it must contain AGENTS.md with agentic guidance.')
|
|
162
248
|
}
|
|
163
249
|
|
|
164
|
-
// Validate skills if they exist
|
|
165
250
|
const skillsPath = join(devinPath, 'skills')
|
|
166
251
|
if (existsSync(skillsPath)) {
|
|
167
252
|
const skillDirs = readdirSync(skillsPath, { withFileTypes: true })
|
|
@@ -180,7 +265,21 @@ function validateDevinDirectory(appPath: string): void {
|
|
|
180
265
|
console.log(`✅ .devin/ directory not present (optional)`)
|
|
181
266
|
}
|
|
182
267
|
}
|
|
183
|
-
|
|
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."]
|
|
281
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
282
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
184
283
|
function validateRoutes(appPath: string, manifest: Manifest): void {
|
|
185
284
|
if (!manifest.route_prefix) {
|
|
186
285
|
console.warn('⚠️ manifest.json is missing route_prefix — install-app will default to /{slug}')
|
|
@@ -204,7 +303,6 @@ function validateRoutes(appPath: string, manifest: Manifest): void {
|
|
|
204
303
|
}
|
|
205
304
|
}
|
|
206
305
|
|
|
207
|
-
// nav_items paths must also be root-relative
|
|
208
306
|
if (Array.isArray((manifest as any).nav_items)) {
|
|
209
307
|
const checkNavItem = (item: any) => {
|
|
210
308
|
if (item.path && prefix && item.path.startsWith(prefix)) {
|
|
@@ -219,9 +317,22 @@ function validateRoutes(appPath: string, manifest: Manifest): void {
|
|
|
219
317
|
for (const item of (manifest as any).nav_items) checkNavItem(item)
|
|
220
318
|
}
|
|
221
319
|
}
|
|
222
|
-
|
|
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."]
|
|
333
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
334
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
223
335
|
function validateManifestComponents(appPath: string, manifest: Manifest): void {
|
|
224
|
-
// entry_point — if declared, the file must exist
|
|
225
336
|
if (manifest.entry_point) {
|
|
226
337
|
const ep = manifest.entry_point.replace(/^\.\//, '')
|
|
227
338
|
if (!existsSync(join(appPath, ep))) {
|
|
@@ -229,7 +340,6 @@ function validateManifestComponents(appPath: string, manifest: Manifest): void {
|
|
|
229
340
|
}
|
|
230
341
|
}
|
|
231
342
|
|
|
232
|
-
// sidebar_component — if declared, the file must exist
|
|
233
343
|
if (manifest.sidebar_component) {
|
|
234
344
|
const sc = manifest.sidebar_component.replace(/^\.\//, '')
|
|
235
345
|
if (!existsSync(join(appPath, sc))) {
|
|
@@ -237,14 +347,27 @@ function validateManifestComponents(appPath: string, manifest: Manifest): void {
|
|
|
237
347
|
}
|
|
238
348
|
}
|
|
239
349
|
|
|
240
|
-
// registration — account_strategy "existing" requires target_account
|
|
241
350
|
if (manifest.registration?.account_strategy === 'existing' && !manifest.registration?.target_account) {
|
|
242
351
|
throw new ValidationError(`❌ manifest.json registration.account_strategy is "existing" but target_account is not set`)
|
|
243
352
|
}
|
|
244
353
|
}
|
|
245
|
-
|
|
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."]
|
|
367
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
368
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
246
369
|
function validateSeedBlock(appPath: string, manifest: Manifest): void {
|
|
247
|
-
if (!manifest.seed) return
|
|
370
|
+
if (!manifest.seed) return
|
|
248
371
|
|
|
249
372
|
if (!Array.isArray(manifest.seed)) {
|
|
250
373
|
throw new ValidationError('❌ manifest.json seed must be an array')
|
|
@@ -252,109 +375,80 @@ function validateSeedBlock(appPath: string, manifest: Manifest): void {
|
|
|
252
375
|
|
|
253
376
|
for (const entry of manifest.seed) {
|
|
254
377
|
if (!entry.file || !entry.table || !entry.conflict) {
|
|
255
|
-
throw new ValidationError(
|
|
256
|
-
`❌ manifest.json seed entry missing required field(s) (file, table, conflict): ${JSON.stringify(entry)}`
|
|
257
|
-
)
|
|
258
|
-
}
|
|
259
|
-
const filePath = join(appPath, entry.file)
|
|
260
|
-
if (!existsSync(filePath)) {
|
|
261
|
-
throw new ValidationError(`❌ manifest.json seed entry file "${entry.file}" does not exist`)
|
|
262
|
-
}
|
|
263
|
-
// Verify the file is valid JSON and an array
|
|
264
|
-
try {
|
|
265
|
-
const contents = JSON.parse(readFileSync(filePath, 'utf8'))
|
|
266
|
-
if (!Array.isArray(contents)) {
|
|
267
|
-
throw new ValidationError(`❌ Seed file "${entry.file}" must export a JSON array`)
|
|
268
|
-
}
|
|
269
|
-
} catch (err: any) {
|
|
270
|
-
if (err instanceof ValidationError) throw err
|
|
271
|
-
throw new ValidationError(`❌ Seed file "${entry.file}" is not valid JSON: ${err.message}`)
|
|
378
|
+
throw new ValidationError('❌ manifest.json seed entries must have file, table, and conflict fields')
|
|
272
379
|
}
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
380
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}
|
|
280
|
-
if (packageJson.private === undefined) {
|
|
281
|
-
console.warn('⚠️ package.json is missing "private": false — add it to confirm the package is publishable')
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
function validatePackageFiles(appPath: string, packageJson: PackageJson): void {
|
|
286
|
-
const { files = [] } = packageJson
|
|
287
|
-
|
|
288
|
-
// Check that important directories are included in files array
|
|
289
|
-
const importantFiles = ['index.tsx', 'manifest.json']
|
|
290
|
-
const importantDirs = ['pages', 'components', 'hooks', 'utils', 'functions', 'seed', 'public']
|
|
291
|
-
|
|
292
|
-
for (const file of importantFiles) {
|
|
293
|
-
if (existsSync(join(appPath, file)) && !files.includes(file)) {
|
|
294
|
-
console.warn(`⚠️ ${file} exists but is not in package.json files array`)
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
for (const dir of importantDirs) {
|
|
299
|
-
if (existsSync(join(appPath, dir)) && !files.includes(`${dir}/`)) {
|
|
300
|
-
console.warn(`⚠️ ${dir}/ exists but is not in package.json files array`)
|
|
381
|
+
const seedFile = join(appPath, 'seed', entry.file)
|
|
382
|
+
if (!existsSync(seedFile)) {
|
|
383
|
+
throw new ValidationError(`❌ Seed file not found: seed/${entry.file}`)
|
|
301
384
|
}
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
function validateApp(appPath: string): void {
|
|
306
|
-
try {
|
|
307
|
-
console.log(`🔍 Validating app at: ${appPath}`)
|
|
308
|
-
|
|
309
|
-
const manifest = validateManifest(appPath)
|
|
310
|
-
console.log(`✅ manifest.json valid for ${manifest.name} v${manifest.version}`)
|
|
311
|
-
|
|
312
|
-
const packageJson = validatePackageJson(appPath, manifest)
|
|
313
|
-
console.log(`✅ package.json valid and versions match`)
|
|
314
|
-
|
|
315
|
-
validateRequiredFiles(appPath, manifest)
|
|
316
|
-
console.log(`✅ Required files present for app_type: ${manifest.app_type}`)
|
|
317
|
-
|
|
318
|
-
validateRoutes(appPath, manifest)
|
|
319
|
-
console.log(`✅ manifest.json routes and nav_items are root-relative`)
|
|
320
|
-
|
|
321
|
-
validateManifestComponents(appPath, manifest)
|
|
322
|
-
console.log(`✅ manifest.json entry_point, sidebar_component, and registration valid`)
|
|
323
|
-
|
|
324
|
-
validateSeedBlock(appPath, manifest)
|
|
325
|
-
console.log(`✅ manifest.json seed block valid`)
|
|
326
385
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
validateDevinDirectory(appPath)
|
|
331
|
-
console.log(`✅ .devin/ directory valid (if present)`)
|
|
332
|
-
|
|
333
|
-
validatePackagePublishability(packageJson)
|
|
334
|
-
console.log(`✅ package.json publishability valid`)
|
|
335
|
-
|
|
336
|
-
validatePackageFiles(appPath, packageJson)
|
|
337
|
-
console.log(`✅ package.json files array checked`)
|
|
338
|
-
|
|
339
|
-
console.log(`\n🎉 App validation passed!`)
|
|
340
|
-
|
|
341
|
-
} catch (err) {
|
|
342
|
-
if (err instanceof ValidationError) {
|
|
343
|
-
console.error(err.message)
|
|
344
|
-
process.exit(1)
|
|
345
|
-
} else {
|
|
346
|
-
console.error(`❌ Unexpected error: ${err.message}`)
|
|
347
|
-
process.exit(1)
|
|
386
|
+
if (!seedFile.endsWith('.sql')) {
|
|
387
|
+
throw new ValidationError(`❌ Seed file must be .sql: seed/${entry.file}`)
|
|
348
388
|
}
|
|
349
389
|
}
|
|
350
390
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
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"]
|
|
399
|
+
// 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."]
|
|
404
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
405
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
406
|
+
function validateAppStructure(appPath: string): void {
|
|
407
|
+
const manifest = validateManifest(appPath)
|
|
408
|
+
validatePackageJson(appPath, manifest)
|
|
409
|
+
validateRequiredFiles(appPath, manifest)
|
|
410
|
+
validateAllowedDirectories(appPath)
|
|
411
|
+
validateDevinDirectory(appPath)
|
|
412
|
+
validateRoutes(appPath, manifest)
|
|
413
|
+
validateManifestComponents(appPath, manifest)
|
|
414
|
+
validateSeedBlock(appPath, manifest)
|
|
415
|
+
console.log(`✅ App structure is valid`)
|
|
416
|
+
}
|
|
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."]
|
|
430
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
431
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
432
|
+
export function registerValidateAppCommands(program: Command) {
|
|
433
|
+
program
|
|
434
|
+
.command('validate-app [path]')
|
|
435
|
+
.description('Validate app structure and manifest')
|
|
436
|
+
.option('--fix', 'Attempt to fix common issues (not implemented)')
|
|
437
|
+
.action(async (path = '.') => {
|
|
438
|
+
try {
|
|
439
|
+
const appPath = join(process.cwd(), path)
|
|
440
|
+
console.log(`Validating app at: ${appPath}`)
|
|
441
|
+
validateAppStructure(appPath)
|
|
442
|
+
console.log(`✅ App validation passed`)
|
|
443
|
+
} catch (err: any) {
|
|
444
|
+
if (err instanceof ValidationError) {
|
|
445
|
+
console.error(err.message)
|
|
446
|
+
process.exit(1)
|
|
447
|
+
} else {
|
|
448
|
+
console.error('❌ Unexpected error:', err.message)
|
|
449
|
+
process.exit(1)
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
})
|
|
453
|
+
}
|
|
454
|
+
// CIL[END chunk_id="validate-app_registervalidateappcommands_1784068794"]
|