spine-framework 0.3.145 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +15 -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
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:module_header:module_header" type="module_header" identity="module_header" parent="none"]
|
|
2
|
+
// CIL[DOC-MACRO purpose="Pass 2 file/folder selection UI for CIL projects"]
|
|
3
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Let users visually select discovered files and folders for a CIL project"]
|
|
4
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/checkbox.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/lib/api.ts"]
|
|
5
|
+
// CIL[DOC-CONTRACT inputs="project_id from URL" outputs="Updated selected_paths for the project" errors="Project not found, selection save failed" side_effects="Calls /api/cil-ingest?action=select"]
|
|
6
|
+
// CIL[DOC-MICRO logic_summary="Fetch discovered files from the project file_statuses map, render a tri-state tree with checkboxes, and submit the selected file set." notable_decisions=["Folders recursively select/deselect all descendant files.","Status is inferred from project.data.file_statuses."]"]
|
|
7
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
8
|
+
// CIL[DOC-STABILITY stability="experimental"]
|
|
9
|
+
// CIL[DOC-AUDIENCE audience="developer"]
|
|
10
|
+
|
|
11
|
+
import { useEffect, useState, useCallback, useMemo } from 'react'
|
|
12
|
+
import { useParams, useNavigate } from 'react-router-dom'
|
|
13
|
+
import { apiFetch } from '@core/lib/api'
|
|
14
|
+
import { Card, CardContent, CardHeader, CardTitle } from '@core/components/ui/card'
|
|
15
|
+
import { Button } from '@core/components/ui/button'
|
|
16
|
+
import { Checkbox } from '@core/components/ui/checkbox'
|
|
17
|
+
import { Skeleton } from '@core/components/ui/skeleton'
|
|
18
|
+
import { ChevronRight, ChevronDown, Folder, FileCode2, Save } from 'lucide-react'
|
|
19
|
+
|
|
20
|
+
import { PageInstructions } from '../../../components/admin/PageInstructions'
|
|
21
|
+
|
|
22
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Pass 2 file/folder selection UI for CIL projects'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/card.tsx,.framework/src/components/ui/button.tsx"]
|
|
23
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
24
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
25
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
26
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
27
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
28
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:module_header:module_header"]
|
|
29
|
+
|
|
30
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:project:interface" type="interface" identity="CILProject" parent="none"]
|
|
31
|
+
// CIL[DOC-MACRO purpose="TypeScript interface describing the CIL project record shape"]
|
|
32
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Define the typed contract for CIL project data used by the file selection page"]
|
|
33
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/checkbox.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILFileSelectPage.tsx"]
|
|
34
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="CILProject type definition" errors="none" side_effects="none"]
|
|
35
|
+
// CIL[DOC-MICRO logic_summary="Declares CILProject with id, title, description, and a data object containing repo_path and file_statuses." notable_decisions="[]"]
|
|
36
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
37
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
38
|
+
interface CILProject {
|
|
39
|
+
id: string
|
|
40
|
+
title: string
|
|
41
|
+
description: string
|
|
42
|
+
data: {
|
|
43
|
+
repo_path: string
|
|
44
|
+
file_statuses: Record<string, string>
|
|
45
|
+
[key: string]: any
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// CIL[DOC-VECTOR type="context" content="purpose='TypeScript interface describing the CIL project record shape'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/card.tsx,.framework/src/components/ui/button.tsx"]
|
|
49
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
50
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
51
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
52
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
53
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
54
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:project:interface"]
|
|
55
|
+
|
|
56
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:treenode:interface" type="interface" identity="TreeNode" parent="none"]
|
|
57
|
+
// CIL[DOC-MACRO purpose="Recursive tree node type for file and folder paths"]
|
|
58
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Define the shape of tree nodes used to render the selectable file tree"]
|
|
59
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/checkbox.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILFileSelectPage.tsx"]
|
|
60
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="TreeNode type definition" errors="none" side_effects="none"]
|
|
61
|
+
// CIL[DOC-MICRO logic_summary="Declares a TreeNode with name, path, type, and a recursive children array." notable_decisions="[]"]
|
|
62
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
63
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
64
|
+
interface TreeNode {
|
|
65
|
+
name: string
|
|
66
|
+
path: string
|
|
67
|
+
type: 'file' | 'folder'
|
|
68
|
+
children: TreeNode[]
|
|
69
|
+
}
|
|
70
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Recursive tree node type for file and folder paths'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/card.tsx,.framework/src/components/ui/button.tsx"]
|
|
71
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
72
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
73
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
74
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
75
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
76
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:treenode:interface"]
|
|
77
|
+
|
|
78
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:buildtree:function" type="function" identity="buildTree" parent="none"]
|
|
79
|
+
// CIL[DOC-MACRO purpose="Build a sorted nested tree from a flat list of file paths"]
|
|
80
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Transform an array of file paths into a hierarchical TreeNode structure grouped by path segments"]
|
|
81
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/checkbox.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILFileSelectPage.tsx"]
|
|
82
|
+
// CIL[DOC-CONTRACT inputs="filePaths: string[], rootName: string" outputs="TreeNode root containing nested files and folders" errors="none" side_effects="none"]
|
|
83
|
+
// CIL[DOC-MICRO logic_summary="Sorts paths, splits each by '/', and creates nested children on demand, sorting folders before files." notable_decisions="["Sorts children by type (folders first) and then by name"]"]
|
|
84
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
85
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
86
|
+
function buildTree(filePaths: string[], rootName: string): TreeNode {
|
|
87
|
+
const root: TreeNode = { name: rootName, path: '', type: 'folder', children: [] }
|
|
88
|
+
|
|
89
|
+
const sortedPaths = [...filePaths].sort()
|
|
90
|
+
for (const fullPath of sortedPaths) {
|
|
91
|
+
const parts = fullPath.split('/')
|
|
92
|
+
let current = root
|
|
93
|
+
let built = ''
|
|
94
|
+
for (let i = 0; i < parts.length; i++) {
|
|
95
|
+
const part = parts[i]
|
|
96
|
+
built = built ? `${built}/${part}` : part
|
|
97
|
+
const isFile = i === parts.length - 1
|
|
98
|
+
const existing = current.children.find(c => c.name === part)
|
|
99
|
+
if (existing) {
|
|
100
|
+
current = existing
|
|
101
|
+
} else {
|
|
102
|
+
const child: TreeNode = {
|
|
103
|
+
name: part,
|
|
104
|
+
path: built,
|
|
105
|
+
type: isFile ? 'file' : 'folder',
|
|
106
|
+
children: [],
|
|
107
|
+
}
|
|
108
|
+
current.children.push(child)
|
|
109
|
+
current.children.sort((a, b) => (a.type === b.type ? a.name.localeCompare(b.name) : a.type === 'folder' ? -1 : 1))
|
|
110
|
+
current = child
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return root
|
|
116
|
+
}
|
|
117
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Build a sorted nested tree from a flat list of file paths'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/card.tsx,.framework/src/components/ui/button.tsx"]
|
|
118
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
119
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
120
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
121
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
122
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
123
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:buildtree:function"]
|
|
124
|
+
|
|
125
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:filepaths:function" type="function" identity="allFilePaths" parent="none"]
|
|
126
|
+
// CIL[DOC-MACRO purpose="Collect all file paths under a tree node"]
|
|
127
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Recursively flatten a node and its children into a list of file paths"]
|
|
128
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/checkbox.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILFileSelectPage.tsx"]
|
|
129
|
+
// CIL[DOC-CONTRACT inputs="node: TreeNode" outputs="string[] of all descendant file paths" errors="none" side_effects="none"]
|
|
130
|
+
// CIL[DOC-MICRO logic_summary="If the node is a file, returns its path; otherwise returns flatMap of child paths." notable_decisions="[]"]
|
|
131
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
132
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
133
|
+
function allFilePaths(node: TreeNode): string[] {
|
|
134
|
+
if (node.type === 'file') return [node.path]
|
|
135
|
+
return node.children.flatMap(allFilePaths)
|
|
136
|
+
}
|
|
137
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Collect all file paths under a tree node'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/card.tsx,.framework/src/components/ui/button.tsx"]
|
|
138
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
139
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
140
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
141
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
142
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
143
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:filepaths:function"]
|
|
144
|
+
|
|
145
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:nodecheck:function" type="function" identity="nodeCheckState" parent="none"]
|
|
146
|
+
// CIL[DOC-MACRO purpose="Determine the checked state of a tree node against a selection set"]
|
|
147
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Compute whether a node is checked, indeterminate, or unchecked based on descendant file selection"]
|
|
148
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/checkbox.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILFileSelectPage.tsx"]
|
|
149
|
+
// CIL[DOC-CONTRACT inputs="node: TreeNode, selected: Set<string>" outputs="'checked' | 'indeterminate' | 'unchecked'" errors="none" side_effects="none"]
|
|
150
|
+
// CIL[DOC-MICRO logic_summary="For files, checks membership in selected. For folders, compares selected descendant count to total descendants." notable_decisions="[]"]
|
|
151
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
152
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
153
|
+
function nodeCheckState(node: TreeNode, selected: Set<string>): 'checked' | 'indeterminate' | 'unchecked' {
|
|
154
|
+
if (node.type === 'file') {
|
|
155
|
+
return selected.has(node.path) ? 'checked' : 'unchecked'
|
|
156
|
+
}
|
|
157
|
+
const paths = allFilePaths(node)
|
|
158
|
+
if (paths.length === 0) return 'unchecked'
|
|
159
|
+
const selectedCount = paths.filter(p => selected.has(p)).length
|
|
160
|
+
if (selectedCount === 0) return 'unchecked'
|
|
161
|
+
if (selectedCount === paths.length) return 'checked'
|
|
162
|
+
return 'indeterminate'
|
|
163
|
+
}
|
|
164
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Determine the checked state of a tree node against a selection set'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/card.tsx,.framework/src/components/ui/button.tsx"]
|
|
165
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
166
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
167
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
168
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
169
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
170
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:nodecheck:function"]
|
|
171
|
+
|
|
172
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:filenamenode:function" type="function" identity="FileNameNode" parent="none"]
|
|
173
|
+
// CIL[DOC-MACRO purpose="Render a file or folder label with icon and expand chevron"]
|
|
174
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Display a node name with an appropriate icon and folder expand/collapse chevron"]
|
|
175
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/checkbox.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILFileSelectPage.tsx"]
|
|
176
|
+
// CIL[DOC-CONTRACT inputs="name: string, isFolder: boolean, expanded: boolean" outputs="JSX.Element label" errors="none" side_effects="none"]
|
|
177
|
+
// CIL[DOC-MICRO logic_summary="Renders a folder with chevron and folder icon when isFolder is true, otherwise a file icon followed by the name." notable_decisions="[]"]
|
|
178
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
179
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
180
|
+
function FileNameNode({ name, isFolder, expanded }: { name: string; isFolder: boolean; expanded: boolean }) {
|
|
181
|
+
return (
|
|
182
|
+
<span className="flex items-center gap-2">
|
|
183
|
+
{isFolder ? (
|
|
184
|
+
<>
|
|
185
|
+
{expanded ? <ChevronDown className="h-3.5 w-3.5 text-muted-foreground" /> : <ChevronRight className="h-3.5 w-3.5 text-muted-foreground" />}
|
|
186
|
+
<Folder className="h-4 w-4 text-indigo-500" />
|
|
187
|
+
</>
|
|
188
|
+
) : (
|
|
189
|
+
<FileCode2 className="h-4 w-4 text-muted-foreground" />
|
|
190
|
+
)}
|
|
191
|
+
<span className="text-sm">{name}</span>
|
|
192
|
+
</span>
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Render a file or folder label with icon and expand chevron'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/card.tsx,.framework/src/components/ui/button.tsx"]
|
|
196
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
197
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
198
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
199
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
200
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
201
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:filenamenode:function"]
|
|
202
|
+
|
|
203
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:treenode:component" type="component" identity="TreeNodeRow" parent="none"]
|
|
204
|
+
// CIL[DOC-MACRO purpose="Render a selectable, recursively expandable tree row"]
|
|
205
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Display a tree node with a tri-state checkbox, expand/collapse behavior, and recursive child rendering"]
|
|
206
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/checkbox.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILFileSelectPage.tsx"]
|
|
207
|
+
// CIL[DOC-CONTRACT inputs="node: TreeNode, selected: Set<string>, expanded: Set<string>, onToggle: (node: TreeNode) => void, onToggleExpand: (path: string) => void, depth?: number" outputs="JSX.Element" errors="none" side_effects="none"]
|
|
208
|
+
// CIL[DOC-MICRO logic_summary="Computes the checkbox state, renders the label with indentation, and conditionally renders children." notable_decisions="[]"]
|
|
209
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
210
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
211
|
+
function TreeNodeRow({
|
|
212
|
+
node,
|
|
213
|
+
selected,
|
|
214
|
+
expanded,
|
|
215
|
+
onToggle,
|
|
216
|
+
onToggleExpand,
|
|
217
|
+
depth = 0,
|
|
218
|
+
}: {
|
|
219
|
+
node: TreeNode
|
|
220
|
+
selected: Set<string>
|
|
221
|
+
expanded: Set<string>
|
|
222
|
+
onToggle: (node: TreeNode) => void
|
|
223
|
+
onToggleExpand: (path: string) => void
|
|
224
|
+
depth?: number
|
|
225
|
+
}) {
|
|
226
|
+
const checkState = nodeCheckState(node, selected)
|
|
227
|
+
const isFolder = node.type === 'folder'
|
|
228
|
+
const hasChildren = isFolder && node.children.length > 0
|
|
229
|
+
const isExpanded = expanded.has(node.path) || depth === 0
|
|
230
|
+
|
|
231
|
+
return (
|
|
232
|
+
<div className="select-none">
|
|
233
|
+
<div
|
|
234
|
+
className="flex items-center gap-2 py-1 hover:bg-muted/40 rounded px-1"
|
|
235
|
+
style={{ paddingLeft: `${depth * 12}px` }}
|
|
236
|
+
>
|
|
237
|
+
<Checkbox
|
|
238
|
+
checked={checkState === 'checked' ? true : checkState === 'indeterminate' ? 'indeterminate' : false}
|
|
239
|
+
onCheckedChange={() => onToggle(node)}
|
|
240
|
+
/>
|
|
241
|
+
<div
|
|
242
|
+
className="flex-1 cursor-pointer"
|
|
243
|
+
onClick={() => isFolder && hasChildren ? onToggleExpand(node.path) : undefined}
|
|
244
|
+
>
|
|
245
|
+
<FileNameNode name={node.name} isFolder={isFolder} expanded={isExpanded} />
|
|
246
|
+
</div>
|
|
247
|
+
</div>
|
|
248
|
+
{isFolder && isExpanded && hasChildren && (
|
|
249
|
+
<div>
|
|
250
|
+
{node.children.map(child => (
|
|
251
|
+
<TreeNodeRow
|
|
252
|
+
key={child.path}
|
|
253
|
+
node={child}
|
|
254
|
+
selected={selected}
|
|
255
|
+
expanded={expanded}
|
|
256
|
+
onToggle={onToggle}
|
|
257
|
+
onToggleExpand={onToggleExpand}
|
|
258
|
+
depth={depth + 1}
|
|
259
|
+
/>
|
|
260
|
+
))}
|
|
261
|
+
</div>
|
|
262
|
+
)}
|
|
263
|
+
</div>
|
|
264
|
+
)
|
|
265
|
+
}
|
|
266
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Render a selectable, recursively expandable tree row'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/card.tsx,.framework/src/components/ui/button.tsx"]
|
|
267
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
268
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
269
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
270
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
271
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
272
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:treenode:component"]
|
|
273
|
+
|
|
274
|
+
// CIL[BEGIN stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:CILFileSelectPage:component" type="component" identity="CILFileSelectPage" parent="none"]
|
|
275
|
+
// CIL[DOC-MACRO purpose="Main page component for CIL file and folder selection"]
|
|
276
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Load the CIL project, render a tri-state file tree, and submit the selected file set"]
|
|
277
|
+
// CIL[DOC-CONTEXT module=".framework/src/pages/admin/cil" layer="admin-ui" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/button.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/checkbox.tsx,.framework/src/components/ui/skeleton.tsx,.framework/src/lib/api.ts,.framework/src/pages/admin/cil/CILFileSelectPage.tsx"]
|
|
278
|
+
// CIL[DOC-CONTRACT inputs="project_id from URL" outputs="Updated selected_paths for the project" errors="Project not found, selection save failed" side_effects="Calls /api/cil-ingest?action=select and navigates to the dashboard"]
|
|
279
|
+
// CIL[DOC-MICRO logic_summary="Fetches the project, builds the tree, manages selected and expanded sets, renders the tree and instructions, and saves the selection." notable_decisions="["Tree root is derived from repo_path basename","All files under a folder are selected/deselected together"]"]
|
|
280
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
281
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
282
|
+
export default function CILFileSelectPage() {
|
|
283
|
+
const { id: projectId } = useParams<{ id: string }>()
|
|
284
|
+
const navigate = useNavigate()
|
|
285
|
+
const appPath = (path: string) => '/spine-framework/admin' + (path.startsWith('/') ? path : '/' + path)
|
|
286
|
+
|
|
287
|
+
const [project, setProject] = useState<CILProject | null>(null)
|
|
288
|
+
const [loading, setLoading] = useState(true)
|
|
289
|
+
const [saving, setSaving] = useState(false)
|
|
290
|
+
const [selected, setSelected] = useState<Set<string>>(new Set())
|
|
291
|
+
const [expanded, setExpanded] = useState<Set<string>>(new Set())
|
|
292
|
+
|
|
293
|
+
const load = useCallback(async () => {
|
|
294
|
+
if (!projectId) return
|
|
295
|
+
setLoading(true)
|
|
296
|
+
try {
|
|
297
|
+
const res = await apiFetch(`/api/cil-project?action=get&id=${projectId}`)
|
|
298
|
+
const result = await res.json()
|
|
299
|
+
const projectData = result?.project || result?.data?.project
|
|
300
|
+
setProject(projectData)
|
|
301
|
+
const statuses: Record<string, string> = projectData?.data?.file_statuses || {}
|
|
302
|
+
const initialSelected = new Set<string>(
|
|
303
|
+
Object.entries(statuses).filter(([_, status]) => status === '1-selected').map(([path]) => path)
|
|
304
|
+
)
|
|
305
|
+
setSelected(initialSelected)
|
|
306
|
+
setExpanded(new Set())
|
|
307
|
+
} finally {
|
|
308
|
+
setLoading(false)
|
|
309
|
+
}
|
|
310
|
+
}, [projectId])
|
|
311
|
+
|
|
312
|
+
useEffect(() => { load() }, [load])
|
|
313
|
+
|
|
314
|
+
const filePaths = useMemo(() => {
|
|
315
|
+
if (!project) return []
|
|
316
|
+
return Object.keys(project.data.file_statuses || {})
|
|
317
|
+
}, [project])
|
|
318
|
+
|
|
319
|
+
const tree = useMemo(() => {
|
|
320
|
+
const rootName = project?.data?.repo_path ? project.data.repo_path.split('/').pop() || 'root' : 'root'
|
|
321
|
+
return buildTree(filePaths, rootName)
|
|
322
|
+
}, [filePaths, project])
|
|
323
|
+
|
|
324
|
+
const handleToggle = useCallback((node: TreeNode) => {
|
|
325
|
+
const paths = allFilePaths(node)
|
|
326
|
+
setSelected(prev => {
|
|
327
|
+
const next = new Set(prev)
|
|
328
|
+
const allSelected = paths.every(p => next.has(p))
|
|
329
|
+
if (allSelected) {
|
|
330
|
+
paths.forEach(p => next.delete(p))
|
|
331
|
+
} else {
|
|
332
|
+
paths.forEach(p => next.add(p))
|
|
333
|
+
}
|
|
334
|
+
return next
|
|
335
|
+
})
|
|
336
|
+
}, [])
|
|
337
|
+
|
|
338
|
+
const handleToggleExpand = useCallback((path: string) => {
|
|
339
|
+
setExpanded(prev => {
|
|
340
|
+
const next = new Set(prev)
|
|
341
|
+
if (next.has(path)) next.delete(path)
|
|
342
|
+
else next.add(path)
|
|
343
|
+
return next
|
|
344
|
+
})
|
|
345
|
+
}, [])
|
|
346
|
+
|
|
347
|
+
const handleSave = useCallback(async () => {
|
|
348
|
+
if (!projectId) return
|
|
349
|
+
setSaving(true)
|
|
350
|
+
try {
|
|
351
|
+
await apiFetch('/api/cil-ingest?action=select', {
|
|
352
|
+
method: 'POST',
|
|
353
|
+
headers: { 'Content-Type': 'application/json' },
|
|
354
|
+
body: JSON.stringify({
|
|
355
|
+
project_id: projectId,
|
|
356
|
+
selected_paths: Array.from(selected),
|
|
357
|
+
}),
|
|
358
|
+
})
|
|
359
|
+
navigate(appPath(`/cil/${projectId}/dashboard`))
|
|
360
|
+
} finally {
|
|
361
|
+
setSaving(false)
|
|
362
|
+
}
|
|
363
|
+
}, [projectId, selected, navigate, appPath])
|
|
364
|
+
|
|
365
|
+
if (loading) {
|
|
366
|
+
return (
|
|
367
|
+
<div className="p-6 space-y-4">
|
|
368
|
+
<Skeleton className="h-8 w-48" />
|
|
369
|
+
<Skeleton className="h-96 w-full" />
|
|
370
|
+
</div>
|
|
371
|
+
)
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (!project) {
|
|
375
|
+
return (
|
|
376
|
+
<div className="p-6">
|
|
377
|
+
<p className="text-muted-foreground">Project not found.</p>
|
|
378
|
+
</div>
|
|
379
|
+
)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return (
|
|
383
|
+
<div className="p-6 space-y-4 max-w-5xl">
|
|
384
|
+
<div className="flex items-start justify-between flex-wrap gap-4">
|
|
385
|
+
<div>
|
|
386
|
+
<h1 className="text-2xl font-bold">Select Files</h1>
|
|
387
|
+
<p className="text-sm text-muted-foreground">{project.title} — choose files and folders for CIL processing</p>
|
|
388
|
+
</div>
|
|
389
|
+
<div className="flex items-center gap-2">
|
|
390
|
+
<Button size="sm" variant="outline" onClick={() => navigate(appPath(`/cil/${projectId}/dashboard`))}>
|
|
391
|
+
Cancel
|
|
392
|
+
</Button>
|
|
393
|
+
<Button size="sm" onClick={handleSave} disabled={saving}>
|
|
394
|
+
{saving ? <span className="animate-pulse">Saving…</span> : <><Save className="h-4 w-4 mr-1" /> Save Selection</>}
|
|
395
|
+
</Button>
|
|
396
|
+
</div>
|
|
397
|
+
</div>
|
|
398
|
+
|
|
399
|
+
<PageInstructions
|
|
400
|
+
description="Select which discovered files should move forward through the CIL pipeline."
|
|
401
|
+
sections={[
|
|
402
|
+
{ title: 'What this page is for', content: 'Pass 2 — selection. Check files or folders to mark them as selected for chunking, documentation, and enrichment.' },
|
|
403
|
+
{ title: 'How to select', content: 'Click a file checkbox to toggle it. Click a folder to select or deselect all files inside that folder.' },
|
|
404
|
+
{ title: 'What happens next', content: 'Saving writes the selected paths to the project and updates each cil_file status to 1-selected. Passes 3-8 are then run by Devin through the CIL MCP tools.' },
|
|
405
|
+
]}
|
|
406
|
+
/>
|
|
407
|
+
|
|
408
|
+
<Card>
|
|
409
|
+
<CardHeader className="pb-2">
|
|
410
|
+
<CardTitle className="text-sm">Discovered Files</CardTitle>
|
|
411
|
+
<p className="text-xs text-muted-foreground">{filePaths.length} discovered • {selected.size} selected</p>
|
|
412
|
+
</CardHeader>
|
|
413
|
+
<CardContent className="max-h-[60vh] overflow-y-auto border-t pt-3">
|
|
414
|
+
<TreeNodeRow
|
|
415
|
+
node={tree}
|
|
416
|
+
selected={selected}
|
|
417
|
+
expanded={expanded}
|
|
418
|
+
onToggle={handleToggle}
|
|
419
|
+
onToggleExpand={handleToggleExpand}
|
|
420
|
+
/>
|
|
421
|
+
</CardContent>
|
|
422
|
+
</Card>
|
|
423
|
+
</div>
|
|
424
|
+
)
|
|
425
|
+
}
|
|
426
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Main page component for CIL file and folder selection'; No verified external callers; imports: .framework/src/lib/api.ts,.framework/src/components/ui/card.tsx,.framework/src/components/ui/button.tsx"]
|
|
427
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
428
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
429
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
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
|
+
// CIL[END stable_id="~/.framework/src/pages/admin/cil/CILFileSelectPage.tsx:CILFileSelectPage:component"]
|