Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0e759-301a-78b1-bbc1-040ef094b12d
55 lines
2.2 KiB
Python
55 lines
2.2 KiB
Python
#!/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()
|