@plures/praxis 1.2.13 → 1.3.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 +44 -0
- package/dist/browser/chunk-MJK3IYTJ.js +384 -0
- package/dist/browser/{chunk-K377RW4V.js → chunk-N63K4KWS.js} +1 -1
- package/dist/browser/{engine-YJZV4SLD.js → engine-YIEGSX7U.js} +1 -1
- package/dist/browser/index.d.ts +104 -2
- package/dist/browser/index.js +188 -7
- package/dist/browser/integrations/svelte.d.ts +2 -2
- package/dist/browser/integrations/svelte.js +2 -2
- package/dist/browser/{reactive-engine.svelte-9aS0kTa8.d.ts → reactive-engine.svelte-DjynI82A.d.ts} +139 -5
- package/dist/node/{chunk-PRPQO6R5.js → chunk-5JQJZADT.js} +1 -1
- package/dist/node/chunk-KMJWAFZV.js +389 -0
- package/dist/node/{chunk-5RH7UAQC.js → chunk-PTH6MD6P.js} +1 -0
- package/dist/node/cli/index.cjs +1553 -839
- package/dist/node/cli/index.js +39 -2
- package/dist/node/cloud/index.d.cts +1 -1
- package/dist/node/cloud/index.d.ts +1 -1
- package/dist/node/components/index.d.cts +2 -2
- package/dist/node/components/index.d.ts +2 -2
- package/dist/node/conversations-KQBXTP3N.js +596 -0
- package/dist/node/{engine-2DQBKBJC.js → engine-FEN5IYZ5.js} +1 -1
- package/dist/node/index.cjs +911 -43
- package/dist/node/index.d.cts +574 -7
- package/dist/node/index.d.ts +574 -7
- package/dist/node/index.js +672 -26
- package/dist/node/integrations/svelte.cjs +190 -3
- package/dist/node/integrations/svelte.d.cts +3 -3
- package/dist/node/integrations/svelte.d.ts +3 -3
- package/dist/node/integrations/svelte.js +2 -2
- package/dist/node/{protocol-Qek7ebBl.d.ts → protocol-DcyGMmWY.d.cts} +8 -1
- package/dist/node/{protocol-Qek7ebBl.d.cts → protocol-DcyGMmWY.d.ts} +8 -1
- package/dist/node/{reactive-engine.svelte-CRNqHlbv.d.ts → reactive-engine.svelte-Cg0Yc2Hs.d.cts} +145 -6
- package/dist/node/{reactive-engine.svelte-BFIZfawz.d.cts → reactive-engine.svelte-DekxqFu0.d.ts} +145 -6
- package/dist/node/{terminal-adapter-B-UK_Vdz.d.ts → terminal-adapter-CvIvgTo4.d.ts} +1 -1
- package/dist/node/{terminal-adapter-BQSIF5bf.d.cts → terminal-adapter-Db-snPJ3.d.cts} +1 -1
- package/dist/node/{validate-CNHUULQE.js → validate-EN3M4FUR.js} +1 -1
- package/dist/node/{verify-KLJRXVJS.js → verify-7VZRP2WS.js} +2 -2
- package/docs/BOT_UPDATE_POLICY.md +125 -0
- package/docs/DOGFOODING_CHECKLIST.md +254 -0
- package/docs/DOGFOODING_INDEX.md +169 -0
- package/docs/DOGFOODING_QUICK_START.md +140 -0
- package/docs/KNO_ENG_EXTRACTION_PLAN.md +577 -0
- package/docs/PLURES_TOOLS_INVENTORY.md +170 -0
- package/docs/README.md +12 -0
- package/docs/TESTING_BOT_WORKFLOWS.md +154 -0
- package/docs/conversations/INTEGRATION_POINTS.md +719 -0
- package/docs/conversations/README.md +168 -0
- package/docs/core/extending-praxis-core.md +604 -0
- package/docs/core/praxis-core-api.md +385 -0
- package/docs/decision-ledger/contract-index.json +2 -2
- package/docs/decision-ledger/decisions/2026-02-01-monorepo-organization.md +130 -0
- package/docs/examples/DOGFOODING_WORKFLOW_EXAMPLE.md +295 -0
- package/docs/examples/README.md +41 -0
- package/docs/workflows/pr-overlap-guard.md +50 -0
- package/package.json +8 -3
- package/src/__tests__/chronicle.test.ts +512 -0
- package/src/__tests__/conversations.test.ts +312 -0
- package/src/__tests__/edge-cases.test.ts +1 -1
- package/src/__tests__/engine-dx.test.ts +355 -0
- package/src/__tests__/engine-v2.test.ts +532 -0
- package/src/cli/commands/conversations.ts +252 -0
- package/src/cli/index.ts +73 -0
- package/src/conversations/README.md +230 -0
- package/src/conversations/candidate.schema.json +123 -0
- package/src/conversations/candidates.ts +114 -0
- package/src/conversations/capture.ts +56 -0
- package/src/conversations/classify.ts +110 -0
- package/src/conversations/conversation.schema.json +106 -0
- package/src/conversations/emitters/fs.ts +65 -0
- package/src/conversations/emitters/github.ts +115 -0
- package/src/conversations/gate.ts +102 -0
- package/src/conversations/index.ts +28 -0
- package/src/conversations/normalize.ts +51 -0
- package/src/conversations/redact.ts +57 -0
- package/src/conversations/types.ts +96 -0
- package/src/core/chronicle/chronicle.ts +227 -0
- package/src/core/chronicle/context.ts +80 -0
- package/src/core/chronicle/index.ts +53 -0
- package/src/core/chronicle/mcp.ts +135 -0
- package/src/core/chronicle/types.ts +61 -0
- package/src/core/completeness.ts +274 -0
- package/src/core/engine.ts +143 -3
- package/src/core/pluresdb/index.ts +22 -0
- package/src/core/pluresdb/store.ts +171 -8
- package/src/core/protocol.ts +7 -0
- package/src/core/rule-result.ts +130 -0
- package/src/core/rules.ts +24 -5
- package/src/core/ui-rules.ts +340 -0
- package/src/dsl/index.ts +6 -0
- package/src/index.ts +45 -0
- package/src/integrations/pluresdb.ts +22 -0
- package/src/vite/completeness-plugin.ts +72 -0
- package/dist/browser/chunk-VOMLVI6V.js +0 -197
- package/dist/node/chunk-VOMLVI6V.js +0 -197
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
// src/core/protocol.ts
|
|
2
|
+
var PRAXIS_PROTOCOL_VERSION = "1.0.0";
|
|
3
|
+
|
|
4
|
+
// src/core/rule-result.ts
|
|
5
|
+
var RuleResult = class _RuleResult {
|
|
6
|
+
/** The kind of result */
|
|
7
|
+
kind;
|
|
8
|
+
/** Facts produced (only for 'emit') */
|
|
9
|
+
facts;
|
|
10
|
+
/** Fact tags to retract (only for 'retract') */
|
|
11
|
+
retractTags;
|
|
12
|
+
/** Optional reason (for noop/skip/retract — useful for debugging) */
|
|
13
|
+
reason;
|
|
14
|
+
/** The rule ID that produced this result (set by engine) */
|
|
15
|
+
ruleId;
|
|
16
|
+
constructor(kind, facts, retractTags, reason) {
|
|
17
|
+
this.kind = kind;
|
|
18
|
+
this.facts = facts;
|
|
19
|
+
this.retractTags = retractTags;
|
|
20
|
+
this.reason = reason;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Rule produced facts.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* return RuleResult.emit([
|
|
27
|
+
* { tag: 'sprint.behind', payload: { deficit: 5 } }
|
|
28
|
+
* ]);
|
|
29
|
+
*/
|
|
30
|
+
static emit(facts) {
|
|
31
|
+
if (facts.length === 0) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
"RuleResult.emit() requires at least one fact. Use RuleResult.noop() or RuleResult.skip() when a rule has nothing to say."
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
return new _RuleResult("emit", facts, []);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Rule evaluated but had nothing to report.
|
|
40
|
+
* Unlike returning [], this is explicit and traceable.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* if (ctx.completedHours >= expectedHours) {
|
|
44
|
+
* return RuleResult.noop('Sprint is on pace');
|
|
45
|
+
* }
|
|
46
|
+
*/
|
|
47
|
+
static noop(reason) {
|
|
48
|
+
return new _RuleResult("noop", [], [], reason);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Rule decided to skip because preconditions were not met.
|
|
52
|
+
* Distinct from noop: skip means "I can't evaluate", noop means "I evaluated and found nothing".
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* if (!ctx.sprintName) {
|
|
56
|
+
* return RuleResult.skip('No active sprint');
|
|
57
|
+
* }
|
|
58
|
+
*/
|
|
59
|
+
static skip(reason) {
|
|
60
|
+
return new _RuleResult("skip", [], [], reason);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Rule retracts previously emitted facts by tag.
|
|
64
|
+
* Used when a condition that previously produced facts is no longer true.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* // Sprint was behind, but caught up
|
|
68
|
+
* if (ctx.completedHours >= expectedHours) {
|
|
69
|
+
* return RuleResult.retract(['sprint.behind'], 'Sprint caught up');
|
|
70
|
+
* }
|
|
71
|
+
*/
|
|
72
|
+
static retract(tags, reason) {
|
|
73
|
+
if (tags.length === 0) {
|
|
74
|
+
throw new Error("RuleResult.retract() requires at least one tag.");
|
|
75
|
+
}
|
|
76
|
+
return new _RuleResult("retract", [], tags, reason);
|
|
77
|
+
}
|
|
78
|
+
/** Whether this result produced facts */
|
|
79
|
+
get hasFacts() {
|
|
80
|
+
return this.facts.length > 0;
|
|
81
|
+
}
|
|
82
|
+
/** Whether this result retracts facts */
|
|
83
|
+
get hasRetractions() {
|
|
84
|
+
return this.retractTags.length > 0;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
function fact(tag, payload) {
|
|
88
|
+
return { tag, payload };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/core/engine.ts
|
|
92
|
+
function safeClone(value) {
|
|
93
|
+
if (value === null || typeof value !== "object") {
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
if (typeof globalThis.structuredClone === "function") {
|
|
97
|
+
try {
|
|
98
|
+
return globalThis.structuredClone(value);
|
|
99
|
+
} catch {
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (Array.isArray(value)) {
|
|
103
|
+
return [...value];
|
|
104
|
+
}
|
|
105
|
+
return { ...value };
|
|
106
|
+
}
|
|
107
|
+
var LogicEngine = class {
|
|
108
|
+
state;
|
|
109
|
+
registry;
|
|
110
|
+
factDedup;
|
|
111
|
+
maxFacts;
|
|
112
|
+
constructor(options) {
|
|
113
|
+
this.registry = options.registry;
|
|
114
|
+
this.factDedup = options.factDedup ?? "last-write-wins";
|
|
115
|
+
this.maxFacts = options.maxFacts ?? 1e3;
|
|
116
|
+
this.state = {
|
|
117
|
+
context: options.initialContext,
|
|
118
|
+
facts: options.initialFacts ?? [],
|
|
119
|
+
meta: options.initialMeta ?? {},
|
|
120
|
+
protocolVersion: PRAXIS_PROTOCOL_VERSION
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Get the current state (immutable copy)
|
|
125
|
+
*/
|
|
126
|
+
getState() {
|
|
127
|
+
return {
|
|
128
|
+
context: safeClone(this.state.context),
|
|
129
|
+
facts: [...this.state.facts],
|
|
130
|
+
meta: this.state.meta ? safeClone(this.state.meta) : void 0,
|
|
131
|
+
protocolVersion: this.state.protocolVersion
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get the current context
|
|
136
|
+
*/
|
|
137
|
+
getContext() {
|
|
138
|
+
return safeClone(this.state.context);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Get current facts
|
|
142
|
+
*/
|
|
143
|
+
getFacts() {
|
|
144
|
+
return [...this.state.facts];
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Process events through the engine.
|
|
148
|
+
* Applies all registered rules and checks all registered constraints.
|
|
149
|
+
*
|
|
150
|
+
* @param events Events to process
|
|
151
|
+
* @returns Result with new state and diagnostics
|
|
152
|
+
*/
|
|
153
|
+
step(events) {
|
|
154
|
+
const config = {
|
|
155
|
+
ruleIds: this.registry.getRuleIds(),
|
|
156
|
+
constraintIds: this.registry.getConstraintIds()
|
|
157
|
+
};
|
|
158
|
+
return this.stepWithConfig(events, config);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Process events with specific rule and constraint configuration.
|
|
162
|
+
*
|
|
163
|
+
* @param events Events to process
|
|
164
|
+
* @param config Step configuration
|
|
165
|
+
* @returns Result with new state and diagnostics
|
|
166
|
+
*/
|
|
167
|
+
stepWithConfig(events, config) {
|
|
168
|
+
const diagnostics = [];
|
|
169
|
+
let newState = { ...this.state };
|
|
170
|
+
const stateWithEvents = {
|
|
171
|
+
...newState,
|
|
172
|
+
events
|
|
173
|
+
// current batch — rules can read state.events
|
|
174
|
+
};
|
|
175
|
+
const newFacts = [];
|
|
176
|
+
const retractions = [];
|
|
177
|
+
const eventTags = new Set(events.map((e) => e.tag));
|
|
178
|
+
for (const ruleId of config.ruleIds) {
|
|
179
|
+
const rule = this.registry.getRule(ruleId);
|
|
180
|
+
if (!rule) {
|
|
181
|
+
diagnostics.push({
|
|
182
|
+
kind: "rule-error",
|
|
183
|
+
message: `Rule "${ruleId}" not found in registry`,
|
|
184
|
+
data: { ruleId }
|
|
185
|
+
});
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (rule.eventTypes) {
|
|
189
|
+
const filterTags = Array.isArray(rule.eventTypes) ? rule.eventTypes : [rule.eventTypes];
|
|
190
|
+
if (!filterTags.some((t) => eventTags.has(t))) {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
try {
|
|
195
|
+
const rawResult = rule.impl(stateWithEvents, events);
|
|
196
|
+
if (rawResult instanceof RuleResult) {
|
|
197
|
+
rawResult.ruleId = ruleId;
|
|
198
|
+
switch (rawResult.kind) {
|
|
199
|
+
case "emit":
|
|
200
|
+
newFacts.push(...rawResult.facts);
|
|
201
|
+
break;
|
|
202
|
+
case "retract":
|
|
203
|
+
retractions.push(...rawResult.retractTags);
|
|
204
|
+
break;
|
|
205
|
+
case "noop":
|
|
206
|
+
case "skip":
|
|
207
|
+
if (rawResult.reason) {
|
|
208
|
+
diagnostics.push({
|
|
209
|
+
kind: "rule-error",
|
|
210
|
+
// reused kind — could add 'rule-trace' in protocol v2
|
|
211
|
+
message: `[${rawResult.kind}] ${ruleId}: ${rawResult.reason}`,
|
|
212
|
+
data: { ruleId, resultKind: rawResult.kind, reason: rawResult.reason }
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
} else if (Array.isArray(rawResult)) {
|
|
218
|
+
newFacts.push(...rawResult);
|
|
219
|
+
}
|
|
220
|
+
} catch (error) {
|
|
221
|
+
diagnostics.push({
|
|
222
|
+
kind: "rule-error",
|
|
223
|
+
message: `Error executing rule "${ruleId}": ${error instanceof Error ? error.message : String(error)}`,
|
|
224
|
+
data: { ruleId, error }
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
let existingFacts = newState.facts;
|
|
229
|
+
if (retractions.length > 0) {
|
|
230
|
+
const retractSet = new Set(retractions);
|
|
231
|
+
existingFacts = existingFacts.filter((f) => !retractSet.has(f.tag));
|
|
232
|
+
}
|
|
233
|
+
let mergedFacts;
|
|
234
|
+
switch (this.factDedup) {
|
|
235
|
+
case "last-write-wins": {
|
|
236
|
+
const factMap = /* @__PURE__ */ new Map();
|
|
237
|
+
for (const f of existingFacts) factMap.set(f.tag, f);
|
|
238
|
+
for (const f of newFacts) factMap.set(f.tag, f);
|
|
239
|
+
mergedFacts = Array.from(factMap.values());
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
case "append":
|
|
243
|
+
mergedFacts = [...existingFacts, ...newFacts];
|
|
244
|
+
break;
|
|
245
|
+
case "none":
|
|
246
|
+
default:
|
|
247
|
+
mergedFacts = [...existingFacts, ...newFacts];
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
if (this.maxFacts > 0 && mergedFacts.length > this.maxFacts) {
|
|
251
|
+
mergedFacts = mergedFacts.slice(mergedFacts.length - this.maxFacts);
|
|
252
|
+
}
|
|
253
|
+
newState = {
|
|
254
|
+
...newState,
|
|
255
|
+
facts: mergedFacts
|
|
256
|
+
};
|
|
257
|
+
for (const constraintId of config.constraintIds) {
|
|
258
|
+
const constraint = this.registry.getConstraint(constraintId);
|
|
259
|
+
if (!constraint) {
|
|
260
|
+
diagnostics.push({
|
|
261
|
+
kind: "constraint-violation",
|
|
262
|
+
message: `Constraint "${constraintId}" not found in registry`,
|
|
263
|
+
data: { constraintId }
|
|
264
|
+
});
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
try {
|
|
268
|
+
const result = constraint.impl(newState);
|
|
269
|
+
if (result === false) {
|
|
270
|
+
diagnostics.push({
|
|
271
|
+
kind: "constraint-violation",
|
|
272
|
+
message: `Constraint "${constraintId}" violated`,
|
|
273
|
+
data: { constraintId, description: constraint.description }
|
|
274
|
+
});
|
|
275
|
+
} else if (typeof result === "string") {
|
|
276
|
+
diagnostics.push({
|
|
277
|
+
kind: "constraint-violation",
|
|
278
|
+
message: result,
|
|
279
|
+
data: { constraintId, description: constraint.description }
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
} catch (error) {
|
|
283
|
+
diagnostics.push({
|
|
284
|
+
kind: "constraint-violation",
|
|
285
|
+
message: `Error checking constraint "${constraintId}": ${error instanceof Error ? error.message : String(error)}`,
|
|
286
|
+
data: { constraintId, error }
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
this.state = newState;
|
|
291
|
+
return {
|
|
292
|
+
state: newState,
|
|
293
|
+
diagnostics
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Update the context directly (for exceptional cases).
|
|
298
|
+
* Generally, context should be updated through rules.
|
|
299
|
+
*
|
|
300
|
+
* @param updater Function that produces new context from old context
|
|
301
|
+
*/
|
|
302
|
+
updateContext(updater) {
|
|
303
|
+
this.state = {
|
|
304
|
+
...this.state,
|
|
305
|
+
context: updater(this.state.context)
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Atomically update context AND process events in a single call.
|
|
310
|
+
*
|
|
311
|
+
* This avoids the fragile pattern of calling updateContext() then step()
|
|
312
|
+
* separately, where rules could see stale context if the ordering is wrong.
|
|
313
|
+
*
|
|
314
|
+
* @param updater Function that produces new context from old context
|
|
315
|
+
* @param events Events to process after context is updated
|
|
316
|
+
* @returns Result with new state and diagnostics
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* engine.stepWithContext(
|
|
320
|
+
* ctx => ({ ...ctx, sprintName: sprint.name, items: sprint.items }),
|
|
321
|
+
* [{ tag: 'sprint.update', payload: { name: sprint.name } }]
|
|
322
|
+
* );
|
|
323
|
+
*/
|
|
324
|
+
stepWithContext(updater, events) {
|
|
325
|
+
this.state = {
|
|
326
|
+
...this.state,
|
|
327
|
+
context: updater(this.state.context)
|
|
328
|
+
};
|
|
329
|
+
return this.step(events);
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Add facts directly (for exceptional cases).
|
|
333
|
+
* Generally, facts should be added through rules.
|
|
334
|
+
*
|
|
335
|
+
* @param facts Facts to add
|
|
336
|
+
*/
|
|
337
|
+
addFacts(facts) {
|
|
338
|
+
this.state = {
|
|
339
|
+
...this.state,
|
|
340
|
+
facts: [...this.state.facts, ...facts]
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Check all constraints without processing any events.
|
|
345
|
+
*
|
|
346
|
+
* Useful for validation-only scenarios (e.g., form validation,
|
|
347
|
+
* pre-save checks) where you want constraint diagnostics without
|
|
348
|
+
* triggering any rules.
|
|
349
|
+
*
|
|
350
|
+
* @returns Array of constraint violation diagnostics (empty = all passing)
|
|
351
|
+
*/
|
|
352
|
+
checkConstraints() {
|
|
353
|
+
return this.stepWithConfig([], {
|
|
354
|
+
ruleIds: [],
|
|
355
|
+
constraintIds: this.registry.getConstraintIds()
|
|
356
|
+
}).diagnostics;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Clear all facts
|
|
360
|
+
*/
|
|
361
|
+
clearFacts() {
|
|
362
|
+
this.state = {
|
|
363
|
+
...this.state,
|
|
364
|
+
facts: []
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Reset the engine to initial state
|
|
369
|
+
*/
|
|
370
|
+
reset(options) {
|
|
371
|
+
this.state = {
|
|
372
|
+
context: options.initialContext,
|
|
373
|
+
facts: options.initialFacts ?? [],
|
|
374
|
+
meta: options.initialMeta ?? {},
|
|
375
|
+
protocolVersion: PRAXIS_PROTOCOL_VERSION
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
function createPraxisEngine(options) {
|
|
380
|
+
return new LogicEngine(options);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export {
|
|
384
|
+
PRAXIS_PROTOCOL_VERSION,
|
|
385
|
+
RuleResult,
|
|
386
|
+
fact,
|
|
387
|
+
LogicEngine,
|
|
388
|
+
createPraxisEngine
|
|
389
|
+
};
|