@stevenvo780/autologic 2.0.0 → 2.2.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.
Files changed (105) hide show
  1. package/README.md +2 -0
  2. package/dist/atoms/index.d.ts +1 -1
  3. package/dist/atoms/index.d.ts.map +1 -1
  4. package/dist/atoms/index.js +91 -3
  5. package/dist/atoms/index.js.map +1 -1
  6. package/dist/atoms/keyword-extractor.d.ts +9 -0
  7. package/dist/atoms/keyword-extractor.d.ts.map +1 -1
  8. package/dist/atoms/keyword-extractor.js +64 -2
  9. package/dist/atoms/keyword-extractor.js.map +1 -1
  10. package/dist/atoms/math-parser.d.ts +11 -0
  11. package/dist/atoms/math-parser.d.ts.map +1 -0
  12. package/dist/atoms/math-parser.js +44 -0
  13. package/dist/atoms/math-parser.js.map +1 -0
  14. package/dist/compiler-frontend.d.ts +9 -0
  15. package/dist/compiler-frontend.d.ts.map +1 -0
  16. package/dist/compiler-frontend.js +142 -0
  17. package/dist/compiler-frontend.js.map +1 -0
  18. package/dist/context/discourse-state.d.ts +10 -0
  19. package/dist/context/discourse-state.d.ts.map +1 -0
  20. package/dist/context/discourse-state.js +26 -0
  21. package/dist/context/discourse-state.js.map +1 -0
  22. package/dist/discourse/markers-es.d.ts.map +1 -1
  23. package/dist/discourse/markers-es.js +23 -0
  24. package/dist/discourse/markers-es.js.map +1 -1
  25. package/dist/discourse/pattern-detector.d.ts.map +1 -1
  26. package/dist/discourse/pattern-detector.js +2 -1
  27. package/dist/discourse/pattern-detector.js.map +1 -1
  28. package/dist/discourse/role-classifier.js +38 -6
  29. package/dist/discourse/role-classifier.js.map +1 -1
  30. package/dist/formalize.d.ts +16 -0
  31. package/dist/formalize.d.ts.map +1 -1
  32. package/dist/formalize.js +128 -0
  33. package/dist/formalize.js.map +1 -1
  34. package/dist/formula/argument-builder.d.ts.map +1 -1
  35. package/dist/formula/argument-builder.js +124 -15
  36. package/dist/formula/argument-builder.js.map +1 -1
  37. package/dist/formula/ast-compiler.d.ts +6 -0
  38. package/dist/formula/ast-compiler.d.ts.map +1 -0
  39. package/dist/formula/ast-compiler.js +105 -0
  40. package/dist/formula/ast-compiler.js.map +1 -0
  41. package/dist/formula/ast.d.ts +81 -0
  42. package/dist/formula/ast.d.ts.map +1 -0
  43. package/dist/formula/ast.js +52 -0
  44. package/dist/formula/ast.js.map +1 -0
  45. package/dist/formula/connectors.js +1 -1
  46. package/dist/formula/connectors.js.map +1 -1
  47. package/dist/formula/first-order.js +74 -7
  48. package/dist/formula/first-order.js.map +1 -1
  49. package/dist/formula/helpers.d.ts +8 -0
  50. package/dist/formula/helpers.d.ts.map +1 -0
  51. package/dist/formula/helpers.js +166 -0
  52. package/dist/formula/helpers.js.map +1 -0
  53. package/dist/formula/index.d.ts +1 -0
  54. package/dist/formula/index.d.ts.map +1 -1
  55. package/dist/formula/index.js +5 -3
  56. package/dist/formula/index.js.map +1 -1
  57. package/dist/formula/modal.d.ts.map +1 -1
  58. package/dist/formula/modal.js +56 -67
  59. package/dist/formula/modal.js.map +1 -1
  60. package/dist/formula/probabilistic.d.ts +3 -0
  61. package/dist/formula/probabilistic.d.ts.map +1 -0
  62. package/dist/formula/probabilistic.js +55 -0
  63. package/dist/formula/probabilistic.js.map +1 -0
  64. package/dist/formula/propositional.d.ts +2 -2
  65. package/dist/formula/propositional.d.ts.map +1 -1
  66. package/dist/formula/propositional.js +99 -88
  67. package/dist/formula/propositional.js.map +1 -1
  68. package/dist/formula/temporal.d.ts.map +1 -1
  69. package/dist/formula/temporal.js +87 -62
  70. package/dist/formula/temporal.js.map +1 -1
  71. package/dist/generator/validator.d.ts +20 -0
  72. package/dist/generator/validator.d.ts.map +1 -1
  73. package/dist/generator/validator.js +112 -0
  74. package/dist/generator/validator.js.map +1 -1
  75. package/dist/index.d.ts +6 -17
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +8 -17
  78. package/dist/index.js.map +1 -1
  79. package/dist/llm-parser.d.ts +29 -0
  80. package/dist/llm-parser.d.ts.map +1 -0
  81. package/dist/llm-parser.js +122 -0
  82. package/dist/llm-parser.js.map +1 -0
  83. package/dist/local-slm-web.d.ts +8 -0
  84. package/dist/local-slm-web.d.ts.map +1 -0
  85. package/dist/local-slm-web.js +87 -0
  86. package/dist/local-slm-web.js.map +1 -0
  87. package/dist/nl-linter/index.d.ts +10 -0
  88. package/dist/nl-linter/index.d.ts.map +1 -0
  89. package/dist/nl-linter/index.js +45 -0
  90. package/dist/nl-linter/index.js.map +1 -0
  91. package/dist/nl-linter/rules.d.ts +6 -0
  92. package/dist/nl-linter/rules.d.ts.map +1 -0
  93. package/dist/nl-linter/rules.js +93 -0
  94. package/dist/nl-linter/rules.js.map +1 -0
  95. package/dist/nl-linter/types.d.ts +14 -0
  96. package/dist/nl-linter/types.d.ts.map +1 -0
  97. package/dist/nl-linter/types.js +3 -0
  98. package/dist/nl-linter/types.js.map +1 -0
  99. package/dist/segmenter/clause-splitter.d.ts.map +1 -1
  100. package/dist/segmenter/clause-splitter.js +208 -10
  101. package/dist/segmenter/clause-splitter.js.map +1 -1
  102. package/dist/types.d.ts +22 -0
  103. package/dist/types.d.ts.map +1 -1
  104. package/package.json +14 -3
  105. package/readme.md +666 -1
package/readme.md CHANGED
@@ -1 +1,666 @@
1
- a
1
+ # autologic
2
+
3
+ > Formalizador automático de texto natural a lógica formal ST, sin IA obligatoria.
4
+
5
+ `@stevenvo780/autologic` toma texto en lenguaje natural y produce código ST válido y ejecutable. Soporta **dos modos**:
6
+
7
+ - **Modo reglas** (sin IA): NLP basado en marcadores discursivos, stemming y coreferencia.
8
+ - **Modo LLM/SLM**: extracción semántica vía OpenAI, Ollama o modelo local ONNX.
9
+
10
+ En ambos casos el pipeline incluye pre-validación con el **NL Linter** y genera código ST compatible con `@stevenvo780/st-lang`.
11
+
12
+ ```
13
+ Texto Natural
14
+
15
+
16
+ NL Linter ──(errores)──▶ Abortar con diagnóstico
17
+
18
+ ▼ (texto válido)
19
+ ┌─────────────────────────────────────────┐
20
+ │ Modo reglas │ Modo LLM/SLM │
21
+ │ (NLP determinista) │ (OpenAI/Ollama/ │
22
+ │ │ SLM local) │
23
+ └──────────┬───────────┴──────┬───────────┘
24
+ │ │
25
+ ▼ ▼
26
+ Pipeline NLP AST JSON → compileAST()
27
+ │ │
28
+ └──────────┬───────┘
29
+
30
+ ST Generator (emitST)
31
+
32
+
33
+ Validación + Ejecución (st-lang)
34
+
35
+
36
+ FormalizationResult
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Instalación
42
+
43
+ ```bash
44
+ npm install @stevenvo780/autologic
45
+ # peerDep requerida:
46
+ npm install @stevenvo780/st-lang
47
+ ```
48
+
49
+ ---
50
+
51
+ ## Uso rápido — Modo reglas
52
+
53
+ ```typescript
54
+ import { formalize } from '@stevenvo780/autologic';
55
+
56
+ const result = formalize(
57
+ "Si llueve, entonces la calle se moja. Dado que está lloviendo, la calle está mojada.",
58
+ { profile: 'classical.propositional', language: 'es' }
59
+ );
60
+
61
+ console.log(result.ok); // true
62
+ console.log(result.stCode); // código ST completo
63
+ console.log(result.analysis.detectedPatterns); // ["modus_ponens"]
64
+ console.log(result.stExecution?.ok); // true (ejecutado con st-lang)
65
+ ```
66
+
67
+ ## Uso con LLM — Modo inferencia
68
+
69
+ ```typescript
70
+ import { formalizeWithLLM } from '@stevenvo780/autologic';
71
+
72
+ const result = await formalizeWithLLM(
73
+ "Es obligatorio pagar impuestos. Si pagas impuestos está permitido votar.",
74
+ {
75
+ profile: 'deontic.standard',
76
+ language: 'es',
77
+ llmConfig: { provider: 'openai', apiKey: process.env.OPENAI_KEY! }
78
+ }
79
+ );
80
+
81
+ // result.linterDiagnostics — pre-validación NL Linter
82
+ // result.llmRawAst — AST JSON crudo devuelto por el LLM
83
+ // result.stCode — código ST generado
84
+ ```
85
+
86
+ ## Uso con modelo local ONNX (sin API externa)
87
+
88
+ ```typescript
89
+ const result = await formalizeWithLLM(text, {
90
+ profile: 'classical.propositional',
91
+ llmConfig: {
92
+ provider: 'web-distilled',
93
+ apiKey: '',
94
+ // Si se omite endpoint, descarga stevenvo780/autologic-slm-onnx de HuggingFace (~2.4 GB)
95
+ endpoint: '/models/autologic-slm' // ruta local opcional
96
+ }
97
+ });
98
+ ```
99
+
100
+ El modelo local usa `@huggingface/transformers` con ONNX runtime en el browser o Node. El modelo `stevenvo780/autologic-slm-onnx` es un Qwen2.5-0.5B fine-tuneado para traducir texto a AST JSON.
101
+
102
+ ## Clase con estado
103
+
104
+ ```typescript
105
+ import { Autologic } from '@stevenvo780/autologic';
106
+
107
+ const al = new Autologic({ language: 'es', defaultProfile: 'classical.propositional' });
108
+
109
+ const r1 = al.formalize("Todo humano es mortal. Sócrates es humano.");
110
+ const analysis = al.analyze("Si P entonces Q, pero no Q, luego no P.");
111
+ const validation = al.validate("logic classical.propositional\ncheck valid (P -> P)");
112
+ al.addMarker({ text: 'se sigue que', role: 'conclusion', language: 'es' });
113
+ ```
114
+
115
+ ---
116
+
117
+ ## API pública
118
+
119
+ ### `formalize(text, options?): FormalizationResult`
120
+
121
+ Función stateless — modo reglas NLP.
122
+
123
+ | Opción | Tipo | Default | Descripción |
124
+ |---|---|---|---|
125
+ | `profile` | `LogicProfile` | `'classical.propositional'` | Perfil lógico ST |
126
+ | `language` | `'es' \| 'en'` | `'es'` | Idioma del texto |
127
+ | `atomStyle` | `'keywords' \| 'letters' \| 'numbered'` | `'keywords'` | Nombres para átomos |
128
+ | `includeComments` | `boolean` | `true` | Comentarios de trazabilidad |
129
+ | `validateOutput` | `boolean` | `true` | Valida y ejecuta con st-lang |
130
+ | `maxClauseDepth` | `number` | `3` | Profundidad máxima de cláusulas |
131
+
132
+ ### `formalizeWithLLM(text, options): Promise<FormalizationLLMResult>`
133
+
134
+ Modo doble capa: NL Linter → LLM/SLM → AST → ST.
135
+
136
+ ```typescript
137
+ interface FormalizeWithLLMOptions extends FormalizeOptions {
138
+ llmConfig: LLMConfig;
139
+ abortOnLinterErrors?: boolean; // default: true
140
+ }
141
+
142
+ interface FormalizationLLMResult extends FormalizationResult {
143
+ linterDiagnostics: NLLinterDiagnostic[];
144
+ llmRawAst?: LLMParsedResult;
145
+ }
146
+ ```
147
+
148
+ ### `lintNaturalLanguage(text, rules?): NLLinterDiagnostic[]`
149
+
150
+ Valida texto natural antes de formalizar. Detecta problemas que reducen la calidad de la formalización.
151
+
152
+ ```typescript
153
+ import { lintNaturalLanguage } from '@stevenvo780/autologic';
154
+
155
+ const diags = lintNaturalLanguage("Frecuentemente, este caso produce errores.");
156
+ // [
157
+ // { id: 'nl-fuzzy-quantifier', severity: 'error', message: "Término difuso 'Frecuentemente'...", start: 0, end: 13 },
158
+ // { id: 'nl-anaphoric-ambiguity', severity: 'warning', message: "El pronombre 'este'...", start: 15, end: 19 }
159
+ // ]
160
+ ```
161
+
162
+ ### `parseTextWithLLM(text, profile, config): Promise<LLMParsedResult>`
163
+
164
+ Llama directamente a la API del LLM y retorna el AST JSON crudo.
165
+
166
+ ### `llmResultToST(result): { formula, type }[]`
167
+
168
+ Convierte el AST JSON del LLM a líneas de código ST.
169
+
170
+ ### Resultado completo
171
+
172
+ ```typescript
173
+ interface FormalizationResult {
174
+ ok: boolean;
175
+ stCode: string;
176
+ analysis: DiscourseAnalysis;
177
+ atoms: Map<string, string>; // atomId → texto original
178
+ formulas: FormulaEntry[];
179
+ diagnostics: Diagnostic[];
180
+ stValidation?: { ok: boolean; errors: string[] };
181
+ stExecution?: STExecutionResult; // resultado real de ejecutar con st-lang
182
+ }
183
+
184
+ interface STExecutionResult {
185
+ ok: boolean;
186
+ exitCode: number;
187
+ timedOut: boolean;
188
+ durationMs: number;
189
+ errors: string[];
190
+ resultStatuses: string[]; // ["valid", "derivable", ...]
191
+ }
192
+ ```
193
+
194
+ ---
195
+
196
+ ## NL Linter
197
+
198
+ El NL Linter es una capa de pre-validación que analiza el texto natural antes de enviarlo a formalización. Se ejecuta automáticamente en `formalizeWithLLM()` y puede usarse de forma independiente.
199
+
200
+ Cuatro reglas integradas (`DEFAULT_RULES`):
201
+
202
+ | ID | Severidad | Qué detecta |
203
+ |---|---|---|
204
+ | `nl-anaphoric-ambiguity` | warning | Pronombres anafóricos: "este", "ese", "lo anterior", "su" — ambigüedad referencial |
205
+ | `nl-cognitive-density` | warning | Oraciones de más de 40 palabras — el contexto semántico pierde precisión |
206
+ | `nl-fuzzy-quantifier` | **error** | Cuantificadores difusos: "frecuentemente", "la mayoría", "a veces", "probablemente" |
207
+ | `nl-missing-relations` | warning | Textos > 60 chars sin conectores de inferencia ("si... entonces", "por lo tanto") |
208
+
209
+ Los errores de severidad `error` abortan `formalizeWithLLM` por defecto (configurable con `abortOnLinterErrors: false`).
210
+
211
+ ```typescript
212
+ import { lintNaturalLanguage, DEFAULT_RULES, anaphoricRule } from '@stevenvo780/autologic';
213
+
214
+ // Usar solo reglas específicas:
215
+ const diags = lintNaturalLanguage(text, [anaphoricRule]);
216
+ ```
217
+
218
+ Cada `NLLinterDiagnostic` incluye `{ id, severity, message, start, end }` con la posición exacta en el texto.
219
+
220
+ ---
221
+
222
+ ## Configuración del LLM
223
+
224
+ ```typescript
225
+ interface LLMConfig {
226
+ provider: 'openai' | 'anthropic' | 'gemini' | 'custom' | 'ollama' | 'web-distilled';
227
+ apiKey: string;
228
+ endpoint?: string; // URL personalizada
229
+ model?: string; // modelo específico
230
+ }
231
+ ```
232
+
233
+ | Provider | Descripción | Default model |
234
+ |---|---|---|
235
+ | `openai` | API OpenAI (fetch isomórfico) | `gpt-4o` |
236
+ | `ollama` | Servidor Ollama local con GPU | `qwen2.5:7b` |
237
+ | `web-distilled` | Modelo ONNX local vía @huggingface/transformers | `stevenvo780/autologic-slm-onnx` |
238
+
239
+ El LLM recibe un **system prompt** que le instruye a actuar como parser AST situado. No debe resolver la lógica, solo extraer claims y relaciones. Devuelve un JSON con la interfaz `LLMParsedResult`:
240
+
241
+ ```typescript
242
+ interface LLMParsedResult {
243
+ axioms: Array<{ name: string; formulaJSON: LogicNode }>;
244
+ conclusions: Array<{ formulaJSON: LogicNode }>;
245
+ }
246
+ ```
247
+
248
+ ---
249
+
250
+ ## Sistema AST
251
+
252
+ autologic incluye un sistema de tipos AST completo para representar fórmulas lógicas de forma programática, independiente del texto.
253
+
254
+ ### Nodos disponibles
255
+
256
+ ```typescript
257
+ // Átomos proposicionales
258
+ AST.atom('LLUEVE', 'llueve')
259
+
260
+ // Conectivos
261
+ AST.and(left, right)
262
+ AST.or(left, right)
263
+ AST.implies(left, right)
264
+ AST.not(child)
265
+
266
+ // Cuantificadores
267
+ AST.forall(['x'], child)
268
+ AST.exists(['x'], child)
269
+ AST.exactlyN(['x', 'y'], 2, child) // Exactamente N instancias
270
+
271
+ // Modales (con soporte multi-agente)
272
+ AST.modal('K', child, 'Diego') // K_Diego(child)
273
+ AST.modal('B', child) // Belief
274
+ AST.modal('O', child) // Obligation
275
+ AST.modal('P', child) // Permission
276
+ AST.modal('F', child) // Forbidden
277
+ AST.modal('BOX', child) // Necesidad
278
+ AST.modal('DIA', child) // Posibilidad
279
+ AST.modal('EVENTUALLY', child) // Temporal F
280
+ AST.modal('NEXT', child) // Temporal X
281
+
282
+ // Temporal binario
283
+ AST.temporalUntil(left, right) // left U right
284
+
285
+ // Primer orden
286
+ AST.predicate('Humano', [AST.obj('x')])
287
+ AST.forall(['x'], AST.implies(AST.predicate('Humano', [AST.obj('x')]), ...))
288
+
289
+ // Matemáticas
290
+ AST.math('ADD', AST.obj('x'), AST.obj('y'))
291
+ AST.math('LT', left, AST.obj('100'))
292
+
293
+ // Probabilidad
294
+ AST.probability(0.755, child) // Pr(child) = 0.755
295
+
296
+ // DRT - referencias
297
+ AST.ref('s1') // Referencia a enunciado anterior (DRT)
298
+ ```
299
+
300
+ ### Compilar AST a ST
301
+
302
+ ```typescript
303
+ import { compileAST, AST } from '@stevenvo780/autologic/formula/ast-compiler';
304
+
305
+ const ast = AST.implies(
306
+ AST.predicate('Humano', [AST.obj('x')]),
307
+ AST.predicate('Mortal', [AST.obj('x')])
308
+ );
309
+
310
+ compileAST(ast); // "Humano(x) -> Mortal(x)"
311
+ ```
312
+
313
+ ---
314
+
315
+ ## DRT — Discourse Reference Theory
316
+
317
+ `DiscourseState` mantiene un registro de enunciados en orden para resolver referencias anafóricas complejas (pronombres como "esto", "lo anterior").
318
+
319
+ ```typescript
320
+ import { globalDrt } from '@stevenvo780/autologic/context/discourse-state';
321
+
322
+ // El estado global registra cada enunciado formalizado
323
+ const id = globalDrt.registerStatement(astNode); // "s1", "s2", ...
324
+ globalDrt.resolvePronoun('esto'); // → "s1" (último enunciado)
325
+ globalDrt.resolvePronoun('lo anterior'); // → "s1"
326
+ ```
327
+
328
+ Se usa internamente en `compiler-frontend.ts` para casos como:
329
+ - "Ana aprueba el balance. Diego **sabe esto**." → K_Diego(ANA_APRUEBA_BALANCE)
330
+ - "El servidor colapsó. El administrador sabe esto. El CEO cree que **lo ignora**."
331
+
332
+ ---
333
+
334
+ ## Compiler Frontend
335
+
336
+ `compileComplexLogic()` es un compilador especializado para textos con estructura lógica compleja que el pipeline NLP genérico no puede manejar. Cubre casos extremos por perfil:
337
+
338
+ | Caso | Perfil | Ejemplo |
339
+ |---|---|---|
340
+ | "Ningún X es Y, excepto Z" | `aristotelian` | `forall x (M(x) -> !H(x)) & H(Ornitorrinco)` |
341
+ | "Exactamente N..." | `classical.first_order` | Cuantificación exacta con desigualdades |
342
+ | Expresiones matemáticas | `arithmetic` | Delega a `extractMath()` |
343
+ | Obligación con excepción | `deontic.standard` | `SystemaFalla -> (O(Reiniciar) & (Prohibe -> F(Reiniciar)))` |
344
+ | Conocimiento multi-agente | `epistemic.s5` | `K_Diego(P) & B_Carlos(!K_Diego(P))` |
345
+ | Contradicción explícita | `paraconsistent` | `Recibido() & !Recibido()` |
346
+ | Probabilidad numérica | `probabilistic` | `Pr(FallaMecanica) = 0.755` |
347
+ | Doble negación | `intuitionistic` | `!!TenemosSoluciones` |
348
+ | Eventualmente / Until | `temporal` | `F_temp(Alarma) & (Alarma U Pin)` |
349
+
350
+ Devuelve `null` si el texto no corresponde a ningún caso extremo conocido, dejando que el pipeline normal continúe.
351
+
352
+ ---
353
+
354
+ ## Math Parser
355
+
356
+ `extractMath()` detecta y extrae expresiones matemáticas del texto, protegiéndolas para que el pipeline NLP no las interprete como proposiciones.
357
+
358
+ ```typescript
359
+ import { extractMath } from '@stevenvo780/autologic/atoms/math-parser';
360
+
361
+ const { nodes, shieldedText } = extractMath(
362
+ "Si al cuadrado de X le sumas la variable Y, el resultado será siempre menor a 100."
363
+ );
364
+ // nodes: Map { "__MATH_1__" → AST.math('LT', ADD(MUL(X,X), Y), 100) }
365
+ // shieldedText: "Si __MATH_1__, ..."
366
+ ```
367
+
368
+ Soporta:
369
+ - Expresiones algebraicas verbales ("al cuadrado de X le sumas Y")
370
+ - Ecuaciones simples (`x = y + 2`, `x = y - 3`)
371
+
372
+ ---
373
+
374
+ ## Perfiles lógicos
375
+
376
+ | Perfil | Caso de uso |
377
+ |---|---|
378
+ | `classical.propositional` | Conectores básicos (→, ∧, ∨, ¬). Default. |
379
+ | `classical.first_order` | Cuantificadores ∀x, ∃x, predicados |
380
+ | `modal.k` | Necesidad (`[]`), posibilidad (`<>`) |
381
+ | `deontic.standard` | Obligación (O), permiso (P), prohibición (F) |
382
+ | `epistemic.s5` | Conocimiento (K), creencia (B), multi-agente |
383
+ | `intuitionistic.propositional` | Sin tercero excluido |
384
+ | `temporal.ltl` | `next`, `until`, `G`, `F` |
385
+ | `paraconsistent.belnap` | Tolerante a contradicciones |
386
+ | `aristotelian.syllogistic` | Silogística clásica |
387
+ | `probabilistic.basic` | `Pr(X) = 0.75` |
388
+ | `arithmetic` | Operaciones aritméticas explicadas |
389
+
390
+ ---
391
+
392
+ ## Ejemplos por perfil
393
+
394
+ ### `classical.propositional` — Modus Ponens
395
+
396
+ ```
397
+ "Si los precios suben, la demanda baja. Los precios están subiendo. Por lo tanto, la demanda bajará."
398
+ ```
399
+ ```st
400
+ logic classical.propositional
401
+ interpret "los precios suben" as PRECIOS_SUBEN
402
+ interpret "la demanda baja" as DEMANDA_BAJA
403
+ axiom regla : PRECIOS_SUBEN -> DEMANDA_BAJA
404
+ axiom hecho : PRECIOS_SUBEN
405
+ derive DEMANDA_BAJA from {regla, hecho}
406
+ ```
407
+
408
+ ### `classical.first_order` — Silogismo
409
+
410
+ ```
411
+ "Todo humano es mortal. Sócrates es humano. Por tanto, Sócrates es mortal."
412
+ ```
413
+ ```st
414
+ logic classical.first_order
415
+ axiom a1 : forall x (Humano(x) -> Mortal(x))
416
+ axiom a2 : Humano(socrates)
417
+ derive Mortal(socrates) from {a1, a2}
418
+ ```
419
+
420
+ ### `deontic.standard` — Normas
421
+
422
+ ```
423
+ "Es obligatorio pagar impuestos. Si pagas impuestos, está permitido votar."
424
+ ```
425
+ ```st
426
+ logic deontic.standard
427
+ axiom obligacion : [](PAGAR_IMPUESTOS)
428
+ axiom permiso : PAGAR_IMPUESTOS -> <>(VOTAR)
429
+ ```
430
+
431
+ ### `epistemic.s5` — Conocimiento multi-agente (LLM)
432
+
433
+ ```
434
+ "Ana aprueba el balance. Diego sabe esto. Carlos duda de lo anterior."
435
+ ```
436
+ ```st
437
+ logic epistemic.s5
438
+ axiom a1 : ANA_APRUEBA_BALANCE & K_Diego(ANA_APRUEBA_BALANCE) & B_Carlos(!K_Diego(ANA_APRUEBA_BALANCE))
439
+ ```
440
+
441
+ ### `probabilistic.basic`
442
+
443
+ ```
444
+ "Existe exactamente un 75.5% de probabilidad de que el disco sufra una falla mecánica."
445
+ ```
446
+ ```st
447
+ logic probabilistic.basic
448
+ axiom a1 : Pr(FallaMecanica) = 0.755
449
+ ```
450
+
451
+ ---
452
+
453
+ ## Pipeline interno (modo reglas)
454
+
455
+ ```
456
+ 1. Segmenter Divide texto en oraciones y cláusulas
457
+ (puntuación + marcadores discursivos)
458
+ 2. Discourse Clasifica roles: premisa, conclusión,
459
+ Analyzer condición, consecuente
460
+ Detecta negaciones y cuantificadores
461
+ 3. Atom Extractor Extrae proposiciones atómicas → IDs
462
+ Correferencia léxica básica (Dice/Jaccard)
463
+ 4. Formula Builder Construye fórmulas por perfil
464
+ (A->B, forall x, []A, next A...)
465
+ 5. ST Generator Emite código ST con trazabilidad
466
+ 6. Validator valida parse + ejecuta con st-lang
467
+ ```
468
+
469
+ ### Marcadores discursivos (~200 bilingüe)
470
+
471
+ | Categoría | Español | English | Rol lógico |
472
+ |---|---|---|---|
473
+ | Condicional | si, siempre que, en caso de | if, whenever, provided that | `condition` |
474
+ | Consecuente | entonces, por lo tanto, luego | then, therefore, hence | `consequent` |
475
+ | Premisa | dado que, puesto que, ya que | since, because, given that | `premise` |
476
+ | Conjunción | y, además, también | and, moreover, furthermore | `and` |
477
+ | Disyunción | o, o bien | or, either...or | `or` |
478
+ | Adversativa | pero, sin embargo, aunque | but, however, although | `adversative` |
479
+ | Negación | no, nunca, ningún | not, never, neither | `negation` |
480
+ | Universal | todo, cada, cualquier | all, every, each | `universal` |
481
+ | Existencial | algún, existe, hay | some, there exists | `existential` |
482
+ | Modal-necesidad | necesariamente, debe | necessarily, must | `necessity` |
483
+ | Modal-posibilidad | posiblemente, puede | possibly, may | `possibility` |
484
+ | Bicondicional | si y solo si | if and only if | `biconditional` |
485
+ | Temporal | después, antes, hasta que | after, before, until | `temporal` |
486
+
487
+ ### Patrones argumentales detectados
488
+
489
+ | Patrón | Condición |
490
+ |---|---|
491
+ | `modus_ponens` | (A→B) + A → B |
492
+ | `modus_tollens` | (A→B) + ¬B → ¬A |
493
+ | `hypothetical_syllogism` | A→B + B→C → A→C |
494
+ | `disjunctive_syllogism` | A∨B + ¬A → B |
495
+ | `constructive_dilemma` | (A→B) & (C→D) + (A∨C) → (B∨D) |
496
+ | `conditional_chain` | Serie de condicionales encadenados |
497
+ | `universal_generalization` | Múltiples instancias del mismo patrón |
498
+ | `conjunction_introduction` | Varias premisas aisladas |
499
+ | `biconditional_introduction` | A si y solo si B |
500
+
501
+ ---
502
+
503
+ ## Estructura del proyecto
504
+
505
+ ```
506
+ autologic/
507
+ ├── src/
508
+ │ ├── index.ts # Exports públicos (API completa)
509
+ │ ├── autologic.ts # Clase Autologic con estado
510
+ │ ├── formalize.ts # formalize() y formalizeWithLLM()
511
+ │ ├── types.ts # Todos los tipos
512
+ │ ├── compiler-frontend.ts # Casos extremos por perfil (AST directo)
513
+ │ ├── llm-parser.ts # Parser LLM (OpenAI/Ollama/web-distilled)
514
+ │ ├── local-slm-web.ts # Inferencia ONNX local (@huggingface/transformers)
515
+ │ │
516
+ │ ├── nl-linter/
517
+ │ │ ├── index.ts # lintNaturalLanguage() + DEFAULT_RULES
518
+ │ │ ├── rules.ts # 4 reglas: anaphoric, density, fuzzy, completeness
519
+ │ │ └── types.ts # NLLinterDiagnostic, NLRule
520
+ │ │
521
+ │ ├── context/
522
+ │ │ └── discourse-state.ts # DRT: DiscourseState + globalDrt
523
+ │ │
524
+ │ ├── formula/
525
+ │ │ ├── ast.ts # Tipos AST + factory AST.*
526
+ │ │ ├── ast-compiler.ts # compileAST() → código ST
527
+ │ │ ├── argument-builder.ts # Constructor de argumentos
528
+ │ │ ├── connectors.ts # Mapa marcador → operador ST
529
+ │ │ ├── first-order.ts # Builder FOL
530
+ │ │ ├── modal.ts # Builder modal
531
+ │ │ ├── propositional.ts # Builder proposicional
532
+ │ │ ├── temporal.ts # Builder temporal
533
+ │ │ ├── probabilistic.ts # Builder probabilístico
534
+ │ │ ├── helpers.ts # Utilidades
535
+ │ │ └── index.ts # buildFormulas()
536
+ │ │
537
+ │ ├── atoms/
538
+ │ │ ├── index.ts # extractAtoms()
539
+ │ │ ├── coreference.ts # Resolución de correferencia
540
+ │ │ ├── identifier-gen.ts # Generador de IDs ST válidos
541
+ │ │ ├── keyword-extractor.ts # Extracción de palabras clave
542
+ │ │ └── math-parser.ts # extractMath() — escudo matemático
543
+ │ │
544
+ │ ├── segmenter/
545
+ │ │ ├── index.ts # segment()
546
+ │ │ ├── sentence-splitter.ts # Split por puntuación
547
+ │ │ └── clause-splitter.ts # Split de cláusulas internas
548
+ │ │
549
+ │ ├── discourse/
550
+ │ │ ├── index.ts # analyzeDiscourse()
551
+ │ │ ├── markers-es.ts # ~100 marcadores español
552
+ │ │ ├── markers-en.ts # ~100 marcadores inglés
553
+ │ │ ├── role-classifier.ts # Asigna roles a cláusulas
554
+ │ │ └── pattern-detector.ts # Detecta patrones argumentales
555
+ │ │
556
+ │ ├── generator/
557
+ │ │ ├── index.ts
558
+ │ │ ├── st-emitter.ts # emitST() — código ST con comentarios
559
+ │ │ └── validator.ts # validateST(), executeST()
560
+ │ │
561
+ │ └── nlp/
562
+ │ ├── index.ts
563
+ │ ├── tokenizer.ts
564
+ │ ├── stemmer-es.ts # Snowball español
565
+ │ ├── stemmer-en.ts # Snowball inglés
566
+ │ └── stopwords.ts
567
+
568
+ └── tests/
569
+ ├── segmenter.test.ts
570
+ ├── discourse.test.ts
571
+ ├── atoms.test.ts
572
+ ├── formula.test.ts
573
+ ├── patterns.test.ts
574
+ └── profiles.test.ts
575
+ ```
576
+
577
+ ---
578
+
579
+ ## Exports públicos (`index.ts`)
580
+
581
+ ```typescript
582
+ // Funciones principales
583
+ export { formalize } from './formalize';
584
+ export { formalizeWithLLM } from './formalize';
585
+ export type { FormalizeWithLLMOptions, FormalizationLLMResult } from './formalize';
586
+
587
+ // NL Linter
588
+ export { lintNaturalLanguage, DEFAULT_RULES } from './nl-linter';
589
+ export type { NLLinterDiagnostic, NLRule } from './nl-linter';
590
+
591
+ // Clase con estado
592
+ export { Autologic } from './autologic';
593
+
594
+ // LLM
595
+ export { parseTextWithLLM, llmResultToST } from './llm-parser';
596
+ export type { LLMConfig, LLMParsedResult } from './llm-parser';
597
+
598
+ // Pipeline interno (uso avanzado)
599
+ export { segment } from './segmenter';
600
+ export { analyzeDiscourse } from './discourse';
601
+ export { extractAtoms } from './atoms';
602
+ export { buildFormulas } from './formula';
603
+ export { emitST } from './generator/st-emitter';
604
+ export { validateST } from './generator/validator';
605
+ ```
606
+
607
+ ---
608
+
609
+ ## Dependencias
610
+
611
+ **Runtime**: ninguna (0 dependencias).
612
+
613
+ **peerDependencies**: `@stevenvo780/st-lang >= 3.0.0`
614
+
615
+ **devDependencies**: `typescript`, `vitest`, `@stevenvo780/st-lang`
616
+
617
+ **Opcional (LLM web)**: `@huggingface/transformers` — se importa dinámicamente solo si se usa el provider `web-distilled`.
618
+
619
+ NLP propio (sin compromise.js ni spaCy):
620
+ - Stemmer Snowball ES/EN (~200 líneas)
621
+ - Stopwords curadas (~150 palabras/idioma)
622
+ - Marcadores discursivos (~200 entradas)
623
+ - Tokenizador regex
624
+
625
+ Tamaño: ~30 KB minificado (sin el modelo ONNX).
626
+
627
+ ---
628
+
629
+ ## Tests
630
+
631
+ ```bash
632
+ npm test # vitest
633
+ npm run test:coverage # con reporte en coverage/
634
+ ```
635
+
636
+ ---
637
+
638
+ ## Decisiones de diseño
639
+
640
+ | Decisión | Razón |
641
+ |---|---|
642
+ | Modo reglas SIN IA por defecto | Determinismo, reproducibilidad, latencia cero, costo cero |
643
+ | Modo LLM opcional | Para textos legales/técnicos complejos que el pipeline NLP no maneja |
644
+ | NL Linter como puerta de entrada | Previene formalización de textos ambiguos que producirían ASTs incorrectos |
645
+ | AST tipado en TypeScript | El LLM devuelve JSON; compileAST() lo transforma a ST sin riesgo de inyección |
646
+ | DRT para correferencia | Resolución de pronombres anafóricos en lógicas epistémicas y modales multi-agente |
647
+ | compiler-frontend para casos extremos | Algunos patrones (cuantificación exacta, probabilidades) requieren construcción AST directa |
648
+ | 0 deps runtime | Librería ultraligera, sin supply-chain risk |
649
+ | st-lang como peerDep | El consumidor ya la tiene; evita duplicación |
650
+
651
+ ---
652
+
653
+ ## Integración con EducacionCooperativa
654
+
655
+ La plataforma usa autologic en dos puntos:
656
+
657
+ 1. **`src/lib/buildSTFromSemantic.ts`** — genera automáticamente el archivo `.st` companion para cada documento de la Mesa Semántica.
658
+ 2. **`src/components/FormalizerPlayground.tsx`** — interfaz interactiva para formalizar texto con selección de perfil, historial y ejecución en tiempo real.
659
+
660
+ Ver `docs/formalizacion-automatica.md` en EducacionCooperativa para el flujo completo.
661
+
662
+ ---
663
+
664
+ ## Licencia
665
+
666
+ Ver [LICENSE](LICENSE).