@plures/praxis 1.4.0 → 2.0.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.
Files changed (72) hide show
  1. package/dist/browser/{chunk-N63K4KWS.js → chunk-4IRUGWR3.js} +1 -1
  2. package/dist/browser/chunk-6MVRT7CK.js +363 -0
  3. package/dist/browser/chunk-6SJ44Q64.js +473 -0
  4. package/dist/browser/chunk-BQOYZBWA.js +282 -0
  5. package/dist/browser/chunk-IG5BJ2MT.js +91 -0
  6. package/dist/browser/{chunk-MJK3IYTJ.js → chunk-JZDJU2DO.js} +4 -84
  7. package/dist/browser/chunk-ZEW4LJAJ.js +353 -0
  8. package/dist/browser/{engine-YIEGSX7U.js → engine-3B5WJPGT.js} +2 -1
  9. package/dist/browser/expectations/index.d.ts +180 -0
  10. package/dist/browser/expectations/index.js +14 -0
  11. package/dist/browser/factory/index.d.ts +150 -0
  12. package/dist/browser/factory/index.js +15 -0
  13. package/dist/browser/index.d.ts +277 -3
  14. package/dist/browser/index.js +425 -60
  15. package/dist/browser/integrations/svelte.d.ts +4 -2
  16. package/dist/browser/integrations/svelte.js +3 -2
  17. package/dist/browser/project/index.d.ts +177 -0
  18. package/dist/browser/project/index.js +19 -0
  19. package/dist/browser/reactive-engine.svelte-BwWadvAW.d.ts +224 -0
  20. package/dist/browser/rule-result-DcXWe9tn.d.ts +206 -0
  21. package/dist/browser/rules-BaWMqxuG.d.ts +277 -0
  22. package/dist/browser/unified/index.d.ts +239 -0
  23. package/dist/browser/unified/index.js +20 -0
  24. package/dist/node/chunk-6MVRT7CK.js +363 -0
  25. package/dist/node/chunk-AZLNISFI.js +1690 -0
  26. package/dist/node/chunk-IG5BJ2MT.js +91 -0
  27. package/dist/node/{chunk-KMJWAFZV.js → chunk-JZDJU2DO.js} +4 -89
  28. package/dist/node/{chunk-7M3HV4XR.js → chunk-WFRHXZBP.js} +3 -3
  29. package/dist/node/cli/index.cjs +48 -0
  30. package/dist/node/cli/index.js +2 -2
  31. package/dist/node/{engine-FEN5IYZ5.js → engine-VFHCIEM4.js} +2 -1
  32. package/dist/node/index.cjs +2114 -0
  33. package/dist/node/index.d.cts +964 -280
  34. package/dist/node/index.d.ts +964 -280
  35. package/dist/node/index.js +575 -10
  36. package/dist/node/integrations/svelte.d.cts +3 -2
  37. package/dist/node/integrations/svelte.d.ts +3 -2
  38. package/dist/node/integrations/svelte.js +3 -2
  39. package/dist/node/{reactive-engine.svelte-DekxqFu0.d.ts → reactive-engine.svelte-BBZLMzus.d.ts} +3 -79
  40. package/dist/node/{reactive-engine.svelte-Cg0Yc2Hs.d.cts → reactive-engine.svelte-Cbq_V20o.d.cts} +3 -79
  41. package/dist/node/rule-result-B9GMivAn.d.cts +80 -0
  42. package/dist/node/rule-result-Bo3sFMmN.d.ts +80 -0
  43. package/dist/node/{server-SYZPDULV.js → server-FKLVY57V.js} +4 -2
  44. package/dist/node/unified/index.cjs +484 -0
  45. package/dist/node/unified/index.d.cts +240 -0
  46. package/dist/node/unified/index.d.ts +240 -0
  47. package/dist/node/unified/index.js +21 -0
  48. package/dist/node/{validate-TQGVIG7G.js → validate-BY7JNY7H.js} +2 -1
  49. package/package.json +38 -11
  50. package/src/__tests__/chronos-project.test.ts +799 -0
  51. package/src/__tests__/decision-ledger.test.ts +857 -402
  52. package/src/chronos/diff.ts +336 -0
  53. package/src/chronos/hooks.ts +227 -0
  54. package/src/chronos/index.ts +83 -0
  55. package/src/chronos/project-chronicle.ts +198 -0
  56. package/src/chronos/timeline.ts +152 -0
  57. package/src/decision-ledger/analyzer-types.ts +280 -0
  58. package/src/decision-ledger/analyzer.ts +518 -0
  59. package/src/decision-ledger/contract-verification.ts +456 -0
  60. package/src/decision-ledger/derivation.ts +158 -0
  61. package/src/decision-ledger/index.ts +59 -0
  62. package/src/decision-ledger/report.ts +378 -0
  63. package/src/decision-ledger/suggestions.ts +287 -0
  64. package/src/index.browser.ts +103 -0
  65. package/src/index.ts +98 -0
  66. package/src/unified/__tests__/unified.test.ts +396 -0
  67. package/src/unified/core.ts +517 -0
  68. package/src/unified/index.ts +32 -0
  69. package/src/unified/rules.ts +66 -0
  70. package/src/unified/types.ts +148 -0
  71. package/dist/browser/reactive-engine.svelte-DjynI82A.d.ts +0 -688
  72. package/dist/node/chunk-FWOXU4MM.js +0 -487
@@ -0,0 +1,363 @@
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
+ }));
38
+ const constraints = config.constraints ?? [];
39
+ const livenessConfig = config.liveness;
40
+ const initTime = Date.now();
41
+ let livenessTimer = null;
42
+ if (livenessConfig) {
43
+ const timeout = livenessConfig.timeoutMs ?? 5e3;
44
+ livenessTimer = setTimeout(() => {
45
+ for (const expectedPath of livenessConfig.expect) {
46
+ const state = paths.get(expectedPath);
47
+ if (!state || state.updateCount === 0) {
48
+ const elapsed = Date.now() - initTime;
49
+ recordTimeline(expectedPath, "liveness", {
50
+ stale: true,
51
+ elapsed,
52
+ message: `Path "${expectedPath}" never updated after ${elapsed}ms`
53
+ });
54
+ livenessConfig.onStale?.(expectedPath, elapsed);
55
+ }
56
+ }
57
+ }, timeout);
58
+ }
59
+ function getPathValues(watchPaths) {
60
+ const values = {};
61
+ for (const p of watchPaths) {
62
+ const state = paths.get(p);
63
+ values[p] = state ? state.value : void 0;
64
+ }
65
+ return values;
66
+ }
67
+ function notify(path, value) {
68
+ const state = paths.get(path);
69
+ if (!state) return;
70
+ for (const cb of state.subscribers) {
71
+ try {
72
+ cb(value);
73
+ } catch (err) {
74
+ console.error(`[praxis] Subscriber error for "${path}":`, err);
75
+ }
76
+ }
77
+ }
78
+ function checkConstraints(path, value) {
79
+ const violations = [];
80
+ for (const c of constraints) {
81
+ if (!c.watch.includes(path)) continue;
82
+ const values = getPathValues(c.watch);
83
+ values[path] = value;
84
+ try {
85
+ const result = c.validate(values);
86
+ if (result !== true) {
87
+ violations.push({
88
+ kind: "constraint-violation",
89
+ message: result,
90
+ data: { constraintId: c.id, path, description: c.description }
91
+ });
92
+ recordTimeline(path, "constraint-check", {
93
+ constraintId: c.id,
94
+ violated: true,
95
+ message: result
96
+ });
97
+ }
98
+ } catch (err) {
99
+ violations.push({
100
+ kind: "constraint-violation",
101
+ message: `Constraint "${c.id}" threw: ${err instanceof Error ? err.message : String(err)}`,
102
+ data: { constraintId: c.id, error: err }
103
+ });
104
+ }
105
+ }
106
+ return violations;
107
+ }
108
+ function evaluateRules() {
109
+ const newFacts = [];
110
+ const retractions = [];
111
+ for (const rs of ruleStates) {
112
+ const values = getPathValues(rs.rule.watch);
113
+ try {
114
+ const result = rs.rule.evaluate(values, [...facts]);
115
+ rs.lastResult = result;
116
+ recordTimeline(rs.rule.watch[0] ?? "*", "rule-eval", {
117
+ ruleId: rs.rule.id,
118
+ kind: result.kind,
119
+ reason: result.reason
120
+ });
121
+ switch (result.kind) {
122
+ case "emit":
123
+ newFacts.push(...result.facts);
124
+ break;
125
+ case "retract":
126
+ retractions.push(...result.retractTags);
127
+ break;
128
+ case "noop":
129
+ case "skip":
130
+ break;
131
+ }
132
+ } catch (err) {
133
+ console.error(`[praxis] Rule "${rs.rule.id}" error:`, err);
134
+ }
135
+ }
136
+ if (retractions.length > 0) {
137
+ const retractSet = new Set(retractions);
138
+ for (const tag of retractSet) {
139
+ factMap.delete(tag);
140
+ }
141
+ }
142
+ for (const f of newFacts) {
143
+ factMap.set(f.tag, f);
144
+ }
145
+ facts = Array.from(factMap.values());
146
+ }
147
+ function query(path, opts) {
148
+ let state = paths.get(path);
149
+ if (!state) {
150
+ state = {
151
+ schema: { path, initial: void 0 },
152
+ value: void 0,
153
+ subscribers: /* @__PURE__ */ new Set(),
154
+ lastUpdated: 0,
155
+ updateCount: 0
156
+ };
157
+ paths.set(path, state);
158
+ }
159
+ const ref = {
160
+ get current() {
161
+ const s = paths.get(path);
162
+ return applyQueryOpts(s?.value ?? state.schema.initial, opts);
163
+ },
164
+ subscribe(cb) {
165
+ const wrappedCb = (rawValue) => {
166
+ const processed = applyQueryOpts(rawValue, opts);
167
+ cb(processed);
168
+ };
169
+ const s = paths.get(path);
170
+ s.subscribers.add(wrappedCb);
171
+ try {
172
+ cb(ref.current);
173
+ } catch (err) {
174
+ console.error(`[praxis] query("${path}") subscriber init error:`, err);
175
+ }
176
+ return () => {
177
+ s.subscribers.delete(wrappedCb);
178
+ };
179
+ }
180
+ };
181
+ return ref;
182
+ }
183
+ function applyQueryOpts(value, opts) {
184
+ if (!opts || !Array.isArray(value)) return value;
185
+ let result = [...value];
186
+ if (opts.where) result = result.filter(opts.where);
187
+ if (opts.sort) result.sort(opts.sort);
188
+ if (opts.select) result = result.map(opts.select);
189
+ if (opts.limit) result = result.slice(0, opts.limit);
190
+ return result;
191
+ }
192
+ function mutateInternal(path, value) {
193
+ const violations = checkConstraints(path, value);
194
+ if (violations.length > 0) {
195
+ return { violations, emittedFacts: [] };
196
+ }
197
+ const state = paths.get(path);
198
+ if (!state) {
199
+ paths.set(path, {
200
+ schema: { path, initial: value },
201
+ value,
202
+ subscribers: /* @__PURE__ */ new Set(),
203
+ lastUpdated: Date.now(),
204
+ updateCount: 1
205
+ });
206
+ } else {
207
+ const before = state.value;
208
+ state.value = value;
209
+ state.lastUpdated = Date.now();
210
+ state.updateCount++;
211
+ recordTimeline(path, "mutation", {
212
+ before: summarize(before),
213
+ after: summarize(value)
214
+ });
215
+ }
216
+ notify(path, value);
217
+ const factsBefore = facts.length;
218
+ evaluateRules();
219
+ const emittedFacts = facts.slice(factsBefore);
220
+ return { violations: [], emittedFacts };
221
+ }
222
+ function mutate(path, value) {
223
+ const { violations, emittedFacts } = mutateInternal(path, value);
224
+ return {
225
+ accepted: violations.length === 0,
226
+ violations,
227
+ facts: emittedFacts
228
+ };
229
+ }
230
+ function batchMutate(fn) {
231
+ const allViolations = [];
232
+ const pendingWrites = [];
233
+ fn((path, value) => {
234
+ const violations = checkConstraints(path, value);
235
+ if (violations.length > 0) {
236
+ allViolations.push(...violations);
237
+ } else {
238
+ pendingWrites.push({ path, value });
239
+ }
240
+ });
241
+ if (allViolations.length > 0) {
242
+ return { accepted: false, violations: allViolations, facts: [] };
243
+ }
244
+ for (const { path, value } of pendingWrites) {
245
+ const state = paths.get(path);
246
+ if (state) {
247
+ const before = state.value;
248
+ state.value = value;
249
+ state.lastUpdated = Date.now();
250
+ state.updateCount++;
251
+ recordTimeline(path, "mutation", {
252
+ before: summarize(before),
253
+ after: summarize(value)
254
+ });
255
+ } else {
256
+ paths.set(path, {
257
+ schema: { path, initial: value },
258
+ value,
259
+ subscribers: /* @__PURE__ */ new Set(),
260
+ lastUpdated: Date.now(),
261
+ updateCount: 1
262
+ });
263
+ }
264
+ }
265
+ for (const { path, value } of pendingWrites) {
266
+ notify(path, value);
267
+ }
268
+ const factsBefore = facts.length;
269
+ evaluateRules();
270
+ return {
271
+ accepted: true,
272
+ violations: [],
273
+ facts: facts.slice(factsBefore)
274
+ };
275
+ }
276
+ function getLiveness() {
277
+ const result = {};
278
+ const now = Date.now();
279
+ const watchPaths = livenessConfig?.expect ?? [];
280
+ for (const p of watchPaths) {
281
+ const state = paths.get(p);
282
+ const lastUpdated = state?.lastUpdated ?? 0;
283
+ const elapsed = lastUpdated > 0 ? now - lastUpdated : now - initTime;
284
+ const timeout = livenessConfig?.timeoutMs ?? 5e3;
285
+ result[p] = {
286
+ stale: state?.updateCount === 0 || elapsed > timeout,
287
+ lastUpdated,
288
+ elapsed
289
+ };
290
+ }
291
+ return result;
292
+ }
293
+ function destroy() {
294
+ if (livenessTimer) clearTimeout(livenessTimer);
295
+ for (const state of paths.values()) {
296
+ state.subscribers.clear();
297
+ }
298
+ paths.clear();
299
+ facts = [];
300
+ factMap.clear();
301
+ timeline.length = 0;
302
+ }
303
+ return {
304
+ query,
305
+ mutate,
306
+ batch: batchMutate,
307
+ facts: () => [...facts],
308
+ violations: () => {
309
+ const allViolations = [];
310
+ for (const c of constraints) {
311
+ const values = getPathValues(c.watch);
312
+ try {
313
+ const result = c.validate(values);
314
+ if (result !== true) {
315
+ allViolations.push({
316
+ kind: "constraint-violation",
317
+ message: result,
318
+ data: { constraintId: c.id }
319
+ });
320
+ }
321
+ } catch {
322
+ }
323
+ }
324
+ return allViolations;
325
+ },
326
+ timeline: () => [...timeline],
327
+ evaluate: evaluateRules,
328
+ destroy,
329
+ liveness: getLiveness
330
+ };
331
+ }
332
+ function summarize(value) {
333
+ if (value === null || value === void 0) return value;
334
+ if (typeof value !== "object") return value;
335
+ if (Array.isArray(value)) return `[Array(${value.length})]`;
336
+ const keys = Object.keys(value);
337
+ if (keys.length > 10) return `{Object(${keys.length} keys)}`;
338
+ return value;
339
+ }
340
+
341
+ // src/unified/types.ts
342
+ function definePath(path, initial, opts) {
343
+ return { path, initial, ...opts };
344
+ }
345
+
346
+ // src/unified/rules.ts
347
+ function defineRule(rule) {
348
+ return rule;
349
+ }
350
+ function defineConstraint(constraint) {
351
+ return constraint;
352
+ }
353
+ function defineModule(name, rules) {
354
+ return { name, rules };
355
+ }
356
+
357
+ export {
358
+ createApp,
359
+ definePath,
360
+ defineRule,
361
+ defineConstraint,
362
+ defineModule
363
+ };