eyemind 0.1.31 → 0.1.32

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/SPEC.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ```text
4
4
  Title: The eyemind Rule Language and Proof Format
5
- Version: eyemind 0.1.31
5
+ Version: eyemind 0.1.32
6
6
  Status: Informational
7
7
  Author: Jos De Roo, KNoWS office of IDLab, Ghent University - imec
8
8
  Repository: https://github.com/eyereasoner/eyemind
@@ -22,7 +22,7 @@ command line.
22
22
  ## Status of This Memo
23
23
 
24
24
  This document is not an Internet Standards Track specification. It describes
25
- the language and formats as implemented by eyemind 0.1.31, for readers who want
25
+ the language and formats as implemented by eyemind 0.1.32, for readers who want
26
26
  to write programs, produce or consume proofs and reports, or implement a
27
27
  compatible reasoner or checker. Where this document and the implementation
28
28
  disagree, that is a defect in one of them.
@@ -820,9 +820,12 @@ forbidden ("strict"), each `'absent'` or `'collected'` step fails C5.
820
820
 
821
821
  A trusted boundary cannot be proved, but the evidence at hand can refute it.
822
822
  The evidence for a goal is: when the goal is a ground primitive, the goal
823
- itself if it holds; when it is a control, none, and the boundary is left
824
- undecided; otherwise the program's facts and the goals of the document's
825
- steps with the same name and arity.
823
+ itself if it holds, and otherwise the recomputed fact that it fails; when it
824
+ is a control, none, and the boundary is left undecided; otherwise the
825
+ program's facts and the goals of the document's steps with the same name and
826
+ arity. A goal of the last kind **has evidence** only when there is at least
827
+ one such fact or step goal; with none, nothing could refute the boundary, and
828
+ it is left undecided.
826
829
 
827
830
  - An absence `not(G)` is decided when `G` is a single goal, or a ground
828
831
  conjunction, whose every goal has evidence. It fails C6 when every goal of
@@ -1052,7 +1055,7 @@ conclusions and proof documents in the canonical text, and checks every proof
1052
1055
  it produces as Section 11 describes. A conforming **checker** implements
1053
1056
  Sections 9, 11 and 12 and does not depend on a reasoner. For the same
1054
1057
  program, a conforming reasoner and checker MUST produce the same
1055
- conclusions, proof documents and reports as eyemind 0.1.31, byte for byte,
1058
+ conclusions, proof documents and reports as eyemind 0.1.32, byte for byte,
1056
1059
  except for comments and the `Detail` texts of failures (Section 12), the internal names of
1057
1060
  variables where Section 3 says so, and where the host's floating-point
1058
1061
  library functions (`exp`, `log`, the trigonometric and hyperbolic functions,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyemind",
3
- "version": "0.1.31",
3
+ "version": "0.1.32",
4
4
  "description": "A dependency-free JavaScript rule language with forward and backward reasoning and checkable proofs.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
package/src/cli.js CHANGED
@@ -74,6 +74,12 @@ export function main(argv, io) {
74
74
  i++;
75
75
  if (i >= argv.length) throw new UsageError(`${arg} needs a value`);
76
76
  const value = argv[i];
77
+ // An option in the value's place means the value was left out, as in
78
+ // --check-proof --strict-proof proof.js; reading the option as a file
79
+ // name would only fail later with a puzzling message.
80
+ if (/^--./.test(value) || ['-p', '-c', '-h'].includes(value)) {
81
+ throw new UsageError(`${arg} needs a value right after it, not the option ${value}`);
82
+ }
77
83
  if (arg === '--check-proof') {
78
84
  proofFile = value;
79
85
  } else if (arg === '--goal') {
package/src/proof.js CHANGED
@@ -552,7 +552,9 @@ function checkBoundaries(program, steps, boundaries, fail) {
552
552
  const nextSerial = () => ++serial;
553
553
 
554
554
  // Each solution of a simple goal that the evidence shows, or null when the
555
- // evidence cannot speak for the goal.
555
+ // evidence cannot speak for the goal. A recomputed primitive always speaks,
556
+ // even when it fails; a predicate with no fact or step at all does not, so
557
+ // a boundary over it is left undecided rather than counted as confronted.
556
558
  function evidence(goal) {
557
559
  if (!isCallable(goal)) return null;
558
560
  const goalKey = key(goal);
@@ -567,13 +569,16 @@ function checkBoundaries(program, steps, boundaries, fail) {
567
569
  return [];
568
570
  }
569
571
  if (CONTROL_KEYS.has(goalKey)) return null;
572
+ let shown;
570
573
  if (INSPECTION_KEYS.has(goalKey)) {
571
- return program.inspections.get(goalKey).map((entry) => freshTerm(entry.term, `evidence${nextSerial()}`));
574
+ shown = program.inspections.get(goalKey).map((entry) => freshTerm(entry.term, `evidence${nextSerial()}`));
575
+ } else {
576
+ const facts = (program.groups.get(goalKey) || [])
577
+ .filter((clause) => !clause.body.length && !clause.forward)
578
+ .map((clause) => freshTerm(clause.head, `evidence${nextSerial()}`));
579
+ shown = [...facts, ...(stepGoals.get(goalKey) || []).map((item) => freshTerm(item, `evidence${nextSerial()}`))];
572
580
  }
573
- const facts = (program.groups.get(goalKey) || [])
574
- .filter((clause) => !clause.body.length && !clause.forward)
575
- .map((clause) => freshTerm(clause.head, `evidence${nextSerial()}`));
576
- return [...facts, ...(stepGoals.get(goalKey) || []).map((item) => freshTerm(item, `evidence${nextSerial()}`))];
581
+ return shown.length ? shown : null;
577
582
  }
578
583
 
579
584
  for (const boundary of boundaries) {
package/src/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // The release this checkout is; ./release keeps it in step with package.json.
2
- export const VERSION = '0.1.31';
2
+ export const VERSION = '0.1.32';