@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
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { P as PraxisState, a as PraxisEvent, R as RuleResult, b as PraxisFact } from './rule-result-DcXWe9tn.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Decision Ledger - Contract Types
|
|
5
|
+
*
|
|
6
|
+
* Types for defining and validating contracts for rules and constraints.
|
|
7
|
+
* All types are JSON-serializable for cross-language compatibility.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* A single assumption made during contract definition.
|
|
11
|
+
*/
|
|
12
|
+
interface Assumption {
|
|
13
|
+
/** Stable unique identifier for the assumption */
|
|
14
|
+
id: string;
|
|
15
|
+
/** The assumption statement */
|
|
16
|
+
statement: string;
|
|
17
|
+
/** Confidence level (0.0 to 1.0) */
|
|
18
|
+
confidence: number;
|
|
19
|
+
/** Justification for the assumption */
|
|
20
|
+
justification: string;
|
|
21
|
+
/** What this assumption was derived from */
|
|
22
|
+
derivedFrom?: string;
|
|
23
|
+
/** What artifacts this assumption impacts */
|
|
24
|
+
impacts: Array<'spec' | 'tests' | 'code'>;
|
|
25
|
+
/** Current status of the assumption */
|
|
26
|
+
status: 'active' | 'revised' | 'invalidated';
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A reference to external documentation or resources.
|
|
30
|
+
*/
|
|
31
|
+
interface Reference {
|
|
32
|
+
/** Type of reference (e.g., 'doc', 'ticket', 'issue') */
|
|
33
|
+
type: string;
|
|
34
|
+
/** URL to the reference */
|
|
35
|
+
url?: string;
|
|
36
|
+
/** Human-readable description */
|
|
37
|
+
description?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A Given/When/Then example for a contract.
|
|
41
|
+
*/
|
|
42
|
+
interface Example {
|
|
43
|
+
/** Initial state or preconditions */
|
|
44
|
+
given: string;
|
|
45
|
+
/** Triggering event or action */
|
|
46
|
+
when: string;
|
|
47
|
+
/** Expected outcome or postconditions */
|
|
48
|
+
then: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Contract for a rule or constraint.
|
|
52
|
+
* Documents the expected behavior, test cases, invariants, and assumptions.
|
|
53
|
+
*/
|
|
54
|
+
interface Contract {
|
|
55
|
+
/** ID of the rule or constraint this contract applies to */
|
|
56
|
+
ruleId: string;
|
|
57
|
+
/** Canonical behavior description */
|
|
58
|
+
behavior: string;
|
|
59
|
+
/** Given/When/Then examples (become test vectors) */
|
|
60
|
+
examples: Example[];
|
|
61
|
+
/** TLA+-friendly invariants or Praxis-level invariants */
|
|
62
|
+
invariants: string[];
|
|
63
|
+
/** Explicit assumptions with confidence levels */
|
|
64
|
+
assumptions?: Assumption[];
|
|
65
|
+
/** References to docs, tickets, links */
|
|
66
|
+
references?: Reference[];
|
|
67
|
+
/** Contract version (for evolution tracking) */
|
|
68
|
+
version?: string;
|
|
69
|
+
/** Timestamp of contract creation */
|
|
70
|
+
timestamp?: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Severity levels for contract gaps.
|
|
74
|
+
*/
|
|
75
|
+
type Severity = 'warning' | 'error' | 'info';
|
|
76
|
+
/**
|
|
77
|
+
* Types of missing contract artifacts.
|
|
78
|
+
*/
|
|
79
|
+
/**
|
|
80
|
+
* Types of artifacts that can be missing from a contract.
|
|
81
|
+
*
|
|
82
|
+
* Note: 'tests' and 'spec' are included in this type for future extensibility
|
|
83
|
+
* and SARIF reporting compatibility, but are not currently validated by the
|
|
84
|
+
* validateContract function. To check for these, implement custom validation
|
|
85
|
+
* logic that scans for test files or spec files in your codebase.
|
|
86
|
+
*/
|
|
87
|
+
type MissingArtifact = 'behavior' | 'examples' | 'invariants' | 'tests' | 'spec' | 'contract';
|
|
88
|
+
/**
|
|
89
|
+
* A gap in contract coverage.
|
|
90
|
+
*/
|
|
91
|
+
interface ContractGap {
|
|
92
|
+
/** ID of the rule or constraint */
|
|
93
|
+
ruleId: string;
|
|
94
|
+
/** What is missing */
|
|
95
|
+
missing: MissingArtifact[];
|
|
96
|
+
/** Severity of the gap */
|
|
97
|
+
severity: Severity;
|
|
98
|
+
/** Optional human-readable message */
|
|
99
|
+
message?: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Rules and Constraints System
|
|
104
|
+
*
|
|
105
|
+
* This module defines the types and registry for rules and constraints.
|
|
106
|
+
* Rules and constraints are identified by stable IDs and can be described as data,
|
|
107
|
+
* making them portable across languages and suitable for DSL-based definitions.
|
|
108
|
+
*/
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Unique identifier for a rule
|
|
112
|
+
*/
|
|
113
|
+
type RuleId = string;
|
|
114
|
+
/**
|
|
115
|
+
* Unique identifier for a constraint
|
|
116
|
+
*/
|
|
117
|
+
type ConstraintId = string;
|
|
118
|
+
/**
|
|
119
|
+
* A rule function derives new facts or transitions from context + input facts/events.
|
|
120
|
+
* Rules must be pure - no side effects.
|
|
121
|
+
*
|
|
122
|
+
* Returns either:
|
|
123
|
+
* - `RuleResult` (new API — typed, traceable, supports retraction)
|
|
124
|
+
* - `PraxisFact[]` (legacy — backward compatible, will be deprecated)
|
|
125
|
+
*
|
|
126
|
+
* The state parameter includes `events` — the current batch being processed.
|
|
127
|
+
*
|
|
128
|
+
* @param state Current Praxis state (includes state.events for current batch)
|
|
129
|
+
* @param events Events to process (same as state.events, provided for convenience)
|
|
130
|
+
* @returns RuleResult or array of new facts
|
|
131
|
+
*/
|
|
132
|
+
type RuleFn<TContext = unknown> = (state: PraxisState & {
|
|
133
|
+
context: TContext;
|
|
134
|
+
events: PraxisEvent[];
|
|
135
|
+
}, events: PraxisEvent[]) => RuleResult | PraxisFact[];
|
|
136
|
+
/**
|
|
137
|
+
* A constraint function checks that an invariant holds.
|
|
138
|
+
* Constraints must be pure - no side effects.
|
|
139
|
+
*
|
|
140
|
+
* @param state Current Praxis state
|
|
141
|
+
* @returns true if constraint is satisfied, false or error message if violated
|
|
142
|
+
*/
|
|
143
|
+
type ConstraintFn<TContext = unknown> = (state: PraxisState & {
|
|
144
|
+
context: TContext;
|
|
145
|
+
}) => boolean | string;
|
|
146
|
+
/**
|
|
147
|
+
* Descriptor for a rule, including its ID, description, and implementation.
|
|
148
|
+
*/
|
|
149
|
+
interface RuleDescriptor<TContext = unknown> {
|
|
150
|
+
/** Unique identifier for the rule */
|
|
151
|
+
id: RuleId;
|
|
152
|
+
/** Human-readable description */
|
|
153
|
+
description: string;
|
|
154
|
+
/** Implementation function */
|
|
155
|
+
impl: RuleFn<TContext>;
|
|
156
|
+
/**
|
|
157
|
+
* Optional event type filter — only evaluate this rule when at least one
|
|
158
|
+
* event in the batch has a matching `tag`. When omitted, the rule runs on
|
|
159
|
+
* every step (catch-all).
|
|
160
|
+
*
|
|
161
|
+
* Accepts a single tag string or an array of tags.
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* { id: 'sprint-behind', eventTypes: ['sprint.update'], impl: ... }
|
|
165
|
+
* { id: 'note-check', eventTypes: 'note.update', impl: ... }
|
|
166
|
+
*/
|
|
167
|
+
eventTypes?: string | string[];
|
|
168
|
+
/** Optional contract for rule behavior */
|
|
169
|
+
contract?: Contract;
|
|
170
|
+
/** Optional metadata */
|
|
171
|
+
meta?: Record<string, unknown>;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Descriptor for a constraint, including its ID, description, and implementation.
|
|
175
|
+
*/
|
|
176
|
+
interface ConstraintDescriptor<TContext = unknown> {
|
|
177
|
+
/** Unique identifier for the constraint */
|
|
178
|
+
id: ConstraintId;
|
|
179
|
+
/** Human-readable description */
|
|
180
|
+
description: string;
|
|
181
|
+
/** Implementation function */
|
|
182
|
+
impl: ConstraintFn<TContext>;
|
|
183
|
+
/** Optional contract for constraint behavior */
|
|
184
|
+
contract?: Contract;
|
|
185
|
+
/** Optional metadata */
|
|
186
|
+
meta?: Record<string, unknown>;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* A Praxis module bundles rules and constraints.
|
|
190
|
+
* Modules can be composed and registered with the engine.
|
|
191
|
+
*/
|
|
192
|
+
interface PraxisModule<TContext = unknown> {
|
|
193
|
+
/** Rules in this module */
|
|
194
|
+
rules: RuleDescriptor<TContext>[];
|
|
195
|
+
/** Constraints in this module */
|
|
196
|
+
constraints: ConstraintDescriptor<TContext>[];
|
|
197
|
+
/** Optional module metadata */
|
|
198
|
+
meta?: Record<string, unknown>;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Compliance validation options for rule/constraint registration.
|
|
202
|
+
*/
|
|
203
|
+
interface RegistryComplianceOptions {
|
|
204
|
+
/** Enable contract checks during registration (default: true in dev) */
|
|
205
|
+
enabled?: boolean;
|
|
206
|
+
/** Required contract fields to be present */
|
|
207
|
+
requiredFields?: Array<'behavior' | 'examples' | 'invariants'>;
|
|
208
|
+
/** Severity to use for missing contracts */
|
|
209
|
+
missingSeverity?: Severity;
|
|
210
|
+
/** Callback for contract gaps (e.g., to emit facts) */
|
|
211
|
+
onGap?: (gap: ContractGap) => void;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* PraxisRegistry configuration options.
|
|
215
|
+
*/
|
|
216
|
+
interface PraxisRegistryOptions {
|
|
217
|
+
compliance?: RegistryComplianceOptions;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Registry for rules and constraints.
|
|
221
|
+
* Maps IDs to their descriptors.
|
|
222
|
+
*/
|
|
223
|
+
declare class PraxisRegistry<TContext = unknown> {
|
|
224
|
+
private rules;
|
|
225
|
+
private constraints;
|
|
226
|
+
private readonly compliance;
|
|
227
|
+
private contractGaps;
|
|
228
|
+
constructor(options?: PraxisRegistryOptions);
|
|
229
|
+
/**
|
|
230
|
+
* Register a rule
|
|
231
|
+
*/
|
|
232
|
+
registerRule(descriptor: RuleDescriptor<TContext>): void;
|
|
233
|
+
/**
|
|
234
|
+
* Register a constraint
|
|
235
|
+
*/
|
|
236
|
+
registerConstraint(descriptor: ConstraintDescriptor<TContext>): void;
|
|
237
|
+
/**
|
|
238
|
+
* Register a module (all its rules and constraints)
|
|
239
|
+
*/
|
|
240
|
+
registerModule(module: PraxisModule<TContext>): void;
|
|
241
|
+
/**
|
|
242
|
+
* Get a rule by ID
|
|
243
|
+
*/
|
|
244
|
+
getRule(id: RuleId): RuleDescriptor<TContext> | undefined;
|
|
245
|
+
/**
|
|
246
|
+
* Get a constraint by ID
|
|
247
|
+
*/
|
|
248
|
+
getConstraint(id: ConstraintId): ConstraintDescriptor<TContext> | undefined;
|
|
249
|
+
/**
|
|
250
|
+
* Get all registered rule IDs
|
|
251
|
+
*/
|
|
252
|
+
getRuleIds(): RuleId[];
|
|
253
|
+
/**
|
|
254
|
+
* Get all registered constraint IDs
|
|
255
|
+
*/
|
|
256
|
+
getConstraintIds(): ConstraintId[];
|
|
257
|
+
/**
|
|
258
|
+
* Get all rules
|
|
259
|
+
*/
|
|
260
|
+
getAllRules(): RuleDescriptor<TContext>[];
|
|
261
|
+
/**
|
|
262
|
+
* Get all constraints
|
|
263
|
+
*/
|
|
264
|
+
getAllConstraints(): ConstraintDescriptor<TContext>[];
|
|
265
|
+
/**
|
|
266
|
+
* Get collected contract gaps from registration-time validation.
|
|
267
|
+
*/
|
|
268
|
+
getContractGaps(): ContractGap[];
|
|
269
|
+
/**
|
|
270
|
+
* Clear collected contract gaps.
|
|
271
|
+
*/
|
|
272
|
+
clearContractGaps(): void;
|
|
273
|
+
private trackContractCompliance;
|
|
274
|
+
private validateDescriptorContract;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export { type ConstraintDescriptor as C, PraxisRegistry as P, type RuleDescriptor as R, type ConstraintFn as a, type Contract as b, type RuleFn as c, type PraxisModule as d, type ConstraintId as e, type RuleId as f };
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { e as PraxisDiagnostics, b as PraxisFact, R as RuleResult } from '../rule-result-DcXWe9tn.js';
|
|
2
|
+
export { h as fact } from '../rule-result-DcXWe9tn.js';
|
|
3
|
+
|
|
4
|
+
/** Minimal store contract — anything with subscribe() */
|
|
5
|
+
interface Subscribable<T> {
|
|
6
|
+
subscribe(cb: (value: T) => void): (() => void) | {
|
|
7
|
+
unsubscribe(): void;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/** Schema definition for a graph path */
|
|
11
|
+
interface PathSchema<T = unknown> {
|
|
12
|
+
/** The graph path (e.g., 'sprint/current') */
|
|
13
|
+
path: string;
|
|
14
|
+
/** Default/initial value */
|
|
15
|
+
initial: T;
|
|
16
|
+
/** Optional TTL for staleness detection (ms) */
|
|
17
|
+
staleTtl?: number;
|
|
18
|
+
/** Whether this path is a collection (maps over children) */
|
|
19
|
+
collection?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Define a typed graph path.
|
|
23
|
+
* This is the primary API for declaring what data exists in your app.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const Sprint = definePath<SprintInfo | null>('sprint/current', null);
|
|
27
|
+
* const Items = definePath<WorkItem[]>('sprint/items', [], { collection: true });
|
|
28
|
+
* const Loading = definePath<boolean>('sprint/loading', false);
|
|
29
|
+
*/
|
|
30
|
+
declare function definePath<T>(path: string, initial: T, opts?: Omit<PathSchema<T>, 'path' | 'initial'>): PathSchema<T>;
|
|
31
|
+
interface QueryOptions<T> {
|
|
32
|
+
/** Filter function for collections */
|
|
33
|
+
where?: (item: T extends (infer U)[] ? U : T) => boolean;
|
|
34
|
+
/** Select/map function */
|
|
35
|
+
select?: (item: T) => unknown;
|
|
36
|
+
/** Sort comparator */
|
|
37
|
+
sort?: (a: any, b: any) => number;
|
|
38
|
+
/** Limit results */
|
|
39
|
+
limit?: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A reactive reference returned by query().
|
|
43
|
+
* Has a Svelte-compatible subscribe() and a .current getter.
|
|
44
|
+
*/
|
|
45
|
+
interface ReactiveRef<T> extends Subscribable<T> {
|
|
46
|
+
/** Current value (synchronous read) */
|
|
47
|
+
readonly current: T;
|
|
48
|
+
/** Svelte store contract — subscribe returns unsubscribe fn */
|
|
49
|
+
subscribe(cb: (value: T) => void): () => void;
|
|
50
|
+
}
|
|
51
|
+
interface MutationResult {
|
|
52
|
+
/** Whether the mutation was accepted */
|
|
53
|
+
accepted: boolean;
|
|
54
|
+
/** Constraint violations that blocked the mutation (if any) */
|
|
55
|
+
violations: PraxisDiagnostics[];
|
|
56
|
+
/** Facts emitted by rules triggered by this mutation */
|
|
57
|
+
facts: PraxisFact[];
|
|
58
|
+
}
|
|
59
|
+
interface UnifiedRule {
|
|
60
|
+
/** Unique rule ID */
|
|
61
|
+
id: string;
|
|
62
|
+
/** Human-readable description */
|
|
63
|
+
description?: string;
|
|
64
|
+
/** Graph paths this rule watches — auto-subscribed */
|
|
65
|
+
watch: string[];
|
|
66
|
+
/** Rule evaluation function — receives watched values by path */
|
|
67
|
+
evaluate: (values: Record<string, any>, facts: PraxisFact[]) => RuleResult;
|
|
68
|
+
}
|
|
69
|
+
interface UnifiedConstraint {
|
|
70
|
+
/** Unique constraint ID */
|
|
71
|
+
id: string;
|
|
72
|
+
/** Human-readable description */
|
|
73
|
+
description?: string;
|
|
74
|
+
/** Graph paths this constraint reads */
|
|
75
|
+
watch: string[];
|
|
76
|
+
/** Validation function — return true if valid, string if violated */
|
|
77
|
+
validate: (values: Record<string, any>) => true | string;
|
|
78
|
+
}
|
|
79
|
+
interface LivenessConfig {
|
|
80
|
+
/** Paths that must update within `timeoutMs` after init */
|
|
81
|
+
expect: string[];
|
|
82
|
+
/** Milliseconds to wait before flagging staleness (default: 5000) */
|
|
83
|
+
timeoutMs?: number;
|
|
84
|
+
/** Callback when a path is stale */
|
|
85
|
+
onStale?: (path: string, elapsed: number) => void;
|
|
86
|
+
}
|
|
87
|
+
interface PraxisAppConfig {
|
|
88
|
+
/** App name (used in Chronos context) */
|
|
89
|
+
name: string;
|
|
90
|
+
/** Graph schema — all paths the app uses */
|
|
91
|
+
schema: PathSchema[];
|
|
92
|
+
/** Business rules */
|
|
93
|
+
rules?: UnifiedRule[];
|
|
94
|
+
/** Constraints */
|
|
95
|
+
constraints?: UnifiedConstraint[];
|
|
96
|
+
/** Liveness monitoring */
|
|
97
|
+
liveness?: LivenessConfig;
|
|
98
|
+
/** Chronos options */
|
|
99
|
+
chronos?: {
|
|
100
|
+
batchMs?: number;
|
|
101
|
+
maxBatch?: number;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Praxis Unified Reactive Layer — Core
|
|
107
|
+
*
|
|
108
|
+
* createApp() → query() / mutate()
|
|
109
|
+
*
|
|
110
|
+
* The developer defines a schema + rules. Praxis handles:
|
|
111
|
+
* - Reactive state (backed by Unum graph DB)
|
|
112
|
+
* - Automatic rule evaluation on state changes
|
|
113
|
+
* - Constraint enforcement on mutations
|
|
114
|
+
* - Chronos logging for every state change
|
|
115
|
+
* - Liveness monitoring (detect broken plumbing)
|
|
116
|
+
* - Svelte-compatible store contract
|
|
117
|
+
*/
|
|
118
|
+
|
|
119
|
+
interface TimelineEntry {
|
|
120
|
+
id: string;
|
|
121
|
+
timestamp: number;
|
|
122
|
+
path: string;
|
|
123
|
+
kind: 'mutation' | 'rule-eval' | 'constraint-check' | 'liveness';
|
|
124
|
+
data: Record<string, unknown>;
|
|
125
|
+
}
|
|
126
|
+
interface PraxisApp {
|
|
127
|
+
/** Reactive query — returns a Svelte-compatible store */
|
|
128
|
+
query: <T>(path: string, opts?: QueryOptions<T>) => ReactiveRef<T>;
|
|
129
|
+
/** Write to the graph — validates through constraints first */
|
|
130
|
+
mutate: (path: string, value: unknown) => MutationResult;
|
|
131
|
+
/** Batch multiple mutations atomically */
|
|
132
|
+
batch: (fn: (mutate: (path: string, value: unknown) => void) => void) => MutationResult;
|
|
133
|
+
/** Current facts */
|
|
134
|
+
facts: () => PraxisFact[];
|
|
135
|
+
/** Current constraint violations */
|
|
136
|
+
violations: () => PraxisDiagnostics[];
|
|
137
|
+
/** Timeline (Chronos entries) */
|
|
138
|
+
timeline: () => TimelineEntry[];
|
|
139
|
+
/** Force re-evaluate all rules */
|
|
140
|
+
evaluate: () => void;
|
|
141
|
+
/** Cleanup */
|
|
142
|
+
destroy: () => void;
|
|
143
|
+
/** Liveness status — which paths are stale */
|
|
144
|
+
liveness: () => Record<string, {
|
|
145
|
+
stale: boolean;
|
|
146
|
+
lastUpdated: number;
|
|
147
|
+
elapsed: number;
|
|
148
|
+
}>;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Create a Praxis application.
|
|
152
|
+
*
|
|
153
|
+
* This is the single entry point. It creates the reactive graph,
|
|
154
|
+
* wires rules and constraints, starts Chronos logging, and returns
|
|
155
|
+
* query() and mutate() — the only two functions a developer needs.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```ts
|
|
159
|
+
* import { createApp, definePath, defineRule } from '@plures/praxis';
|
|
160
|
+
*
|
|
161
|
+
* const Sprint = definePath<SprintInfo | null>('sprint/current', null);
|
|
162
|
+
* const Loading = definePath<boolean>('sprint/loading', false);
|
|
163
|
+
*
|
|
164
|
+
* const app = createApp({
|
|
165
|
+
* name: 'sprint-log',
|
|
166
|
+
* schema: [Sprint, Loading],
|
|
167
|
+
* rules: [sprintBehindRule, capacityRule],
|
|
168
|
+
* constraints: [noCloseWithoutHoursConstraint],
|
|
169
|
+
* });
|
|
170
|
+
*
|
|
171
|
+
* // In a Svelte component:
|
|
172
|
+
* const sprint = app.query<SprintInfo | null>('sprint/current');
|
|
173
|
+
* // $sprint is reactive — updates automatically
|
|
174
|
+
*
|
|
175
|
+
* // To write:
|
|
176
|
+
* app.mutate('sprint/current', sprintData);
|
|
177
|
+
* // Constraints validated, rules re-evaluated, Chronos logged — all automatic
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
declare function createApp(config: PraxisAppConfig): PraxisApp;
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Praxis Unified — Rule DSL helpers
|
|
184
|
+
*
|
|
185
|
+
* Developers define rules as plain objects with watch paths.
|
|
186
|
+
* No manual subscriptions, no wirePraxis(), no context mapping.
|
|
187
|
+
*/
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Define a rule that watches graph paths and auto-evaluates.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* const sprintBehind = defineRule({
|
|
194
|
+
* id: 'sprint.behind',
|
|
195
|
+
* watch: ['sprint/current'],
|
|
196
|
+
* evaluate: (values) => {
|
|
197
|
+
* const sprint = values['sprint/current'];
|
|
198
|
+
* if (!sprint) return RuleResult.skip('No sprint');
|
|
199
|
+
* const pace = sprint.currentDay / sprint.totalDays;
|
|
200
|
+
* const work = sprint.completedHours / sprint.totalHours;
|
|
201
|
+
* if (work >= pace) return RuleResult.retract(['sprint.behind']);
|
|
202
|
+
* return RuleResult.emit([fact('sprint.behind', { pace, work })]);
|
|
203
|
+
* }
|
|
204
|
+
* });
|
|
205
|
+
*/
|
|
206
|
+
declare function defineRule(rule: UnifiedRule): UnifiedRule;
|
|
207
|
+
/**
|
|
208
|
+
* Define a constraint that validates mutations before they're applied.
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* const noCloseWithoutHours = defineConstraint({
|
|
212
|
+
* id: 'no-close-without-hours',
|
|
213
|
+
* description: 'Cannot close a work item with 0 completed hours',
|
|
214
|
+
* watch: ['sprint/items'],
|
|
215
|
+
* validate: (values) => {
|
|
216
|
+
* const items = values['sprint/items'] ?? [];
|
|
217
|
+
* const bad = items.find(i => i.state === 'Closed' && !i.completedWork);
|
|
218
|
+
* if (bad) return `Item #${bad.id} cannot be closed with 0 hours`;
|
|
219
|
+
* return true;
|
|
220
|
+
* }
|
|
221
|
+
* });
|
|
222
|
+
*/
|
|
223
|
+
declare function defineConstraint(constraint: UnifiedConstraint): UnifiedConstraint;
|
|
224
|
+
/**
|
|
225
|
+
* Compose multiple rules into a named module.
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* const sprintModule = defineModule('sprint-health', [
|
|
229
|
+
* sprintBehindRule,
|
|
230
|
+
* capacityRule,
|
|
231
|
+
* endNearRule,
|
|
232
|
+
* ]);
|
|
233
|
+
*/
|
|
234
|
+
declare function defineModule(name: string, rules: UnifiedRule[]): {
|
|
235
|
+
name: string;
|
|
236
|
+
rules: UnifiedRule[];
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
export { type LivenessConfig, type MutationResult, type PathSchema, type PraxisApp, type PraxisAppConfig, type QueryOptions, type ReactiveRef, RuleResult, type UnifiedConstraint, type UnifiedRule, createApp, defineConstraint, defineModule, definePath, defineRule };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createApp,
|
|
3
|
+
defineConstraint,
|
|
4
|
+
defineModule,
|
|
5
|
+
definePath,
|
|
6
|
+
defineRule
|
|
7
|
+
} from "../chunk-6MVRT7CK.js";
|
|
8
|
+
import {
|
|
9
|
+
RuleResult,
|
|
10
|
+
fact
|
|
11
|
+
} from "../chunk-IG5BJ2MT.js";
|
|
12
|
+
export {
|
|
13
|
+
RuleResult,
|
|
14
|
+
createApp,
|
|
15
|
+
defineConstraint,
|
|
16
|
+
defineModule,
|
|
17
|
+
definePath,
|
|
18
|
+
defineRule,
|
|
19
|
+
fact
|
|
20
|
+
};
|