@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.
- package/dist/browser/{chunk-N63K4KWS.js → chunk-4IRUGWR3.js} +1 -1
- package/dist/browser/chunk-6MVRT7CK.js +363 -0
- package/dist/browser/chunk-6SJ44Q64.js +473 -0
- package/dist/browser/chunk-BQOYZBWA.js +282 -0
- package/dist/browser/chunk-IG5BJ2MT.js +91 -0
- package/dist/browser/{chunk-MJK3IYTJ.js → chunk-JZDJU2DO.js} +4 -84
- package/dist/browser/chunk-ZEW4LJAJ.js +353 -0
- package/dist/browser/{engine-YIEGSX7U.js → engine-3B5WJPGT.js} +2 -1
- package/dist/browser/expectations/index.d.ts +180 -0
- package/dist/browser/expectations/index.js +14 -0
- package/dist/browser/factory/index.d.ts +150 -0
- package/dist/browser/factory/index.js +15 -0
- package/dist/browser/index.d.ts +277 -3
- package/dist/browser/index.js +425 -60
- package/dist/browser/integrations/svelte.d.ts +4 -2
- package/dist/browser/integrations/svelte.js +3 -2
- package/dist/browser/project/index.d.ts +177 -0
- package/dist/browser/project/index.js +19 -0
- package/dist/browser/reactive-engine.svelte-BwWadvAW.d.ts +224 -0
- package/dist/browser/rule-result-DcXWe9tn.d.ts +206 -0
- package/dist/browser/rules-BaWMqxuG.d.ts +277 -0
- package/dist/browser/unified/index.d.ts +239 -0
- package/dist/browser/unified/index.js +20 -0
- package/dist/node/chunk-6MVRT7CK.js +363 -0
- package/dist/node/chunk-AZLNISFI.js +1690 -0
- package/dist/node/chunk-IG5BJ2MT.js +91 -0
- package/dist/node/{chunk-KMJWAFZV.js → chunk-JZDJU2DO.js} +4 -89
- package/dist/node/{chunk-7M3HV4XR.js → chunk-WFRHXZBP.js} +3 -3
- package/dist/node/cli/index.cjs +48 -0
- package/dist/node/cli/index.js +2 -2
- package/dist/node/{engine-FEN5IYZ5.js → engine-VFHCIEM4.js} +2 -1
- package/dist/node/index.cjs +2114 -0
- package/dist/node/index.d.cts +964 -280
- package/dist/node/index.d.ts +964 -280
- package/dist/node/index.js +575 -10
- package/dist/node/integrations/svelte.d.cts +3 -2
- package/dist/node/integrations/svelte.d.ts +3 -2
- package/dist/node/integrations/svelte.js +3 -2
- package/dist/node/{reactive-engine.svelte-DekxqFu0.d.ts → reactive-engine.svelte-BBZLMzus.d.ts} +3 -79
- package/dist/node/{reactive-engine.svelte-Cg0Yc2Hs.d.cts → reactive-engine.svelte-Cbq_V20o.d.cts} +3 -79
- package/dist/node/rule-result-B9GMivAn.d.cts +80 -0
- package/dist/node/rule-result-Bo3sFMmN.d.ts +80 -0
- package/dist/node/{server-SYZPDULV.js → server-FKLVY57V.js} +4 -2
- package/dist/node/unified/index.cjs +484 -0
- package/dist/node/unified/index.d.cts +240 -0
- package/dist/node/unified/index.d.ts +240 -0
- package/dist/node/unified/index.js +21 -0
- package/dist/node/{validate-TQGVIG7G.js → validate-BY7JNY7H.js} +2 -1
- package/package.json +38 -11
- package/src/__tests__/chronos-project.test.ts +799 -0
- package/src/__tests__/decision-ledger.test.ts +857 -402
- package/src/chronos/diff.ts +336 -0
- package/src/chronos/hooks.ts +227 -0
- package/src/chronos/index.ts +83 -0
- package/src/chronos/project-chronicle.ts +198 -0
- package/src/chronos/timeline.ts +152 -0
- package/src/decision-ledger/analyzer-types.ts +280 -0
- package/src/decision-ledger/analyzer.ts +518 -0
- package/src/decision-ledger/contract-verification.ts +456 -0
- package/src/decision-ledger/derivation.ts +158 -0
- package/src/decision-ledger/index.ts +59 -0
- package/src/decision-ledger/report.ts +378 -0
- package/src/decision-ledger/suggestions.ts +287 -0
- package/src/index.browser.ts +103 -0
- package/src/index.ts +98 -0
- package/src/unified/__tests__/unified.test.ts +396 -0
- package/src/unified/core.ts +517 -0
- package/src/unified/index.ts +32 -0
- package/src/unified/rules.ts +66 -0
- package/src/unified/types.ts +148 -0
- package/dist/browser/reactive-engine.svelte-DjynI82A.d.ts +0 -688
- package/dist/node/chunk-FWOXU4MM.js +0 -487
|
@@ -1,688 +0,0 @@
|
|
|
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
|
-
* Decision Ledger - Contract Types
|
|
131
|
-
*
|
|
132
|
-
* Types for defining and validating contracts for rules and constraints.
|
|
133
|
-
* All types are JSON-serializable for cross-language compatibility.
|
|
134
|
-
*/
|
|
135
|
-
/**
|
|
136
|
-
* A single assumption made during contract definition.
|
|
137
|
-
*/
|
|
138
|
-
interface Assumption {
|
|
139
|
-
/** Stable unique identifier for the assumption */
|
|
140
|
-
id: string;
|
|
141
|
-
/** The assumption statement */
|
|
142
|
-
statement: string;
|
|
143
|
-
/** Confidence level (0.0 to 1.0) */
|
|
144
|
-
confidence: number;
|
|
145
|
-
/** Justification for the assumption */
|
|
146
|
-
justification: string;
|
|
147
|
-
/** What this assumption was derived from */
|
|
148
|
-
derivedFrom?: string;
|
|
149
|
-
/** What artifacts this assumption impacts */
|
|
150
|
-
impacts: Array<'spec' | 'tests' | 'code'>;
|
|
151
|
-
/** Current status of the assumption */
|
|
152
|
-
status: 'active' | 'revised' | 'invalidated';
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* A reference to external documentation or resources.
|
|
156
|
-
*/
|
|
157
|
-
interface Reference {
|
|
158
|
-
/** Type of reference (e.g., 'doc', 'ticket', 'issue') */
|
|
159
|
-
type: string;
|
|
160
|
-
/** URL to the reference */
|
|
161
|
-
url?: string;
|
|
162
|
-
/** Human-readable description */
|
|
163
|
-
description?: string;
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* A Given/When/Then example for a contract.
|
|
167
|
-
*/
|
|
168
|
-
interface Example {
|
|
169
|
-
/** Initial state or preconditions */
|
|
170
|
-
given: string;
|
|
171
|
-
/** Triggering event or action */
|
|
172
|
-
when: string;
|
|
173
|
-
/** Expected outcome or postconditions */
|
|
174
|
-
then: string;
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Contract for a rule or constraint.
|
|
178
|
-
* Documents the expected behavior, test cases, invariants, and assumptions.
|
|
179
|
-
*/
|
|
180
|
-
interface Contract {
|
|
181
|
-
/** ID of the rule or constraint this contract applies to */
|
|
182
|
-
ruleId: string;
|
|
183
|
-
/** Canonical behavior description */
|
|
184
|
-
behavior: string;
|
|
185
|
-
/** Given/When/Then examples (become test vectors) */
|
|
186
|
-
examples: Example[];
|
|
187
|
-
/** TLA+-friendly invariants or Praxis-level invariants */
|
|
188
|
-
invariants: string[];
|
|
189
|
-
/** Explicit assumptions with confidence levels */
|
|
190
|
-
assumptions?: Assumption[];
|
|
191
|
-
/** References to docs, tickets, links */
|
|
192
|
-
references?: Reference[];
|
|
193
|
-
/** Contract version (for evolution tracking) */
|
|
194
|
-
version?: string;
|
|
195
|
-
/** Timestamp of contract creation */
|
|
196
|
-
timestamp?: string;
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Severity levels for contract gaps.
|
|
200
|
-
*/
|
|
201
|
-
type Severity = 'warning' | 'error' | 'info';
|
|
202
|
-
/**
|
|
203
|
-
* Types of missing contract artifacts.
|
|
204
|
-
*/
|
|
205
|
-
/**
|
|
206
|
-
* Types of artifacts that can be missing from a contract.
|
|
207
|
-
*
|
|
208
|
-
* Note: 'tests' and 'spec' are included in this type for future extensibility
|
|
209
|
-
* and SARIF reporting compatibility, but are not currently validated by the
|
|
210
|
-
* validateContract function. To check for these, implement custom validation
|
|
211
|
-
* logic that scans for test files or spec files in your codebase.
|
|
212
|
-
*/
|
|
213
|
-
type MissingArtifact = 'behavior' | 'examples' | 'invariants' | 'tests' | 'spec' | 'contract';
|
|
214
|
-
/**
|
|
215
|
-
* A gap in contract coverage.
|
|
216
|
-
*/
|
|
217
|
-
interface ContractGap {
|
|
218
|
-
/** ID of the rule or constraint */
|
|
219
|
-
ruleId: string;
|
|
220
|
-
/** What is missing */
|
|
221
|
-
missing: MissingArtifact[];
|
|
222
|
-
/** Severity of the gap */
|
|
223
|
-
severity: Severity;
|
|
224
|
-
/** Optional human-readable message */
|
|
225
|
-
message?: string;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* The result of evaluating a rule. Every rule MUST return one of:
|
|
230
|
-
* - `RuleResult.emit(facts)` — rule produced facts
|
|
231
|
-
* - `RuleResult.noop(reason?)` — rule evaluated but had nothing to say
|
|
232
|
-
* - `RuleResult.skip(reason?)` — rule decided to skip (preconditions not met)
|
|
233
|
-
* - `RuleResult.retract(tags)` — rule retracts previously emitted facts
|
|
234
|
-
*/
|
|
235
|
-
declare class RuleResult {
|
|
236
|
-
/** The kind of result */
|
|
237
|
-
readonly kind: 'emit' | 'noop' | 'skip' | 'retract';
|
|
238
|
-
/** Facts produced (only for 'emit') */
|
|
239
|
-
readonly facts: PraxisFact[];
|
|
240
|
-
/** Fact tags to retract (only for 'retract') */
|
|
241
|
-
readonly retractTags: string[];
|
|
242
|
-
/** Optional reason (for noop/skip/retract — useful for debugging) */
|
|
243
|
-
readonly reason?: string;
|
|
244
|
-
/** The rule ID that produced this result (set by engine) */
|
|
245
|
-
ruleId?: string;
|
|
246
|
-
private constructor();
|
|
247
|
-
/**
|
|
248
|
-
* Rule produced facts.
|
|
249
|
-
*
|
|
250
|
-
* @example
|
|
251
|
-
* return RuleResult.emit([
|
|
252
|
-
* { tag: 'sprint.behind', payload: { deficit: 5 } }
|
|
253
|
-
* ]);
|
|
254
|
-
*/
|
|
255
|
-
static emit(facts: PraxisFact[]): RuleResult;
|
|
256
|
-
/**
|
|
257
|
-
* Rule evaluated but had nothing to report.
|
|
258
|
-
* Unlike returning [], this is explicit and traceable.
|
|
259
|
-
*
|
|
260
|
-
* @example
|
|
261
|
-
* if (ctx.completedHours >= expectedHours) {
|
|
262
|
-
* return RuleResult.noop('Sprint is on pace');
|
|
263
|
-
* }
|
|
264
|
-
*/
|
|
265
|
-
static noop(reason?: string): RuleResult;
|
|
266
|
-
/**
|
|
267
|
-
* Rule decided to skip because preconditions were not met.
|
|
268
|
-
* Distinct from noop: skip means "I can't evaluate", noop means "I evaluated and found nothing".
|
|
269
|
-
*
|
|
270
|
-
* @example
|
|
271
|
-
* if (!ctx.sprintName) {
|
|
272
|
-
* return RuleResult.skip('No active sprint');
|
|
273
|
-
* }
|
|
274
|
-
*/
|
|
275
|
-
static skip(reason?: string): RuleResult;
|
|
276
|
-
/**
|
|
277
|
-
* Rule retracts previously emitted facts by tag.
|
|
278
|
-
* Used when a condition that previously produced facts is no longer true.
|
|
279
|
-
*
|
|
280
|
-
* @example
|
|
281
|
-
* // Sprint was behind, but caught up
|
|
282
|
-
* if (ctx.completedHours >= expectedHours) {
|
|
283
|
-
* return RuleResult.retract(['sprint.behind'], 'Sprint caught up');
|
|
284
|
-
* }
|
|
285
|
-
*/
|
|
286
|
-
static retract(tags: string[], reason?: string): RuleResult;
|
|
287
|
-
/** Whether this result produced facts */
|
|
288
|
-
get hasFacts(): boolean;
|
|
289
|
-
/** Whether this result retracts facts */
|
|
290
|
-
get hasRetractions(): boolean;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* Rules and Constraints System
|
|
295
|
-
*
|
|
296
|
-
* This module defines the types and registry for rules and constraints.
|
|
297
|
-
* Rules and constraints are identified by stable IDs and can be described as data,
|
|
298
|
-
* making them portable across languages and suitable for DSL-based definitions.
|
|
299
|
-
*/
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* Unique identifier for a rule
|
|
303
|
-
*/
|
|
304
|
-
type RuleId = string;
|
|
305
|
-
/**
|
|
306
|
-
* Unique identifier for a constraint
|
|
307
|
-
*/
|
|
308
|
-
type ConstraintId = string;
|
|
309
|
-
/**
|
|
310
|
-
* A rule function derives new facts or transitions from context + input facts/events.
|
|
311
|
-
* Rules must be pure - no side effects.
|
|
312
|
-
*
|
|
313
|
-
* Returns either:
|
|
314
|
-
* - `RuleResult` (new API — typed, traceable, supports retraction)
|
|
315
|
-
* - `PraxisFact[]` (legacy — backward compatible, will be deprecated)
|
|
316
|
-
*
|
|
317
|
-
* The state parameter includes `events` — the current batch being processed.
|
|
318
|
-
*
|
|
319
|
-
* @param state Current Praxis state (includes state.events for current batch)
|
|
320
|
-
* @param events Events to process (same as state.events, provided for convenience)
|
|
321
|
-
* @returns RuleResult or array of new facts
|
|
322
|
-
*/
|
|
323
|
-
type RuleFn<TContext = unknown> = (state: PraxisState & {
|
|
324
|
-
context: TContext;
|
|
325
|
-
events: PraxisEvent[];
|
|
326
|
-
}, events: PraxisEvent[]) => RuleResult | PraxisFact[];
|
|
327
|
-
/**
|
|
328
|
-
* A constraint function checks that an invariant holds.
|
|
329
|
-
* Constraints must be pure - no side effects.
|
|
330
|
-
*
|
|
331
|
-
* @param state Current Praxis state
|
|
332
|
-
* @returns true if constraint is satisfied, false or error message if violated
|
|
333
|
-
*/
|
|
334
|
-
type ConstraintFn<TContext = unknown> = (state: PraxisState & {
|
|
335
|
-
context: TContext;
|
|
336
|
-
}) => boolean | string;
|
|
337
|
-
/**
|
|
338
|
-
* Descriptor for a rule, including its ID, description, and implementation.
|
|
339
|
-
*/
|
|
340
|
-
interface RuleDescriptor<TContext = unknown> {
|
|
341
|
-
/** Unique identifier for the rule */
|
|
342
|
-
id: RuleId;
|
|
343
|
-
/** Human-readable description */
|
|
344
|
-
description: string;
|
|
345
|
-
/** Implementation function */
|
|
346
|
-
impl: RuleFn<TContext>;
|
|
347
|
-
/**
|
|
348
|
-
* Optional event type filter — only evaluate this rule when at least one
|
|
349
|
-
* event in the batch has a matching `tag`. When omitted, the rule runs on
|
|
350
|
-
* every step (catch-all).
|
|
351
|
-
*
|
|
352
|
-
* Accepts a single tag string or an array of tags.
|
|
353
|
-
*
|
|
354
|
-
* @example
|
|
355
|
-
* { id: 'sprint-behind', eventTypes: ['sprint.update'], impl: ... }
|
|
356
|
-
* { id: 'note-check', eventTypes: 'note.update', impl: ... }
|
|
357
|
-
*/
|
|
358
|
-
eventTypes?: string | string[];
|
|
359
|
-
/** Optional contract for rule behavior */
|
|
360
|
-
contract?: Contract;
|
|
361
|
-
/** Optional metadata */
|
|
362
|
-
meta?: Record<string, unknown>;
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Descriptor for a constraint, including its ID, description, and implementation.
|
|
366
|
-
*/
|
|
367
|
-
interface ConstraintDescriptor<TContext = unknown> {
|
|
368
|
-
/** Unique identifier for the constraint */
|
|
369
|
-
id: ConstraintId;
|
|
370
|
-
/** Human-readable description */
|
|
371
|
-
description: string;
|
|
372
|
-
/** Implementation function */
|
|
373
|
-
impl: ConstraintFn<TContext>;
|
|
374
|
-
/** Optional contract for constraint behavior */
|
|
375
|
-
contract?: Contract;
|
|
376
|
-
/** Optional metadata */
|
|
377
|
-
meta?: Record<string, unknown>;
|
|
378
|
-
}
|
|
379
|
-
/**
|
|
380
|
-
* A Praxis module bundles rules and constraints.
|
|
381
|
-
* Modules can be composed and registered with the engine.
|
|
382
|
-
*/
|
|
383
|
-
interface PraxisModule<TContext = unknown> {
|
|
384
|
-
/** Rules in this module */
|
|
385
|
-
rules: RuleDescriptor<TContext>[];
|
|
386
|
-
/** Constraints in this module */
|
|
387
|
-
constraints: ConstraintDescriptor<TContext>[];
|
|
388
|
-
/** Optional module metadata */
|
|
389
|
-
meta?: Record<string, unknown>;
|
|
390
|
-
}
|
|
391
|
-
/**
|
|
392
|
-
* Compliance validation options for rule/constraint registration.
|
|
393
|
-
*/
|
|
394
|
-
interface RegistryComplianceOptions {
|
|
395
|
-
/** Enable contract checks during registration (default: true in dev) */
|
|
396
|
-
enabled?: boolean;
|
|
397
|
-
/** Required contract fields to be present */
|
|
398
|
-
requiredFields?: Array<'behavior' | 'examples' | 'invariants'>;
|
|
399
|
-
/** Severity to use for missing contracts */
|
|
400
|
-
missingSeverity?: Severity;
|
|
401
|
-
/** Callback for contract gaps (e.g., to emit facts) */
|
|
402
|
-
onGap?: (gap: ContractGap) => void;
|
|
403
|
-
}
|
|
404
|
-
/**
|
|
405
|
-
* PraxisRegistry configuration options.
|
|
406
|
-
*/
|
|
407
|
-
interface PraxisRegistryOptions {
|
|
408
|
-
compliance?: RegistryComplianceOptions;
|
|
409
|
-
}
|
|
410
|
-
/**
|
|
411
|
-
* Registry for rules and constraints.
|
|
412
|
-
* Maps IDs to their descriptors.
|
|
413
|
-
*/
|
|
414
|
-
declare class PraxisRegistry<TContext = unknown> {
|
|
415
|
-
private rules;
|
|
416
|
-
private constraints;
|
|
417
|
-
private readonly compliance;
|
|
418
|
-
private contractGaps;
|
|
419
|
-
constructor(options?: PraxisRegistryOptions);
|
|
420
|
-
/**
|
|
421
|
-
* Register a rule
|
|
422
|
-
*/
|
|
423
|
-
registerRule(descriptor: RuleDescriptor<TContext>): void;
|
|
424
|
-
/**
|
|
425
|
-
* Register a constraint
|
|
426
|
-
*/
|
|
427
|
-
registerConstraint(descriptor: ConstraintDescriptor<TContext>): void;
|
|
428
|
-
/**
|
|
429
|
-
* Register a module (all its rules and constraints)
|
|
430
|
-
*/
|
|
431
|
-
registerModule(module: PraxisModule<TContext>): void;
|
|
432
|
-
/**
|
|
433
|
-
* Get a rule by ID
|
|
434
|
-
*/
|
|
435
|
-
getRule(id: RuleId): RuleDescriptor<TContext> | undefined;
|
|
436
|
-
/**
|
|
437
|
-
* Get a constraint by ID
|
|
438
|
-
*/
|
|
439
|
-
getConstraint(id: ConstraintId): ConstraintDescriptor<TContext> | undefined;
|
|
440
|
-
/**
|
|
441
|
-
* Get all registered rule IDs
|
|
442
|
-
*/
|
|
443
|
-
getRuleIds(): RuleId[];
|
|
444
|
-
/**
|
|
445
|
-
* Get all registered constraint IDs
|
|
446
|
-
*/
|
|
447
|
-
getConstraintIds(): ConstraintId[];
|
|
448
|
-
/**
|
|
449
|
-
* Get all rules
|
|
450
|
-
*/
|
|
451
|
-
getAllRules(): RuleDescriptor<TContext>[];
|
|
452
|
-
/**
|
|
453
|
-
* Get all constraints
|
|
454
|
-
*/
|
|
455
|
-
getAllConstraints(): ConstraintDescriptor<TContext>[];
|
|
456
|
-
/**
|
|
457
|
-
* Get collected contract gaps from registration-time validation.
|
|
458
|
-
*/
|
|
459
|
-
getContractGaps(): ContractGap[];
|
|
460
|
-
/**
|
|
461
|
-
* Clear collected contract gaps.
|
|
462
|
-
*/
|
|
463
|
-
clearContractGaps(): void;
|
|
464
|
-
private trackContractCompliance;
|
|
465
|
-
private validateDescriptorContract;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
/**
|
|
469
|
-
* Praxis Logic Engine
|
|
470
|
-
*
|
|
471
|
-
* The logic engine manages state, processes events through rules,
|
|
472
|
-
* checks constraints, and provides a strongly-typed API for application logic.
|
|
473
|
-
*/
|
|
474
|
-
|
|
475
|
-
/**
|
|
476
|
-
* Options for creating a Praxis engine
|
|
477
|
-
*/
|
|
478
|
-
interface PraxisEngineOptions<TContext = unknown> {
|
|
479
|
-
/** Initial context */
|
|
480
|
-
initialContext: TContext;
|
|
481
|
-
/** Registry of rules and constraints */
|
|
482
|
-
registry: PraxisRegistry<TContext>;
|
|
483
|
-
/** Initial facts (optional) */
|
|
484
|
-
initialFacts?: PraxisFact[];
|
|
485
|
-
/** Initial metadata (optional) */
|
|
486
|
-
initialMeta?: Record<string, unknown>;
|
|
487
|
-
/**
|
|
488
|
-
* Fact deduplication strategy (default: 'last-write-wins').
|
|
489
|
-
*
|
|
490
|
-
* - 'none': facts accumulate without dedup (original behavior)
|
|
491
|
-
* - 'last-write-wins': only keep the latest fact per tag (most common)
|
|
492
|
-
* - 'append': keep all facts but cap at maxFacts
|
|
493
|
-
*/
|
|
494
|
-
factDedup?: 'none' | 'last-write-wins' | 'append';
|
|
495
|
-
/**
|
|
496
|
-
* Maximum number of facts to retain (default: 1000).
|
|
497
|
-
* When exceeded, oldest facts are evicted (FIFO).
|
|
498
|
-
* Set to 0 for unlimited (not recommended).
|
|
499
|
-
*/
|
|
500
|
-
maxFacts?: number;
|
|
501
|
-
}
|
|
502
|
-
/**
|
|
503
|
-
* The Praxis Logic Engine
|
|
504
|
-
*
|
|
505
|
-
* Manages application logic through facts, events, rules, and constraints.
|
|
506
|
-
* The engine is strongly typed and functional - all state updates are immutable.
|
|
507
|
-
*/
|
|
508
|
-
declare class LogicEngine<TContext = unknown> {
|
|
509
|
-
private state;
|
|
510
|
-
private readonly registry;
|
|
511
|
-
private readonly factDedup;
|
|
512
|
-
private readonly maxFacts;
|
|
513
|
-
constructor(options: PraxisEngineOptions<TContext>);
|
|
514
|
-
/**
|
|
515
|
-
* Get the current state (immutable copy)
|
|
516
|
-
*/
|
|
517
|
-
getState(): Readonly<PraxisState & {
|
|
518
|
-
context: TContext;
|
|
519
|
-
}>;
|
|
520
|
-
/**
|
|
521
|
-
* Get the current context
|
|
522
|
-
*/
|
|
523
|
-
getContext(): TContext;
|
|
524
|
-
/**
|
|
525
|
-
* Get current facts
|
|
526
|
-
*/
|
|
527
|
-
getFacts(): PraxisFact[];
|
|
528
|
-
/**
|
|
529
|
-
* Process events through the engine.
|
|
530
|
-
* Applies all registered rules and checks all registered constraints.
|
|
531
|
-
*
|
|
532
|
-
* @param events Events to process
|
|
533
|
-
* @returns Result with new state and diagnostics
|
|
534
|
-
*/
|
|
535
|
-
step(events: PraxisEvent[]): PraxisStepResult;
|
|
536
|
-
/**
|
|
537
|
-
* Process events with specific rule and constraint configuration.
|
|
538
|
-
*
|
|
539
|
-
* @param events Events to process
|
|
540
|
-
* @param config Step configuration
|
|
541
|
-
* @returns Result with new state and diagnostics
|
|
542
|
-
*/
|
|
543
|
-
stepWithConfig(events: PraxisEvent[], config: PraxisStepConfig): PraxisStepResult;
|
|
544
|
-
/**
|
|
545
|
-
* Update the context directly (for exceptional cases).
|
|
546
|
-
* Generally, context should be updated through rules.
|
|
547
|
-
*
|
|
548
|
-
* @param updater Function that produces new context from old context
|
|
549
|
-
*/
|
|
550
|
-
updateContext(updater: (context: TContext) => TContext): void;
|
|
551
|
-
/**
|
|
552
|
-
* Atomically update context AND process events in a single call.
|
|
553
|
-
*
|
|
554
|
-
* This avoids the fragile pattern of calling updateContext() then step()
|
|
555
|
-
* separately, where rules could see stale context if the ordering is wrong.
|
|
556
|
-
*
|
|
557
|
-
* @param updater Function that produces new context from old context
|
|
558
|
-
* @param events Events to process after context is updated
|
|
559
|
-
* @returns Result with new state and diagnostics
|
|
560
|
-
*
|
|
561
|
-
* @example
|
|
562
|
-
* engine.stepWithContext(
|
|
563
|
-
* ctx => ({ ...ctx, sprintName: sprint.name, items: sprint.items }),
|
|
564
|
-
* [{ tag: 'sprint.update', payload: { name: sprint.name } }]
|
|
565
|
-
* );
|
|
566
|
-
*/
|
|
567
|
-
stepWithContext(updater: (context: TContext) => TContext, events: PraxisEvent[]): PraxisStepResult;
|
|
568
|
-
/**
|
|
569
|
-
* Add facts directly (for exceptional cases).
|
|
570
|
-
* Generally, facts should be added through rules.
|
|
571
|
-
*
|
|
572
|
-
* @param facts Facts to add
|
|
573
|
-
*/
|
|
574
|
-
addFacts(facts: PraxisFact[]): void;
|
|
575
|
-
/**
|
|
576
|
-
* Check all constraints without processing any events.
|
|
577
|
-
*
|
|
578
|
-
* Useful for validation-only scenarios (e.g., form validation,
|
|
579
|
-
* pre-save checks) where you want constraint diagnostics without
|
|
580
|
-
* triggering any rules.
|
|
581
|
-
*
|
|
582
|
-
* @returns Array of constraint violation diagnostics (empty = all passing)
|
|
583
|
-
*/
|
|
584
|
-
checkConstraints(): PraxisDiagnostics[];
|
|
585
|
-
/**
|
|
586
|
-
* Clear all facts
|
|
587
|
-
*/
|
|
588
|
-
clearFacts(): void;
|
|
589
|
-
/**
|
|
590
|
-
* Reset the engine to initial state
|
|
591
|
-
*/
|
|
592
|
-
reset(options: PraxisEngineOptions<TContext>): void;
|
|
593
|
-
}
|
|
594
|
-
/**
|
|
595
|
-
* Create a new Praxis logic engine.
|
|
596
|
-
*
|
|
597
|
-
* @param options Engine options
|
|
598
|
-
* @returns New LogicEngine instance
|
|
599
|
-
*/
|
|
600
|
-
declare function createPraxisEngine<TContext = unknown>(options: PraxisEngineOptions<TContext>): LogicEngine<TContext>;
|
|
601
|
-
|
|
602
|
-
/**
|
|
603
|
-
* Praxis Reactive Logic Engine - Svelte 5 Implementation
|
|
604
|
-
*
|
|
605
|
-
* This version uses Svelte 5 runes ($state) for built-in reactivity.
|
|
606
|
-
* The state object is automatically reactive when used in Svelte components.
|
|
607
|
-
*/
|
|
608
|
-
|
|
609
|
-
interface ReactiveEngineOptions<TContext> {
|
|
610
|
-
initialContext: TContext;
|
|
611
|
-
initialFacts?: any[];
|
|
612
|
-
initialMeta?: Record<string, unknown>;
|
|
613
|
-
registry?: PraxisRegistry<TContext>;
|
|
614
|
-
}
|
|
615
|
-
/**
|
|
616
|
-
* Reactive Logic Engine using Svelte 5 runes.
|
|
617
|
-
* Combines the standard LogicEngine with reactive state management.
|
|
618
|
-
*/
|
|
619
|
-
declare class ReactiveLogicEngine<TContext extends object> {
|
|
620
|
-
state: {
|
|
621
|
-
context: TContext;
|
|
622
|
-
facts: any[];
|
|
623
|
-
meta: Record<string, unknown>;
|
|
624
|
-
};
|
|
625
|
-
private _engine;
|
|
626
|
-
constructor(options: ReactiveEngineOptions<TContext>);
|
|
627
|
-
/**
|
|
628
|
-
* Access the reactive context.
|
|
629
|
-
* In Svelte 5 components, changes to this object will automatically trigger updates.
|
|
630
|
-
*/
|
|
631
|
-
get context(): TContext;
|
|
632
|
-
/**
|
|
633
|
-
* Access the reactive facts list.
|
|
634
|
-
*/
|
|
635
|
-
get facts(): any[];
|
|
636
|
-
/**
|
|
637
|
-
* Access the reactive metadata.
|
|
638
|
-
*/
|
|
639
|
-
get meta(): Record<string, unknown>;
|
|
640
|
-
/**
|
|
641
|
-
* Apply a mutation to the state.
|
|
642
|
-
* Changes will automatically trigger Svelte reactivity.
|
|
643
|
-
*
|
|
644
|
-
* @param mutator A function that receives the state and modifies it.
|
|
645
|
-
*/
|
|
646
|
-
apply(mutator: (state: {
|
|
647
|
-
context: TContext;
|
|
648
|
-
facts: any[];
|
|
649
|
-
meta: Record<string, unknown>;
|
|
650
|
-
}) => void): void;
|
|
651
|
-
/**
|
|
652
|
-
* Process events through the logic engine and update reactive state.
|
|
653
|
-
*
|
|
654
|
-
* @param events Events to process
|
|
655
|
-
*/
|
|
656
|
-
step(events: PraxisEvent[]): void;
|
|
657
|
-
}
|
|
658
|
-
/**
|
|
659
|
-
* Create a reactive logic engine with Svelte 5 runes.
|
|
660
|
-
*
|
|
661
|
-
* @param options Configuration options
|
|
662
|
-
* @returns A reactive logic engine instance
|
|
663
|
-
*
|
|
664
|
-
* @example
|
|
665
|
-
* ```svelte
|
|
666
|
-
* <script lang="ts">
|
|
667
|
-
* import { createReactiveEngine } from '@plures/praxis/svelte';
|
|
668
|
-
*
|
|
669
|
-
* const engine = createReactiveEngine({
|
|
670
|
-
* initialContext: { count: 0 },
|
|
671
|
-
* registry
|
|
672
|
-
* });
|
|
673
|
-
*
|
|
674
|
-
* // Use $derived for computed values
|
|
675
|
-
* const count = $derived(engine.context.count);
|
|
676
|
-
* const doubled = $derived(engine.context.count * 2);
|
|
677
|
-
*
|
|
678
|
-
* function increment() {
|
|
679
|
-
* engine.step([Increment.create({ amount: 1 })]);
|
|
680
|
-
* }
|
|
681
|
-
* </script>
|
|
682
|
-
*
|
|
683
|
-
* <button on:click={increment}>Count: {count}, Doubled: {doubled}</button>
|
|
684
|
-
* ```
|
|
685
|
-
*/
|
|
686
|
-
declare function createReactiveEngine<TContext extends object>(options: ReactiveEngineOptions<TContext>): ReactiveLogicEngine<TContext>;
|
|
687
|
-
|
|
688
|
-
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 };
|