#!/usr/bin/env python3 """Export hall entry evidence as JSONL, without changing or grading seats. Usage: python3 export-pqrst.py /path/to/hall-of-helix [--revision HEAD] Only committed entries at the resolved revision are read. Every entry is emitted, including missing/malformed PQRST sections. Raw text is retained for review. """ import argparse import hashlib import json import re import subprocess from pathlib import Path def git(repo, *args): return subprocess.check_output(['git', '-C', str(repo), *args]) def export(repo, revision): commit = git(repo, 'rev-parse', '--verify', revision + '^{commit}').decode().strip() paths = git(repo, 'ls-tree', '-r', '--name-only', '-z', commit, '--', 'entries/') for name in sorted(p.decode() for p in paths.split(b'\0') if p.endswith(b'.md')): raw = git(repo, 'show', f'{commit}:{name}') text = raw.decode('utf-8') fm = re.match(r'\A---\n(.*?)\n---(?:\n|$)', text, re.S) body = text[fm.end():] if fm else text sections = re.findall(r'^## PQRST estimate\s*\n(.*?)(?=^## |\Z)', body, re.M | re.S | re.I) blocks = [] for section in sections: for match in re.finditer(r'^```[^\n]*\n(PQRST-Estimate\n.*?)^```[ \t]*$', section, re.M | re.S): record = match.group(1) fields = {} for field in re.finditer(r'^([A-Za-z][A-Za-z ]*):[ \t]*(.*?)(?=^[A-Za-z][A-Za-z ]*:|\Z)', record, re.M | re.S): fields.setdefault(field.group(1), []).append(field.group(2).strip()) blocks.append({'raw': record, 'fields': fields}) yield { 'source_commit': commit, 'path': name, 'sha256': hashlib.sha256(raw).hexdigest(), 'frontmatter_raw': fm.group(1) if fm else None, 'pqrst_sections': sections, 'blocks': blocks, } def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('repo', type=Path) parser.add_argument('--revision', default='HEAD') args = parser.parse_args() for record in export(args.repo, args.revision): print(json.dumps(record, ensure_ascii=False)) if __name__ == '__main__': main()