pmat 3.11.0

PMAT - Zero-config AI context generation and code quality toolkit (CLI, MCP, HTTP)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
# Provability Analysis

## Overview

The Provability Analysis feature provides lightweight formal verification capabilities for code properties. It uses abstract interpretation and property domain analysis to prove certain properties about code without full formal methods overhead. This enables developers to gain confidence in critical code properties while maintaining practical analysis times.

## Core Concepts

### Property Domains

The analyzer supports several property domains:

1. **Nullability Analysis** - Proves absence of null pointer dereferences
2. **Alias Analysis** - Tracks pointer aliasing and ownership
3. **Range Analysis** - Proves integer bounds and overflow safety
4. **Initialization Analysis** - Ensures variables are initialized before use
5. **Taint Analysis** - Tracks data flow from untrusted sources
6. **Lifetime Analysis** - Proves memory safety in Rust-like systems

### Confidence Levels

Each property annotation includes a confidence score:

- **High (90-100%)** - Property can be proven with high certainty
- **Medium (70-89%)** - Property likely holds but with some assumptions
- **Low (50-69%)** - Property may hold but requires manual verification

## Command Usage

### Basic Analysis

```bash
# Analyze current directory
pmat analyze proof-annotations

# Specific path with high confidence only
pmat analyze proof-annotations \
  --project-path /path/to/project \
  --high-confidence-only

# Include detailed evidence
pmat analyze proof-annotations --include-evidence
```

### Filtering Options

```bash
# Filter by property type
pmat analyze proof-annotations --property-type nullability

# Filter by verification method
pmat analyze proof-annotations --verification-method abstract-interpretation

# Clear cache for fresh analysis
pmat analyze proof-annotations --clear-cache
```

## Output Formats

### Summary Format (Default)

```
Provability Analysis Results
================================================================================

High Confidence Properties (95%+)
─────────────────────────────────
src/core/parser.rs::parse_input
  ✓ Nullability: Parameter 'input' is never null
  ✓ Bounds: Index 'i' always within array bounds
  ✓ Initialization: All paths initialize 'result'

src/utils/validator.rs::check_range
  ✓ Overflow: No integer overflow possible
  ✓ Range: Return value always in [0, 100]

Medium Confidence Properties (70-94%)
────────────────────────────────────
src/handlers/request.rs::process
  ? Aliasing: No mutable aliasing detected (85%)
  ? Taint: User input properly sanitized (78%)

Total functions analyzed: 234
Properties proven: 156 (66.7%)
Average confidence: 84.3%
```

### JSON Format

```json
{
  "analysis_results": [
    {
      "file": "src/core/parser.rs",
      "function": "parse_input",
      "properties": [
        {
          "type": "nullability",
          "property": "parameter_non_null",
          "parameter": "input",
          "confidence": 0.98,
          "evidence": {
            "type": "precondition_check",
            "location": {"line": 15, "column": 8},
            "description": "Explicit null check at function entry"
          }
        },
        {
          "type": "bounds",
          "property": "array_access_safe",
          "confidence": 0.95,
          "evidence": {
            "type": "loop_invariant",
            "invariant": "0 <= i < array.len()",
            "verified_by": "induction"
          }
        }
      ]
    }
  ],
  "summary": {
    "total_functions": 234,
    "functions_with_properties": 178,
    "total_properties": 523,
    "proven_properties": 412,
    "property_distribution": {
      "nullability": 145,
      "bounds": 89,
      "initialization": 67,
      "aliasing": 45,
      "overflow": 34,
      "taint": 32
    }
  }
}
```

## Property Types

### Nullability Properties

Proves that pointers/references are non-null:

```rust
// Proven: input is never null
fn process(input: &str) -> Result<Data> {
    // Analyzer proves this can't panic
    let first_char = input.chars().next().unwrap();
    // ...
}

// Proven: Option is checked before use
fn safe_divide(a: i32, b: Option<i32>) -> Option<i32> {
    b.map(|divisor| a / divisor)  // No division by zero
}
```

### Bounds Properties

Proves array/slice accesses are within bounds:

```rust
// Proven: No out-of-bounds access
fn sum_array(arr: &[i32]) -> i32 {
    let mut sum = 0;
    for i in 0..arr.len() {
        sum += arr[i];  // Proven safe
    }
    sum
}

// Proven: Substring bounds are valid
fn extract_middle(s: &str, start: usize, len: usize) -> &str {
    if start + len <= s.len() {
        &s[start..start + len]  // Proven safe
    } else {
        ""
    }
}
```

### Overflow Properties

Proves absence of integer overflow:

```rust
// Proven: No overflow in factorial
fn factorial(n: u32) -> Option<u32> {
    if n > 12 {
        return None;  // Prevents overflow
    }
    
    let mut result = 1u32;
    for i in 2..=n {
        result *= i;  // Proven: no overflow due to guard
    }
    Some(result)
}
```

### Initialization Properties

Proves variables are initialized before use:

```rust
// Proven: result always initialized
fn find_max(values: &[i32]) -> Option<i32> {
    let mut result;
    
    if values.is_empty() {
        return None;
    }
    
    result = values[0];  // Always executed if not empty
    
    for &val in &values[1..] {
        if val > result {
            result = val;
        }
    }
    
    Some(result)  // Proven: result is initialized
}
```

### Aliasing Properties

Proves absence of problematic aliasing:

```rust
// Proven: No mutable aliasing
fn swap_elements(arr: &mut [i32], i: usize, j: usize) {
    if i != j && i < arr.len() && j < arr.len() {
        // Proven: arr[i] and arr[j] don't alias
        let temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}
```

### Taint Properties

Tracks data flow from untrusted sources:

```python
# Proven: SQL injection safe
def get_user(user_id: str) -> User:
    # Proven: user_id is sanitized before use
    sanitized_id = sanitize_input(user_id)
    query = f"SELECT * FROM users WHERE id = ?"
    return db.execute(query, [sanitized_id])

# Proven: XSS safe
def render_comment(comment: str) -> str:
    # Proven: HTML escaping prevents XSS
    escaped = html.escape(comment)
    return f"<div class='comment'>{escaped}</div>"
```

## Evidence Types

### Direct Evidence

```json
{
  "type": "direct_proof",
  "description": "Explicit check proves property",
  "code_snippet": "if ptr != null { use(ptr) }",
  "confidence": 1.0
}
```

### Inductive Evidence

```json
{
  "type": "loop_invariant",
  "invariant": "0 <= i <= array.length",
  "initialization": "i = 0",
  "preservation": "i++",
  "confidence": 0.95
}
```

### Flow-Sensitive Evidence

```json
{
  "type": "path_analysis",
  "paths_analyzed": 12,
  "paths_proven": 12,
  "description": "All execution paths maintain property",
  "confidence": 0.92
}
```

### Compositional Evidence

```json
{
  "type": "function_contract",
  "callee": "validate_input",
  "postcondition": "return != null",
  "propagated_property": "input validated",
  "confidence": 0.88
}
```

## Integration with Other Tools

### Deep Context Integration

```bash
# Include provability in deep context
pmat analyze deep-context \
  --include-provability \
  --min-confidence 0.8
```

### Refactoring Integration

```bash
# Preserve proven properties during refactoring
pmat refactor serve \
  --preserve-properties \
  --property-confidence 0.9
```

### CI/CD Integration

```yaml
- name: Verify Critical Properties
  run: |
    pmat analyze proof-annotations \
      --property-type nullability \
      --high-confidence-only \
      --format json > properties.json
    
    # Fail if critical properties can't be proven
    if [ $(jq '.summary.proven_properties' properties.json) -lt 50 ]; then
      echo "::error::Failed to prove required properties"
      exit 1
    fi
```

## Advanced Features

### Custom Properties

Define domain-specific properties:

```json
{
  "custom_properties": [
    {
      "name": "monetary_precision",
      "description": "Monetary calculations maintain precision",
      "pattern": "Money\\s*\\*|/\\s*",
      "verification": "range_analysis",
      "constraints": ["no_precision_loss", "no_overflow"]
    }
  ]
}
```

### Incremental Analysis

Leverage caching for faster re-analysis:

```bash
# First run builds cache
pmat analyze proof-annotations

# Subsequent runs are incremental
pmat analyze proof-annotations  # Only analyzes changed files
```

### Property Composition

Combine simple properties into complex guarantees:

```
Memory Safety = Nullability ∧ Bounds ∧ Initialization ∧ No-Aliasing
Security = Taint-Free ∧ Bounds ∧ Input-Validation
```

## Performance Characteristics

### Analysis Speed

- **Small functions (<50 LOC)**: <10ms
- **Medium functions (50-200 LOC)**: 10-50ms
- **Large functions (>200 LOC)**: 50-200ms
- **Cache hit**: <1ms

### Memory Usage

- **Per-function state**: ~10KB
- **Cache overhead**: ~100KB per file
- **Peak memory**: O(largest function)

### Scalability

- Linear in codebase size
- Parallelizable across files
- Incremental analysis support

## Limitations

### Decidability

Some properties are undecidable in general:

- Arbitrary loop termination
- Complex pointer arithmetic
- Recursive data structure properties
- Concurrency properties

### Precision

The analysis is necessarily conservative:

- May report "unknown" for provable properties
- Assumes worst-case for external functions
- Limited inter-procedural analysis depth

### Language Support

Property support varies by language:

| Language | Nullability | Bounds | Overflow | Aliasing | Taint |
|----------|------------|---------|----------|----------|-------|
| Rust     ||||||
| C/C++    |||| Partial  ||
| Python   || Partial | N/A      | Limited  ||
| TypeScript|| Partial | N/A      | Limited  ||

## Best Practices

### 1. Focus on Critical Code

Prioritize proving properties for:
- Security-sensitive functions
- Core algorithms
- API boundaries
- Error handling paths

### 2. Write Provable Code

Structure code to be amenable to analysis:

```rust
// Harder to prove
fn complex_logic(data: &[u8]) -> Option<u32> {
    let mut result = None;
    for i in 0..data.len() {
        if some_complex_condition(i, data) {
            result = Some(calculate(data, i));
            break;
        }
    }
    result
}

// Easier to prove
fn simple_logic(data: &[u8]) -> Option<u32> {
    data.iter()
        .position(|&b| is_target(b))
        .map(|i| calculate_at(data, i))
}
```

### 3. Document Assumptions

Make implicit assumptions explicit:

```rust
/// Assumes: input.len() > 0
/// Proves: No panic, returns value in range [0, 255]
fn process_bytes(input: &[u8]) -> u8 {
    assert!(!input.is_empty());
    // Analysis can now prove properties
    input.iter().fold(0u8, |acc, &b| acc.saturating_add(b))
}
```

### 4. Incremental Adoption

Start with high-value properties:

1. Null safety in critical paths
2. Bounds checking in parsers
3. Overflow prevention in calculations
4. Taint tracking in user input handling

## Related Commands

- `pmat analyze complexity` - Identify complex code needing verification
- `pmat analyze deep-context` - Include provability in analysis
- `pmat refactor interactive` - Refactor while preserving properties
- `pmat analyze defect-prediction` - Correlate properties with defects