spine-framework 0.4.3 → 0.5.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +13 -3
- package/.framework/cli/commands/bootstrap.ts +392 -0
- package/.framework/cli/commands/dev.ts +91 -218
- package/.framework/cli/commands/doctor.ts +132 -26
- package/.framework/cli/commands/generate.ts +38 -298
- package/.framework/cli/commands/init.ts +20 -1
- package/.framework/cli/commands/migrate.ts +36 -30
- package/.framework/cli/commands/migrations.ts +16 -56
- package/.framework/cli/commands/upgrade.ts +35 -0
- package/.framework/cli/commands/validate-schema.ts +147 -0
- package/.framework/cli/context.ts +223 -110
- package/.framework/cli/index.ts +6 -0
- package/.framework/cli/lib/project-files.ts +241 -1
- package/.framework/functions/_shared/agent-runner.ts +1000 -81
- package/.framework/functions/_shared/cil.ts +2 -1
- package/.framework/functions/_shared/db.ts +3 -6
- package/.framework/functions/_shared/hash-api-key.ts +183 -79
- package/.framework/functions/_shared/kb.ts +61 -7
- package/.framework/functions/_shared/logging.ts +562 -224
- package/.framework/functions/_shared/message-sequence.ts +53 -0
- package/.framework/functions/_shared/middleware.ts +47 -44
- package/.framework/functions/_shared/pipeline-runner.ts +150 -37
- package/.framework/functions/_shared/principal.ts +9 -6
- package/.framework/functions/_shared/trigger-engine.ts +149 -40
- package/.framework/functions/admin-data.ts +48 -31
- package/.framework/functions/ai-agents.ts +103 -33
- package/.framework/functions/api-keys.ts +301 -122
- package/.framework/functions/apps.ts +43 -26
- package/.framework/functions/cil-ingest.ts +48 -15
- package/.framework/functions/debug-auth.ts +14 -8
- package/.framework/functions/deliveries.ts +39 -12
- package/.framework/functions/embeddings.ts +145 -76
- package/.framework/functions/integration-outbound.ts +67 -27
- package/.framework/functions/integrations.ts +254 -127
- package/.framework/functions/logs.ts +273 -133
- package/.framework/functions/observability.ts +277 -147
- package/.framework/functions/pipeline-executions.ts +1 -1
- package/.framework/functions/pipeline-runner-background.ts +120 -0
- package/.framework/functions/pipelines.ts +14 -9
- package/.framework/functions/prompt-configs.ts +7 -4
- package/.framework/functions/roles.ts +8 -5
- package/.framework/functions/security.ts +30 -17
- package/.framework/functions/system-cron.ts +250 -128
- package/.framework/functions/tests.ts +7 -6
- package/.framework/functions/timers.ts +310 -107
- package/.framework/functions/trigger-scheduler.ts +65 -5
- package/.framework/functions/triggers.ts +28 -13
- package/.framework/functions/types.ts +13 -10
- package/.framework/migrations/064_episode_leases.sql +196 -0
- package/.framework/migrations/065_execution_tables_updated_at.sql +20 -0
- package/.framework/migrations/066_episode_steal_thread_merge.sql +148 -0
- package/.framework/migrations/067_episode_lease_stale_steal.sql +93 -0
- package/.framework/migrations/068_cron_schedule_timer_rpcs.sql +251 -0
- package/.framework/migrations/069_log_stats_window.sql +54 -0
- package/.framework/migrations/070_app_type_schema_rpcs.sql +166 -0
- package/.framework/migrations/071_timer_interval_keys.sql +96 -0
- package/.framework/migrations/072_slug_autofill.sql +77 -0
- package/.framework/migrations/073_seed_member_roles.sql +26 -0
- package/.framework/schemas/spine.config.schema.json +62 -0
- package/.framework/src/App.tsx +3 -1
- package/.framework/src/apps/admin/index.tsx +1141 -775
- package/.framework/src/components/ErrorBoundary.tsx +136 -0
- package/.framework/src/components/admin/AdminListPage.tsx +81 -73
- package/.framework/src/components/admin/AdminSidebar.tsx +92 -81
- package/.framework/src/components/admin/EntitySelect.tsx +181 -0
- package/.framework/src/components/admin/PageInstructions.tsx +86 -127
- package/.framework/src/components/app-shell/GenericAppShell.tsx +3 -1
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +37 -13
- package/.framework/src/components/app-shell/GenericListPage.tsx +28 -32
- package/.framework/src/components/auth/TurnstileWidget.tsx +9 -6
- package/.framework/src/components/kb/KBArticleEditor.tsx +49 -6
- package/.framework/src/components/layout/Layout.tsx +4 -2
- package/.framework/src/components/layout/Sidebar.tsx +304 -179
- package/.framework/src/components/runtime/DataDetailPage.tsx +67 -35
- package/.framework/src/components/runtime/DataHeader.tsx +96 -48
- package/.framework/src/components/runtime/DataListPage.tsx +3 -26
- package/.framework/src/components/runtime/DataStats.tsx +10 -10
- package/.framework/src/components/runtime/DataTable.tsx +12 -10
- package/.framework/src/components/ui/sheet.tsx +24 -26
- package/.framework/src/components/ui/textarea.tsx +74 -48
- package/.framework/src/hooks/useBranding.ts +47 -0
- package/.framework/src/hooks/useEntityList.ts +12 -9
- package/.framework/src/hooks/useListSchema.ts +108 -58
- package/.framework/src/instructions/README.md +57 -0
- package/.framework/src/instructions/ai-agents.md +69 -0
- package/.framework/src/instructions/alerts.md +80 -0
- package/.framework/src/instructions/api-keys.md +87 -0
- package/.framework/src/instructions/apps.md +77 -0
- package/.framework/src/instructions/concepts/ai-and-prompts.md +150 -0
- package/.framework/src/instructions/concepts/apps-and-renderers.md +162 -0
- package/.framework/src/instructions/concepts/auth-and-api-keys.md +133 -0
- package/.framework/src/instructions/concepts/automation.md +186 -0
- package/.framework/src/instructions/concepts/concurrency-and-idempotency.md +125 -0
- package/.framework/src/instructions/concepts/core-vs-custom.md +124 -0
- package/.framework/src/instructions/concepts/design-schema.md +152 -0
- package/.framework/src/instructions/concepts/integrations-and-webhooks.md +127 -0
- package/.framework/src/instructions/concepts/observability.md +116 -0
- package/.framework/src/instructions/concepts/permissions.md +150 -0
- package/.framework/src/instructions/concepts/runtime-records.md +111 -0
- package/.framework/src/instructions/concepts/scope-and-accounts.md +112 -0
- package/.framework/src/instructions/concepts/spine-way.md +172 -0
- package/.framework/src/instructions/deliveries.md +59 -0
- package/.framework/src/instructions/guide/00-orientation.md +106 -0
- package/.framework/src/instructions/guide/01-install-and-first-run.md +253 -0
- package/.framework/src/instructions/guide/02-project-map.md +147 -0
- package/.framework/src/instructions/guide/03-domain-model.md +223 -0
- package/.framework/src/instructions/guide/04-first-app.md +227 -0
- package/.framework/src/instructions/guide/05-glossary.md +183 -0
- package/.framework/src/instructions/integrations.md +96 -0
- package/.framework/src/instructions/internal/cil-markers.md +83 -0
- package/.framework/src/instructions/invites.md +60 -0
- package/.framework/src/instructions/kb.md +80 -0
- package/.framework/src/instructions/logs.md +77 -0
- package/.framework/src/instructions/observability.md +61 -0
- package/.framework/src/instructions/operations/deployment.md +115 -0
- package/.framework/src/instructions/operations/migrations.md +125 -0
- package/.framework/src/instructions/operations/security-checklist.md +148 -0
- package/.framework/src/instructions/operations/troubleshooting.md +170 -0
- package/.framework/src/instructions/operations/upgrade.md +116 -0
- package/.framework/src/instructions/pipeline-executions.md +62 -0
- package/.framework/src/instructions/pipelines.md +78 -0
- package/.framework/src/instructions/prompts.md +95 -0
- package/.framework/src/instructions/reference/api/admin-data.md +162 -0
- package/.framework/src/instructions/reference/api/auth.md +113 -0
- package/.framework/src/instructions/reference/api/errors-and-envelopes.md +113 -0
- package/.framework/src/instructions/reference/app-manifest.md +150 -0
- package/.framework/src/instructions/reference/cli.md +124 -0
- package/.framework/src/instructions/reference/database.md +132 -0
- package/.framework/src/instructions/reference/design-schema.md +280 -0
- package/.framework/src/instructions/reference/env-vars.md +133 -0
- package/.framework/src/instructions/reference/functions/account-nodes.md +75 -0
- package/.framework/src/instructions/reference/functions/admin-data.md +195 -0
- package/.framework/src/instructions/reference/functions/admin-funnel.md +90 -0
- package/.framework/src/instructions/reference/functions/admin-install-funnel.md +107 -0
- package/.framework/src/instructions/reference/functions/admin-signals.md +102 -0
- package/.framework/src/instructions/reference/functions/ai-agents.md +148 -0
- package/.framework/src/instructions/reference/functions/ai-interactions.md +156 -0
- package/.framework/src/instructions/reference/functions/api-keys.md +130 -0
- package/.framework/src/instructions/reference/functions/apps.md +140 -0
- package/.framework/src/instructions/reference/functions/auth.md +99 -0
- package/.framework/src/instructions/reference/functions/debug-auth.md +91 -0
- package/.framework/src/instructions/reference/functions/deliveries.md +110 -0
- package/.framework/src/instructions/reference/functions/embeddings.md +166 -0
- package/.framework/src/instructions/reference/functions/eval-harness.md +149 -0
- package/.framework/src/instructions/reference/functions/index.md +103 -0
- package/.framework/src/instructions/reference/functions/integration-outbound.md +200 -0
- package/.framework/src/instructions/reference/functions/integration-routes.md +151 -0
- package/.framework/src/instructions/reference/functions/integrations.md +130 -0
- package/.framework/src/instructions/reference/functions/invites.md +182 -0
- package/.framework/src/instructions/reference/functions/item-progress.md +107 -0
- package/.framework/src/instructions/reference/functions/kb.md +166 -0
- package/.framework/src/instructions/reference/functions/logs.md +141 -0
- package/.framework/src/instructions/reference/functions/observability.md +105 -0
- package/.framework/src/instructions/reference/functions/pipeline-executions.md +132 -0
- package/.framework/src/instructions/reference/functions/pipeline-runner-background.md +121 -0
- package/.framework/src/instructions/reference/functions/pipelines.md +136 -0
- package/.framework/src/instructions/reference/functions/prompt-configs.md +121 -0
- package/.framework/src/instructions/reference/functions/roles.md +121 -0
- package/.framework/src/instructions/reference/functions/security.md +140 -0
- package/.framework/src/instructions/reference/functions/system-cron.md +136 -0
- package/.framework/src/instructions/reference/functions/system.md +106 -0
- package/.framework/src/instructions/reference/functions/tests.md +97 -0
- package/.framework/src/instructions/reference/functions/timers.md +117 -0
- package/.framework/src/instructions/reference/functions/trigger-scheduler.md +102 -0
- package/.framework/src/instructions/reference/functions/triggers.md +140 -0
- package/.framework/src/instructions/reference/functions/types.md +146 -0
- package/.framework/src/instructions/reference/seeds.md +126 -0
- package/.framework/src/instructions/reference/shared-modules.md +127 -0
- package/.framework/src/instructions/reference/spine-config.md +114 -0
- package/.framework/src/instructions/roles.md +80 -0
- package/.framework/src/instructions/runtime-detail.md +70 -0
- package/.framework/src/instructions/runtime-list.md +77 -0
- package/.framework/src/instructions/security.md +67 -0
- package/.framework/src/instructions/tasks/add-a-pipeline.md +110 -0
- package/.framework/src/instructions/tasks/add-a-role.md +96 -0
- package/.framework/src/instructions/tasks/add-a-timer.md +114 -0
- package/.framework/src/instructions/tasks/add-a-trigger.md +106 -0
- package/.framework/src/instructions/tasks/add-a-type.md +151 -0
- package/.framework/src/instructions/tasks/add-a-webhook.md +108 -0
- package/.framework/src/instructions/tasks/add-an-ai-agent.md +108 -0
- package/.framework/src/instructions/tasks/add-an-integration.md +124 -0
- package/.framework/src/instructions/tasks/build-a-custom-page.md +118 -0
- package/.framework/src/instructions/tasks/package-and-install-an-app.md +127 -0
- package/.framework/src/instructions/tasks/test-your-code.md +108 -0
- package/.framework/src/instructions/tasks/write-a-function.md +132 -0
- package/.framework/src/instructions/tasks/write-a-migration.md +110 -0
- package/.framework/src/instructions/testing.md +59 -0
- package/.framework/src/instructions/timers.md +82 -0
- package/.framework/src/instructions/triggers.md +69 -0
- package/.framework/src/instructions/types.md +93 -0
- package/.framework/src/lib/branding.ts +128 -0
- package/.framework/src/pages/NoAppPage.tsx +3 -1
- package/.framework/src/pages/NotFoundPage.tsx +62 -31
- package/.framework/src/pages/SetupPage.tsx +5 -2
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +117 -106
- package/.framework/src/pages/admin/AIAgentsPage.tsx +86 -48
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +153 -152
- package/.framework/src/pages/admin/APIKeysPage.tsx +91 -90
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +29 -18
- package/.framework/src/pages/admin/AppDetailPage.tsx +6 -60
- package/.framework/src/pages/admin/AppsPage.tsx +104 -66
- package/.framework/src/pages/admin/DeliveriesPage.tsx +5 -5
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +5 -23
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +5 -26
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +7 -7
- package/.framework/src/pages/admin/IntegrationsPage.tsx +85 -43
- package/.framework/src/pages/admin/LogsPage.tsx +144 -76
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +223 -140
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +134 -113
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +108 -45
- package/.framework/src/pages/admin/PipelinesPage.tsx +160 -115
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +96 -98
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +101 -59
- package/.framework/src/pages/admin/RoleDetailPage.tsx +90 -79
- package/.framework/src/pages/admin/RolesPage.tsx +86 -43
- package/.framework/src/pages/admin/SecurityPage.tsx +1 -1
- package/.framework/src/pages/admin/TestingDashboard.tsx +16 -28
- package/.framework/src/pages/admin/TimerDetailPage.tsx +117 -100
- package/.framework/src/pages/admin/TimersPage.tsx +90 -62
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +90 -83
- package/.framework/src/pages/admin/TriggersPage.tsx +124 -99
- package/.framework/src/pages/admin/TypeDetailPage.tsx +152 -138
- package/.framework/src/pages/admin/TypesPage.tsx +90 -48
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +17 -25
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +17 -27
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +72 -40
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +321 -129
- package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +18 -29
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +26 -38
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +34 -46
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +189 -103
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +246 -136
- package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +11 -22
- package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +9 -20
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +26 -38
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +7 -26
- package/.framework/src/pages/auth/AuthConfirmPage.tsx +3 -1
- package/.framework/src/pages/auth/ForgotPasswordPage.tsx +3 -1
- package/.framework/src/pages/auth/LoginPage.tsx +4 -2
- package/.framework/src/pages/auth/RegisterPage.tsx +3 -1
- package/.framework/templates/agent/AGENTS.md +150 -0
- package/.framework/templates/agent/skills/spine-add-ai-agent/SKILL.md +58 -0
- package/.framework/templates/agent/skills/spine-add-automation/SKILL.md +62 -0
- package/.framework/templates/agent/skills/spine-add-integration/SKILL.md +63 -0
- package/.framework/templates/agent/skills/spine-architect/SKILL.md +86 -0
- package/.framework/templates/agent/skills/spine-install-app/SKILL.md +72 -0
- package/.framework/templates/agent/skills/spine-migration/SKILL.md +75 -0
- package/.framework/templates/agent/skills/spine-new-app/SKILL.md +67 -0
- package/.framework/templates/agent/skills/spine-new-function/SKILL.md +65 -0
- package/.framework/templates/agent/skills/spine-new-type/SKILL.md +65 -0
- package/.framework/templates/agent/skills/spine-schema/SKILL.md +77 -0
- package/.framework/templates/agent/skills/spine-test/SKILL.md +67 -0
- package/.framework/templates/agent/skills/spine-troubleshoot/SKILL.md +74 -0
- package/.framework/templates/agent/skills/spine-upgrade/SKILL.md +69 -0
- package/.framework/templates/project.json +5 -1
- package/.framework/tests/unit/account-scoping-gates.test.ts +392 -0
- package/.framework/tests/unit/agent-files.test.ts +355 -0
- package/.framework/tests/unit/agent-runner.test.ts +496 -47
- package/.framework/tests/unit/api-keys-create-scope-gate.test.ts +160 -0
- package/.framework/tests/unit/api-keys-omit-secret-fields.test.ts +38 -0
- package/.framework/tests/unit/bootstrap.test.ts +242 -0
- package/.framework/tests/unit/cli-context-api-key.test.ts +114 -0
- package/.framework/tests/unit/debug-auth.test.ts +38 -0
- package/.framework/tests/unit/deliveries-account-scoping.test.ts +185 -0
- package/.framework/tests/unit/episode-lease.test.ts +695 -0
- package/.framework/tests/unit/integration-outbound-credentials.test.ts +167 -0
- package/.framework/tests/unit/integrations-audit-redaction.test.ts +130 -0
- package/.framework/tests/unit/kb-ingest-lease.test.ts +19 -0
- package/.framework/tests/unit/logging-app-id.test.ts +75 -0
- package/.framework/tests/unit/pipeline-runner-background.test.ts +120 -0
- package/.framework/tests/unit/pipeline-runner.test.ts +153 -1
- package/.framework/tests/unit/principal-cache.test.ts +15 -0
- package/.framework/tests/unit/system-context-denial.test.ts +145 -0
- package/.framework/tests/unit/system-cron.test.ts +240 -0
- package/.framework/tests/unit/timers.test.ts +159 -0
- package/.framework/tests/unit/trigger-engine.test.ts +278 -91
- package/.framework/tests/unit/trigger-scheduler.test.ts +78 -0
- package/README.md +125 -166
- package/config/tsconfig.cli.json +2 -2
- package/netlify.toml +5 -0
- package/package.json +15 -4
- package/templates/project/package-lock.json +2 -2
- package/.framework/docs/admin-routes.md +0 -76
- package/.framework/docs/api-docs-progress.md +0 -38
- package/.framework/docs/api-governance.md +0 -146
- package/.framework/docs/api-testing-results.md +0 -212
- package/.framework/docs/assembly-launch-guide.md +0 -138
- package/.framework/docs/audit-results.md +0 -590
- package/.framework/docs/db-api-inventory.md +0 -95
- package/.framework/docs/gap-remediation-backlog.md +0 -103
- package/.framework/docs/ui-adoption-verification.md +0 -111
- package/.framework/docs/ui-api-coverage.md +0 -84
- package/.framework/docs/v2-compatibility-audit.md +0 -228
- package/.framework/mcp/index.ts +0 -133
- package/.framework/mcp/load-env.ts +0 -60
- package/.framework/mcp/shared/app-manifest.ts +0 -275
- package/.framework/mcp/shared/db.ts +0 -477
- package/.framework/mcp/shared/kb.ts +0 -118
- package/.framework/mcp/tools/architect.ts +0 -431
- package/.framework/mcp/tools/cil/context.ts +0 -345
- package/.framework/mcp/tools/cil/graph.ts +0 -242
- package/.framework/mcp/tools/cil/ingest.ts +0 -1217
- package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +0 -693
- package/.framework/mcp/tools/cil/pipeline.ts +0 -767
- package/.framework/mcp/tools/cil/project.ts +0 -791
- package/.framework/mcp/tools/cil/retrieval.ts +0 -336
- package/.framework/mcp/tools/cil/search-core.ts +0 -454
- package/.framework/mcp/tools/cil/search.ts +0 -97
- package/.framework/mcp/tools/cil/suggest.ts +0 -186
- package/.framework/mcp/tools/cil/validate.ts +0 -1369
- package/.framework/mcp/tools/kb/delete.ts +0 -139
- package/.framework/mcp/tools/kb/index.ts +0 -52
- package/.framework/mcp/tools/kb/ingest.ts +0 -84
- package/.framework/mcp/tools/kb/list-types.ts +0 -102
- package/.framework/mcp/tools/kb/publish.ts +0 -100
- package/.framework/mcp/tools/kb/reindex.ts +0 -86
- package/.framework/mcp/tools/kb/revoke.ts +0 -85
- package/.framework/mcp/tools/kb/search.ts +0 -101
- package/.framework/mcp/tools/kb/upsert.ts +0 -125
- package/.framework/mcp/tools/observability.ts +0 -510
|
@@ -11,9 +11,12 @@
|
|
|
11
11
|
import type { Command } from 'commander'
|
|
12
12
|
import { buildCliContext, handleError } from '../context.ts'
|
|
13
13
|
import { adminDb } from '../../functions/_shared/index.ts'
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
14
|
+
import { collectMigrations } from './migrate.ts'
|
|
15
|
+
import { readFileSync, existsSync } from 'fs'
|
|
16
|
+
import { resolve, dirname, join } from 'path'
|
|
16
17
|
import { fileURLToPath } from 'url'
|
|
18
|
+
import { findAgentsBlock, agentsBlockVersion } from '../lib/project-files.ts'
|
|
19
|
+
import { hashEntry } from '../../../scripts/checksum-manifest.mts'
|
|
17
20
|
|
|
18
21
|
// CIL[DOC-VECTOR type="context" content="purpose='Provides CLI commands for the doctor (system health) functionality, integrating with CLI context and shared database functions.'; No verified external callers; imports: .framework/cli/context.ts,.framework/functions/_shared/index.ts"]
|
|
19
22
|
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
@@ -131,7 +134,27 @@ async function checkEnvironment(): Promise<CheckResult> {
|
|
|
131
134
|
}
|
|
132
135
|
}
|
|
133
136
|
|
|
134
|
-
|
|
137
|
+
const bad = required.filter(v => /your[-_]|placeholder|change-?me|^<[^>]*>|^xxx/i.test(process.env[v]!))
|
|
138
|
+
if (bad.length > 0) {
|
|
139
|
+
return {
|
|
140
|
+
name: 'environment',
|
|
141
|
+
status: 'fail',
|
|
142
|
+
message: `Placeholder values still set: ${bad.join(', ')} — replace with real Supabase credentials`,
|
|
143
|
+
details: { bad },
|
|
144
|
+
fixable: true
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (!/^https:\/\/[a-z0-9-]+\.supabase\.co/.test(process.env.SUPABASE_URL || '')) {
|
|
149
|
+
return {
|
|
150
|
+
name: 'environment',
|
|
151
|
+
status: 'fail',
|
|
152
|
+
message: 'SUPABASE_URL must look like https://<project-ref>.supabase.co',
|
|
153
|
+
details: {},
|
|
154
|
+
fixable: true
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
135
158
|
const xenvPath = resolve(__dirname, '../../.xenv')
|
|
136
159
|
const hasXenv = existsSync(xenvPath)
|
|
137
160
|
|
|
@@ -142,6 +165,7 @@ async function checkEnvironment(): Promise<CheckResult> {
|
|
|
142
165
|
details: { has_xenv: hasXenv, vars_present: required.length }
|
|
143
166
|
}
|
|
144
167
|
}
|
|
168
|
+
|
|
145
169
|
// CIL[DOC-VECTOR type="context" content="purpose='Validates required environment variables and optional .xenv file presence.'; No verified external callers; imports: .framework/cli/context.ts,.framework/functions/_shared/index.ts"]
|
|
146
170
|
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
147
171
|
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
@@ -202,15 +226,15 @@ async function checkDatabase(): Promise<CheckResult> {
|
|
|
202
226
|
// CIL[DOC-MACRO purpose="Compares local migration files against applied database migrations."]
|
|
203
227
|
// CIL[DOC-RESPONSIBILITY responsibility="Identify pending or missing database migrations."]
|
|
204
228
|
// CIL[DOC-CONTEXT module="doctor" layer="app-specific" related_files=".framework/cli/commands/doctor.ts,.framework/cli/context.ts,.framework/functions/_shared/index.ts"]
|
|
205
|
-
// CIL[DOC-CONTRACT inputs="[]" outputs="Promise<CheckResult>" errors="[]" side_effects="
|
|
206
|
-
// CIL[DOC-MICRO logic_summary="List local SQL files, query applied
|
|
229
|
+
// CIL[DOC-CONTRACT inputs="[]" outputs="Promise<CheckResult>" errors="[]" side_effects="Collects local migration files and queries _spine_migrations."]
|
|
230
|
+
// CIL[DOC-MICRO logic_summary="List local SQL files via collectMigrations (framework + custom), query applied filenames from _spine_migrations, and report any local files not yet applied." notable_decisions="Returns warn for pending migrations — including when the tracking table does not exist yet — and fail only on unexpected query errors."]
|
|
207
231
|
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
208
232
|
// CIL[DOC-STABILITY stability="stable"]
|
|
209
233
|
|
|
210
234
|
async function checkMigrations(): Promise<CheckResult> {
|
|
211
|
-
const
|
|
235
|
+
const migrationFiles = collectMigrations(false)
|
|
212
236
|
|
|
213
|
-
if (
|
|
237
|
+
if (migrationFiles.length === 0) {
|
|
214
238
|
return {
|
|
215
239
|
name: 'migrations',
|
|
216
240
|
status: 'fail',
|
|
@@ -219,36 +243,37 @@ async function checkMigrations(): Promise<CheckResult> {
|
|
|
219
243
|
}
|
|
220
244
|
}
|
|
221
245
|
|
|
222
|
-
const localFiles = readdirSync(migrationsDir)
|
|
223
|
-
.filter(f => f.endsWith('.sql'))
|
|
224
|
-
.sort()
|
|
225
|
-
|
|
226
246
|
try {
|
|
227
247
|
const { data, error } = await adminDb
|
|
228
|
-
.
|
|
229
|
-
.
|
|
230
|
-
.select('version')
|
|
248
|
+
.from('_spine_migrations' as any)
|
|
249
|
+
.select('filename')
|
|
231
250
|
|
|
232
251
|
if (error) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
252
|
+
// A missing tracking table means `migrate` has never run on this
|
|
253
|
+
// database — every file is pending, which is a warn, not a query error.
|
|
254
|
+
const tableMissing = error.code === '42P01' ||
|
|
255
|
+
/does not exist|schema cache/i.test(error.message)
|
|
256
|
+
if (!tableMissing) {
|
|
257
|
+
return {
|
|
258
|
+
name: 'migrations',
|
|
259
|
+
status: 'fail',
|
|
260
|
+
message: `Cannot query applied migrations: ${error.message}`,
|
|
261
|
+
details: { error: error.message },
|
|
262
|
+
fixable: false
|
|
263
|
+
}
|
|
239
264
|
}
|
|
240
265
|
}
|
|
241
266
|
|
|
242
|
-
const applied = (data || []).map((r: any) => r.
|
|
267
|
+
const applied = (data || []).map((r: any) => r.filename)
|
|
243
268
|
const appliedSet = new Set(applied)
|
|
244
|
-
const pending =
|
|
269
|
+
const pending = migrationFiles.filter(f => !appliedSet.has(f.name))
|
|
245
270
|
|
|
246
271
|
if (pending.length > 0) {
|
|
247
272
|
return {
|
|
248
273
|
name: 'migrations',
|
|
249
274
|
status: 'warn',
|
|
250
|
-
message: `${pending.length} pending migrations: ${pending.join(', ')}`,
|
|
251
|
-
details: { pending: pending.map(f => f.replace('.sql', '')), applied: applied.length },
|
|
275
|
+
message: `${pending.length} pending migrations: ${pending.map(f => f.name).join(', ')}`,
|
|
276
|
+
details: { pending: pending.map(f => f.name.replace('.sql', '')), applied: applied.length },
|
|
252
277
|
fixable: true
|
|
253
278
|
}
|
|
254
279
|
}
|
|
@@ -335,6 +360,83 @@ async function checkIntegrity(): Promise<CheckResult> {
|
|
|
335
360
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
336
361
|
// CIL[END stable_id="~/.framework/cli/commands/doctor.ts:checkIntegrity:function"]
|
|
337
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Verify the agent assets init/upgrade install: AGENTS.md carries a
|
|
365
|
+
* spine-framework marker block whose version matches the manifest's
|
|
366
|
+
* framework_version, and every spine-* skill file listed under the
|
|
367
|
+
* manifest's `agent_files` map exists and hashes clean.
|
|
368
|
+
*
|
|
369
|
+
* All mismatches are WARNINGS, never failures — agent assets are
|
|
370
|
+
* refreshable state (`npx spine-framework upgrade` re-syncs them), and
|
|
371
|
+
* customer edits outside the markers / non-spine-* skills must never
|
|
372
|
+
* degrade health. Runs from process.cwd() (the project root).
|
|
373
|
+
*/
|
|
374
|
+
async function checkAgentFiles(): Promise<CheckResult> {
|
|
375
|
+
const root = process.cwd()
|
|
376
|
+
const manifestPath = join(root, '.spine-manifest.json')
|
|
377
|
+
|
|
378
|
+
let manifest: any = null
|
|
379
|
+
try {
|
|
380
|
+
if (existsSync(manifestPath)) manifest = JSON.parse(readFileSync(manifestPath, 'utf8'))
|
|
381
|
+
} catch {
|
|
382
|
+
manifest = null
|
|
383
|
+
}
|
|
384
|
+
const agentFiles: Record<string, string> = manifest?.agent_files ?? {}
|
|
385
|
+
const expectedVersion: string | null = manifest?.framework_version ?? null
|
|
386
|
+
const problems: string[] = []
|
|
387
|
+
|
|
388
|
+
// AGENTS.md — marker block presence + version agreement.
|
|
389
|
+
const agentsPath = join(root, 'AGENTS.md')
|
|
390
|
+
if ('AGENTS.md' in agentFiles || existsSync(agentsPath)) {
|
|
391
|
+
if (!existsSync(agentsPath)) {
|
|
392
|
+
problems.push('AGENTS.md missing (manifest expects it)')
|
|
393
|
+
} else {
|
|
394
|
+
const text = readFileSync(agentsPath, 'utf8')
|
|
395
|
+
const range = findAgentsBlock(text.split(/\r?\n/))
|
|
396
|
+
if (!range) {
|
|
397
|
+
problems.push('AGENTS.md has no spine-framework marker block')
|
|
398
|
+
} else {
|
|
399
|
+
const blockVersion = agentsBlockVersion(text)
|
|
400
|
+
if (expectedVersion && blockVersion && blockVersion !== expectedVersion) {
|
|
401
|
+
problems.push(`AGENTS.md block is v${blockVersion}, project is v${expectedVersion}`)
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// spine-* skills — existence + hash vs manifest agent_files entries.
|
|
408
|
+
for (const [rel, hash] of Object.entries(agentFiles)) {
|
|
409
|
+
if (rel === 'AGENTS.md') continue
|
|
410
|
+
const abs = join(root, rel)
|
|
411
|
+
if (!existsSync(abs)) { problems.push(`${rel} missing`); continue }
|
|
412
|
+
try {
|
|
413
|
+
if (hashEntry({ rel, abs, symlink: false }) !== hash) {
|
|
414
|
+
problems.push(`${rel} modified`)
|
|
415
|
+
}
|
|
416
|
+
} catch {
|
|
417
|
+
problems.push(`${rel} unreadable`)
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (problems.length) {
|
|
422
|
+
return {
|
|
423
|
+
name: 'agent_files',
|
|
424
|
+
status: 'warn',
|
|
425
|
+
message: `Agent asset drift: ${problems.join('; ')}`,
|
|
426
|
+
details: { problems },
|
|
427
|
+
fixable: true,
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
const count = Object.keys(agentFiles).length
|
|
431
|
+
return {
|
|
432
|
+
name: 'agent_files',
|
|
433
|
+
status: 'pass',
|
|
434
|
+
message: count
|
|
435
|
+
? `Agent assets in sync (${count} manifest entries)`
|
|
436
|
+
: 'No agent assets tracked — this framework version predates agent_files',
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
338
440
|
// CIL[BEGIN stable_id="~/.framework/cli/commands/doctor.ts:checkTestRuns:function" type="function" identity="checkTestRuns" parent="~/.framework/cli/commands/doctor.ts"]
|
|
339
441
|
// CIL[DOC-MACRO purpose="Fetches the latest test run from the database."]
|
|
340
442
|
// CIL[DOC-RESPONSIBILITY responsibility="Report the status of the most recent test suite execution."]
|
|
@@ -351,7 +453,7 @@ async function checkTestRuns(): Promise<CheckResult> {
|
|
|
351
453
|
.select('suite, status, started_at')
|
|
352
454
|
.order('started_at', { ascending: false })
|
|
353
455
|
.limit(1)
|
|
354
|
-
.
|
|
456
|
+
.maybeSingle()
|
|
355
457
|
|
|
356
458
|
if (error) {
|
|
357
459
|
return {
|
|
@@ -502,7 +604,7 @@ async function tryFix(check: CheckResult): Promise<string> {
|
|
|
502
604
|
return 'Please set missing environment variables in .xenv or export them'
|
|
503
605
|
|
|
504
606
|
case 'migrations':
|
|
505
|
-
return 'Run `npx spine
|
|
607
|
+
return 'Run `npx spine-framework migrate` to apply pending migrations'
|
|
506
608
|
|
|
507
609
|
case 'integrity':
|
|
508
610
|
return 'Run `npm run manifest` to regenerate the integrity manifest'
|
|
@@ -513,6 +615,9 @@ async function tryFix(check: CheckResult): Promise<string> {
|
|
|
513
615
|
case 'runtime_wiring':
|
|
514
616
|
return 'Fix the dangling trigger/pipeline references listed in details (re-install the owning app or correct the type_slug / pipeline reference)'
|
|
515
617
|
|
|
618
|
+
case 'agent_files':
|
|
619
|
+
return 'Run `npx spine-framework upgrade` to re-sync AGENTS.md and .devin/skills/spine-*'
|
|
620
|
+
|
|
516
621
|
default:
|
|
517
622
|
return 'No automatic fix available'
|
|
518
623
|
}
|
|
@@ -613,6 +718,7 @@ export function registerDoctorCommands(program: Command) {
|
|
|
613
718
|
}
|
|
614
719
|
|
|
615
720
|
checks.push(await checkIntegrity())
|
|
721
|
+
checks.push(await checkAgentFiles())
|
|
616
722
|
|
|
617
723
|
|
|
618
724
|
const failed = checks.filter(c => c.status === 'fail').length
|
|
@@ -1,322 +1,62 @@
|
|
|
1
1
|
// CIL[BEGIN stable_id="~/.framework/cli/commands/generate.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/cli/commands/generate.ts"]
|
|
2
2
|
// CIL[DOC-AUDIENCE audience="internal, cli-users"]
|
|
3
|
-
// CIL[DOC-MACRO purpose="
|
|
4
|
-
// CIL[DOC-RESPONSIBILITY responsibility="
|
|
5
|
-
// CIL[DOC-CONTEXT module=".framework/cli/commands/generate" layer="app-specific" related_files=".framework/cli/
|
|
6
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="
|
|
7
|
-
// CIL[DOC-MICRO logic_summary="
|
|
8
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.
|
|
9
|
-
// CIL[DOC-STABILITY
|
|
10
|
-
|
|
3
|
+
// CIL[DOC-MACRO purpose="Deprecated stub: the legacy 'generate' scaffold was removed; the command stays registered so callers get a clear migration message instead of writes to a dead v2-custom/ tree"]
|
|
4
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Register the 'generate' command and fail fast with guidance"]
|
|
5
|
+
// CIL[DOC-CONTEXT module=".framework/cli/commands/generate" layer="app-specific" related_files=".framework/cli/commands/create-app.ts,.framework/cli/commands/validate-schema.ts"]
|
|
6
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="registered deprecated command" errors="always exits non-zero when invoked" side_effects="prints removal notice to stderr"]
|
|
7
|
+
// CIL[DOC-MICRO logic_summary="Prints a removal notice pointing at create-app, the admin UI, and validate-schema, then exits with code 1" notable_decisions="Not aliased to create-app: generate created a type record + v2-custom stubs, create-app scaffolds custom/apps/<slug>/ — different semantics"]
|
|
8
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
9
|
+
// CIL[DOC-STABILITY deprecated]
|
|
11
10
|
|
|
12
11
|
import type { Command } from 'commander'
|
|
13
|
-
import { buildCliContext, handleError } from '../context.ts'
|
|
14
|
-
import { adminDb } from '../../functions/_shared/index.ts'
|
|
15
|
-
import { existsSync, mkdirSync, writeFileSync } from 'fs'
|
|
16
|
-
import { resolve, dirname } from 'path'
|
|
17
|
-
import { fileURLToPath } from 'url'
|
|
18
|
-
|
|
19
|
-
// CIL[DOC-VECTOR type="context" content="purpose='Provide CLI commands for generating database types, handler stubs, and UI page stubs'; No verified external callers; imports: .framework/cli/context.ts,.framework/functions/_shared/index.ts"]
|
|
20
|
-
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
21
|
-
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
22
|
-
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
23
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
24
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
25
12
|
// CIL[END stable_id="~/.framework/cli/commands/generate.ts:module_header:module_header"]
|
|
26
|
-
// CIL[BEGIN stable_id="~/.framework/cli/commands/generate.ts:__filename:constant" type="constant" identity="__filename" parent="~/.framework/cli/commands/generate.ts"]
|
|
27
|
-
// CIL[DOC-MACRO purpose="Derive the current module's file path for ESM modules"]
|
|
28
|
-
// CIL[DOC-RESPONSIBILITY responsibility="Hold the resolved __filename for path operations"]
|
|
29
|
-
// CIL[DOC-STABILITY stability="internal"]
|
|
30
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
31
|
-
// CIL[DOC-CONTEXT module=".framework/cli/commands/generate" layer="app-specific" related_files=".framework/cli/commands/generate.ts,.framework/cli/context.ts,.framework/functions/_shared/index.ts"]
|
|
32
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="string __filename" errors="none" side_effects="none"]
|
|
33
|
-
// CIL[DOC-MICRO logic_summary="Calls fileURLToPath on import.meta.url" notable_decisions=""]
|
|
34
|
-
const __filename = fileURLToPath(import.meta.url)
|
|
35
|
-
// CIL[END stable_id="~/.framework/cli/commands/generate.ts:__filename:constant"]
|
|
36
|
-
// CIL[BEGIN stable_id="~/.framework/cli/commands/generate.ts:__dirname:constant" type="constant" identity="__dirname" parent="~/.framework/cli/commands/generate.ts"]
|
|
37
|
-
// CIL[DOC-VECTOR type="context" content="purpose='Derive the current module's file path for ESM modules'; No verified external callers; imports: .framework/cli/context.ts,.framework/functions/_shared/index.ts"]
|
|
38
|
-
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
39
|
-
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
40
|
-
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
41
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
42
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
43
|
-
// CIL[DOC-MACRO purpose="Derive the current module's directory name for relative path resolution"]
|
|
44
|
-
// CIL[DOC-RESPONSIBILITY responsibility="Hold the resolved __dirname for directory operations"]
|
|
45
|
-
// CIL[DOC-CONTEXT module=".framework/cli/commands/generate" layer="app-specific" related_files=".framework/cli/commands/generate.ts,.framework/cli/context.ts,.framework/functions/_shared/index.ts"]
|
|
46
|
-
// CIL[DOC-STABILITY stability="internal"]
|
|
47
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
48
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="string __dirname" errors="none" side_effects="none"]
|
|
49
|
-
// CIL[DOC-MICRO logic_summary="Applies dirname to the resolved __filename" notable_decisions=""]
|
|
50
|
-
const __dirname = dirname(__filename)
|
|
51
|
-
// CIL[END stable_id="~/.framework/cli/commands/generate.ts:__dirname:constant"]
|
|
52
|
-
// CIL[BEGIN stable_id="~/.framework/cli/commands/generate.ts:PROJECT_ROOT:constant" type="constant" identity="PROJECT_ROOT" parent="~/.framework/cli/commands/generate.ts"]
|
|
53
|
-
// CIL[DOC-VECTOR type="context" content="purpose='Derive the current module's directory name for relative path resolution'; No verified external callers; imports: .framework/cli/context.ts,.framework/functions/_shared/index.ts"]
|
|
54
|
-
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
55
|
-
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
56
|
-
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
57
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
58
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
59
|
-
// CIL[DOC-MACRO purpose="Resolve the absolute project root directory for file operations"]
|
|
60
|
-
// CIL[DOC-RESPONSIBILITY responsibility="Hold the resolved project root path for stub generation"]
|
|
61
|
-
// CIL[DOC-CONTEXT module=".framework/cli/commands/generate" layer="app-specific" related_files=".framework/cli/commands/generate.ts,.framework/cli/context.ts,.framework/functions/_shared/index.ts"]
|
|
62
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="string PROJECT_ROOT" errors="none" side_effects="none"]
|
|
63
|
-
// CIL[DOC-MICRO logic_summary="Resolves __dirname three levels up to reach project root" notable_decisions=""]
|
|
64
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
65
|
-
// CIL[DOC-STABILITY stable]
|
|
66
|
-
const PROJECT_ROOT = resolve(__dirname, '../../../')
|
|
67
|
-
// CIL[DOC-VECTOR type="context" content="purpose='Resolve the absolute project root directory for file operations'; No verified external callers; imports: .framework/cli/context.ts,.framework/functions/_shared/index.ts"]
|
|
68
|
-
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
69
|
-
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
70
|
-
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
71
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
72
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
73
|
-
// CIL[END stable_id="~/.framework/cli/commands/generate.ts:PROJECT_ROOT:constant"]
|
|
74
|
-
|
|
75
|
-
// CIL[BEGIN stable_id="~/.framework/cli/commands/generate.ts:generateType:function" type="function" identity="generateType" parent="~/.framework/cli/commands/generate.ts"]
|
|
76
|
-
// CIL[DOC-MACRO purpose="Generate a new database type and create handler and UI page stubs"]
|
|
77
|
-
// CIL[DOC-RESPONSIBILITY responsibility="Check for existing type, insert a new record, and write handler and page stub files"]
|
|
78
|
-
// CIL[DOC-CONTEXT module=".framework/cli/commands/generate" layer="app-specific" related_files=".framework/cli/commands/generate.ts,.framework/cli/context.ts,.framework/functions/_shared/index.ts"]
|
|
79
|
-
// CIL[DOC-CONTRACT inputs="ctx: any, slug: string, options: any" outputs="Promise<void>" errors="Error on DB check/insert failure; skip if type exists" side_effects="Writes to the database and filesystem"]
|
|
80
|
-
// CIL[DOC-MICRO logic_summary="Builds name/kind/description, checks for an existing type, inserts the design schema, and writes handler and page files unless present or force=true" notable_decisions="Defaults kind to 'item' and status options to open/in_progress/closed"]
|
|
81
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
82
|
-
// CIL[DOC-STABILITY stable]
|
|
83
|
-
async function generateType(ctx: any, slug: string, options: any): Promise<void> {
|
|
84
|
-
const name = options.name || slug.split('-').map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(' ')
|
|
85
|
-
const kind = options.kind || 'item'
|
|
86
|
-
const description = options.description || `${name} type generated by spine CLI`
|
|
87
|
-
|
|
88
|
-
console.log(`\n🔧 Generating type '${slug}'...`)
|
|
89
|
-
|
|
90
|
-
const { data: existing, error: checkErr } = await adminDb
|
|
91
|
-
.from('types')
|
|
92
|
-
.select('id')
|
|
93
|
-
.eq('slug', slug)
|
|
94
|
-
.eq('kind', kind)
|
|
95
|
-
.single()
|
|
96
|
-
|
|
97
|
-
if (checkErr && checkErr.code !== 'PGRST116') {
|
|
98
|
-
throw new Error(`Failed to check existing type: ${checkErr.message}`)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (existing) {
|
|
102
|
-
console.log(` ⚠️ Type '${slug}' already exists (skipping DB creation)`)
|
|
103
|
-
} else {
|
|
104
|
-
const designSchema = {
|
|
105
|
-
fields: {
|
|
106
|
-
title: {
|
|
107
|
-
type: 'string',
|
|
108
|
-
required: true,
|
|
109
|
-
label: 'Title',
|
|
110
|
-
description: `Title for this ${name}`
|
|
111
|
-
},
|
|
112
|
-
status: {
|
|
113
|
-
type: 'select',
|
|
114
|
-
options: ['open', 'in_progress', 'closed'],
|
|
115
|
-
default: 'open',
|
|
116
|
-
label: 'Status'
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
layout: {
|
|
120
|
-
detail: ['title', 'status'],
|
|
121
|
-
list: ['title', 'status']
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const { error: insertErr } = await adminDb
|
|
126
|
-
.from('types')
|
|
127
|
-
.insert({
|
|
128
|
-
kind,
|
|
129
|
-
slug,
|
|
130
|
-
name,
|
|
131
|
-
description,
|
|
132
|
-
design_schema: designSchema,
|
|
133
|
-
validation_schema: {},
|
|
134
|
-
ownership: 'system',
|
|
135
|
-
is_active: true
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
if (insertErr) {
|
|
139
|
-
throw new Error(`Failed to create type: ${insertErr.message}`)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
console.log(' ✓ Type record created')
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const handlerPath = resolve(PROJECT_ROOT, `v2-custom/functions/${slug}.ts`)
|
|
146
|
-
|
|
147
|
-
if (existsSync(handlerPath) && !options.force) {
|
|
148
|
-
console.log(` ⚠️ Handler stub already exists: ${handlerPath}`)
|
|
149
|
-
} else {
|
|
150
|
-
const handlerCode = generateHandlerStub(slug, kind, name)
|
|
151
|
-
writeFileSync(handlerPath, handlerCode)
|
|
152
|
-
console.log(` ✓ Handler stub created: v2-custom/functions/${slug}.ts`)
|
|
153
|
-
}
|
|
154
13
|
|
|
155
|
-
|
|
156
|
-
const pagePath = resolve(pageDir, 'index.tsx')
|
|
157
|
-
|
|
158
|
-
if (existsSync(pagePath) && !options.force) {
|
|
159
|
-
console.log(` ⚠️ UI page stub already exists: ${pagePath}`)
|
|
160
|
-
} else {
|
|
161
|
-
mkdirSync(pageDir, { recursive: true })
|
|
162
|
-
const pageCode = generatePageStub(slug, name, kind)
|
|
163
|
-
writeFileSync(pagePath, pageCode)
|
|
164
|
-
console.log(` ✓ UI page stub created: v2-custom/src/pages/${slug}/index.tsx`)
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
console.log(`\n✅ Type '${slug}' generation complete!`)
|
|
168
|
-
console.log(` Next steps:`)
|
|
169
|
-
console.log(` 1. Edit v2-custom/functions/${slug}.ts to implement custom logic`)
|
|
170
|
-
console.log(` 2. Edit v2-custom/src/pages/${slug}/index.tsx to customize the UI`)
|
|
171
|
-
console.log(` 3. Run 'spine dev' to see your changes`)
|
|
172
|
-
}
|
|
173
|
-
// CIL[DOC-VECTOR type="context" content="purpose='Generate a new database type and create handler and UI page stubs'; No verified external callers; imports: .framework/cli/context.ts,.framework/functions/_shared/index.ts"]
|
|
14
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Deprecated stub for the removed generate scaffold'; No verified external callers; imports: none"]
|
|
174
15
|
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
175
16
|
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
176
17
|
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
177
18
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
178
19
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
179
|
-
// CIL[END stable_id="~/.framework/cli/commands/generate.ts:generateType:function"]
|
|
180
|
-
|
|
181
|
-
// CIL[BEGIN stable_id="~/.framework/cli/commands/generate.ts:generateHandlerStub:function" type="function" identity="generateHandlerStub" parent="~/.framework/cli/commands/generate.ts"]
|
|
182
|
-
// CIL[DOC-MACRO purpose="Generate a custom API handler stub string for a type"]
|
|
183
|
-
// CIL[DOC-RESPONSIBILITY responsibility="Return a templated handler function using createHandler"]
|
|
184
|
-
// CIL[DOC-CONTEXT module=".framework/cli/commands/generate" layer="app-specific" related_files=".framework/cli/commands/generate.ts,.framework/cli/context.ts,.framework/functions/_shared/index.ts"]
|
|
185
|
-
// CIL[DOC-CONTRACT inputs="slug: string, kind: string, name: string" outputs="string handler code" errors="Error for unsupported HTTP method at runtime" side_effects="none"]
|
|
186
|
-
// CIL[DOC-MICRO logic_summary="Builds a handler template with a switch for GET/POST/PATCH/DELETE methods" notable_decisions="Uses new Date().toISOString() in the generated header comment"]
|
|
187
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
188
|
-
// CIL[DOC-STABILITY experimental]
|
|
189
|
-
function generateHandlerStub(slug: string, kind: string, name: string): string {
|
|
190
|
-
return `/**
|
|
191
|
-
* @module ${slug}
|
|
192
|
-
* @audience custom
|
|
193
|
-
* @layer api-handler
|
|
194
|
-
* @stability experimental
|
|
195
|
-
*
|
|
196
|
-
* Custom handler for ${name} (${kind} type).
|
|
197
|
-
* Generated by spine CLI on ${new Date().toISOString()}.
|
|
198
|
-
*
|
|
199
|
-
* Extend this handler to add custom logic for your type.
|
|
200
|
-
*/
|
|
201
|
-
|
|
202
|
-
import { createHandler } from '../v2-core/functions/_shared/middleware'
|
|
203
|
-
|
|
204
|
-
export const handler = createHandler(async (ctx) => {
|
|
205
|
-
const method = ctx.query?.method || 'GET'
|
|
206
|
-
|
|
207
|
-
switch (method) {
|
|
208
|
-
case 'GET':
|
|
209
|
-
return { message: '${name} handler - GET not implemented' }
|
|
210
|
-
|
|
211
|
-
case 'POST':
|
|
212
|
-
return { message: '${name} handler - POST not implemented' }
|
|
213
20
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
230
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
231
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
232
|
-
// CIL[END stable_id="~/.framework/cli/commands/generate.ts:generateHandlerStub:function"]
|
|
233
|
-
|
|
234
|
-
// CIL[BEGIN stable_id="~/.framework/cli/commands/generate.ts:generatePageStub:function" type="function" identity="generatePageStub" parent="~/.framework/cli/commands/generate.ts"]
|
|
235
|
-
// CIL[DOC-MACRO purpose="Generate a React page stub string for a type"]
|
|
236
|
-
// CIL[DOC-RESPONSIBILITY responsibility="Return a React component template that fetches and displays record data"]
|
|
237
|
-
// CIL[DOC-CONTEXT module=".framework/cli/commands/generate" layer="app-specific" related_files=".framework/cli/commands/generate.ts,.framework/cli/context.ts,.framework/functions/_shared/index.ts"]
|
|
238
|
-
// CIL[DOC-CONTRACT inputs="slug: string, name: string, kind: string" outputs="string React component code" errors="Error on failed API fetch at runtime" side_effects="none (generated string only)"]
|
|
239
|
-
// CIL[DOC-MICRO logic_summary="Builds a React page template using useParams, useApi, and apiFetch" notable_decisions="Uses new Date().toISOString() in the generated header comment"]
|
|
240
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
241
|
-
// CIL[DOC-STABILITY experimental]
|
|
242
|
-
function generatePageStub(slug: string, name: string, kind: string): string {
|
|
243
|
-
return `/**
|
|
244
|
-
* @page ${slug}/index
|
|
245
|
-
* @audience custom
|
|
246
|
-
* @layer page
|
|
247
|
-
* @stability experimental
|
|
248
|
-
*
|
|
249
|
-
* UI page for ${name} (${kind} type).
|
|
250
|
-
* Generated by spine CLI on ${new Date().toISOString()}.
|
|
251
|
-
*/
|
|
252
|
-
|
|
253
|
-
import React from 'react'
|
|
254
|
-
import { useParams } from 'react-router-dom'
|
|
255
|
-
import { useApi } from '../../v2-core/src/hooks/useApi'
|
|
256
|
-
import { apiFetch } from '../../v2-core/src/lib/api'
|
|
21
|
+
// CIL[DOC-MACRO purpose="Register the deprecated 'generate' command so invocations fail with a clear removal notice"]
|
|
22
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Wire the deprecated generate command into the program"]
|
|
23
|
+
// CIL[DOC-CONTEXT module=".framework/cli/commands/generate" layer="app-specific" related_files=".framework/cli/commands/create-app.ts"]
|
|
24
|
+
// CIL[DOC-CONTRACT inputs="program: Command" outputs="void" errors="always exits 1 on invocation" side_effects="Registers a command and prints guidance to stderr"]
|
|
25
|
+
// CIL[DOC-MICRO logic_summary="Defines 'generate [slug]' whose action prints the removal notice and exits 1" notable_decisions="Exit 1 (non-zero) so scripts fail loudly rather than silently writing nothing"]
|
|
26
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
27
|
+
// CIL[DOC-STABILITY deprecated]
|
|
28
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/generate.ts:registerGenerateCommands:function" type="function" identity="registerGenerateCommands" parent="~/.framework/cli/commands/generate.ts"]
|
|
29
|
+
export function registerGenerateCommands(program: Command) {
|
|
30
|
+
program
|
|
31
|
+
.command('generate [slug]')
|
|
32
|
+
.description('Removed — legacy v2 scaffold no longer exists (prints migration guidance)')
|
|
33
|
+
.action(() => {
|
|
34
|
+
console.error(`
|
|
35
|
+
❌ 'spine-framework generate' was removed.
|
|
257
36
|
|
|
258
|
-
|
|
259
|
-
|
|
37
|
+
The old scaffold wrote type/handler/page stubs into a 'v2-custom/' tree
|
|
38
|
+
and emitted a legacy design_schema shape — neither exists in this layout.
|
|
260
39
|
|
|
261
|
-
|
|
262
|
-
() => apiFetch('/.netlify/functions/${slug}' + (id ? '?id=' + id : '')),
|
|
263
|
-
{ immediate: true }
|
|
264
|
-
)
|
|
40
|
+
To get the same outcome today:
|
|
265
41
|
|
|
266
|
-
|
|
267
|
-
|
|
42
|
+
• New app: spine-framework create-app <slug>
|
|
43
|
+
(scaffolds custom/apps/<slug>/ + registers the app)
|
|
268
44
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
{JSON.stringify(data, null, 2)}
|
|
274
|
-
</pre>
|
|
275
|
-
<p className="mt-4 text-gray-600">
|
|
276
|
-
Edit v2-custom/src/pages/${slug}/index.tsx to customize this page.
|
|
277
|
-
</p>
|
|
278
|
-
</div>
|
|
279
|
-
)
|
|
280
|
-
}
|
|
281
|
-
`
|
|
282
|
-
}
|
|
283
|
-
// CIL[END stable_id="~/.framework/cli/commands/generate.ts:generatePageStub:function"]
|
|
45
|
+
• New type: author design_schema JSON, then either
|
|
46
|
+
- create it in the admin UI (Spine Admin → Types), or
|
|
47
|
+
- POST it to /api/types
|
|
48
|
+
Validate first: spine-framework validate-schema <file.json>
|
|
284
49
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
290
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
291
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
292
|
-
// CIL[DOC-MACRO purpose="Register the generate CLI command with the Commander program"]
|
|
293
|
-
// CIL[DOC-RESPONSIBILITY responsibility="Wire the generate command, options, and action into the program"]
|
|
294
|
-
// CIL[DOC-CONTEXT module=".framework/cli/commands/generate" layer="app-specific" related_files=".framework/cli/commands/generate.ts,.framework/cli/context.ts,.framework/functions/_shared/index.ts"]
|
|
295
|
-
// CIL[DOC-CONTRACT inputs="program: Command" outputs="void" errors="none (handled by handleError)" side_effects="Adds command and action to the program"]
|
|
296
|
-
// CIL[DOC-MICRO logic_summary="Attaches the 'generate <slug>' command with options and an async action that builds context and calls generateType" notable_decisions="Defaults kind to 'item' and passes parsed options to generateType"]
|
|
297
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
298
|
-
// CIL[DOC-STABILITY stable]
|
|
299
|
-
export function registerGenerateCommands(program: Command) {
|
|
300
|
-
program
|
|
301
|
-
.command('generate <slug>')
|
|
302
|
-
.description('Generate type, handler, and UI stubs')
|
|
303
|
-
.option('--name <name>', 'Human-readable name')
|
|
304
|
-
.option('--kind <kind>', 'Type kind', 'item')
|
|
305
|
-
.option('--description <description>', 'Type description')
|
|
306
|
-
.option('--force', 'Overwrite existing files', false)
|
|
307
|
-
.action(async (slug, opts) => {
|
|
308
|
-
try {
|
|
309
|
-
const ctx = await buildCliContext()
|
|
310
|
-
await generateType(ctx, slug, opts)
|
|
311
|
-
} catch (err: any) {
|
|
312
|
-
handleError(err)
|
|
313
|
-
}
|
|
50
|
+
• Custom logic: put functions in custom/apps/<slug>/functions/ — they are
|
|
51
|
+
picked up by 'npm run assemble' automatically.
|
|
52
|
+
`)
|
|
53
|
+
process.exit(1)
|
|
314
54
|
})
|
|
315
55
|
}
|
|
316
|
-
// CIL[
|
|
56
|
+
// CIL[END stable_id="~/.framework/cli/commands/generate.ts:registerGenerateCommands:function"]
|
|
57
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Register the deprecated generate command'; No verified external callers; imports: none"]
|
|
317
58
|
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
318
59
|
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
319
60
|
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
320
61
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
321
62
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
322
|
-
// CIL[END stable_id="~/.framework/cli/commands/generate.ts:registerGenerateCommands:function"]
|