Optionaloptions: TLogicEngineOptionsProtectedcachedProtectedcachedProtectedcachedProtectedchecksumRegisters a propositional variable for use across all premises.
The variable entity to register.
The registered variable (with checksum) and changeset.
Adds a premise-bound variable that references another argument's conclusion premise.
Adds a premise-bound variable that references a premise in a different argument.
Registers a premise-bound propositional variable whose truth value is derived from another premise's evaluation.
The premise-bound variable entity to register.
The registered variable (with checksum) and changeset.
ProtectedbuildProtectedcanOverride point for subclasses to restrict cross-argument bindings.
When this returns false, bindVariableToExternalPremise will throw.
Override point for subclasses to prevent forking. When this returns
false, forkArgument will throw.
Returns the meta checksum — derived from entity data only.
Enumerates all 2^n variable assignments and checks for counterexamples.
A counterexample is an admissible assignment where all supporting
premises are true but the conclusion is false. The argument is valid
if no counterexamples exist. This is the exhaustive entailment check;
the single-assignment premisesHoldConclusionFalse fact is a weaker,
reader-relative statement and not a countermodel.
Premise-set satisfiability is computed once before the row loop and threaded into each row, since the generated assignments carry no operator decisions and the premise set never varies.
Grounded claim-bound variables — axiomatic and citation — are
excluded from the enumeration and pinned true on every row, so an
argument with g of them enumerates 2^(k - g) assignments and no
counterexample can rest on a cited claim reading false. Evaluation is
deliberately different: it answers the reader's question, where a
citation is only seeded true and remains assignable.
Calls validateEvaluability() (including derivation pre-flight)
before enumeration. If the argument is not evaluable, returns early
with an appropriate result rather than throwing.
Optionaloptions: TCoreValidityCheckOptionsOptional limits on variables/assignments checked and early termination mode.
The validity check result including any counterexamples.
Clears the conclusion designation.
Invariant guard (1.0.2): A non-empty argument always has a conclusion designated (E-7). On an argument with one or more premises this method is a no-op — it returns the current (unchanged) role state with an empty changeset rather than leaving the engine in an E-7-violating state. The only path to legitimately end up with no conclusion designated is to remove every premise first. On a zero-premise argument the call still clears (vacuously satisfies the invariant).
The current role state and changeset. If premises exist, the changeset is empty (no-op); if zero premises, the role state is cleared and the changeset reflects the role change.
Collects all variables referenced by expressions across all premises, indexed both by variable ID and by symbol.
An object with variableIds, byId, and bySymbol indexes.
Returns the combined checksum — hash(checksum + descendantChecksum), or equals checksum if no descendants.
Creates a new premise with an auto-generated UUID and registers it with this engine.
Two call styles are supported:
Typed-bag (preferred, since 0.11.0):
engine.createPremise({
type: "freeform", // or "derivation"
derivedClaimId: claimId, // required when type === "derivation"
extras: { label: "P1" },
symbol: "P1",
})
Legacy positional (kept for compatibility):
engine.createPremise(extras, symbol) // creates a freeform premise
When type === "derivation", the engine looks up derivedClaimId in
the claim library, materializes a claim-bound variable for it (via
ensureClaimBoundVariable) if one does not already exist, and
initializes the premise's expression tree to the naked-Q form — a
single variable expression at the root referencing the consequent.
The newly created PremiseEngine instance and changeset.
Optionalsymbol: stringCreates a premise with a caller-supplied ID and registers it with
this engine. Mirrors createPremise exactly, but accepts an explicit
id as the first argument instead of generating one.
Two call styles are supported:
Typed-bag (preferred, since 0.11.0):
engine.createPremiseWithId(id, {
type: "freeform", // or "derivation"
derivedClaimId: claimId, // required when type === "derivation"
extras: { label: "P1" },
symbol: "P1",
})
Legacy positional (kept for compatibility):
engine.createPremiseWithId(id, extras, symbol) // creates a freeform premise
When type === "derivation", the same derivation initialization as
createPremise runs: variable materialization and naked-Q tree setup.
The ID to assign to the new premise.
Optionalextras: Record<string, unknown>Optionalsymbol: stringDerives a default truth-value assignment for every variable in the
argument, from claim type and immediate support structure alone. Values
are true or null (unknown) — never false.
D(claim) for the variable backing claim c:
c is a citation or axiomatic claim → true.c is a normal claim: locate its derivation premise (the inference
whose consequent is c's variable). Seed each variable referenced in
that premise's immediate antecedent true iff it is itself bound to a
citation/axiomatic claim, else null, and Kleene-evaluate the
antecedent once. Antecedent true → true; otherwise null. No
recursion — only the immediate antecedent claims' types are
inspected, never their own supports.null.The returned map is variable-keyed; use getVariableIdForClaim /
getClaimIdForVariable to translate to/from claimId.
Consistency with the axiomatic pre-pass: evaluate force-sets
axiomatic-bound variables true and rejects any explicit assignment
for them (AXIOM_VARIABLE_ASSIGNMENT_FORBIDDEN). This map reports those
same variables as true (the two agree), but the axiom keys must not be
passed to evaluate directly. Feed the map through evaluateWithDefaults
(which drops them), or strip axiomatic-bound keys before calling
evaluate yourself.
Returns the descendant checksum — derived from children's combinedChecksums. Null if no children.
Repair primitive: resolve D-3 violations (mixed-grounding antecedent — axioms + citations in one derivation) by deleting every axiom-bound variable expression from the offending antecedent subtree. The remaining citation-bound variables stay, giving the derivation a homogeneous citation-grounded antecedent.
User-initiated; never auto-runs. Respects behavior. In
'assistive' mode, AN may collapse a resulting single-child OR
via AN-3; in 'permissive' the OR may persist with one child
(a downstream D-2 violation — follow up with
removeOrphanOperators() if desired).
Ensures a claim-bound variable for the given claim exists in this argument. If one already exists, returns it. Otherwise creates a new claim-bound variable with a fresh UUID, the current version of the claim from the ClaimLibrary, and an auto-generated symbol.
Evaluates the argument under a three-valued expression assignment.
Variables may be assigned true, false, or null (unknown).
Evaluation reports a fourth value, CONTESTED, for anything the
reader's assignments and the steps they granted force both true and
false; null still means indeterminate. isAdmissibleAssignment,
survivingSupportingPremisesTrue, conclusionTrue and
premisesHoldConclusionFalse all range over the four values;
premiseSetSatisfiable stays three-valued, since it is a classical
search over the premise set alone.
The result is a set of orthogonal facts, not a single outcome. In
particular survivingSupportingPremisesTrue is vacuously true when
every supporting premise is struck, so whether the argument reached its
conclusion is conclusionAttribution.reachedWithoutAssertion and never
that field. A rejected operator strikes its whole premise and asserts
nothing.
Calls validateEvaluability() internally before evaluation; if the
argument is not structurally ready (including derivation pre-flight),
the method returns early with { ok: false } and the validation
details. Do not bypass evaluate to avoid this check.
Axiomatic-bound variables are forced true by this method's pre-pass and
passed down as forcedTrueVariableIds, so they are never read back as
reader assertions and never enter the reached-without-assertion
counterfactual. A caller's own forcedTrueVariableIds is unioned with
that set, never substituted for it.
The premise-set satisfiability search is given a wider set —
satisfiabilityForcedTrueVariableIds, every grounded variable, citation
as well as axiomatic. Whether the premises can hold together is a
question about the argument, so a cited claim is taken at its source's
word there, exactly as checkValidity does. The two sets are separate
because the narrower one also decides what counts as the reader's own
assertion, and a reader may disagree with a source: a citation belongs in
the satisfiability question and not in that one.
The variable assignment and the reader's operator decisions.
Optionaloptions: TCoreArgumentEvaluationOptionsOptional evaluation options.
The evaluation result, or { ok: false } with validation
details if the argument is not structurally evaluable.
Convenience: merge caller overrides over deriveDefaultAssignment()
and evaluate in one call. Default-sourced axiomatic-bound keys are
dropped before evaluation — the engine's pre-pass force-sets them true
and rejects explicit axiom assignments, so passing the default true
through would throw AXIOM_VARIABLE_ASSIGNMENT_FORBIDDEN. Dropping them
keeps deriveDefaultAssignment (which reports axioms as true) and the
pre-pass in agreement without double-applying. An override that names
an axiomatic variable is left intact, so evaluate still enforces the
one-way rule.
Citations are different from axioms. The engine does not force
citation-bound variables true and does not reject an explicit
citation assignment — a citation is a free variable, so its default
true is kept here (dropping it would leave the citation unknown at
evaluation). Both citations and axioms read as true under defaults, but
only the axiom true comes from the engine; the citation true is
supplied by this map. That also makes citation defaults reviewer-
overridable, whereas axioms stay locked.
Optionaloverrides: TCoreVariableAssignmentOptionaloptions: TCoreArgumentEvaluationOptionsReturns the PremiseEngine containing the given expression, or
undefined.
The expression ID to search for.
The owning PremiseEngine, or undefined.
Forces recomputation of all dirty checksums in the hierarchy.
Returns all expressions across all premises, sorted by ID.
An array of expression entities.
Returns a shallow copy of the argument metadata with checksum attached.
The argument entity.
Look up a claim by (id, version) in the engine's claim library.
Returns undefined if the claim is not present. Exposed for
repair primitives and other tooling that needs to inspect a
claim's type discriminator at a particular version pinned by
a claim-bound variable.
Returns the checksum for a named descendant collection. Null if collection is empty.
Returns the conclusion premise, or undefined if none is set.
The conclusion PremiseEngine, or undefined.
Returns an expression by ID from any premise, or undefined if not
found.
The expression ID to look up.
The expression entity, or undefined.
Returns the premise ID that contains the given expression, or
undefined.
The expression ID to look up.
The owning premise ID, or undefined.
Returns all expressions that reference the given variable ID, across all premises.
The variable ID to search for.
An array of referencing expression entities.
Returns the argument's extra metadata record (all fields except id, version, and checksums).
The extras record.
Returns the premise with the given ID, or undefined if not found.
The ID of the premise to retrieve.
The PremiseEngine instance, or undefined.
Returns the current role assignments (conclusion premise ID only; supporting is derived).
The current argument role state.
Returns the current reactive snapshot for external store consumption.
The reactive snapshot.
Returns the variable with the given ID, or undefined if not found.
The variable ID to look up.
The variable entity, or undefined.
Returns the variable with the given symbol, or undefined if not
found.
The symbol string to look up.
The variable entity, or undefined.
Returns the ID of the lowest-id claim-bound variable bound to claimId
in this argument, or undefined if no variable is. Pure lookup — it
never creates a variable (contrast ensureClaimBoundVariable).
The engine's evaluation surface is variable-keyed, but consumers key
their review/UI state by claimId; this accessor (with its inverse
getClaimIdForVariable) is the documented seam for translating between
the two.
It answers for one variable, and a claim may bind several. The pick
is deterministic and snapshot-stable — variables enumerate sorted by id
— but arbitrary with respect to the claim: it is not "the authored one"
or "the one an evaluation settled". When a claim may bind more than one
and losing the others would be wrong, use getVariableIdsForClaim.
Returns the IDs of every claim-bound variable bound to claimId in this
argument, in the engine's id-sorted variable order, or [] when none is.
Pure lookup — it never creates a variable (contrast
ensureClaimBoundVariable).
A claim may bind more than one variable: addVariable enforces no
per-claim uniqueness, so an argument can carry several variables
standing for the same proposition, each reached — and valued —
independently by evaluation. Any translation that must not lose one of
them (reading propagated values back onto a claim, say) belongs here
rather than on the singular accessor.
Returns all premise-bound variables whose boundPremiseId matches the
given premise ID. This is a linear scan over all variables.
The premise ID to filter by.
An array of variables bound to the given premise.
Returns true if an expression with the given ID exists in any
premise.
The expression ID to check.
Whether the expression exists.
Returns true if a premise with the given ID exists.
The ID to check.
Whether the premise exists.
Returns true if a variable with the given ID exists.
The variable ID to check.
Whether the variable exists.
Returns all premise IDs in lexicographic order.
An array of premise ID strings.
Returns all premises in lexicographic ID order.
An array of PremiseEngine instances.
Returns the root expression from each premise that has one.
An array of root expression entities.
Returns all supporting premises (derived: inference premises that are not the conclusion) in lexicographic ID order.
An array of supporting PremiseEngine instances.
Global normalize pass per spec §6. Runs the AN rule set
(AN-1..AN-4) everywhere it can fire, converging the argument
toward tier (defaults to 'presentable').
normalize is non-destructive in the logical-meaning sense — it
does not delete variables, change claim references, or modify
operator semantics. Recovery from Evaluable or Derivable violations
requires user intent and is exposed via the repair primitives.
In v1.0 every AN rule targets a Presentable invariant, so calls
with tier ∈ {'structural', 'evaluable', 'derivable'} are
effectively no-ops. The parameter exists as forward-compatible
API surface for a future submit/finalize gate.
Bypasses behavior. normalize() is user-initiated (the UI
invokes it after the user confirms a Tidy / Normalize action), so
cleanup runs regardless of whether the engine is in 'assistive'
or 'permissive' mode. The engine's behavior setting is not
mutated by this call.
ProtectednotifyPatches application-specific fields onto an expression across all premises, then marks the expression and its ancestors dirty so the next checksum flush recomputes from the patched values.
This is the public API for consumers that need to attach app-level
metadata (e.g. creatorId, createdOn) to expressions synthesized
by the engine's auto-normalization. It resolves the owning premise
internally, applies the patch in place, and marks the expression
dirty — callers cannot patch without marking (stale checksum) or mark
without patching (no-op). A field whose value is undefined is
deleted rather than assigned, so clearing one restores the shape and
the checksum the entity had before it was set.
The ID of the expression to patch.
Fields to merge into the expression.
Mirror of populateFromCitations for axiom connections. Same
factory contract: naked-Q-only, no throw on already-populated.
Construct (or no-op on) the per-claim derivation premise's antecedent from a citation lookup. Factory + naked-Q-only:
IMPLIES(citation-var, Q).IMPLIES(OR(c1, …, cn), Q). In
'assistive' mode the per-mutation AN-1 post-hook inserts a
formula buffer between IMPLIES and OR; in 'permissive' the
OR sits directly under IMPLIES (a P-1 violation surfaces via
validate('presentable')).No throw on already-populated. Per the Structural-only
mutation throw rule, if the target derivation premise is not in
the naked-Q form the factory returns { kind: 'no-op', state: <existing> } without mutating. UI/caller is responsible for
explicit user consent + clearing the antecedent via a repair
primitive before re-calling. Preserves the no-changes-without-
consent principle.
Throws only when no derivation premise exists for the given
derivedClaimId (legitimate entity-not-found Structural check).
Repair primitive: resolve E-6 violations (claim has > 1
derivation premise) by keeping one premise per derivedClaimId
and deleting the rest. Strategy controls which premise is kept:
'keep-first' (default): keep the premise with the
lexicographically smallest id; delete the rest. Deterministic
and snapshot-stable.'keep-largest-antecedent': keep the premise whose antecedent
subtree has the most claim-bound variable expressions; tie-break
by id.User-initiated; never auto-runs. Respects behavior.
Repair primitive: resolve E-1 violations (operators with < 2
children) by running the AN-3 cleanup pass globally. Returns the
violations resolved. The repair is non-meaning-changing — it
only removes empty operators and promotes single-child operators
— but lives alongside normalize() so the UI can present a
focused "Remove N orphan operators" action with a precise return
value.
User-initiated; never auto-runs. Bypasses behavior —
cleanup runs even in permissive mode (the user has already
accepted the action by clicking the repair button).
Removes a premise and reassigns any role assignments that reference it.
Invariant guard (1.0.2): when the removed premise was the
conclusion AND other premises remain after the delete, the
conclusion role is atomically reassigned to the lowest-id
remaining premise (sorted lexicographically) rather than left
undefined, preserving the engine-level invariant that a
non-empty argument always has a conclusion designated (E-7).
When the removed premise was the conclusion AND no premises
remain, the role is cleared as before (vacuous invariant on the
empty argument). Consumers that want a different reassignment
policy (e.g., server-side createdOn ordering or a UI-defined
sibling position) should issue their own
setConclusionPremise(...) call immediately after this method
returns — the post-mutation E-7 will continue to pass because
a conclusion stays designated throughout.
The ID of the premise to remove.
The removed premise data, or undefined if not found.
Repair primitive: resolve E-3 violations by deleting each unresolvable claim- or premise-bound variable, cascading the removal across all premises. Returns the violations resolved (for UX confirmation / undo / "we made N changes" feedback).
User-initiated; never auto-runs. Respects behavior: in
'assistive' mode, the AN post-hook fires after each cascade
mutation; in 'permissive' no AN runs.
Removes a variable and cascade-deletes all expressions referencing it
across every premise (including their full subtrees). As of v1.0
operator collapse on the surviving parents is the AN-3
post-mutation hook's responsibility in assistive behavior; in
permissive behavior the un-collapsed shape stays and surfaces via
engine.validate('presentable').
The ID of the variable to remove.
The removed variable, or undefined if not found.
Restores the engine to a previously captured snapshot state.
The snapshot to restore from.
Switches the engine's behavior at runtime. Going permissive → assistive does not auto-run a global normalize() pass; the
UI is expected to prompt the user before invoking normalize()
explicitly.
As of v1.0 behavior is enforced entirely via the AN
post-mutation hook in runAssistiveNormalization — the legacy
per-flag grammarConfig plumbing that bridged behavior to
premise-level enforcement is gone. Switching permissive → assistive makes the next successful Structural mutation trigger
the AN pass; switching the other direction stops the AN pass
from running until the user opts back in.
Designates a premise as the argument's conclusion.
The ID of the premise to designate.
The updated role state and changeset.
Replaces the argument's extra metadata record.
The new extras record.
The new extras record and a changeset with the modified argument.
Returns a serializable snapshot of the full engine state.
The engine snapshot.
Registers a listener that is called after every mutation.
The callback to invoke on mutation.
An unsubscribe function that removes the listener.
Renders the entity as a human-readable string.
A human-readable display string.
Shallow-merges updates into the argument's existing extras.
Key-value pairs to merge into the current extras.
The merged extras record and a changeset with the modified argument.
Updates fields on an existing variable. Since all premises share the same VariableManager, the update is immediately visible everywhere.
The ID of the variable to update.
Fields to update. For claim-bound variables: symbol,
claimId, claimVersion. For premise-bound variables: symbol,
boundPremiseId, boundArgumentId, boundArgumentVersion.
claimId and claimVersion must be provided together on claim-bound variables.
The updated variable, or undefined if not found.
Four-tier grammar validation per spec §4. Returns the union of
violations from Structural up through tier — 'structural'
returns S-rule violations only, 'evaluable' returns S + E,
'derivable' returns S + E + D, 'presentable' returns the full
union. Empty array means the argument is at the requested tier
or stricter. Never throws on grammar issues.
For the legacy pre-1.0 invariant sweep (schema conformance,
reference integrity, ownership, conclusion ref, circularity,
checksums) use validateInvariants instead. The pre-1.0
no-arg overload of validate() has been removed.
Returns the derivation-specific subset of validateEvaluability checks.
Apps can pre-check derivation premise structures before invoking the full
evaluation pipeline.
Violations carry the underlying DERIVATION_STRUCTURE_INVALID code
(per the derivation-validation utility). The pre-1.0
DERIVATION_STRUCTURE_INVALID_AT_EVALUATION override was removed
alongside the legacy validate() no-arg overload — naked-Q
is a valid Derivable state (per spec §4.2) and is skipped by
evaluation rather than thrown.
Validates that this argument is structurally ready for evaluation: a conclusion must be set, all role references must point to existing premises, variable ID/symbol mappings must be consistent, every premise must be individually evaluable, and all derivation premise structures must be well-formed (naked-Q invariant; since 0.11.0).
Derivation premises with structurally broken trees are flagged with
DERIVATION_STRUCTURE_INVALID. Use
validateDerivationStructures() to isolate derivation checks without
running the full evaluability sweep.
Naked-Q derivation premises (single-variable root) are not flagged
— they are a valid Derivable state per spec §4.2 and are skipped by
evaluation rather than throwing. The pre-1.0
DERIVATION_STRUCTURE_INVALID_AT_EVALUATION code has been removed.
A validation result with any issues found.
Legacy invariant sweep — schema conformance, reference integrity,
ownership, conclusion-ref + circularity, checksum stability, and
per-premise validation. Returns a TInvariantValidationResult.
Used internally by mutation-rollback and snapshot-load paths and
exposed publicly for library-wide invariant checks (see
ArgumentLibrary.validate and PropositCore.validate).
Distinct from validate, which runs the four-tier grammar
validator (Structural ⊇ Evaluable ⊇ Derivable ⊇ Presentable)
and returns a readonly TViolation[]. The two are
complementary — grammar tiers cover AST-shape rules; this method
covers schema/reference/structural-bookkeeping invariants that
sit outside the tier hierarchy.
ProtectedwithStaticfromCreates a new ArgumentEngine from flat arrays of entities, as typically
stored in a relational database. Expressions are grouped by their
premiseId field and loaded in BFS order (roots first, then children
of already-added nodes) to satisfy parent-existence requirements.
Optionalconfig: TLogicEngineOptionsOptionalchecksumVerification: "ignore" | "strict"StaticfromCreates a new ArgumentEngine from a previously captured snapshot.
OptionalchecksumVerification: "ignore" | "strict"OptionalgenerateId: () => string
Manages a propositional logic argument composed of premises, variable assignments, and logical roles (supporting premises and a conclusion).
Provides premise CRUD, role management, evaluation of individual assignments, and exhaustive validity checking via truth-table enumeration.