@plures/praxis 1.2.0 → 1.2.11

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 (63) hide show
  1. package/README.md +93 -96
  2. package/dist/browser/{adapter-TM4IS5KT.js → adapter-CIMBGDC7.js} +5 -3
  3. package/dist/browser/{chunk-LE2ZJYFC.js → chunk-K377RW4V.js} +76 -0
  4. package/dist/{node/chunk-JQ64KMLN.js → browser/chunk-MBVHLOU2.js} +12 -1
  5. package/dist/browser/index.d.ts +32 -5
  6. package/dist/browser/index.js +15 -7
  7. package/dist/browser/integrations/svelte.d.ts +2 -2
  8. package/dist/browser/integrations/svelte.js +1 -1
  9. package/dist/browser/{reactive-engine.svelte-C9OpcTHf.d.ts → reactive-engine.svelte-9aS0kTa8.d.ts} +136 -1
  10. package/dist/node/{adapter-K6DOX6XS.js → adapter-75ISSMWD.js} +5 -3
  11. package/dist/node/chunk-5RH7UAQC.js +486 -0
  12. package/dist/{browser/chunk-JQ64KMLN.js → node/chunk-MBVHLOU2.js} +12 -1
  13. package/dist/node/{chunk-LE2ZJYFC.js → chunk-PRPQO6R5.js} +3 -72
  14. package/dist/node/chunk-R2PSBPKQ.js +150 -0
  15. package/dist/node/chunk-WZ6B3LZ6.js +638 -0
  16. package/dist/node/cli/index.cjs +2316 -832
  17. package/dist/node/cli/index.js +18 -0
  18. package/dist/node/components/index.d.cts +3 -2
  19. package/dist/node/components/index.d.ts +3 -2
  20. package/dist/node/index.cjs +620 -38
  21. package/dist/node/index.d.cts +259 -5
  22. package/dist/node/index.d.ts +259 -5
  23. package/dist/node/index.js +55 -65
  24. package/dist/node/integrations/svelte.cjs +76 -0
  25. package/dist/node/integrations/svelte.d.cts +2 -2
  26. package/dist/node/integrations/svelte.d.ts +2 -2
  27. package/dist/node/integrations/svelte.js +2 -1
  28. package/dist/node/{reactive-engine.svelte-1M4m_C_v.d.cts → reactive-engine.svelte-BFIZfawz.d.cts} +199 -1
  29. package/dist/node/{reactive-engine.svelte-ChNFn4Hj.d.ts → reactive-engine.svelte-CRNqHlbv.d.ts} +199 -1
  30. package/dist/node/reverse-W7THPV45.js +193 -0
  31. package/dist/node/{terminal-adapter-CWka-yL8.d.ts → terminal-adapter-B-UK_Vdz.d.ts} +28 -3
  32. package/dist/node/{terminal-adapter-CDzxoLKR.d.cts → terminal-adapter-BQSIF5bf.d.cts} +28 -3
  33. package/dist/node/validate-CNHUULQE.js +180 -0
  34. package/docs/core/pluresdb-integration.md +15 -15
  35. package/docs/decision-ledger/BEHAVIOR_LEDGER.md +225 -0
  36. package/docs/decision-ledger/DecisionLedger.tla +180 -0
  37. package/docs/decision-ledger/IMPLEMENTATION_SUMMARY.md +217 -0
  38. package/docs/decision-ledger/LATEST.md +166 -0
  39. package/docs/guides/cicd-pipeline.md +142 -0
  40. package/package.json +2 -2
  41. package/src/__tests__/cli-validate.test.ts +197 -0
  42. package/src/__tests__/decision-ledger.test.ts +485 -0
  43. package/src/__tests__/reverse-generator.test.ts +189 -0
  44. package/src/__tests__/scanner.test.ts +215 -0
  45. package/src/cli/commands/reverse.ts +289 -0
  46. package/src/cli/commands/validate.ts +264 -0
  47. package/src/cli/index.ts +47 -0
  48. package/src/core/pluresdb/adapter.ts +45 -2
  49. package/src/core/rules.ts +133 -0
  50. package/src/decision-ledger/README.md +400 -0
  51. package/src/decision-ledger/REVERSE_ENGINEERING.md +484 -0
  52. package/src/decision-ledger/facts-events.ts +121 -0
  53. package/src/decision-ledger/index.ts +70 -0
  54. package/src/decision-ledger/ledger.ts +246 -0
  55. package/src/decision-ledger/logic-ledger.ts +158 -0
  56. package/src/decision-ledger/reverse-generator.ts +426 -0
  57. package/src/decision-ledger/scanner.ts +506 -0
  58. package/src/decision-ledger/types.ts +247 -0
  59. package/src/decision-ledger/validation.ts +336 -0
  60. package/src/dsl/index.ts +13 -2
  61. package/src/index.browser.ts +2 -0
  62. package/src/index.ts +36 -0
  63. package/src/integrations/pluresdb.ts +14 -2
@@ -1,9 +1,39 @@
1
+ import {
2
+ AcknowledgeContractGap,
3
+ BehaviorLedger,
4
+ ContractAdded,
5
+ ContractGapAcknowledged,
6
+ ContractMissing,
7
+ ContractUpdated,
8
+ ContractValidated,
9
+ ValidateContracts,
10
+ createBehaviorLedger,
11
+ defineConstraint,
12
+ defineEvent,
13
+ defineFact,
14
+ defineModule,
15
+ defineRule,
16
+ filterEvents,
17
+ filterFacts,
18
+ findEvent,
19
+ findFact,
20
+ formatValidationReport,
21
+ formatValidationReportJSON,
22
+ formatValidationReportSARIF,
23
+ validateContracts
24
+ } from "./chunk-5RH7UAQC.js";
25
+ import {
26
+ defineContract,
27
+ getContract,
28
+ isContract
29
+ } from "./chunk-WZ6B3LZ6.js";
1
30
  import {
2
31
  InMemoryPraxisDB,
3
32
  PluresDBPraxisAdapter,
4
33
  createInMemoryDB,
5
- createPluresDB
6
- } from "./chunk-JQ64KMLN.js";
34
+ createPluresDB,
35
+ createPraxisLocalFirst
36
+ } from "./chunk-MBVHLOU2.js";
7
37
  import {
8
38
  StateDocsGenerator,
9
39
  createStateDocsGenerator,
@@ -18,10 +48,12 @@ import {
18
48
  validateWithGuardian
19
49
  } from "./chunk-SRM3OPPM.js";
20
50
  import {
21
- PraxisRegistry,
22
51
  ReactiveLogicEngine,
23
52
  createReactiveEngine
24
- } from "./chunk-LE2ZJYFC.js";
53
+ } from "./chunk-PRPQO6R5.js";
54
+ import {
55
+ PraxisRegistry
56
+ } from "./chunk-R2PSBPKQ.js";
25
57
  import {
26
58
  TerminalAdapter,
27
59
  createMockExecutor,
@@ -590,65 +622,6 @@ function createIntrospector(registry) {
590
622
  return new RegistryIntrospector(registry);
591
623
  }
592
624
 
593
- // src/dsl/index.ts
594
- function defineFact(tag) {
595
- return {
596
- tag,
597
- create(payload) {
598
- return { tag, payload };
599
- },
600
- is(fact) {
601
- return fact.tag === tag;
602
- }
603
- };
604
- }
605
- function defineEvent(tag) {
606
- return {
607
- tag,
608
- create(payload) {
609
- return { tag, payload };
610
- },
611
- is(event) {
612
- return event.tag === tag;
613
- }
614
- };
615
- }
616
- function defineRule(options) {
617
- return {
618
- id: options.id,
619
- description: options.description,
620
- impl: options.impl,
621
- meta: options.meta
622
- };
623
- }
624
- function defineConstraint(options) {
625
- return {
626
- id: options.id,
627
- description: options.description,
628
- impl: options.impl,
629
- meta: options.meta
630
- };
631
- }
632
- function defineModule(options) {
633
- return {
634
- rules: options.rules ?? [],
635
- constraints: options.constraints ?? [],
636
- meta: options.meta
637
- };
638
- }
639
- function filterEvents(events, definition) {
640
- return events.filter(definition.is);
641
- }
642
- function filterFacts(facts, definition) {
643
- return facts.filter(definition.is);
644
- }
645
- function findEvent(events, definition) {
646
- return events.find(definition.is);
647
- }
648
- function findFact(facts, definition) {
649
- return facts.find(definition.is);
650
- }
651
-
652
625
  // src/core/pluresdb/store.ts
653
626
  var PRAXIS_PATHS = {
654
627
  /** Base path for all Praxis data */
@@ -1471,7 +1444,7 @@ function generateTauriConfig(config) {
1471
1444
  // src/integrations/unified.ts
1472
1445
  async function createUnifiedApp(config) {
1473
1446
  const { createPraxisEngine: createPraxisEngine2 } = await import("./engine-2DQBKBJC.js");
1474
- const { createInMemoryDB: createInMemoryDB2 } = await import("./adapter-K6DOX6XS.js");
1447
+ const { createInMemoryDB: createInMemoryDB2 } = await import("./adapter-75ISSMWD.js");
1475
1448
  const db = config.db || createInMemoryDB2();
1476
1449
  const pluresdb = createPluresDBAdapter({
1477
1450
  db,
@@ -1545,7 +1518,7 @@ async function createUnifiedApp(config) {
1545
1518
  };
1546
1519
  }
1547
1520
  async function attachAllIntegrations(engine, registry, options = {}) {
1548
- const { createInMemoryDB: createInMemoryDB2 } = await import("./adapter-K6DOX6XS.js");
1521
+ const { createInMemoryDB: createInMemoryDB2 } = await import("./adapter-75ISSMWD.js");
1549
1522
  const db = options.db || createInMemoryDB2();
1550
1523
  const pluresdb = createPluresDBAdapter({
1551
1524
  db,
@@ -1600,7 +1573,14 @@ async function attachAllIntegrations(engine, registry, options = {}) {
1600
1573
  };
1601
1574
  }
1602
1575
  export {
1576
+ AcknowledgeContractGap,
1603
1577
  ActorManager,
1578
+ BehaviorLedger,
1579
+ ContractAdded,
1580
+ ContractGapAcknowledged,
1581
+ ContractMissing,
1582
+ ContractUpdated,
1583
+ ContractValidated,
1604
1584
  ReactiveLogicEngine2 as FrameworkAgnosticReactiveEngine,
1605
1585
  InMemoryPraxisDB,
1606
1586
  LogicEngine,
@@ -1615,6 +1595,7 @@ export {
1615
1595
  RegistryIntrospector,
1616
1596
  StateDocsGenerator,
1617
1597
  TerminalAdapter,
1598
+ ValidateContracts,
1618
1599
  attachAllIntegrations,
1619
1600
  attachTauriToEngine,
1620
1601
  attachToEngine,
@@ -1622,6 +1603,7 @@ export {
1622
1603
  canvasToMermaid,
1623
1604
  canvasToSchema,
1624
1605
  canvasToYaml,
1606
+ createBehaviorLedger,
1625
1607
  createCanvasEditor,
1626
1608
  createReactiveEngine2 as createFrameworkAgnosticReactiveEngine,
1627
1609
  createInMemoryDB,
@@ -1633,6 +1615,7 @@ export {
1633
1615
  createPluresDBGenerator,
1634
1616
  createPraxisDBStore,
1635
1617
  createPraxisEngine,
1618
+ createPraxisLocalFirst,
1636
1619
  createReactiveEngine,
1637
1620
  createSchemaRegistry,
1638
1621
  createSchemaTemplate,
@@ -1643,6 +1626,7 @@ export {
1643
1626
  createUnifiedApp,
1644
1627
  createUnumAdapter,
1645
1628
  defineConstraint,
1629
+ defineContract,
1646
1630
  defineEvent,
1647
1631
  defineFact,
1648
1632
  defineModule,
@@ -1651,12 +1635,17 @@ export {
1651
1635
  filterFacts,
1652
1636
  findEvent,
1653
1637
  findFact,
1638
+ formatValidationReport,
1639
+ formatValidationReportJSON,
1640
+ formatValidationReportSARIF,
1654
1641
  generateDocs,
1655
1642
  generateId,
1656
1643
  generateTauriConfig,
1644
+ getContract,
1657
1645
  getEventPath,
1658
1646
  getFactPath,
1659
1647
  getSchemaPath,
1648
+ isContract,
1660
1649
  loadSchema,
1661
1650
  loadSchemaFromFile,
1662
1651
  loadSchemaFromJson,
@@ -1664,6 +1653,7 @@ export {
1664
1653
  registerSchema,
1665
1654
  runTerminalCommand,
1666
1655
  schemaToCanvas,
1656
+ validateContracts,
1667
1657
  validateForGeneration,
1668
1658
  validateSchema,
1669
1659
  validateWithGuardian
@@ -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,8 @@
1
1
  import {
2
2
  ReactiveLogicEngine,
3
3
  createReactiveEngine
4
- } from "../chunk-LE2ZJYFC.js";
4
+ } from "../chunk-PRPQO6R5.js";
5
+ import "../chunk-R2PSBPKQ.js";
5
6
  import "../chunk-VOMLVI6V.js";
6
7
  import "../chunk-QGM4M3NI.js";
7
8
 
@@ -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 };