# Memory Verifier Algorithm

**Status:** Active
**Version:** 1.0
**Implemented by:** `script/_lib/memory_drift_check.py`

---

## 1. Overview

The Memory Verifier runs `script/memory-drift-check` against deployed memory files in `memory/` (or any path specified via `--files`). It produces a structured verdict: PASS, WARN, or FAIL per file, plus an overall sweep result.

All logic is implemented in `script/_lib/memory_drift_check.py`. The bash shim `script/memory-drift-check` delegates to it.

---

## 2. Input Sources

| Input | Source |
|-------|--------|
| Memory files to check | `memory/` directory (excluding `memory/templates/` and `memory/archive/`) |
| Policy configuration | `.abi/memory_policy.yml` |
| Template definitions | `memory/templates/*.md` |
| Disallowed patterns | `memory_policy.yml → disallowed_patterns` |

---

## 3. Check Categories

### 3.1 `unfilled_markers`

Scan each memory file for unfilled template markers:

```
Pattern: <!-- REQUIRED: \w+ -->
```

Any match is a WARN finding. Rationale: unfilled markers indicate incomplete population of a template field.

**Verdict contribution:** WARN per marker found.

---

### 3.2 `required_sections`

Each deployed memory file is classified by filename stem. Required sections are defined per type:

| File stem | Required sections |
|-----------|------------------|
| `STATE` | `## Current State`, `## Phase`, `## Known Issues` |
| `TASKS` | `## Active`, `## Backlog`, `## Completed` |
| `DECISIONS` | `## Decision Log`, `## Pending` |
| `RISKS` | `## Risk Register`, `## Mitigations` |
| `INTERFACES` | `## Interface Ledger`, `## Contracts` |
| `GLOSSARY` | `## Terms` |
| `RESUME_PROMPT` | `## Context`, `## Last Known State`, `## Next Steps` |

A missing required section in a deployed file is a WARN finding. In strict mode, missing sections are FAIL.

Section detection: case-sensitive prefix match on lines beginning with `## ` followed by the section title.

**Verdict contribution:** WARN (or FAIL in strict/block mode) per missing section.

---

### 3.3 `secret_scan`

Scan each memory file against `disallowed_patterns` from `.abi/memory_policy.yml`. These patterns are the same high-signal secret regexes used by `script/context-gate`.

**Built-in patterns (always active, regardless of policy):**

```
-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----
AKIA[A-Z0-9]{16}
ghp_[a-zA-Z0-9]{36}
gho_[a-zA-Z0-9]{36}
sk-ant-[a-zA-Z0-9_-]{20,}
sk-[a-zA-Z0-9]{20,}
```

A secret pattern match is always a FAIL finding, regardless of enforcement mode. Secrets in memory files are a hard error.

**Verdict contribution:** FAIL per pattern match (always).

---

### 3.4 `template_drift`

If a deployed memory file predates its corresponding template (by mtime), emit a WARN suggesting re-verification. This check is advisory only and is skipped when mtime information is unavailable (e.g., in certain CI environments).

**Verdict contribution:** WARN per stale file.

---

## 4. Verdict Computation

### Per-file verdict

```
if any FAIL finding:
    file_verdict = FAIL
elif any WARN finding:
    file_verdict = WARN
else:
    file_verdict = PASS
```

### Overall verdict

```
if any file_verdict == FAIL:
    overall = FAIL
elif any file_verdict == WARN:
    overall = WARN
else:
    overall = PASS
```

### Exit code

| Enforcement mode | PASS | WARN | FAIL |
|-----------------|------|------|------|
| `warn` (default) | 0 | 0 | 0 |
| `block` | 0 | 0 | 1 |
| `strict` | 0 | 1 | 1 |

---

## 5. Output Format

### Human-readable (default)

```
Memory Drift Check
==================
[PASS] memory/STATE.md
[WARN] memory/TASKS.md — missing section: ## Completed
[FAIL] memory/RISKS.md — secret pattern match: AKIA...

Results: 1 passed, 1 warned, 1 failed
Overall: WARN
```

### JSON output (`--json` flag)

```json
{
  "overall": "WARN",
  "enforcement": "warn",
  "files": [
    {
      "path": "memory/STATE.md",
      "verdict": "PASS",
      "findings": []
    },
    {
      "path": "memory/TASKS.md",
      "verdict": "WARN",
      "findings": [
        {"category": "required_sections", "severity": "WARN", "detail": "missing section: ## Completed"}
      ]
    }
  ]
}
```

---

## 6. Archive Exclusion

Files under `memory/archive/` are excluded from all checks. Archives are historical records and are not expected to satisfy current template contracts.

---

## 7. Determinism Properties

- Results depend only on file content, not on filesystem timestamps (except `template_drift` advisory).
- JSON output fields are sorted by key (via `sort_keys=True`).
- File list is sorted lexicographically before processing.
- No random elements, no clock reads in core verdict computation.

---

## 8. Extension Points

To add a new check category:
1. Add a function `check_<category>(content: str, path: Path, policy: dict) -> list[Finding]` in `memory_drift_check.py`.
2. Register it in the `CHECKS` list in `_run_checks()`.
3. Add the category name to `docs/governance/MEMORY_VERIFIER_ALGORITHM.md` (this file).
4. Add at least two tests in `tests/memory-drift/test_memory_drift_check.py`.
