eyeprolog 1.5.53 → 1.5.54

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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.5.53",
6
+ "version": "1.5.54",
7
7
  "description": "EyeProlog turns facts and rules into answers and proofs.",
8
8
  "type": "module",
9
9
  "main": "./index.js",
@@ -131,10 +131,9 @@ Normal mode provides documented module and DCG compatibility profiles whose
131
131
  features overlap standardized Part 2 and Part 3 facilities. They are extensions
132
132
  relative to the Part 1 strict-core boundary and are tested separately; this
133
133
  ledger does not assert complete Part 2 or Part 3 conformance. The concrete
134
- compatibility boundary, including the normal-profile `phrase/2-3` terminal-sequence
135
- error choice, is recorded in `ISO-PART2-PART3-SCOPE.md`. The requirements
136
- clarified by the 2013 Part 2 amendment are tracked separately in the executable
137
- `ISO-PART2-AMENDMENT-2013.md` ledger.
134
+ per-directive and per-predicate boundary is recorded in `ISO-PART2.md` and
135
+ `ISO-PART3.md`, including the 2013 module-amendment evidence and the
136
+ normal-profile `phrase/2-3` terminal-sequence error choice.
138
137
 
139
138
  ## Important implementation-dependent behavior (not the 5.4 mandatory table)
140
139
 
@@ -0,0 +1,117 @@
1
+ # ISO/IEC 13211-2:2000 (Modules) — implementation status
2
+
3
+ This document records, predicate by predicate and directive by directive, what
4
+ EyeProlog implements of Prolog Part 2 (Modules). It is a status ledger, not a
5
+ conformance claim.
6
+
7
+ **EyeProlog does not claim Part 2 conformance.** What normal mode provides is a
8
+ procedure-oriented module *compatibility layer* built around the widespread
9
+ Quintus-style syntax. The ISO interface/body directive surface is not
10
+ implemented. `--iso-strict` targets Part 1 + Corrigenda 1-3 only and excludes
11
+ module directives and the `:` operator entirely.
12
+
13
+ ## Interface and body directives (ISO form)
14
+
15
+ Part 2 separates a module *interface* from one or more module *bodies*. None of
16
+ this surface is implemented; EyeProlog accepts only the compatibility syntax in
17
+ the next section.
18
+
19
+ | Directive | Part 2 role | Status |
20
+ | --- | --- | --- |
21
+ | `module/1` | begin the interface for a named module | **not implemented** |
22
+ | `export/1` | export locally defined procedures | **not implemented** |
23
+ | `reexport/2` | selectively import from another module and export again | **not implemented** |
24
+ | `reexport/1` | re-export the exports of named modules | **not implemented** |
25
+ | `metapredicate/1` | declare and export context-sensitive procedures (ISO spelling, no underscore) | **not implemented** |
26
+ | `op/3` in an interface | initial operators for this module's bodies only | **not implemented** — operator state is global |
27
+ | `char_conversion/2` in an interface | initial character conversions for this module's bodies only | **not implemented** — conversion state is global |
28
+ | `set_prolog_flag/2` in an interface | initial flag values for this module's bodies only | **not implemented** — flag state is global |
29
+ | `end_module/1` | end the interface | **not implemented** |
30
+ | `body/1` | begin a body of an already interfaced module | **not implemented** |
31
+ | `import/2` | selectively import exported procedures | **not implemented** |
32
+ | `import/1` | import all exports of named modules | **not implemented** |
33
+ | `end_body/1` | end the module body | **not implemented** |
34
+
35
+ ## Compatibility directives (what EyeProlog actually accepts)
36
+
37
+ | Directive | Status | Notes |
38
+ | --- | --- | --- |
39
+ | `module/2` | **implemented** | `:- module(Name, Exports).` Records the named module and its export map. Non-terminal indicators `A//N` are accepted in the export list. |
40
+ | `use_module/1` | **implemented** | Imports the full export map of the source module. |
41
+ | `use_module/2` | **implemented** | Selective import, validated against the source module's exports. |
42
+ | `meta_predicate/1` | **implemented** | Both `:- meta_predicate p(:).` and the parenthesized spelling. Numeric closure modes are a further EyeProlog extension. |
43
+ | `ensure_loaded/1` | **implemented** | Imports a module's public predicates while keeping source loading idempotent. |
44
+
45
+ Only one module body is supported per Prolog text: a second `module/2` in the
46
+ same text is rejected rather than switching modules mid-text. Part 2 allows a
47
+ module to have several non-contiguous bodies.
48
+
49
+ ## Built-in predicates
50
+
51
+ | Predicate | Part 2 requirement | Status |
52
+ | --- | --- | --- |
53
+ | `current_module/1` | enumerate existing modules and test a supplied name; `user` must exist | **not implemented** — raises `existence_error(procedure, current_module/1)` |
54
+ | `predicate_property/2` | module-aware predicate-property model | **not implemented** — raises `existence_error(procedure, predicate_property/2)` |
55
+ | `clause/2` | module-aware redefinition | **partial** — qualification is resolved, but against the compatibility model rather than Part 2 lookup/defining-module rules |
56
+ | `current_predicate/1` | module-aware redefinition | **partial** — as above |
57
+ | `asserta/1` | module-aware redefinition | **partial** — as above |
58
+ | `assertz/1` | module-aware redefinition | **partial** — as above |
59
+ | `retract/1` | module-aware redefinition | **partial** — as above |
60
+ | `abolish/1` | module-aware redefinition | **partial** — as above |
61
+
62
+ The six *partial* rows share one cause: EyeProlog resolves `Module:Goal` and
63
+ tracks a single module per goal, whereas Part 2 distinguishes defining module,
64
+ lookup module, qualifying module, and calling context. Ordinary calls make
65
+ these coincide, so the difference shows up in meta-calls and nested
66
+ qualification rather than in everyday use.
67
+
68
+ ## Operators and flags
69
+
70
+ | Item | Part 2 requirement | Status |
71
+ | --- | --- | --- |
72
+ | `:` operator | added to the initial operator table as `op(600, xfy, :)` | **implemented** in normal mode (`current_op(600, xfy, ':')`); deliberately absent from the Part 1 strict initial table |
73
+ | `colon_sets_calling_context` | a Boolean flag governing whether explicit qualification establishes calling context | **not implemented** — `current_prolog_flag/2` raises `domain_error(prolog_flag, colon_sets_calling_context)` |
74
+
75
+ ## 2013 amendment (WG17 N251) coverage
76
+
77
+ The requirements clarified by the 2013 amendment draft have executable evidence
78
+ in `test/run-iso-part2-amendment.mjs`, which is part of `npm test` and the
79
+ conformance aggregate. This is the one part of the Part 2 surface that is
80
+ release-gated.
81
+
82
+ | Amendment clause | Required behaviour | EyeProlog behaviour / evidence |
83
+ | --- | --- | --- |
84
+ | 6.2.4.1 | A `module(Name, Exports)` directive identifies a named module and its public predicate indicators. | `Program.defineModule()` records the named module and export map. The focused suite checks that public predicates import and private predicates stay module-local. |
85
+ | 6.2.5 | A module body is a Prolog text beginning with its `module/2` directive and extending to the end of that text. | Files named by `use_module/1-2` are accepted as module sources only when their first read term is `module/2`. A second `module/2` in the same text is rejected; a distinct text may begin a distinct module body. |
86
+ | 6.2.5.5 | `use_module(F, L)` selectively imports the predicates in `L` from the exports of the module defined by `F`. | `Program.importModule()` validates requested indicators against the source module's export map and installs only those imports. |
87
+ | 6.2.5.6 | `use_module(F)` imports all exported predicates; the amendment also aligns the public-predicate effect of `ensure_loaded(F)` for a module source. | `use_module/1` imports the full export map. `ensure_loaded/1` imports a module's public predicates while retaining idempotent source loading, including when the module was already loaded for another caller. |
88
+ | 6.2.5.7 | `meta_predicate/1` marks context-sensitive arguments; `:` arguments carry the current source/calling module. | Normal parsing accepts `:- meta_predicate p(:).`. Colon-mode arguments are represented as an observable `Module:Goal` term, including when the argument is a variable. |
89
+ | 6.4.4.3 | Imported metapredicates preserve the caller's module context for their meta-arguments. | The focused suite verifies both visible `Module:Goal` decomposition and execution of a caller-private predicate through a variable meta-argument. Explicit `Module:Goal` calls set their stated module context. |
90
+
91
+ ## Known gaps
92
+
93
+ Beyond the *not implemented* rows above, four structural gaps stand between the
94
+ current compatibility layer and a Part 2 claim.
95
+
96
+ 1. **Module-local reader/writer state.** Part 2 makes a calling context include
97
+ the operator table, character-conversion mapping, and relevant flag values,
98
+ not just a set of visible procedures. EyeProlog keeps operators, conversions,
99
+ and flags in one global program state, so interface-local environment
100
+ settings cannot be expressed. This is the largest single item.
101
+ 2. **Four separate module notions.** Defining, lookup, qualifying, and calling
102
+ context are collapsed into one module field per goal.
103
+ 3. **Re-export and visibility conflicts.** There is no re-export model, and no
104
+ preparation-time rejection of a second import that would make a *different*
105
+ procedure visible under the same unqualified indicator.
106
+ 4. **Introspection.** `current_module/1` and `predicate_property/2` are absent,
107
+ so the module structure is not observable from within a program.
108
+
109
+ Interoperability with Scryer, Trealla, or Logtalk is not treated as evidence of
110
+ Part 2 coverage.
111
+
112
+ ## See also
113
+
114
+ - `ISO-PART3.md` — Part 3 (definite clause grammar rules) status
115
+ - `ISO-COMPLIANCE.md` — the Part 1 review that carries the release-facing claim
116
+ - `ISO-IMPLEMENTATION-DEFINED.md` — implementation-defined choices, including
117
+ the module-qualification error choice
@@ -0,0 +1,99 @@
1
+ # ISO/IEC 13211-3 (Definite clause grammar rules) — implementation status
2
+
3
+ This document records what EyeProlog implements of Prolog Part 3, non-terminal
4
+ by non-terminal and predicate by predicate. It is a status ledger, not a
5
+ conformance claim.
6
+
7
+ Normal mode implements the whole grammar surface below. `--iso-strict` leaves
8
+ `-->/2` as ordinary Part 1 operator syntax and excludes grammar expansion and
9
+ `phrase/2-3` from the strict registry, so `phrase/2` there raises
10
+ `existence_error(procedure, phrase/2)`.
11
+
12
+ ## Grammar control constructs (clause 7.14)
13
+
14
+ | Clause | Construct | Status |
15
+ | --- | --- | --- |
16
+ | 7.14.1 | `[]//0` — empty terminal-sequence | **implemented** |
17
+ | 7.14.2 | `('.')//2` — terminal sequence | **implemented** |
18
+ | 7.14.3 | `(',')//2` — concatenation | **implemented** |
19
+ | 7.14.4 | `(;)//2` — alternative | **implemented** |
20
+ | 7.14.5 | `(;)//2` with `(->)//2` — if-then-else | **implemented** |
21
+ | 7.14.6 | `('\|')//2` — second form of alternative | **implemented** |
22
+ | 7.14.7 | `{}//1` — grammar-body-goal | **implemented** |
23
+ | 7.14.8 | `call//1` | **implemented** |
24
+ | 7.14.9 | `phrase//1` | **implemented** |
25
+ | 7.14.10 | `!//0` — grammar-body-cut | **implemented** |
26
+ | 7.14.11 | `(\+)//1` — grammar-body-not | **implemented** |
27
+ | 7.14.12 | `(->)//2` — if-then | **implemented** |
28
+
29
+ ## Built-in predicates (clause 8.18)
30
+
31
+ | Clause | Predicate | Status |
32
+ | --- | --- | --- |
33
+ | 8.18.1 | `phrase/3` | **implemented** |
34
+ | 8.18.1.3 | `phrase/2` (bootstrapped as `phrase(GRBody, S0, [])`) | **implemented** |
35
+
36
+ ### Prescribed errors (8.18.1.4)
37
+
38
+ | Error | Requirement | EyeProlog |
39
+ | --- | --- | --- |
40
+ | a) `GRBody` is a variable | `instantiation_error` | **matches** |
41
+ | b) `GRBody` is neither a variable nor callable | `type_error(callable, GRBody)` | **matches** |
42
+ | c) `S0` is not a terminal-sequence | `type_error(terminal_sequence, S0)` — implementation-defined for `phrase/3`, **required for `phrase/2`** | **diverges**: EyeProlog raises `type_error(list, S0)` |
43
+ | d) `S` is not a terminal-sequence | `type_error(terminal_sequence, S)` — implementation-defined | **diverges**: EyeProlog raises `type_error(list, S)` |
44
+
45
+ **Open divergence.** EyeProlog performs both optional checks — which the draft
46
+ permits, and which for `phrase/2` clause c it requires — but reports
47
+ `type_error(list, Culprit)` where the 2023-08-14 draft specifies
48
+ `type_error(terminal_sequence, Culprit)`. The draft is explicit that if a
49
+ processor offers these errors, "their form and consequence must be the
50
+ following", so the *form* is not left open even though performing the check is.
51
+
52
+ This appears to track an earlier edition, in which these clauses were numbered
53
+ 8.18.1.3 g and h and specified `list`. The behaviour is deliberate and covered
54
+ by a dedicated regression matrix, so changing the error term is a decision to
55
+ take explicitly rather than a bug to patch silently. Until it is taken, this
56
+ row is the one known Part 3 deviation.
57
+
58
+ What the regression matrix does pin, independently of the error term: the same
59
+ diagnostic across both arities, both sequence positions, atomic and compound
60
+ non-lists, and improper lists at several depths; the culprit is the whole
61
+ invalid argument, including an improper list, not just its tail; variables,
62
+ proper lists, and partial lists are accepted; and for otherwise valid grammar
63
+ bodies, validation precedes execution even when the grammar would fail or
64
+ produce a side effect. The upstream phrase quads permit both checking and
65
+ non-checking outcomes and so do not establish this consistency on their own.
66
+
67
+ ## Language concepts
68
+
69
+ | Clause | Concept | Status |
70
+ | --- | --- | --- |
71
+ | 7.4.4 | grammar rules in Prolog text | **implemented** |
72
+ | 7.5.1 | grammar-rule expansion during preparation | **implemented** |
73
+ | 7.13.1 | terminals and non-terminals | **implemented** |
74
+ | 7.13.2 | format of grammar rules | **implemented** |
75
+ | 7.13.3 | semicontext (pushback) | **implemented** — `head, [Pushback] --> Body` |
76
+ | 7.13.4 | non-terminal indicator `A//N` | **implemented** — accepted in module export lists |
77
+ | 7.15 | executing clauses expanded from grammar rules | **implemented** |
78
+ | 5.5.2 | predefined operators | **implemented** — `-->` is predeclared in both profiles; it is grammar syntax only in normal mode |
79
+
80
+ `predicate_property/2` does not appear in the 2023-08-14 draft, so no Part 3
81
+ predicate-property extension is claimed here. See `ISO-PART2.md` for the Part 2
82
+ status of that predicate.
83
+
84
+ ## Executable evidence
85
+
86
+ Grammar expansion, sequence validation, grammar-body callability, variable-body
87
+ instantiation errors, and `phrase/3` steadfastness are under focused tests in
88
+ `test/run-regression.mjs` and the conformance corpus. The live Neumerkel gate
89
+ covers the upstream phrase quads.
90
+
91
+ Changes intended to advance a formal Part 3 claim should update this ledger and
92
+ the corresponding error cases rather than silently changing the compatibility
93
+ profile.
94
+
95
+ ## See also
96
+
97
+ - `ISO-PART2.md` — Part 2 (modules) status
98
+ - `ISO-COMPLIANCE.md` — the Part 1 review that carries the release-facing claim
99
+ - `NEUMERKEL-LIVE.md` — the live upstream gate
@@ -16,10 +16,11 @@ closes 7.9/Clause 9, and [ISO-PROCESSOR-REQUIREMENTS.md](ISO-PROCESSOR-REQUIREME
16
16
  decomposes the Clause 5 processor obligations.
17
17
  [ISO-CORRIGENDA-MATRIX.md](ISO-CORRIGENDA-MATRIX.md) gives every published
18
18
  Corrigenda amendment cluster an executable, editorial, or superseded
19
- disposition. [ISO-PART2-AMENDMENT-2013.md](ISO-PART2-AMENDMENT-2013.md) maps the
20
- 2013 module-amendment requirements to executable evidence, while
21
- [ISO-PART2-PART3-SCOPE.md](ISO-PART2-PART3-SCOPE.md) records the broader
22
- normal-profile module/DCG compatibility boundary and known non-claims. Built-in rows may group closely related conditions only when the
19
+ disposition. [ISO-PART2.md](ISO-PART2.md) and [ISO-PART3.md](ISO-PART3.md) record,
20
+ directive by directive and predicate by predicate, what the normal profile
21
+ implements of Part 2 (modules) and Part 3 (definite clause grammar rules),
22
+ including the 2013 module-amendment evidence and the known gaps and deviations.
23
+ Neither part carries a conformance claim. Built-in rows may group closely related conditions only when the
23
24
  row names every grouped condition and its executable evidence.
24
25
  The exit checklist is embedded in [ISO-COMPLIANCE.md](ISO-COMPLIANCE.md). [WG17-SYNTAX-STATUS.md](WG17-SYNTAX-STATUS.md) records the
25
26
  complete one-to-one trace for the vendored active upstream WG17 syntax cases.
@@ -5883,7 +5883,9 @@ Variables, proper lists, and partial lists pass these checks. Validation
5883
5883
  precedes grammar execution; an otherwise valid failing grammar does not
5884
5884
  suppress the diagnostic. Dedicated regressions enforce this policy separately
5885
5885
  from the portable quads, which accept both checking and non-checking outcomes. See
5886
- [`ISO-PART2-PART3-SCOPE.md`](test/conformance/ISO-PART2-PART3-SCOPE.md).
5886
+ [`ISO-PART3.md`](test/conformance/ISO-PART3.md), which also records that the
5887
+ 2023-08-14 working draft specifies `type_error(terminal_sequence, Culprit)` for
5888
+ this condition.
5887
5889
 
5888
5890
  #### A bidirectional expression grammar
5889
5891
 
@@ -1,36 +0,0 @@
1
- # ISO/IEC 13211-2 module amendment (2013) coverage
2
-
3
- This ledger maps EyeProlog's normal module profile to the requirements clarified
4
- by the attached 2013 ISO/IEC 13211-2 amendment draft (WG17 N251). It is narrowly
5
- scoped to that amendment. It does **not** turn the broader ISO/IEC 13211-2:2000
6
- base document into a release-facing certification claim; unchanged Part 2
7
- facilities outside the amendment still need their own clause-by-clause review.
8
-
9
- Executable evidence lives in `test/run-iso-part2-amendment.mjs` and is included
10
- in both `npm test` and the conformance aggregate.
11
-
12
- | Amendment clause | Required behavior | EyeProlog behavior / evidence |
13
- | --- | --- | --- |
14
- | 6.2.4.1 | A `module(Name, Exports)` directive identifies a named module and its public predicate indicators. | `Program.defineModule()` records the named module and export map. The focused suite checks that public predicates import and private predicates remain module-local. |
15
- | 6.2.5 | A module body is a Prolog text beginning with its `module/2` directive and extending to the end of that text. | Files designated by `use_module/1-2` are accepted as module sources only when their first read term is `module/2`. A second `module/2` later in the same Prolog text is rejected rather than switching modules mid-text, while a distinct Prolog text may begin a distinct module body. |
16
- | 6.2.5.5 | `use_module(F, L)` selectively imports the predicates in `L` from the exports of the module defined by `F`. | `Program.importModule()` validates requested indicators against the source module's export map and installs only those imports. The focused suite verifies selective import. |
17
- | 6.2.5.6 | `use_module(F)` imports all exported predicates; the amendment also aligns the public-predicate effect of `ensure_loaded(F)` for a module source. | `use_module/1` imports the full export map. `ensure_loaded/1` now imports a module's public predicates while retaining idempotent source loading, including when the same module was already loaded for another caller. |
18
- | 6.2.5.7 | `meta_predicate/1` marks context-sensitive arguments; `:` arguments carry the current source/calling module. | Normal parsing accepts the amendment spelling `:- meta_predicate p(:).`. Colon-mode arguments are represented as an observable `Module:Goal` term, including when the argument is a variable. Numeric closure modes remain a separate compatibility extension. |
19
- | 6.4.4.3 | Imported metapredicates preserve the caller's module context for their meta-arguments. | The focused suite verifies both visible `Module:Goal` decomposition and execution of a caller-private predicate through a variable meta-argument. Explicit `Module:Goal` calls continue to set their stated module context. |
20
-
21
- ## Operator boundary
22
-
23
- ISO/IEC 13211-2 adds `:` as the module-qualification operator relative to the
24
- Part 1 initial operator table. EyeProlog therefore predeclares `:` only in its
25
- normal module profile; `--iso-strict` no longer includes it in the Part 1
26
- initial table. Normal mode also predeclares `meta_predicate` as a directive
27
- operator so the amendment's source spelling is accepted, while the parenthesized
28
- `meta_predicate(...)` compatibility spelling remains valid.
29
-
30
- ## Remaining Part 2 scope
31
-
32
- The amendment coverage above is executable and release-gated. EyeProlog still
33
- describes the overall Part 2 surface as a compatibility profile until the
34
- unchanged portions of ISO/IEC 13211-2:2000 - including its broader module
35
- interface and re-export model - have a complete processor/semantics ledger.
36
- See `ISO-PART2-PART3-SCOPE.md` for that release boundary.
@@ -1,71 +0,0 @@
1
- # ISO Part 2 and Part 3 compatibility scope
2
-
3
- EyeProlog's release-facing `--iso-strict` claim is deliberately limited to
4
- ISO/IEC 13211-1:1995 together with Technical Corrigenda 1:2007, 2:2012, and
5
- 3:2017. This note records the separate status of the normal-profile facilities
6
- that overlap ISO/IEC 13211-2:2000 (modules) and ISO/IEC TS 13211-3:2025 (definite
7
- clause grammar rules). It is a scope ledger, not an independent certification.
8
-
9
- ## Part 2 modules
10
-
11
- Normal mode implements a procedure-oriented module compatibility layer:
12
- `module/2`, `use_module/1-2`, `meta_predicate/1`, explicit `Module:Goal`
13
- qualification, exports/imports, nonterminal indicators, and module-aware meta
14
- calls are covered by the regression and conformance corpora.
15
-
16
- The requirements clarified by the 2013 ISO/IEC 13211-2 module amendment draft
17
- (WG17 N251) now have a dedicated executable ledger in
18
- `ISO-PART2-AMENDMENT-2013.md`: module/2 exports, selective and full imports, the
19
- module-source behavior of ensure_loaded/1, the amendment's meta_predicate
20
- directive spelling, and visible caller-module qualification of `:`
21
- meta-arguments. The focused runner is part of the release gate.
22
-
23
- This amendment coverage is intentionally narrower than a complete Part 2
24
- conformance claim. In particular, the Part 1 strict registry does not enable
25
- module directives or the Part 2 `:` operator, and the project does not infer
26
- full Part 2 coverage from interoperability with Scryer, Trealla, or Logtalk. A
27
- future complete Part 2 claim would require a clause-by-clause review of the
28
- unchanged ISO/IEC 13211-2:2000 module-interface and re-export facilities as well
29
- as the amendment.
30
-
31
- ## Part 3 definite clause grammars
32
-
33
- Normal mode expands grammar rules to ordinary predicates and supports terminal
34
- sequences, sequencing, alternatives, semicontexts, embedded goals, cut,
35
- `call//1`, `phrase//1`, `phrase/2-3`, module-qualified nonterminals, and the
36
- implementation-dependent negation/if-then choices documented in the reference.
37
- `--iso-strict` leaves `-->/2` as ordinary Part 1 operator syntax and excludes
38
- Part 3 grammar expansion and `phrase/2-3` from the strict registry.
39
-
40
- EyeProlog elects to perform both implementation-defined terminal-sequence
41
- checks in ISO/IEC TS 13211-3:2025, 8.18.1.3 g and h. The checks are optional;
42
- when performed, their specified error type is `list`. EyeProlog consistently
43
- raises `type_error(list, Culprit)` for a non-list input to `phrase/2` or
44
- `phrase/3`, and for a non-list remainder to `phrase/3`. The culprit is the
45
- whole invalid argument, including an improper list, not just its tail.
46
- Variables, proper lists, and partial lists are accepted by these checks.
47
- For otherwise valid grammar bodies, validation precedes execution, even when
48
- the grammar would fail or produce a side effect.
49
-
50
- The upstream phrase quads permit both checking and non-checking outcomes and
51
- therefore do not establish this consistency. A dedicated regression matrix in
52
- `test/run-regression.mjs` requires the exact diagnostic across both arities,
53
- both sequence positions, atomic and compound non-lists, improper lists at
54
- several depths, and several grammar bodies. Positive cases protect variables,
55
- proper lists, and partial lists. These are policy checks, not a relaxation of
56
- the unmodified upstream corpus.
57
-
58
- The Part 3 implementation otherwise keeps sequence validation, grammar-body
59
- callability, variable-body instantiation errors, `phrase/3` steadfastness, and
60
- grammar expansion under focused executable tests. Changes intended to advance a
61
- formal Part 3 claim should update this ledger and the corresponding error cases
62
- rather than silently changing the compatibility profile.
63
-
64
- ## Release boundary
65
-
66
- - Part 1 + Corrigenda 1-3: release-facing strict-core conformance target.
67
- - Part 2: 2013 amendment requirements release-gated; broader Part 2 remains a normal-mode compatibility profile, not a complete certification.
68
- - Part 3: normal-mode compatibility profile, tested but not certified complete.
69
-
70
- This separation keeps Part 1 conformance evidence independent of useful module
71
- and DCG extensions while making known Part 2/Part 3 scope limits visible.