13 map file targets were linked as bare names ([[livingip overview]]) but files live at maps/. Script walks all claim files outside maps/ and prefixes with maps/ path. 351 files modified, zero remaining bare instances, zero double-prefixes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
125 lines
4.3 KiB
Python
125 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Fix broken wiki-links to map files by adding maps/ prefix.
|
|
|
|
These links appear in Topics: sections of claim files. The target files
|
|
exist in maps/ but the links use bare names without the path prefix.
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
|
|
CODEX_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
# Map files that exist — link text (inside [[]]) → correct path prefix
|
|
MAP_TARGETS = [
|
|
"livingip overview",
|
|
"LivingIP architecture",
|
|
"internet finance and decision markets",
|
|
"attractor dynamics",
|
|
"coordination mechanisms",
|
|
"competitive advantage and moats",
|
|
"collective agents",
|
|
"living capital",
|
|
"overview",
|
|
"blockchain infrastructure and coordination",
|
|
"analytical-toolkit",
|
|
"metadao-decision-markets",
|
|
"rio positions",
|
|
]
|
|
|
|
# Verify all targets actually exist as map files
|
|
for target in MAP_TARGETS:
|
|
path = os.path.join(CODEX_ROOT, "maps", f"{target}.md")
|
|
if not os.path.isfile(path):
|
|
print(f"WARNING: maps/{target}.md does not exist — skipping")
|
|
MAP_TARGETS.remove(target)
|
|
|
|
# Build regex: match [[target]] but NOT [[maps/target]] (already fixed)
|
|
# Case-insensitive for safety
|
|
patterns = []
|
|
for target in MAP_TARGETS:
|
|
escaped = re.escape(target)
|
|
# Match [[target]] but not [[maps/target]] or [[anything/target]]
|
|
pattern = re.compile(
|
|
r'\[\[(' + escaped + r')\]\]',
|
|
re.IGNORECASE
|
|
)
|
|
patterns.append((target, pattern))
|
|
|
|
total_fixes = 0
|
|
files_fixed = 0
|
|
|
|
for dirpath, dirnames, filenames in os.walk(CODEX_ROOT):
|
|
# Skip .git and ops directories
|
|
rel = os.path.relpath(dirpath, CODEX_ROOT)
|
|
if rel.startswith('.git') or rel.startswith('ops'):
|
|
continue
|
|
|
|
for fname in filenames:
|
|
if not fname.endswith('.md'):
|
|
continue
|
|
|
|
filepath = os.path.join(dirpath, fname)
|
|
try:
|
|
with open(filepath, 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
except (UnicodeDecodeError, OSError):
|
|
continue
|
|
|
|
original = content
|
|
file_fixes = 0
|
|
|
|
for target, pattern in patterns:
|
|
# Don't fix links that are already prefixed with maps/
|
|
# First check: does the file contain [[maps/target]]? Skip those.
|
|
already_prefixed = re.compile(
|
|
r'\[\[maps/' + re.escape(target) + r'\]\]',
|
|
re.IGNORECASE
|
|
)
|
|
|
|
def replace_bare_link(m):
|
|
# Check if this is inside the maps/ directory itself
|
|
# Map files can reference each other without prefix
|
|
if os.path.relpath(filepath, CODEX_ROOT).startswith('maps/'):
|
|
return m.group(0) # Don't touch links inside maps/
|
|
return f'[[maps/{m.group(1)}]]'
|
|
|
|
content = pattern.sub(replace_bare_link, content)
|
|
fixes_this_target = len(pattern.findall(original)) - len(pattern.findall(content))
|
|
|
|
if content != original:
|
|
file_fixes = sum(
|
|
len(p.findall(original)) - len(p.findall(content))
|
|
for _, p in patterns
|
|
)
|
|
# Recount properly
|
|
file_fixes = 0
|
|
for line_orig, line_new in zip(original.splitlines(), content.splitlines()):
|
|
if line_orig != line_new:
|
|
file_fixes += 1
|
|
|
|
with open(filepath, 'w', encoding='utf-8') as f:
|
|
f.write(content)
|
|
files_fixed += 1
|
|
total_fixes += file_fixes
|
|
|
|
print(f"\nFixed {total_fixes} links across {files_fixed} files")
|
|
|
|
# Show per-target counts
|
|
print("\nPer-target breakdown:")
|
|
for target in MAP_TARGETS:
|
|
pattern = re.compile(r'\[\[maps/' + re.escape(target) + r'\]\]', re.IGNORECASE)
|
|
count = 0
|
|
for dirpath, _, filenames in os.walk(CODEX_ROOT):
|
|
rel = os.path.relpath(dirpath, CODEX_ROOT)
|
|
if rel.startswith('.git') or rel.startswith('ops') or rel.startswith('maps'):
|
|
continue
|
|
for fname in filenames:
|
|
if not fname.endswith('.md'):
|
|
continue
|
|
try:
|
|
with open(os.path.join(dirpath, fname), 'r', encoding='utf-8') as f:
|
|
count += len(pattern.findall(f.read()))
|
|
except (UnicodeDecodeError, OSError):
|
|
continue
|
|
print(f" [[maps/{target}]]: {count} instances")
|