@stevenvo780/st-lang 3.1.1 → 3.1.2

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 (66) hide show
  1. package/README.md +3 -3
  2. package/dist/lexer/lexer.d.ts.map +1 -1
  3. package/dist/lexer/lexer.js +8 -0
  4. package/dist/lexer/lexer.js.map +1 -1
  5. package/dist/lexer/tokens.d.ts +2 -0
  6. package/dist/lexer/tokens.d.ts.map +1 -1
  7. package/dist/lexer/tokens.js +6 -0
  8. package/dist/lexer/tokens.js.map +1 -1
  9. package/dist/parser/parser.d.ts.map +1 -1
  10. package/dist/parser/parser.js +11 -0
  11. package/dist/parser/parser.js.map +1 -1
  12. package/dist/profiles/aristotelian/syllogistic.d.ts +1 -1
  13. package/dist/profiles/aristotelian/syllogistic.d.ts.map +1 -1
  14. package/dist/profiles/aristotelian/syllogistic.js +26 -8
  15. package/dist/profiles/aristotelian/syllogistic.js.map +1 -1
  16. package/dist/profiles/arithmetic/index.d.ts +1 -1
  17. package/dist/profiles/arithmetic/index.d.ts.map +1 -1
  18. package/dist/profiles/arithmetic/index.js +29 -7
  19. package/dist/profiles/arithmetic/index.js.map +1 -1
  20. package/dist/profiles/classical/first-order.d.ts +1 -1
  21. package/dist/profiles/classical/first-order.d.ts.map +1 -1
  22. package/dist/profiles/classical/first-order.js +20 -3
  23. package/dist/profiles/classical/first-order.js.map +1 -1
  24. package/dist/profiles/classical/propositional.d.ts +1 -1
  25. package/dist/profiles/classical/propositional.d.ts.map +1 -1
  26. package/dist/profiles/classical/propositional.js +200 -51
  27. package/dist/profiles/classical/propositional.js.map +1 -1
  28. package/dist/profiles/intuitionistic/propositional.d.ts +1 -1
  29. package/dist/profiles/intuitionistic/propositional.d.ts.map +1 -1
  30. package/dist/profiles/intuitionistic/propositional.js +33 -5
  31. package/dist/profiles/intuitionistic/propositional.js.map +1 -1
  32. package/dist/profiles/paraconsistent/belnap.d.ts +1 -2
  33. package/dist/profiles/paraconsistent/belnap.d.ts.map +1 -1
  34. package/dist/profiles/paraconsistent/belnap.js +25 -11
  35. package/dist/profiles/paraconsistent/belnap.js.map +1 -1
  36. package/dist/profiles/probabilistic/basic.d.ts +1 -1
  37. package/dist/profiles/probabilistic/basic.d.ts.map +1 -1
  38. package/dist/profiles/probabilistic/basic.js +29 -5
  39. package/dist/profiles/probabilistic/basic.js.map +1 -1
  40. package/dist/profiles/shared/base-profile.d.ts +1 -1
  41. package/dist/profiles/shared/base-profile.d.ts.map +1 -1
  42. package/dist/profiles/shared/base-profile.js +20 -3
  43. package/dist/profiles/shared/base-profile.js.map +1 -1
  44. package/dist/profiles/shared/tableau-engine.d.ts.map +1 -1
  45. package/dist/profiles/shared/tableau-engine.js +6 -0
  46. package/dist/profiles/shared/tableau-engine.js.map +1 -1
  47. package/dist/repl/repl.d.ts.map +1 -1
  48. package/dist/repl/repl.js +5 -1
  49. package/dist/repl/repl.js.map +1 -1
  50. package/dist/runtime/compat.d.ts.map +1 -1
  51. package/dist/runtime/compat.js +2 -4
  52. package/dist/runtime/compat.js.map +1 -1
  53. package/dist/runtime/interpreter.d.ts.map +1 -1
  54. package/dist/runtime/interpreter.js +7 -4
  55. package/dist/runtime/interpreter.js.map +1 -1
  56. package/dist/tests/cli.test.js +5 -1
  57. package/dist/tests/cli.test.js.map +1 -1
  58. package/dist/tests/core.test.js +4 -1
  59. package/dist/tests/core.test.js.map +1 -1
  60. package/dist/tests/stress-exhaustive.test.js +5 -1
  61. package/dist/tests/stress-exhaustive.test.js.map +1 -1
  62. package/dist/types/index.d.ts +10 -2
  63. package/dist/types/index.d.ts.map +1 -1
  64. package/dist/types/index.js +36 -1
  65. package/dist/types/index.js.map +1 -1
  66. package/package.json +1 -3
@@ -38,6 +38,10 @@ function computeCollectAtoms(f) {
38
38
  }
39
39
  function evaluateClassical(f, v) {
40
40
  switch (f.kind) {
41
+ case 'true':
42
+ return true;
43
+ case 'false':
44
+ return false;
41
45
  case 'atom':
42
46
  return f.name ? (v[f.name] ?? false) : false;
43
47
  case 'not':
@@ -311,6 +315,10 @@ function formulaToString(f) {
311
315
  }
312
316
  function computeFormulaToString(f) {
313
317
  switch (f.kind) {
318
+ case 'true':
319
+ return '⊤';
320
+ case 'false':
321
+ return '⊥';
314
322
  case 'atom':
315
323
  return f.name || '?';
316
324
  case 'not': {
@@ -425,6 +433,8 @@ function computeNNF(f) {
425
433
  const args = node.args || [];
426
434
  if (!negated) {
427
435
  switch (k) {
436
+ case 'true':
437
+ case 'false':
428
438
  case 'atom':
429
439
  case 'predicate':
430
440
  return node;
@@ -468,6 +478,10 @@ function computeNNF(f) {
468
478
  }
469
479
  else {
470
480
  switch (k) {
481
+ case 'true':
482
+ return { kind: 'false' };
483
+ case 'false':
484
+ return { kind: 'true' };
471
485
  case 'atom':
472
486
  case 'predicate':
473
487
  return { kind: 'not', args: [node] };
@@ -637,18 +651,105 @@ function getSubFormulas(f) {
637
651
  // Remove atoms and the full formula itself
638
652
  return result.filter((n) => n.kind !== 'atom' && formulaToString(n) !== formulaToString(f));
639
653
  }
654
+ /**
655
+ * Igualdad estructural con alpha-equivalencia sobre variables cuantificadas.
656
+ * Cubre átomos, predicados, cuantificadores (∀/∃), modales y constantes.
657
+ */
640
658
  function formulasEqual(a, b) {
659
+ return alphaEqualFormulas(a, b, new Map(), new Map());
660
+ }
661
+ function alphaEqualFormulas(a, b, bindA, bindB, depth = 0) {
641
662
  if (a.kind !== b.kind)
642
663
  return false;
643
- if (a.kind === 'atom' && b.kind === 'atom')
644
- return a.name === b.name;
645
- if (a.args && b.args) {
646
- if (a.args.length !== b.args.length)
647
- return false;
648
- const bArgs = b.args;
649
- return a.args.every((arg, i) => formulasEqual(arg, bArgs[i]));
664
+ switch (a.kind) {
665
+ case 'true':
666
+ case 'false':
667
+ return true;
668
+ case 'atom': {
669
+ const nameA = a.name;
670
+ const nameB = b.name;
671
+ if (nameA === undefined || nameB === undefined)
672
+ return nameA === nameB;
673
+ const bA = bindA.get(nameA);
674
+ const bB = bindB.get(nameB);
675
+ if (bA !== undefined || bB !== undefined)
676
+ return bA === bB;
677
+ return nameA === nameB;
678
+ }
679
+ case 'number':
680
+ return a.value === b.value;
681
+ case 'predicate': {
682
+ if (a.name !== b.name)
683
+ return false;
684
+ const paramsA = a.params || a.terms || [];
685
+ const paramsB = b.params || b.terms || [];
686
+ if (paramsA.length !== paramsB.length)
687
+ return false;
688
+ for (let i = 0; i < paramsA.length; i++) {
689
+ const pA = paramsA[i];
690
+ const pB = paramsB[i];
691
+ const bndA = bindA.get(pA);
692
+ const bndB = bindB.get(pB);
693
+ if (bndA !== undefined || bndB !== undefined) {
694
+ if (bndA !== bndB)
695
+ return false;
696
+ }
697
+ else if (pA !== pB) {
698
+ return false;
699
+ }
700
+ }
701
+ return true;
702
+ }
703
+ case 'forall':
704
+ case 'exists': {
705
+ const vA = a.variable;
706
+ const vB = b.variable;
707
+ if (!vA || !vB)
708
+ return vA === vB;
709
+ const innerA = a.args?.[0];
710
+ const innerB = b.args?.[0];
711
+ if (!innerA || !innerB)
712
+ return false;
713
+ const prevA = bindA.get(vA);
714
+ const prevB = bindB.get(vB);
715
+ bindA.set(vA, depth);
716
+ bindB.set(vB, depth);
717
+ const eq = alphaEqualFormulas(innerA, innerB, bindA, bindB, depth + 1);
718
+ if (prevA === undefined)
719
+ bindA.delete(vA);
720
+ else
721
+ bindA.set(vA, prevA);
722
+ if (prevB === undefined)
723
+ bindB.delete(vB);
724
+ else
725
+ bindB.set(vB, prevB);
726
+ return eq;
727
+ }
728
+ case 'modal_necessity':
729
+ case 'modal_possibility':
730
+ case 'temporal_next':
731
+ case 'temporal_until': {
732
+ if (a.name !== b.name)
733
+ return false;
734
+ const argsA = a.args || [];
735
+ const argsB = b.args || [];
736
+ if (argsA.length !== argsB.length)
737
+ return false;
738
+ return argsA.every((arg, i) => alphaEqualFormulas(arg, argsB[i], bindA, bindB, depth));
739
+ }
740
+ default: {
741
+ const argsA = a.args || [];
742
+ const argsB = b.args || [];
743
+ if (argsA.length !== argsB.length)
744
+ return false;
745
+ if (argsA.length === 0) {
746
+ if (a.name !== b.name)
747
+ return false;
748
+ return a.value === b.value;
749
+ }
750
+ return argsA.every((arg, i) => alphaEqualFormulas(arg, argsB[i], bindA, bindB, depth));
751
+ }
650
752
  }
651
- return false;
652
753
  }
653
754
  // --- Motor de derivación ---
654
755
  /** Límite duro de fórmulas derivadas para evitar explosión combinatoria */
@@ -690,7 +791,7 @@ function isRelevantToGoal(f, goal) {
690
791
  };
691
792
  return checkSub(goal);
692
793
  }
693
- function addDerivedFormula(state, formula, justification, premises) {
794
+ function addDerivedFormula(state, formula, justification, premises, source = 'rule') {
694
795
  const hash = formulaHash(formula);
695
796
  if (state.known.has(hash))
696
797
  return false;
@@ -700,6 +801,7 @@ function addDerivedFormula(state, formula, justification, premises) {
700
801
  formula,
701
802
  justification,
702
803
  premises,
804
+ source,
703
805
  });
704
806
  state.known.set(hash, formula);
705
807
  return true;
@@ -809,6 +911,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
809
911
  formula: f,
810
912
  justification: `Premisa (${name})`,
811
913
  premises: [],
914
+ source: 'premise',
812
915
  });
813
916
  state.known.set(formulaHash(f), f);
814
917
  }
@@ -1423,14 +1526,14 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1423
1526
  const subProof = tryDerive(subGoal, tempTheory, subPremises, depth + 1);
1424
1527
  if (subProof && subProof.status === 'complete') {
1425
1528
  // Check the sub-proof doesn't rely solely on semantic fallback
1426
- const isSyntactic = subProof.steps.every((s) => !s.justification.startsWith('Verificacion semantica'));
1529
+ const isSyntactic = subProof.steps.every((s) => s.source !== 'semantic');
1427
1530
  if (isSyntactic) {
1428
1531
  // Build the main proof: premises + sub-derivation steps + conditional proof conclusion
1429
1532
  const mainSteps = [];
1430
1533
  let stepNum = 0;
1431
1534
  // Copy premise steps from current state
1432
1535
  for (const s of state.steps) {
1433
- if (s.justification.startsWith('Premisa')) {
1536
+ if (s.source === 'premise') {
1434
1537
  stepNum++;
1435
1538
  mainSteps.push({ ...s, stepNumber: stepNum, premises: [] });
1436
1539
  }
@@ -1443,17 +1546,18 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1443
1546
  formula: assumption,
1444
1547
  justification: 'Supuesto (para prueba condicional)',
1445
1548
  premises: [],
1549
+ source: 'assumption',
1446
1550
  });
1447
1551
  // Add sub-derivation steps (renumber, adjusting premise references)
1448
1552
  const subStepMap = new Map();
1449
1553
  for (const s of subProof.steps) {
1450
- if (s.justification.startsWith('Premisa') && formulasEqual(s.formula, assumption)) {
1554
+ if (s.source === 'premise' && formulasEqual(s.formula, assumption)) {
1451
1555
  subStepMap.set(s.stepNumber, assumptionStepNum);
1452
1556
  continue;
1453
1557
  }
1454
- if (s.justification.startsWith('Premisa')) {
1558
+ if (s.source === 'premise') {
1455
1559
  // Find existing premise step in main
1456
- const existing = mainSteps.find((ms) => ms.justification.startsWith('Premisa') && formulasEqual(ms.formula, s.formula));
1560
+ const existing = mainSteps.find((ms) => ms.source === 'premise' && formulasEqual(ms.formula, s.formula));
1457
1561
  if (existing) {
1458
1562
  subStepMap.set(s.stepNumber, existing.stepNumber);
1459
1563
  continue;
@@ -1466,6 +1570,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1466
1570
  formula: s.formula,
1467
1571
  justification: s.justification,
1468
1572
  premises: s.premises.map((p) => subStepMap.get(p) || p),
1573
+ source: s.source,
1469
1574
  });
1470
1575
  }
1471
1576
  // Add final conditional proof step
@@ -1477,6 +1582,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1477
1582
  justification: 'Prueba Condicional (Teorema de Deduccion)',
1478
1583
  premises: [assumptionStepNum, subGoalStepNum],
1479
1584
  subproofs: [subProof],
1585
+ source: 'rule',
1480
1586
  });
1481
1587
  return buildProof(goal, mainSteps, premiseNames, theory, 'natural_deduction', [subProof]);
1482
1588
  }
@@ -1505,7 +1611,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1505
1611
  const subProofL = tryDerive(goal, tempTheoryL, subPremisesL, depth + 1);
1506
1612
  if (!subProofL || subProofL.status !== 'complete')
1507
1613
  continue;
1508
- const isSyntacticL = subProofL.steps.every((s) => !s.justification.startsWith('Verificacion semantica'));
1614
+ const isSyntacticL = subProofL.steps.every((s) => s.source !== 'semantic');
1509
1615
  if (!isSyntacticL)
1510
1616
  continue;
1511
1617
  // Try to derive goal assuming right
@@ -1522,7 +1628,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1522
1628
  const subProofR = tryDerive(goal, tempTheoryR, subPremisesR, depth + 1);
1523
1629
  if (!subProofR || subProofR.status !== 'complete')
1524
1630
  continue;
1525
- const isSyntacticR = subProofR.steps.every((s) => !s.justification.startsWith('Verificacion semantica'));
1631
+ const isSyntacticR = subProofR.steps.every((s) => s.source !== 'semantic');
1526
1632
  if (!isSyntacticR)
1527
1633
  continue;
1528
1634
  // Both cases succeed — build proof by cases
@@ -1530,7 +1636,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1530
1636
  let stepNum = 0;
1531
1637
  // Copy premise steps
1532
1638
  for (const s of state.steps) {
1533
- if (s.justification.startsWith('Premisa')) {
1639
+ if (s.source === 'premise') {
1534
1640
  stepNum++;
1535
1641
  mainSteps.push({ ...s, stepNumber: stepNum, premises: [] });
1536
1642
  }
@@ -1544,15 +1650,16 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1544
1650
  formula: left,
1545
1651
  justification: 'Supuesto (caso izquierdo)',
1546
1652
  premises: [],
1653
+ source: 'assumption',
1547
1654
  });
1548
1655
  const leftStepMap = new Map();
1549
1656
  for (const s of subProofL.steps) {
1550
- if (s.justification.startsWith('Premisa') && formulasEqual(s.formula, left)) {
1657
+ if (s.source === 'premise' && formulasEqual(s.formula, left)) {
1551
1658
  leftStepMap.set(s.stepNumber, leftAssumptionStep);
1552
1659
  continue;
1553
1660
  }
1554
- if (s.justification.startsWith('Premisa')) {
1555
- const existing = mainSteps.find((ms) => ms.justification.startsWith('Premisa') && formulasEqual(ms.formula, s.formula));
1661
+ if (s.source === 'premise') {
1662
+ const existing = mainSteps.find((ms) => ms.source === 'premise' && formulasEqual(ms.formula, s.formula));
1556
1663
  if (existing) {
1557
1664
  leftStepMap.set(s.stepNumber, existing.stepNumber);
1558
1665
  continue;
@@ -1565,6 +1672,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1565
1672
  formula: s.formula,
1566
1673
  justification: s.justification,
1567
1674
  premises: s.premises.map((p) => leftStepMap.get(p) || p),
1675
+ source: s.source,
1568
1676
  });
1569
1677
  }
1570
1678
  const leftGoalStep = leftStepMap.get(subProofL.steps[subProofL.steps.length - 1]?.stepNumber ?? 0) ?? stepNum;
@@ -1576,15 +1684,16 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1576
1684
  formula: right,
1577
1685
  justification: 'Supuesto (caso derecho)',
1578
1686
  premises: [],
1687
+ source: 'assumption',
1579
1688
  });
1580
1689
  const rightStepMap = new Map();
1581
1690
  for (const s of subProofR.steps) {
1582
- if (s.justification.startsWith('Premisa') && formulasEqual(s.formula, right)) {
1691
+ if (s.source === 'premise' && formulasEqual(s.formula, right)) {
1583
1692
  rightStepMap.set(s.stepNumber, rightAssumptionStep);
1584
1693
  continue;
1585
1694
  }
1586
- if (s.justification.startsWith('Premisa')) {
1587
- const existing = mainSteps.find((ms) => ms.justification.startsWith('Premisa') && formulasEqual(ms.formula, s.formula));
1695
+ if (s.source === 'premise') {
1696
+ const existing = mainSteps.find((ms) => ms.source === 'premise' && formulasEqual(ms.formula, s.formula));
1588
1697
  if (existing) {
1589
1698
  rightStepMap.set(s.stepNumber, existing.stepNumber);
1590
1699
  continue;
@@ -1597,6 +1706,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1597
1706
  formula: s.formula,
1598
1707
  justification: s.justification,
1599
1708
  premises: s.premises.map((p) => rightStepMap.get(p) || p),
1709
+ source: s.source,
1600
1710
  });
1601
1711
  }
1602
1712
  const rightGoalStep = rightStepMap.get(subProofR.steps[subProofR.steps.length - 1]?.stepNumber ?? 0) ?? stepNum;
@@ -1608,6 +1718,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1608
1718
  justification: 'Eliminacion de disyuncion (prueba por casos)',
1609
1719
  premises: [disjStepNum, leftGoalStep, rightGoalStep],
1610
1720
  subproofs: [subProofL, subProofR],
1721
+ source: 'rule',
1611
1722
  });
1612
1723
  return buildProof(goal, mainSteps, premiseNames, theory, 'natural_deduction', [
1613
1724
  subProofL,
@@ -1680,6 +1791,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1680
1791
  formula: goal,
1681
1792
  justification: 'Verificacion semantica (todas las valuaciones satisfacen la consecuencia)',
1682
1793
  premises: premiseStepNums,
1794
+ source: 'semantic',
1683
1795
  });
1684
1796
  state.known.set(goalHash, goal);
1685
1797
  }
@@ -1904,26 +2016,56 @@ class ClassicalPropositional {
1904
2016
  };
1905
2017
  }
1906
2018
  }
1907
- prove(goal, theory) {
2019
+ prove(goal, theory, premises) {
1908
2020
  const wf = this.checkWellFormed(goal);
1909
2021
  if (wf.length > 0) {
1910
2022
  return { status: 'error', diagnostics: wf, formula: goal };
1911
2023
  }
1912
- const premiseNames = Array.from(theory.axioms.keys());
1913
- const proof = tryDerive(goal, theory, premiseNames);
2024
+ const usingRestricted = premises !== undefined && premises.length > 0;
2025
+ const premiseNames = usingRestricted
2026
+ ? premises.filter((n) => theory.axioms.has(n) || theory.theorems.has(n))
2027
+ : Array.from(theory.axioms.keys());
2028
+ const diagnostics = [];
2029
+ if (usingRestricted) {
2030
+ for (const n of premises) {
2031
+ if (!theory.axioms.has(n) && !theory.theorems.has(n)) {
2032
+ diagnostics.push({
2033
+ severity: 'warning',
2034
+ message: `Premisa '${n}' no encontrada en la teoría; será ignorada en prove`,
2035
+ });
2036
+ }
2037
+ }
2038
+ }
2039
+ const effectiveTheory = usingRestricted
2040
+ ? {
2041
+ profile: theory.profile,
2042
+ axioms: new Map(premiseNames
2043
+ .filter((n) => theory.axioms.has(n))
2044
+ .map((n) => [n, theory.axioms.get(n)])),
2045
+ theorems: new Map(premiseNames
2046
+ .filter((n) => theory.theorems.has(n))
2047
+ .map((n) => [n, theory.theorems.get(n)])),
2048
+ claims: theory.claims,
2049
+ judgments: theory.judgments,
2050
+ }
2051
+ : theory;
2052
+ const proof = tryDerive(goal, effectiveTheory, premiseNames);
1914
2053
  if (proof && proof.status === 'complete') {
2054
+ const isSemantic = proof.method === 'semantic';
1915
2055
  return {
1916
2056
  status: 'provable',
1917
- output: `${formulaToString(goal)} es DEMOSTRABLE desde la teoria`,
2057
+ output: isSemantic
2058
+ ? `${formulaToString(goal)} es DEMOSTRABLE desde la teoria (verificación semántica, sin derivación sintáctica)`
2059
+ : `${formulaToString(goal)} es DEMOSTRABLE desde la teoria`,
1918
2060
  proof,
1919
2061
  educationalNote: (0, educational_notes_1.pickEducationalNote)({ op: 'prove', ok: true }),
1920
- diagnostics: [],
2062
+ diagnostics,
1921
2063
  formula: goal,
1922
2064
  };
1923
2065
  }
1924
2066
  // Semantic fallback: verify via SAT/truth-table whether goal follows from axioms
1925
2067
  const allAxiomFormulas = premiseNames
1926
- .map((n) => theory.axioms.get(n) || theory.theorems.get(n))
2068
+ .map((n) => effectiveTheory.axioms.get(n) || effectiveTheory.theorems.get(n))
1927
2069
  .filter((f) => f !== undefined);
1928
2070
  let semanticResult;
1929
2071
  const atoms = new Set();
@@ -1980,42 +2122,46 @@ class ClassicalPropositional {
1980
2122
  }
1981
2123
  }
1982
2124
  if (semanticResult) {
2125
+ const premiseSteps = [];
2126
+ premiseNames.forEach((n, i) => {
2127
+ const f = effectiveTheory.axioms.get(n) || effectiveTheory.theorems.get(n);
2128
+ if (f) {
2129
+ premiseSteps.push({
2130
+ stepNumber: i + 1,
2131
+ formula: f,
2132
+ justification: `Premisa (${n})`,
2133
+ premises: [],
2134
+ source: 'premise',
2135
+ });
2136
+ }
2137
+ });
1983
2138
  const semanticProofSteps = [
1984
- ...premiseNames
1985
- .map((n, i) => {
1986
- const f = theory.axioms.get(n) || theory.theorems.get(n);
1987
- return f
1988
- ? {
1989
- stepNumber: i + 1,
1990
- formula: f,
1991
- justification: `Premisa (${n})`,
1992
- premises: [],
1993
- }
1994
- : null;
1995
- })
1996
- .filter((s) => s !== null),
2139
+ ...premiseSteps,
1997
2140
  {
1998
2141
  stepNumber: premiseNames.length + 1,
1999
2142
  formula: goal,
2000
2143
  justification: 'Verificacion semantica (tautologia o consecuencia logica)',
2001
2144
  premises: premiseNames.map((_, i) => i + 1),
2145
+ source: 'semantic',
2002
2146
  },
2003
2147
  ];
2004
- const semanticProof = buildProof(goal, semanticProofSteps, premiseNames, theory, 'semantic');
2148
+ const semanticProof = buildProof(goal, semanticProofSteps, premiseNames, effectiveTheory, 'semantic');
2005
2149
  return {
2006
2150
  status: 'provable',
2007
- output: `${formulaToString(goal)} es DEMOSTRABLE desde la teoria`,
2151
+ output: `${formulaToString(goal)} es DEMOSTRABLE desde la teoria (verificación semántica, sin derivación sintáctica)`,
2008
2152
  proof: semanticProof,
2009
2153
  educationalNote: (0, educational_notes_1.pickEducationalNote)({ op: 'prove', ok: true }),
2010
- diagnostics: [],
2154
+ diagnostics,
2011
2155
  formula: goal,
2012
2156
  };
2013
2157
  }
2158
+ // Ni derivación sintáctica ni consecuencia semántica: existe contramodelo.
2159
+ // Esto sí es refutable en el sentido fuerte.
2014
2160
  return {
2015
2161
  status: 'refutable',
2016
- output: `${formulaToString(goal)} NO es demostrable desde la teoria dada`,
2162
+ output: `${formulaToString(goal)} NO se sigue de la teoría (existe contramodelo en ${formulaToString(goal)})`,
2017
2163
  educationalNote: (0, educational_notes_1.pickEducationalNote)({ op: 'prove', ok: false }),
2018
- diagnostics: [],
2164
+ diagnostics,
2019
2165
  formula: goal,
2020
2166
  };
2021
2167
  }
@@ -2029,14 +2175,17 @@ class ClassicalPropositional {
2029
2175
  // Build reasoning info
2030
2176
  const rulesUsed = new Set();
2031
2177
  for (const step of proof.steps) {
2032
- if (!step.justification.startsWith('Premisa')) {
2178
+ if (step.source !== 'premise') {
2033
2179
  rulesUsed.add(step.justification);
2034
2180
  }
2035
2181
  }
2036
2182
  const reasoningType = rulesUsed.size > 0 ? Array.from(rulesUsed).join(', ') : 'Derivación directa';
2183
+ const isSemantic = proof.method === 'semantic';
2037
2184
  return {
2038
2185
  status: 'provable',
2039
- output: `${formulaToString(goal)} derivado exitosamente`,
2186
+ output: isSemantic
2187
+ ? `${formulaToString(goal)} derivado (verificación semántica, sin derivación sintáctica)`
2188
+ : `${formulaToString(goal)} derivado exitosamente`,
2040
2189
  proof,
2041
2190
  reasoningType,
2042
2191
  reasoningSchema: rulesUsed.has('Modus Ponens')
@@ -2057,8 +2206,8 @@ class ClassicalPropositional {
2057
2206
  };
2058
2207
  }
2059
2208
  return {
2060
- status: 'refutable',
2061
- output: `No se puede derivar ${formulaToString(goal)} desde las premisas dadas`,
2209
+ status: 'unknown',
2210
+ output: `No se pudo derivar ${formulaToString(goal)} desde las premisas dadas (sin refutación)`,
2062
2211
  educationalNote: (0, educational_notes_1.pickEducationalNote)({ op: 'derive', ok: false }),
2063
2212
  diagnostics: [],
2064
2213
  formula: goal,