@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
@@ -50,6 +50,17 @@ var $ = __toESM(require("svelte/internal/client"), 1);
50
50
  var PraxisRegistry = class {
51
51
  rules = /* @__PURE__ */ new Map();
52
52
  constraints = /* @__PURE__ */ new Map();
53
+ compliance;
54
+ contractGaps = [];
55
+ constructor(options = {}) {
56
+ const defaultEnabled = typeof process !== "undefined" ? process.env?.NODE_ENV !== "production" : false;
57
+ this.compliance = {
58
+ enabled: defaultEnabled,
59
+ requiredFields: ["behavior", "examples", "invariants"],
60
+ missingSeverity: "warning",
61
+ ...options.compliance
62
+ };
63
+ }
53
64
  /**
54
65
  * Register a rule
55
66
  */
@@ -58,6 +69,7 @@ var PraxisRegistry = class {
58
69
  throw new Error(`Rule with id "${descriptor.id}" already registered`);
59
70
  }
60
71
  this.rules.set(descriptor.id, descriptor);
72
+ this.trackContractCompliance(descriptor.id, descriptor);
61
73
  }
62
74
  /**
63
75
  * Register a constraint
@@ -67,6 +79,7 @@ var PraxisRegistry = class {
67
79
  throw new Error(`Constraint with id "${descriptor.id}" already registered`);
68
80
  }
69
81
  this.constraints.set(descriptor.id, descriptor);
82
+ this.trackContractCompliance(descriptor.id, descriptor);
70
83
  }
71
84
  /**
72
85
  * Register a module (all its rules and constraints)
@@ -115,6 +128,69 @@ var PraxisRegistry = class {
115
128
  getAllConstraints() {
116
129
  return Array.from(this.constraints.values());
117
130
  }
131
+ /**
132
+ * Get collected contract gaps from registration-time validation.
133
+ */
134
+ getContractGaps() {
135
+ return [...this.contractGaps];
136
+ }
137
+ /**
138
+ * Clear collected contract gaps.
139
+ */
140
+ clearContractGaps() {
141
+ this.contractGaps = [];
142
+ }
143
+ trackContractCompliance(id, descriptor) {
144
+ if (!this.compliance.enabled) {
145
+ return;
146
+ }
147
+ const gaps = this.validateDescriptorContract(id, descriptor);
148
+ for (const gap of gaps) {
149
+ this.contractGaps.push(gap);
150
+ if (this.compliance.onGap) {
151
+ this.compliance.onGap(gap);
152
+ } else {
153
+ const label = gap.severity === "error" ? "ERROR" : gap.severity === "warning" ? "WARN" : "INFO";
154
+ console.warn(`[Praxis][${label}] Contract gap for "${gap.ruleId}": missing ${gap.missing.join(", ")}`);
155
+ }
156
+ }
157
+ }
158
+ validateDescriptorContract(id, descriptor) {
159
+ const requiredFields = this.compliance.requiredFields ?? ["behavior", "examples", "invariants"];
160
+ const missingSeverity = this.compliance.missingSeverity ?? "warning";
161
+ const contract = descriptor.contract ?? (descriptor.meta?.contract && typeof descriptor.meta.contract === "object" ? descriptor.meta.contract : void 0);
162
+ if (!contract) {
163
+ return [
164
+ {
165
+ ruleId: id,
166
+ missing: ["contract"],
167
+ severity: missingSeverity,
168
+ message: `Contract missing for "${id}"`
169
+ }
170
+ ];
171
+ }
172
+ const missing = [];
173
+ if (requiredFields.includes("behavior") && (!contract.behavior || contract.behavior.trim() === "")) {
174
+ missing.push("behavior");
175
+ }
176
+ if (requiredFields.includes("examples") && (!contract.examples || contract.examples.length === 0)) {
177
+ missing.push("examples");
178
+ }
179
+ if (requiredFields.includes("invariants") && (!contract.invariants || contract.invariants.length === 0)) {
180
+ missing.push("invariants");
181
+ }
182
+ if (missing.length === 0) {
183
+ return [];
184
+ }
185
+ return [
186
+ {
187
+ ruleId: id,
188
+ missing,
189
+ severity: "warning",
190
+ message: `Contract for "${id}" is incomplete: missing ${missing.join(", ")}`
191
+ }
192
+ ];
193
+ }
118
194
  };
119
195
 
120
196
  // src/core/protocol.ts
@@ -1,5 +1,5 @@
1
- import { L as LogicEngine } from '../reactive-engine.svelte-1M4m_C_v.cjs';
2
- export { a as ReactiveEngineOptions, R as ReactiveLogicEngine, c as createReactiveEngine } from '../reactive-engine.svelte-1M4m_C_v.cjs';
1
+ import { L as LogicEngine } from '../reactive-engine.svelte-BFIZfawz.cjs';
2
+ export { a as ReactiveEngineOptions, R as ReactiveLogicEngine, c as createReactiveEngine } from '../reactive-engine.svelte-BFIZfawz.cjs';
3
3
  import { P as PraxisState, a as PraxisEvent } from '../protocol-Qek7ebBl.cjs';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { L as LogicEngine } from '../reactive-engine.svelte-ChNFn4Hj.js';
2
- export { a as ReactiveEngineOptions, R as ReactiveLogicEngine, c as createReactiveEngine } from '../reactive-engine.svelte-ChNFn4Hj.js';
1
+ import { L as LogicEngine } from '../reactive-engine.svelte-CRNqHlbv.js';
2
+ export { a as ReactiveEngineOptions, R as ReactiveLogicEngine, c as createReactiveEngine } from '../reactive-engine.svelte-CRNqHlbv.js';
3
3
  import { P as PraxisState, a as PraxisEvent } from '../protocol-Qek7ebBl.js';
4
4
 
5
5
  /**
@@ -1,7 +1,9 @@
1
1
  import {
2
2
  ReactiveLogicEngine,
3
3
  createReactiveEngine
4
- } from "../chunk-R45WXWKH.js";
4
+ } from "../chunk-PRPQO6R5.js";
5
+ import "../chunk-R2PSBPKQ.js";
6
+ import "../chunk-VOMLVI6V.js";
5
7
  import "../chunk-QGM4M3NI.js";
6
8
 
7
9
  // src/integrations/svelte.ts
@@ -1,5 +1,167 @@
1
1
  import { P as PraxisState, a as PraxisEvent, b as PraxisFact, c as PraxisStepResult, d as PraxisStepConfig } from './protocol-Qek7ebBl.cjs';
2
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
+ * Type guard to check if an object is a valid Contract.
74
+ */
75
+ declare function isContract(obj: unknown): obj is Contract;
76
+ /**
77
+ * Options for defining a contract.
78
+ */
79
+ interface DefineContractOptions {
80
+ /** ID of the rule or constraint */
81
+ ruleId: string;
82
+ /** Canonical behavior description */
83
+ behavior: string;
84
+ /** Given/When/Then examples */
85
+ examples: Example[];
86
+ /** Invariants that must hold */
87
+ invariants: string[];
88
+ /** Optional assumptions */
89
+ assumptions?: Assumption[];
90
+ /** Optional references */
91
+ references?: Reference[];
92
+ /** Optional version */
93
+ version?: string;
94
+ }
95
+ /**
96
+ * Define a contract for a rule or constraint.
97
+ *
98
+ * @example
99
+ * const loginContract = defineContract({
100
+ * ruleId: 'auth.login',
101
+ * behavior: 'Process login events and create user session facts',
102
+ * examples: [
103
+ * {
104
+ * given: 'User provides valid credentials',
105
+ * when: 'LOGIN event is received',
106
+ * then: 'UserSessionCreated fact is emitted'
107
+ * }
108
+ * ],
109
+ * invariants: ['Session must have unique ID']
110
+ * });
111
+ */
112
+ declare function defineContract(options: DefineContractOptions): Contract;
113
+ /**
114
+ * Extract contract from rule/constraint metadata.
115
+ */
116
+ declare function getContract(meta?: Record<string, unknown>): Contract | undefined;
117
+ /**
118
+ * Severity levels for contract gaps.
119
+ */
120
+ type Severity = 'warning' | 'error' | 'info';
121
+ /**
122
+ * Types of missing contract artifacts.
123
+ */
124
+ /**
125
+ * Types of artifacts that can be missing from a contract.
126
+ *
127
+ * Note: 'tests' and 'spec' are included in this type for future extensibility
128
+ * and SARIF reporting compatibility, but are not currently validated by the
129
+ * validateContract function. To check for these, implement custom validation
130
+ * logic that scans for test files or spec files in your codebase.
131
+ */
132
+ type MissingArtifact = 'behavior' | 'examples' | 'invariants' | 'tests' | 'spec' | 'contract';
133
+ /**
134
+ * A gap in contract coverage.
135
+ */
136
+ interface ContractGap {
137
+ /** ID of the rule or constraint */
138
+ ruleId: string;
139
+ /** What is missing */
140
+ missing: MissingArtifact[];
141
+ /** Severity of the gap */
142
+ severity: Severity;
143
+ /** Optional human-readable message */
144
+ message?: string;
145
+ }
146
+ /**
147
+ * Result of contract validation.
148
+ */
149
+ interface ValidationReport {
150
+ /** Rules/constraints with complete contracts */
151
+ complete: Array<{
152
+ ruleId: string;
153
+ contract: Contract;
154
+ }>;
155
+ /** Rules/constraints with incomplete contracts */
156
+ incomplete: ContractGap[];
157
+ /** Rules/constraints with no contract at all */
158
+ missing: string[];
159
+ /** Total number of rules/constraints validated */
160
+ total: number;
161
+ /** Timestamp of validation */
162
+ timestamp: string;
163
+ }
164
+
3
165
  /**
4
166
  * Rules and Constraints System
5
167
  *
@@ -47,6 +209,8 @@ interface RuleDescriptor<TContext = unknown> {
47
209
  description: string;
48
210
  /** Implementation function */
49
211
  impl: RuleFn<TContext>;
212
+ /** Optional contract for rule behavior */
213
+ contract?: Contract;
50
214
  /** Optional metadata */
51
215
  meta?: Record<string, unknown>;
52
216
  }
@@ -60,6 +224,8 @@ interface ConstraintDescriptor<TContext = unknown> {
60
224
  description: string;
61
225
  /** Implementation function */
62
226
  impl: ConstraintFn<TContext>;
227
+ /** Optional contract for constraint behavior */
228
+ contract?: Contract;
63
229
  /** Optional metadata */
64
230
  meta?: Record<string, unknown>;
65
231
  }
@@ -75,6 +241,25 @@ interface PraxisModule<TContext = unknown> {
75
241
  /** Optional module metadata */
76
242
  meta?: Record<string, unknown>;
77
243
  }
244
+ /**
245
+ * Compliance validation options for rule/constraint registration.
246
+ */
247
+ interface RegistryComplianceOptions {
248
+ /** Enable contract checks during registration (default: true in dev) */
249
+ enabled?: boolean;
250
+ /** Required contract fields to be present */
251
+ requiredFields?: Array<'behavior' | 'examples' | 'invariants'>;
252
+ /** Severity to use for missing contracts */
253
+ missingSeverity?: Severity;
254
+ /** Callback for contract gaps (e.g., to emit facts) */
255
+ onGap?: (gap: ContractGap) => void;
256
+ }
257
+ /**
258
+ * PraxisRegistry configuration options.
259
+ */
260
+ interface PraxisRegistryOptions {
261
+ compliance?: RegistryComplianceOptions;
262
+ }
78
263
  /**
79
264
  * Registry for rules and constraints.
80
265
  * Maps IDs to their descriptors.
@@ -82,6 +267,9 @@ interface PraxisModule<TContext = unknown> {
82
267
  declare class PraxisRegistry<TContext = unknown> {
83
268
  private rules;
84
269
  private constraints;
270
+ private readonly compliance;
271
+ private contractGaps;
272
+ constructor(options?: PraxisRegistryOptions);
85
273
  /**
86
274
  * Register a rule
87
275
  */
@@ -118,6 +306,16 @@ declare class PraxisRegistry<TContext = unknown> {
118
306
  * Get all constraints
119
307
  */
120
308
  getAllConstraints(): ConstraintDescriptor<TContext>[];
309
+ /**
310
+ * Get collected contract gaps from registration-time validation.
311
+ */
312
+ getContractGaps(): ContractGap[];
313
+ /**
314
+ * Clear collected contract gaps.
315
+ */
316
+ clearContractGaps(): void;
317
+ private trackContractCompliance;
318
+ private validateDescriptorContract;
121
319
  }
122
320
 
123
321
  /**
@@ -297,4 +495,4 @@ declare class ReactiveLogicEngine<TContext extends object> {
297
495
  */
298
496
  declare function createReactiveEngine<TContext extends object>(options: ReactiveEngineOptions<TContext>): ReactiveLogicEngine<TContext>;
299
497
 
300
- export { type ConstraintDescriptor as C, LogicEngine as L, PraxisRegistry as P, ReactiveLogicEngine as R, type ReactiveEngineOptions as a, type RuleDescriptor as b, createReactiveEngine as c, type RuleFn as d, type ConstraintFn as e, type PraxisModule as f, type RuleId as g, type ConstraintId as h, type PraxisEngineOptions as i, createPraxisEngine as j };
498
+ export { type Assumption as A, type ConstraintDescriptor as C, type DefineContractOptions as D, type Example as E, LogicEngine as L, type MissingArtifact as M, PraxisRegistry as P, ReactiveLogicEngine as R, type Severity as S, type ValidationReport as V, type ReactiveEngineOptions as a, type RuleDescriptor as b, createReactiveEngine as c, type RuleFn as d, type Contract as e, type ConstraintFn as f, type PraxisModule as g, type RuleId as h, type ConstraintId as i, type PraxisEngineOptions as j, createPraxisEngine as k, defineContract as l, getContract as m, isContract as n, type Reference as o, type ContractGap as p };
@@ -1,5 +1,167 @@
1
1
  import { P as PraxisState, a as PraxisEvent, b as PraxisFact, c as PraxisStepResult, d as PraxisStepConfig } from './protocol-Qek7ebBl.js';
2
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
+ * Type guard to check if an object is a valid Contract.
74
+ */
75
+ declare function isContract(obj: unknown): obj is Contract;
76
+ /**
77
+ * Options for defining a contract.
78
+ */
79
+ interface DefineContractOptions {
80
+ /** ID of the rule or constraint */
81
+ ruleId: string;
82
+ /** Canonical behavior description */
83
+ behavior: string;
84
+ /** Given/When/Then examples */
85
+ examples: Example[];
86
+ /** Invariants that must hold */
87
+ invariants: string[];
88
+ /** Optional assumptions */
89
+ assumptions?: Assumption[];
90
+ /** Optional references */
91
+ references?: Reference[];
92
+ /** Optional version */
93
+ version?: string;
94
+ }
95
+ /**
96
+ * Define a contract for a rule or constraint.
97
+ *
98
+ * @example
99
+ * const loginContract = defineContract({
100
+ * ruleId: 'auth.login',
101
+ * behavior: 'Process login events and create user session facts',
102
+ * examples: [
103
+ * {
104
+ * given: 'User provides valid credentials',
105
+ * when: 'LOGIN event is received',
106
+ * then: 'UserSessionCreated fact is emitted'
107
+ * }
108
+ * ],
109
+ * invariants: ['Session must have unique ID']
110
+ * });
111
+ */
112
+ declare function defineContract(options: DefineContractOptions): Contract;
113
+ /**
114
+ * Extract contract from rule/constraint metadata.
115
+ */
116
+ declare function getContract(meta?: Record<string, unknown>): Contract | undefined;
117
+ /**
118
+ * Severity levels for contract gaps.
119
+ */
120
+ type Severity = 'warning' | 'error' | 'info';
121
+ /**
122
+ * Types of missing contract artifacts.
123
+ */
124
+ /**
125
+ * Types of artifacts that can be missing from a contract.
126
+ *
127
+ * Note: 'tests' and 'spec' are included in this type for future extensibility
128
+ * and SARIF reporting compatibility, but are not currently validated by the
129
+ * validateContract function. To check for these, implement custom validation
130
+ * logic that scans for test files or spec files in your codebase.
131
+ */
132
+ type MissingArtifact = 'behavior' | 'examples' | 'invariants' | 'tests' | 'spec' | 'contract';
133
+ /**
134
+ * A gap in contract coverage.
135
+ */
136
+ interface ContractGap {
137
+ /** ID of the rule or constraint */
138
+ ruleId: string;
139
+ /** What is missing */
140
+ missing: MissingArtifact[];
141
+ /** Severity of the gap */
142
+ severity: Severity;
143
+ /** Optional human-readable message */
144
+ message?: string;
145
+ }
146
+ /**
147
+ * Result of contract validation.
148
+ */
149
+ interface ValidationReport {
150
+ /** Rules/constraints with complete contracts */
151
+ complete: Array<{
152
+ ruleId: string;
153
+ contract: Contract;
154
+ }>;
155
+ /** Rules/constraints with incomplete contracts */
156
+ incomplete: ContractGap[];
157
+ /** Rules/constraints with no contract at all */
158
+ missing: string[];
159
+ /** Total number of rules/constraints validated */
160
+ total: number;
161
+ /** Timestamp of validation */
162
+ timestamp: string;
163
+ }
164
+
3
165
  /**
4
166
  * Rules and Constraints System
5
167
  *
@@ -47,6 +209,8 @@ interface RuleDescriptor<TContext = unknown> {
47
209
  description: string;
48
210
  /** Implementation function */
49
211
  impl: RuleFn<TContext>;
212
+ /** Optional contract for rule behavior */
213
+ contract?: Contract;
50
214
  /** Optional metadata */
51
215
  meta?: Record<string, unknown>;
52
216
  }
@@ -60,6 +224,8 @@ interface ConstraintDescriptor<TContext = unknown> {
60
224
  description: string;
61
225
  /** Implementation function */
62
226
  impl: ConstraintFn<TContext>;
227
+ /** Optional contract for constraint behavior */
228
+ contract?: Contract;
63
229
  /** Optional metadata */
64
230
  meta?: Record<string, unknown>;
65
231
  }
@@ -75,6 +241,25 @@ interface PraxisModule<TContext = unknown> {
75
241
  /** Optional module metadata */
76
242
  meta?: Record<string, unknown>;
77
243
  }
244
+ /**
245
+ * Compliance validation options for rule/constraint registration.
246
+ */
247
+ interface RegistryComplianceOptions {
248
+ /** Enable contract checks during registration (default: true in dev) */
249
+ enabled?: boolean;
250
+ /** Required contract fields to be present */
251
+ requiredFields?: Array<'behavior' | 'examples' | 'invariants'>;
252
+ /** Severity to use for missing contracts */
253
+ missingSeverity?: Severity;
254
+ /** Callback for contract gaps (e.g., to emit facts) */
255
+ onGap?: (gap: ContractGap) => void;
256
+ }
257
+ /**
258
+ * PraxisRegistry configuration options.
259
+ */
260
+ interface PraxisRegistryOptions {
261
+ compliance?: RegistryComplianceOptions;
262
+ }
78
263
  /**
79
264
  * Registry for rules and constraints.
80
265
  * Maps IDs to their descriptors.
@@ -82,6 +267,9 @@ interface PraxisModule<TContext = unknown> {
82
267
  declare class PraxisRegistry<TContext = unknown> {
83
268
  private rules;
84
269
  private constraints;
270
+ private readonly compliance;
271
+ private contractGaps;
272
+ constructor(options?: PraxisRegistryOptions);
85
273
  /**
86
274
  * Register a rule
87
275
  */
@@ -118,6 +306,16 @@ declare class PraxisRegistry<TContext = unknown> {
118
306
  * Get all constraints
119
307
  */
120
308
  getAllConstraints(): ConstraintDescriptor<TContext>[];
309
+ /**
310
+ * Get collected contract gaps from registration-time validation.
311
+ */
312
+ getContractGaps(): ContractGap[];
313
+ /**
314
+ * Clear collected contract gaps.
315
+ */
316
+ clearContractGaps(): void;
317
+ private trackContractCompliance;
318
+ private validateDescriptorContract;
121
319
  }
122
320
 
123
321
  /**
@@ -297,4 +495,4 @@ declare class ReactiveLogicEngine<TContext extends object> {
297
495
  */
298
496
  declare function createReactiveEngine<TContext extends object>(options: ReactiveEngineOptions<TContext>): ReactiveLogicEngine<TContext>;
299
497
 
300
- export { type ConstraintDescriptor as C, LogicEngine as L, PraxisRegistry as P, ReactiveLogicEngine as R, type ReactiveEngineOptions as a, type RuleDescriptor as b, createReactiveEngine as c, type RuleFn as d, type ConstraintFn as e, type PraxisModule as f, type RuleId as g, type ConstraintId as h, type PraxisEngineOptions as i, createPraxisEngine as j };
498
+ export { type Assumption as A, type ConstraintDescriptor as C, type DefineContractOptions as D, type Example as E, LogicEngine as L, type MissingArtifact as M, PraxisRegistry as P, ReactiveLogicEngine as R, type Severity as S, type ValidationReport as V, type ReactiveEngineOptions as a, type RuleDescriptor as b, createReactiveEngine as c, type RuleFn as d, type Contract as e, type ConstraintFn as f, type PraxisModule as g, type RuleId as h, type ConstraintId as i, type PraxisEngineOptions as j, createPraxisEngine as k, defineContract as l, getContract as m, isContract as n, type Reference as o, type ContractGap as p };