tools/

Maintenance scripts for the Medical Research Wiki. All are dependency-free Python 3 (standard library only) and operate on the vault root (the parent of this folder). Run them from the vault root:

python3 tools/check_links.py
python3 tools/validate_structure.py
python3 tools/fix_links.py            # dry run
python3 tools/fix_links.py --apply   # write changes

check_links.py

Resolves [[wikilinks]] and relative Markdown links the way Obsidian actually does (filename / shortest-path matching, not frontmatter titles) and reports:

  • DEAD — resolves to no file. (Notion-export URL artifacts and scraped javascript: / Reddit-compose junk inside raw/ are expected noise.)
  • SYNTH→RAW — a synthesized page links to an empty raw note (a real navigation bug).
  • AMBIGUOUS — a bare basename ties across multiple files at the same shortest depth.
  • RELATIVE-DOTS — a link uses a ../ prefix (discouraged; works only by accident).
  • ORPHAN — a synthesized page nothing links to.

Fenced/inline code is ignored, so link syntax shown as examples in docs is not flagged. Exits non-zero if any DEAD or AMBIGUOUS links exist. --json for machine-readable output.

validate_structure.py

Checks that synthesized pages follow SCHEMA.md: frontmatter present; required keys (title, type, evidence_level, confidence); controlled-vocabulary values for type, evidence_level, confidence, and source_class; and that raw sources carry raw frontmatter. Exits non-zero on errors (warnings are non-fatal). --json supported.

Keep the vocabularies in sync with SCHEMA.md. If you add a type or source_class, add it in both places.

fix_links.py

Normalizes internal wikilinks to the vault convention (see SCHEMA.md → Link Conventions): strips ../ prefixes, uses a bare basename when unique and a full vault path when the basename collides, and preserves #anchors and |display aliases (adding an alias when needed so the visible text is unchanged). Only touches body text of non-raw/ pages; leaves raw/ immutable. Default is a dry run; pass --apply to write. Links it cannot resolve unambiguously are reported and left untouched.

Suggested workflow

python3 scripts/backup_vault.py "$(pwd)"   # back up (writes to ~/Backups/ObsidianMedicalResearch)
python3 tools/fix_links.py                 # review proposed link normalizations
python3 tools/fix_links.py --apply         # apply them
python3 tools/check_links.py               # confirm no dead/ambiguous/orphan links
python3 tools/validate_structure.py        # confirm frontmatter/vocabulary