@proposit/proposit-core 2.3.1 → 2.4.1
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/dist/cli/builder-repl.d.ts +3 -0
- package/dist/cli/builder-repl.d.ts.map +1 -0
- package/dist/cli/builder-repl.js +174 -0
- package/dist/cli/builder-repl.js.map +1 -0
- package/dist/extensions/builder/distill.d.ts +38 -0
- package/dist/extensions/builder/distill.d.ts.map +1 -0
- package/dist/extensions/builder/distill.js +81 -0
- package/dist/extensions/builder/distill.js.map +1 -0
- package/dist/extensions/builder/index.d.ts +7 -0
- package/dist/extensions/builder/index.d.ts.map +1 -0
- package/dist/extensions/builder/index.js +11 -0
- package/dist/extensions/builder/index.js.map +1 -0
- package/dist/extensions/builder/review.d.ts +11 -0
- package/dist/extensions/builder/review.d.ts.map +1 -0
- package/dist/extensions/builder/review.js +32 -0
- package/dist/extensions/builder/review.js.map +1 -0
- package/dist/extensions/builder/simulate.d.ts +12 -0
- package/dist/extensions/builder/simulate.d.ts.map +1 -0
- package/dist/extensions/builder/simulate.js +33 -0
- package/dist/extensions/builder/simulate.js.map +1 -0
- package/dist/extensions/openai/provider.d.ts.map +1 -1
- package/dist/extensions/openai/provider.js +3 -0
- package/dist/extensions/openai/provider.js.map +1 -1
- package/dist/extensions/openai/types.d.ts +2 -0
- package/dist/extensions/openai/types.d.ts.map +1 -1
- package/dist/lib/conversation/contract.d.ts +16 -0
- package/dist/lib/conversation/contract.d.ts.map +1 -0
- package/dist/lib/conversation/contract.js +9 -0
- package/dist/lib/conversation/contract.js.map +1 -0
- package/dist/lib/conversation/conversation.d.ts +43 -0
- package/dist/lib/conversation/conversation.d.ts.map +1 -0
- package/dist/lib/conversation/conversation.js +65 -0
- package/dist/lib/conversation/conversation.js.map +1 -0
- package/dist/lib/conversation/index.d.ts +8 -0
- package/dist/lib/conversation/index.d.ts.map +1 -0
- package/dist/lib/conversation/index.js +7 -0
- package/dist/lib/conversation/index.js.map +1 -0
- package/dist/lib/conversation/turn.d.ts +55 -0
- package/dist/lib/conversation/turn.d.ts.map +1 -0
- package/dist/lib/conversation/turn.js +112 -0
- package/dist/lib/conversation/turn.js.map +1 -0
- package/dist/lib/core/expression-manager-checks.d.ts +73 -0
- package/dist/lib/core/expression-manager-checks.d.ts.map +1 -0
- package/dist/lib/core/expression-manager-checks.js +355 -0
- package/dist/lib/core/expression-manager-checks.js.map +1 -0
- package/dist/lib/core/expression-manager-dirty-set.d.ts +21 -0
- package/dist/lib/core/expression-manager-dirty-set.d.ts.map +1 -0
- package/dist/lib/core/expression-manager-dirty-set.js +93 -0
- package/dist/lib/core/expression-manager-dirty-set.js.map +1 -0
- package/dist/lib/core/expression-manager-invariants.d.ts +14 -0
- package/dist/lib/core/expression-manager-invariants.d.ts.map +1 -0
- package/dist/lib/core/expression-manager-invariants.js +171 -0
- package/dist/lib/core/expression-manager-invariants.js.map +1 -0
- package/dist/lib/core/expression-manager.d.ts +2 -3
- package/dist/lib/core/expression-manager.d.ts.map +1 -1
- package/dist/lib/core/expression-manager.js +18 -523
- package/dist/lib/core/expression-manager.js.map +1 -1
- package/dist/lib/index.d.ts +4 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +6 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/llm/index.d.ts +1 -1
- package/dist/lib/llm/index.d.ts.map +1 -1
- package/dist/lib/llm/types.d.ts +13 -0
- package/dist/lib/llm/types.d.ts.map +1 -1
- package/dist/lib/parsing/prompt-builder.d.ts.map +1 -1
- package/dist/lib/parsing/prompt-builder.js +13 -5
- package/dist/lib/parsing/prompt-builder.js.map +1 -1
- package/dist/lib/pipelines/index.d.ts +4 -2
- package/dist/lib/pipelines/index.d.ts.map +1 -1
- package/dist/lib/pipelines/index.js +2 -1
- package/dist/lib/pipelines/index.js.map +1 -1
- package/dist/lib/pipelines/llm-stage-helpers.d.ts +126 -0
- package/dist/lib/pipelines/llm-stage-helpers.d.ts.map +1 -0
- package/dist/lib/pipelines/llm-stage-helpers.js +567 -0
- package/dist/lib/pipelines/llm-stage-helpers.js.map +1 -0
- package/dist/lib/pipelines/scheduler.d.ts +62 -0
- package/dist/lib/pipelines/scheduler.d.ts.map +1 -0
- package/dist/lib/pipelines/{execute.js → scheduler.js} +8 -325
- package/dist/lib/pipelines/scheduler.js.map +1 -0
- package/dist/lib/pipelines/{execute.d.ts → single-stage.d.ts} +2 -22
- package/dist/lib/pipelines/{execute.d.ts.map → single-stage.d.ts.map} +1 -1
- package/dist/lib/pipelines/single-stage.js +333 -0
- package/dist/lib/pipelines/single-stage.js.map +1 -0
- package/dist/lib/pipelines/stage-helpers.d.ts +4 -123
- package/dist/lib/pipelines/stage-helpers.d.ts.map +1 -1
- package/dist/lib/pipelines/stage-helpers.js +28 -567
- package/dist/lib/pipelines/stage-helpers.js.map +1 -1
- package/package.json +13 -3
- package/dist/lib/pipelines/execute.js.map +0 -1
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
const PERMITTED_OPERATOR_SWAPS = {
|
|
2
|
+
and: "or",
|
|
3
|
+
or: "and",
|
|
4
|
+
implies: "iff",
|
|
5
|
+
iff: "implies",
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Validates the preconditions for `ExpressionManager.insertExpression`
|
|
9
|
+
* (existence, arity, and root-only-operator rules) and returns the anchor
|
|
10
|
+
* slot the new expression inherits.
|
|
11
|
+
*
|
|
12
|
+
* @throws Under the same conditions documented on `insertExpression`.
|
|
13
|
+
*/
|
|
14
|
+
export function validateInsertExpression(expression, leftNodeId, rightNodeId, expressions) {
|
|
15
|
+
// 1. At least one child node must be provided.
|
|
16
|
+
if (leftNodeId === undefined && rightNodeId === undefined) {
|
|
17
|
+
throw new Error(`insertExpression requires at least one of leftNodeId or rightNodeId.`);
|
|
18
|
+
}
|
|
19
|
+
// 2. The new expression's ID must not already exist.
|
|
20
|
+
if (expressions.has(expression.id)) {
|
|
21
|
+
throw new Error(`Expression with ID "${expression.id}" already exists.`);
|
|
22
|
+
}
|
|
23
|
+
// 3. An expression cannot be its own parent.
|
|
24
|
+
if (expression.parentId === expression.id) {
|
|
25
|
+
throw new Error(`Expression "${expression.id}" cannot be its own parent.`);
|
|
26
|
+
}
|
|
27
|
+
// 4. Left and right nodes must be distinct.
|
|
28
|
+
if (leftNodeId !== undefined &&
|
|
29
|
+
rightNodeId !== undefined &&
|
|
30
|
+
leftNodeId === rightNodeId) {
|
|
31
|
+
throw new Error(`leftNodeId and rightNodeId must be different.`);
|
|
32
|
+
}
|
|
33
|
+
// 5. The left node must exist if provided.
|
|
34
|
+
// Cast to base TExpressionInput for validation access — deferred conditional
|
|
35
|
+
// types (TExpressionInput<TExpr>) cannot be narrowed by TS control flow.
|
|
36
|
+
const leftNode = leftNodeId !== undefined
|
|
37
|
+
? expressions.get(leftNodeId)
|
|
38
|
+
: undefined;
|
|
39
|
+
if (leftNodeId !== undefined && !leftNode) {
|
|
40
|
+
throw new Error(`Expression "${leftNodeId}" does not exist.`);
|
|
41
|
+
}
|
|
42
|
+
// 6. The right node must exist if provided.
|
|
43
|
+
const rightNode = rightNodeId !== undefined
|
|
44
|
+
? expressions.get(rightNodeId)
|
|
45
|
+
: undefined;
|
|
46
|
+
if (rightNodeId !== undefined && !rightNode) {
|
|
47
|
+
throw new Error(`Expression "${rightNodeId}" does not exist.`);
|
|
48
|
+
}
|
|
49
|
+
// 7a. A variable expression cannot have children.
|
|
50
|
+
if (expression.type === "variable") {
|
|
51
|
+
throw new Error(`Variable expression "${expression.id}" cannot have children.`);
|
|
52
|
+
}
|
|
53
|
+
// 7. The "not" operator is unary and cannot take two children.
|
|
54
|
+
if (expression.type === "operator" &&
|
|
55
|
+
expression.operator === "not" &&
|
|
56
|
+
leftNodeId !== undefined &&
|
|
57
|
+
rightNodeId !== undefined) {
|
|
58
|
+
throw new Error(`Operator expression "${expression.id}" with "not" can only have one child.`);
|
|
59
|
+
}
|
|
60
|
+
// 7b. A formula expression is also unary and cannot take two children.
|
|
61
|
+
if (expression.type === "formula" &&
|
|
62
|
+
leftNodeId !== undefined &&
|
|
63
|
+
rightNodeId !== undefined) {
|
|
64
|
+
throw new Error(`Formula expression "${expression.id}" can only have one child.`);
|
|
65
|
+
}
|
|
66
|
+
// 8. The left node must not be an implies/iff expression (which must remain a root).
|
|
67
|
+
if (leftNode?.type === "operator" &&
|
|
68
|
+
(leftNode.operator === "implies" || leftNode.operator === "iff")) {
|
|
69
|
+
throw new Error(`Expression "${leftNodeId}" with "${leftNode.operator}" cannot be subordinated (it must remain a root expression).`);
|
|
70
|
+
}
|
|
71
|
+
// 9. The right node must not be an implies/iff expression (which must remain a root).
|
|
72
|
+
if (rightNode?.type === "operator" &&
|
|
73
|
+
(rightNode.operator === "implies" || rightNode.operator === "iff")) {
|
|
74
|
+
throw new Error(`Expression "${rightNodeId}" with "${rightNode.operator}" cannot be subordinated (it must remain a root expression).`);
|
|
75
|
+
}
|
|
76
|
+
// The anchor is the node whose current tree slot the new expression will inherit.
|
|
77
|
+
const anchor = (leftNode ?? rightNode);
|
|
78
|
+
// 10. implies/iff expressions may only be inserted at the root of the tree.
|
|
79
|
+
if (expression.type === "operator" &&
|
|
80
|
+
(expression.operator === "implies" || expression.operator === "iff") &&
|
|
81
|
+
anchor.parentId !== null) {
|
|
82
|
+
throw new Error(`Operator expression "${expression.id}" with "${expression.operator}" must be a root expression (parentId must be null).`);
|
|
83
|
+
}
|
|
84
|
+
// The pre-v1.0 P-1 inline buffer-insertion / throw branches
|
|
85
|
+
// (gated on `grammarConfig.enforceFormulaBetweenOperators` +
|
|
86
|
+
// `resolveAutoNormalize(_, 'wrapInsertFormula')`) for three
|
|
87
|
+
// sites — (1) new expression as child of anchor's parent;
|
|
88
|
+
// (2) left node as child of new expression; (3) right node as
|
|
89
|
+
// child of new expression — were deleted. AN-1 (post-mutation
|
|
90
|
+
// hook in assistive mode) inserts the buffer when any of these
|
|
91
|
+
// sites produces a non-not operator under operator;
|
|
92
|
+
// permissive mode leaves the un-buffered state and
|
|
93
|
+
// `validate('presentable')` flags it.
|
|
94
|
+
return { anchorParentId: anchor.parentId, anchorPosition: anchor.position };
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Validates the preconditions for `ExpressionManager.wrapExpression`
|
|
98
|
+
* (existence, arity, and root-only-operator rules) and returns the existing
|
|
99
|
+
* node's ID plus the anchor slot the operator inherits.
|
|
100
|
+
*
|
|
101
|
+
* @throws Under the same conditions documented on `wrapExpression`.
|
|
102
|
+
*/
|
|
103
|
+
export function validateWrapExpression(operator, newSibling, leftNodeId, rightNodeId, expressions) {
|
|
104
|
+
// 1. Exactly one of leftNodeId / rightNodeId must be provided.
|
|
105
|
+
if (leftNodeId === undefined && rightNodeId === undefined) {
|
|
106
|
+
throw new Error(`wrapExpression requires exactly one of leftNodeId or rightNodeId.`);
|
|
107
|
+
}
|
|
108
|
+
if (leftNodeId !== undefined && rightNodeId !== undefined) {
|
|
109
|
+
throw new Error(`wrapExpression requires exactly one of leftNodeId or rightNodeId, not both.`);
|
|
110
|
+
}
|
|
111
|
+
// 2. Operator expression ID must not already exist.
|
|
112
|
+
if (expressions.has(operator.id)) {
|
|
113
|
+
throw new Error(`Expression with ID "${operator.id}" already exists.`);
|
|
114
|
+
}
|
|
115
|
+
// 3. New sibling expression ID must not already exist.
|
|
116
|
+
if (expressions.has(newSibling.id)) {
|
|
117
|
+
throw new Error(`Expression with ID "${newSibling.id}" already exists.`);
|
|
118
|
+
}
|
|
119
|
+
// 4. Operator and sibling IDs must be different.
|
|
120
|
+
if (operator.id === newSibling.id) {
|
|
121
|
+
throw new Error(`Operator and sibling expression IDs must be different.`);
|
|
122
|
+
}
|
|
123
|
+
// 5. The existing node must exist.
|
|
124
|
+
const existingNodeId = (leftNodeId ?? rightNodeId);
|
|
125
|
+
const existingNode = expressions.get(existingNodeId);
|
|
126
|
+
if (!existingNode) {
|
|
127
|
+
throw new Error(`Expression "${existingNodeId}" does not exist.`);
|
|
128
|
+
}
|
|
129
|
+
// 6. Operator expression must have type "operator".
|
|
130
|
+
if (operator.type !== "operator") {
|
|
131
|
+
throw new Error(`Wrap operator expression "${operator.id}" must have type "operator", got "${operator.type}".`);
|
|
132
|
+
}
|
|
133
|
+
// 7. Operator must not be unary ("not").
|
|
134
|
+
if (operator.operator === "not") {
|
|
135
|
+
throw new Error(`Operator expression "${operator.id}" with "not" cannot wrap (it is unary and wrapping always produces two children).`);
|
|
136
|
+
}
|
|
137
|
+
// 8. implies/iff operator only allowed if existing node is at root.
|
|
138
|
+
if ((operator.operator === "implies" || operator.operator === "iff") &&
|
|
139
|
+
existingNode.parentId !== null) {
|
|
140
|
+
throw new Error(`Operator expression "${operator.id}" with "${operator.operator}" must be a root expression (parentId must be null).`);
|
|
141
|
+
}
|
|
142
|
+
// 9. Existing node must not be implies/iff (cannot be subordinated).
|
|
143
|
+
if (existingNode.type === "operator" &&
|
|
144
|
+
(existingNode.operator === "implies" || existingNode.operator === "iff")) {
|
|
145
|
+
throw new Error(`Expression "${existingNodeId}" with "${existingNode.operator}" cannot be subordinated (it must remain a root expression).`);
|
|
146
|
+
}
|
|
147
|
+
// 10. New sibling must not be implies/iff (cannot be subordinated).
|
|
148
|
+
if (newSibling.type === "operator" &&
|
|
149
|
+
(newSibling.operator === "implies" || newSibling.operator === "iff")) {
|
|
150
|
+
throw new Error(`Sibling expression "${newSibling.id}" with "${newSibling.operator}" cannot be subordinated (it must remain a root expression).`);
|
|
151
|
+
}
|
|
152
|
+
// The pre-v1.0 P-1 inline buffer-insertion / throw branches
|
|
153
|
+
// (gated on `grammarConfig.enforceFormulaBetweenOperators` +
|
|
154
|
+
// `resolveAutoNormalize(_, 'wrapInsertFormula')`) for three
|
|
155
|
+
// sites — (1) new operator as child of existing node's parent;
|
|
156
|
+
// (2) existing node as child of new operator;
|
|
157
|
+
// (3) new sibling as child of new operator — were deleted.
|
|
158
|
+
// AN-1 (post-mutation hook in assistive mode) inserts the
|
|
159
|
+
// buffer when any of these sites produces a non-not operator
|
|
160
|
+
// under operator; permissive mode leaves the un-buffered state
|
|
161
|
+
// and `validate('presentable')` flags it.
|
|
162
|
+
return {
|
|
163
|
+
existingNodeId,
|
|
164
|
+
anchorParentId: existingNode.parentId,
|
|
165
|
+
anchorPosition: existingNode.position,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Computes the sibling-position redistribution range for
|
|
170
|
+
* `ExpressionManager.repositionSiblings`: which contiguous run of
|
|
171
|
+
* `children` to shift, and the bounds to spread them across.
|
|
172
|
+
*
|
|
173
|
+
* @throws If neither direction has enough space to redistribute into.
|
|
174
|
+
*/
|
|
175
|
+
export function validateRepositionSiblings(children, leftPos, rightPos, positionConfig) {
|
|
176
|
+
const positions = children.map((c) => c.position);
|
|
177
|
+
const leftIdx = positions.indexOf(leftPos);
|
|
178
|
+
const rightIdx = positions.indexOf(rightPos);
|
|
179
|
+
// Scan left from leftIdx: expand while consecutive gaps <= 1.
|
|
180
|
+
let scanLeft;
|
|
181
|
+
let leftBound;
|
|
182
|
+
let leftCount;
|
|
183
|
+
if (leftIdx === -1) {
|
|
184
|
+
// leftPos is a boundary (positionConfig.min), not a real node.
|
|
185
|
+
scanLeft = 0;
|
|
186
|
+
leftBound = leftPos;
|
|
187
|
+
leftCount = 0;
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
scanLeft = leftIdx;
|
|
191
|
+
while (scanLeft > 0 &&
|
|
192
|
+
positions[scanLeft] - positions[scanLeft - 1] <= 1) {
|
|
193
|
+
scanLeft--;
|
|
194
|
+
}
|
|
195
|
+
leftBound = scanLeft > 0 ? positions[scanLeft - 1] : positionConfig.min;
|
|
196
|
+
leftCount = leftIdx - scanLeft + 1;
|
|
197
|
+
}
|
|
198
|
+
// Scan right from rightIdx: expand while consecutive gaps <= 1.
|
|
199
|
+
let scanRight;
|
|
200
|
+
let rightBound;
|
|
201
|
+
let rightCount;
|
|
202
|
+
if (rightIdx === -1) {
|
|
203
|
+
// rightPos is a boundary (positionConfig.max), not a real node.
|
|
204
|
+
scanRight = positions.length - 1;
|
|
205
|
+
rightBound = rightPos;
|
|
206
|
+
rightCount = 0;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
scanRight = rightIdx;
|
|
210
|
+
while (scanRight < positions.length - 1 &&
|
|
211
|
+
positions[scanRight + 1] - positions[scanRight] <= 1) {
|
|
212
|
+
scanRight++;
|
|
213
|
+
}
|
|
214
|
+
rightBound =
|
|
215
|
+
scanRight < positions.length - 1
|
|
216
|
+
? positions[scanRight + 1]
|
|
217
|
+
: positionConfig.max;
|
|
218
|
+
rightCount = scanRight - rightIdx + 1;
|
|
219
|
+
}
|
|
220
|
+
// Pick direction with fewer nodes. Tie-break: right.
|
|
221
|
+
let startIdx;
|
|
222
|
+
let endIdx;
|
|
223
|
+
let lowerBound;
|
|
224
|
+
let upperBound;
|
|
225
|
+
if (leftCount > 0 && leftCount < rightCount) {
|
|
226
|
+
startIdx = scanLeft;
|
|
227
|
+
endIdx = leftIdx;
|
|
228
|
+
lowerBound = leftBound;
|
|
229
|
+
upperBound = rightPos;
|
|
230
|
+
}
|
|
231
|
+
else if (rightCount > 0) {
|
|
232
|
+
startIdx = rightIdx;
|
|
233
|
+
endIdx = scanRight;
|
|
234
|
+
lowerBound = leftPos;
|
|
235
|
+
upperBound = rightBound;
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
// leftCount > 0, rightCount === 0: must pick left.
|
|
239
|
+
startIdx = scanLeft;
|
|
240
|
+
endIdx = leftIdx;
|
|
241
|
+
lowerBound = leftBound;
|
|
242
|
+
upperBound = rightPos;
|
|
243
|
+
}
|
|
244
|
+
const count = endIdx - startIdx + 1;
|
|
245
|
+
const range = upperBound - lowerBound;
|
|
246
|
+
if (range <= count) {
|
|
247
|
+
throw new Error(`Cannot reposition: not enough space in range (${lowerBound}, ${upperBound}) for ${count} expressions.`);
|
|
248
|
+
}
|
|
249
|
+
return { startIdx, endIdx, lowerBound, upperBound, count };
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Validates the preconditions for `ExpressionManager.updateExpression`
|
|
253
|
+
* and, when the update includes a position change, performs the sibling
|
|
254
|
+
* position-set swap (delete old position, reject or accept the new one).
|
|
255
|
+
*
|
|
256
|
+
* Mutates `childPositionsByParentId` in place when a position update is
|
|
257
|
+
* accepted — this is the one check in this module that isn't a pure
|
|
258
|
+
* throw-or-void helper, since the swap must happen atomically with the
|
|
259
|
+
* collision check to avoid leaving the position set inconsistent.
|
|
260
|
+
*
|
|
261
|
+
* @throws Under the same conditions documented on `updateExpression`.
|
|
262
|
+
*/
|
|
263
|
+
export function validateUpdateExpression(expressionId, expression, updates, childPositionsByParentId) {
|
|
264
|
+
// Reject forbidden fields passed via `as any`.
|
|
265
|
+
const FORBIDDEN_KEYS = [
|
|
266
|
+
"id",
|
|
267
|
+
"argumentId",
|
|
268
|
+
"argumentVersion",
|
|
269
|
+
"premiseId",
|
|
270
|
+
"checksum",
|
|
271
|
+
"parentId",
|
|
272
|
+
"type",
|
|
273
|
+
];
|
|
274
|
+
for (const key of FORBIDDEN_KEYS) {
|
|
275
|
+
if (key in updates) {
|
|
276
|
+
throw new Error(`Field "${key}" is forbidden in expression updates.`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// Validate operator change.
|
|
280
|
+
if (updates.operator !== undefined) {
|
|
281
|
+
if (expression.type !== "operator") {
|
|
282
|
+
throw new Error(`Expression "${expressionId}" is not an operator expression; cannot update operator.`);
|
|
283
|
+
}
|
|
284
|
+
const permitted = PERMITTED_OPERATOR_SWAPS[expression.operator];
|
|
285
|
+
if (permitted !== updates.operator) {
|
|
286
|
+
throw new Error(`Changing operator from "${expression.operator}" to "${updates.operator}" is not a permitted operator change. Permitted: and↔or, implies↔iff.`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// Validate variableId change.
|
|
290
|
+
if (updates.variableId !== undefined) {
|
|
291
|
+
if (expression.type !== "variable") {
|
|
292
|
+
throw new Error(`Expression "${expressionId}" is not a variable expression; cannot update variableId.`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// Validate position change.
|
|
296
|
+
if (updates.position !== undefined) {
|
|
297
|
+
const positionSet = childPositionsByParentId.get(expression.parentId);
|
|
298
|
+
if (positionSet) {
|
|
299
|
+
positionSet.delete(expression.position);
|
|
300
|
+
if (positionSet.has(updates.position)) {
|
|
301
|
+
// Restore old position before throwing.
|
|
302
|
+
positionSet.add(expression.position);
|
|
303
|
+
throw new Error(`Position ${updates.position} is already used under parent "${expression.parentId}".`);
|
|
304
|
+
}
|
|
305
|
+
positionSet.add(updates.position);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Validates the preconditions for the single-child-promotion branch of
|
|
311
|
+
* `ExpressionManager.removeAndPromote` and returns which of the two
|
|
312
|
+
* branches applies.
|
|
313
|
+
*
|
|
314
|
+
* @throws If `target` has more than one child.
|
|
315
|
+
* @throws If the single child is a root-only operator (`implies`/`iff`)
|
|
316
|
+
* that would be placed in a non-root position.
|
|
317
|
+
* @returns The child to promote, or `undefined` for a plain leaf removal.
|
|
318
|
+
*/
|
|
319
|
+
export function validateRemoveAndPromote(expressionId, target, children) {
|
|
320
|
+
if (children.length > 1) {
|
|
321
|
+
throw new Error(`Cannot promote: expression "${expressionId}" has multiple children (${children.length}). Use deleteSubtree: true or remove children first.`);
|
|
322
|
+
}
|
|
323
|
+
if (children.length === 0) {
|
|
324
|
+
return undefined;
|
|
325
|
+
}
|
|
326
|
+
// Exactly 1 child — promote it into the target's slot.
|
|
327
|
+
const child = children[0];
|
|
328
|
+
// The P-1 promote-on-remove enforcement throw lived here under
|
|
329
|
+
// `grammarConfig.enforceFormulaBetweenOperators`. AN-1 (post-mutation
|
|
330
|
+
// hook in assistive mode) now inserts the buffer if the promotion
|
|
331
|
+
// produced a non-not operator under operator; permissive mode leaves
|
|
332
|
+
// the un-buffered state and `validate('presentable')` flags it.
|
|
333
|
+
// Validate: root-only operators cannot be promoted into a non-root position.
|
|
334
|
+
if (child.type === "operator" &&
|
|
335
|
+
(child.operator === "implies" || child.operator === "iff") &&
|
|
336
|
+
target.parentId !== null) {
|
|
337
|
+
throw new Error(`Cannot promote: child "${child.id}" is a root-only operator ("${child.operator}") and would be placed in a non-root position.`);
|
|
338
|
+
}
|
|
339
|
+
return child;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Validates the preconditions for
|
|
343
|
+
* `ExpressionManager.addExpressionRelative` and returns the sibling
|
|
344
|
+
* looked up by ID.
|
|
345
|
+
*
|
|
346
|
+
* @throws If the sibling does not exist.
|
|
347
|
+
*/
|
|
348
|
+
export function validateAddExpressionRelative(siblingId, expressions) {
|
|
349
|
+
const sibling = expressions.get(siblingId);
|
|
350
|
+
if (!sibling) {
|
|
351
|
+
throw new Error(`Expression "${siblingId}" not found.`);
|
|
352
|
+
}
|
|
353
|
+
return sibling;
|
|
354
|
+
}
|
|
355
|
+
//# sourceMappingURL=expression-manager-checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression-manager-checks.js","sourceRoot":"","sources":["../../../src/lib/core/expression-manager-checks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { TCorePropositionalExpression } from "../schemata/index.js";
|
|
2
|
+
import type { ChangeCollector } from "./change-collector.js";
|
|
3
|
+
import type { TLogicEngineOptions } from "./argument-engine.js";
|
|
4
|
+
/**
|
|
5
|
+
* Marks an expression and all its ancestors as dirty for hierarchical
|
|
6
|
+
* checksum recomputation. Stops early when it reaches an expression
|
|
7
|
+
* already in the dirty set (since its ancestors are already marked).
|
|
8
|
+
*/
|
|
9
|
+
export declare function markExpressionDirty<TExpr extends TCorePropositionalExpression>(exprId: string, dirtyExpressionIds: Set<string>, expressions: Map<string, TExpr>): void;
|
|
10
|
+
/**
|
|
11
|
+
* Recomputes `descendantChecksum` and `combinedChecksum` for all dirty
|
|
12
|
+
* expressions, processing bottom-up (deepest first) so that children
|
|
13
|
+
* are up-to-date before their parents are computed.
|
|
14
|
+
*/
|
|
15
|
+
export declare function flushExpressionChecksums<TExpr extends TCorePropositionalExpression>(dirtyExpressionIds: Set<string>, expressions: Map<string, TExpr>, childExpressionIdsByParentId: Map<string | null, Set<string>>, config: TLogicEngineOptions | undefined, collector: ChangeCollector | null): void;
|
|
16
|
+
/**
|
|
17
|
+
* Removes deleted expression IDs from the dirty set so that flush
|
|
18
|
+
* doesn't attempt to process expressions that no longer exist.
|
|
19
|
+
*/
|
|
20
|
+
export declare function pruneDeletedFromDirtySet(deletedIds: Set<string>, dirtyExpressionIds: Set<string>): void;
|
|
21
|
+
//# sourceMappingURL=expression-manager-dirty-set.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression-manager-dirty-set.d.ts","sourceRoot":"","sources":["../../../src/lib/core/expression-manager-dirty-set.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAA;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAI/D;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,SAAS,4BAA4B,EAC1E,MAAM,EAAE,MAAM,EACd,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,EAC/B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,GAChC,IAAI,CAQN;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACpC,KAAK,SAAS,4BAA4B,EAE1C,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,EAC/B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,EAC/B,4BAA4B,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,EAC7D,MAAM,EAAE,mBAAmB,GAAG,SAAS,EACvC,SAAS,EAAE,eAAe,GAAG,IAAI,GAClC,IAAI,CA2EN;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACpC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,EACvB,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,GAChC,IAAI,CAIN"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { DEFAULT_CHECKSUM_CONFIG } from "../consts.js";
|
|
2
|
+
import { entityChecksum, computeHash, canonicalSerialize } from "./checksum.js";
|
|
3
|
+
/**
|
|
4
|
+
* Marks an expression and all its ancestors as dirty for hierarchical
|
|
5
|
+
* checksum recomputation. Stops early when it reaches an expression
|
|
6
|
+
* already in the dirty set (since its ancestors are already marked).
|
|
7
|
+
*/
|
|
8
|
+
export function markExpressionDirty(exprId, dirtyExpressionIds, expressions) {
|
|
9
|
+
let current = exprId;
|
|
10
|
+
while (current !== null) {
|
|
11
|
+
if (dirtyExpressionIds.has(current))
|
|
12
|
+
break; // ancestors already dirty
|
|
13
|
+
dirtyExpressionIds.add(current);
|
|
14
|
+
const expr = expressions.get(current);
|
|
15
|
+
current = expr ? expr.parentId : null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Recomputes `descendantChecksum` and `combinedChecksum` for all dirty
|
|
20
|
+
* expressions, processing bottom-up (deepest first) so that children
|
|
21
|
+
* are up-to-date before their parents are computed.
|
|
22
|
+
*/
|
|
23
|
+
export function flushExpressionChecksums(dirtyExpressionIds, expressions, childExpressionIdsByParentId, config, collector) {
|
|
24
|
+
if (dirtyExpressionIds.size === 0)
|
|
25
|
+
return;
|
|
26
|
+
// Sort dirty expressions by depth (deepest first) for bottom-up processing
|
|
27
|
+
const dirtyIds = [...dirtyExpressionIds];
|
|
28
|
+
const depthOf = (id) => {
|
|
29
|
+
let depth = 0;
|
|
30
|
+
let current = expressions.get(id);
|
|
31
|
+
while (current && current.parentId !== null) {
|
|
32
|
+
depth++;
|
|
33
|
+
current = expressions.get(current.parentId);
|
|
34
|
+
}
|
|
35
|
+
return depth;
|
|
36
|
+
};
|
|
37
|
+
dirtyIds.sort((a, b) => depthOf(b) - depthOf(a));
|
|
38
|
+
const fields = config?.checksumConfig?.expressionFields ??
|
|
39
|
+
DEFAULT_CHECKSUM_CONFIG.expressionFields;
|
|
40
|
+
for (const id of dirtyIds) {
|
|
41
|
+
const expr = expressions.get(id);
|
|
42
|
+
if (!expr)
|
|
43
|
+
continue;
|
|
44
|
+
const oldChecksum = expr.checksum;
|
|
45
|
+
const oldDescendantChecksum = expr.descendantChecksum;
|
|
46
|
+
const oldCombinedChecksum = expr.combinedChecksum;
|
|
47
|
+
const metaChecksum = entityChecksum(expr, fields);
|
|
48
|
+
const childIds = childExpressionIdsByParentId.get(id);
|
|
49
|
+
let descendantChecksum = null;
|
|
50
|
+
if (childIds && childIds.size > 0) {
|
|
51
|
+
const childMap = {};
|
|
52
|
+
for (const childId of childIds) {
|
|
53
|
+
const child = expressions.get(childId);
|
|
54
|
+
if (child) {
|
|
55
|
+
childMap[childId] = child.combinedChecksum;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
descendantChecksum = computeHash(canonicalSerialize(childMap));
|
|
59
|
+
}
|
|
60
|
+
const combinedChecksum = descendantChecksum === null
|
|
61
|
+
? metaChecksum
|
|
62
|
+
: computeHash(metaChecksum + descendantChecksum);
|
|
63
|
+
expressions.set(id, {
|
|
64
|
+
...expr,
|
|
65
|
+
checksum: metaChecksum,
|
|
66
|
+
descendantChecksum,
|
|
67
|
+
combinedChecksum,
|
|
68
|
+
});
|
|
69
|
+
if (collector &&
|
|
70
|
+
!collector.isExpressionAdded(expr.id) &&
|
|
71
|
+
(metaChecksum !== oldChecksum ||
|
|
72
|
+
descendantChecksum !== oldDescendantChecksum ||
|
|
73
|
+
combinedChecksum !== oldCombinedChecksum)) {
|
|
74
|
+
collector.modifiedExpression({
|
|
75
|
+
...expr,
|
|
76
|
+
checksum: metaChecksum,
|
|
77
|
+
descendantChecksum,
|
|
78
|
+
combinedChecksum,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
dirtyExpressionIds.clear();
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Removes deleted expression IDs from the dirty set so that flush
|
|
86
|
+
* doesn't attempt to process expressions that no longer exist.
|
|
87
|
+
*/
|
|
88
|
+
export function pruneDeletedFromDirtySet(deletedIds, dirtyExpressionIds) {
|
|
89
|
+
for (const id of deletedIds) {
|
|
90
|
+
dirtyExpressionIds.delete(id);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=expression-manager-dirty-set.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression-manager-dirty-set.js","sourceRoot":"","sources":["../../../src/lib/core/expression-manager-dirty-set.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TCorePropositionalExpression } from "../schemata/index.js";
|
|
2
|
+
import type { ChangeCollector } from "./change-collector.js";
|
|
3
|
+
import type { TLogicEngineOptions } from "./argument-engine.js";
|
|
4
|
+
import type { TInvariantValidationResult } from "../types/validation.js";
|
|
5
|
+
/**
|
|
6
|
+
* Performs a comprehensive validation sweep on all managed expressions.
|
|
7
|
+
*
|
|
8
|
+
* Collects ALL violations rather than failing on the first one. Checks:
|
|
9
|
+
* schema validity, duplicate IDs, self-referential parents, parent
|
|
10
|
+
* existence, parent container type, root-only operators, child limits,
|
|
11
|
+
* position uniqueness, and checksum integrity.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateExpressionManagerInvariants<TExpr extends TCorePropositionalExpression>(expressions: Map<string, TExpr>, childExpressionIdsByParentId: Map<string | null, Set<string>>, dirtyExpressionIds: Set<string>, config: TLogicEngineOptions | undefined, collector: ChangeCollector | null): TInvariantValidationResult;
|
|
14
|
+
//# sourceMappingURL=expression-manager-invariants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression-manager-invariants.d.ts","sourceRoot":"","sources":["../../../src/lib/core/expression-manager-invariants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAA;AAExE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAE/D,OAAO,KAAK,EAER,0BAA0B,EAC7B,MAAM,wBAAwB,CAAA;AAc/B;;;;;;;GAOG;AACH,wBAAgB,mCAAmC,CAC/C,KAAK,SAAS,4BAA4B,EAE1C,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,EAC/B,4BAA4B,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,EAC7D,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,EAC/B,MAAM,EAAE,mBAAmB,GAAG,SAAS,EACvC,SAAS,EAAE,eAAe,GAAG,IAAI,GAClC,0BAA0B,CAoM5B"}
|