@plures/praxis 1.4.4 → 2.0.3

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.
Files changed (59) hide show
  1. package/README.md +164 -1067
  2. package/dist/browser/chunk-IUEKGHQN.js +373 -0
  3. package/dist/browser/factory/index.d.ts +2 -1
  4. package/dist/browser/index.d.ts +7 -4
  5. package/dist/browser/index.js +18 -6
  6. package/dist/browser/integrations/svelte.d.ts +4 -3
  7. package/dist/browser/project/index.d.ts +2 -1
  8. package/dist/browser/{reactive-engine.svelte-DgVTqHLc.d.ts → reactive-engine.svelte-BwWadvAW.d.ts} +2 -1
  9. package/dist/browser/rule-result-DcXWe9tn.d.ts +206 -0
  10. package/dist/browser/{rules-i1LHpnGd.d.ts → rules-BaWMqxuG.d.ts} +2 -205
  11. package/dist/browser/unified/index.d.ts +239 -0
  12. package/dist/browser/unified/index.js +20 -0
  13. package/dist/node/chunk-IUEKGHQN.js +373 -0
  14. package/dist/node/cli/index.js +1 -1
  15. package/dist/node/index.cjs +377 -0
  16. package/dist/node/index.d.cts +4 -2
  17. package/dist/node/index.d.ts +4 -2
  18. package/dist/node/index.js +19 -7
  19. package/dist/node/integrations/svelte.d.cts +3 -2
  20. package/dist/node/integrations/svelte.d.ts +3 -2
  21. package/dist/node/integrations/svelte.js +2 -2
  22. package/dist/node/{reactive-engine.svelte-DekxqFu0.d.ts → reactive-engine.svelte-BBZLMzus.d.ts} +3 -79
  23. package/dist/node/{reactive-engine.svelte-Cg0Yc2Hs.d.cts → reactive-engine.svelte-Cbq_V20o.d.cts} +3 -79
  24. package/dist/node/rule-result-B9GMivAn.d.cts +80 -0
  25. package/dist/node/rule-result-Bo3sFMmN.d.ts +80 -0
  26. package/dist/node/unified/index.cjs +494 -0
  27. package/dist/node/unified/index.d.cts +240 -0
  28. package/dist/node/unified/index.d.ts +240 -0
  29. package/dist/node/unified/index.js +21 -0
  30. package/docs/README.md +58 -102
  31. package/docs/archive/1.x/CONVERSATIONS_IMPLEMENTATION.md +207 -0
  32. package/docs/archive/1.x/DECISION_LEDGER_IMPLEMENTATION.md +109 -0
  33. package/docs/archive/1.x/DECISION_LEDGER_SUMMARY.md +424 -0
  34. package/docs/archive/1.x/ELEVATION_SUMMARY.md +249 -0
  35. package/docs/archive/1.x/FEATURE_SUMMARY.md +238 -0
  36. package/docs/archive/1.x/GOLDEN_PATH_IMPLEMENTATION.md +280 -0
  37. package/docs/archive/1.x/IMPLEMENTATION.md +166 -0
  38. package/docs/archive/1.x/IMPLEMENTATION_COMPLETE.md +389 -0
  39. package/docs/archive/1.x/IMPLEMENTATION_SUMMARY.md +59 -0
  40. package/docs/archive/1.x/INTEGRATION_ENHANCEMENT_SUMMARY.md +238 -0
  41. package/docs/archive/1.x/KNO_ENG_REFACTORING_SUMMARY.md +198 -0
  42. package/docs/archive/1.x/MONOREPO_SUMMARY.md +158 -0
  43. package/docs/archive/1.x/README.md +28 -0
  44. package/docs/archive/1.x/SVELTE_INTEGRATION_SUMMARY.md +415 -0
  45. package/docs/archive/1.x/TASK_1_COMPLETE.md +235 -0
  46. package/docs/archive/1.x/TASK_1_SUMMARY.md +281 -0
  47. package/docs/archive/1.x/VERSION_0.2.0_RELEASE_NOTES.md +288 -0
  48. package/docs/archive/1.x/ValidationChecklist.md +7 -0
  49. package/package.json +13 -1
  50. package/src/index.browser.ts +20 -0
  51. package/src/index.ts +21 -0
  52. package/src/unified/__tests__/unified-qa.test.ts +761 -0
  53. package/src/unified/__tests__/unified.test.ts +396 -0
  54. package/src/unified/core.ts +534 -0
  55. package/src/unified/index.ts +32 -0
  56. package/src/unified/rules.ts +66 -0
  57. package/src/unified/types.ts +148 -0
  58. package/dist/node/{chunk-ZO2LU4G4.js → chunk-WFRHXZBP.js} +3 -3
  59. package/dist/node/{validate-5PSWJTIC.js → validate-BY7JNY7H.js} +1 -1
@@ -0,0 +1,373 @@
1
+ // src/unified/core.ts
2
+ var _idCounter = 0;
3
+ function nextId() {
4
+ return `px:${Date.now()}-${++_idCounter}`;
5
+ }
6
+ function createApp(config) {
7
+ const paths = /* @__PURE__ */ new Map();
8
+ for (const schema of config.schema) {
9
+ paths.set(schema.path, {
10
+ schema,
11
+ value: schema.initial,
12
+ subscribers: /* @__PURE__ */ new Set(),
13
+ lastUpdated: 0,
14
+ updateCount: 0
15
+ });
16
+ }
17
+ let facts = [];
18
+ const factMap = /* @__PURE__ */ new Map();
19
+ const timeline = [];
20
+ const maxTimeline = 1e4;
21
+ function recordTimeline(path, kind, data) {
22
+ const entry = {
23
+ id: nextId(),
24
+ timestamp: Date.now(),
25
+ path,
26
+ kind,
27
+ data
28
+ };
29
+ timeline.push(entry);
30
+ if (timeline.length > maxTimeline) {
31
+ timeline.splice(0, timeline.length - maxTimeline);
32
+ }
33
+ }
34
+ const ruleStates = (config.rules ?? []).map((rule) => ({
35
+ rule,
36
+ lastResult: null,
37
+ emittedTags: /* @__PURE__ */ new Set()
38
+ }));
39
+ const constraints = config.constraints ?? [];
40
+ const livenessConfig = config.liveness;
41
+ const initTime = Date.now();
42
+ let livenessTimer = null;
43
+ if (livenessConfig) {
44
+ const timeout = livenessConfig.timeoutMs ?? 5e3;
45
+ livenessTimer = setTimeout(() => {
46
+ for (const expectedPath of livenessConfig.expect) {
47
+ const state = paths.get(expectedPath);
48
+ if (!state || state.updateCount === 0) {
49
+ const elapsed = Date.now() - initTime;
50
+ recordTimeline(expectedPath, "liveness", {
51
+ stale: true,
52
+ elapsed,
53
+ message: `Path "${expectedPath}" never updated after ${elapsed}ms`
54
+ });
55
+ livenessConfig.onStale?.(expectedPath, elapsed);
56
+ }
57
+ }
58
+ }, timeout);
59
+ }
60
+ function getPathValues(watchPaths) {
61
+ const values = {};
62
+ for (const p of watchPaths) {
63
+ const state = paths.get(p);
64
+ values[p] = state ? state.value : void 0;
65
+ }
66
+ return values;
67
+ }
68
+ function notify(path, value) {
69
+ const state = paths.get(path);
70
+ if (!state) return;
71
+ for (const cb of state.subscribers) {
72
+ try {
73
+ cb(value);
74
+ } catch (err) {
75
+ console.error(`[praxis] Subscriber error for "${path}":`, err);
76
+ }
77
+ }
78
+ }
79
+ function checkConstraints(path, value) {
80
+ const violations = [];
81
+ for (const c of constraints) {
82
+ if (!c.watch.includes(path)) continue;
83
+ const values = getPathValues(c.watch);
84
+ values[path] = value;
85
+ try {
86
+ const result = c.validate(values);
87
+ if (result !== true) {
88
+ violations.push({
89
+ kind: "constraint-violation",
90
+ message: result,
91
+ data: { constraintId: c.id, path, description: c.description }
92
+ });
93
+ recordTimeline(path, "constraint-check", {
94
+ constraintId: c.id,
95
+ violated: true,
96
+ message: result
97
+ });
98
+ }
99
+ } catch (err) {
100
+ violations.push({
101
+ kind: "constraint-violation",
102
+ message: `Constraint "${c.id}" threw: ${err instanceof Error ? err.message : String(err)}`,
103
+ data: { constraintId: c.id, error: err }
104
+ });
105
+ }
106
+ }
107
+ return violations;
108
+ }
109
+ function evaluateRules() {
110
+ const newFacts = [];
111
+ const retractions = [];
112
+ for (const rs of ruleStates) {
113
+ const values = getPathValues(rs.rule.watch);
114
+ try {
115
+ const result = rs.rule.evaluate(values, [...facts]);
116
+ rs.lastResult = result;
117
+ recordTimeline(rs.rule.watch[0] ?? "*", "rule-eval", {
118
+ ruleId: rs.rule.id,
119
+ kind: result.kind,
120
+ reason: result.reason
121
+ });
122
+ switch (result.kind) {
123
+ case "emit":
124
+ newFacts.push(...result.facts);
125
+ for (const f of result.facts) {
126
+ rs.emittedTags.add(f.tag);
127
+ }
128
+ break;
129
+ case "retract":
130
+ retractions.push(...result.retractTags);
131
+ for (const tag of result.retractTags) {
132
+ rs.emittedTags.delete(tag);
133
+ }
134
+ break;
135
+ case "noop":
136
+ case "skip":
137
+ if (rs.emittedTags.size > 0) {
138
+ retractions.push(...rs.emittedTags);
139
+ rs.emittedTags.clear();
140
+ }
141
+ break;
142
+ }
143
+ } catch (err) {
144
+ console.error(`[praxis] Rule "${rs.rule.id}" error:`, err);
145
+ }
146
+ }
147
+ if (retractions.length > 0) {
148
+ const retractSet = new Set(retractions);
149
+ for (const tag of retractSet) {
150
+ factMap.delete(tag);
151
+ }
152
+ }
153
+ for (const f of newFacts) {
154
+ factMap.set(f.tag, f);
155
+ }
156
+ facts = Array.from(factMap.values());
157
+ }
158
+ function query(path, opts) {
159
+ let state = paths.get(path);
160
+ if (!state) {
161
+ state = {
162
+ schema: { path, initial: void 0 },
163
+ value: void 0,
164
+ subscribers: /* @__PURE__ */ new Set(),
165
+ lastUpdated: 0,
166
+ updateCount: 0
167
+ };
168
+ paths.set(path, state);
169
+ }
170
+ const ref = {
171
+ get current() {
172
+ const s = paths.get(path);
173
+ return applyQueryOpts(s?.value ?? state.schema.initial, opts);
174
+ },
175
+ subscribe(cb) {
176
+ const wrappedCb = (rawValue) => {
177
+ const processed = applyQueryOpts(rawValue, opts);
178
+ cb(processed);
179
+ };
180
+ const s = paths.get(path);
181
+ s.subscribers.add(wrappedCb);
182
+ try {
183
+ cb(ref.current);
184
+ } catch (err) {
185
+ console.error(`[praxis] query("${path}") subscriber init error:`, err);
186
+ }
187
+ return () => {
188
+ s.subscribers.delete(wrappedCb);
189
+ };
190
+ }
191
+ };
192
+ return ref;
193
+ }
194
+ function applyQueryOpts(value, opts) {
195
+ if (!opts || !Array.isArray(value)) return value;
196
+ let result = [...value];
197
+ if (opts.where) result = result.filter(opts.where);
198
+ if (opts.sort) result.sort(opts.sort);
199
+ if (opts.select) result = result.map(opts.select);
200
+ if (opts.limit) result = result.slice(0, opts.limit);
201
+ return result;
202
+ }
203
+ function mutateInternal(path, value) {
204
+ const violations = checkConstraints(path, value);
205
+ if (violations.length > 0) {
206
+ return { violations, emittedFacts: [] };
207
+ }
208
+ const state = paths.get(path);
209
+ if (!state) {
210
+ paths.set(path, {
211
+ schema: { path, initial: value },
212
+ value,
213
+ subscribers: /* @__PURE__ */ new Set(),
214
+ lastUpdated: Date.now(),
215
+ updateCount: 1
216
+ });
217
+ } else {
218
+ const before = state.value;
219
+ state.value = value;
220
+ state.lastUpdated = Date.now();
221
+ state.updateCount++;
222
+ recordTimeline(path, "mutation", {
223
+ before: summarize(before),
224
+ after: summarize(value)
225
+ });
226
+ }
227
+ notify(path, value);
228
+ const factsBefore = facts.length;
229
+ evaluateRules();
230
+ const emittedFacts = facts.slice(factsBefore);
231
+ return { violations: [], emittedFacts };
232
+ }
233
+ function mutate(path, value) {
234
+ const { violations, emittedFacts } = mutateInternal(path, value);
235
+ return {
236
+ accepted: violations.length === 0,
237
+ violations,
238
+ facts: emittedFacts
239
+ };
240
+ }
241
+ function batchMutate(fn) {
242
+ const allViolations = [];
243
+ const pendingWrites = [];
244
+ fn((path, value) => {
245
+ const violations = checkConstraints(path, value);
246
+ if (violations.length > 0) {
247
+ allViolations.push(...violations);
248
+ } else {
249
+ pendingWrites.push({ path, value });
250
+ }
251
+ });
252
+ if (allViolations.length > 0) {
253
+ return { accepted: false, violations: allViolations, facts: [] };
254
+ }
255
+ for (const { path, value } of pendingWrites) {
256
+ const state = paths.get(path);
257
+ if (state) {
258
+ const before = state.value;
259
+ state.value = value;
260
+ state.lastUpdated = Date.now();
261
+ state.updateCount++;
262
+ recordTimeline(path, "mutation", {
263
+ before: summarize(before),
264
+ after: summarize(value)
265
+ });
266
+ } else {
267
+ paths.set(path, {
268
+ schema: { path, initial: value },
269
+ value,
270
+ subscribers: /* @__PURE__ */ new Set(),
271
+ lastUpdated: Date.now(),
272
+ updateCount: 1
273
+ });
274
+ }
275
+ }
276
+ for (const { path, value } of pendingWrites) {
277
+ notify(path, value);
278
+ }
279
+ const factsBefore = facts.length;
280
+ evaluateRules();
281
+ return {
282
+ accepted: true,
283
+ violations: [],
284
+ facts: facts.slice(factsBefore)
285
+ };
286
+ }
287
+ function getLiveness() {
288
+ const result = {};
289
+ const now = Date.now();
290
+ const watchPaths = livenessConfig?.expect ?? [];
291
+ for (const p of watchPaths) {
292
+ const state = paths.get(p);
293
+ const lastUpdated = state?.lastUpdated ?? 0;
294
+ const elapsed = lastUpdated > 0 ? now - lastUpdated : now - initTime;
295
+ result[p] = {
296
+ stale: !state || state.updateCount === 0,
297
+ lastUpdated,
298
+ elapsed
299
+ };
300
+ }
301
+ return result;
302
+ }
303
+ function destroy() {
304
+ if (livenessTimer) clearTimeout(livenessTimer);
305
+ for (const state of paths.values()) {
306
+ state.subscribers.clear();
307
+ }
308
+ paths.clear();
309
+ facts = [];
310
+ factMap.clear();
311
+ timeline.length = 0;
312
+ }
313
+ return {
314
+ query,
315
+ mutate,
316
+ batch: batchMutate,
317
+ facts: () => [...facts],
318
+ violations: () => {
319
+ const allViolations = [];
320
+ for (const c of constraints) {
321
+ const values = getPathValues(c.watch);
322
+ try {
323
+ const result = c.validate(values);
324
+ if (result !== true) {
325
+ allViolations.push({
326
+ kind: "constraint-violation",
327
+ message: result,
328
+ data: { constraintId: c.id }
329
+ });
330
+ }
331
+ } catch {
332
+ }
333
+ }
334
+ return allViolations;
335
+ },
336
+ timeline: () => [...timeline],
337
+ evaluate: evaluateRules,
338
+ destroy,
339
+ liveness: getLiveness
340
+ };
341
+ }
342
+ function summarize(value) {
343
+ if (value === null || value === void 0) return value;
344
+ if (typeof value !== "object") return value;
345
+ if (Array.isArray(value)) return `[Array(${value.length})]`;
346
+ const keys = Object.keys(value);
347
+ if (keys.length > 10) return `{Object(${keys.length} keys)}`;
348
+ return value;
349
+ }
350
+
351
+ // src/unified/types.ts
352
+ function definePath(path, initial, opts) {
353
+ return { path, initial, ...opts };
354
+ }
355
+
356
+ // src/unified/rules.ts
357
+ function defineRule(rule) {
358
+ return rule;
359
+ }
360
+ function defineConstraint(constraint) {
361
+ return constraint;
362
+ }
363
+ function defineModule(name, rules) {
364
+ return { name, rules };
365
+ }
366
+
367
+ export {
368
+ createApp,
369
+ definePath,
370
+ defineRule,
371
+ defineConstraint,
372
+ defineModule
373
+ };
@@ -1,4 +1,5 @@
1
- import { j as PraxisModule } from '../rules-i1LHpnGd.js';
1
+ import { d as PraxisModule } from '../rules-BaWMqxuG.js';
2
+ import '../rule-result-DcXWe9tn.js';
2
3
 
3
4
  /**
4
5
  * Praxis Rules Factory — Types
@@ -1,11 +1,14 @@
1
- import { P as PraxisState, a as PraxisEvent, b as PraxisRegistry, R as RuleDescriptor, C as ConstraintDescriptor, g as ConstraintFn, h as Contract, i as RuleFn, c as PraxisFact, j as PraxisModule } from './rules-i1LHpnGd.js';
2
- export { k as ConstraintId, l as PRAXIS_PROTOCOL_VERSION, f as PraxisDiagnostics, e as PraxisStepConfig, m as PraxisStepFn, d as PraxisStepResult, n as RuleId, o as RuleResult, T as TypedRuleFn, p as fact } from './rules-i1LHpnGd.js';
3
- import { L as LogicEngine } from './reactive-engine.svelte-DgVTqHLc.js';
4
- export { P as PraxisEngineOptions, R as ReactiveEngineOptions, a as ReactiveLogicEngine, b as createPraxisEngine, c as createReactiveEngine } from './reactive-engine.svelte-DgVTqHLc.js';
1
+ import { P as PraxisState, a as PraxisEvent, b as PraxisFact } from './rule-result-DcXWe9tn.js';
2
+ export { f as PRAXIS_PROTOCOL_VERSION, e as PraxisDiagnostics, d as PraxisStepConfig, g as PraxisStepFn, c as PraxisStepResult, R as RuleResult, T as TypedRuleFn, h as fact } from './rule-result-DcXWe9tn.js';
3
+ import { P as PraxisRegistry, R as RuleDescriptor, C as ConstraintDescriptor, a as ConstraintFn, b as Contract, c as RuleFn, d as PraxisModule } from './rules-BaWMqxuG.js';
4
+ export { e as ConstraintId, f as RuleId } from './rules-BaWMqxuG.js';
5
+ import { L as LogicEngine } from './reactive-engine.svelte-BwWadvAW.js';
6
+ export { P as PraxisEngineOptions, R as ReactiveEngineOptions, a as ReactiveLogicEngine, b as createPraxisEngine, c as createReactiveEngine } from './reactive-engine.svelte-BwWadvAW.js';
5
7
  import { LocalFirstOptions } from '@plures/pluresdb/local-first';
6
8
  export { ConditionResult, ConditionStatus, Expectation, ExpectationCondition, ExpectationResult, ExpectationSet, ExpectationSetOptions, VerifiableDescriptor, VerifiableRegistry, VerificationReport, expectBehavior, formatVerificationReport, verify } from './expectations/index.js';
7
9
  export { DataRulesConfig, FormRulesConfig, InputRulesConfig, NavigationRulesConfig, SanitizationType, ToastRulesConfig, dataRules, formRules, inputRules, navigationRules, toastRules } from './factory/index.js';
8
10
  export { BranchRulesConfig, GateConfig, GateState, GateStatus, PraxisDiff, PredefinedGateConfig, SemverContractConfig, SemverReport, branchRules, commitFromState, defineGate, expectationGate, formatGate, lintGate, semverContract } from './project/index.js';
11
+ export { LivenessConfig, MutationResult, PathSchema, PraxisApp, PraxisAppConfig, QueryOptions, ReactiveRef, UnifiedConstraint, UnifiedRule, createApp, definePath, defineConstraint as defineUnifiedConstraint, defineModule as defineUnifiedModule, defineRule as defineUnifiedRule } from './unified/index.js';
9
12
 
10
13
  /**
11
14
  * Praxis Reactive Logic Engine
@@ -26,6 +26,13 @@ import {
26
26
  lintGate,
27
27
  semverContract
28
28
  } from "./chunk-BQOYZBWA.js";
29
+ import {
30
+ createApp,
31
+ defineConstraint,
32
+ defineModule,
33
+ definePath,
34
+ defineRule
35
+ } from "./chunk-IUEKGHQN.js";
29
36
  import {
30
37
  LogicEngine,
31
38
  PRAXIS_PROTOCOL_VERSION,
@@ -606,7 +613,7 @@ function defineEvent(tag) {
606
613
  }
607
614
  };
608
615
  }
609
- function defineRule(options) {
616
+ function defineRule2(options) {
610
617
  const contract = options.contract ?? options.meta?.contract;
611
618
  const meta = contract ? { ...options.meta ?? {}, contract } : options.meta;
612
619
  return {
@@ -618,7 +625,7 @@ function defineRule(options) {
618
625
  meta
619
626
  };
620
627
  }
621
- function defineConstraint(options) {
628
+ function defineConstraint2(options) {
622
629
  const contract = options.contract ?? options.meta?.contract;
623
630
  const meta = contract ? { ...options.meta ?? {}, contract } : options.meta;
624
631
  return {
@@ -629,7 +636,7 @@ function defineConstraint(options) {
629
636
  meta
630
637
  };
631
638
  }
632
- function defineModule(options) {
639
+ function defineModule2(options) {
633
640
  return {
634
641
  rules: options.rules ?? [],
635
642
  constraints: options.constraints ?? [],
@@ -3370,6 +3377,7 @@ export {
3370
3377
  canvasToSchema,
3371
3378
  canvasToYaml,
3372
3379
  commitFromState,
3380
+ createApp,
3373
3381
  createCanvasEditor,
3374
3382
  createReactiveEngine2 as createFrameworkAgnosticReactiveEngine,
3375
3383
  createInMemoryDB,
@@ -3392,12 +3400,16 @@ export {
3392
3400
  createUnifiedApp,
3393
3401
  createUnumAdapter,
3394
3402
  dataRules,
3395
- defineConstraint,
3403
+ defineConstraint2 as defineConstraint,
3396
3404
  defineEvent,
3397
3405
  defineFact,
3398
3406
  defineGate,
3399
- defineModule,
3400
- defineRule,
3407
+ defineModule2 as defineModule,
3408
+ definePath,
3409
+ defineRule2 as defineRule,
3410
+ defineConstraint as defineUnifiedConstraint,
3411
+ defineModule as defineUnifiedModule,
3412
+ defineRule as defineUnifiedRule,
3401
3413
  dirtyGuardRule,
3402
3414
  errorDisplayRule,
3403
3415
  expectBehavior,
@@ -1,6 +1,7 @@
1
- import { L as LogicEngine } from '../reactive-engine.svelte-DgVTqHLc.js';
2
- export { R as ReactiveEngineOptions, a as ReactiveLogicEngine, c as createReactiveEngine } from '../reactive-engine.svelte-DgVTqHLc.js';
3
- import { P as PraxisState, a as PraxisEvent } from '../rules-i1LHpnGd.js';
1
+ import { L as LogicEngine } from '../reactive-engine.svelte-BwWadvAW.js';
2
+ export { R as ReactiveEngineOptions, a as ReactiveLogicEngine, c as createReactiveEngine } from '../reactive-engine.svelte-BwWadvAW.js';
3
+ import { P as PraxisState, a as PraxisEvent } from '../rule-result-DcXWe9tn.js';
4
+ import '../rules-BaWMqxuG.js';
4
5
 
5
6
  /**
6
7
  * Svelte v5 Integration
@@ -1,4 +1,5 @@
1
- import { j as PraxisModule } from '../rules-i1LHpnGd.js';
1
+ import { d as PraxisModule } from '../rules-BaWMqxuG.js';
2
+ import '../rule-result-DcXWe9tn.js';
2
3
 
3
4
  /**
4
5
  * Praxis Project Logic — Types
@@ -1,4 +1,5 @@
1
- import { b as PraxisRegistry, c as PraxisFact, P as PraxisState, a as PraxisEvent, d as PraxisStepResult, e as PraxisStepConfig, f as PraxisDiagnostics } from './rules-i1LHpnGd.js';
1
+ import { b as PraxisFact, P as PraxisState, a as PraxisEvent, c as PraxisStepResult, d as PraxisStepConfig, e as PraxisDiagnostics } from './rule-result-DcXWe9tn.js';
2
+ import { P as PraxisRegistry } from './rules-BaWMqxuG.js';
2
3
 
3
4
  /**
4
5
  * Praxis Logic Engine
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Core Praxis Protocol
3
+ *
4
+ * Language-neutral, JSON-friendly protocol that forms the foundation of Praxis.
5
+ * This protocol is designed to be stable and portable across languages (TypeScript, C#, PowerShell, etc.)
6
+ *
7
+ * The protocol defines the conceptual core of the engine:
8
+ * - Pure, deterministic, data in → data out
9
+ * - No side effects, no global state
10
+ * - All higher-level TypeScript APIs are built on top of this protocol
11
+ *
12
+ * ## Protocol Versioning
13
+ *
14
+ * The Praxis protocol follows semantic versioning (MAJOR.MINOR.PATCH):
15
+ * - MAJOR: Breaking changes to core protocol types or semantics
16
+ * - MINOR: Backward-compatible additions to protocol (new optional fields)
17
+ * - PATCH: Clarifications, documentation updates, no functional changes
18
+ *
19
+ * Current version: 1.0.0
20
+ *
21
+ * ### Stability Guarantees
22
+ *
23
+ * 1. **Core Types Stability**: The following types are considered stable and will not
24
+ * change in backward-incompatible ways within the same major version:
25
+ * - PraxisFact (tag, payload structure)
26
+ * - PraxisEvent (tag, payload structure)
27
+ * - PraxisState (context, facts, meta structure)
28
+ * - PraxisStepFn signature
29
+ *
30
+ * 2. **JSON Compatibility**: All protocol types will remain JSON-serializable.
31
+ * No non-JSON-safe types (functions, symbols, etc.) will be added to the protocol.
32
+ *
33
+ * 3. **Cross-Language Compatibility**: Protocol changes will be coordinated across
34
+ * all official language implementations (TypeScript, C#, PowerShell) to ensure
35
+ * interoperability.
36
+ *
37
+ * 4. **Migration Path**: Major version changes will be accompanied by:
38
+ * - Migration guide
39
+ * - Deprecation warnings in previous version
40
+ * - Compatibility shims where possible
41
+ */
42
+ /**
43
+ * Protocol version following semantic versioning
44
+ */
45
+ declare const PRAXIS_PROTOCOL_VERSION: "1.0.0";
46
+ /**
47
+ * A fact is a typed proposition about the domain.
48
+ * Examples: UserLoggedIn, CartItem, NetworkOnline
49
+ */
50
+ interface PraxisFact {
51
+ /** Tag identifying the fact type */
52
+ tag: string;
53
+ /** Payload containing the fact data */
54
+ payload: unknown;
55
+ }
56
+ /**
57
+ * An event is a temporally ordered fact meant to drive change.
58
+ * Examples: LOGIN, LOGOUT, ADD_TO_CART
59
+ */
60
+ interface PraxisEvent {
61
+ /** Tag identifying the event type */
62
+ tag: string;
63
+ /** Payload containing the event data */
64
+ payload: unknown;
65
+ }
66
+ /**
67
+ * The state of the Praxis engine at a point in time.
68
+ */
69
+ interface PraxisState {
70
+ /** Application context (domain-specific data) */
71
+ context: unknown;
72
+ /** Current facts about the domain */
73
+ facts: PraxisFact[];
74
+ /**
75
+ * Events currently being processed in this step.
76
+ * Available to rules during execution — guaranteed to contain the exact
77
+ * events passed to step()/stepWithContext().
78
+ * Empty outside of step execution.
79
+ */
80
+ events?: PraxisEvent[];
81
+ /** Optional metadata (timestamps, version, etc.) */
82
+ meta?: Record<string, unknown>;
83
+ /** Protocol version (for cross-language compatibility) */
84
+ protocolVersion?: string;
85
+ }
86
+ /**
87
+ * Diagnostic information about constraint violations or rule errors.
88
+ */
89
+ interface PraxisDiagnostics {
90
+ /** Kind of diagnostic */
91
+ kind: 'constraint-violation' | 'rule-error';
92
+ /** Human-readable message */
93
+ message: string;
94
+ /** Additional diagnostic data */
95
+ data?: unknown;
96
+ }
97
+ /**
98
+ * Configuration for a step execution.
99
+ * Specifies which rules and constraints to apply.
100
+ */
101
+ interface PraxisStepConfig {
102
+ /** IDs of rules to apply during this step */
103
+ ruleIds: string[];
104
+ /** IDs of constraints to check during this step */
105
+ constraintIds: string[];
106
+ }
107
+ /**
108
+ * Result of a step execution.
109
+ */
110
+ interface PraxisStepResult {
111
+ /** New state after applying rules and checking constraints */
112
+ state: PraxisState;
113
+ /** Diagnostics from rule execution and constraint checking */
114
+ diagnostics: PraxisDiagnostics[];
115
+ }
116
+ /**
117
+ * The core step function of the Praxis engine.
118
+ *
119
+ * This is the conceptual heart of the engine:
120
+ * - Takes current state, events, and configuration
121
+ * - Applies rules and checks constraints
122
+ * - Returns new state and diagnostics
123
+ *
124
+ * Pure, deterministic, data in → data out.
125
+ * No side effects, no global state.
126
+ */
127
+ type PraxisStepFn = (state: PraxisState, events: PraxisEvent[], config: PraxisStepConfig) => PraxisStepResult;
128
+
129
+ /**
130
+ * The result of evaluating a rule. Every rule MUST return one of:
131
+ * - `RuleResult.emit(facts)` — rule produced facts
132
+ * - `RuleResult.noop(reason?)` — rule evaluated but had nothing to say
133
+ * - `RuleResult.skip(reason?)` — rule decided to skip (preconditions not met)
134
+ * - `RuleResult.retract(tags)` — rule retracts previously emitted facts
135
+ */
136
+ declare class RuleResult {
137
+ /** The kind of result */
138
+ readonly kind: 'emit' | 'noop' | 'skip' | 'retract';
139
+ /** Facts produced (only for 'emit') */
140
+ readonly facts: PraxisFact[];
141
+ /** Fact tags to retract (only for 'retract') */
142
+ readonly retractTags: string[];
143
+ /** Optional reason (for noop/skip/retract — useful for debugging) */
144
+ readonly reason?: string;
145
+ /** The rule ID that produced this result (set by engine) */
146
+ ruleId?: string;
147
+ private constructor();
148
+ /**
149
+ * Rule produced facts.
150
+ *
151
+ * @example
152
+ * return RuleResult.emit([
153
+ * { tag: 'sprint.behind', payload: { deficit: 5 } }
154
+ * ]);
155
+ */
156
+ static emit(facts: PraxisFact[]): RuleResult;
157
+ /**
158
+ * Rule evaluated but had nothing to report.
159
+ * Unlike returning [], this is explicit and traceable.
160
+ *
161
+ * @example
162
+ * if (ctx.completedHours >= expectedHours) {
163
+ * return RuleResult.noop('Sprint is on pace');
164
+ * }
165
+ */
166
+ static noop(reason?: string): RuleResult;
167
+ /**
168
+ * Rule decided to skip because preconditions were not met.
169
+ * Distinct from noop: skip means "I can't evaluate", noop means "I evaluated and found nothing".
170
+ *
171
+ * @example
172
+ * if (!ctx.sprintName) {
173
+ * return RuleResult.skip('No active sprint');
174
+ * }
175
+ */
176
+ static skip(reason?: string): RuleResult;
177
+ /**
178
+ * Rule retracts previously emitted facts by tag.
179
+ * Used when a condition that previously produced facts is no longer true.
180
+ *
181
+ * @example
182
+ * // Sprint was behind, but caught up
183
+ * if (ctx.completedHours >= expectedHours) {
184
+ * return RuleResult.retract(['sprint.behind'], 'Sprint caught up');
185
+ * }
186
+ */
187
+ static retract(tags: string[], reason?: string): RuleResult;
188
+ /** Whether this result produced facts */
189
+ get hasFacts(): boolean;
190
+ /** Whether this result retracts facts */
191
+ get hasRetractions(): boolean;
192
+ }
193
+ /**
194
+ * A rule function that returns a typed RuleResult.
195
+ * New API — replaces the old PraxisFact[] return type.
196
+ */
197
+ type TypedRuleFn<TContext = unknown> = (state: PraxisState & {
198
+ context: TContext;
199
+ events: PraxisEvent[];
200
+ }, events: PraxisEvent[]) => RuleResult;
201
+ /**
202
+ * Convenience: create a fact object (just a shorthand)
203
+ */
204
+ declare function fact(tag: string, payload: unknown): PraxisFact;
205
+
206
+ export { type PraxisState as P, RuleResult as R, type TypedRuleFn as T, type PraxisEvent as a, type PraxisFact as b, type PraxisStepResult as c, type PraxisStepConfig as d, type PraxisDiagnostics as e, PRAXIS_PROTOCOL_VERSION as f, type PraxisStepFn as g, fact as h };