@proposit/proposit-core 0.12.3 → 1.0.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.
- package/README.md +104 -93
- package/dist/cli/commands/premises.d.ts.map +1 -1
- package/dist/cli/commands/premises.js +28 -24
- package/dist/cli/commands/premises.js.map +1 -1
- package/dist/cli/commands/repair.d.ts.map +1 -1
- package/dist/cli/commands/repair.js +4 -2
- package/dist/cli/commands/repair.js.map +1 -1
- package/dist/cli/commands/validate.d.ts.map +1 -1
- package/dist/cli/commands/validate.js +7 -1
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/engine.d.ts.map +1 -1
- package/dist/cli/engine.js +7 -25
- package/dist/cli/engine.js.map +1 -1
- package/dist/cli/import.d.ts.map +1 -1
- package/dist/cli/import.js +66 -28
- package/dist/cli/import.js.map +1 -1
- package/dist/lib/core/argument-engine.d.ts +275 -10
- package/dist/lib/core/argument-engine.d.ts.map +1 -1
- package/dist/lib/core/argument-engine.js +442 -82
- package/dist/lib/core/argument-engine.js.map +1 -1
- package/dist/lib/core/argument-library.d.ts +5 -1
- package/dist/lib/core/argument-library.d.ts.map +1 -1
- package/dist/lib/core/argument-library.js +7 -3
- package/dist/lib/core/argument-library.js.map +1 -1
- package/dist/lib/core/expression-manager.d.ts +68 -73
- package/dist/lib/core/expression-manager.d.ts.map +1 -1
- package/dist/lib/core/expression-manager.js +242 -762
- package/dist/lib/core/expression-manager.js.map +1 -1
- package/dist/lib/core/fork.d.ts +5 -1
- package/dist/lib/core/fork.d.ts.map +1 -1
- package/dist/lib/core/fork.js +16 -6
- package/dist/lib/core/fork.js.map +1 -1
- package/dist/lib/core/interfaces/argument-engine.interfaces.d.ts +68 -7
- package/dist/lib/core/interfaces/argument-engine.interfaces.d.ts.map +1 -1
- package/dist/lib/core/interfaces/library.interfaces.d.ts +8 -3
- package/dist/lib/core/interfaces/library.interfaces.d.ts.map +1 -1
- package/dist/lib/core/interfaces/premise-engine.interfaces.d.ts +50 -47
- package/dist/lib/core/interfaces/premise-engine.interfaces.d.ts.map +1 -1
- package/dist/lib/core/premise-engine.d.ts +80 -11
- package/dist/lib/core/premise-engine.d.ts.map +1 -1
- package/dist/lib/core/premise-engine.js +232 -80
- package/dist/lib/core/premise-engine.js.map +1 -1
- package/dist/lib/core/proposit-core.d.ts.map +1 -1
- package/dist/lib/core/proposit-core.js +13 -3
- package/dist/lib/core/proposit-core.js.map +1 -1
- package/dist/lib/grammar/an-rules.d.ts +158 -0
- package/dist/lib/grammar/an-rules.d.ts.map +1 -0
- package/dist/lib/grammar/an-rules.js +778 -0
- package/dist/lib/grammar/an-rules.js.map +1 -0
- package/dist/lib/grammar/auto-normalize.d.ts +14 -0
- package/dist/lib/grammar/auto-normalize.d.ts.map +1 -0
- package/dist/lib/grammar/auto-normalize.js +35 -0
- package/dist/lib/grammar/auto-normalize.js.map +1 -0
- package/dist/lib/grammar/bounded-subtree.d.ts +30 -0
- package/dist/lib/grammar/bounded-subtree.d.ts.map +1 -0
- package/dist/lib/grammar/bounded-subtree.js +74 -0
- package/dist/lib/grammar/bounded-subtree.js.map +1 -0
- package/dist/lib/grammar/naked-q.d.ts +20 -0
- package/dist/lib/grammar/naked-q.d.ts.map +1 -0
- package/dist/lib/grammar/naked-q.js +58 -0
- package/dist/lib/grammar/naked-q.js.map +1 -0
- package/dist/lib/grammar/normalize.d.ts +12 -0
- package/dist/lib/grammar/normalize.d.ts.map +1 -0
- package/dist/lib/grammar/normalize.js +45 -0
- package/dist/lib/grammar/normalize.js.map +1 -0
- package/dist/lib/grammar/populate-from.d.ts +25 -0
- package/dist/lib/grammar/populate-from.d.ts.map +1 -0
- package/dist/lib/grammar/populate-from.js +252 -0
- package/dist/lib/grammar/populate-from.js.map +1 -0
- package/dist/lib/grammar/repair.d.ts +65 -0
- package/dist/lib/grammar/repair.d.ts.map +1 -0
- package/dist/lib/grammar/repair.js +251 -0
- package/dist/lib/grammar/repair.js.map +1 -0
- package/dist/lib/grammar/types.d.ts +17 -0
- package/dist/lib/grammar/types.d.ts.map +1 -0
- package/dist/lib/grammar/types.js +82 -0
- package/dist/lib/grammar/types.js.map +1 -0
- package/dist/lib/grammar/validate.d.ts +4 -0
- package/dist/lib/grammar/validate.d.ts.map +1 -0
- package/dist/lib/grammar/validate.js +28 -0
- package/dist/lib/grammar/validate.js.map +1 -0
- package/dist/lib/grammar/validators/context.d.ts +11 -0
- package/dist/lib/grammar/validators/context.d.ts.map +1 -0
- package/dist/lib/grammar/validators/context.js +5 -0
- package/dist/lib/grammar/validators/context.js.map +1 -0
- package/dist/lib/grammar/validators/derivable.d.ts +63 -0
- package/dist/lib/grammar/validators/derivable.d.ts.map +1 -0
- package/dist/lib/grammar/validators/derivable.js +502 -0
- package/dist/lib/grammar/validators/derivable.js.map +1 -0
- package/dist/lib/grammar/validators/evaluable.d.ts +48 -0
- package/dist/lib/grammar/validators/evaluable.d.ts.map +1 -0
- package/dist/lib/grammar/validators/evaluable.js +226 -0
- package/dist/lib/grammar/validators/evaluable.js.map +1 -0
- package/dist/lib/grammar/validators/presentable.d.ts +45 -0
- package/dist/lib/grammar/validators/presentable.d.ts.map +1 -0
- package/dist/lib/grammar/validators/presentable.js +231 -0
- package/dist/lib/grammar/validators/presentable.js.map +1 -0
- package/dist/lib/grammar/validators/structural.d.ts +103 -0
- package/dist/lib/grammar/validators/structural.d.ts.map +1 -0
- package/dist/lib/grammar/validators/structural.js +602 -0
- package/dist/lib/grammar/validators/structural.js.map +1 -0
- package/dist/lib/index.d.ts +4 -3
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +2 -2
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/parsing/argument-parser.d.ts.map +1 -1
- package/dist/lib/parsing/argument-parser.js +52 -10
- package/dist/lib/parsing/argument-parser.js.map +1 -1
- package/dist/lib/types/evaluation.d.ts +1 -1
- package/dist/lib/types/evaluation.d.ts.map +1 -1
- package/dist/lib/types/fork.d.ts +12 -3
- package/dist/lib/types/fork.d.ts.map +1 -1
- package/dist/lib/types/validation.d.ts +0 -6
- package/dist/lib/types/validation.d.ts.map +1 -1
- package/dist/lib/types/validation.js +23 -6
- package/dist/lib/types/validation.js.map +1 -1
- package/package.json +1 -1
- package/dist/lib/core/managed-derivation-premise-engine.d.ts +0 -172
- package/dist/lib/core/managed-derivation-premise-engine.d.ts.map +0 -1
- package/dist/lib/core/managed-derivation-premise-engine.js +0 -550
- package/dist/lib/core/managed-derivation-premise-engine.js.map +0 -1
- package/dist/lib/types/grammar.d.ts +0 -83
- package/dist/lib/types/grammar.d.ts.map +0 -1
- package/dist/lib/types/grammar.js +0 -24
- package/dist/lib/types/grammar.js.map +0 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { isClaimBound, isPremiseBound, } from "../schemata/index.js";
|
|
2
|
-
import {
|
|
3
|
-
import { AXIOM_VARIABLE_ASSIGNMENT_FORBIDDEN, CLAIM_NOT_FOUND, CREATE_DERIVATION_CLAIM_NOT_FOUND, CREATE_DERIVATION_REQUIRES_DERIVED_CLAIM_ID, DERIVATION_STRUCTURE_INVALID_AT_EVALUATION, } from "../types/validation.js";
|
|
2
|
+
import { AXIOM_VARIABLE_ASSIGNMENT_FORBIDDEN, CLAIM_NOT_FOUND, CREATE_DERIVATION_CLAIM_NOT_FOUND, CREATE_DERIVATION_REQUIRES_DERIVED_CLAIM_ID, } from "../types/validation.js";
|
|
4
3
|
import { validateDerivationStructure } from "../utils/derivation-validation.js";
|
|
5
4
|
import { DEFAULT_CHECKSUM_CONFIG, normalizeChecksumConfig, serializeChecksumConfig, } from "../consts.js";
|
|
6
5
|
import { ChangeCollector } from "./change-collector.js";
|
|
@@ -8,6 +7,12 @@ import { canonicalSerialize, computeHash, entityChecksum } from "./checksum.js";
|
|
|
8
7
|
import { evaluateArgument as evaluateArgumentStandalone, checkArgumentValidity as checkArgumentValidityStandalone, } from "./evaluation/argument-evaluation.js";
|
|
9
8
|
import { makeErrorIssue, makeValidationResult, } from "./evaluation/validation.js";
|
|
10
9
|
import { validateArgument as validateArgumentStandalone, validateArgumentAfterPremiseMutation as validateAfterPremiseMutationStandalone, validateArgumentEvaluability as validateArgumentEvaluabilityStandalone, collectArgumentReferencedVariables as collectArgumentReferencedVariablesStandalone, } from "./argument-validation.js";
|
|
10
|
+
import { normalizeArgument } from "../grammar/normalize.js";
|
|
11
|
+
import { runAssistiveNormalization } from "../grammar/auto-normalize.js";
|
|
12
|
+
import { isNakedQDerivationPremise } from "../grammar/naked-q.js";
|
|
13
|
+
import { populateFromGrounding as populateFromGroundingImpl, } from "../grammar/populate-from.js";
|
|
14
|
+
import { removeUnresolvableVariables as removeUnresolvableVariablesImpl, removeOrphanOperators as removeOrphanOperatorsImpl, removeDuplicateDerivationPremises as removeDuplicateDerivationPremisesImpl, dropAxiomsFromMixedAntecedent as dropAxiomsFromMixedAntecedentImpl, } from "../grammar/repair.js";
|
|
15
|
+
import { validate as validateGrammar } from "../grammar/validate.js";
|
|
11
16
|
import { InvariantViolationError } from "./invariant-violation-error.js";
|
|
12
17
|
import { PremiseEngine } from "./premise-engine.js";
|
|
13
18
|
import { VariableManager } from "./variable-manager.js";
|
|
@@ -28,9 +33,24 @@ export class ArgumentEngine {
|
|
|
28
33
|
conclusionPremiseId;
|
|
29
34
|
checksumConfig;
|
|
30
35
|
positionConfig;
|
|
31
|
-
|
|
36
|
+
engineBehavior;
|
|
32
37
|
generateId;
|
|
33
38
|
restoringFromSnapshot = false;
|
|
39
|
+
// D2b — re-entrance guard for the AN post-mutation hook. The
|
|
40
|
+
// `setOnMutate` callbacks (3 sites: createPremise, fromSnapshot,
|
|
41
|
+
// restoreFromSnapshot) fire `runAssistiveNormalization(this)` after
|
|
42
|
+
// every successful mutation when `behavior === 'assistive'`. AN
|
|
43
|
+
// itself mutates premises (removeExpression / reparentExpression /
|
|
44
|
+
// wrapInFormula), which re-fires `setOnMutate`. Without a guard the
|
|
45
|
+
// outer mutation would trigger nested AN sweeps. The guard is
|
|
46
|
+
// toggled by `_beginApplyAN()` / `_endApplyAN()` (see below); the
|
|
47
|
+
// chokepoint is `applyANToFixedPoint` in
|
|
48
|
+
// `src/lib/grammar/an-rules.ts`, so both
|
|
49
|
+
// `runAssistiveNormalization` (post-hook) and `normalizeArgument`
|
|
50
|
+
// (`engine.normalize()`) are covered by the same gate. The
|
|
51
|
+
// accessor pair is `beginApplyAN()` / `endApplyAN()` below
|
|
52
|
+
// (marked `@internal` — not part of the public API).
|
|
53
|
+
applyingAN = false;
|
|
34
54
|
checksumDirty = true;
|
|
35
55
|
cachedMetaChecksum;
|
|
36
56
|
cachedDescendantChecksum;
|
|
@@ -53,7 +73,7 @@ export class ArgumentEngine {
|
|
|
53
73
|
this.premises = new Map();
|
|
54
74
|
this.checksumConfig = options?.checksumConfig;
|
|
55
75
|
this.positionConfig = options?.positionConfig;
|
|
56
|
-
this.
|
|
76
|
+
this.engineBehavior = options?.behavior ?? "assistive";
|
|
57
77
|
this.generateId = options?.generateId ?? defaultGenerateId;
|
|
58
78
|
this.variables = new VariableManager({
|
|
59
79
|
checksumConfig: this.checksumConfig,
|
|
@@ -159,7 +179,7 @@ export class ArgumentEngine {
|
|
|
159
179
|
this.suppressPremiseValidation();
|
|
160
180
|
try {
|
|
161
181
|
const result = fn();
|
|
162
|
-
const validation = this.
|
|
182
|
+
const validation = this.validateInvariants();
|
|
163
183
|
if (!validation.ok) {
|
|
164
184
|
this.rollbackInternal(snap);
|
|
165
185
|
throw new InvariantViolationError(validation.violations);
|
|
@@ -295,6 +315,92 @@ export class ArgumentEngine {
|
|
|
295
315
|
}
|
|
296
316
|
}
|
|
297
317
|
}
|
|
318
|
+
/**
|
|
319
|
+
* Current engine behavior setting. Controls whether the
|
|
320
|
+
* auto-normalization (AN) rule set runs as a post-hook after every
|
|
321
|
+
* successful Structural mutation. See the JSDoc on
|
|
322
|
+
* `TLogicEngineOptions.behavior` for the full contract.
|
|
323
|
+
*
|
|
324
|
+
* @since 1.0.0
|
|
325
|
+
*/
|
|
326
|
+
get behavior() {
|
|
327
|
+
return this.engineBehavior;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Access to the engine's ID generator function. Used by in-package
|
|
331
|
+
* helpers that build new entity trees and need fresh IDs (e.g. the
|
|
332
|
+
* `populateFromGrounding` factory in
|
|
333
|
+
* `src/lib/grammar/populate-from.ts`). The generator is captured
|
|
334
|
+
* once at construction (default `crypto.randomUUID`) and stays
|
|
335
|
+
* immutable for the engine's lifetime; this accessor returns the
|
|
336
|
+
* same function reference on every call.
|
|
337
|
+
*
|
|
338
|
+
* Replaces the prior `(engine as unknown as { generateId: () =>
|
|
339
|
+
* string }).generateId` cast in `populate-from.ts`. The accessor is
|
|
340
|
+
* marked `@internal` so it is not surfaced in generated API docs /
|
|
341
|
+
* type bundles — the in-package factory callers are its intended
|
|
342
|
+
* consumers; external programmatic-construction use cases should
|
|
343
|
+
* supply their own generator rather than borrowing the engine's.
|
|
344
|
+
*
|
|
345
|
+
* @internal
|
|
346
|
+
* @since 1.0.0
|
|
347
|
+
*/
|
|
348
|
+
get idGenerator() {
|
|
349
|
+
return this.generateId;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Switches the engine's behavior at runtime. Going `permissive →
|
|
353
|
+
* assistive` does **not** auto-run a global `normalize()` pass; the
|
|
354
|
+
* UI is expected to prompt the user before invoking `normalize()`
|
|
355
|
+
* explicitly.
|
|
356
|
+
*
|
|
357
|
+
* As of v1.0 (Phase D2) behavior is enforced entirely via the AN
|
|
358
|
+
* post-mutation hook in `runAssistiveNormalization` — the legacy
|
|
359
|
+
* per-flag `grammarConfig` plumbing that bridged behavior to
|
|
360
|
+
* premise-level enforcement is gone. Switching `permissive →
|
|
361
|
+
* assistive` makes the next successful Structural mutation trigger
|
|
362
|
+
* the AN pass; switching the other direction stops the AN pass
|
|
363
|
+
* from running until the user opts back in.
|
|
364
|
+
*
|
|
365
|
+
* @since 1.0.0
|
|
366
|
+
*/
|
|
367
|
+
setBehavior(b) {
|
|
368
|
+
this.engineBehavior = b;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Acquire the AN re-entrance guard. Returns `true` iff the guard
|
|
372
|
+
* was acquired (i.e. AN is not already running for this engine);
|
|
373
|
+
* the caller is then obligated to call `endApplyAN()` after the
|
|
374
|
+
* AN sweep. Returns `false` if AN is already in progress, in
|
|
375
|
+
* which case the caller short-circuits to avoid nested AN
|
|
376
|
+
* sweeps.
|
|
377
|
+
*
|
|
378
|
+
* Used by `applyANToFixedPoint` in `src/lib/grammar/an-rules.ts`
|
|
379
|
+
* (the single chokepoint for both `runAssistiveNormalization`
|
|
380
|
+
* and `normalizeArgument`). The post-mutation hook in
|
|
381
|
+
* `setOnMutate` calls `runAssistiveNormalization(this)` which
|
|
382
|
+
* delegates to `applyANToFixedPoint`; AN's own mutations re-fire
|
|
383
|
+
* `setOnMutate`, which would otherwise recurse. This guard
|
|
384
|
+
* breaks the recursion.
|
|
385
|
+
*
|
|
386
|
+
* @internal
|
|
387
|
+
* @since 1.0.0
|
|
388
|
+
*/
|
|
389
|
+
beginApplyAN() {
|
|
390
|
+
if (this.applyingAN)
|
|
391
|
+
return false;
|
|
392
|
+
this.applyingAN = true;
|
|
393
|
+
return true;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Release the AN re-entrance guard. Pairs with `beginApplyAN()`.
|
|
397
|
+
*
|
|
398
|
+
* @internal
|
|
399
|
+
* @since 1.0.0
|
|
400
|
+
*/
|
|
401
|
+
endApplyAN() {
|
|
402
|
+
this.applyingAN = false;
|
|
403
|
+
}
|
|
298
404
|
getArgument() {
|
|
299
405
|
this.flushChecksums();
|
|
300
406
|
return {
|
|
@@ -429,7 +535,6 @@ export class ArgumentEngine {
|
|
|
429
535
|
}, {
|
|
430
536
|
checksumConfig: this.checksumConfig,
|
|
431
537
|
positionConfig: this.positionConfig,
|
|
432
|
-
grammarConfig: this.grammarConfig,
|
|
433
538
|
generateId: this.generateId,
|
|
434
539
|
});
|
|
435
540
|
this.premises.set(id, pm);
|
|
@@ -441,6 +546,16 @@ export class ArgumentEngine {
|
|
|
441
546
|
this.markDirty();
|
|
442
547
|
this.reactiveDirty.premiseIds.add(id);
|
|
443
548
|
this.notifySubscribers();
|
|
549
|
+
// D2b — AN post-mutation hook per spec §5. Skipped
|
|
550
|
+
// during snapshot restoration (PE.fromSnapshot bypasses
|
|
551
|
+
// mutations anyway, but the guard is defensive).
|
|
552
|
+
// `runAssistiveNormalization` is a no-op in permissive
|
|
553
|
+
// mode; re-entrance from AN's own mutations is guarded
|
|
554
|
+
// inside `applyANToFixedPoint` via the engine's
|
|
555
|
+
// `_beginApplyAN()` flag.
|
|
556
|
+
if (!this.restoringFromSnapshot) {
|
|
557
|
+
runAssistiveNormalization(this);
|
|
558
|
+
}
|
|
444
559
|
});
|
|
445
560
|
const collector = new ChangeCollector();
|
|
446
561
|
collector.addedPremise(pm.toPremiseData());
|
|
@@ -813,6 +928,18 @@ export class ArgumentEngine {
|
|
|
813
928
|
getVariable(variableId) {
|
|
814
929
|
return this.variables.getVariable(variableId);
|
|
815
930
|
}
|
|
931
|
+
/**
|
|
932
|
+
* Look up a claim by `(id, version)` in the engine's claim library.
|
|
933
|
+
* Returns `undefined` if the claim is not present. Exposed for
|
|
934
|
+
* repair primitives and other tooling that needs to inspect a
|
|
935
|
+
* claim's `type` discriminator at a particular version pinned by
|
|
936
|
+
* a claim-bound variable.
|
|
937
|
+
*
|
|
938
|
+
* @since 1.0.0
|
|
939
|
+
*/
|
|
940
|
+
getClaim(claimId, claimVersion) {
|
|
941
|
+
return this.claimLibrary.get(claimId, claimVersion);
|
|
942
|
+
}
|
|
816
943
|
hasVariable(variableId) {
|
|
817
944
|
return this.variables.hasVariable(variableId);
|
|
818
945
|
}
|
|
@@ -882,27 +1009,144 @@ export class ArgumentEngine {
|
|
|
882
1009
|
return roots;
|
|
883
1010
|
}
|
|
884
1011
|
/**
|
|
885
|
-
*
|
|
886
|
-
*
|
|
887
|
-
*
|
|
1012
|
+
* Construct (or no-op on) the per-claim derivation premise's
|
|
1013
|
+
* antecedent from a citation lookup. Factory + naked-Q-only:
|
|
1014
|
+
*
|
|
1015
|
+
* - 0 connections → no-op (naked-Q stays).
|
|
1016
|
+
* - 1 connection → `IMPLIES(citation-var, Q)`.
|
|
1017
|
+
* - ≥ 2 connections → `IMPLIES(OR(c1, …, cn), Q)`. In
|
|
1018
|
+
* `'assistive'` mode the per-mutation AN-1 post-hook inserts a
|
|
1019
|
+
* formula buffer between IMPLIES and OR; in `'permissive'` the
|
|
1020
|
+
* OR sits directly under IMPLIES (a P-1 violation surfaces via
|
|
1021
|
+
* `validate('presentable')`).
|
|
1022
|
+
*
|
|
1023
|
+
* **No throw on already-populated.** Per the Structural-only
|
|
1024
|
+
* mutation throw rule, if the target derivation premise is not in
|
|
1025
|
+
* the naked-Q form the factory returns `{ kind: 'no-op', state:
|
|
1026
|
+
* <existing> }` without mutating. UI/caller is responsible for
|
|
1027
|
+
* explicit user consent + clearing the antecedent via a repair
|
|
1028
|
+
* primitive before re-calling. Preserves the no-changes-without-
|
|
1029
|
+
* consent principle.
|
|
1030
|
+
*
|
|
1031
|
+
* Throws only when no derivation premise exists for the given
|
|
1032
|
+
* `derivedClaimId` (legitimate entity-not-found Structural check).
|
|
1033
|
+
*
|
|
1034
|
+
* @since 1.0.0
|
|
888
1035
|
*/
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
1036
|
+
populateFromCitations(derivedClaimId, citationLookup) {
|
|
1037
|
+
return populateFromGroundingImpl(this, derivedClaimId, citationLookup);
|
|
1038
|
+
}
|
|
1039
|
+
/**
|
|
1040
|
+
* Mirror of `populateFromCitations` for axiom connections. Same
|
|
1041
|
+
* factory contract: naked-Q-only, no throw on already-populated.
|
|
1042
|
+
*
|
|
1043
|
+
* @since 1.0.0
|
|
1044
|
+
*/
|
|
1045
|
+
populateFromAxioms(derivedClaimId, axiomLookup) {
|
|
1046
|
+
return populateFromGroundingImpl(this, derivedClaimId, axiomLookup);
|
|
1047
|
+
}
|
|
1048
|
+
/**
|
|
1049
|
+
* Repair primitive: resolve E-3 violations by deleting each
|
|
1050
|
+
* unresolvable claim- or premise-bound variable, cascading the
|
|
1051
|
+
* removal across all premises. Returns the violations resolved
|
|
1052
|
+
* (for UX confirmation / undo / "we made N changes" feedback).
|
|
1053
|
+
*
|
|
1054
|
+
* **User-initiated; never auto-runs.** Respects `behavior`: in
|
|
1055
|
+
* `'assistive'` mode, the AN post-hook fires after each cascade
|
|
1056
|
+
* mutation; in `'permissive'` no AN runs.
|
|
1057
|
+
*
|
|
1058
|
+
* @since 1.0.0
|
|
1059
|
+
*/
|
|
1060
|
+
removeUnresolvableVariables() {
|
|
1061
|
+
return removeUnresolvableVariablesImpl(this);
|
|
1062
|
+
}
|
|
1063
|
+
/**
|
|
1064
|
+
* Repair primitive: resolve E-1 violations (operators with < 2
|
|
1065
|
+
* children) by running the AN-3 cleanup pass globally. Returns the
|
|
1066
|
+
* violations resolved. The repair is non-meaning-changing — it
|
|
1067
|
+
* only removes empty operators and promotes single-child operators
|
|
1068
|
+
* — but lives alongside `normalize()` so the UI can present a
|
|
1069
|
+
* focused "Remove N orphan operators" action with a precise return
|
|
1070
|
+
* value.
|
|
1071
|
+
*
|
|
1072
|
+
* **User-initiated; never auto-runs.** Bypasses `behavior` —
|
|
1073
|
+
* cleanup runs even in permissive mode (the user has already
|
|
1074
|
+
* accepted the action by clicking the repair button).
|
|
1075
|
+
*
|
|
1076
|
+
* @since 1.0.0
|
|
1077
|
+
*/
|
|
1078
|
+
removeOrphanOperators() {
|
|
1079
|
+
return removeOrphanOperatorsImpl(this);
|
|
1080
|
+
}
|
|
1081
|
+
/**
|
|
1082
|
+
* Repair primitive: resolve E-6 violations (claim has > 1
|
|
1083
|
+
* derivation premise) by keeping one premise per `derivedClaimId`
|
|
1084
|
+
* and deleting the rest. Strategy controls which premise is kept:
|
|
1085
|
+
*
|
|
1086
|
+
* - `'keep-first'` (default): keep the premise with the
|
|
1087
|
+
* lexicographically smallest id; delete the rest. Deterministic
|
|
1088
|
+
* and snapshot-stable.
|
|
1089
|
+
* - `'keep-largest-antecedent'`: keep the premise whose antecedent
|
|
1090
|
+
* subtree has the most claim-bound variable expressions; tie-break
|
|
1091
|
+
* by id.
|
|
1092
|
+
*
|
|
1093
|
+
* **User-initiated; never auto-runs.** Respects `behavior`.
|
|
1094
|
+
*
|
|
1095
|
+
* @since 1.0.0
|
|
1096
|
+
*/
|
|
1097
|
+
removeDuplicateDerivationPremises(strategy = "keep-first") {
|
|
1098
|
+
return removeDuplicateDerivationPremisesImpl(this, strategy);
|
|
1099
|
+
}
|
|
1100
|
+
/**
|
|
1101
|
+
* Repair primitive: resolve D-3 violations (mixed-grounding
|
|
1102
|
+
* antecedent — axioms + citations in one derivation) by deleting
|
|
1103
|
+
* every axiom-bound variable expression from the offending
|
|
1104
|
+
* antecedent subtree. The remaining citation-bound variables stay,
|
|
1105
|
+
* giving the derivation a homogeneous citation-grounded antecedent.
|
|
1106
|
+
*
|
|
1107
|
+
* **User-initiated; never auto-runs.** Respects `behavior`. In
|
|
1108
|
+
* `'assistive'` mode, AN may collapse a resulting single-child OR
|
|
1109
|
+
* via AN-3; in `'permissive'` the OR may persist with one child
|
|
1110
|
+
* (a downstream D-2 violation — follow up with
|
|
1111
|
+
* `removeOrphanOperators()` if desired).
|
|
1112
|
+
*
|
|
1113
|
+
* @since 1.0.0
|
|
1114
|
+
*/
|
|
1115
|
+
dropAxiomsFromMixedAntecedent() {
|
|
1116
|
+
return dropAxiomsFromMixedAntecedentImpl(this);
|
|
905
1117
|
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Global normalize pass per spec §6. Runs the AN rule set
|
|
1120
|
+
* (AN-1..AN-4) everywhere it can fire, converging the argument
|
|
1121
|
+
* toward `tier` (defaults to `'presentable'`).
|
|
1122
|
+
*
|
|
1123
|
+
* `normalize` is non-destructive in the logical-meaning sense — it
|
|
1124
|
+
* does not delete variables, change claim references, or modify
|
|
1125
|
+
* operator semantics. Recovery from Evaluable or Derivable violations
|
|
1126
|
+
* requires user intent and is exposed via the repair primitives
|
|
1127
|
+
* (Phase C4).
|
|
1128
|
+
*
|
|
1129
|
+
* In v1.0 every AN rule targets a Presentable invariant, so calls
|
|
1130
|
+
* with `tier` ∈ {'structural', 'evaluable', 'derivable'} are
|
|
1131
|
+
* effectively no-ops. The parameter exists as forward-compatible
|
|
1132
|
+
* API surface for a future submit/finalize gate.
|
|
1133
|
+
*
|
|
1134
|
+
* **Bypasses `behavior`.** `normalize()` is user-initiated (the UI
|
|
1135
|
+
* invokes it after the user confirms a Tidy / Normalize action), so
|
|
1136
|
+
* cleanup runs regardless of whether the engine is in `'assistive'`
|
|
1137
|
+
* or `'permissive'` mode. The engine's `behavior` setting is not
|
|
1138
|
+
* mutated by this call.
|
|
1139
|
+
*
|
|
1140
|
+
* @since 1.0.0
|
|
1141
|
+
*/
|
|
1142
|
+
normalize(tier = "presentable") {
|
|
1143
|
+
normalizeArgument(this, tier);
|
|
1144
|
+
}
|
|
1145
|
+
// D2 — `normalizeAllExpressions` was the per-engine wrapper that
|
|
1146
|
+
// delegated to `pe.normalizeExpressions()` on every premise.
|
|
1147
|
+
// Both methods are deleted in D2. Callers migrate to
|
|
1148
|
+
// `engine.normalize(tier?)` (Phase C3), which routes through the
|
|
1149
|
+
// four native AN passes in `src/lib/grammar/an-rules.ts`.
|
|
906
1150
|
getRoleState() {
|
|
907
1151
|
return {
|
|
908
1152
|
...(this.conclusionPremiseId !== undefined
|
|
@@ -966,12 +1210,23 @@ export class ArgumentEngine {
|
|
|
966
1210
|
config: {
|
|
967
1211
|
checksumConfig: serializeChecksumConfig(this.checksumConfig),
|
|
968
1212
|
positionConfig: this.positionConfig,
|
|
969
|
-
|
|
1213
|
+
// `behavior` is intentionally omitted from the snapshot.
|
|
1214
|
+
// Consumers re-supply it at restore time via
|
|
1215
|
+
// `new ArgumentEngine(...)` options or `setBehavior()`;
|
|
1216
|
+
// a restored engine defaults to `'assistive'`. The fork
|
|
1217
|
+
// path (`forkArgumentEngine` / `PropositCore.forkArgument`)
|
|
1218
|
+
// explicitly threads the source engine's `behavior` into
|
|
1219
|
+
// the forked engine's config (see D5 — `fork.ts`), so
|
|
1220
|
+
// fork callers don't lose the setting.
|
|
1221
|
+
//
|
|
1222
|
+
// D2: the legacy `grammarConfig` field is gone — all
|
|
1223
|
+
// P-1 / AN behavior is driven by `engine.behavior` +
|
|
1224
|
+
// the AN post-mutation hook.
|
|
970
1225
|
},
|
|
971
1226
|
};
|
|
972
1227
|
}
|
|
973
1228
|
/** Creates a new ArgumentEngine from a previously captured snapshot. */
|
|
974
|
-
static fromSnapshot(snapshot, claimLibrary,
|
|
1229
|
+
static fromSnapshot(snapshot, claimLibrary, checksumVerification, generateId) {
|
|
975
1230
|
const engine = new ArgumentEngine(snapshot.argument, claimLibrary, snapshot.config
|
|
976
1231
|
? {
|
|
977
1232
|
...snapshot.config,
|
|
@@ -984,7 +1239,7 @@ export class ArgumentEngine {
|
|
|
984
1239
|
engine.restoringFromSnapshot = true;
|
|
985
1240
|
// Restore premises first (premise-bound variables reference them)
|
|
986
1241
|
for (const premiseSnap of snapshot.premises) {
|
|
987
|
-
const pe = PremiseEngine.fromSnapshot(premiseSnap, snapshot.argument, engine.variables, engine.expressionIndex,
|
|
1242
|
+
const pe = PremiseEngine.fromSnapshot(premiseSnap, snapshot.argument, engine.variables, engine.expressionIndex, generateId);
|
|
988
1243
|
engine.premises.set(pe.getId(), pe);
|
|
989
1244
|
engine.wireCircularityCheck(pe);
|
|
990
1245
|
engine.wireEmptyBoundPremiseCheck(pe);
|
|
@@ -995,6 +1250,13 @@ export class ArgumentEngine {
|
|
|
995
1250
|
engine.markDirty();
|
|
996
1251
|
engine.reactiveDirty.premiseIds.add(premiseId);
|
|
997
1252
|
engine.notifySubscribers();
|
|
1253
|
+
// D2b — AN post-mutation hook per spec §5. See the
|
|
1254
|
+
// matching comment in `createPremise`'s setOnMutate
|
|
1255
|
+
// callback for the re-entrance / snapshot-restore
|
|
1256
|
+
// rationale.
|
|
1257
|
+
if (!engine.restoringFromSnapshot) {
|
|
1258
|
+
runAssistiveNormalization(engine);
|
|
1259
|
+
}
|
|
998
1260
|
});
|
|
999
1261
|
}
|
|
1000
1262
|
// Restore claim-bound variables first, then premise-bound variables
|
|
@@ -1017,31 +1279,25 @@ export class ArgumentEngine {
|
|
|
1017
1279
|
// Restore conclusion role (don't use setConclusionPremise to avoid auto-assign logic)
|
|
1018
1280
|
engine.conclusionPremiseId = snapshot.conclusionPremiseId;
|
|
1019
1281
|
engine.restoringFromSnapshot = false;
|
|
1020
|
-
//
|
|
1021
|
-
//
|
|
1022
|
-
//
|
|
1023
|
-
if (grammarConfig) {
|
|
1024
|
-
engine.grammarConfig = grammarConfig;
|
|
1025
|
-
for (const pe of engine.premises.values()) {
|
|
1026
|
-
pe.setGrammarConfig(grammarConfig);
|
|
1027
|
-
}
|
|
1028
|
-
}
|
|
1029
|
-
// Post-load normalization: only run full normalize when autoNormalize
|
|
1030
|
-
// is `true` (boolean). When it is a granular config object, individual
|
|
1031
|
-
// flags control in-operation behavior — loading should not mutate data.
|
|
1032
|
-
const restoredGrammarConfig = grammarConfig ?? DEFAULT_GRAMMAR_CONFIG;
|
|
1033
|
-
if (restoredGrammarConfig.autoNormalize === true) {
|
|
1034
|
-
for (const pe of engine.premises.values()) {
|
|
1035
|
-
pe.normalizeExpressions();
|
|
1036
|
-
}
|
|
1037
|
-
}
|
|
1282
|
+
// C7: No post-load normalization. The snapshot loads as-is; any
|
|
1283
|
+
// lower-tier (Evaluable / Derivable / Presentable) violations
|
|
1284
|
+
// are queryable post-load via `engine.validate(tier)`.
|
|
1038
1285
|
if (checksumVerification === "strict") {
|
|
1039
1286
|
engine.flushChecksums();
|
|
1040
1287
|
ArgumentEngine.verifySnapshotChecksums(engine, snapshot);
|
|
1041
1288
|
}
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1289
|
+
// D2: load-time invariant validation no longer needs the
|
|
1290
|
+
// PERMISSIVE swap — the legacy `EXPR_FORMULA_BETWEEN_OPERATORS_VIOLATED`
|
|
1291
|
+
// check was deleted alongside the rest of `grammarConfig`. P-1
|
|
1292
|
+
// is now surfaced via `engine.validate('presentable')`
|
|
1293
|
+
// post-load. Non-grammar invariants (schema conformance,
|
|
1294
|
+
// reference integrity, conclusion ref, circularity, etc.)
|
|
1295
|
+
// still throw at load time. D4 inlined the
|
|
1296
|
+
// `runLoadTimeValidationCore` wrapper and routes through the
|
|
1297
|
+
// public `validateInvariants()` method.
|
|
1298
|
+
const loadValidation = engine.validateInvariants();
|
|
1299
|
+
if (!loadValidation.ok) {
|
|
1300
|
+
throw new InvariantViolationError(loadValidation.violations);
|
|
1045
1301
|
}
|
|
1046
1302
|
return engine;
|
|
1047
1303
|
}
|
|
@@ -1051,19 +1307,14 @@ export class ArgumentEngine {
|
|
|
1051
1307
|
* `premiseId` field and loaded in BFS order (roots first, then children
|
|
1052
1308
|
* of already-added nodes) to satisfy parent-existence requirements.
|
|
1053
1309
|
*/
|
|
1054
|
-
static fromData(argument, claimLibrary, variables, premises, expressions, roles, config,
|
|
1055
|
-
const loadingGrammarConfig = grammarConfig ?? config?.grammarConfig ?? DEFAULT_GRAMMAR_CONFIG;
|
|
1310
|
+
static fromData(argument, claimLibrary, variables, premises, expressions, roles, config, checksumVerification) {
|
|
1056
1311
|
const normalizedConfig = config
|
|
1057
1312
|
? {
|
|
1058
1313
|
...config,
|
|
1059
1314
|
checksumConfig: normalizeChecksumConfig(config.checksumConfig),
|
|
1060
1315
|
}
|
|
1061
1316
|
: undefined;
|
|
1062
|
-
const
|
|
1063
|
-
...normalizedConfig,
|
|
1064
|
-
grammarConfig: loadingGrammarConfig,
|
|
1065
|
-
};
|
|
1066
|
-
const engine = new ArgumentEngine(argument, claimLibrary, loadingConfig);
|
|
1317
|
+
const engine = new ArgumentEngine(argument, claimLibrary, normalizedConfig);
|
|
1067
1318
|
engine.restoringFromSnapshot = true;
|
|
1068
1319
|
// Register claim-bound variables first (no dependencies)
|
|
1069
1320
|
for (const v of variables) {
|
|
@@ -1121,24 +1372,24 @@ export class ArgumentEngine {
|
|
|
1121
1372
|
if (roles.conclusionPremiseId !== undefined) {
|
|
1122
1373
|
engine.setConclusionPremise(roles.conclusionPremiseId);
|
|
1123
1374
|
}
|
|
1124
|
-
// After loading: restore the caller's intended grammar config
|
|
1125
|
-
engine.grammarConfig = config?.grammarConfig;
|
|
1126
1375
|
engine.restoringFromSnapshot = false;
|
|
1127
|
-
//
|
|
1128
|
-
//
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
for (const pe of engine.premises.values()) {
|
|
1132
|
-
pe.normalizeExpressions();
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1376
|
+
// C7: No post-load normalization. See the matched note in
|
|
1377
|
+
// `fromSnapshot` above. Load is non-mutating; lower-tier
|
|
1378
|
+
// violations surface via `engine.validate(tier)`. Phase D
|
|
1379
|
+
// removes the legacy grammarConfig parameter entirely.
|
|
1135
1380
|
if (checksumVerification === "strict") {
|
|
1136
1381
|
engine.flushChecksums();
|
|
1137
1382
|
ArgumentEngine.verifyDataChecksums(engine, argument, variables, premises);
|
|
1138
1383
|
}
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1384
|
+
// C7: PERMISSIVE-gated load-time validation (see matched comment
|
|
1385
|
+
// in `fromSnapshot` above). Non-grammar invariants still throw at
|
|
1386
|
+
// load; lower-tier grammar violations surface post-load via
|
|
1387
|
+
// `engine.validate(tier)`. D4 inlined the
|
|
1388
|
+
// `runLoadTimeValidationCore` wrapper and routes through the
|
|
1389
|
+
// public `validateInvariants()` method.
|
|
1390
|
+
const loadValidation = engine.validateInvariants();
|
|
1391
|
+
if (!loadValidation.ok) {
|
|
1392
|
+
throw new InvariantViolationError(loadValidation.violations);
|
|
1142
1393
|
}
|
|
1143
1394
|
return engine;
|
|
1144
1395
|
}
|
|
@@ -1253,7 +1504,7 @@ export class ArgumentEngine {
|
|
|
1253
1504
|
rollback(snapshot) {
|
|
1254
1505
|
const preRollbackSnap = this.snapshot();
|
|
1255
1506
|
this.rollbackInternal(snapshot);
|
|
1256
|
-
const validation = this.
|
|
1507
|
+
const validation = this.validateInvariants();
|
|
1257
1508
|
if (!validation.ok) {
|
|
1258
1509
|
this.rollbackInternal(preRollbackSnap);
|
|
1259
1510
|
throw new InvariantViolationError(validation.violations);
|
|
@@ -1263,12 +1514,11 @@ export class ArgumentEngine {
|
|
|
1263
1514
|
this.argument = { ...snapshot.argument };
|
|
1264
1515
|
this.checksumConfig = normalizeChecksumConfig(snapshot.config?.checksumConfig);
|
|
1265
1516
|
this.positionConfig = snapshot.config?.positionConfig;
|
|
1266
|
-
this.grammarConfig = snapshot.config?.grammarConfig;
|
|
1267
1517
|
this.variables = VariableManager.fromSnapshot(snapshot.variables);
|
|
1268
1518
|
this.premises = new Map();
|
|
1269
1519
|
this.expressionIndex = new Map();
|
|
1270
1520
|
for (const premiseSnap of snapshot.premises) {
|
|
1271
|
-
const pe = PremiseEngine.fromSnapshot(premiseSnap, this.argument, this.variables, this.expressionIndex
|
|
1521
|
+
const pe = PremiseEngine.fromSnapshot(premiseSnap, this.argument, this.variables, this.expressionIndex);
|
|
1272
1522
|
this.premises.set(pe.getId(), pe);
|
|
1273
1523
|
}
|
|
1274
1524
|
this.conclusionPremiseId = snapshot.conclusionPremiseId;
|
|
@@ -1282,6 +1532,13 @@ export class ArgumentEngine {
|
|
|
1282
1532
|
this.markDirty();
|
|
1283
1533
|
this.reactiveDirty.premiseIds.add(premiseId);
|
|
1284
1534
|
this.notifySubscribers();
|
|
1535
|
+
// D2b — AN post-mutation hook per spec §5. See the
|
|
1536
|
+
// matching comment in `createPremise`'s setOnMutate
|
|
1537
|
+
// callback for the re-entrance / snapshot-restore
|
|
1538
|
+
// rationale.
|
|
1539
|
+
if (!this.restoringFromSnapshot) {
|
|
1540
|
+
runAssistiveNormalization(this);
|
|
1541
|
+
}
|
|
1285
1542
|
});
|
|
1286
1543
|
}
|
|
1287
1544
|
this.markDirty();
|
|
@@ -1405,9 +1662,85 @@ export class ArgumentEngine {
|
|
|
1405
1662
|
validateAfterPremiseMutation() {
|
|
1406
1663
|
return validateAfterPremiseMutationStandalone(this.asValidationContext());
|
|
1407
1664
|
}
|
|
1408
|
-
|
|
1665
|
+
/**
|
|
1666
|
+
* Four-tier grammar validation per spec §4. Returns the union of
|
|
1667
|
+
* violations from Structural up through `tier` — `'structural'`
|
|
1668
|
+
* returns S-rule violations only, `'evaluable'` returns S + E,
|
|
1669
|
+
* `'derivable'` returns S + E + D, `'presentable'` returns the full
|
|
1670
|
+
* union. Empty array means the argument is at the requested tier
|
|
1671
|
+
* or stricter. Never throws on grammar issues.
|
|
1672
|
+
*
|
|
1673
|
+
* For the legacy pre-1.0 invariant sweep (schema conformance,
|
|
1674
|
+
* reference integrity, ownership, conclusion ref, circularity,
|
|
1675
|
+
* checksums) use {@link validateInvariants} instead. The pre-1.0
|
|
1676
|
+
* no-arg overload of `validate()` was removed in Phase D4.
|
|
1677
|
+
*/
|
|
1678
|
+
validate(tier) {
|
|
1679
|
+
return validateGrammar(tier, this.asGrammarValidatorContext());
|
|
1680
|
+
}
|
|
1681
|
+
/**
|
|
1682
|
+
* Legacy invariant sweep — schema conformance, reference integrity,
|
|
1683
|
+
* ownership, conclusion-ref + circularity, checksum stability, and
|
|
1684
|
+
* per-premise validation. Returns a `TInvariantValidationResult`.
|
|
1685
|
+
* Used internally by mutation-rollback and snapshot-load paths and
|
|
1686
|
+
* exposed publicly for library-wide invariant checks (see
|
|
1687
|
+
* `ArgumentLibrary.validate` and `PropositCore.validate`).
|
|
1688
|
+
*
|
|
1689
|
+
* Distinct from {@link validate}, which runs the four-tier grammar
|
|
1690
|
+
* validator (`Structural ⊇ Evaluable ⊇ Derivable ⊇ Presentable`)
|
|
1691
|
+
* and returns a `readonly TViolation[]`. The two are
|
|
1692
|
+
* complementary — grammar tiers cover AST-shape rules; this method
|
|
1693
|
+
* covers schema/reference/structural-bookkeeping invariants that
|
|
1694
|
+
* sit outside the tier hierarchy.
|
|
1695
|
+
*
|
|
1696
|
+
* @since 1.0.0 — replaces the legacy `validate()` no-arg overload
|
|
1697
|
+
* removed in Phase D4 of the `grammar-tiers/core` branch.
|
|
1698
|
+
*/
|
|
1699
|
+
validateInvariants() {
|
|
1409
1700
|
return validateArgumentStandalone(this.asValidationContext());
|
|
1410
1701
|
}
|
|
1702
|
+
/**
|
|
1703
|
+
* Construct the pure-data `TValidatorContext` consumed by the
|
|
1704
|
+
* grammar-tier validators. Claims are gathered by walking the
|
|
1705
|
+
* engine's claim-bound variables and looking each one up in the
|
|
1706
|
+
* claim library — the `TClaimLookup` contract doesn't expose
|
|
1707
|
+
* iteration, so we materialize the referenced subset only.
|
|
1708
|
+
*/
|
|
1709
|
+
asGrammarValidatorContext() {
|
|
1710
|
+
const argument = this.getArgument();
|
|
1711
|
+
const premises = [];
|
|
1712
|
+
const expressions = [];
|
|
1713
|
+
for (const pe of this.listPremises()) {
|
|
1714
|
+
premises.push(pe.toPremiseData());
|
|
1715
|
+
expressions.push(...pe.getExpressions());
|
|
1716
|
+
}
|
|
1717
|
+
const variables = this.variables.toArray();
|
|
1718
|
+
// Gather referenced claims via claim-bound variables. Duplicate
|
|
1719
|
+
// (id, version) pairs are deduped via a Set on the composite key.
|
|
1720
|
+
const seen = new Set();
|
|
1721
|
+
const claims = [];
|
|
1722
|
+
for (const v of variables) {
|
|
1723
|
+
if (!isClaimBound(v))
|
|
1724
|
+
continue;
|
|
1725
|
+
const cb = v;
|
|
1726
|
+
const key = `${cb.claimId}:${cb.claimVersion}`;
|
|
1727
|
+
if (seen.has(key))
|
|
1728
|
+
continue;
|
|
1729
|
+
seen.add(key);
|
|
1730
|
+
const claim = this.claimLibrary.get(cb.claimId, cb.claimVersion);
|
|
1731
|
+
if (claim !== undefined) {
|
|
1732
|
+
claims.push(claim);
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
return {
|
|
1736
|
+
argument,
|
|
1737
|
+
premises,
|
|
1738
|
+
expressions,
|
|
1739
|
+
variables,
|
|
1740
|
+
claims,
|
|
1741
|
+
roleState: this.getRoleState(),
|
|
1742
|
+
};
|
|
1743
|
+
}
|
|
1411
1744
|
validateEvaluability() {
|
|
1412
1745
|
const base = validateArgumentEvaluabilityStandalone(this.asValidationContext());
|
|
1413
1746
|
const derivationIssues = this.collectDerivationStructureIssues();
|
|
@@ -1420,15 +1753,19 @@ export class ArgumentEngine {
|
|
|
1420
1753
|
* Apps can pre-check derivation premise structures before invoking the full
|
|
1421
1754
|
* evaluation pipeline.
|
|
1422
1755
|
*
|
|
1756
|
+
* Violations carry the underlying `DERIVATION_STRUCTURE_INVALID` code
|
|
1757
|
+
* (per the derivation-validation utility). The pre-1.0
|
|
1758
|
+
* `DERIVATION_STRUCTURE_INVALID_AT_EVALUATION` override was removed in
|
|
1759
|
+
* Phase D4 alongside the legacy `validate()` no-arg overload — naked-Q
|
|
1760
|
+
* is a valid Derivable state (per spec §4.2) and is skipped by
|
|
1761
|
+
* evaluation rather than thrown.
|
|
1762
|
+
*
|
|
1423
1763
|
* @since 0.11.0
|
|
1424
1764
|
*/
|
|
1425
1765
|
validateDerivationStructures() {
|
|
1426
1766
|
const violations = [];
|
|
1427
1767
|
for (const { violation } of this.collectDerivationViolations()) {
|
|
1428
|
-
violations.push(
|
|
1429
|
-
...violation,
|
|
1430
|
-
code: DERIVATION_STRUCTURE_INVALID_AT_EVALUATION,
|
|
1431
|
-
});
|
|
1768
|
+
violations.push(violation);
|
|
1432
1769
|
}
|
|
1433
1770
|
return { ok: violations.length === 0, violations };
|
|
1434
1771
|
}
|
|
@@ -1436,7 +1773,7 @@ export class ArgumentEngine {
|
|
|
1436
1773
|
const issues = [];
|
|
1437
1774
|
for (const { violation } of this.collectDerivationViolations()) {
|
|
1438
1775
|
issues.push(makeErrorIssue({
|
|
1439
|
-
code:
|
|
1776
|
+
code: "DERIVATION_STRUCTURE_INVALID",
|
|
1440
1777
|
message: violation.message,
|
|
1441
1778
|
premiseId: violation.entityId,
|
|
1442
1779
|
}));
|
|
@@ -1486,14 +1823,37 @@ export class ArgumentEngine {
|
|
|
1486
1823
|
};
|
|
1487
1824
|
}
|
|
1488
1825
|
asEvaluationContext() {
|
|
1826
|
+
// C8: naked-Q derivation premises (single variable expression at
|
|
1827
|
+
// root, type='derivation') contribute nothing to evaluation. The
|
|
1828
|
+
// evaluator-context's premise listings filter them out so they
|
|
1829
|
+
// are entirely invisible to evaluate() and checkValidity(). This
|
|
1830
|
+
// replaces the pre-1.0 DERIVATION_STRUCTURE_INVALID_AT_EVALUATION
|
|
1831
|
+
// throw on naked-Q. Filter applies uniformly to conclusion,
|
|
1832
|
+
// supporting, and full premise listings. The predicate lives in
|
|
1833
|
+
// `src/lib/grammar/naked-q.ts` so the C6 factory and this filter
|
|
1834
|
+
// share one definition.
|
|
1489
1835
|
return {
|
|
1490
1836
|
argumentId: this.argument.id,
|
|
1491
1837
|
conclusionPremiseId: this.conclusionPremiseId,
|
|
1492
|
-
getConclusionPremise: () =>
|
|
1493
|
-
|
|
1494
|
-
|
|
1838
|
+
getConclusionPremise: () => {
|
|
1839
|
+
const c = this.getConclusionPremise();
|
|
1840
|
+
if (c === undefined)
|
|
1841
|
+
return undefined;
|
|
1842
|
+
if (isNakedQDerivationPremise(c))
|
|
1843
|
+
return undefined;
|
|
1844
|
+
return c;
|
|
1845
|
+
},
|
|
1846
|
+
listSupportingPremises: () => this.listSupportingPremises().filter((pm) => !isNakedQDerivationPremise(pm)),
|
|
1847
|
+
listPremises: () => this.listPremises().filter((pm) => !isNakedQDerivationPremise(pm)),
|
|
1495
1848
|
getVariable: (id) => this.variables.getVariable(id),
|
|
1496
|
-
getPremise: (id) =>
|
|
1849
|
+
getPremise: (id) => {
|
|
1850
|
+
const pe = this.premises.get(id);
|
|
1851
|
+
if (pe === undefined)
|
|
1852
|
+
return undefined;
|
|
1853
|
+
if (isNakedQDerivationPremise(pe))
|
|
1854
|
+
return undefined;
|
|
1855
|
+
return pe;
|
|
1856
|
+
},
|
|
1497
1857
|
validateEvaluability: () => this.validateEvaluability(),
|
|
1498
1858
|
};
|
|
1499
1859
|
}
|