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.
- Step 1: Confirm the map covers every untyped entity-person page (no misses, no extras)
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.
- Step 2: No commit (validation only). If misses were found, update the MAP in this plan file and the Task 2 script identically.
Task 2: Apply the frontmatter backfill
Files: Modify the 62 .wiki/wiki/topics/<slug>.md pages in the map.
- Step 1: Apply
relationship:+relationship-<type>tag to each page
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
- Step 2: Verify all 77 person pages are now typed with valid values
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".
- Step 3: Commit
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
- Step 1: Regenerate the People list with per-entry relationship annotation + legend
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.
- Step 2: Commit
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
- Step 1: Update the vocabulary line for consistency
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)`.
- Step 2: Commit
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
- Step 1: Confirm link integrity unaffected (frontmatter-only change, but verify)
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).
-
Step 2: Run
/wiki:lint --localand confirm 0 broken links, See Also bidirectional, indexes consistent, tag hygiene OK (the newrelationship-*tags are consistent). Article count is unchanged (no new pages). -
Step 3: Set Last lint + add provenance
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]
- Step 4: Commit
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)
- The backfill map covers exactly the 62 untyped person pages (no misses/extras); all values in the 9-term vocab.
- All 77 person pages carry a valid
relationship:+ matchingrelationship-<type>tag; no page bodies changed. -
fuller-people.mdregenerated with per-entry relationship annotation + legend (77 rows, 0 unclassified). - IMP-16 spec vocab line updated to include
chronicler. -
/wiki:lint --localclean; link-integrity unchanged; article count unchanged.