Variable: Constraint
@kortexya/reasoninglayer / Constraint
Variable: Constraint
Section titled “Variable: Constraint”
constConstraint:object
Defined in: src/builders/constraint.ts:57
Builders for the chainer’s homoiconic meta-constraints. Each function
returns a single TermInputArg representing one constraint term — drop
the result into a clause body or rule antecedents.
Type Declaration
Section titled “Type Declaration”aggregate()
Section titled “aggregate()”
readonlyaggregate(op,options):TermInputArg
Aggregate over every solution of a goal, and bind the result.
Parameters
Section titled “Parameters”"count" | "min" | "max" | "sum" | "avg"
The aggregation — count, sum, min, max, avg.
options
Section titled “options”The goal, where the result lands, the variable being aggregated, and an optional grouping variable.
The goal whose solutions are aggregated.
groupBy?
Section titled “groupBy?”string
Aggregate once per distinct value of this variable.
result
Section titled “result”string
The variable that receives the aggregate.
variable?
Section titled “variable?”string
The variable being aggregated. Omit for count.
Returns
Section titled “Returns”An aggregate_constraint term.
Remarks
Section titled “Remarks”A BODY aggregate, over the solutions of one goal. The HEAD aggregate — a rule that derives one conclusion per group — is AddRuleRequest.aggregator, and is a different mechanism.
variable, groupBy and result must be three DIFFERENT variables: the
evaluator identifies each by position, and aliasing two of them makes it
read one role as another. count is the one op that needs no variable.
Example
Section titled “Example”// ?Total is the sum of ?Amount over every line of the order.Constraint.aggregate('sum', { goal: psi('order_line', { order_number: '?No', amount: '?Amount' }), variable: '?Amount', result: '?Total',})
readonlycut():TermInputArg
Commit to the choices made so far in this clause.
Returns
Section titled “Returns”A cut term.
Remarks
Section titled “Remarks”Prolog’s !. Everything to its left in the body keeps its current
bindings and is not retried; alternative clauses for the same conclusion
are not tried either.
equation()
Section titled “equation()”
readonlyequation(result,op,left,right):TermInputArg
State that result = left op right. Selects the chainer sort by op:
+ → plus_constraint, - → minus_constraint, * →
times_constraint, / → div_constraint. The chainer reads each
operand as either a Reference variable or a numeric literal, and can
run forward, reverse, or verify depending on which operands are
bound.
Parameters
Section titled “Parameters”result
Section titled “result”Result variable or value (z).
Arithmetic operator.
Left operand (x).
Right operand (y).
Returns
Section titled “Returns”The appropriate arithmetic-constraint term.
findall()
Section titled “findall()”
readonlyfindall(template,goal,results):TermInputArg
Collect every solution of a goal into a list.
Parameters
Section titled “Parameters”template
Section titled “template”What to collect per solution — usually a variable the goal binds.
The goal to enumerate.
results
Section titled “results”string
The variable that receives the list.
Returns
Section titled “Returns”A findall_constraint term.
Remarks
Section titled “Remarks”Succeeds with an empty list when the goal has no solutions, which is what separates it from stating the goal directly.
Example
Section titled “Example”Constraint.findall('?Name', psi('employee', { name: '?Name' }), '?Everyone')forall()
Section titled “forall()”
readonlyforall(cond,action):TermInputArg
State that an action holds for EVERY solution of a condition.
Parameters
Section titled “Parameters”The condition to enumerate.
action
Section titled “action”What must hold for each of its solutions.
Returns
Section titled “Returns”A forall_constraint term.
Remarks
Section titled “Remarks”Vacuously true when the condition has no solutions — the usual reading of universal quantification, and worth stating because it is the usual surprise.
Example
Section titled “Example”// Every task of the project is done.Constraint.forall( psi('task', { project_code: '?P', key: '?K' }), psi('done_task', { key: '?K' }),)
readonlyhas(variable,feature,target):TermInputArg
State that a variable’s feature equals a target. The chainer unifies the variable’s feature value with the target.
Important: the chainer’s feature_constraint only unifies
term-references with term-references. The variable’s feature on the
persisted side must itself be a Value::Reference. Comparing against
literals (e.g. has('?N', 'name', 'S') where name is stored as a
plain string) silently returns zero solutions — that’s a chainer
design constraint, not a builder bug.
Parameters
Section titled “Parameters”variable
Section titled “variable”string
The owning variable (e.g. '?Edge').
feature
Section titled “feature”string
The feature name (e.g. 'src').
target
Section titled “target”The target — typically another variable ('?Src')
or an existing term referenced by its UUID via '!<uuid>'.
Returns
Section titled “Returns”A feature_constraint term.
intRange()
Section titled “intRange()”
readonlyintRange(variable,min,max):TermInputArg
Constrain a variable to be an integer in the inclusive range
[min, max]. Required before the chainer’s labeling step can assign
a concrete value via Constraint.solveFor.
Parameters
Section titled “Parameters”variable
Section titled “variable”string
Variable name to constrain.
number
Lower bound (inclusive).
number
Upper bound (inclusive).
Returns
Section titled “Returns”An fd_domain_constraint term.
readonlynot(goal):TermInputArg
State that a goal does NOT hold — negation as failure.
Parameters
Section titled “Parameters”The goal that must fail, as a Ψ-term.
Returns
Section titled “Returns”A negation term, for a rule body or a clause body.
Remarks
Section titled “Remarks”Closed-world: the goal fails when nothing in the store proves it, which is not the same as the store proving its opposite.
The engine spells this as a negation term whose clause feature
references the goal. Nothing in the SDK said so, and nothing in the
OpenAPI description of AddRuleRequest says so either — a caller had to
read TermStore::create_negation to find the shape. Hand-rolling it
with a different key silently produces a rule with an antecedent the
chainer does not recognise.
⚠️ Not expressible in OSFQL DERIVE at all (backend #244): the JSON
rule surface is the only one that has it.
Example
Section titled “Example”// An open invoice with no payment against it.await client.inference.addRule({ term: psi('unpaid_invoice', { number: '?N' }), antecedents: [ psi('invoice', { number: '?N', status: 'open' }), Constraint.not(psi('payment', { invoice_number: '?N' })), ],});once()
Section titled “once()”
readonlyonce(goal):TermInputArg
Take only the FIRST solution of a goal.
Parameters
Section titled “Parameters”The goal.
Returns
Section titled “Returns”A once_constraint term.
Remarks
Section titled “Remarks”Commits to the first solution and does not backtrack into the goal for more — the rule fires once per outer solution rather than once per inner one.
solveFor()
Section titled “solveFor()”
readonlysolveFor(…variables):TermInputArg
Search for concrete integer assignments to the listed variables that satisfy every other constraint mentioning them. Place this at the END of a clause body — it’s the labeling/search step that turns a constraint network into solutions.
Parameters
Section titled “Parameters”variables
Section titled “variables”…string[]
Variable names to assign.
Returns
Section titled “Returns”An fd_labeling_constraint term.
typeOf()
Section titled “typeOf()”
readonlytypeOf(variable,sortUuid):TermInputArg
State that a variable is a term of a given sort. The chainer enumerates every persisted term of that sort via backtracking.
Parameters
Section titled “Parameters”variable
Section titled “variable”string
Variable name (e.g. '?E') or pre-built variable Ψ-term.
sortUuid
Section titled “sortUuid”string
UUID of the target sort (resolve from
client.inference.getMetaSorts() or your own createSort response).
Returns
Section titled “Returns”A sort_constraint term.
where()
Section titled “where()”
readonlywhere(left,op,right):TermInputArg
State a boolean comparison between two operands. The chainer residuates the constraint until both sides are bound; when they are, the comparison must hold or the proof branch fails.
Parameters
Section titled “Parameters”Left operand — variable, literal number, or term ref.
Comparison operator.
Right operand.
Returns
Section titled “Returns”A guard_constraint term.
Remarks
Section titled “Remarks”These wrap the underlying meta-sort names (sort_constraint,
feature_constraint, guard_constraint, plus_constraint, etc.) and
use the exact feature keys the chainer reads. Hand-rolled psi('...')
calls with guessed keys silently fail — use these builders instead.
Example
Section titled “Example”import { Constraint, psi } from '@kortexya/reasoninglayer';
// "?E is a term of sort flow_edge_constraint, with edges leaving X"const body = [ Constraint.typeOf('?E', flowEdgeSortUuid), Constraint.has('?E', 'src', '?X'), Constraint.has('?E', 'dst', '?Y'), Constraint.has('?E', 'cap', '?C'), Constraint.intRange('?Amount', 1, 100), Constraint.where('?Amount', '<=', '?C'), Constraint.solveFor('?Amount'),];