#!/usr/bin/env python3 """Render groups.json + records.json as one self-contained page: REFERENCE.html.""" import html, json, pathlib here = pathlib.Path(__file__).parent d = json.loads((here / 'groups.json').read_text()) recs = {r['chunk']: r for r in json.loads((here / 'records.json').read_text())} stories = json.loads((here.parent / 'stories.json').read_text()) e = html.escape SRC = {'archetype': 'archetype', 'filled': 'filled gap'} def src(o): if o['source'].startswith('scene:'): n = o['source'].split(':')[1] return f'from scene {n}' + ('' if o['in_group'] else ' (outside this group)') return SRC[o['source']] def moves(m): return ' '.join(f'{e(k)} {e(v)}' for k, v in m.items()) def scene(c): r = recs[c] return (f'
{c} · {e(stories[r["story"]]["title"])} — {e(r["predicament"])}' f'

{e(r["summary"])}

') out = [] for g in d['groups']: out.append(f'''

{g["id"]} · {e(g["name"])}

{e(g["predicament"])}

{e(g["sentence"])} · {len(g["members"])} scenes from {len(g["stories"])} stories ({e(", ".join(g["story_titles"]))}) · stage {g["stage"]}

Options

    {"".join(f"
  1. {e(o['text'])} {src(o)}
    {moves(o['moves'])}
  2. " for o in g["options"])}

Scenes

{"".join(scene(m["chunk"]) for m in g["members"])}
''') un = ''.join(scene(c) for c in d['unassigned']) page = f''' Winesburg Reference Groups

Winesburg, Ohio: reference groups

Sherwood Anderson, 1919 (Standard Ebooks text). 24 stories, 284 scenes cut by the same rule as chunk.py. Summaries, predicaments, groups and options written by Claude by reading every scene: no local inference. A comparison baseline, not a pack. Option moves give a direction only, never a number.

{"".join(out)}

Unassigned ({len(d["unassigned"])})

Scenes that fit no situation recurring in three or more stories.

{un}
''' (here / 'REFERENCE.html').write_text(page, encoding='utf-8') print('wrote', here / 'REFERENCE.html', len(page), 'bytes')