@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
@@ -1,5 +1,7 @@
1
- import { P as PraxisState, a as PraxisEvent, L as LogicEngine } from '../reactive-engine.svelte-DjynI82A.js';
2
- export { o as ReactiveEngineOptions, p as ReactiveLogicEngine, s as createReactiveEngine } from '../reactive-engine.svelte-DjynI82A.js';
1
+ import { L as LogicEngine } from '../reactive-engine.svelte-BwWadvAW.js';
2
+ export { R as ReactiveEngineOptions, a as ReactiveLogicEngine, c as createReactiveEngine } from '../reactive-engine.svelte-BwWadvAW.js';
3
+ import { P as PraxisState, a as PraxisEvent } from '../rule-result-DcXWe9tn.js';
4
+ import '../rules-BaWMqxuG.js';
3
5
 
4
6
  /**
5
7
  * Svelte v5 Integration
@@ -1,8 +1,9 @@
1
1
  import {
2
2
  ReactiveLogicEngine,
3
3
  createReactiveEngine
4
- } from "../chunk-N63K4KWS.js";
5
- import "../chunk-MJK3IYTJ.js";
4
+ } from "../chunk-4IRUGWR3.js";
5
+ import "../chunk-JZDJU2DO.js";
6
+ import "../chunk-IG5BJ2MT.js";
6
7
 
7
8
  // src/integrations/svelte.ts
8
9
  function createPraxisStore(engine) {
@@ -0,0 +1,177 @@
1
+ import { d as PraxisModule } from '../rules-BaWMqxuG.js';
2
+ import '../rule-result-DcXWe9tn.js';
3
+
4
+ /**
5
+ * Praxis Project Logic — Types
6
+ *
7
+ * Types for developer workflow rules: gates, semver contracts,
8
+ * commit generation, and branch management.
9
+ */
10
+ type GateStatus = 'open' | 'closed' | 'blocked';
11
+ interface GateConfig {
12
+ /** Expectations that must be satisfied for the gate to open */
13
+ expects: string[];
14
+ /** Action when gate is satisfied */
15
+ onSatisfied?: string;
16
+ /** Action when gate is violated */
17
+ onViolation?: string;
18
+ }
19
+ interface GateState {
20
+ name: string;
21
+ status: GateStatus;
22
+ /** Which expectations are satisfied */
23
+ satisfied: string[];
24
+ /** Which expectations are not satisfied */
25
+ unsatisfied: string[];
26
+ /** Timestamp of last status change */
27
+ lastChanged: number;
28
+ }
29
+ interface SemverContractConfig {
30
+ /** Files/sources that contain version strings */
31
+ sources: string[];
32
+ /** Invariants about version consistency */
33
+ invariants: string[];
34
+ }
35
+ interface SemverReport {
36
+ /** Whether all sources have consistent versions */
37
+ consistent: boolean;
38
+ /** Version found in each source */
39
+ versions: Record<string, string>;
40
+ /** Invariant violations */
41
+ violations: string[];
42
+ }
43
+ interface PraxisDiff {
44
+ /** Rules added since last commit */
45
+ rulesAdded: string[];
46
+ /** Rules removed */
47
+ rulesRemoved: string[];
48
+ /** Rules modified */
49
+ rulesModified: string[];
50
+ /** Contracts added */
51
+ contractsAdded: string[];
52
+ /** Contracts removed */
53
+ contractsRemoved: string[];
54
+ /** Expectations added */
55
+ expectationsAdded: string[];
56
+ /** Expectations removed */
57
+ expectationsRemoved: string[];
58
+ /** Gate state changes */
59
+ gateChanges: Array<{
60
+ gate: string;
61
+ from: GateStatus;
62
+ to: GateStatus;
63
+ }>;
64
+ }
65
+ interface BranchRulesConfig {
66
+ /** Naming convention pattern (e.g., 'feat/{name}', 'fix/{issue}') */
67
+ naming: string;
68
+ /** Conditions required for merge */
69
+ mergeConditions: string[];
70
+ }
71
+ interface PredefinedGateConfig {
72
+ /** Whether to enable this gate */
73
+ enabled?: boolean;
74
+ /** Custom expectations to add */
75
+ additionalExpects?: string[];
76
+ }
77
+
78
+ /**
79
+ * Praxis Project Logic
80
+ *
81
+ * Developer workflow rules: gates, semver contracts, commit message
82
+ * generation from behavioral deltas, and branch management.
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * import { defineGate, semverContract, commitFromState } from '@plures/praxis/project';
87
+ *
88
+ * const testGate = defineGate('test', {
89
+ * expects: ['all-tests-pass', 'no-type-errors'],
90
+ * onSatisfied: 'merge-allowed',
91
+ * onViolation: 'merge-blocked',
92
+ * });
93
+ *
94
+ * const diff = { rulesAdded: ['auth/login'], ... };
95
+ * const message = commitFromState(diff);
96
+ * // → "feat(rules): add auth/login rule"
97
+ * ```
98
+ */
99
+
100
+ /**
101
+ * Context type for gates. Apps extend their context with gate state.
102
+ */
103
+ interface GateContext {
104
+ gates?: Record<string, GateState>;
105
+ expectations?: Record<string, boolean>;
106
+ }
107
+ /**
108
+ * Define a feature gate — a condition that must be satisfied before
109
+ * proceeding with a workflow step (deploy, merge, release, etc.).
110
+ *
111
+ * @example
112
+ * ```ts
113
+ * const testGate = defineGate('test', {
114
+ * expects: ['all-tests-pass', 'no-type-errors'],
115
+ * onSatisfied: 'deploy-allowed',
116
+ * onViolation: 'deploy-blocked',
117
+ * });
118
+ * registry.registerModule(testGate);
119
+ * ```
120
+ */
121
+ declare function defineGate(name: string, config: GateConfig): PraxisModule<GateContext>;
122
+ /**
123
+ * Create a semver contract module that checks version consistency
124
+ * across multiple sources (package.json, Cargo.toml, etc.).
125
+ *
126
+ * @example
127
+ * ```ts
128
+ * const version = semverContract({
129
+ * sources: ['package.json', 'src/version.ts', 'README.md'],
130
+ * invariants: ['All sources must have the same version'],
131
+ * });
132
+ * ```
133
+ */
134
+ declare function semverContract(config: SemverContractConfig): PraxisModule;
135
+ /**
136
+ * Generate a conventional commit message from a behavioral delta.
137
+ *
138
+ * Unlike file-based commit messages, this describes WHAT behavioral
139
+ * changes occurred — rule additions, contract changes, expectation shifts.
140
+ *
141
+ * @example
142
+ * ```ts
143
+ * const msg = commitFromState({
144
+ * rulesAdded: ['auth/login', 'auth/logout'],
145
+ * contractsAdded: ['auth/login'],
146
+ * ...empty
147
+ * });
148
+ * // → "feat(rules): add auth/login, auth/logout\n\nContracts added: auth/login"
149
+ * ```
150
+ */
151
+ declare function commitFromState(diff: PraxisDiff): string;
152
+ /**
153
+ * Create branch management rules.
154
+ *
155
+ * @example
156
+ * ```ts
157
+ * const branches = branchRules({
158
+ * naming: 'feat/{name}',
159
+ * mergeConditions: ['tests-pass', 'review-approved'],
160
+ * });
161
+ * ```
162
+ */
163
+ declare function branchRules(config: BranchRulesConfig): PraxisModule;
164
+ /**
165
+ * Create a lint gate — blocks workflow until linting passes.
166
+ */
167
+ declare function lintGate(config?: PredefinedGateConfig): PraxisModule<GateContext>;
168
+ /**
169
+ * Create a format gate — blocks workflow until formatting is correct.
170
+ */
171
+ declare function formatGate(config?: PredefinedGateConfig): PraxisModule<GateContext>;
172
+ /**
173
+ * Create an expectation gate — blocks workflow until expectations are verified.
174
+ */
175
+ declare function expectationGate(config?: PredefinedGateConfig): PraxisModule<GateContext>;
176
+
177
+ export { type BranchRulesConfig, type GateConfig, type GateState, type GateStatus, type PraxisDiff, type PredefinedGateConfig, type SemverContractConfig, type SemverReport, branchRules, commitFromState, defineGate, expectationGate, formatGate, lintGate, semverContract };
@@ -0,0 +1,19 @@
1
+ import {
2
+ branchRules,
3
+ commitFromState,
4
+ defineGate,
5
+ expectationGate,
6
+ formatGate,
7
+ lintGate,
8
+ semverContract
9
+ } from "../chunk-BQOYZBWA.js";
10
+ import "../chunk-IG5BJ2MT.js";
11
+ export {
12
+ branchRules,
13
+ commitFromState,
14
+ defineGate,
15
+ expectationGate,
16
+ formatGate,
17
+ lintGate,
18
+ semverContract
19
+ };
@@ -0,0 +1,224 @@
1
+ import { b as PraxisFact, P as PraxisState, a as PraxisEvent, c as PraxisStepResult, d as PraxisStepConfig, e as PraxisDiagnostics } from './rule-result-DcXWe9tn.js';
2
+ import { P as PraxisRegistry } from './rules-BaWMqxuG.js';
3
+
4
+ /**
5
+ * Praxis Logic Engine
6
+ *
7
+ * The logic engine manages state, processes events through rules,
8
+ * checks constraints, and provides a strongly-typed API for application logic.
9
+ */
10
+
11
+ /**
12
+ * Options for creating a Praxis engine
13
+ */
14
+ interface PraxisEngineOptions<TContext = unknown> {
15
+ /** Initial context */
16
+ initialContext: TContext;
17
+ /** Registry of rules and constraints */
18
+ registry: PraxisRegistry<TContext>;
19
+ /** Initial facts (optional) */
20
+ initialFacts?: PraxisFact[];
21
+ /** Initial metadata (optional) */
22
+ initialMeta?: Record<string, unknown>;
23
+ /**
24
+ * Fact deduplication strategy (default: 'last-write-wins').
25
+ *
26
+ * - 'none': facts accumulate without dedup (original behavior)
27
+ * - 'last-write-wins': only keep the latest fact per tag (most common)
28
+ * - 'append': keep all facts but cap at maxFacts
29
+ */
30
+ factDedup?: 'none' | 'last-write-wins' | 'append';
31
+ /**
32
+ * Maximum number of facts to retain (default: 1000).
33
+ * When exceeded, oldest facts are evicted (FIFO).
34
+ * Set to 0 for unlimited (not recommended).
35
+ */
36
+ maxFacts?: number;
37
+ }
38
+ /**
39
+ * The Praxis Logic Engine
40
+ *
41
+ * Manages application logic through facts, events, rules, and constraints.
42
+ * The engine is strongly typed and functional - all state updates are immutable.
43
+ */
44
+ declare class LogicEngine<TContext = unknown> {
45
+ private state;
46
+ private readonly registry;
47
+ private readonly factDedup;
48
+ private readonly maxFacts;
49
+ constructor(options: PraxisEngineOptions<TContext>);
50
+ /**
51
+ * Get the current state (immutable copy)
52
+ */
53
+ getState(): Readonly<PraxisState & {
54
+ context: TContext;
55
+ }>;
56
+ /**
57
+ * Get the current context
58
+ */
59
+ getContext(): TContext;
60
+ /**
61
+ * Get current facts
62
+ */
63
+ getFacts(): PraxisFact[];
64
+ /**
65
+ * Process events through the engine.
66
+ * Applies all registered rules and checks all registered constraints.
67
+ *
68
+ * @param events Events to process
69
+ * @returns Result with new state and diagnostics
70
+ */
71
+ step(events: PraxisEvent[]): PraxisStepResult;
72
+ /**
73
+ * Process events with specific rule and constraint configuration.
74
+ *
75
+ * @param events Events to process
76
+ * @param config Step configuration
77
+ * @returns Result with new state and diagnostics
78
+ */
79
+ stepWithConfig(events: PraxisEvent[], config: PraxisStepConfig): PraxisStepResult;
80
+ /**
81
+ * Update the context directly (for exceptional cases).
82
+ * Generally, context should be updated through rules.
83
+ *
84
+ * @param updater Function that produces new context from old context
85
+ */
86
+ updateContext(updater: (context: TContext) => TContext): void;
87
+ /**
88
+ * Atomically update context AND process events in a single call.
89
+ *
90
+ * This avoids the fragile pattern of calling updateContext() then step()
91
+ * separately, where rules could see stale context if the ordering is wrong.
92
+ *
93
+ * @param updater Function that produces new context from old context
94
+ * @param events Events to process after context is updated
95
+ * @returns Result with new state and diagnostics
96
+ *
97
+ * @example
98
+ * engine.stepWithContext(
99
+ * ctx => ({ ...ctx, sprintName: sprint.name, items: sprint.items }),
100
+ * [{ tag: 'sprint.update', payload: { name: sprint.name } }]
101
+ * );
102
+ */
103
+ stepWithContext(updater: (context: TContext) => TContext, events: PraxisEvent[]): PraxisStepResult;
104
+ /**
105
+ * Add facts directly (for exceptional cases).
106
+ * Generally, facts should be added through rules.
107
+ *
108
+ * @param facts Facts to add
109
+ */
110
+ addFacts(facts: PraxisFact[]): void;
111
+ /**
112
+ * Check all constraints without processing any events.
113
+ *
114
+ * Useful for validation-only scenarios (e.g., form validation,
115
+ * pre-save checks) where you want constraint diagnostics without
116
+ * triggering any rules.
117
+ *
118
+ * @returns Array of constraint violation diagnostics (empty = all passing)
119
+ */
120
+ checkConstraints(): PraxisDiagnostics[];
121
+ /**
122
+ * Clear all facts
123
+ */
124
+ clearFacts(): void;
125
+ /**
126
+ * Reset the engine to initial state
127
+ */
128
+ reset(options: PraxisEngineOptions<TContext>): void;
129
+ }
130
+ /**
131
+ * Create a new Praxis logic engine.
132
+ *
133
+ * @param options Engine options
134
+ * @returns New LogicEngine instance
135
+ */
136
+ declare function createPraxisEngine<TContext = unknown>(options: PraxisEngineOptions<TContext>): LogicEngine<TContext>;
137
+
138
+ /**
139
+ * Praxis Reactive Logic Engine - Svelte 5 Implementation
140
+ *
141
+ * This version uses Svelte 5 runes ($state) for built-in reactivity.
142
+ * The state object is automatically reactive when used in Svelte components.
143
+ */
144
+
145
+ interface ReactiveEngineOptions<TContext> {
146
+ initialContext: TContext;
147
+ initialFacts?: any[];
148
+ initialMeta?: Record<string, unknown>;
149
+ registry?: PraxisRegistry<TContext>;
150
+ }
151
+ /**
152
+ * Reactive Logic Engine using Svelte 5 runes.
153
+ * Combines the standard LogicEngine with reactive state management.
154
+ */
155
+ declare class ReactiveLogicEngine<TContext extends object> {
156
+ state: {
157
+ context: TContext;
158
+ facts: any[];
159
+ meta: Record<string, unknown>;
160
+ };
161
+ private _engine;
162
+ constructor(options: ReactiveEngineOptions<TContext>);
163
+ /**
164
+ * Access the reactive context.
165
+ * In Svelte 5 components, changes to this object will automatically trigger updates.
166
+ */
167
+ get context(): TContext;
168
+ /**
169
+ * Access the reactive facts list.
170
+ */
171
+ get facts(): any[];
172
+ /**
173
+ * Access the reactive metadata.
174
+ */
175
+ get meta(): Record<string, unknown>;
176
+ /**
177
+ * Apply a mutation to the state.
178
+ * Changes will automatically trigger Svelte reactivity.
179
+ *
180
+ * @param mutator A function that receives the state and modifies it.
181
+ */
182
+ apply(mutator: (state: {
183
+ context: TContext;
184
+ facts: any[];
185
+ meta: Record<string, unknown>;
186
+ }) => void): void;
187
+ /**
188
+ * Process events through the logic engine and update reactive state.
189
+ *
190
+ * @param events Events to process
191
+ */
192
+ step(events: PraxisEvent[]): void;
193
+ }
194
+ /**
195
+ * Create a reactive logic engine with Svelte 5 runes.
196
+ *
197
+ * @param options Configuration options
198
+ * @returns A reactive logic engine instance
199
+ *
200
+ * @example
201
+ * ```svelte
202
+ * <script lang="ts">
203
+ * import { createReactiveEngine } from '@plures/praxis/svelte';
204
+ *
205
+ * const engine = createReactiveEngine({
206
+ * initialContext: { count: 0 },
207
+ * registry
208
+ * });
209
+ *
210
+ * // Use $derived for computed values
211
+ * const count = $derived(engine.context.count);
212
+ * const doubled = $derived(engine.context.count * 2);
213
+ *
214
+ * function increment() {
215
+ * engine.step([Increment.create({ amount: 1 })]);
216
+ * }
217
+ * </script>
218
+ *
219
+ * <button on:click={increment}>Count: {count}, Doubled: {doubled}</button>
220
+ * ```
221
+ */
222
+ declare function createReactiveEngine<TContext extends object>(options: ReactiveEngineOptions<TContext>): ReactiveLogicEngine<TContext>;
223
+
224
+ export { LogicEngine as L, type PraxisEngineOptions as P, type ReactiveEngineOptions as R, ReactiveLogicEngine as a, createPraxisEngine as b, createReactiveEngine as c };
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Core Praxis Protocol
3
+ *
4
+ * Language-neutral, JSON-friendly protocol that forms the foundation of Praxis.
5
+ * This protocol is designed to be stable and portable across languages (TypeScript, C#, PowerShell, etc.)
6
+ *
7
+ * The protocol defines the conceptual core of the engine:
8
+ * - Pure, deterministic, data in → data out
9
+ * - No side effects, no global state
10
+ * - All higher-level TypeScript APIs are built on top of this protocol
11
+ *
12
+ * ## Protocol Versioning
13
+ *
14
+ * The Praxis protocol follows semantic versioning (MAJOR.MINOR.PATCH):
15
+ * - MAJOR: Breaking changes to core protocol types or semantics
16
+ * - MINOR: Backward-compatible additions to protocol (new optional fields)
17
+ * - PATCH: Clarifications, documentation updates, no functional changes
18
+ *
19
+ * Current version: 1.0.0
20
+ *
21
+ * ### Stability Guarantees
22
+ *
23
+ * 1. **Core Types Stability**: The following types are considered stable and will not
24
+ * change in backward-incompatible ways within the same major version:
25
+ * - PraxisFact (tag, payload structure)
26
+ * - PraxisEvent (tag, payload structure)
27
+ * - PraxisState (context, facts, meta structure)
28
+ * - PraxisStepFn signature
29
+ *
30
+ * 2. **JSON Compatibility**: All protocol types will remain JSON-serializable.
31
+ * No non-JSON-safe types (functions, symbols, etc.) will be added to the protocol.
32
+ *
33
+ * 3. **Cross-Language Compatibility**: Protocol changes will be coordinated across
34
+ * all official language implementations (TypeScript, C#, PowerShell) to ensure
35
+ * interoperability.
36
+ *
37
+ * 4. **Migration Path**: Major version changes will be accompanied by:
38
+ * - Migration guide
39
+ * - Deprecation warnings in previous version
40
+ * - Compatibility shims where possible
41
+ */
42
+ /**
43
+ * Protocol version following semantic versioning
44
+ */
45
+ declare const PRAXIS_PROTOCOL_VERSION: "1.0.0";
46
+ /**
47
+ * A fact is a typed proposition about the domain.
48
+ * Examples: UserLoggedIn, CartItem, NetworkOnline
49
+ */
50
+ interface PraxisFact {
51
+ /** Tag identifying the fact type */
52
+ tag: string;
53
+ /** Payload containing the fact data */
54
+ payload: unknown;
55
+ }
56
+ /**
57
+ * An event is a temporally ordered fact meant to drive change.
58
+ * Examples: LOGIN, LOGOUT, ADD_TO_CART
59
+ */
60
+ interface PraxisEvent {
61
+ /** Tag identifying the event type */
62
+ tag: string;
63
+ /** Payload containing the event data */
64
+ payload: unknown;
65
+ }
66
+ /**
67
+ * The state of the Praxis engine at a point in time.
68
+ */
69
+ interface PraxisState {
70
+ /** Application context (domain-specific data) */
71
+ context: unknown;
72
+ /** Current facts about the domain */
73
+ facts: PraxisFact[];
74
+ /**
75
+ * Events currently being processed in this step.
76
+ * Available to rules during execution — guaranteed to contain the exact
77
+ * events passed to step()/stepWithContext().
78
+ * Empty outside of step execution.
79
+ */
80
+ events?: PraxisEvent[];
81
+ /** Optional metadata (timestamps, version, etc.) */
82
+ meta?: Record<string, unknown>;
83
+ /** Protocol version (for cross-language compatibility) */
84
+ protocolVersion?: string;
85
+ }
86
+ /**
87
+ * Diagnostic information about constraint violations or rule errors.
88
+ */
89
+ interface PraxisDiagnostics {
90
+ /** Kind of diagnostic */
91
+ kind: 'constraint-violation' | 'rule-error';
92
+ /** Human-readable message */
93
+ message: string;
94
+ /** Additional diagnostic data */
95
+ data?: unknown;
96
+ }
97
+ /**
98
+ * Configuration for a step execution.
99
+ * Specifies which rules and constraints to apply.
100
+ */
101
+ interface PraxisStepConfig {
102
+ /** IDs of rules to apply during this step */
103
+ ruleIds: string[];
104
+ /** IDs of constraints to check during this step */
105
+ constraintIds: string[];
106
+ }
107
+ /**
108
+ * Result of a step execution.
109
+ */
110
+ interface PraxisStepResult {
111
+ /** New state after applying rules and checking constraints */
112
+ state: PraxisState;
113
+ /** Diagnostics from rule execution and constraint checking */
114
+ diagnostics: PraxisDiagnostics[];
115
+ }
116
+ /**
117
+ * The core step function of the Praxis engine.
118
+ *
119
+ * This is the conceptual heart of the engine:
120
+ * - Takes current state, events, and configuration
121
+ * - Applies rules and checks constraints
122
+ * - Returns new state and diagnostics
123
+ *
124
+ * Pure, deterministic, data in → data out.
125
+ * No side effects, no global state.
126
+ */
127
+ type PraxisStepFn = (state: PraxisState, events: PraxisEvent[], config: PraxisStepConfig) => PraxisStepResult;
128
+
129
+ /**
130
+ * The result of evaluating a rule. Every rule MUST return one of:
131
+ * - `RuleResult.emit(facts)` — rule produced facts
132
+ * - `RuleResult.noop(reason?)` — rule evaluated but had nothing to say
133
+ * - `RuleResult.skip(reason?)` — rule decided to skip (preconditions not met)
134
+ * - `RuleResult.retract(tags)` — rule retracts previously emitted facts
135
+ */
136
+ declare class RuleResult {
137
+ /** The kind of result */
138
+ readonly kind: 'emit' | 'noop' | 'skip' | 'retract';
139
+ /** Facts produced (only for 'emit') */
140
+ readonly facts: PraxisFact[];
141
+ /** Fact tags to retract (only for 'retract') */
142
+ readonly retractTags: string[];
143
+ /** Optional reason (for noop/skip/retract — useful for debugging) */
144
+ readonly reason?: string;
145
+ /** The rule ID that produced this result (set by engine) */
146
+ ruleId?: string;
147
+ private constructor();
148
+ /**
149
+ * Rule produced facts.
150
+ *
151
+ * @example
152
+ * return RuleResult.emit([
153
+ * { tag: 'sprint.behind', payload: { deficit: 5 } }
154
+ * ]);
155
+ */
156
+ static emit(facts: PraxisFact[]): RuleResult;
157
+ /**
158
+ * Rule evaluated but had nothing to report.
159
+ * Unlike returning [], this is explicit and traceable.
160
+ *
161
+ * @example
162
+ * if (ctx.completedHours >= expectedHours) {
163
+ * return RuleResult.noop('Sprint is on pace');
164
+ * }
165
+ */
166
+ static noop(reason?: string): RuleResult;
167
+ /**
168
+ * Rule decided to skip because preconditions were not met.
169
+ * Distinct from noop: skip means "I can't evaluate", noop means "I evaluated and found nothing".
170
+ *
171
+ * @example
172
+ * if (!ctx.sprintName) {
173
+ * return RuleResult.skip('No active sprint');
174
+ * }
175
+ */
176
+ static skip(reason?: string): RuleResult;
177
+ /**
178
+ * Rule retracts previously emitted facts by tag.
179
+ * Used when a condition that previously produced facts is no longer true.
180
+ *
181
+ * @example
182
+ * // Sprint was behind, but caught up
183
+ * if (ctx.completedHours >= expectedHours) {
184
+ * return RuleResult.retract(['sprint.behind'], 'Sprint caught up');
185
+ * }
186
+ */
187
+ static retract(tags: string[], reason?: string): RuleResult;
188
+ /** Whether this result produced facts */
189
+ get hasFacts(): boolean;
190
+ /** Whether this result retracts facts */
191
+ get hasRetractions(): boolean;
192
+ }
193
+ /**
194
+ * A rule function that returns a typed RuleResult.
195
+ * New API — replaces the old PraxisFact[] return type.
196
+ */
197
+ type TypedRuleFn<TContext = unknown> = (state: PraxisState & {
198
+ context: TContext;
199
+ events: PraxisEvent[];
200
+ }, events: PraxisEvent[]) => RuleResult;
201
+ /**
202
+ * Convenience: create a fact object (just a shorthand)
203
+ */
204
+ declare function fact(tag: string, payload: unknown): PraxisFact;
205
+
206
+ export { type PraxisState as P, RuleResult as R, type TypedRuleFn as T, type PraxisEvent as a, type PraxisFact as b, type PraxisStepResult as c, type PraxisStepConfig as d, type PraxisDiagnostics as e, PRAXIS_PROTOCOL_VERSION as f, type PraxisStepFn as g, fact as h };