@plures/praxis 1.2.0 → 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.
- package/README.md +10 -96
- package/dist/browser/{adapter-TM4IS5KT.js → adapter-CIMBGDC7.js} +5 -3
- package/dist/browser/{chunk-LE2ZJYFC.js → chunk-K377RW4V.js} +76 -0
- package/dist/{node/chunk-JQ64KMLN.js → browser/chunk-MBVHLOU2.js} +12 -1
- package/dist/browser/index.d.ts +32 -5
- package/dist/browser/index.js +15 -7
- package/dist/browser/integrations/svelte.d.ts +2 -2
- package/dist/browser/integrations/svelte.js +1 -1
- package/dist/browser/{reactive-engine.svelte-C9OpcTHf.d.ts → reactive-engine.svelte-9aS0kTa8.d.ts} +136 -1
- package/dist/node/{adapter-K6DOX6XS.js → adapter-75ISSMWD.js} +5 -3
- package/dist/node/chunk-5RH7UAQC.js +486 -0
- package/dist/{browser/chunk-JQ64KMLN.js → node/chunk-MBVHLOU2.js} +12 -1
- package/dist/node/{chunk-LE2ZJYFC.js → chunk-PRPQO6R5.js} +3 -72
- package/dist/node/chunk-R2PSBPKQ.js +150 -0
- package/dist/node/chunk-WZ6B3LZ6.js +638 -0
- package/dist/node/cli/index.cjs +2316 -832
- package/dist/node/cli/index.js +18 -0
- package/dist/node/components/index.d.cts +3 -2
- package/dist/node/components/index.d.ts +3 -2
- package/dist/node/index.cjs +620 -38
- package/dist/node/index.d.cts +259 -5
- package/dist/node/index.d.ts +259 -5
- package/dist/node/index.js +55 -65
- package/dist/node/integrations/svelte.cjs +76 -0
- package/dist/node/integrations/svelte.d.cts +2 -2
- package/dist/node/integrations/svelte.d.ts +2 -2
- package/dist/node/integrations/svelte.js +2 -1
- package/dist/node/{reactive-engine.svelte-1M4m_C_v.d.cts → reactive-engine.svelte-BFIZfawz.d.cts} +199 -1
- package/dist/node/{reactive-engine.svelte-ChNFn4Hj.d.ts → reactive-engine.svelte-CRNqHlbv.d.ts} +199 -1
- package/dist/node/reverse-W7THPV45.js +193 -0
- package/dist/node/{terminal-adapter-CWka-yL8.d.ts → terminal-adapter-B-UK_Vdz.d.ts} +28 -3
- package/dist/node/{terminal-adapter-CDzxoLKR.d.cts → terminal-adapter-BQSIF5bf.d.cts} +28 -3
- package/dist/node/validate-CNHUULQE.js +180 -0
- package/docs/core/pluresdb-integration.md +15 -15
- package/docs/decision-ledger/BEHAVIOR_LEDGER.md +225 -0
- package/docs/decision-ledger/DecisionLedger.tla +180 -0
- package/docs/decision-ledger/IMPLEMENTATION_SUMMARY.md +217 -0
- package/docs/decision-ledger/LATEST.md +166 -0
- package/docs/guides/cicd-pipeline.md +142 -0
- package/package.json +2 -2
- package/src/__tests__/cli-validate.test.ts +197 -0
- package/src/__tests__/decision-ledger.test.ts +485 -0
- package/src/__tests__/reverse-generator.test.ts +189 -0
- package/src/__tests__/scanner.test.ts +215 -0
- package/src/cli/commands/reverse.ts +289 -0
- package/src/cli/commands/validate.ts +264 -0
- package/src/cli/index.ts +47 -0
- package/src/core/pluresdb/adapter.ts +45 -2
- package/src/core/rules.ts +133 -0
- package/src/decision-ledger/README.md +400 -0
- package/src/decision-ledger/REVERSE_ENGINEERING.md +484 -0
- package/src/decision-ledger/facts-events.ts +121 -0
- package/src/decision-ledger/index.ts +70 -0
- package/src/decision-ledger/ledger.ts +246 -0
- package/src/decision-ledger/logic-ledger.ts +158 -0
- package/src/decision-ledger/reverse-generator.ts +426 -0
- package/src/decision-ledger/scanner.ts +506 -0
- package/src/decision-ledger/types.ts +247 -0
- package/src/decision-ledger/validation.ts +336 -0
- package/src/dsl/index.ts +13 -2
- package/src/index.browser.ts +2 -0
- package/src/index.ts +36 -0
- package/src/integrations/pluresdb.ts +14 -2
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
# Decision Ledger - Reverse Engineering Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how to use Praxis's decision ledger reverse engineering capabilities to scan existing codebases and automatically generate contracts for rules and constraints.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The reverse engineering feature helps teams adopt decision ledgers for existing Praxis applications by:
|
|
8
|
+
|
|
9
|
+
1. **Scanning repositories** to discover existing rules and constraints
|
|
10
|
+
2. **Inferring contracts** from code, comments, and tests
|
|
11
|
+
3. **Generating contracts** with AI assistance or heuristic analysis
|
|
12
|
+
4. **Creating migration paths** for legacy codebases
|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
### Basic Usage
|
|
17
|
+
|
|
18
|
+
Scan your codebase and generate contracts:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Basic scan (non-AI, heuristic-based)
|
|
22
|
+
praxis reverse
|
|
23
|
+
|
|
24
|
+
# Specify a directory
|
|
25
|
+
praxis reverse --dir ./src
|
|
26
|
+
|
|
27
|
+
# Save contracts to a specific directory
|
|
28
|
+
praxis reverse --output ./contracts
|
|
29
|
+
|
|
30
|
+
# Write to logic ledger
|
|
31
|
+
praxis reverse --ledger --output ./contracts
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Interactive Mode
|
|
35
|
+
|
|
36
|
+
Review each contract before generating:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
praxis reverse --interactive
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Example session:
|
|
43
|
+
```
|
|
44
|
+
🔍 Scanning repository for rules and constraints...
|
|
45
|
+
Directory: /home/user/myproject
|
|
46
|
+
AI Provider: none
|
|
47
|
+
|
|
48
|
+
✅ Scan complete in 342ms
|
|
49
|
+
Files scanned: 156
|
|
50
|
+
Rules found: 12
|
|
51
|
+
Constraints found: 5
|
|
52
|
+
Test files: 8 mapped
|
|
53
|
+
Spec files: 2 mapped
|
|
54
|
+
|
|
55
|
+
🤖 Generating contracts for 17 items...
|
|
56
|
+
|
|
57
|
+
📝 Processing rule: auth.login
|
|
58
|
+
Generate contract for auth.login? (y/n) y
|
|
59
|
+
✅ Generated (heuristic, confidence: 0.70)
|
|
60
|
+
⚠️ Warnings:
|
|
61
|
+
- No test files found - using default example
|
|
62
|
+
📋 Contract summary:
|
|
63
|
+
Behavior: Process login events and create user sessions
|
|
64
|
+
Examples: 1
|
|
65
|
+
Invariants: 1
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### AI-Powered Generation
|
|
69
|
+
|
|
70
|
+
Use AI to improve contract quality (requires API keys):
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Using OpenAI
|
|
74
|
+
export OPENAI_API_KEY="your-key-here"
|
|
75
|
+
praxis reverse --ai openai
|
|
76
|
+
|
|
77
|
+
# Using GitHub Copilot
|
|
78
|
+
export GITHUB_TOKEN="your-token-here"
|
|
79
|
+
praxis reverse --ai github-copilot
|
|
80
|
+
|
|
81
|
+
# Auto-select (tries GitHub Copilot first, then OpenAI)
|
|
82
|
+
praxis reverse --ai auto
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Dry Run Mode
|
|
86
|
+
|
|
87
|
+
Preview what would be generated without writing files:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
praxis reverse --dry-run
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Advanced Options
|
|
94
|
+
|
|
95
|
+
### Filtering and Limits
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Process only the first 10 rules
|
|
99
|
+
praxis reverse --limit 10
|
|
100
|
+
|
|
101
|
+
# Set confidence threshold (0.0-1.0)
|
|
102
|
+
praxis reverse --confidence 0.8
|
|
103
|
+
|
|
104
|
+
# Specify author for ledger entries
|
|
105
|
+
praxis reverse --author "engineering-team"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Output Formats
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# JSON format (default)
|
|
112
|
+
praxis reverse --format json
|
|
113
|
+
|
|
114
|
+
# YAML format
|
|
115
|
+
praxis reverse --format yaml
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Integration with Validation
|
|
119
|
+
|
|
120
|
+
Generate contracts and validate immediately:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Generate contracts
|
|
124
|
+
praxis reverse --output ./contracts --ledger
|
|
125
|
+
|
|
126
|
+
# Validate the contracts
|
|
127
|
+
praxis validate --output console
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## How It Works
|
|
131
|
+
|
|
132
|
+
### 1. Repository Scanning
|
|
133
|
+
|
|
134
|
+
The scanner traverses your codebase and:
|
|
135
|
+
|
|
136
|
+
- **Finds rule definitions**: Searches for `defineRule()` calls
|
|
137
|
+
- **Finds constraint definitions**: Searches for `defineConstraint()` calls
|
|
138
|
+
- **Maps test files**: Links test files to rules by ID references
|
|
139
|
+
- **Maps spec files**: Links specification files (TLA+, markdown)
|
|
140
|
+
|
|
141
|
+
Example:
|
|
142
|
+
```typescript
|
|
143
|
+
// This will be discovered:
|
|
144
|
+
const loginRule = defineRule({
|
|
145
|
+
id: 'auth.login',
|
|
146
|
+
description: 'Process login events',
|
|
147
|
+
impl: (state, events) => { /* ... */ }
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### 2. Contract Inference
|
|
152
|
+
|
|
153
|
+
For each discovered rule, the system infers:
|
|
154
|
+
|
|
155
|
+
**Behavior Description**:
|
|
156
|
+
- From JSDoc comments above the rule
|
|
157
|
+
- From the `description` field
|
|
158
|
+
- Fallback: derived from rule ID
|
|
159
|
+
|
|
160
|
+
**Examples**:
|
|
161
|
+
- Extracted from test descriptions
|
|
162
|
+
- Parsed as Given/When/Then
|
|
163
|
+
- Default example if no tests found
|
|
164
|
+
|
|
165
|
+
**Invariants**:
|
|
166
|
+
- Extracted from assertions in code
|
|
167
|
+
- Inferred from constraint definitions
|
|
168
|
+
- Default invariants generated
|
|
169
|
+
|
|
170
|
+
**Assumptions**:
|
|
171
|
+
- Generated based on common patterns
|
|
172
|
+
- Includes confidence scores
|
|
173
|
+
- Tracks what artifacts they impact
|
|
174
|
+
|
|
175
|
+
### 3. AI Enhancement (Optional)
|
|
176
|
+
|
|
177
|
+
When AI is enabled:
|
|
178
|
+
|
|
179
|
+
1. **Builds contextual prompt** with rule info, tests, and specs
|
|
180
|
+
2. **Requests contract** from AI provider
|
|
181
|
+
3. **Validates response** against schema
|
|
182
|
+
4. **Falls back to heuristics** if confidence is too low
|
|
183
|
+
|
|
184
|
+
### 4. Output Generation
|
|
185
|
+
|
|
186
|
+
Contracts are written to:
|
|
187
|
+
|
|
188
|
+
- **JSON/YAML files**: One file per rule in output directory
|
|
189
|
+
- **Logic ledger**: Immutable append-only ledger with versioning
|
|
190
|
+
- **Console**: Summary report of what was generated
|
|
191
|
+
|
|
192
|
+
## Configuration
|
|
193
|
+
|
|
194
|
+
### Project Configuration
|
|
195
|
+
|
|
196
|
+
Create a `.praxisrc.json` file in your project root:
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"reverse": {
|
|
201
|
+
"aiProvider": "none",
|
|
202
|
+
"confidenceThreshold": 0.7,
|
|
203
|
+
"includeAssumptions": true,
|
|
204
|
+
"outputDir": "./contracts",
|
|
205
|
+
"author": "team"
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Environment Variables
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# AI providers
|
|
214
|
+
export OPENAI_API_KEY="sk-..."
|
|
215
|
+
export GITHUB_TOKEN="ghp_..."
|
|
216
|
+
|
|
217
|
+
# Default author
|
|
218
|
+
export PRAXIS_AUTHOR="engineering-team"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Migration Workflow
|
|
222
|
+
|
|
223
|
+
### Step 1: Initial Scan
|
|
224
|
+
|
|
225
|
+
Get an overview of your codebase:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
praxis reverse --dry-run
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Review the output to understand:
|
|
232
|
+
- How many rules/constraints exist
|
|
233
|
+
- Which ones have tests/specs
|
|
234
|
+
- Expected contract quality
|
|
235
|
+
|
|
236
|
+
### Step 2: Generate Contracts
|
|
237
|
+
|
|
238
|
+
Generate contracts with iterative refinement:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
# First pass: high-confidence items only
|
|
242
|
+
praxis reverse --confidence 0.8 --output ./contracts
|
|
243
|
+
|
|
244
|
+
# Second pass: review lower-confidence items interactively
|
|
245
|
+
praxis reverse --confidence 0.5 --interactive
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Step 3: Validate and Refine
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
# Validate generated contracts
|
|
252
|
+
praxis validate --output console
|
|
253
|
+
|
|
254
|
+
# Review incomplete contracts
|
|
255
|
+
praxis validate --output json | jq '.incomplete'
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Step 4: Manual Refinement
|
|
259
|
+
|
|
260
|
+
Review and improve generated contracts:
|
|
261
|
+
|
|
262
|
+
1. **Add missing examples** from documentation
|
|
263
|
+
2. **Refine invariants** based on domain knowledge
|
|
264
|
+
3. **Update assumptions** with team input
|
|
265
|
+
4. **Add references** to tickets, docs, specs
|
|
266
|
+
|
|
267
|
+
### Step 5: Commit to Ledger
|
|
268
|
+
|
|
269
|
+
Once satisfied, commit to the logic ledger:
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
praxis reverse --ledger --author "migration-2024"
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Best Practices
|
|
276
|
+
|
|
277
|
+
### 1. Incremental Migration
|
|
278
|
+
|
|
279
|
+
Don't try to migrate everything at once:
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
# Migrate high-priority modules first
|
|
283
|
+
praxis reverse --dir ./src/core --ledger
|
|
284
|
+
|
|
285
|
+
# Then expand
|
|
286
|
+
praxis reverse --dir ./src/features --ledger
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### 2. Test Coverage First
|
|
290
|
+
|
|
291
|
+
Ensure tests exist before reverse engineering:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
# Generate contracts for rules with tests
|
|
295
|
+
praxis reverse --confidence 0.8
|
|
296
|
+
|
|
297
|
+
# Flag rules without tests for manual work
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### 3. Review AI Output
|
|
301
|
+
|
|
302
|
+
Always review AI-generated contracts:
|
|
303
|
+
|
|
304
|
+
- Check behavior descriptions make sense
|
|
305
|
+
- Verify examples match actual behavior
|
|
306
|
+
- Validate invariants are correct
|
|
307
|
+
- Update assumptions with team knowledge
|
|
308
|
+
|
|
309
|
+
### 4. Use Version Control
|
|
310
|
+
|
|
311
|
+
Track contract evolution:
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
# Generate initial contracts
|
|
315
|
+
praxis reverse --output ./contracts
|
|
316
|
+
|
|
317
|
+
# Commit to version control
|
|
318
|
+
git add contracts/
|
|
319
|
+
git commit -m "Initial contract generation"
|
|
320
|
+
|
|
321
|
+
# Iterate and improve
|
|
322
|
+
# ... manual edits ...
|
|
323
|
+
git commit -m "Refine auth.login contract"
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## Troubleshooting
|
|
327
|
+
|
|
328
|
+
### No Rules Found
|
|
329
|
+
|
|
330
|
+
If the scanner doesn't find rules:
|
|
331
|
+
|
|
332
|
+
1. **Check file patterns**: Ensure `defineRule` is used
|
|
333
|
+
2. **Verify paths**: Make sure you're scanning the right directory
|
|
334
|
+
3. **Check exclusions**: node_modules and dist are excluded by default
|
|
335
|
+
|
|
336
|
+
### Low Confidence Scores
|
|
337
|
+
|
|
338
|
+
If contracts have low confidence:
|
|
339
|
+
|
|
340
|
+
1. **Add tests**: Tests significantly increase confidence
|
|
341
|
+
2. **Add JSDoc comments**: Better descriptions improve quality
|
|
342
|
+
3. **Use AI**: AI can infer better contracts from limited info
|
|
343
|
+
|
|
344
|
+
### AI Integration Issues
|
|
345
|
+
|
|
346
|
+
If AI integration fails:
|
|
347
|
+
|
|
348
|
+
1. **Check API keys**: Ensure they're valid and have permissions
|
|
349
|
+
2. **Review quotas**: Ensure you haven't hit rate limits
|
|
350
|
+
3. **Fallback**: System falls back to heuristics automatically
|
|
351
|
+
|
|
352
|
+
## Examples
|
|
353
|
+
|
|
354
|
+
### Example 1: Simple Rule
|
|
355
|
+
|
|
356
|
+
Input code:
|
|
357
|
+
```typescript
|
|
358
|
+
/**
|
|
359
|
+
* Increments the counter when INCREMENT event is received
|
|
360
|
+
*/
|
|
361
|
+
const incrementRule = defineRule({
|
|
362
|
+
id: 'counter.increment',
|
|
363
|
+
description: 'Increment counter',
|
|
364
|
+
impl: (state, events) => {
|
|
365
|
+
const increments = events.filter(e => e.tag === 'INCREMENT');
|
|
366
|
+
return increments.map(() => ({
|
|
367
|
+
tag: 'COUNTER_UPDATED',
|
|
368
|
+
payload: { value: state.context.count + 1 }
|
|
369
|
+
}));
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Generated contract:
|
|
375
|
+
```json
|
|
376
|
+
{
|
|
377
|
+
"ruleId": "counter.increment",
|
|
378
|
+
"behavior": "Increments the counter when INCREMENT event is received",
|
|
379
|
+
"examples": [
|
|
380
|
+
{
|
|
381
|
+
"given": "Counter is at 0",
|
|
382
|
+
"when": "INCREMENT event is received",
|
|
383
|
+
"then": "COUNTER_UPDATED fact with value 1 is emitted"
|
|
384
|
+
}
|
|
385
|
+
],
|
|
386
|
+
"invariants": [
|
|
387
|
+
"Counter value always increases by 1",
|
|
388
|
+
"COUNTER_UPDATED fact is always emitted for INCREMENT event"
|
|
389
|
+
],
|
|
390
|
+
"assumptions": [
|
|
391
|
+
{
|
|
392
|
+
"id": "counter.increment-assumption-1",
|
|
393
|
+
"statement": "Input data is valid and well-formed",
|
|
394
|
+
"confidence": 0.8,
|
|
395
|
+
"justification": "Standard assumption for rule processing",
|
|
396
|
+
"impacts": ["tests", "code"],
|
|
397
|
+
"status": "active"
|
|
398
|
+
}
|
|
399
|
+
],
|
|
400
|
+
"version": "1.0.0",
|
|
401
|
+
"timestamp": "2024-01-28T07:00:00.000Z"
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Example 2: Rule with Tests
|
|
406
|
+
|
|
407
|
+
Input code + tests:
|
|
408
|
+
```typescript
|
|
409
|
+
// rule.ts
|
|
410
|
+
const loginRule = defineRule({
|
|
411
|
+
id: 'auth.login',
|
|
412
|
+
description: 'Process login events',
|
|
413
|
+
impl: (state, events) => { /* ... */ }
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
// rule.test.ts
|
|
417
|
+
describe('auth.login', () => {
|
|
418
|
+
it('should create session when valid credentials provided', () => {
|
|
419
|
+
// test implementation
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
it('should reject invalid credentials', () => {
|
|
423
|
+
// test implementation
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
Generated contract:
|
|
429
|
+
```json
|
|
430
|
+
{
|
|
431
|
+
"ruleId": "auth.login",
|
|
432
|
+
"behavior": "Process login events",
|
|
433
|
+
"examples": [
|
|
434
|
+
{
|
|
435
|
+
"given": "Valid credentials provided",
|
|
436
|
+
"when": "Login event is received",
|
|
437
|
+
"then": "Session is created"
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
"given": "Invalid credentials",
|
|
441
|
+
"when": "Login event is received",
|
|
442
|
+
"then": "Login is rejected"
|
|
443
|
+
}
|
|
444
|
+
],
|
|
445
|
+
"invariants": [
|
|
446
|
+
"Sessions have unique IDs",
|
|
447
|
+
"Only one session per user"
|
|
448
|
+
],
|
|
449
|
+
"assumptions": [
|
|
450
|
+
{
|
|
451
|
+
"id": "auth.login-assumption-1",
|
|
452
|
+
"statement": "Credentials are validated before login",
|
|
453
|
+
"confidence": 0.9,
|
|
454
|
+
"justification": "Inferred from test cases",
|
|
455
|
+
"impacts": ["spec", "tests", "code"],
|
|
456
|
+
"status": "active"
|
|
457
|
+
}
|
|
458
|
+
],
|
|
459
|
+
"references": [
|
|
460
|
+
{
|
|
461
|
+
"type": "test",
|
|
462
|
+
"url": "file://./src/__tests__/rule.test.ts",
|
|
463
|
+
"description": "Tests for auth.login"
|
|
464
|
+
}
|
|
465
|
+
],
|
|
466
|
+
"version": "1.0.0",
|
|
467
|
+
"timestamp": "2024-01-28T07:00:00.000Z"
|
|
468
|
+
}
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
## Next Steps
|
|
472
|
+
|
|
473
|
+
After reverse engineering:
|
|
474
|
+
|
|
475
|
+
1. **Review contracts**: Manually verify and improve
|
|
476
|
+
2. **Add to build**: Run `praxis validate` in CI
|
|
477
|
+
3. **Track evolution**: Use logic ledger for history
|
|
478
|
+
4. **Iterate**: Continuously improve contracts
|
|
479
|
+
|
|
480
|
+
## See Also
|
|
481
|
+
|
|
482
|
+
- [Decision Ledger README](./README.md)
|
|
483
|
+
- [Contract Validation Guide](./VALIDATION.md)
|
|
484
|
+
- [CLI Reference](../../docs/cli.md)
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decision Ledger - Facts and Events
|
|
3
|
+
*
|
|
4
|
+
* Defines the facts and events used by the Decision Ledger system.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { defineFact, defineEvent } from '../dsl/index.js';
|
|
8
|
+
import type { MissingArtifact, Severity } from './types.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Fact: ContractMissing
|
|
12
|
+
*
|
|
13
|
+
* Indicates that a rule or constraint is missing contract artifacts.
|
|
14
|
+
*/
|
|
15
|
+
export const ContractMissing = defineFact<
|
|
16
|
+
'ContractMissing',
|
|
17
|
+
{
|
|
18
|
+
ruleId: string;
|
|
19
|
+
missing: MissingArtifact[];
|
|
20
|
+
severity: Severity;
|
|
21
|
+
message?: string;
|
|
22
|
+
}
|
|
23
|
+
>('ContractMissing');
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Fact: ContractValidated
|
|
27
|
+
*
|
|
28
|
+
* Indicates that a rule or constraint has been validated and has a complete contract.
|
|
29
|
+
*/
|
|
30
|
+
export const ContractValidated = defineFact<
|
|
31
|
+
'ContractValidated',
|
|
32
|
+
{
|
|
33
|
+
ruleId: string;
|
|
34
|
+
version: string;
|
|
35
|
+
timestamp: string;
|
|
36
|
+
}
|
|
37
|
+
>('ContractValidated');
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Event: ACKNOWLEDGE_CONTRACT_GAP
|
|
41
|
+
*
|
|
42
|
+
* Acknowledges a known contract gap with justification.
|
|
43
|
+
*/
|
|
44
|
+
export const AcknowledgeContractGap = defineEvent<
|
|
45
|
+
'ACKNOWLEDGE_CONTRACT_GAP',
|
|
46
|
+
{
|
|
47
|
+
ruleId: string;
|
|
48
|
+
missing: MissingArtifact[];
|
|
49
|
+
justification: string;
|
|
50
|
+
expiresAt?: string;
|
|
51
|
+
}
|
|
52
|
+
>('ACKNOWLEDGE_CONTRACT_GAP');
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Event: VALIDATE_CONTRACTS
|
|
56
|
+
*
|
|
57
|
+
* Triggers validation of all registered contracts.
|
|
58
|
+
*/
|
|
59
|
+
export const ValidateContracts = defineEvent<
|
|
60
|
+
'VALIDATE_CONTRACTS',
|
|
61
|
+
{
|
|
62
|
+
strict?: boolean;
|
|
63
|
+
}
|
|
64
|
+
>('VALIDATE_CONTRACTS');
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Fact: ContractGapAcknowledged
|
|
68
|
+
*
|
|
69
|
+
* Records that a contract gap has been acknowledged.
|
|
70
|
+
*/
|
|
71
|
+
export const ContractGapAcknowledged = defineFact<
|
|
72
|
+
'ContractGapAcknowledged',
|
|
73
|
+
{
|
|
74
|
+
ruleId: string;
|
|
75
|
+
missing: MissingArtifact[];
|
|
76
|
+
justification: string;
|
|
77
|
+
acknowledgedAt: string;
|
|
78
|
+
expiresAt?: string;
|
|
79
|
+
}
|
|
80
|
+
>('ContractGapAcknowledged');
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Event: CONTRACT_ADDED
|
|
84
|
+
*
|
|
85
|
+
* Emitted when a contract is added to a rule or constraint.
|
|
86
|
+
*/
|
|
87
|
+
export const ContractAdded = defineEvent<
|
|
88
|
+
'CONTRACT_ADDED',
|
|
89
|
+
{
|
|
90
|
+
ruleId: string;
|
|
91
|
+
version: string;
|
|
92
|
+
}
|
|
93
|
+
>('CONTRACT_ADDED');
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Event: CONTRACT_UPDATED
|
|
97
|
+
*
|
|
98
|
+
* Emitted when a contract is updated.
|
|
99
|
+
*/
|
|
100
|
+
export const ContractUpdated = defineEvent<
|
|
101
|
+
'CONTRACT_UPDATED',
|
|
102
|
+
{
|
|
103
|
+
ruleId: string;
|
|
104
|
+
previousVersion: string;
|
|
105
|
+
newVersion: string;
|
|
106
|
+
}
|
|
107
|
+
>('CONTRACT_UPDATED');
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Event: CONTRACT_GAP_EMITTED
|
|
111
|
+
*
|
|
112
|
+
* Emitted when contract gaps are surfaced during validation.
|
|
113
|
+
*/
|
|
114
|
+
export const ContractGapEmitted = defineEvent<
|
|
115
|
+
'CONTRACT_GAP_EMITTED',
|
|
116
|
+
{
|
|
117
|
+
ruleId: string;
|
|
118
|
+
missing: MissingArtifact[];
|
|
119
|
+
severity: Severity;
|
|
120
|
+
}
|
|
121
|
+
>('CONTRACT_GAP_EMITTED');
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decision Ledger - Main Entry Point
|
|
3
|
+
*
|
|
4
|
+
* Contract-based validation and documentation for Praxis rules and constraints.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
type Assumption,
|
|
9
|
+
type Reference,
|
|
10
|
+
type Example,
|
|
11
|
+
type Contract,
|
|
12
|
+
type DefineContractOptions,
|
|
13
|
+
type Severity,
|
|
14
|
+
type MissingArtifact,
|
|
15
|
+
type ContractGap,
|
|
16
|
+
type ValidationReport,
|
|
17
|
+
defineContract,
|
|
18
|
+
getContract,
|
|
19
|
+
getContractFromDescriptor,
|
|
20
|
+
isContract,
|
|
21
|
+
} from './types.js';
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
ContractMissing,
|
|
25
|
+
ContractValidated,
|
|
26
|
+
AcknowledgeContractGap,
|
|
27
|
+
ValidateContracts,
|
|
28
|
+
ContractGapAcknowledged,
|
|
29
|
+
ContractAdded,
|
|
30
|
+
ContractUpdated,
|
|
31
|
+
ContractGapEmitted,
|
|
32
|
+
} from './facts-events.js';
|
|
33
|
+
|
|
34
|
+
export {
|
|
35
|
+
type ValidateOptions,
|
|
36
|
+
type ArtifactIndex,
|
|
37
|
+
validateContracts,
|
|
38
|
+
formatValidationReport,
|
|
39
|
+
formatValidationReportJSON,
|
|
40
|
+
formatValidationReportSARIF,
|
|
41
|
+
} from './validation.js';
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
type LedgerEntry,
|
|
45
|
+
type LedgerEntryStatus,
|
|
46
|
+
BehaviorLedger,
|
|
47
|
+
createBehaviorLedger,
|
|
48
|
+
} from './ledger.js';
|
|
49
|
+
|
|
50
|
+
export {
|
|
51
|
+
type LogicLedgerEntry,
|
|
52
|
+
type LogicLedgerWriteOptions,
|
|
53
|
+
type LogicLedgerIndex,
|
|
54
|
+
writeLogicLedgerEntry,
|
|
55
|
+
} from './logic-ledger.js';
|
|
56
|
+
|
|
57
|
+
export {
|
|
58
|
+
type ScanOptions,
|
|
59
|
+
type ScanResult,
|
|
60
|
+
type DiscoveredArtifact,
|
|
61
|
+
scanRepository,
|
|
62
|
+
inferContractFromFile,
|
|
63
|
+
} from './scanner.js';
|
|
64
|
+
|
|
65
|
+
export {
|
|
66
|
+
type AIProvider,
|
|
67
|
+
type ReverseGenerationOptions,
|
|
68
|
+
type GenerationResult,
|
|
69
|
+
generateContractFromRule,
|
|
70
|
+
} from './reverse-generator.js';
|