# Verification Notes — Tranche G: abi-spec

## Prerequisites

- Python >= 3.12
- uv (package manager)
- Git

## Setup

```bash
cd abi-spec
uv sync --group dev
```

## Commands to Run

### 1. Full Verify (MUST PASS)

```bash
uv run --group dev python script/verify.py
```

**Expected output (last line):**
```
Results: 3 passed, 0 failed
```

### 2. Tests Only (36 expected)

```bash
uv run --group dev python -m pytest tests/ -q
```

**Expected output:**
```
36 passed
```

### 3. Lint Only

```bash
uv run --group dev python -m ruff check src/ tests/ script/
```

**Expected output:**
```
All checks passed!
```

### 4. Version Consistency

```bash
python script/check_version_consistency
```

**Expected output:**
```
INFO: HEAD is untagged (dev commit). Tag checks skipped.
```

### 5. Compile Example PRD

```bash
uv run --group dev python -m abi_spec compile fixtures/prd.json --out /tmp/specpack
```

**Expected output:**
```
spec_id: compiled from fixtures/prd.json
prd_hash: <64-char hex>
manifest_hash: <64-char hex>
output: /tmp/specpack
```

### 6. Validate SpecPack

```bash
uv run --group dev python -m abi_spec validate /tmp/specpack
```

**Expected output:**
```
PASS: /tmp/specpack is valid
```

### 7. Determinism Proof

```bash
uv run --group dev python -c "
from abi_spec.compiler import compile_prd_json_to_specpack
import tempfile, os
t1 = tempfile.mkdtemp()
t2 = tempfile.mkdtemp()
r1 = compile_prd_json_to_specpack('fixtures/prd.json', t1)
r2 = compile_prd_json_to_specpack('fixtures/prd.json', t2)
assert r1['manifest_hash'] == r2['manifest_hash'], 'DETERMINISM FAILURE'
print(f'PASS: manifest_hash={r1[\"manifest_hash\"]}')
"
```

**Expected output:**
```
PASS: manifest_hash=<64-char hex>
```

## File Count Summary

| Directory | Count | Description |
|-----------|-------|-------------|
| `src/abi_spec/` | 5 files | Core Python modules |
| `tests/` | 4 files + __init__.py | Test modules |
| `schemas/` | 1 file | JSON Schema definition |
| `fixtures/` | 1 file | Example PRD |
| `script/` | 5 files | Verification scripts |
| `docs/` | 8 files | Documentation |
| `.github/workflows/` | 1 file | CI configuration |

## Determinism Tests

| Test | What It Proves |
|------|---------------|
| `test_same_input_same_hash_100_times` | 100 compilations produce one hash |
| `test_same_input_same_prd_hash` | PRD hash stable across 10 compilations |
| `test_output_files_byte_identical` | Two compilations produce identical bytes |
| `test_prd_key_order_does_not_affect_hash` | Key reordering does not change hash |

## Timestamp Exclusion Tests

| Test | What It Proves |
|------|---------------|
| `test_manifest_has_no_timestamp_keys` | spec_manifest.json has zero timestamp keys |
| `test_hashes_json_has_no_timestamp_keys` | hashes.json has zero timestamp keys |
| `test_hash_identical_when_prd_has_extra_timestamps` | Extra PRD timestamps don't leak |
| `test_canonical_json_excludes_timestamps` | Canonical payload has no timestamps |
| `test_stable_hash_without_timestamps` | Same PRD → same hash across 10 runs |

## Negative Tests

| Test | What It Verifies |
|------|-----------------|
| `test_invalid_prd_no_requirements` | Rejects PRD without requirements |
| `test_invalid_prd_not_object` | Rejects non-object PRD |
| `test_missing_manifest` | Rejects SpecPack without manifest |
| `test_missing_hashes` | Rejects SpecPack without hashes.json |
| `test_tampered_manifest` | Detects manifest tampering via hash mismatch |
