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 changescheck_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 insideraw/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