@plures/praxis 1.1.3 → 1.2.10

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 (74) hide show
  1. package/FRAMEWORK.md +106 -15
  2. package/README.md +194 -119
  3. package/dist/browser/adapter-CIMBGDC7.js +14 -0
  4. package/dist/browser/chunk-K377RW4V.js +230 -0
  5. package/dist/browser/chunk-MBVHLOU2.js +152 -0
  6. package/dist/browser/{chunk-R45WXWKH.js → chunk-VOMLVI6V.js} +1 -149
  7. package/dist/browser/engine-YJZV4SLD.js +8 -0
  8. package/dist/browser/index.d.ts +161 -5
  9. package/dist/browser/index.js +156 -141
  10. package/dist/browser/integrations/svelte.d.ts +2 -2
  11. package/dist/browser/integrations/svelte.js +2 -1
  12. package/dist/browser/{reactive-engine.svelte-C9OpcTHf.d.ts → reactive-engine.svelte-9aS0kTa8.d.ts} +136 -1
  13. package/dist/node/adapter-75ISSMWD.js +15 -0
  14. package/dist/node/chunk-5RH7UAQC.js +486 -0
  15. package/dist/node/chunk-MBVHLOU2.js +152 -0
  16. package/dist/node/chunk-PRPQO6R5.js +85 -0
  17. package/dist/node/chunk-R2PSBPKQ.js +150 -0
  18. package/dist/node/chunk-S54337I5.js +446 -0
  19. package/dist/node/{chunk-R45WXWKH.js → chunk-VOMLVI6V.js} +1 -149
  20. package/dist/node/chunk-WZ6B3LZ6.js +638 -0
  21. package/dist/node/cli/index.cjs +2936 -897
  22. package/dist/node/cli/index.js +27 -0
  23. package/dist/node/components/index.d.cts +3 -2
  24. package/dist/node/components/index.d.ts +3 -2
  25. package/dist/node/docs-JFNYTOJA.js +102 -0
  26. package/dist/node/engine-2DQBKBJC.js +9 -0
  27. package/dist/node/index.cjs +1114 -354
  28. package/dist/node/index.d.cts +388 -5
  29. package/dist/node/index.d.ts +388 -5
  30. package/dist/node/index.js +201 -640
  31. package/dist/node/integrations/svelte.cjs +76 -0
  32. package/dist/node/integrations/svelte.d.cts +2 -2
  33. package/dist/node/integrations/svelte.d.ts +2 -2
  34. package/dist/node/integrations/svelte.js +3 -1
  35. package/dist/node/{reactive-engine.svelte-1M4m_C_v.d.cts → reactive-engine.svelte-BFIZfawz.d.cts} +199 -1
  36. package/dist/node/{reactive-engine.svelte-ChNFn4Hj.d.ts → reactive-engine.svelte-CRNqHlbv.d.ts} +199 -1
  37. package/dist/node/reverse-W7THPV45.js +193 -0
  38. package/dist/node/{terminal-adapter-CWka-yL8.d.ts → terminal-adapter-B-UK_Vdz.d.ts} +28 -3
  39. package/dist/node/{terminal-adapter-CDzxoLKR.d.cts → terminal-adapter-BQSIF5bf.d.cts} +28 -3
  40. package/dist/node/validate-CNHUULQE.js +180 -0
  41. package/docs/core/pluresdb-integration.md +15 -15
  42. package/docs/decision-ledger/BEHAVIOR_LEDGER.md +225 -0
  43. package/docs/decision-ledger/DecisionLedger.tla +180 -0
  44. package/docs/decision-ledger/IMPLEMENTATION_SUMMARY.md +217 -0
  45. package/docs/decision-ledger/LATEST.md +166 -0
  46. package/docs/guides/cicd-pipeline.md +142 -0
  47. package/package.json +2 -2
  48. package/src/__tests__/cli-validate.test.ts +197 -0
  49. package/src/__tests__/decision-ledger.test.ts +485 -0
  50. package/src/__tests__/reverse-generator.test.ts +189 -0
  51. package/src/__tests__/scanner.test.ts +215 -0
  52. package/src/cli/commands/docs.ts +147 -0
  53. package/src/cli/commands/reverse.ts +289 -0
  54. package/src/cli/commands/validate.ts +264 -0
  55. package/src/cli/index.ts +68 -0
  56. package/src/core/pluresdb/adapter.ts +46 -3
  57. package/src/core/reactive-engine.svelte.ts +6 -1
  58. package/src/core/reactive-engine.ts +1 -1
  59. package/src/core/rules.ts +133 -0
  60. package/src/decision-ledger/README.md +400 -0
  61. package/src/decision-ledger/REVERSE_ENGINEERING.md +484 -0
  62. package/src/decision-ledger/facts-events.ts +121 -0
  63. package/src/decision-ledger/index.ts +70 -0
  64. package/src/decision-ledger/ledger.ts +246 -0
  65. package/src/decision-ledger/logic-ledger.ts +158 -0
  66. package/src/decision-ledger/reverse-generator.ts +426 -0
  67. package/src/decision-ledger/scanner.ts +506 -0
  68. package/src/decision-ledger/types.ts +247 -0
  69. package/src/decision-ledger/validation.ts +336 -0
  70. package/src/dsl/index.ts +13 -2
  71. package/src/index.browser.ts +6 -0
  72. package/src/index.ts +40 -0
  73. package/src/integrations/pluresdb.ts +14 -2
  74. package/src/integrations/unified.ts +350 -0
@@ -0,0 +1,230 @@
1
+ import {
2
+ createPraxisEngine
3
+ } from "./chunk-VOMLVI6V.js";
4
+
5
+ // src/core/rules.ts
6
+ var PraxisRegistry = class {
7
+ rules = /* @__PURE__ */ new Map();
8
+ constraints = /* @__PURE__ */ new Map();
9
+ compliance;
10
+ contractGaps = [];
11
+ constructor(options = {}) {
12
+ const defaultEnabled = typeof process !== "undefined" ? true : false;
13
+ this.compliance = {
14
+ enabled: defaultEnabled,
15
+ requiredFields: ["behavior", "examples", "invariants"],
16
+ missingSeverity: "warning",
17
+ ...options.compliance
18
+ };
19
+ }
20
+ /**
21
+ * Register a rule
22
+ */
23
+ registerRule(descriptor) {
24
+ if (this.rules.has(descriptor.id)) {
25
+ throw new Error(`Rule with id "${descriptor.id}" already registered`);
26
+ }
27
+ this.rules.set(descriptor.id, descriptor);
28
+ this.trackContractCompliance(descriptor.id, descriptor);
29
+ }
30
+ /**
31
+ * Register a constraint
32
+ */
33
+ registerConstraint(descriptor) {
34
+ if (this.constraints.has(descriptor.id)) {
35
+ throw new Error(`Constraint with id "${descriptor.id}" already registered`);
36
+ }
37
+ this.constraints.set(descriptor.id, descriptor);
38
+ this.trackContractCompliance(descriptor.id, descriptor);
39
+ }
40
+ /**
41
+ * Register a module (all its rules and constraints)
42
+ */
43
+ registerModule(module) {
44
+ for (const rule of module.rules) {
45
+ this.registerRule(rule);
46
+ }
47
+ for (const constraint of module.constraints) {
48
+ this.registerConstraint(constraint);
49
+ }
50
+ }
51
+ /**
52
+ * Get a rule by ID
53
+ */
54
+ getRule(id) {
55
+ return this.rules.get(id);
56
+ }
57
+ /**
58
+ * Get a constraint by ID
59
+ */
60
+ getConstraint(id) {
61
+ return this.constraints.get(id);
62
+ }
63
+ /**
64
+ * Get all registered rule IDs
65
+ */
66
+ getRuleIds() {
67
+ return Array.from(this.rules.keys());
68
+ }
69
+ /**
70
+ * Get all registered constraint IDs
71
+ */
72
+ getConstraintIds() {
73
+ return Array.from(this.constraints.keys());
74
+ }
75
+ /**
76
+ * Get all rules
77
+ */
78
+ getAllRules() {
79
+ return Array.from(this.rules.values());
80
+ }
81
+ /**
82
+ * Get all constraints
83
+ */
84
+ getAllConstraints() {
85
+ return Array.from(this.constraints.values());
86
+ }
87
+ /**
88
+ * Get collected contract gaps from registration-time validation.
89
+ */
90
+ getContractGaps() {
91
+ return [...this.contractGaps];
92
+ }
93
+ /**
94
+ * Clear collected contract gaps.
95
+ */
96
+ clearContractGaps() {
97
+ this.contractGaps = [];
98
+ }
99
+ trackContractCompliance(id, descriptor) {
100
+ if (!this.compliance.enabled) {
101
+ return;
102
+ }
103
+ const gaps = this.validateDescriptorContract(id, descriptor);
104
+ for (const gap of gaps) {
105
+ this.contractGaps.push(gap);
106
+ if (this.compliance.onGap) {
107
+ this.compliance.onGap(gap);
108
+ } else {
109
+ const label = gap.severity === "error" ? "ERROR" : gap.severity === "warning" ? "WARN" : "INFO";
110
+ console.warn(`[Praxis][${label}] Contract gap for "${gap.ruleId}": missing ${gap.missing.join(", ")}`);
111
+ }
112
+ }
113
+ }
114
+ validateDescriptorContract(id, descriptor) {
115
+ const requiredFields = this.compliance.requiredFields ?? ["behavior", "examples", "invariants"];
116
+ const missingSeverity = this.compliance.missingSeverity ?? "warning";
117
+ const contract = descriptor.contract ?? (descriptor.meta?.contract && typeof descriptor.meta.contract === "object" ? descriptor.meta.contract : void 0);
118
+ if (!contract) {
119
+ return [
120
+ {
121
+ ruleId: id,
122
+ missing: ["contract"],
123
+ severity: missingSeverity,
124
+ message: `Contract missing for "${id}"`
125
+ }
126
+ ];
127
+ }
128
+ const missing = [];
129
+ if (requiredFields.includes("behavior") && (!contract.behavior || contract.behavior.trim() === "")) {
130
+ missing.push("behavior");
131
+ }
132
+ if (requiredFields.includes("examples") && (!contract.examples || contract.examples.length === 0)) {
133
+ missing.push("examples");
134
+ }
135
+ if (requiredFields.includes("invariants") && (!contract.invariants || contract.invariants.length === 0)) {
136
+ missing.push("invariants");
137
+ }
138
+ if (missing.length === 0) {
139
+ return [];
140
+ }
141
+ return [
142
+ {
143
+ ruleId: id,
144
+ missing,
145
+ severity: "warning",
146
+ message: `Contract for "${id}" is incomplete: missing ${missing.join(", ")}`
147
+ }
148
+ ];
149
+ }
150
+ };
151
+
152
+ // src/core/reactive-engine.svelte.ts
153
+ import * as $ from "svelte/internal/client";
154
+ var ReactiveLogicEngine = class {
155
+ #state = (
156
+ // Use Svelte's $state rune for automatic reactivity
157
+ $.state($.proxy({ context: {}, facts: [], meta: {} }))
158
+ );
159
+ get state() {
160
+ return $.get(this.#state);
161
+ }
162
+ set state(value) {
163
+ $.set(this.#state, value, true);
164
+ }
165
+ _engine;
166
+ constructor(options) {
167
+ this.state.context = options.initialContext;
168
+ this.state.facts = options.initialFacts ?? [];
169
+ this.state.meta = options.initialMeta ?? {};
170
+ if (options.registry) {
171
+ this._engine = createPraxisEngine({
172
+ initialContext: options.initialContext,
173
+ registry: options.registry
174
+ });
175
+ } else {
176
+ this._engine = createPraxisEngine({
177
+ initialContext: options.initialContext,
178
+ registry: new PraxisRegistry()
179
+ });
180
+ }
181
+ }
182
+ /**
183
+ * Access the reactive context.
184
+ * In Svelte 5 components, changes to this object will automatically trigger updates.
185
+ */
186
+ get context() {
187
+ return this.state.context;
188
+ }
189
+ /**
190
+ * Access the reactive facts list.
191
+ */
192
+ get facts() {
193
+ return this.state.facts;
194
+ }
195
+ /**
196
+ * Access the reactive metadata.
197
+ */
198
+ get meta() {
199
+ return this.state.meta;
200
+ }
201
+ /**
202
+ * Apply a mutation to the state.
203
+ * Changes will automatically trigger Svelte reactivity.
204
+ *
205
+ * @param mutator A function that receives the state and modifies it.
206
+ */
207
+ apply(mutator) {
208
+ mutator(this.state);
209
+ }
210
+ /**
211
+ * Process events through the logic engine and update reactive state.
212
+ *
213
+ * @param events Events to process
214
+ */
215
+ step(events) {
216
+ const result = this._engine.step(events);
217
+ this.state.context = result.state.context;
218
+ this.state.facts = result.state.facts;
219
+ this.state.meta = result.state.meta ?? {};
220
+ }
221
+ };
222
+ function createReactiveEngine(options) {
223
+ return new ReactiveLogicEngine(options);
224
+ }
225
+
226
+ export {
227
+ PraxisRegistry,
228
+ ReactiveLogicEngine,
229
+ createReactiveEngine
230
+ };
@@ -0,0 +1,152 @@
1
+ // src/core/pluresdb/adapter.ts
2
+ var InMemoryPraxisDB = class {
3
+ store = /* @__PURE__ */ new Map();
4
+ watchers = /* @__PURE__ */ new Map();
5
+ async get(key) {
6
+ return this.store.get(key);
7
+ }
8
+ async set(key, value) {
9
+ this.store.set(key, value);
10
+ const keyWatchers = this.watchers.get(key);
11
+ if (keyWatchers) {
12
+ for (const callback of keyWatchers) {
13
+ callback(value);
14
+ }
15
+ }
16
+ }
17
+ watch(key, callback) {
18
+ if (!this.watchers.has(key)) {
19
+ this.watchers.set(key, /* @__PURE__ */ new Set());
20
+ }
21
+ const watchers = this.watchers.get(key);
22
+ const wrappedCallback = (val) => callback(val);
23
+ watchers.add(wrappedCallback);
24
+ return () => {
25
+ watchers.delete(wrappedCallback);
26
+ if (watchers.size === 0) {
27
+ this.watchers.delete(key);
28
+ }
29
+ };
30
+ }
31
+ /**
32
+ * Get all keys (for testing/debugging)
33
+ */
34
+ keys() {
35
+ return Array.from(this.store.keys());
36
+ }
37
+ /**
38
+ * Clear all data (for testing)
39
+ */
40
+ clear() {
41
+ this.store.clear();
42
+ this.watchers.clear();
43
+ }
44
+ };
45
+ function createInMemoryDB() {
46
+ return new InMemoryPraxisDB();
47
+ }
48
+ var PluresDBPraxisAdapter = class {
49
+ db;
50
+ watchers = /* @__PURE__ */ new Map();
51
+ pollIntervals = /* @__PURE__ */ new Map();
52
+ lastValues = /* @__PURE__ */ new Map();
53
+ pollInterval;
54
+ constructor(config) {
55
+ if ("get" in config && "put" in config) {
56
+ this.db = config;
57
+ this.pollInterval = 1e3;
58
+ } else {
59
+ this.db = config.db;
60
+ this.pollInterval = config.pollInterval ?? 1e3;
61
+ }
62
+ }
63
+ async get(key) {
64
+ try {
65
+ const value = await this.db.get(key);
66
+ return value;
67
+ } catch (error) {
68
+ return void 0;
69
+ }
70
+ }
71
+ async set(key, value) {
72
+ await this.db.put(key, value);
73
+ this.lastValues.set(key, value);
74
+ const keyWatchers = this.watchers.get(key);
75
+ if (keyWatchers) {
76
+ for (const callback of keyWatchers) {
77
+ callback(value);
78
+ }
79
+ }
80
+ }
81
+ watch(key, callback) {
82
+ if (!this.watchers.has(key)) {
83
+ this.watchers.set(key, /* @__PURE__ */ new Set());
84
+ }
85
+ const watchers = this.watchers.get(key);
86
+ const wrappedCallback = (val) => callback(val);
87
+ watchers.add(wrappedCallback);
88
+ if (!this.pollIntervals.has(key)) {
89
+ const interval = setInterval(async () => {
90
+ try {
91
+ const value = await this.db.get(key);
92
+ const lastValue = this.lastValues.get(key);
93
+ if (JSON.stringify(value) !== JSON.stringify(lastValue)) {
94
+ this.lastValues.set(key, value);
95
+ const currentWatchers = this.watchers.get(key);
96
+ if (currentWatchers) {
97
+ for (const cb of currentWatchers) {
98
+ cb(value);
99
+ }
100
+ }
101
+ }
102
+ } catch (error) {
103
+ }
104
+ }, this.pollInterval);
105
+ this.pollIntervals.set(key, interval);
106
+ }
107
+ return () => {
108
+ watchers.delete(wrappedCallback);
109
+ if (watchers.size === 0) {
110
+ this.watchers.delete(key);
111
+ const interval = this.pollIntervals.get(key);
112
+ if (interval) {
113
+ clearInterval(interval);
114
+ this.pollIntervals.delete(key);
115
+ }
116
+ this.lastValues.delete(key);
117
+ }
118
+ };
119
+ }
120
+ /**
121
+ * Clean up all resources
122
+ */
123
+ dispose() {
124
+ for (const interval of this.pollIntervals.values()) {
125
+ clearInterval(interval);
126
+ }
127
+ this.pollIntervals.clear();
128
+ this.watchers.clear();
129
+ this.lastValues.clear();
130
+ }
131
+ };
132
+ function createPluresDB(config) {
133
+ return new PluresDBPraxisAdapter(config);
134
+ }
135
+ async function createPraxisLocalFirst(options = {}) {
136
+ const { pollInterval, ...localOptions } = options;
137
+ const mod = await import("@plures/pluresdb/local-first");
138
+ const LocalFirstCtor = mod.PluresDBLocalFirst ?? mod.default;
139
+ if (!LocalFirstCtor) {
140
+ throw new Error("Failed to load PluresDBLocalFirst from @plures/pluresdb/local-first");
141
+ }
142
+ const db = new LocalFirstCtor(localOptions);
143
+ return new PluresDBPraxisAdapter({ db, pollInterval });
144
+ }
145
+
146
+ export {
147
+ InMemoryPraxisDB,
148
+ createInMemoryDB,
149
+ PluresDBPraxisAdapter,
150
+ createPluresDB,
151
+ createPraxisLocalFirst
152
+ };
@@ -1,77 +1,6 @@
1
1
  // src/core/protocol.ts
2
2
  var PRAXIS_PROTOCOL_VERSION = "1.0.0";
3
3
 
4
- // src/core/rules.ts
5
- var PraxisRegistry = class {
6
- rules = /* @__PURE__ */ new Map();
7
- constraints = /* @__PURE__ */ new Map();
8
- /**
9
- * Register a rule
10
- */
11
- registerRule(descriptor) {
12
- if (this.rules.has(descriptor.id)) {
13
- throw new Error(`Rule with id "${descriptor.id}" already registered`);
14
- }
15
- this.rules.set(descriptor.id, descriptor);
16
- }
17
- /**
18
- * Register a constraint
19
- */
20
- registerConstraint(descriptor) {
21
- if (this.constraints.has(descriptor.id)) {
22
- throw new Error(`Constraint with id "${descriptor.id}" already registered`);
23
- }
24
- this.constraints.set(descriptor.id, descriptor);
25
- }
26
- /**
27
- * Register a module (all its rules and constraints)
28
- */
29
- registerModule(module) {
30
- for (const rule of module.rules) {
31
- this.registerRule(rule);
32
- }
33
- for (const constraint of module.constraints) {
34
- this.registerConstraint(constraint);
35
- }
36
- }
37
- /**
38
- * Get a rule by ID
39
- */
40
- getRule(id) {
41
- return this.rules.get(id);
42
- }
43
- /**
44
- * Get a constraint by ID
45
- */
46
- getConstraint(id) {
47
- return this.constraints.get(id);
48
- }
49
- /**
50
- * Get all registered rule IDs
51
- */
52
- getRuleIds() {
53
- return Array.from(this.rules.keys());
54
- }
55
- /**
56
- * Get all registered constraint IDs
57
- */
58
- getConstraintIds() {
59
- return Array.from(this.constraints.keys());
60
- }
61
- /**
62
- * Get all rules
63
- */
64
- getAllRules() {
65
- return Array.from(this.rules.values());
66
- }
67
- /**
68
- * Get all constraints
69
- */
70
- getAllConstraints() {
71
- return Array.from(this.constraints.values());
72
- }
73
- };
74
-
75
4
  // src/core/engine.ts
76
5
  function safeClone(value) {
77
6
  if (value === null || typeof value !== "object") {
@@ -261,85 +190,8 @@ function createPraxisEngine(options) {
261
190
  return new LogicEngine(options);
262
191
  }
263
192
 
264
- // src/core/reactive-engine.svelte.ts
265
- import * as $ from "svelte/internal/client";
266
- var ReactiveLogicEngine = class {
267
- #state = (
268
- // Use Svelte's $state rune for automatic reactivity
269
- $.state($.proxy({ context: {}, facts: [], meta: {} }))
270
- );
271
- get state() {
272
- return $.get(this.#state);
273
- }
274
- set state(value) {
275
- $.set(this.#state, value, true);
276
- }
277
- _engine;
278
- constructor(options) {
279
- this.state.context = options.initialContext;
280
- this.state.facts = options.initialFacts ?? [];
281
- this.state.meta = options.initialMeta ?? {};
282
- if (options.registry) {
283
- this._engine = createPraxisEngine({
284
- initialContext: options.initialContext,
285
- registry: options.registry
286
- });
287
- } else {
288
- this._engine = createPraxisEngine({
289
- initialContext: options.initialContext,
290
- registry: new PraxisRegistry()
291
- });
292
- }
293
- }
294
- /**
295
- * Access the reactive context.
296
- * In Svelte 5 components, changes to this object will automatically trigger updates.
297
- */
298
- get context() {
299
- return this.state.context;
300
- }
301
- /**
302
- * Access the reactive facts list.
303
- */
304
- get facts() {
305
- return this.state.facts;
306
- }
307
- /**
308
- * Access the reactive metadata.
309
- */
310
- get meta() {
311
- return this.state.meta;
312
- }
313
- /**
314
- * Apply a mutation to the state.
315
- * Changes will automatically trigger Svelte reactivity.
316
- *
317
- * @param mutator A function that receives the state and modifies it.
318
- */
319
- apply(mutator) {
320
- mutator(this.state);
321
- }
322
- /**
323
- * Process events through the logic engine and update reactive state.
324
- *
325
- * @param events Events to process
326
- */
327
- step(events) {
328
- const result = this._engine.step(events);
329
- this.state.context = result.state.context;
330
- this.state.facts = result.state.facts;
331
- this.state.meta = result.state.meta ?? {};
332
- }
333
- };
334
- function createReactiveEngine(options) {
335
- return new ReactiveLogicEngine(options);
336
- }
337
-
338
193
  export {
339
194
  PRAXIS_PROTOCOL_VERSION,
340
- PraxisRegistry,
341
195
  LogicEngine,
342
- createPraxisEngine,
343
- ReactiveLogicEngine,
344
- createReactiveEngine
196
+ createPraxisEngine
345
197
  };
@@ -0,0 +1,8 @@
1
+ import {
2
+ LogicEngine,
3
+ createPraxisEngine
4
+ } from "./chunk-VOMLVI6V.js";
5
+ export {
6
+ LogicEngine,
7
+ createPraxisEngine
8
+ };