@plures/praxis 1.2.12 → 1.2.41
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 +63 -0
- package/dist/browser/{chunk-VOMLVI6V.js → chunk-BBP2F7TT.js} +70 -1
- package/dist/browser/{chunk-K377RW4V.js → chunk-FCEH7WMH.js} +1 -1
- package/dist/browser/{engine-YJZV4SLD.js → engine-65QDGCAN.js} +1 -1
- package/dist/browser/index.d.ts +104 -2
- package/dist/browser/index.js +181 -5
- 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-Cqd8Mod2.d.ts} +56 -1
- package/dist/node/{chunk-PRPQO6R5.js → chunk-32YFEEML.js} +1 -1
- package/dist/node/{chunk-VOMLVI6V.js → chunk-BBP2F7TT.js} +70 -1
- 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-7CXQV6RC.js} +1 -1
- package/dist/node/index.cjs +408 -3
- package/dist/node/index.d.cts +308 -7
- package/dist/node/index.d.ts +308 -7
- package/dist/node/index.js +336 -6
- package/dist/node/integrations/svelte.cjs +70 -1
- 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-BocKczNv.d.cts} +1 -1
- package/dist/node/{protocol-Qek7ebBl.d.cts → protocol-BocKczNv.d.ts} +1 -1
- package/dist/node/{reactive-engine.svelte-CRNqHlbv.d.ts → reactive-engine.svelte-CGe8SpVE.d.cts} +57 -2
- package/dist/node/{reactive-engine.svelte-BFIZfawz.d.cts → reactive-engine.svelte-D-xTDxT5.d.ts} +57 -2
- 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 +7 -2
- 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/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/engine.ts +99 -1
- package/src/core/pluresdb/index.ts +22 -0
- package/src/core/pluresdb/store.ts +162 -5
- package/src/core/rules.ts +12 -0
- package/src/dsl/index.ts +6 -0
- package/src/index.ts +18 -0
- package/src/integrations/pluresdb.ts +22 -0
package/dist/browser/{reactive-engine.svelte-9aS0kTa8.d.ts → reactive-engine.svelte-Cqd8Mod2.d.ts}
RENAMED
|
@@ -265,6 +265,18 @@ interface RuleDescriptor<TContext = unknown> {
|
|
|
265
265
|
description: string;
|
|
266
266
|
/** Implementation function */
|
|
267
267
|
impl: RuleFn<TContext>;
|
|
268
|
+
/**
|
|
269
|
+
* Optional event type filter — only evaluate this rule when at least one
|
|
270
|
+
* event in the batch has a matching `tag`. When omitted, the rule runs on
|
|
271
|
+
* every step (catch-all).
|
|
272
|
+
*
|
|
273
|
+
* Accepts a single tag string or an array of tags.
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* { id: 'sprint-behind', eventTypes: ['sprint.update'], impl: ... }
|
|
277
|
+
* { id: 'note-check', eventTypes: 'note.update', impl: ... }
|
|
278
|
+
*/
|
|
279
|
+
eventTypes?: string | string[];
|
|
268
280
|
/** Optional contract for rule behavior */
|
|
269
281
|
contract?: Contract;
|
|
270
282
|
/** Optional metadata */
|
|
@@ -393,6 +405,20 @@ interface PraxisEngineOptions<TContext = unknown> {
|
|
|
393
405
|
initialFacts?: PraxisFact[];
|
|
394
406
|
/** Initial metadata (optional) */
|
|
395
407
|
initialMeta?: Record<string, unknown>;
|
|
408
|
+
/**
|
|
409
|
+
* Fact deduplication strategy (default: 'last-write-wins').
|
|
410
|
+
*
|
|
411
|
+
* - 'none': facts accumulate without dedup (original behavior)
|
|
412
|
+
* - 'last-write-wins': only keep the latest fact per tag (most common)
|
|
413
|
+
* - 'append': keep all facts but cap at maxFacts
|
|
414
|
+
*/
|
|
415
|
+
factDedup?: 'none' | 'last-write-wins' | 'append';
|
|
416
|
+
/**
|
|
417
|
+
* Maximum number of facts to retain (default: 1000).
|
|
418
|
+
* When exceeded, oldest facts are evicted (FIFO).
|
|
419
|
+
* Set to 0 for unlimited (not recommended).
|
|
420
|
+
*/
|
|
421
|
+
maxFacts?: number;
|
|
396
422
|
}
|
|
397
423
|
/**
|
|
398
424
|
* The Praxis Logic Engine
|
|
@@ -403,6 +429,8 @@ interface PraxisEngineOptions<TContext = unknown> {
|
|
|
403
429
|
declare class LogicEngine<TContext = unknown> {
|
|
404
430
|
private state;
|
|
405
431
|
private readonly registry;
|
|
432
|
+
private readonly factDedup;
|
|
433
|
+
private readonly maxFacts;
|
|
406
434
|
constructor(options: PraxisEngineOptions<TContext>);
|
|
407
435
|
/**
|
|
408
436
|
* Get the current state (immutable copy)
|
|
@@ -441,6 +469,23 @@ declare class LogicEngine<TContext = unknown> {
|
|
|
441
469
|
* @param updater Function that produces new context from old context
|
|
442
470
|
*/
|
|
443
471
|
updateContext(updater: (context: TContext) => TContext): void;
|
|
472
|
+
/**
|
|
473
|
+
* Atomically update context AND process events in a single call.
|
|
474
|
+
*
|
|
475
|
+
* This avoids the fragile pattern of calling updateContext() then step()
|
|
476
|
+
* separately, where rules could see stale context if the ordering is wrong.
|
|
477
|
+
*
|
|
478
|
+
* @param updater Function that produces new context from old context
|
|
479
|
+
* @param events Events to process after context is updated
|
|
480
|
+
* @returns Result with new state and diagnostics
|
|
481
|
+
*
|
|
482
|
+
* @example
|
|
483
|
+
* engine.stepWithContext(
|
|
484
|
+
* ctx => ({ ...ctx, sprintName: sprint.name, items: sprint.items }),
|
|
485
|
+
* [{ tag: 'sprint.update', payload: { name: sprint.name } }]
|
|
486
|
+
* );
|
|
487
|
+
*/
|
|
488
|
+
stepWithContext(updater: (context: TContext) => TContext, events: PraxisEvent[]): PraxisStepResult;
|
|
444
489
|
/**
|
|
445
490
|
* Add facts directly (for exceptional cases).
|
|
446
491
|
* Generally, facts should be added through rules.
|
|
@@ -448,6 +493,16 @@ declare class LogicEngine<TContext = unknown> {
|
|
|
448
493
|
* @param facts Facts to add
|
|
449
494
|
*/
|
|
450
495
|
addFacts(facts: PraxisFact[]): void;
|
|
496
|
+
/**
|
|
497
|
+
* Check all constraints without processing any events.
|
|
498
|
+
*
|
|
499
|
+
* Useful for validation-only scenarios (e.g., form validation,
|
|
500
|
+
* pre-save checks) where you want constraint diagnostics without
|
|
501
|
+
* triggering any rules.
|
|
502
|
+
*
|
|
503
|
+
* @returns Array of constraint violation diagnostics (empty = all passing)
|
|
504
|
+
*/
|
|
505
|
+
checkConstraints(): PraxisDiagnostics[];
|
|
451
506
|
/**
|
|
452
507
|
* Clear all facts
|
|
453
508
|
*/
|
|
@@ -551,4 +606,4 @@ declare class ReactiveLogicEngine<TContext extends object> {
|
|
|
551
606
|
*/
|
|
552
607
|
declare function createReactiveEngine<TContext extends object>(options: ReactiveEngineOptions<TContext>): ReactiveLogicEngine<TContext>;
|
|
553
608
|
|
|
554
|
-
export { type ConstraintDescriptor as C, LogicEngine as L, type PraxisState as P, type RuleDescriptor as R, type PraxisEvent as a, PraxisRegistry as b, type
|
|
609
|
+
export { type ConstraintDescriptor as C, LogicEngine as L, type PraxisState as P, type RuleDescriptor as R, type PraxisEvent as a, PraxisRegistry as b, type ConstraintFn as c, type Contract as d, type RuleFn as e, type PraxisFact as f, type PraxisModule as g, type ConstraintId as h, PRAXIS_PROTOCOL_VERSION as i, type PraxisDiagnostics as j, type PraxisEngineOptions as k, type PraxisStepConfig as l, type PraxisStepFn as m, type PraxisStepResult as n, type ReactiveEngineOptions as o, ReactiveLogicEngine as p, type RuleId as q, createPraxisEngine as r, createReactiveEngine as s };
|
|
@@ -20,8 +20,12 @@ function safeClone(value) {
|
|
|
20
20
|
var LogicEngine = class {
|
|
21
21
|
state;
|
|
22
22
|
registry;
|
|
23
|
+
factDedup;
|
|
24
|
+
maxFacts;
|
|
23
25
|
constructor(options) {
|
|
24
26
|
this.registry = options.registry;
|
|
27
|
+
this.factDedup = options.factDedup ?? "last-write-wins";
|
|
28
|
+
this.maxFacts = options.maxFacts ?? 1e3;
|
|
25
29
|
this.state = {
|
|
26
30
|
context: options.initialContext,
|
|
27
31
|
facts: options.initialFacts ?? [],
|
|
@@ -77,6 +81,7 @@ var LogicEngine = class {
|
|
|
77
81
|
const diagnostics = [];
|
|
78
82
|
let newState = { ...this.state };
|
|
79
83
|
const newFacts = [];
|
|
84
|
+
const eventTags = new Set(events.map((e) => e.tag));
|
|
80
85
|
for (const ruleId of config.ruleIds) {
|
|
81
86
|
const rule = this.registry.getRule(ruleId);
|
|
82
87
|
if (!rule) {
|
|
@@ -87,6 +92,12 @@ var LogicEngine = class {
|
|
|
87
92
|
});
|
|
88
93
|
continue;
|
|
89
94
|
}
|
|
95
|
+
if (rule.eventTypes) {
|
|
96
|
+
const filterTags = Array.isArray(rule.eventTypes) ? rule.eventTypes : [rule.eventTypes];
|
|
97
|
+
if (!filterTags.some((t) => eventTags.has(t))) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
90
101
|
try {
|
|
91
102
|
const ruleFacts = rule.impl(newState, events);
|
|
92
103
|
newFacts.push(...ruleFacts);
|
|
@@ -98,9 +109,29 @@ var LogicEngine = class {
|
|
|
98
109
|
});
|
|
99
110
|
}
|
|
100
111
|
}
|
|
112
|
+
let mergedFacts;
|
|
113
|
+
switch (this.factDedup) {
|
|
114
|
+
case "last-write-wins": {
|
|
115
|
+
const factMap = /* @__PURE__ */ new Map();
|
|
116
|
+
for (const f of newState.facts) factMap.set(f.tag, f);
|
|
117
|
+
for (const f of newFacts) factMap.set(f.tag, f);
|
|
118
|
+
mergedFacts = Array.from(factMap.values());
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
case "append":
|
|
122
|
+
mergedFacts = [...newState.facts, ...newFacts];
|
|
123
|
+
break;
|
|
124
|
+
case "none":
|
|
125
|
+
default:
|
|
126
|
+
mergedFacts = [...newState.facts, ...newFacts];
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
if (this.maxFacts > 0 && mergedFacts.length > this.maxFacts) {
|
|
130
|
+
mergedFacts = mergedFacts.slice(mergedFacts.length - this.maxFacts);
|
|
131
|
+
}
|
|
101
132
|
newState = {
|
|
102
133
|
...newState,
|
|
103
|
-
facts:
|
|
134
|
+
facts: mergedFacts
|
|
104
135
|
};
|
|
105
136
|
for (const constraintId of config.constraintIds) {
|
|
106
137
|
const constraint = this.registry.getConstraint(constraintId);
|
|
@@ -153,6 +184,29 @@ var LogicEngine = class {
|
|
|
153
184
|
context: updater(this.state.context)
|
|
154
185
|
};
|
|
155
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Atomically update context AND process events in a single call.
|
|
189
|
+
*
|
|
190
|
+
* This avoids the fragile pattern of calling updateContext() then step()
|
|
191
|
+
* separately, where rules could see stale context if the ordering is wrong.
|
|
192
|
+
*
|
|
193
|
+
* @param updater Function that produces new context from old context
|
|
194
|
+
* @param events Events to process after context is updated
|
|
195
|
+
* @returns Result with new state and diagnostics
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* engine.stepWithContext(
|
|
199
|
+
* ctx => ({ ...ctx, sprintName: sprint.name, items: sprint.items }),
|
|
200
|
+
* [{ tag: 'sprint.update', payload: { name: sprint.name } }]
|
|
201
|
+
* );
|
|
202
|
+
*/
|
|
203
|
+
stepWithContext(updater, events) {
|
|
204
|
+
this.state = {
|
|
205
|
+
...this.state,
|
|
206
|
+
context: updater(this.state.context)
|
|
207
|
+
};
|
|
208
|
+
return this.step(events);
|
|
209
|
+
}
|
|
156
210
|
/**
|
|
157
211
|
* Add facts directly (for exceptional cases).
|
|
158
212
|
* Generally, facts should be added through rules.
|
|
@@ -165,6 +219,21 @@ var LogicEngine = class {
|
|
|
165
219
|
facts: [...this.state.facts, ...facts]
|
|
166
220
|
};
|
|
167
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Check all constraints without processing any events.
|
|
224
|
+
*
|
|
225
|
+
* Useful for validation-only scenarios (e.g., form validation,
|
|
226
|
+
* pre-save checks) where you want constraint diagnostics without
|
|
227
|
+
* triggering any rules.
|
|
228
|
+
*
|
|
229
|
+
* @returns Array of constraint violation diagnostics (empty = all passing)
|
|
230
|
+
*/
|
|
231
|
+
checkConstraints() {
|
|
232
|
+
return this.stepWithConfig([], {
|
|
233
|
+
ruleIds: [],
|
|
234
|
+
constraintIds: this.registry.getConstraintIds()
|
|
235
|
+
}).diagnostics;
|
|
236
|
+
}
|
|
168
237
|
/**
|
|
169
238
|
* Clear all facts
|
|
170
239
|
*/
|