---
phase: 47-library-records-deprecation-cleanup
plan: 001
type: execute
wave: 1
depends_on: []
files_modified:
  - paperforge/worker/status.py
  - paperforge/worker/sync.py
  - paperforge/worker/repair.py
  - paperforge/skills/literature-qa/scripts/ld_deep.py
  - paperforge/worker/discussion.py
autonomous: true
requirements: [LEGACY-01, LEGACY-02, LEGACY-03, LEGACY-04, LEGACY-07]
must_haves:
  truths:
    - "paperforge status prints `formal_notes` count (not `library_records`)"
    - "paperforge sync no longer constructs record_path or calls parse_existing_library_record()"
    - "ld_deep.py _paperforge_paths() return dict contains no `records` key"
    - "repair.py _detect_path_errors docstring reads 'Scan formal literature notes'"
    - "discussion.py _build_ai_dir docstring uses generic label not hardcoded 'Literature/'"
    - "sync.py migrate_to_workspace docstring uses variable references not 'Literature/'"
  artifacts:
    - path: paperforge/worker/status.py
      provides: stale-record detection path + output label
      min_lines: 756
    - path: paperforge/worker/sync.py
      provides: dead code removed + docstring fixes
      min_lines: 1755
    - path: paperforge/skills/literature-qa/scripts/ld_deep.py
      provides: clean return dict with no records key
      min_lines: 1780
    - path: paperforge/worker/repair.py
      provides: updated docstring
      min_lines: 410
    - path: paperforge/worker/discussion.py
      provides: generic docstring label
      min_lines: 390
  key_links:
    - from: status.py:525
      to: paperforge_paths()["control"]
      via: paths.get("control") replaces paths.get("library_records")
      pattern: paths\.get\("control"\)
    - from: sync.py:700
      to: parse_existing_library_record removed
      via: delete function + call site
      pattern: parse_existing_library_record
---
<objective>
Purge library-records references from all production Python source code.

Purpose: Four LEGACY requirements (01-04) remove library-records references from status.py, sync.py, ld_deep.py, and repair.py. One additional requirement (LEGACY-07) replaces hardcoded "Literature/" docstring references in sync.py and discussion.py with variable/generic labels. After this plan, Python production code contains zero library-records identifiers or stale references.

Output: 5 modified Python files with dead code deleted, docstrings corrected, output labels updated, and path scans re-anchored.
</objective>

<execution_context>
@C:/Users/Lin/.opencode/get-shit-done/workflows/execute-plan.md
@C:/Users/Lin/.opencode/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/phases/47-library-records-deprecation-cleanup/47-CONTEXT.md

<interfaces>
From paperforge/config.py:331:
```python
"library_records": control / "library-records",   # DEPRECATED — still resolves
"control": control,                                 # actual control directory
```

From paperforge/worker/_utils.py:243-267 (pipeline_paths):
```python
def pipeline_paths(vault: Path) -> dict[str, Path]:
    shared = paperforge_paths(vault)
    return {**shared, ...}  # spreads "control", "library_records", etc.
```

From paperforge/config.py:321-336 (paperforge_paths):
```python
return {
    "vault": vault, "system": system, "paperforge": paperforge,
    "exports": paperforge / "exports", "ocr": paperforge / "ocr",
    "zotero_dir": Path(zotero_dir_val), "resources": resources,
    "literature": literature, "control": control,
    "library_records": control / "library-records",  # being phased out
    "bases": bases, "worker_script": worker_script,
    "skill_dir": skill_path, "ld_deep_script": ld_deep_script,
}
```

From paperforge/worker/sync.py:652-669:
```python
def parse_existing_library_record(path: Path) -> dict:
    # Dead function — only caller is line 723 which is also being removed
```
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Fix status.py stale-record scan + label, repair.py docstring, ld_deep.py records key, discussion.py docstring</name>
  <files>
    paperforge/worker/status.py
    paperforge/worker/repair.py
    paperforge/skills/literature-qa/scripts/ld_deep.py
    paperforge/worker/discussion.py
  </files>
  <action>
    Make four independent edits across four files. Verify syntax after each edit.

    === A) status.py:525-533 — Stale-record detection path (LEGACY-01) ===
    - Line 526: Change `_lr_dir = paths.get("library_records")` to `_lr_dir = paths.get("control")`
      Reason: library-records directory no longer exists; scan the control directory for any leftover .md files
    - Line 532: Change message from `f"{_stale_count} stale library-record(s) found — library-records are deprecated in v1.9"` to `f"{_stale_count} stale record(s) found in control directory"`
    - Line 533: Change fix instruction from `"Manually delete the library-records directory after confirming migration"` to `"Review and remove stale files from the control directory"`
    - Also update the comment on line 525 from `# LRD-05: Stale library-records detection` to `# LRD-05: Stale record detection in control directory`

    === B) status.py:728 — Output label (LEGACY-01) ===
    - Line 728: Change `print(f"- library_records: {record_count}")` to `print(f"- formal_notes: {record_count}")`
      Reason: v1.9 deprecated library-records; user-facing label should reflect post-v1.9 reality

    === C) repair.py:33 — Docstring (LEGACY-04) ===
    - Line 33: Change `"""Scan library-records for path_error fields.` to `"""Scan formal literature notes for path_error fields.`
      Reason: library-records no longer exist; repair scans formal notes

    === D) ld_deep.py:32,39 — Docstring + records key (LEGACY-03) ===
    - Line 32: Change docstring `Returns ocr, records, literature keys matching shared resolver output.` to `Returns ocr, literature keys matching shared resolver output.`
    - Line 39: Remove the entire line `"records": shared["library_records"],`
      Reason: library_records key is deprecated; no consumer reads "records" from this dict. `_paperforge_paths` callers only use "ocr" and "literature" keys.
    - Verify no other code reads `["records"]` from the return value of `_paperforge_paths`

    === E) discussion.py:94 — Docstring (LEGACY-07) ===
    - Line 94: Change `Pattern: Literature/{domain}/{key} - {title_slug}/ai/` to `Pattern: {literature_dir}/{domain}/{key} - {title_slug}/ai/`
      Reason: Replace hardcoded "Literature/" with a variable reference to make it clear the path is configurable
  </action>
  <verify>
    <automated>python -c "
import py_compile
for f in ['paperforge/worker/status.py', 'paperforge/worker/repair.py', 'paperforge/skills/literature-qa/scripts/ld_deep.py', 'paperforge/worker/discussion.py']:
    py_compile.compile(f, doraise=True)
    print(f'{f}: OK')
import sys
sys.path.insert(0, '.')
# Verify ld_deep.py no longer returns 'records' key
from paperforge.skills.literature_qa.scripts.ld_deep import _paperforge_paths
result = _paperforge_paths.__code__.co_consts
assert 'records' not in str(result), '_paperforge_paths still returns records key'
print('ld_deep.py records key removed: OK')
# Verify status.py label uses formal_notes
source = open('paperforge/worker/status.py').read()
assert 'formal_notes' in source, 'status.py missing formal_notes label'
assert '- library_records:' not in source, 'status.py still has old library_records label'
print('status.py label updated: OK')
# Verify repair.py docstring
source = open('paperforge/worker/repair.py').read()
assert 'Scan formal literature notes' in source, 'repair.py docstring not updated'
print('repair.py docstring: OK')
"</automated>
  </verify>
  <done>
    status.py: stale-record detection scans control dir, output label is `formal_notes`.
    repair.py: docstring reads "Scan formal literature notes".
    ld_deep.py: return dict has no `records` key.
    discussion.py: docstring uses `{literature_dir}/...` pattern.
    All files syntax-valid.
  </done>
</task>

<task type="auto">
  <name>Task 2: Remove dead parse_existing_library_record from sync.py + fix hardcoded Literature/ docstrings</name>
  <files>paperforge/worker/sync.py</files>
  <action>
    Two independent changes in sync.py. Verify no remaining library-records references after edits.

    === A) Remove dead code (LEGACY-02) ===
    1. Remove the entire function `parse_existing_library_record()` at lines 652-669 (inclusive).
       - Confirm the function has no other callers (verified by grep showing only line 723 references it, which is also being removed).
       - Remove from the `def parse_existing_library_record(...):` line through the last return line.
    
    2. Remove lines 722-723 (the call site):
       - Line 722: `record_path = paths["library_records"] / domain / f"{item['key']}.md"`
       - Line 723: `existing = parse_existing_library_record(record_path)`
       - Reason: These lines constructed a dead `record_path` and called the now-removed function. The `existing` variable was never used downstream (all workflow state now comes from formal note frontmatter).

    === B) Fix hardcoded "Literature/" docstrings (LEGACY-07) ===
    3. Lines 1557-1562: In `migrate_to_workspace()` docstring, change:
       - `Copies each flat note at Literature/<domain>/<key> - <Title>.md into:` to `Copies each flat note at <literature_dir>/<domain>/<key> - <Title>.md into:`
       - `Literature/<domain>/<key> - <Title>/<key> - <Title>.md` to `<literature_dir>/<domain>/<key> - <Title>/<key> - <Title>.md`
       - `Literature/<domain>/<key> - <Title>/deep-reading.md` to `<literature_dir>/<domain>/<key> - <Title>/deep-reading.md`
       - `Literature/<domain>/<key> - <Title>/ai/  (empty directory)` to `<literature_dir>/<domain>/<key> - <Title>/ai/  (empty directory)`
       Reason: Docstrings should reference the configured literature_dir, not hardcode "Literature/".
    
    4. Line 1759: Change `print(f"index-refresh: {total} formal note(s) in Literature/")` to `print(f"index-refresh: {total} formal note(s) in literature")`
       Reason: User-facing label should not hardcode directory name.
  </action>
  <verify>
    <automated>python -c "
import py_compile
py_compile.compile('paperforge/worker/sync.py', doraise=True)
source = open('paperforge/worker/sync.py').read()
# Verify dead code removed
assert 'parse_existing_library_record' not in source, 'Dead function still present'
assert 'record_path = paths' and 'library_records' not in source.split('record_path')[0] if 'record_path' in source else True, 'record_path construction still present (or moved elsewhere)'
# Verify docstring fixed
assert '<literature_dir>/<domain>' in source, 'Docstring still uses hardcoded Literature/'
# Verify label fixed
assert 'in Literature/' not in source, 'Print label still uses hardcoded Literature/'
assert 'in literature' in source, 'Print label not updated to generic form'
print('sync.py: All LEGACY-02 and LEGACY-07 changes verified')
"</automated>
  </verify>
  <done>
    parse_existing_library_record() function removed (no callers).
    record_path construction and dead call removed from run_selection_sync().
    migrate_to_workspace() docstring uses `<literature_dir>/` variable references.
    Print label uses generic "literature" instead of hardcoded "Literature/".
  </done>
</task>

</tasks>

<verification>
1. All 5 Python files compile without syntax errors
2. `grep -n "library_records" paperforge/worker/status.py paperforge/worker/sync.py paperforge/worker/repair.py paperforge/skills/literature-qa/scripts/ld_deep.py paperforge/worker/discussion.py` returns zero hits in production code paths (comments about Phase 37/40/42 in sync.py:757-759 are acceptable historical comments)
3. `grep -n "parse_existing_library_record" paperforge/worker/sync.py` returns zero hits
4. `grep -n "library_records" paperforge/worker/status.py` returns zero hits
5. `grep -n '"records"' paperforge/skills/literature-qa/scripts/ld_deep.py` returns zero hits
6. `grep -n '"Literature/"' paperforge/worker/sync.py` returns zero hits in docstrings/print labels (comments mentioning "Literature/" from Phase 37/40 are acceptable if they exist)
</verification>

<success_criteria>
1. status.py stale-record detection uses `paths.get("control")` instead of `paths.get("library_records")`
2. status.py output label reads `- formal_notes:` (not `- library_records:`)
3. sync.py has no `parse_existing_library_record` function or call
4. ld_deep.py `_paperforge_paths()` returns no `"records"` key
5. repair.py docstring reads "Scan formal literature notes"
6. discussion.py docstring uses `{literature_dir}/` not `"Literature/"`
7. sync.py docstrings use `<literature_dir>/` not `"Literature/"`
8. All files pass Python syntax check
</success_criteria>

<output>
After completion, create `.planning/phases/47-library-records-deprecation-cleanup/47-001-SUMMARY.md`
</output>
