---
milestone: v1.11
milestone_name: "Merge Gate — v1.9 Ripple Remediation"
status: passed
audited_date: "2026-05-07"
---

# Milestone Audit: v1.11

## Summary

v1.11 completed 27 requirements across 5 phases (46–50), closing all remediation gaps left by the v1.9 frontmatter rationalization. Index path resolution was corrected from hardcoded `"Literature/"` to config-resolved paths; all `library_records` references were purged from source, docs, and command files; the broken Textual TUI was removed entirely (1187 lines); four modules received production-grade hardening (file locking, markdown escaping, UTC timestamps, XSS-safe DOM, workspace integrity checks, empty-safe dicts); and the repair worker had four blind spots closed (condition 4 divergence detection, `--fix` coverage, exception logging, dead code removal). All phases have verified verification reports showing PASSED status.

## Phase Status

| # | Phase | Status | Requirements |
|---|-------|--------|-------------|
| 46 | Index Path Resolution | Complete | 6/6 |
| 47 | Library-Records Deprecation Cleanup | Complete | 7/7 |
| 48 | Textual TUI Removal | Complete | 3/3 |
| 49 | Module Hardening | Complete | 7/7 |
| 50 | Repair Blind Spots | Complete | 4/4 |
| **Total** | **5 phases** | **All Complete** | **27/27** |

## Requirements Coverage

| Requirement | Status | Notes |
|-------------|--------|-------|
| PATH-01 | Passed | 5 workspace fields use config-resolved `literature_dir` via `workspace_dir.relative_to(vault)` |
| PATH-02 | Passed | `library_records` returns `control / "library-records"` matching docstring |
| PATH-03 | Passed | `PAPERFORGE_LITERATURE_DIR` env var correct; no `paperforgeRATURE_DIR` remnants |
| PATH-04 | Passed | `CONFIG_PATH_KEYS` includes `skill_dir` and `command_dir` |
| PATH-05 | Passed | `${LIBRARY_RECORDS}` placeholder removed from `base_views.py` |
| PATH-06 | Passed | Unnecessary `ai_path_str.replace("/", "\\")` removed from `discussion.py` |
| LEGACY-01 | Passed | `status.py` stale-record detection uses control dir; output label uses `formal_notes` |
| LEGACY-02 | Passed | Dead `parse_existing_library_record()` removed from `sync.py` |
| LEGACY-03 | Passed | `"records"` key removed from `ld_deep.py` return dict; tests updated |
| LEGACY-04 | Passed | `repair.py` docstring updated to "Scan formal literature notes" |
| LEGACY-05 | Passed | `setup_wizard.py` post-install updated to single-command workflow |
| LEGACY-06 | Passed | 10 command file copies purged of `library-records` references |
| LEGACY-07 | Passed | Hardcoded `"Literature/"` docstring refs replaced with `{literature_dir}/` in `discussion.py` and `sync.py` |
| DEPR-01 | Passed | 1187 lines of Textual TUI code removed from `setup_wizard.py`; `main()` redirects to help |
| DEPR-02 | Passed | All docs updated to headless-only (`setup-guide.md`, `INSTALLATION.md`) |
| DEPR-03 | Passed | `textual` removed from `pyproject.toml` dependencies and `validate_setup.py` |
| HARDEN-01 | Passed | Cross-process file locking (`filelock.FileLock`) wraps JSON + MD writes in `discussion.py` |
| HARDEN-02 | Passed | `_escape_md()` escapes `*`, `#`, `[`, `]`, `_`, `` ` `` in QA text fields |
| HARDEN-03 | Passed | UTC timestamps (`timezone.utc`) replace CST in `discussion.py` |
| HARDEN-04 | Passed | API key passed via `PADDLEOCR_API_TOKEN` env var instead of `--paddleocr-key` CLI arg |
| HARDEN-05 | Passed | `createEl()` DOM API replaces `innerHTML` in `main.js` (XSS-safe) |
| HARDEN-06 | Passed | `note_path` and `workspace_paths` checked before `/pf-deep` recommendation |
| HARDEN-07 | Passed | Empty dicts `{}` instead of `None` for 3 index aggregate fields in `status.py` |
| REPAIR-01 | Passed | Condition 4 now detects `pending` vs `done/failed` divergence in three-way scan |
| REPAIR-02 | Passed | `--fix` mode prints `[WARNING]` for unhandled divergence types (no silent skips) |
| REPAIR-03 | Passed | All 5 bare `except Exception: pass` blocks replaced with `logger.warning()` |
| REPAIR-04 | Passed | Dead `load_domain_config` import, call, and orphaned dict comprehension removed |

## Gaps

None found. All 27 requirements have passed verification with automated test evidence, static analysis, and manual confirmation recorded in each phase's verification report.

## Tech Debt

1. **2 pre-existing OCR test failures deferred** — `test_retry_exhaustion_becomes_error` (expects `"error"` but gets `"blocked"`) and `test_full_cycle_from_pending_to_done` (expects `"done"` but gets `"queued"`) in `tests/test_ocr_state_machine.py`. These failures predate v1.11 and have been re-deferred through phases 46, 47, 48, and 49. They relate to OCR state-transition status values that no longer match the test expectations — likely an OCR state machine change that needs a dedicated fix phase.

2. **`main.js` runtime not tested** — Obsidian plugin JavaScript cannot be automated in CLI CI. Syntax verified via Node.js `require()`, but full runtime verification requires manual testing in Obsidian.

## Final Test Suite

| Metric | Count |
|--------|-------|
| Total tests | 489 |
| Passed | 485 |
| Skipped | 2 |
| Failed (pre-existing, deferred) | 2 |
| Phase regression failures | 0 |

---

*AUDIT COMPLETE — v1.11 milestone seal verified. All 27 requirements passed. 2 items of tech debt logged for future milestone triage.*
