/ .github / scripts / check_doc_source_of_truth.py
check_doc_source_of_truth.py
 1  #!/usr/bin/env python3
 2  from __future__ import annotations
 3  
 4  from pathlib import Path
 5  import re
 6  import sys
 7  
 8  ROOT = Path(__file__).resolve().parents[2]
 9  FILES = [
10      ROOT / 'README.md',
11      ROOT / 'USAGE.md',
12      ROOT / 'PARITY.md',
13      ROOT / 'PHILOSOPHY.md',
14      ROOT / 'ROADMAP.md',
15      ROOT / '.github' / 'FUNDING.yml',
16  ]
17  FILES.extend(sorted((ROOT / 'docs').rglob('*.md')) if (ROOT / 'docs').exists() else [])
18  
19  FORBIDDEN = {
20      r'github\.com/Yeachan-Heo/claw-code(?!-parity)': 'replace old claw-code GitHub links with ultraworkers/claw-code',
21      r'github\.com/code-yeongyu/claw-code': 'replace stale alternate claw-code GitHub links with ultraworkers/claw-code',
22      r'discord\.gg/6ztZB9jvWq': 'replace the stale UltraWorkers Discord invite with the current invite',
23      r'api\.star-history\.com/svg\?repos=Yeachan-Heo/claw-code': 'update star-history embeds to ultraworkers/claw-code',
24      r'star-history\.com/#Yeachan-Heo/claw-code': 'update star-history links to ultraworkers/claw-code',
25      r'assets/clawd-hero\.jpeg': 'rename stale hero asset references to assets/claw-hero.jpeg',
26      r'assets/instructkr\.png': 'remove stale instructkr image references',
27  }
28  
29  errors: list[str] = []
30  for path in FILES:
31      if not path.exists():
32          continue
33      text = path.read_text(encoding='utf-8')
34      for pattern, message in FORBIDDEN.items():
35          for match in re.finditer(pattern, text):
36              line = text.count('\n', 0, match.start()) + 1
37              errors.append(f'{path.relative_to(ROOT)}:{line}: {message}')
38  
39  if errors:
40      print('doc source-of-truth check failed:', file=sys.stderr)
41      for error in errors:
42          print(f'  - {error}', file=sys.stderr)
43      sys.exit(1)
44  
45  print('doc source-of-truth check passed')