@fastintent/engine
v0.4.0-alpha.0
Published
Declarative schema-first engine: FDML → canonical AST → SQL + TypeScript SDK + UI schemas.
Downloads
249
Readme
intent-engine
Motor declarativo schema-first: FDML → AST canónico → SQL Postgres + TypeScript SDK + UI schemas.
Reemplaza
OWNERen los badges cuando el repo tenga origen remoto.
Estado actual (2026-04-23)
Hibernado como escalón. El motor está cerrado al feature creep. La superficie que hay hoy es la única superficie soportada hasta que el editor (editor-plasmic) retome AppGraph y pida integración programática concreta vía AI_AGENT_SPEC.
- Consumidor hoy: ninguno programático.
editor-plasmicleeclient.schema.jsoncomo artefacto JSON;image-to-codeinvoca el motor solo por CLI. No hayimportruntime desde el editor. - Consumidor planeado: el propio editor, cuando implemente AppGraph (plan→preview→materialize estilo Terraform). Ver
/Users/soporte/rust/editor-plasmic/APPGRAPH_PLAN.mdFase 1.1 — contrato de integración vive enspecs/AI_AGENT_SPEC.ts(pendiente de crear cuando AppGraph arranque). - Weaver (
editor-plasmic/app/api/weaver/) es compilador hermano independiente hoy; con AppGraph se convierte en el brazo de materialización que delega schema al motor ("el editor con super poderes"). - ShellChat (prompt → schema completo) queda fuera de scope: el editor + Weaver + AppGraph cubren ese caso sin proyecto separado.
Visión IntentOS (contexto estratégico)
Este motor es la capa de datos de una arquitectura de 4 capas:
- FastDev (Data Layer) — este repo. FDML → SQL + tipos + UI schemas.
- UI AST (View Layer) —
editor-plasmic. Bloques visuales → código Next.js. - BDML (Business Layer) — reglas de dominio, RBAC, flujos. Integrado parcialmente en el editor.
- Orchestrator (Cognitive Layer) — AppGraph + Weaver. Intent prompt → plan → preview → materialize.
El motor no aspira a resolver las 4 capas. Solo blinda la primera con determinismo y tests.
Documento histórico de la visión: docs/archive/IntentOS.md.
Cobertura real
| Capa | Stmts | Branch | Observaciones |
|------|-------|--------|---------------|
| normalizer/ | 92.85% | 85.85% | FDML → AST canónico |
| compiler/sql/ | 96.55% | 87.83% | SQLCompiler + MigrationCompiler + PostgresDialect |
| compiler/ts/ | 90.95% | 89.60% | TypeGenerator + QueryBuilder + UISchemaGenerator |
| planner/ | 93.10% | 79.22% | Planner + PolicyEngine + StrategyEngine + MigrationSimulator + ExecutionEngine + ReconciliationEngine |
| specs/ | 100% (diagnostics · utils · query) | — | EngineDiagnostics + SchemaUtils + QUERY_SPEC |
Suite: 436 tests · 41 archivos · ~43 s. Thresholds enforzados en CI: 93/85/93/93 (stmts/branch/funcs/lines).
Arquitectura (4 capas puras)
- Normalizer (
normalizer/) — FDML → AST canónico inmutable.irVersion: 1.0.0congelado. - Planner (
planner/) — Diff AST actual vs propuesto →ExecutionPlanvalidado porPolicyEngine. IncluyeStrategyEngine(costo + riesgo),MigrationSimulator(impacto),ExecutionEngine(apply + rollback),ReconciliationEngine(reusar identidad en renames). - Compiler (
compiler/sql/+compiler/ts/) — AST → SQL Postgres + TypeScript types + QueryBuilder + UI schemas. - Connector (
cli/· tipado separado) — capa física.tsconfig.cli.jsonsepara su module resolution del principal. Desde §R1 (2026-04-23) typecheck CLI es BLOCKING en CI.
src/index.ts expone las 3 primeras capas como API pública. src/planner.ts expone subsistemas del planner.
Superficie pública (package.json#exports)
{
".": "dist/src/index.js",
"./planner": "dist/src/planner.js",
"./spec": "dist/specs/INTENT_SPEC.js"
}Superficie mínima intencional. Cualquier ampliación requiere consumidor real que la motive.
Qué hace hoy
- Compilar FDML a SQL Postgres ejecutable (
CREATE TABLE,FK,INDEX,ENUM,RLS,timestamps,soft-delete,manyToMany). - Generar tipos TypeScript + QueryBuilder + UI schemas desde el mismo AST.
- Diffear modelos y producir
ExecutionPlan(up/down) conshadow columnsyexpand-and-contract. - Detectar y bloquear:
- bloqueos en tabla (
allowBlocking=false) - acciones destructivas en producción
drop_tablecon FKs entrantes en el mismo plan
- bloqueos en tabla (
- Simular impacto con
MigrationSimulator(row counts, lock recommendations, duración estimada). - Aplicar + revertir con
ExecutionEngine(checkpoints, rollback granular). EngineDiagnostics(doctor): detecta drift, migraciones fantasma, corrupción de checksums. Falla graceful si el driver no expone historial.- CLI (
cli/):plan,apply --dry-run,generate-types,doctor. Usado hoy porimage-to-codemanualmente.
Qué NO hace hoy (y no va a hacer sin consumidor real)
- No hay integración AppGraph.
specs/AI_AGENT_SPEC.tsno existe todavía. Se crea cuando el editor lo pida. - No hay ShellChat ni prompt-to-schema directo. Ese camino se sirve vía editor + Weaver, no vía este motor.
- Sin locks distribuidos, sin telemetría, sin disaster recovery. Si no está en la tabla de cobertura, trátelo como no-implementado.
- Sin dialectos no-Postgres ejecutables.
mysql2/better-sqlite3/sqliteviven enpackage.jsonpero solo Postgres (vía PGlite) tiene cobertura real.
Instalación y desarrollo
Requisitos: Node ≥ 20, pnpm 10.
pnpm install
pnpm test # 436 tests, ~43s
pnpm test:coverage # con thresholds enforzados (93/85/93/93)
pnpm typecheck # tsconfig principal (incluye planner/ y compiler/)
pnpm typecheck:cli # BLOCKING desde §R1 cierre
pnpm lint # 0 errores / 0 warnings enforzados
pnpm ci # lint + typecheck + typecheck:cli + test:coveragePolíticas de lint (ver eslint.config.mjs):
no-unused-vars: errorconargsIgnorePattern: ^_no-explicit-any: off(polimorfismo intencional enMigrationAction)consistent-type-imports: erroreqeqeq: errorcon{ null: "ignore" }(idiom TS:x != nullcubre null y undefined)
Blindajes del motor (qué garantiza la suite)
| # | Blindaje | Dónde vive |
|---|----------|-----------|
| 1 | Snapshot guard estructural (no basta con -u) | Planner.test.ts |
| 2 | planner(M,M) es idempotente | Planner.test.ts |
| 3 | MigrationSimulator aislado entre runs + recovery tras throw | MigrationSimulator.test.ts |
| 4 | PolicyEngine bloquea drop_table con FK entrantes o en producción | PolicyEngine.test.ts |
| 5 | Orden: create_table < add_constraint en up, inverso en down | Planner.test.ts |
| 6 | EngineDiagnostics "modo sucio" (conn fail, ghost migrations, múltiples corrupciones) | EngineDiagnostics.test.ts |
| 7 | Escenario complejo real: rename + type change + FK + datos preservados | tests/e2e/planner-scenarios.test.ts |
| 8 | Reversibilidad fuerte: apply(up) + apply(down) regresa al esquema original | tests/e2e/planner-scenarios.test.ts |
| 9 | StrategyEngine property-based: 200 combinaciones random → shape válida siempre | StrategyEngine.test.ts |
| 10 | PostgresDialect combinaciones reales: timestamps + softDelete + RLS + reserved + tipos exóticos | PostgresDialect.combinations.test.ts |
| 11 | Plan-size budget guard: refactors que inflan el plan rompen CI | Planner.test.ts |
| 12 | ExecutionEngine rollback real contra PGlite | ExecutionEngine.test.ts |
| 13 | ReconciliationEngine preserva identidad en renames ambiguos | ReconciliationEngine.test.ts |
Archivos clave
specs/CANONICAL_SCHEMA_SPEC.ts— el AST canónico (congelado,irVersion: 1.0.0).specs/INTENT_SPEC.ts— acciones de migración tipadas.planner/Planner.ts— diff engine.planner/PolicyEngine.ts— guardrails.planner/postgresStrategyModel.ts— reglas declarativas de costo/riesgo Postgres.compiler/sql/dialects/PostgresDialect.ts— único dialecto con cobertura real.tests/helpers/{at,model,context}.ts— builders para escribir tests sin boilerplate.
Deuda conocida (documentada)
- §5bis(3) —
topologicalSortO(n²) ennormalizer/Normalizer.ts:326. Funcionalmente correcto; refactor a Kahn O(V+E) pendiente cuando haya cargas > 10 entidades. No bloquea hibernación.
Toda la deuda previa (§4.1–§4.7) quedó cerrada en el cierre §R1 (2026-04-23).
Nota histórica
Versiones previas emitían MigrationCompiler.create_table sin PRIMARY KEY/DEFAULT/UNIQUE — FK entrante fallaba con no unique constraint matching given keys. Detectado contra Neon el 2026-04-11. La Fase 4 reusó compileFieldDefinition entre SQLCompiler y MigrationCompiler y añadió tests de integración PGlite. Blindado desde entonces.
El CHANGELOG recoge el resto del camino.
Licencia
Ver LICENSE en la raíz del repo (si no existe, pendiente de añadir — el paquete es alpha).
