BUCKYVERSE

Relationship Backfill (62 person pages) — Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Backfill a single-primary relationship: field + relationship-<type> tag onto the 62 existing entity-person pages that lack it, so all 77 person pages are relationship-typed; annotate the fuller-people.md registry with each type.

Architecture: Frontmatter-only edits driven by a fixed slug→relationship map (built from each page's existing "Role in Fuller's orbit" prose). No body/link/source changes. Python applies the edits and regenerates the annotated registry (this repo's grep is ugrep; prefer Python).

Tech Stack: Python for the frontmatter edits + registry regen; /wiki:lint for verification. No code, no unit tests.

Note on TDD: Content/metadata task. Verify steps are Python assertions + lint. Commit per task.

Working directory: repo root /Volumes/Storage/belmendo/Projects/buckyverse.org; wiki root .wiki/; branch pluck/imp-18-relationship-backfill.

Controlled vocabulary (9): collaborator · influence-on-fuller · influenced-by-fuller · friend · family · contemporary · rival-critic · forebear · chronicler

The complete slug → relationship map (62 pages):

# authors (21)
amy-edmondson: collaborator
e-j-applewhite: collaborator
hugh-kenner: chronicler
loretta-lorance: chronicler
lloyd-steven-sieden: chronicler
sidney-rosen: chronicler
martin-pawley: chronicler
robert-marks: chronicler
athena-v-lord: chronicler
trevor-blake: chronicler
donald-w-robertson: chronicler
james-meller: chronicler
eva-diaz: chronicler
alex-gerber: chronicler
james-ward: chronicler
l-clark-stevens: chronicler
robert-snyder: chronicler
h-s-m-coxeter: contemporary
siobhan-roberts: contemporary
keith-critchlow: contemporary
david-kruschke: influenced-by-fuller
# referenced figures (41)
alfred-korzybski: influence-on-fuller
charles-howard-hinton: influence-on-fuller
knud-lonberg-holm: influence-on-fuller
ludwig-von-bertalanffy: influence-on-fuller
clark-richert: influenced-by-fuller
david-johnston-builder: influenced-by-fuller
david-w-orr: influenced-by-fuller
george-w-hart: influenced-by-fuller
james-t-baldwin: influenced-by-fuller
jason-f-mclennan: influenced-by-fuller
jeannie-moberly: influenced-by-fuller
robert-anton-wilson: influenced-by-fuller
steve-baer: influenced-by-fuller
stewart-brand: influenced-by-fuller
william-mcdonough: influenced-by-fuller
constance-abernathy: collaborator
edwin-schlossberg: collaborator
joseph-clinton: collaborator
kenneth-snelson: collaborator
medard-gabel: collaborator
norman-foster: collaborator
peter-jon-pearce: collaborator
shoji-sadao: collaborator
hideo-sasaki: contemporary
john-dos-passos: contemporary
manly-p-hall: contemporary
marina-warner: contemporary
martin-gardner: contemporary
nicolas-bourbaki: contemporary
paolo-soleri: contemporary
rammellzee: contemporary
robert-sapolsky: contemporary
rupert-sheldrake: contemporary
ruth-asawa: contemporary
stanislaw-ulam: contemporary
ted-nelson: contemporary
alicia-boole-stott: forebear
anton-wilhelm-amo: forebear
josiah-willard-gibbs: forebear
lewis-mumford: rival-critic

(21 authors + 40 referenced figures = 61 mapped here; Task 1 reconciles this against the actual untyped-page count and surfaces any miss to add — e.g. if a page the scan didn't classify remains, read its Role prose and add it.) Notable single-relation judgment calls to confirm with the user: Kenneth Snelson (collaborator, though the tensegrity-credit dispute also reads rival-critic); Lewis Mumford (rival-critic as the critical counterweight); Nicolas Bourbaki (contemporary, the formalist "opposite pole").


Task 1: Build and validate the backfill map

Files: none written — validates the map covers exactly the untyped pages.

cd /Volumes/Storage/belmendo/Projects/buckyverse.org/.wiki
python3 - <<'PY'
import glob, re
MAP = """amy-edmondson collaborator
e-j-applewhite collaborator
hugh-kenner chronicler
loretta-lorance chronicler
lloyd-steven-sieden chronicler
sidney-rosen chronicler
martin-pawley chronicler
robert-marks chronicler
athena-v-lord chronicler
trevor-blake chronicler
donald-w-robertson chronicler
james-meller chronicler
eva-diaz chronicler
alex-gerber chronicler
james-ward chronicler
l-clark-stevens chronicler
robert-snyder chronicler
h-s-m-coxeter contemporary
siobhan-roberts contemporary
keith-critchlow contemporary
david-kruschke influenced-by-fuller
alfred-korzybski influence-on-fuller
charles-howard-hinton influence-on-fuller
knud-lonberg-holm influence-on-fuller
ludwig-von-bertalanffy influence-on-fuller
clark-richert influenced-by-fuller
david-johnston-builder influenced-by-fuller
david-w-orr influenced-by-fuller
george-w-hart influenced-by-fuller
james-t-baldwin influenced-by-fuller
jason-f-mclennan influenced-by-fuller
jeannie-moberly influenced-by-fuller
robert-anton-wilson influenced-by-fuller
steve-baer influenced-by-fuller
stewart-brand influenced-by-fuller
william-mcdonough influenced-by-fuller
constance-abernathy collaborator
edwin-schlossberg collaborator
joseph-clinton collaborator
kenneth-snelson collaborator
medard-gabel collaborator
norman-foster collaborator
peter-jon-pearce collaborator
shoji-sadao collaborator
hideo-sasaki contemporary
john-dos-passos contemporary
manly-p-hall contemporary
marina-warner contemporary
martin-gardner contemporary
nicolas-bourbaki contemporary
paolo-soleri contemporary
rammellzee contemporary
robert-sapolsky contemporary
rupert-sheldrake contemporary
ruth-asawa contemporary
stanislaw-ulam contemporary
ted-nelson contemporary
alicia-boole-stott forebear
anton-wilhelm-amo forebear
josiah-willard-gibbs forebear
lewis-mumford rival-critic"""
mp={ln.split()[0]:ln.split()[1] for ln in MAP.strip().splitlines()}
VOCAB={"collaborator","influence-on-fuller","influenced-by-fuller","friend","family","contemporary","rival-critic","forebear","chronicler"}
untyped=set()
for f in glob.glob("wiki/topics/*.md"):
    if f.endswith("_index.md"): continue
    t=open(f,encoding="utf-8").read()
    if 'entity-person' in t and not re.search(r'^relationship:',t,re.M):
        untyped.add(f.split("/")[-1][:-3])
print("map size:", len(mp))
print("untyped pages:", len(untyped))
print("bad vocab values:", [v for v in mp.values() if v not in VOCAB] or "none")
print("in map but NOT untyped (extras):", sorted(set(mp)-untyped) or "none")
print("untyped but NOT in map (misses):", sorted(untyped-set(mp)) or "none")
PY

Expected: map size == untyped count; no bad vocab; no extras; no misses. If there are misses (a page the earlier scan didn't classify), read that page's ## Role in Fuller's orbit and add it to the map with the dominant relation before proceeding.


Task 2: Apply the frontmatter backfill

Files: Modify the 62 .wiki/wiki/topics/<slug>.md pages in the map.

cd /Volumes/Storage/belmendo/Projects/buckyverse.org/.wiki
python3 - <<'PY'
import re
MAP = open("/dev/stdin").read() if False else None
# paste the SAME map string as Task 1:
MAPSTR = """amy-edmondson collaborator
e-j-applewhite collaborator
hugh-kenner chronicler
loretta-lorance chronicler
lloyd-steven-sieden chronicler
sidney-rosen chronicler
martin-pawley chronicler
robert-marks chronicler
athena-v-lord chronicler
trevor-blake chronicler
donald-w-robertson chronicler
james-meller chronicler
eva-diaz chronicler
alex-gerber chronicler
james-ward chronicler
l-clark-stevens chronicler
robert-snyder chronicler
h-s-m-coxeter contemporary
siobhan-roberts contemporary
keith-critchlow contemporary
david-kruschke influenced-by-fuller
alfred-korzybski influence-on-fuller
charles-howard-hinton influence-on-fuller
knud-lonberg-holm influence-on-fuller
ludwig-von-bertalanffy influence-on-fuller
clark-richert influenced-by-fuller
david-johnston-builder influenced-by-fuller
david-w-orr influenced-by-fuller
george-w-hart influenced-by-fuller
james-t-baldwin influenced-by-fuller
jason-f-mclennan influenced-by-fuller
jeannie-moberly influenced-by-fuller
robert-anton-wilson influenced-by-fuller
steve-baer influenced-by-fuller
stewart-brand influenced-by-fuller
william-mcdonough influenced-by-fuller
constance-abernathy collaborator
edwin-schlossberg collaborator
joseph-clinton collaborator
kenneth-snelson collaborator
medard-gabel collaborator
norman-foster collaborator
peter-jon-pearce collaborator
shoji-sadao collaborator
hideo-sasaki contemporary
john-dos-passos contemporary
manly-p-hall contemporary
marina-warner contemporary
martin-gardner contemporary
nicolas-bourbaki contemporary
paolo-soleri contemporary
rammellzee contemporary
robert-sapolsky contemporary
rupert-sheldrake contemporary
ruth-asawa contemporary
stanislaw-ulam contemporary
ted-nelson contemporary
alicia-boole-stott forebear
anton-wilhelm-amo forebear
josiah-willard-gibbs forebear
lewis-mumford rival-critic"""
mp={ln.split()[0]:ln.split()[1] for ln in MAPSTR.strip().splitlines()}
changed=0
for slug,rel in mp.items():
    f=f"wiki/topics/{slug}.md"; t=open(f,encoding="utf-8").read()
    if re.search(r'^relationship:',t,re.M): continue
    # insert `relationship: <rel>` right after the `verified:` line
    t2=re.sub(r'(^verified:.*$)', r'\1\nrelationship: '+rel, t, count=1, flags=re.M)
    # add relationship-<rel> tag into the tags: [...] list (after entity-person)
    t2=re.sub(r'(tags:\s*\[entity-person)', r'\1, relationship-'+rel, t2, count=1)
    if t2==t: 
        print("WARN no change:", slug); continue
    open(f,"w",encoding="utf-8").write(t2); changed+=1
print("pages updated:", changed)
PY
cd /Volumes/Storage/belmendo/Projects/buckyverse.org/.wiki
python3 - <<'PY'
import glob, re
VOCAB={"collaborator","influence-on-fuller","influenced-by-fuller","friend","family","contemporary","rival-critic","forebear","chronicler"}
persons=[f for f in glob.glob("wiki/topics/*.md") if 'entity-person' in open(f,encoding="utf-8").read()]
missing=[]; bad=[]; tagmiss=[]
for f in persons:
    t=open(f,encoding="utf-8").read()
    m=re.search(r'^relationship:\s*(\S+)',t,re.M)
    if not m: missing.append(f); continue
    if m.group(1) not in VOCAB: bad.append((f,m.group(1)))
    if f"relationship-{m.group(1)}" not in t: tagmiss.append(f)
print("person pages:", len(persons))
print("missing relationship:", missing or "none")
print("bad values:", bad or "none")
print("missing relationship-<type> tag:", tagmiss or "none")
PY

Expected: person pages 77; missing/bad/tag-missing all "none".

cd /Volumes/Storage/belmendo/Projects/buckyverse.org
git add .wiki/wiki/topics/
git commit -m "feat: backfill relationship: field + tag onto 62 person pages (all 77 typed)"

Task 3: Annotate the fuller-people.md registry

Files: Modify .wiki/wiki/references/fuller-people.md

cd /Volumes/Storage/belmendo/Projects/buckyverse.org/.wiki
python3 - <<'PY'
import glob, re
rows=[]
for f in glob.glob("wiki/topics/*.md"):
    if f.endswith("_index.md"): continue
    t=open(f,encoding="utf-8").read()
    if 'entity-person' not in t: continue
    title=re.search(r'^title:\s*"(.*)"',t,re.M).group(1)
    rel=re.search(r'^relationship:\s*(\S+)',t,re.M)
    rel=rel.group(1) if rel else "unclassified"
    slug=f.split("/")[-1][:-3]
    rows.append((title, f"- [{title}](../topics/{slug}.md) — {rel}"))
rows.sort(key=lambda r:r[0].lower())
body="\n".join(r[1] for r in rows); n=len(rows)
legend=("*Relationship types: collaborator · influence-on-fuller · influenced-by-fuller · "
        "friend · family · contemporary · rival-critic · forebear · chronicler (documented/wrote about Fuller).*\n\n")
f="wiki/references/fuller-people.md"; t=open(f,encoding="utf-8").read()
t=re.sub(r'## People\n\n.*?\n\n## See Also', "## People\n\n"+legend+body+"\n\n## See Also", t, count=1, flags=re.S)
open(f,"w",encoding="utf-8").write(t)
print("registry rows:", n, "| unclassified:", body.count("— unclassified"))
PY

Expected: registry rows 77; unclassified 0.

cd /Volumes/Storage/belmendo/Projects/buckyverse.org
git add .wiki/wiki/references/fuller-people.md
git commit -m "feat: annotate fuller-people.md registry with relationship types + legend"

Task 4: Add chronicler to the IMP-16 spec's vocab line

Files: Modify docs/superpowers/specs/2026-07-01-referenced-people-relationship-map-design.md

In that spec's "relationship: controlled vocabulary" section, append chronicler to the list, with a short note: · chronicler (documented/wrote about Fuller — added in IMP-18)`.

cd /Volumes/Storage/belmendo/Projects/buckyverse.org
git add docs/superpowers/specs/2026-07-01-referenced-people-relationship-map-design.md
git commit -m "docs: add chronicler to the relationship vocab (IMP-18)"

Task 5: Lint and provenance

Files: Modify .wiki/_index.md (Last lint / Recent Changes), .wiki/log.md

cd /Volumes/Storage/belmendo/Projects/buckyverse.org/.wiki
python3 - <<'PY'
import glob, re, os
def sa(t):
    m=re.search(r'^## See Also\s*(.*?)(?=^## |\Z)', t, re.M|re.S)
    return re.findall(r'\]\(([a-z0-9-]+)\.md\)', m.group(1)) if m else []
pages={os.path.basename(f)[:-3]:open(f,encoding="utf-8").read() for f in glob.glob("wiki/topics/*.md") if not f.endswith("_index.md")}
ent=[s for s,t in pages.items() if 'entity-person' in t or 'entity-organization' in t]
broken=[(s,x) for s in ent for x in sa(pages[s]) if x not in pages]
nonrecip=[(s,x) for s in ent for x in sa(pages[s]) if x in pages and s not in sa(pages[x])]
print("broken:", broken or "none"); print("non-reciprocal:", nonrecip or "none")
PY

Expected: both "none" (unchanged from before).

Set Last lint: 2026-07-01 in .wiki/_index.md; add a Recent Changes bullet:

- 2026-07-01: Backfilled the relationship: field onto all 77 person pages (relationship-typed graph) + annotated fuller-people.md registry [IMP-18]

Append to .wiki/log.md:

## [2026-07-01] backfill | relationship: field onto 62 person pages (all 77 typed), registry annotated [IMP-18]
cd /Volumes/Storage/belmendo/Projects/buckyverse.org
git add .wiki/_index.md .wiki/log.md
git commit -m "chore: provenance + lint for relationship backfill"

Verification checklist (whole plan)