spine-framework 0.3.144 → 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.
- package/.env.example +76 -0
- package/.framework/.spine-manifest.json +19 -0
- package/.framework/cli/commands/agents.ts +61 -33
- package/.framework/cli/commands/auth.ts +60 -28
- package/.framework/cli/commands/create-app.ts +212 -80
- package/.framework/cli/commands/dev.ts +184 -68
- package/.framework/cli/commands/doctor.ts +324 -152
- package/.framework/cli/commands/generate.ts +119 -68
- package/.framework/cli/commands/init.ts +141 -242
- package/.framework/cli/commands/install-app.ts +1336 -314
- package/.framework/cli/commands/items.ts +31 -29
- package/.framework/cli/commands/migrate.ts +299 -156
- package/.framework/cli/commands/migrations.ts +62 -30
- package/.framework/cli/commands/pipelines.ts +31 -29
- package/.framework/cli/commands/status.ts +105 -45
- package/.framework/cli/commands/system.ts +47 -42
- package/.framework/cli/commands/test.ts +161 -102
- package/.framework/cli/commands/upgrade.ts +260 -0
- package/.framework/cli/commands/validate-app.ts +517 -161
- package/.framework/cli/context.ts +117 -85
- package/.framework/cli/env-loader.ts +74 -43
- package/.framework/cli/index.ts +70 -46
- package/.framework/cli/lib/project-files.ts +404 -0
- package/.framework/docs/guides/testing-guide.md +1 -1
- package/.framework/docs/runtime-types.md +72 -72
- package/.framework/functions/_shared/access.ts +84 -0
- package/.framework/functions/_shared/agent-runner.ts +5051 -1026
- package/.framework/functions/_shared/app-manifest.ts +214 -94
- package/.framework/functions/_shared/ast.ts +214 -0
- package/.framework/functions/_shared/audit.ts +91 -55
- package/.framework/functions/_shared/cil.ts +368 -127
- package/.framework/functions/_shared/db.ts +337 -68
- package/.framework/functions/_shared/funnel.ts +228 -0
- package/.framework/functions/_shared/geo.ts +105 -0
- package/.framework/functions/_shared/hash-api-key.ts +94 -17
- package/.framework/functions/_shared/index.ts +22 -224
- package/.framework/functions/_shared/kb.ts +832 -58
- package/.framework/functions/_shared/llm.ts +118 -18
- package/.framework/functions/_shared/logging.ts +317 -19
- package/.framework/functions/_shared/middleware.ts +701 -131
- package/.framework/functions/_shared/notify.ts +70 -0
- package/.framework/functions/_shared/outcomes.ts +34 -19
- package/.framework/functions/_shared/permissions.ts +501 -315
- package/.framework/functions/_shared/pipeline-runner.ts +704 -155
- package/.framework/functions/_shared/principal.ts +436 -263
- package/.framework/functions/_shared/rate-limit.ts +233 -0
- package/.framework/functions/_shared/resolve-credentials.ts +86 -19
- package/.framework/functions/_shared/resolve-ids.ts +203 -139
- package/.framework/functions/_shared/retry-deliveries.ts +51 -16
- package/.framework/functions/_shared/schema-utils.ts +602 -521
- package/.framework/functions/_shared/security.ts +345 -0
- package/.framework/functions/_shared/testing.ts +197 -172
- package/.framework/functions/_shared/tracing.ts +351 -21
- package/.framework/functions/_shared/trigger-engine.ts +425 -136
- package/.framework/functions/_shared/webhook-registration.ts +71 -70
- package/.framework/functions/_shared/webhook-registry.ts +126 -83
- package/.framework/functions/account-nodes.ts +30 -30
- package/.framework/functions/adapters/generic-webhook-inbound.ts +49 -16
- package/.framework/functions/adapters/generic-webhook-outbound.ts +17 -17
- package/.framework/functions/adapters/openai-outbound.ts +15 -16
- package/.framework/functions/admin-data.ts +596 -173
- package/.framework/functions/admin-funnel.ts +64 -60
- package/.framework/functions/admin-install-funnel.ts +84 -66
- package/.framework/functions/admin-signals.ts +69 -51
- package/.framework/functions/ai-agents.ts +431 -106
- package/.framework/functions/ai-interactions.ts +186 -112
- package/.framework/functions/api-keys.ts +107 -107
- package/.framework/functions/apps.ts +154 -136
- package/.framework/functions/auth.ts +83 -65
- package/.framework/functions/cil-agent-ingest.ts +189 -232
- package/.framework/functions/cil-agent.ts +433 -177
- package/.framework/functions/cil-callmap.ts +642 -430
- package/.framework/functions/cil-config.ts +139 -135
- package/.framework/functions/cil-context.ts +214 -127
- package/.framework/functions/cil-doc.ts +587 -458
- package/.framework/functions/cil-embeddings.ts +453 -364
- package/.framework/functions/cil-graph.ts +427 -142
- package/.framework/functions/cil-ingest.ts +1418 -1154
- package/.framework/functions/cil-pipeline.ts +276 -21
- package/.framework/functions/cil-project.ts +659 -132
- package/.framework/functions/cil-validate.ts +198 -164
- package/.framework/functions/debug-auth.ts +57 -55
- package/.framework/functions/deliveries.ts +80 -21
- package/.framework/functions/embeddings.ts +1023 -318
- package/.framework/functions/eval-harness.ts +146 -108
- package/.framework/functions/integration-outbound.ts +205 -75
- package/.framework/functions/integration-routes.ts +128 -23
- package/.framework/functions/integrations.ts +125 -100
- package/.framework/functions/invites.ts +1095 -460
- package/.framework/functions/item-progress.ts +158 -102
- package/.framework/functions/kb.ts +34 -10
- package/.framework/functions/logs.ts +133 -133
- package/.framework/functions/observability.ts +152 -122
- package/.framework/functions/pipeline-executions.ts +147 -132
- package/.framework/functions/pipelines.ts +134 -119
- package/.framework/functions/prompt-configs.ts +96 -80
- package/.framework/functions/roles.ts +112 -82
- package/.framework/functions/security.ts +450 -0
- package/.framework/functions/system-cron.ts +117 -80
- package/.framework/functions/system.ts +158 -98
- package/.framework/functions/tests.ts +29 -29
- package/.framework/functions/timers.ts +94 -95
- package/.framework/functions/trigger-scheduler.ts +10 -0
- package/.framework/functions/triggers.ts +179 -149
- package/.framework/functions/types.ts +137 -125
- package/.framework/mcp/index.ts +133 -0
- package/.framework/mcp/load-env.ts +60 -0
- package/.framework/mcp/shared/app-manifest.ts +275 -0
- package/.framework/mcp/shared/db.ts +477 -0
- package/.framework/mcp/shared/kb.ts +118 -0
- package/.framework/mcp/tools/architect.ts +431 -0
- package/.framework/mcp/tools/cil/context.ts +345 -0
- package/.framework/mcp/tools/cil/graph.ts +242 -0
- package/.framework/mcp/tools/cil/ingest.ts +1217 -0
- package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +693 -0
- package/.framework/mcp/tools/cil/pipeline.ts +767 -0
- package/.framework/mcp/tools/cil/project.ts +791 -0
- package/.framework/mcp/tools/cil/retrieval.ts +336 -0
- package/.framework/mcp/tools/cil/search-core.ts +454 -0
- package/.framework/mcp/tools/cil/search.ts +97 -0
- package/.framework/mcp/tools/cil/suggest.ts +186 -0
- package/.framework/mcp/tools/cil/validate.ts +1369 -0
- package/.framework/mcp/tools/kb/delete.ts +139 -0
- package/.framework/mcp/tools/kb/index.ts +52 -0
- package/.framework/mcp/tools/kb/ingest.ts +84 -0
- package/.framework/mcp/tools/kb/list-types.ts +102 -0
- package/.framework/mcp/tools/kb/publish.ts +100 -0
- package/.framework/mcp/tools/kb/reindex.ts +86 -0
- package/.framework/mcp/tools/kb/revoke.ts +85 -0
- package/.framework/mcp/tools/kb/search.ts +101 -0
- package/.framework/mcp/tools/kb/upsert.ts +125 -0
- package/.framework/mcp/tools/observability.ts +510 -0
- package/.framework/migrations/001_core_schema.sql +15 -0
- package/.framework/migrations/002_core_rls_and_functions.sql +15 -0
- package/.framework/migrations/003_core_system_data.sql +16 -1
- package/.framework/migrations/004_core_rpc_and_broker.sql +17 -1
- package/.framework/migrations/005_core_observability.sql +17 -1
- package/.framework/migrations/006_security_hardening_rls.sql +15 -0
- package/.framework/migrations/007_kb_article_list.sql +17 -1
- package/.framework/migrations/008_items_target.sql +15 -0
- package/.framework/migrations/009_roles_slug_unique.sql +15 -0
- package/.framework/migrations/010_auth_user_trigger.sql +15 -0
- package/.framework/migrations/011_spine_system_account.sql +16 -0
- package/.framework/migrations/012_service_role_grants.sql +16 -0
- package/.framework/migrations/013_get_account_apps_role_filter.sql +15 -0
- package/.framework/migrations/014_apps_required_roles.sql +16 -0
- package/.framework/migrations/015_types_kind_slug_unique.sql +20 -0
- package/.framework/migrations/016_cil_types.sql +281 -0
- package/.framework/migrations/017_cil_stable_ids.sql +37 -0
- package/.framework/migrations/018_runtime_tables.sql +129 -0
- package/.framework/migrations/019_agent_prompt_columns.sql +56 -0
- package/.framework/migrations/020_schema_reconciliation.sql +67 -0
- package/.framework/migrations/021_kb_embedding_lifecycle.sql +31 -0
- package/.framework/migrations/032_cil_status_migration.sql +73 -0
- package/.framework/migrations/033_cil_versioning.sql +73 -0
- package/.framework/migrations/034_match_embeddings_knn.sql +115 -0
- package/.framework/migrations/035_rate_limits.sql +55 -0
- package/.framework/migrations/036_demo_record_flags.sql +72 -0
- package/.framework/migrations/037_kb_types_canonical.sql +244 -0
- package/.framework/migrations/038_drop_demo_record_flags.sql +38 -0
- package/.framework/migrations/042_registration_hierarchy.sql +309 -0
- package/.framework/migrations/043_policy_actor_cleanup.sql +39 -0
- package/.framework/migrations/044_match_embeddings_filtered_knn.sql +151 -0
- package/.framework/migrations/045_security_critical_rls.sql +139 -0
- package/.framework/migrations/046_security_missing_rls.sql +79 -0
- package/.framework/migrations/047_people_updated_by.sql +27 -0
- package/.framework/migrations/048_watcher_last_seen_at.sql +24 -0
- package/.framework/migrations/049_security_blocklist.sql +148 -0
- package/.framework/migrations/050_notifications.sql +49 -0
- package/.framework/migrations/051_message_agent_fields.sql +74 -0
- package/.framework/migrations/052_registration_security.sql +421 -0
- package/.framework/migrations/053_builtin_action_seeds.sql +66 -0
- package/.framework/migrations/054_kb_ingest_lease.sql +157 -0
- package/.framework/migrations/055_type_id_drift_reconciliation.sql +33 -0
- package/.framework/migrations/056_slug_column_reconciliation.sql +38 -0
- package/.framework/migrations/057_pipelines_slug_identity.sql +14 -0
- package/.framework/migrations/058_account_data_field_declarations.sql +53 -0
- package/.framework/migrations/059_registration_placement_fixes.sql +269 -0
- package/.framework/migrations/060_account_person_record_permissions.sql +38 -0
- package/.framework/migrations/061_fk_dedup.sql +32 -0
- package/.framework/public/spine-logo.svg +10 -3
- package/.framework/scripts/app-install-cli.ts +190 -93
- package/.framework/scripts/assemble-frontend.sh +127 -44
- package/.framework/scripts/assemble-functions.sh +128 -30
- package/.framework/scripts/boundary-check.sh +6 -2
- package/.framework/scripts/build-manifest.sh +24 -68
- package/.framework/scripts/check-core-integrity.sh +15 -76
- package/.framework/scripts/checksum-manifest.mts +343 -0
- package/.framework/scripts/cil-migrate-markers.ts +403 -0
- package/.framework/scripts/fix-cil-markers.mjs +176 -0
- package/.framework/scripts/verify-integrity.sh +21 -57
- package/.framework/scripts/verify-manifest.mts +305 -0
- package/.framework/seeds/types/funnel_signal_use.json +74 -21
- package/.framework/seeds/types/spine_instance.json +73 -21
- package/.framework/src/App.tsx +118 -72
- package/.framework/src/apps/admin/index.tsx +855 -58
- package/.framework/src/components/AppWrapper.tsx +43 -45
- package/.framework/src/components/CustomAppLoader.tsx +160 -116
- package/.framework/src/components/admin/AdminListPage.tsx +46 -44
- package/.framework/src/components/admin/AdminSidebar.tsx +57 -47
- package/.framework/src/components/admin/AdminStatsCard.tsx +46 -44
- package/.framework/src/components/admin/PageInstructions.tsx +98 -2
- package/.framework/src/components/admin/SortableTableHeader.tsx +44 -45
- package/.framework/src/components/app-shell/GenericAppShell.tsx +64 -65
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +44 -47
- package/.framework/src/components/app-shell/GenericListPage.tsx +45 -49
- package/.framework/src/components/app-sidebar.tsx +42 -45
- package/.framework/src/components/auth/ProtectedRoute.tsx +48 -41
- package/.framework/src/components/auth/TurnstileWidget.tsx +27 -0
- package/.framework/src/components/kb/KBArticleEditor.tsx +231 -22
- package/.framework/src/components/kb/KBArticleList.tsx +251 -10
- package/.framework/src/components/layout/AppShell.tsx +51 -45
- package/.framework/src/components/layout/Header.tsx +42 -43
- package/.framework/src/components/layout/Layout.tsx +46 -46
- package/.framework/src/components/layout/Sidebar.tsx +196 -96
- package/.framework/src/components/runtime/DataDetailHeader.tsx +55 -30
- package/.framework/src/components/runtime/DataDetailPage.tsx +31 -269
- package/.framework/src/components/runtime/DataFilters.tsx +49 -74
- package/.framework/src/components/runtime/DataHeader.tsx +53 -32
- package/.framework/src/components/runtime/DataListPage.tsx +51 -155
- package/.framework/src/components/runtime/DataStats.tsx +66 -44
- package/.framework/src/components/runtime/DataTable.tsx +49 -149
- package/.framework/src/components/runtime/SchemaDetailForm.tsx +45 -75
- package/.framework/src/components/runtime/index.ts +119 -16
- package/.framework/src/components/search-form.tsx +46 -29
- package/.framework/src/components/shared/AgentView.tsx +65 -48
- package/.framework/src/components/shared/FieldRenderer.tsx +144 -50
- package/.framework/src/components/shared/InviteManager.tsx +207 -97
- package/.framework/src/components/shared/MemberList.tsx +97 -0
- package/.framework/src/components/shared/SchemaFields.tsx +107 -86
- package/.framework/src/components/ui/DataTable.tsx +80 -68
- package/.framework/src/components/ui/Form.tsx +157 -146
- package/.framework/src/components/ui/ItemCard.tsx +74 -67
- package/.framework/src/components/ui/ItemListView.tsx +73 -68
- package/.framework/src/components/ui/LoadingSpinner.tsx +43 -48
- package/.framework/src/components/ui/Modal.tsx +78 -68
- package/.framework/src/components/ui/RichTextEditor.tsx +89 -69
- package/.framework/src/components/ui/accordion.tsx +85 -86
- package/.framework/src/components/ui/alert-dialog.tsx +197 -184
- package/.framework/src/components/ui/alert.tsx +105 -94
- package/.framework/src/components/ui/aspect-ratio.tsx +57 -43
- package/.framework/src/components/ui/avatar.tsx +122 -107
- package/.framework/src/components/ui/badge.tsx +60 -55
- package/.framework/src/components/ui/breadcrumb.tsx +127 -128
- package/.framework/src/components/ui/button-group.tsx +86 -72
- package/.framework/src/components/ui/button.tsx +71 -50
- package/.framework/src/components/ui/calendar.tsx +72 -57
- package/.framework/src/components/ui/card.tsx +136 -129
- package/.framework/src/components/ui/carousel.tsx +226 -107
- package/.framework/src/components/ui/chart.tsx +252 -147
- package/.framework/src/components/ui/checkbox.tsx +43 -44
- package/.framework/src/components/ui/collapsible.tsx +86 -71
- package/.framework/src/components/ui/combobox.tsx +282 -249
- package/.framework/src/components/ui/command.tsx +158 -146
- package/.framework/src/components/ui/context-menu.tsx +239 -240
- package/.framework/src/components/ui/dialog.tsx +174 -157
- package/.framework/src/components/ui/direction.tsx +72 -56
- package/.framework/src/components/ui/drawer.tsx +168 -169
- package/.framework/src/components/ui/dropdown-menu.tsx +254 -223
- package/.framework/src/components/ui/empty.tsx +131 -120
- package/.framework/src/components/ui/field.tsx +205 -173
- package/.framework/src/components/ui/hover-card.tsx +71 -72
- package/.framework/src/components/ui/input-group.tsx +148 -133
- package/.framework/src/components/ui/input-otp.tsx +99 -86
- package/.framework/src/components/ui/input.tsx +43 -41
- package/.framework/src/components/ui/item.tsx +207 -185
- package/.framework/src/components/ui/kbd.tsx +57 -56
- package/.framework/src/components/ui/label.tsx +45 -41
- package/.framework/src/components/ui/menubar.tsx +268 -236
- package/.framework/src/components/ui/native-select.tsx +85 -86
- package/.framework/src/components/ui/navigation-menu.tsx +166 -156
- package/.framework/src/components/ui/pagination.tsx +131 -141
- package/.framework/src/components/ui/popover.tsx +125 -128
- package/.framework/src/components/ui/progress.tsx +47 -44
- package/.framework/src/components/ui/radio-group.tsx +60 -55
- package/.framework/src/components/ui/resizable.tsx +85 -72
- package/.framework/src/components/ui/scroll-area.tsx +57 -58
- package/.framework/src/components/ui/select.tsx +182 -169
- package/.framework/src/components/ui/separator.tsx +42 -43
- package/.framework/src/components/ui/sheet.tsx +170 -159
- package/.framework/src/components/ui/sidebar.tsx +395 -398
- package/.framework/src/components/ui/skeleton.tsx +42 -43
- package/.framework/src/components/ui/slider.tsx +61 -44
- package/.framework/src/components/ui/sonner.tsx +44 -44
- package/.framework/src/components/ui/spinner.tsx +47 -42
- package/.framework/src/components/ui/switch.tsx +56 -42
- package/.framework/src/components/ui/table-primitives.tsx +272 -132
- package/.framework/src/components/ui/table.tsx +140 -142
- package/.framework/src/components/ui/tabs.tsx +110 -93
- package/.framework/src/components/ui/textarea.tsx +43 -44
- package/.framework/src/components/ui/toggle-group.tsx +87 -71
- package/.framework/src/components/ui/toggle.tsx +56 -56
- package/.framework/src/components/ui/tooltip.tsx +99 -85
- package/.framework/src/contexts/AppContext.tsx +166 -114
- package/.framework/src/contexts/AuthContext.tsx +232 -137
- package/.framework/src/hooks/use-mobile.ts +43 -44
- package/.framework/src/hooks/useApi.ts +185 -172
- package/.framework/src/hooks/useAppPath.ts +31 -29
- package/.framework/src/hooks/useApps.ts +77 -42
- package/.framework/src/hooks/useEntityList.ts +66 -29
- package/.framework/src/hooks/useEntityRecord.ts +76 -32
- package/.framework/src/hooks/useForm.ts +62 -30
- package/.framework/src/hooks/useListSchema.ts +60 -43
- package/.framework/src/hooks/useSchemaRecord.ts +115 -95
- package/.framework/src/lib/api.ts +258 -134
- package/.framework/src/lib/registration.ts +181 -0
- package/.framework/src/lib/supabase.ts +118 -81
- package/.framework/src/lib/utils.ts +266 -266
- package/.framework/src/main.tsx +43 -44
- package/.framework/src/pages/DashboardPage.tsx +44 -43
- package/.framework/src/pages/NoAppPage.tsx +50 -0
- package/.framework/src/pages/NotFoundPage.tsx +32 -29
- package/.framework/src/pages/SetupPage.tsx +34 -33
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +69 -58
- package/.framework/src/pages/admin/AIAgentsPage.tsx +43 -40
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +63 -55
- package/.framework/src/pages/admin/APIKeysPage.tsx +44 -42
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +117 -94
- package/.framework/src/pages/admin/AppDetailPage.tsx +48 -42
- package/.framework/src/pages/admin/AppsPage.tsx +45 -42
- package/.framework/src/pages/admin/DeliveriesPage.tsx +49 -17
- package/.framework/src/pages/admin/DesignedPage.tsx +31 -30
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +58 -0
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +49 -0
- package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +31 -29
- package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +46 -29
- package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -29
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +68 -55
- package/.framework/src/pages/admin/IntegrationsPage.tsx +45 -42
- package/.framework/src/pages/admin/InvitesPage.tsx +60 -44
- package/.framework/src/pages/admin/LogsPage.tsx +87 -137
- package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +31 -29
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +150 -89
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +77 -104
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +44 -43
- package/.framework/src/pages/admin/PipelinesPage.tsx +59 -145
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +53 -42
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +47 -117
- package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +31 -44
- package/.framework/src/pages/admin/RoleDetailPage.tsx +49 -92
- package/.framework/src/pages/admin/RolesPage.tsx +47 -164
- package/.framework/src/pages/admin/SecurityPage.tsx +310 -0
- package/.framework/src/pages/admin/SelectTestPage.tsx +30 -32
- package/.framework/src/pages/admin/ShadcnTestPage.tsx +37 -44
- package/.framework/src/pages/admin/SimpleDashboard.tsx +32 -44
- package/.framework/src/pages/admin/TestRunDetailPage.tsx +97 -44
- package/.framework/src/pages/admin/TestingDashboard.tsx +126 -71
- package/.framework/src/pages/admin/TimerDetailPage.tsx +67 -55
- package/.framework/src/pages/admin/TimersPage.tsx +44 -42
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +47 -42
- package/.framework/src/pages/admin/TriggersPage.tsx +58 -57
- package/.framework/src/pages/admin/TypeDetailPage.tsx +91 -55
- package/.framework/src/pages/admin/TypesPage.tsx +45 -42
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +258 -128
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +127 -123
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +308 -235
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +159 -110
- package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +432 -0
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +200 -178
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +286 -239
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +211 -90
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +156 -143
- package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +379 -0
- package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +337 -0
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +219 -214
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
- package/.framework/src/pages/auth/AuthConfirmPage.tsx +135 -65
- package/.framework/src/pages/auth/ForgotPasswordPage.tsx +39 -31
- package/.framework/src/pages/auth/LoginPage.tsx +38 -32
- package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -28
- package/.framework/src/pages/auth/RegisterPage.tsx +429 -155
- package/.framework/src/pages/spine-framework/APIPage.tsx +33 -30
- package/.framework/src/pages/spine-framework/CLIPage.tsx +32 -30
- package/.framework/src/types/auth.ts +101 -93
- package/.framework/src/types/types.ts +283 -262
- package/.framework/templates/project.json +87 -0
- package/.framework/templates/spine.config.neutral.json +7 -0
- package/.framework/tests/api/api-surface.test.ts +381 -0
- package/.framework/tests/fixtures/seed.ts +427 -0
- package/.framework/tests/fixtures/teardown.ts +228 -0
- package/.framework/tests/reporter.ts +351 -0
- package/.framework/tests/setup.ts +135 -0
- package/.framework/tests/ui/ui-sweep.ts +278 -0
- package/.framework/tests/unit/admin-data-logger.test.ts +310 -0
- package/.framework/tests/unit/agent-runner.test.ts +2389 -0
- package/.framework/tests/unit/ai-interactions.test.ts +81 -0
- package/.framework/tests/unit/app-manifest.test.ts +359 -0
- package/.framework/tests/unit/assembly-scripts.test.ts +172 -0
- package/.framework/tests/unit/cil-determinism.test.ts +85 -0
- package/.framework/tests/unit/core-isolation.test.ts +153 -0
- package/.framework/tests/unit/funnel-signals.test.ts +135 -0
- package/.framework/tests/unit/install-app.test.ts +1759 -0
- package/.framework/tests/unit/invites-security.test.ts +572 -0
- package/.framework/tests/unit/kb-ingest-lease.test.ts +287 -0
- package/.framework/tests/unit/kb-search.test.ts +119 -0
- package/.framework/tests/unit/migrate.test.ts +509 -0
- package/.framework/tests/unit/notify.test.ts +136 -0
- package/.framework/tests/unit/permissions.test.ts +269 -0
- package/.framework/tests/unit/pipeline-runner.test.ts +755 -0
- package/.framework/tests/unit/principal-cache.test.ts +138 -0
- package/.framework/tests/unit/retrieval-golden.test.ts +520 -0
- package/.framework/tests/unit/runtime-isolation.test.ts +642 -0
- package/.framework/tests/unit/schema-utils.test.ts +225 -0
- package/.framework/tests/unit/trigger-engine.test.ts +513 -0
- package/.framework/tests/unit/validate-app.test.ts +527 -0
- package/README.md +34 -3
- package/bin/spine-framework.cjs +1 -0
- package/config/tailwind.config.cjs +7 -0
- package/config/tsconfig.functions.json +42 -0
- package/config/tsconfig.json +37 -9
- package/config/vite.config.ts +31 -2
- package/netlify.toml +31 -3
- package/package.json +46 -29
- package/scripts/assemble-frontend.sh +127 -44
- package/scripts/assemble-functions.sh +127 -29
- package/scripts/boundary-check.sh +6 -2
- package/scripts/build-manifest.sh +24 -68
- package/scripts/checksum-manifest.mts +345 -0
- package/scripts/dev-clean.sh +86 -0
- package/scripts/dev-netlify.sh +49 -0
- package/scripts/netlify-dev-wrapper.sh +2 -0
- package/scripts/verify-install.ts +358 -0
- package/scripts/verify-integrity.sh +21 -57
- package/scripts/verify-manifest.mts +305 -0
- package/templates/project/gitignore +45 -0
- package/{config → templates/project}/package-lock.json +22335 -9366
- package/vitest.config.ts +46 -0
- package/.framework/public/spine.config.json +0 -91
- package/config/deno.lock +0 -108
- package/config/tsconfig.node.tsbuildinfo +0 -1
- package/config/tsconfig.tsbuildinfo +0 -1
- package/config/vite.config.d.ts +0 -2
- package/custom/.devin/AGENT.md +0 -357
- package/custom/.devin/skills/install-app/SKILL.md +0 -39
- package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +0 -39
- package/custom/.devin/skills/spine-workbench-idea/SKILL.md +0 -36
- package/custom/.devin/skills/spine-workbench-implement/SKILL.md +0 -46
- package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +0 -28
- package/custom/.devin/skills/spine-workbench-plan/SKILL.md +0 -38
- package/custom/.devin/workflows/app-install.yaml +0 -83
- package/custom/README.md +0 -79
- package/docs/README.md +0 -15
- package/scripts/app-install-cli.ts +0 -286
- package/scripts/check-core-integrity.sh +0 -82
- package/scripts/ingest-chunks.cjs +0 -202
- package/scripts/kb-chunk-parser.cjs +0 -312
- package/scripts/kb-chunk-parser.ts +0 -330
- package/scripts/kb-ingest-docs.ts +0 -203
- package/scripts/load-test-app-install.ts +0 -484
- package/scripts/test-login.js +0 -33
- package/spine.config.json +0 -91
|
@@ -1,70 +1,119 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
// CIL[
|
|
8
|
-
// CIL[DOC-
|
|
9
|
-
// CIL[DOC-
|
|
10
|
-
// 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/RolesPage.tsx\",\".framework/src/components/ui/dialog.tsx\",\"\\\"]"]
|
|
11
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="loaded_modules" errors="none" side_effects="none"]
|
|
12
|
-
// CIL[DOC-MICRO logic_summary="Imports Commander, child process, path utilities and defines TestSuite type" notable_decisions="[]"]
|
|
13
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
14
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
15
|
-
// CIL[DOC-AUDIENCE audience="developer"]
|
|
16
|
-
// 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/RolesPage.tsx, .framework/src/components/ui/dialog.tsx, \."]
|
|
17
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
18
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
19
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
20
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
21
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
1
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/test.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/cli/commands/test.ts"]
|
|
2
|
+
// CIL[DOC-MACRO purpose="Module-level setup and shared imports for the CLI test command"]
|
|
3
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Provide ESM path helpers, type definitions, and runner configuration used by test command functions"]
|
|
4
|
+
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files=".framework/cli/commands/test.ts"]
|
|
5
|
+
// CIL[DOC-CONTRACT inputs="" outputs="" errors="" side_effects=""]
|
|
6
|
+
// CIL[DOC-MICRO logic_summary="Imports Commander, child_process, and path helpers; defines constants and types for test execution" notable_decisions="ESM-compatible __filename and __dirname resolution"]
|
|
7
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
8
|
+
// CIL[DOC-STABILITY stable]
|
|
9
|
+
// CIL[DOC-AUDIENCE audience="cli developer, maintainer"]
|
|
22
10
|
import type { Command } from 'commander'
|
|
23
11
|
import { spawn } from 'child_process'
|
|
24
12
|
import { resolve, dirname } from 'path'
|
|
25
13
|
import { fileURLToPath } from 'url'
|
|
26
|
-
|
|
14
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Module-level setup and shared imports for the CLI test command'; No verified external callers; imports: none"]
|
|
15
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
16
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
17
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
18
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
19
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
20
|
+
// CIL[END stable_id="~/.framework/cli/commands/test.ts:module_header:module_header"]
|
|
21
|
+
|
|
22
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/test.ts:__filename:constant" type="constant" identity="__filename" parent="~/.framework/cli/commands/test.ts"]
|
|
23
|
+
// CIL[DOC-MACRO purpose="Compute the absolute file path for this ESM module"]
|
|
24
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Resolve the current modules __filename equivalent for path calculations"]
|
|
25
|
+
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files=".framework/cli/commands/test.ts"]
|
|
26
|
+
// CIL[DOC-CONTRACT inputs="import.meta.url" outputs="string absolute file path" errors="none" side_effects="none"]
|
|
27
|
+
// CIL[DOC-MICRO logic_summary="Converts the ESM import.meta.url to a file URL path using fileURLToPath" notable_decisions="Polyfills CommonJS __filename in an ESM module"]
|
|
28
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
29
|
+
// CIL[DOC-STABILITY stable]
|
|
27
30
|
const __filename = fileURLToPath(import.meta.url)
|
|
31
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Compute the absolute file path for this ESM module'; No verified external callers; imports: none"]
|
|
32
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
33
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
34
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
35
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
36
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
37
|
+
// CIL[END stable_id="~/.framework/cli/commands/test.ts:__filename:constant"]
|
|
38
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/test.ts:__dirname:constant" type="constant" identity="__dirname" parent="~/.framework/cli/commands/test.ts"]
|
|
39
|
+
// CIL[DOC-MACRO purpose="Compute the directory path of this ESM module"]
|
|
40
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Resolve the current modules __dirname equivalent for project-root lookup"]
|
|
41
|
+
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files=".framework/cli/commands/test.ts"]
|
|
42
|
+
// CIL[DOC-CONTRACT inputs="__filename" outputs="string directory path" errors="none" side_effects="none"]
|
|
43
|
+
// CIL[DOC-MICRO logic_summary="Uses path.dirname to derive the directory from the ESM __filename" notable_decisions="Polyfills CommonJS __dirname in an ESM module"]
|
|
44
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
45
|
+
// CIL[DOC-STABILITY stable]
|
|
28
46
|
const __dirname = dirname(__filename)
|
|
47
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Compute the directory path of this ESM module'; No verified external callers; imports: none"]
|
|
48
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
49
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
50
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
51
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
52
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
53
|
+
// CIL[END stable_id="~/.framework/cli/commands/test.ts:__dirname:constant"]
|
|
54
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/test.ts:PROJECT_ROOT:constant" type="constant" identity="PROJECT_ROOT" parent="~/.framework/cli/commands/test.ts"]
|
|
55
|
+
// CIL[DOC-MACRO purpose="Resolve the absolute project root from the CLI command location"]
|
|
56
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Provide the root directory used as working directory for test runners"]
|
|
57
|
+
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files=".framework/cli/commands/test.ts"]
|
|
58
|
+
// CIL[DOC-CONTRACT inputs="__dirname" outputs="string project root path" errors="none" side_effects="none"]
|
|
59
|
+
// CIL[DOC-MICRO logic_summary="Resolves three parent directories up from .framework/cli/commands" notable_decisions="Hardcoded relative traversal matches the framework path layout"]
|
|
60
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
61
|
+
// CIL[DOC-STABILITY stable]
|
|
29
62
|
const PROJECT_ROOT = resolve(__dirname, '../../../')
|
|
30
|
-
|
|
63
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Resolve the absolute project root from the CLI command location'; No verified external callers; imports: none"]
|
|
64
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
65
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
66
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
67
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
68
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
69
|
+
// CIL[END stable_id="~/.framework/cli/commands/test.ts:PROJECT_ROOT:constant"]
|
|
70
|
+
|
|
71
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/test.ts:TestSuite:type" type="type" identity="TestSuite" parent="~/.framework/cli/commands/test.ts"]
|
|
72
|
+
// CIL[DOC-MACRO purpose="Define the union of supported test suite identifiers"]
|
|
73
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Type-check the suite argument accepted by the test command"]
|
|
74
|
+
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files=".framework/cli/commands/test.ts"]
|
|
75
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="TestSuite union type" errors="none" side_effects="none"]
|
|
76
|
+
// CIL[DOC-MICRO logic_summary="Exports a string literal union of unit, integration, api, ui, and all" notable_decisions="Keeps suite names as a single source of truth for CLI validation"]
|
|
77
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
78
|
+
// CIL[DOC-STABILITY stable]
|
|
31
79
|
type TestSuite = 'unit' | 'integration' | 'api' | 'ui' | 'all'
|
|
32
|
-
// CIL[
|
|
33
|
-
// CIL[
|
|
34
|
-
// CIL[DOC-
|
|
35
|
-
// CIL[DOC-
|
|
36
|
-
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/functions/_shared/schema-utils.ts\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\"\\\"]"]
|
|
37
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="suite_config" errors="none" side_effects="none"]
|
|
38
|
-
// CIL[DOC-MICRO logic_summary="Maps test suite names to file patterns and test runners" notable_decisions="[]"]
|
|
39
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
40
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
41
|
-
// CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/IntegrationsPage.tsx, .framework/functions/_shared/principal.ts, .framework/functions/_shared/schema-utils.ts, custom/apps/cortex/functions/custom_cil-embeddings.ts, \."]
|
|
42
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
43
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
44
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
80
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Define the union of supported test suite identifiers'; No verified external callers; imports: none"]
|
|
81
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
82
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
83
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
45
84
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
46
85
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
86
|
+
// CIL[END stable_id="~/.framework/cli/commands/test.ts:TestSuite:type"]
|
|
87
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/test.ts:SUITES:constant" type="constant" identity="SUITES" parent="~/.framework/cli/commands/test.ts"]
|
|
88
|
+
// CIL[DOC-MACRO purpose="Map suite names to their test directory patterns and runner executables"]
|
|
89
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Centralize suite configuration consumed by registerTestCommands and runner functions"]
|
|
90
|
+
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files=".framework/cli/commands/test.ts"]
|
|
91
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="Record<string, {pattern: string, runner: vitest|playwright|node}>" errors="none" side_effects="none"]
|
|
92
|
+
// CIL[DOC-MICRO logic_summary="Defines a lookup of suite patterns under v2-core/tests and the runner to invoke" notable_decisions="Defaults all non-ui suites to vitest; ui suite uses playwright"]
|
|
93
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
94
|
+
// CIL[DOC-STABILITY stable]
|
|
47
95
|
const SUITES: Record<string, { pattern: string; runner: 'vitest' | 'playwright' | 'node' }> = {
|
|
48
96
|
unit: { pattern: 'v2-core/tests/unit', runner: 'vitest' },
|
|
49
97
|
integration: { pattern: 'v2-core/tests/integration', runner: 'vitest' },
|
|
50
98
|
api: { pattern: 'v2-core/tests/api', runner: 'vitest' },
|
|
51
99
|
ui: { pattern: 'v2-core/tests/ui', runner: 'playwright' }
|
|
52
100
|
}
|
|
53
|
-
// CIL[
|
|
54
|
-
// CIL[
|
|
55
|
-
// CIL[DOC-
|
|
56
|
-
// CIL[DOC-
|
|
57
|
-
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[\".framework/functions/_shared/schema-utils.ts\",\".framework/src/components/ui/dialog.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/src/components/ui/table-primitives.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"\\\"]"]
|
|
58
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="test_execution" errors="test_errors" side_effects="process_exit"]
|
|
59
|
-
// CIL[DOC-MICRO logic_summary="Registers test command with options for suite, watch, reporter, and JSON output" notable_decisions="[]"]
|
|
60
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="complex_dependencies"]
|
|
61
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
62
|
-
// CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, .framework/src/components/ui/dialog.tsx, .framework/functions/_shared/principal.ts, .framework/src/components/ui/table-primitives.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
|
|
63
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
64
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
65
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
101
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Map suite names to their test directory patterns and runner executables'; No verified external callers; imports: none"]
|
|
102
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
103
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
104
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
66
105
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
67
106
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
107
|
+
// CIL[END stable_id="~/.framework/cli/commands/test.ts:SUITES:constant"]
|
|
108
|
+
|
|
109
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/test.ts:registerTestCommands:function" type="function" identity="registerTestCommands" parent="~/.framework/cli/commands/test.ts"]
|
|
110
|
+
// CIL[DOC-MACRO purpose="Register the test subcommand with the Commander CLI program"]
|
|
111
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Wire the test command, validate the suite argument, run suites, and print a summary"]
|
|
112
|
+
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files=".framework/cli/commands/test.ts"]
|
|
113
|
+
// CIL[DOC-CONTRACT inputs="program: Command" outputs="void" errors="console.error and process.exit(1) on unknown suite" side_effects="registers test subcommand, logs to console, calls process.exit with 0 or 1"]
|
|
114
|
+
// CIL[DOC-MICRO logic_summary="Parses suite and options, iterates over suites, dispatches runner, collects results, and prints JSON or text summary" notable_decisions="Unknown suites cause immediate stderr and exit; all runs all known suites in order"]
|
|
115
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
116
|
+
// CIL[DOC-STABILITY stable]
|
|
68
117
|
export function registerTestCommands(program: Command) {
|
|
69
118
|
const testCmd = program
|
|
70
119
|
.command('test [suite]')
|
|
@@ -154,21 +203,22 @@ export function registerTestCommands(program: Command) {
|
|
|
154
203
|
process.exit(totalFailed > 0 ? 1 : 0)
|
|
155
204
|
})
|
|
156
205
|
}
|
|
157
|
-
// CIL[
|
|
158
|
-
// CIL[
|
|
159
|
-
// CIL[DOC-
|
|
160
|
-
// CIL[DOC-
|
|
161
|
-
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[\".framework/migrations/015_simplify_apps_table.sql\",\"\\\"]"]
|
|
162
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="exit_code" errors="vitest_errors" side_effects="process_spawn"]
|
|
163
|
-
// CIL[DOC-MICRO logic_summary="Configures and runs Vitest with pattern, config, watch mode, and reporter options" notable_decisions="[]"]
|
|
164
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="external_symbols_unknown"]
|
|
165
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
166
|
-
// CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: .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."]
|
|
206
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Register the test subcommand with the Commander CLI program'; No verified external callers; imports: none"]
|
|
207
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
208
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
209
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
170
210
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
171
211
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
212
|
+
// CIL[END stable_id="~/.framework/cli/commands/test.ts:registerTestCommands:function"]
|
|
213
|
+
|
|
214
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/test.ts:runVitest:function" type="function" identity="runVitest" parent="~/.framework/cli/commands/test.ts"]
|
|
215
|
+
// CIL[DOC-MACRO purpose="Assemble and execute a Vitest test run for a given suite"]
|
|
216
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Build Vitest CLI arguments and return the exit code"]
|
|
217
|
+
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files=".framework/cli/commands/test.ts"]
|
|
218
|
+
// CIL[DOC-CONTRACT inputs="suite: string, opts: any" outputs="number (exit code)" errors="rejects if npx vitest fails to spawn or exits with an error event" side_effects="spawns npx vitest child process with inherited stdio"]
|
|
219
|
+
// CIL[DOC-MICRO logic_summary="Constructs run/watch and reporter arguments, then delegates to runCommand" notable_decisions="Adds a custom reporter from v2-core/tests/reporter.ts when default is selected"]
|
|
220
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
221
|
+
// CIL[DOC-STABILITY stable]
|
|
172
222
|
async function runVitest(suite: string, opts: any): Promise<number> {
|
|
173
223
|
const config = SUITES[suite]
|
|
174
224
|
const args = [
|
|
@@ -190,21 +240,22 @@ async function runVitest(suite: string, opts: any): Promise<number> {
|
|
|
190
240
|
|
|
191
241
|
return runCommand('npx', ['vitest', ...args], PROJECT_ROOT)
|
|
192
242
|
}
|
|
193
|
-
// CIL[
|
|
194
|
-
// CIL[
|
|
195
|
-
// CIL[DOC-
|
|
196
|
-
// CIL[DOC-
|
|
197
|
-
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[\".framework/migrations/015_simplify_apps_table.sql\",\"\\\"]"]
|
|
198
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="exit_code" errors="playwright_errors" side_effects="process_spawn"]
|
|
199
|
-
// CIL[DOC-MICRO logic_summary="Configures and runs Playwright with pattern and JSON reporter option" notable_decisions="[]"]
|
|
200
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="external_symbols_unknown"]
|
|
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, \."]
|
|
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."]
|
|
243
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Assemble and execute a Vitest test run for a given suite'; No verified external callers; imports: none"]
|
|
244
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
245
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
246
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
206
247
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
207
248
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
249
|
+
// CIL[END stable_id="~/.framework/cli/commands/test.ts:runVitest:function"]
|
|
250
|
+
|
|
251
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/test.ts:runPlaywright:function" type="function" identity="runPlaywright" parent="~/.framework/cli/commands/test.ts"]
|
|
252
|
+
// CIL[DOC-MACRO purpose="Assemble and execute a Playwright test run for the UI suite"]
|
|
253
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Build Playwright CLI arguments and return the exit code"]
|
|
254
|
+
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files=".framework/cli/commands/test.ts"]
|
|
255
|
+
// CIL[DOC-CONTRACT inputs="suite: string, opts: any" outputs="number (exit code)" errors="rejects if npx playwright fails to spawn or exits with an error event" side_effects="spawns npx playwright child process with inherited stdio; logs dev server requirement"]
|
|
256
|
+
// CIL[DOC-MICRO logic_summary="Constructs playwright test arguments and optionally enables JSON reporter" notable_decisions="Assumes a dev server is running on localhost:8888"]
|
|
257
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
258
|
+
// CIL[DOC-STABILITY stable]
|
|
208
259
|
async function runPlaywright(suite: string, opts: any): Promise<number> {
|
|
209
260
|
console.log(' (Playwright tests require dev server on localhost:8888)')
|
|
210
261
|
|
|
@@ -216,40 +267,42 @@ async function runPlaywright(suite: string, opts: any): Promise<number> {
|
|
|
216
267
|
|
|
217
268
|
return runCommand('npx', args, PROJECT_ROOT)
|
|
218
269
|
}
|
|
219
|
-
// CIL[
|
|
220
|
-
// CIL[
|
|
221
|
-
// CIL[DOC-
|
|
222
|
-
// CIL[DOC-
|
|
223
|
-
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[]"]
|
|
224
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="exit_code" errors="node_errors" side_effects="process_spawn"]
|
|
225
|
-
// CIL[DOC-MICRO logic_summary="Runs test files directly with Node.js using suite pattern" notable_decisions="[]"]
|
|
226
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="external_symbols_unknown"]
|
|
227
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
228
|
-
// CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
229
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
230
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
231
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
270
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Assemble and execute a Playwright test run for the UI suite'; No verified external callers; imports: none"]
|
|
271
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
272
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
273
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
232
274
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
233
275
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
276
|
+
// CIL[END stable_id="~/.framework/cli/commands/test.ts:runPlaywright:function"]
|
|
277
|
+
|
|
278
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/test.ts:runNode:function" type="function" identity="runNode" parent="~/.framework/cli/commands/test.ts"]
|
|
279
|
+
// CIL[DOC-MACRO purpose="Execute a test file directly with Node.js"]
|
|
280
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Run a suites test directory as a Node.js module and return the exit code"]
|
|
281
|
+
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files=".framework/cli/commands/test.ts"]
|
|
282
|
+
// CIL[DOC-CONTRACT inputs="suite: string, opts: any" outputs="number (exit code)" errors="rejects if node process fails to spawn or emits an error event" side_effects="spawns node child process with inherited stdio"]
|
|
283
|
+
// CIL[DOC-MICRO logic_summary="Looks up the suite pattern and spawns node with it as the entry point" notable_decisions="Relies on Node.js for simple or one-off test scripts"]
|
|
284
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
285
|
+
// CIL[DOC-STABILITY stable]
|
|
234
286
|
async function runNode(suite: string, opts: any): Promise<number> {
|
|
235
287
|
const args = [SUITES[suite].pattern]
|
|
236
288
|
return runCommand('node', args, PROJECT_ROOT)
|
|
237
289
|
}
|
|
238
|
-
// CIL[
|
|
239
|
-
// CIL[
|
|
240
|
-
// CIL[DOC-
|
|
241
|
-
// CIL[DOC-
|
|
242
|
-
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files="[]"]
|
|
243
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="exit_code" errors="spawn_errors" side_effects="process_spawn"]
|
|
244
|
-
// CIL[DOC-MICRO logic_summary="Wraps child_process.spawn in Promise with proper error handling" notable_decisions="[]"]
|
|
245
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
246
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
247
|
-
// CIL[DOC-VECTOR type="context" content="Layer: commands. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
248
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
249
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
250
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
290
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Execute a test file directly with Node.js'; No verified external callers; imports: none"]
|
|
291
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
292
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
293
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
251
294
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
252
295
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
296
|
+
// CIL[END stable_id="~/.framework/cli/commands/test.ts:runNode:function"]
|
|
297
|
+
|
|
298
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/test.ts:runCommand:function" type="function" identity="runCommand" parent="~/.framework/cli/commands/test.ts"]
|
|
299
|
+
// CIL[DOC-MACRO purpose="Spawn a shell command and return its exit code"]
|
|
300
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Abstract child_process spawn for test runners"]
|
|
301
|
+
// CIL[DOC-CONTEXT module="cli" layer="commands" related_files=".framework/cli/commands/test.ts"]
|
|
302
|
+
// CIL[DOC-CONTRACT inputs="command: string, args: string[], cwd: string" outputs="number (exit code)" errors="rejects on spawn error" side_effects="spawns a child process with inherited stdio and shell mode"]
|
|
303
|
+
// CIL[DOC-MICRO logic_summary="Returns a promise that resolves when the child process exits and rejects on spawn errors" notable_decisions="Uses shell: true and stdio: inherit to preserve terminal output"]
|
|
304
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
305
|
+
// CIL[DOC-STABILITY stable]
|
|
253
306
|
function runCommand(command: string, args: string[], cwd: string): Promise<number> {
|
|
254
307
|
return new Promise((resolve, reject) => {
|
|
255
308
|
const proc = spawn(command, args, {
|
|
@@ -268,4 +321,10 @@ function runCommand(command: string, args: string[], cwd: string): Promise<numbe
|
|
|
268
321
|
})
|
|
269
322
|
})
|
|
270
323
|
}
|
|
271
|
-
// CIL[
|
|
324
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Spawn a shell command and return its exit code'; No verified external callers; imports: none"]
|
|
325
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
326
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
327
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
328
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
329
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
330
|
+
// CIL[END stable_id="~/.framework/cli/commands/test.ts:runCommand:function"]
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/upgrade.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/cli/commands/upgrade.ts"]
|
|
2
|
+
// CIL[DOC-MACRO purpose="Sync an installed project's framework-owned files to the spine-framework version in node_modules"]
|
|
3
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Verify the current tree against the frozen .spine-manifest.json, then overwrite .framework/config/scripts/bin from the installed package, merge framework deps+scripts into package.json, re-render netlify.toml preserving app-owned custom_* sections, and regenerate the manifest at the new framework_version"]
|
|
4
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/lib/project-files.ts,.framework/templates/project.json,.framework/cli/commands/init.ts"]
|
|
5
|
+
// CIL[DOC-CONTRACT inputs="[--dry-run] [--force]; runs in the project root; new version comes from node_modules/spine-framework" outputs="synced tree + regenerated manifest + change report" errors="exit 1 when no manifest, package absent/older, or protected files were locally modified (without --force)" side_effects="writes framework-owned paths only; --dry-run writes nothing"]
|
|
6
|
+
// CIL[DOC-MICRO logic_summary="The executing command is always the NEW package's copy — npx spine-framework upgrade resolves node_modules. Deletions are limited to .framework/ entries tracked in the old manifest but absent upstream; config/scripts files dropped upstream are warned, not deleted. custom/, spine.config.json, .env, .spine/, and netlify.toml custom_* sections are never touched" notable_decisions="integrity abort is the safety rail — a sealed .framework/ tree means overwrite-on-upgrade loses nothing the user owned"]
|
|
7
|
+
// CIL[DOC-CONFIDENCE pass="first" score="0.85" flags="none"]
|
|
8
|
+
// CIL[DOC-STABILITY stability="experimental"]
|
|
9
|
+
// CIL[DOC-NOTE type="design" content="Upgrade is file-sync, not git-aware; rollback = git. Migrations are reported, never run — `npx spine-framework migrate` applies them"]
|
|
10
|
+
// CIL[DOC-AUDIENCE audience="developer"]
|
|
11
|
+
|
|
12
|
+
import type { Command } from 'commander'
|
|
13
|
+
import { existsSync, readFileSync, writeFileSync, rmSync, lstatSync } from 'fs'
|
|
14
|
+
import { resolve, dirname, join } from 'path'
|
|
15
|
+
import { fileURLToPath } from 'url'
|
|
16
|
+
import { hashEntry } from '../../../scripts/checksum-manifest.mts'
|
|
17
|
+
import {
|
|
18
|
+
loadProjectProfile,
|
|
19
|
+
collectFrameworkFiles,
|
|
20
|
+
copyCollectedFiles,
|
|
21
|
+
renderNetlifyToml,
|
|
22
|
+
mergePackageJson,
|
|
23
|
+
writeFrozenManifest,
|
|
24
|
+
cmpSemver,
|
|
25
|
+
} from '../lib/project-files.ts'
|
|
26
|
+
// CIL[END stable_id="~/.framework/cli/commands/upgrade.ts:module_header:module_header"]
|
|
27
|
+
|
|
28
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/upgrade.ts:paths:block" type="block" identity="paths" parent="~/.framework/cli/commands/upgrade.ts"]
|
|
29
|
+
// CIL[DOC-MACRO purpose="Path constants — PACKAGE_ROOT is the new version's source of truth; PROJECT_ROOT is the installed project being upgraded"]
|
|
30
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files="package.json,.spine-manifest.json"]
|
|
31
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="resolved path constants" errors="none" side_effects="none"]
|
|
32
|
+
// CIL[DOC-MICRO logic_summary="PACKAGE_ROOT resolves inside node_modules/spine-framework — the executing command is always the NEW package's copy; PROJECT_ROOT is process.cwd()" notable_decisions="new code upgrades old files, never the reverse"]
|
|
33
|
+
// CIL[DOC-CONFIDENCE pass="first" score="0.95" flags="none"]
|
|
34
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
35
|
+
// CIL[DOC-AUDIENCE audience="developer"]
|
|
36
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
37
|
+
const __dirname = dirname(__filename)
|
|
38
|
+
|
|
39
|
+
const PACKAGE_ROOT = resolve(__dirname, '../../../')
|
|
40
|
+
const PROJECT_ROOT = process.cwd()
|
|
41
|
+
|
|
42
|
+
const MANIFEST_PATH = join(PROJECT_ROOT, '.spine-manifest.json')
|
|
43
|
+
// CIL[END stable_id="~/.framework/cli/commands/upgrade.ts:paths:block"]
|
|
44
|
+
|
|
45
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/upgrade.ts:registerUpgradeCommands:function" type="function" identity="registerUpgradeCommands" parent="~/.framework/cli/commands/upgrade.ts"]
|
|
46
|
+
// CIL[DOC-MACRO purpose="Register `upgrade [--dry-run] [--force]` — delegates to runUpgrade with a fatal-error wrapper"]
|
|
47
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/index.ts"]
|
|
48
|
+
// CIL[DOC-CONTRACT inputs="program: Command" outputs="void" errors="catches runUpgrade errors → exit 1 (stack behind SPINE_CLI_DEBUG)" side_effects="mutates Commander program; may write project files via runUpgrade"]
|
|
49
|
+
// CIL[DOC-MICRO logic_summary="Thin Commander wiring — all logic lives in runUpgrade" notable_decisions="error wrapper prints message + exits; stack only under SPINE_CLI_DEBUG"]
|
|
50
|
+
// CIL[DOC-CONFIDENCE pass="first" score="0.95" flags="none"]
|
|
51
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
52
|
+
// CIL[DOC-AUDIENCE audience="developer"]
|
|
53
|
+
export function registerUpgradeCommands(program: Command) {
|
|
54
|
+
program
|
|
55
|
+
.command('upgrade')
|
|
56
|
+
.description('Sync this project to the spine-framework version installed in node_modules')
|
|
57
|
+
.option('--dry-run', 'Report the changes without writing anything', false)
|
|
58
|
+
.option('--force', 'Overwrite locally modified framework files', false)
|
|
59
|
+
.action(async (opts: { dryRun: boolean; force: boolean }) => {
|
|
60
|
+
try {
|
|
61
|
+
runUpgrade(opts)
|
|
62
|
+
} catch (err: any) {
|
|
63
|
+
console.error(`\n❌ Upgrade failed: ${err.message}`)
|
|
64
|
+
if (process.env.SPINE_CLI_DEBUG) console.error(err.stack)
|
|
65
|
+
process.exit(1)
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
// CIL[END stable_id="~/.framework/cli/commands/upgrade.ts:registerUpgradeCommands:function"]
|
|
70
|
+
|
|
71
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/upgrade.ts:runUpgrade:function" type="function" identity="runUpgrade" parent="~/.framework/cli/commands/upgrade.ts"]
|
|
72
|
+
// CIL[DOC-MACRO purpose="Sync installed project's framework-owned files to the package version — integrity check, file sync, package.json merge, netlify.toml render, manifest regen"]
|
|
73
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".spine-manifest.json,.framework/cli/lib/project-files.ts"]
|
|
74
|
+
// CIL[DOC-CONTRACT inputs="abs: string, opts: { dryRun: boolean; force: boolean }" outputs="change report to stdout; synced tree on disk" errors="exit 1 on missing manifest, missing/older package, or locally modified protected files without --force" side_effects="writes framework-owned paths only; --dry-run writes nothing; netlify.toml custom_* sections preserved verbatim"]
|
|
75
|
+
// CIL[DOC-MICRO logic_summary="Three-way compare (disk vs old manifest vs package payload): integrity abort on local mods → copy added/changed files → delete only .framework entries dropped upstream → merge package.json deps/scripts/pin → re-render netlify.toml → regenerate frozen manifest → list new migrations without running them" notable_decisions="non-.framework files dropped upstream are warned and retained; identical rendered TOML writes no .bak"]
|
|
76
|
+
// CIL[DOC-CONFIDENCE pass="first" score="0.85" flags="none"]
|
|
77
|
+
// CIL[DOC-STABILITY stability="experimental"]
|
|
78
|
+
// CIL[DOC-AUDIENCE audience="developer"]
|
|
79
|
+
function diskHash(abs: string): string {
|
|
80
|
+
const lst = lstatSync(abs)
|
|
81
|
+
return hashEntry({ rel: '', abs, symlink: lst.isSymbolicLink() })
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function runUpgrade(opts: { dryRun: boolean; force: boolean }): void {
|
|
85
|
+
console.log('\nSpine Framework upgrade\n')
|
|
86
|
+
|
|
87
|
+
// 1. Preconditions
|
|
88
|
+
const srcPkgEarly = safeJson(join(PACKAGE_ROOT, 'package.json'))
|
|
89
|
+
if (srcPkgEarly?.name !== 'spine-framework') {
|
|
90
|
+
throw new Error(
|
|
91
|
+
'This upgrade command is running from the vendored project copy, which cannot update itself.\n' +
|
|
92
|
+
' Run the installed package instead: npx spine-framework upgrade (or npm run upgrade)',
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
if (!existsSync(MANIFEST_PATH)) {
|
|
96
|
+
throw new Error('No .spine-manifest.json — not a Spine-managed project (use `spine-framework init`)')
|
|
97
|
+
}
|
|
98
|
+
const oldManifest = JSON.parse(readFileSync(MANIFEST_PATH, 'utf8'))
|
|
99
|
+
const oldVersion: string | null = oldManifest.framework_version ?? null
|
|
100
|
+
const newVersion = getPackageVersion()
|
|
101
|
+
const prevFrameworkDeps: string[] = Array.isArray(oldManifest.framework_dependencies)
|
|
102
|
+
? oldManifest.framework_dependencies
|
|
103
|
+
: []
|
|
104
|
+
|
|
105
|
+
if (!oldVersion) {
|
|
106
|
+
console.log(' ⚠ Manifest has no framework_version — proceeding carefully')
|
|
107
|
+
} else if (cmpSemver(newVersion, oldVersion) < 0) {
|
|
108
|
+
throw new Error(`Installed package (v${newVersion}) is older than this project (v${oldVersion}). Install a newer spine-framework first.`)
|
|
109
|
+
} else if (cmpSemver(newVersion, oldVersion) === 0) {
|
|
110
|
+
console.log(` ℹ Project already at spine-framework ${oldVersion}; syncing anyway`)
|
|
111
|
+
} else {
|
|
112
|
+
console.log(` ${oldVersion} → ${newVersion}`)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const profile = loadProjectProfile(PACKAGE_ROOT)
|
|
116
|
+
const srcPkg = JSON.parse(readFileSync(join(PACKAGE_ROOT, 'package.json'), 'utf8'))
|
|
117
|
+
|
|
118
|
+
// 2. Integrity — abort on locally modified or missing framework files
|
|
119
|
+
const oldFiles: Record<string, string> = oldManifest.files ?? {}
|
|
120
|
+
const modified: string[] = []
|
|
121
|
+
const missing: string[] = []
|
|
122
|
+
for (const [rel, hash] of Object.entries(oldFiles)) {
|
|
123
|
+
const abs = join(PROJECT_ROOT, rel)
|
|
124
|
+
if (!existsSync(abs)) { missing.push(rel); continue }
|
|
125
|
+
if (diskHash(abs) !== hash) modified.push(rel)
|
|
126
|
+
}
|
|
127
|
+
if ((modified.length > 0 || missing.length > 0) && !opts.force) {
|
|
128
|
+
console.error('\n❌ Framework files were modified locally — upgrade would overwrite them:')
|
|
129
|
+
for (const f of modified) console.error(` modified: ${f}`)
|
|
130
|
+
for (const f of missing) console.error(` missing: ${f}`)
|
|
131
|
+
console.error('\n Revert the changes, or rerun with --force to overwrite.')
|
|
132
|
+
process.exit(1)
|
|
133
|
+
}
|
|
134
|
+
if (opts.force && (modified.length || missing.length)) {
|
|
135
|
+
console.log(` ⚠ --force: overwriting ${modified.length} modified, restoring ${missing.length} missing files`)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// 3. Compute the new file set and the change report
|
|
139
|
+
const files = collectFrameworkFiles(PACKAGE_ROOT, profile)
|
|
140
|
+
const newRels = new Set(files.map((f) => f.rel))
|
|
141
|
+
const added: string[] = []
|
|
142
|
+
const changed: string[] = []
|
|
143
|
+
let kept = 0
|
|
144
|
+
for (const f of files) {
|
|
145
|
+
const oldHash = oldFiles[f.rel]
|
|
146
|
+
const newHash = hashEntry(f)
|
|
147
|
+
if (oldHash) {
|
|
148
|
+
if (newHash !== oldHash) changed.push(f.rel)
|
|
149
|
+
else kept++
|
|
150
|
+
} else {
|
|
151
|
+
// Not in the manifest (root config files aren't integrity-tracked).
|
|
152
|
+
// Compare against what's on disk so reruns don't report phantom adds.
|
|
153
|
+
const abs = join(PROJECT_ROOT, f.rel)
|
|
154
|
+
if (!existsSync(abs)) added.push(f.rel)
|
|
155
|
+
else if (diskHash(abs) !== newHash) changed.push(f.rel)
|
|
156
|
+
else kept++
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Deletions: only inside .framework/ (fully sealed). config/scripts entries
|
|
160
|
+
// dropped upstream are reported, not deleted — extras there are harmless.
|
|
161
|
+
const removed = Object.keys(oldFiles).filter((rel) => !newRels.has(rel) && rel.startsWith('.framework/'))
|
|
162
|
+
const staleOutside = Object.keys(oldFiles).filter((rel) => !newRels.has(rel) && !rel.startsWith('.framework/'))
|
|
163
|
+
|
|
164
|
+
// New framework migrations = files under .framework/migrations not in the old manifest
|
|
165
|
+
const newMigrations = files
|
|
166
|
+
.map((f) => f.rel)
|
|
167
|
+
.filter((rel) => rel.startsWith('.framework/migrations/') && rel.endsWith('.sql') && !(rel in oldFiles))
|
|
168
|
+
|
|
169
|
+
console.log(`\n ${added.length} added · ${changed.length} changed · ${removed.length} removed · ${kept} unchanged`)
|
|
170
|
+
if (opts.dryRun) {
|
|
171
|
+
for (const f of added) console.log(` + ${f}`)
|
|
172
|
+
for (const f of changed) console.log(` ~ ${f}`)
|
|
173
|
+
for (const f of removed) console.log(` - ${f}`)
|
|
174
|
+
for (const f of staleOutside) console.log(` ? ${f} (dropped upstream, left in place)`)
|
|
175
|
+
if (newMigrations.length > 0) {
|
|
176
|
+
console.log(`\n New migrations in this version (${newMigrations.length}):`)
|
|
177
|
+
for (const rel of newMigrations) console.log(` ${rel.split('/').pop()}`)
|
|
178
|
+
}
|
|
179
|
+
console.log('\n (dry run — nothing written)\n')
|
|
180
|
+
return
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// 4. Apply: copy new files, remove dropped .framework files
|
|
184
|
+
copyCollectedFiles(files, PROJECT_ROOT)
|
|
185
|
+
for (const rel of removed) rmSync(join(PROJECT_ROOT, rel), { force: true })
|
|
186
|
+
for (const rel of staleOutside) console.log(` ⚠ ${rel} is no longer shipped upstream — left in place`)
|
|
187
|
+
console.log(` ✓ framework files synced (${files.length})`)
|
|
188
|
+
|
|
189
|
+
// 5. package.json — framework scripts/deps, exact pin
|
|
190
|
+
const pkgPath = join(PROJECT_ROOT, 'package.json')
|
|
191
|
+
const existingPkg = existsSync(pkgPath) ? JSON.parse(readFileSync(pkgPath, 'utf8')) : {}
|
|
192
|
+
const merged = mergePackageJson({
|
|
193
|
+
existing: existingPkg,
|
|
194
|
+
name: existingPkg.name ?? 'spine-project',
|
|
195
|
+
scripts: profile.package_scripts,
|
|
196
|
+
newDependencies: srcPkg.dependencies ?? {},
|
|
197
|
+
newDevDependencies: srcPkg.devDependencies ?? {},
|
|
198
|
+
prevFrameworkDeps,
|
|
199
|
+
spineVersion: newVersion,
|
|
200
|
+
})
|
|
201
|
+
writeFileSync(pkgPath, merged.text)
|
|
202
|
+
console.log(' ✓ package.json updated (spine-framework pin + framework deps/scripts)')
|
|
203
|
+
|
|
204
|
+
// 6. netlify.toml — framework base replaced, app custom_* sections preserved
|
|
205
|
+
const netlifySrc = join(PACKAGE_ROOT, 'netlify.toml')
|
|
206
|
+
const netlifyDest = join(PROJECT_ROOT, 'netlify.toml')
|
|
207
|
+
if (existsSync(netlifySrc)) {
|
|
208
|
+
const existingToml = existsSync(netlifyDest) ? readFileSync(netlifyDest, 'utf8') : undefined
|
|
209
|
+
const nextToml = renderNetlifyToml(readFileSync(netlifySrc, 'utf8'), existingToml)
|
|
210
|
+
if (existingToml && existingToml !== nextToml) {
|
|
211
|
+
writeFileSync(`${netlifyDest}.bak`, existingToml)
|
|
212
|
+
console.log(' ✓ netlify.toml updated (backup at netlify.toml.bak; custom_* sections preserved)')
|
|
213
|
+
writeFileSync(netlifyDest, nextToml)
|
|
214
|
+
} else {
|
|
215
|
+
writeFileSync(netlifyDest, nextToml)
|
|
216
|
+
console.log(' ✓ netlify.toml written')
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// 7. Regenerate frozen manifest at the new version
|
|
221
|
+
const manifest = writeFrozenManifest({
|
|
222
|
+
projectRoot: PROJECT_ROOT,
|
|
223
|
+
frameworkVersion: newVersion,
|
|
224
|
+
frameworkDeps: merged.frameworkDeps,
|
|
225
|
+
})
|
|
226
|
+
console.log(` ✓ .spine-manifest.json regenerated (${manifest.fileCount} files)`)
|
|
227
|
+
|
|
228
|
+
if (newMigrations.length > 0) {
|
|
229
|
+
console.log(`\n New migrations in this version (${newMigrations.length}):`)
|
|
230
|
+
for (const rel of newMigrations) console.log(` ${rel.split('/').pop()}`)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
console.log('\nNext steps:')
|
|
234
|
+
console.log(' 1. npm install # resolve the new dependency set')
|
|
235
|
+
console.log(' 2. npm run verify # confirm frozen integrity')
|
|
236
|
+
console.log(' 3. npx spine-framework migrate # apply new migrations (if any)')
|
|
237
|
+
console.log(' 4. commit + deploy\n')
|
|
238
|
+
}
|
|
239
|
+
// CIL[END stable_id="~/.framework/cli/commands/upgrade.ts:runUpgrade:function"]
|
|
240
|
+
|
|
241
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/upgrade.ts:helpers:block" type="block" identity="helpers" parent="~/.framework/cli/commands/upgrade.ts"]
|
|
242
|
+
// CIL[DOC-MACRO purpose="safeJson + getPackageVersion helpers — package version read is tolerant of missing/malformed JSON"]
|
|
243
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files="package.json"]
|
|
244
|
+
// CIL[DOC-CONTRACT inputs="file: string" outputs="parsed JSON | null; version string" errors="safeJson returns null on missing/malformed input" side_effects="none"]
|
|
245
|
+
// CIL[DOC-MICRO logic_summary="Tolerant reads — a missing or corrupt JSON file degrades to null rather than throwing" notable_decisions="absence is data for upgrade decisions, not an exception"]
|
|
246
|
+
// CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"]
|
|
247
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
248
|
+
// CIL[DOC-AUDIENCE audience="developer"]
|
|
249
|
+
function safeJson(file: string): Record<string, any> | null {
|
|
250
|
+
try {
|
|
251
|
+
return JSON.parse(readFileSync(file, 'utf8'))
|
|
252
|
+
} catch {
|
|
253
|
+
return null
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function getPackageVersion(): string {
|
|
258
|
+
return safeJson(join(PACKAGE_ROOT, 'package.json'))?.version ?? '0.0.0'
|
|
259
|
+
}
|
|
260
|
+
// CIL[END stable_id="~/.framework/cli/commands/upgrade.ts:helpers:block"]
|