Authority axis v1: mint the executive branch + link 27,804 § → office edges
The Code empowers the executive branch, but the mirror only had legislative Bodies — every authority reference pointed at nothing. Fixed by minting the executive branch from the Code's OWN enumerations: 15 Cabinet departments (5 U.S.C. § 101) + 21 Executive-Schedule Level I offices (§ 5312), 42 Body nodes under us/executive/. Then the axis: scripts/extract_authority.py matches named office/department references across all 59,740 sections (guarding against Deputy/Assistant/Under subordinates) and emits data/section_authority_edges.jsonl — 27,804 edges from 17,031 sections (28.7% of the Code) to the offices they empower. build.py renders reciprocal 'empowered by' links on each office node; the section files are never touched. Now: click the Attorney General, see all 2,386 sections that vest authority in it. Named references only in v1 (cabinet-level). Deterministic; body.schema classification enum extended (executive-department/-agency/-office); make check green at 105,746 records. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -756,6 +756,43 @@ def city_arrays(counties):
|
||||
return "[" + ", ".join(yval(c) for c in counties) + "]"
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Executive branch nodes + the authority axis (§ -> office)
|
||||
#
|
||||
# The Code empowers the executive branch, but the mirror only had legislative
|
||||
# Bodies. These nodes are minted from the Code's own enumerations — 5 U.S.C.
|
||||
# §101 (the departments) and §5312 (Executive Schedule Level I, the cabinet-rank
|
||||
# officers) — and the section_authority_edges (a committed input from
|
||||
# scripts/extract_authority.py) render as reciprocal "empowered by" links here.
|
||||
# The 59,740 section files are never touched; the edge lives on the office node.
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
def exec_body_file(title, classification, code, extra_fm, sources, intro,
|
||||
auth_header, auth_verb, edges, cap=25):
|
||||
lines = ["type: Body", f"title: {yval(title)}",
|
||||
f"classification: {yval(classification)}",
|
||||
'chamber: "executive"', f"code: {yval(code)}"]
|
||||
lines += extra_fm
|
||||
lines.append("sources:")
|
||||
for field, src in sources:
|
||||
lines += [f" - field: {field}", f" source: {yval(src)}"]
|
||||
lines += ["confidence: official",
|
||||
f"tags: [body, executive, {classification}]",
|
||||
f"timestamp: {yval(CONGRESS_DATE)}"]
|
||||
body = [f"# {title}", "", intro, ""]
|
||||
if edges:
|
||||
sample = " A sample:" if len(edges) > cap else ""
|
||||
body += [f"## {auth_header}", "",
|
||||
f"{len(edges):,} sections of the U.S. Code {auth_verb}.{sample}", ""]
|
||||
for e in edges[:cap]:
|
||||
body.append(f"- [{e['citation']}](/{e['path']})")
|
||||
if len(edges) > cap:
|
||||
body.append(f"- …and {len(edges) - cap:,} more (full set in "
|
||||
"data/section_authority_edges.jsonl)")
|
||||
body.append("")
|
||||
return "---\n" + "\n".join(lines) + "\n---\n\n" + "\n".join(body).rstrip() + "\n"
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# main
|
||||
# --------------------------------------------------------------------------- #
|
||||
@@ -1011,11 +1048,69 @@ def main():
|
||||
n_city += 1
|
||||
n_skel += 1
|
||||
|
||||
# ---- executive branch nodes + authority axis (§ -> office) ----
|
||||
exec_offices = load("executive_offices.jsonl")
|
||||
authority = load("section_authority_edges.jsonl")
|
||||
edges_by_target = {}
|
||||
for e in authority:
|
||||
edges_by_target.setdefault(e["target"], []).append(e)
|
||||
for lst in edges_by_target.values():
|
||||
lst.sort(key=lambda e: (e["title"] or 0, e["section"]))
|
||||
|
||||
EXEC = OUT / "us" / "executive"
|
||||
n_exec = 0
|
||||
for r in sorted(exec_offices, key=lambda x: x["slug"]):
|
||||
dept_id = f"us/executive/{r['slug']}"
|
||||
head = r["head"]
|
||||
office_id = f"{dept_id}/{head['slug']}"
|
||||
is_dept = r["kind"] == "department"
|
||||
estab = ("5 U.S.C. § 101 (Executive departments)" if is_dept
|
||||
else "5 U.S.C. § 5312 (Executive Schedule, Level I)")
|
||||
|
||||
# department / agency node
|
||||
dept_extra = [f"head: {yval(office_id)}"]
|
||||
if r.get("parent"):
|
||||
dept_extra.append(f"parent: {yval(r['parent'])}")
|
||||
if is_dept:
|
||||
intro = (f"Executive department, established by 5 U.S.C. § 101. "
|
||||
f"Headed by the [{head['name']}](/{office_id}.md).")
|
||||
else:
|
||||
par = (f" It sits within the [Executive Office of the President]"
|
||||
f"(/{r['parent']}.md)." if r.get("parent") else "")
|
||||
intro = (f"Executive agency. Its head, the [{head['name']}](/{office_id}.md), "
|
||||
f"is a Level I position in the Executive Schedule (5 U.S.C. § 5312).{par}")
|
||||
(EXEC / r["slug"]).mkdir(parents=True, exist_ok=True)
|
||||
(EXEC / r["slug"] / "index.md").write_text(exec_body_file(
|
||||
title=r["name"], classification="executive-department" if is_dept else "executive-agency",
|
||||
code=f"EXEC-{r['slug'].upper()}", extra_fm=dept_extra,
|
||||
sources=[("definition", estab)], intro=intro,
|
||||
auth_header="Referenced by the U.S. Code",
|
||||
auth_verb=f"reference this {'department' if is_dept else 'agency'}",
|
||||
edges=edges_by_target.get(dept_id, [])), encoding="utf-8")
|
||||
|
||||
# head office node (the position the law empowers)
|
||||
seat = "department" if is_dept else "agency"
|
||||
office_intro = (f"Cabinet-rank office (Executive Schedule Level I, 5 U.S.C. § 5312), "
|
||||
f"head of the [{r['name']}](/{dept_id}/index.md).")
|
||||
(EXEC / r["slug"] / f"{head['slug']}.md").write_text(exec_body_file(
|
||||
title=head["name"], classification="executive-office",
|
||||
code=f"EXEC-{r['slug'].upper()}-{head['slug'].upper()}",
|
||||
extra_fm=[f"parent: {yval(dept_id)}", 'schedule_level: "I"'],
|
||||
sources=[("definition", "5 U.S.C. § 5312 (Executive Schedule, Level I)")],
|
||||
intro=office_intro,
|
||||
auth_header="Empowered by the U.S. Code",
|
||||
auth_verb="vest authority in this office",
|
||||
edges=edges_by_target.get(office_id, [])), encoding="utf-8")
|
||||
n_exec += 2
|
||||
|
||||
print(f"candidate files: {n_cand} county jurisdictions: {n_county} "
|
||||
f"CD nodes: {n_cd} state-leg district nodes: {n_sld} "
|
||||
f"county->district edges: {len(county_district_edges)}")
|
||||
print(f"city jurisdictions: {n_city} (filled {n_filled}: {n_resolved} GEOID-resolved; "
|
||||
f"skeleton {n_skel}; skipped {n_skipped})")
|
||||
print(f"executive nodes: {n_exec} (departments/agencies + offices) "
|
||||
f"authority edges: {len(authority)} across "
|
||||
f"{len({e['section'] for e in authority})} sections")
|
||||
print(f"person files: {len(person_files)} "
|
||||
f"(federal enriched: {matched}/{sum(1 for r in officeholders if r['level']=='federal')})")
|
||||
print(f"body files: {len(bodies)} "
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Extract the authority axis: U.S. Code section -> executive office/department.
|
||||
|
||||
Named-reference extraction (v1): matches the canonical office and department
|
||||
names in data/executive_offices.jsonl against each section's operative text
|
||||
(the '## Text' body, excluding historical Notes), and emits one edge per
|
||||
(section, target) into data/section_authority_edges.jsonl.
|
||||
|
||||
Deterministic and mechanical — no NLP, no network. This is a committed input,
|
||||
generated like county_district_edges.jsonl; scripts/build.py renders it into
|
||||
reciprocal links on the executive office nodes (the section files are never
|
||||
touched). Relative references ("the Secretary") are out of scope for v1.
|
||||
|
||||
Usage: python3 scripts/extract_authority.py
|
||||
"""
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
REPO = Path(__file__).resolve().parent.parent
|
||||
OFFICES = REPO / "data" / "executive_offices.jsonl"
|
||||
CODE = REPO / "legal" / "us" / "code"
|
||||
OUT = REPO / "data" / "section_authority_edges.jsonl"
|
||||
|
||||
# An alias immediately preceded by one of these is a *different*, lower office
|
||||
# (a Deputy/Assistant/Under Secretary, a Solicitor/Inspector General, etc.) —
|
||||
# not the cabinet-rank principal, so it must not match.
|
||||
SUBORDINATE_PREFIX = re.compile(
|
||||
r"(?:Deputy|Assistant|Associate|Under|Acting|Solicitor|Inspector|Principal|"
|
||||
r"Special|Vice|Former|Additional)\s*$")
|
||||
|
||||
|
||||
def load_targets():
|
||||
"""Return alias-matchers sorted longest-first: (regex, target_id, name, kind, rel)."""
|
||||
targets = []
|
||||
for line in OFFICES.open():
|
||||
r = json.loads(line)
|
||||
dept_id = f"us/executive/{r['slug']}"
|
||||
office_id = f"{dept_id}/{r['head']['slug']}"
|
||||
rel_kind = "references" # a department/agency mention
|
||||
for alias in r["aliases"]:
|
||||
targets.append((alias, dept_id, r["name"], r["kind"], rel_kind))
|
||||
for alias in r["head"]["aliases"]: # the officer the law empowers
|
||||
targets.append((alias, office_id, r["head"]["name"], "office", "empowers"))
|
||||
# longest alias first so "Secretary of the Treasury" wins over any substring
|
||||
targets.sort(key=lambda t: -len(t[0]))
|
||||
return [(re.compile(r"\b" + re.escape(a) + r"\b"), tid, name, kind, rel)
|
||||
for a, tid, name, kind, rel in targets]
|
||||
|
||||
|
||||
def operative_text(md):
|
||||
"""The section's live text only — frontmatter and historical Notes dropped."""
|
||||
parts = md.split("---", 2)
|
||||
body = parts[2] if len(parts) >= 3 else md
|
||||
return re.split(r"\n##\s+Notes", body, maxsplit=1)[0]
|
||||
|
||||
|
||||
def frontmatter_field(md, key):
|
||||
m = re.search(rf"(?m)^{key}:\s*(.+)$", md.split("---", 2)[1] if "---" in md else md)
|
||||
if not m:
|
||||
return None
|
||||
v = m.group(1).strip()
|
||||
return v[1:-1] if len(v) >= 2 and v[0] == v[-1] == '"' else v
|
||||
|
||||
|
||||
def main():
|
||||
targets = load_targets()
|
||||
edges = []
|
||||
for path in sorted(CODE.rglob("section-*.md")):
|
||||
md = path.read_text(encoding="utf-8")
|
||||
text = operative_text(md)
|
||||
section = frontmatter_field(md, "source_identifier")
|
||||
citation = frontmatter_field(md, "citation")
|
||||
title_num = frontmatter_field(md, "title_number")
|
||||
if not section:
|
||||
continue
|
||||
rel_path = str(path.relative_to(REPO))
|
||||
# (target_id) -> [name, kind, rel, mentions]; keep the most-specific hit
|
||||
hits = {}
|
||||
for rx, tid, name, kind, rel in targets:
|
||||
occ = 0
|
||||
for m in rx.finditer(text):
|
||||
pre = text[max(0, m.start() - 24):m.start()]
|
||||
if SUBORDINATE_PREFIX.search(pre):
|
||||
continue
|
||||
occ += 1
|
||||
if occ:
|
||||
cur = hits.get(tid)
|
||||
if cur is None:
|
||||
hits[tid] = [name, kind, rel, occ]
|
||||
else:
|
||||
cur[3] += occ
|
||||
for tid, (name, kind, rel, mentions) in hits.items():
|
||||
edges.append({
|
||||
"section": section,
|
||||
"citation": citation,
|
||||
"path": rel_path,
|
||||
"title": int(title_num) if title_num and title_num.isdigit() else None,
|
||||
"target": tid,
|
||||
"target_name": name,
|
||||
"target_kind": kind,
|
||||
"relationship": rel,
|
||||
"mentions": mentions,
|
||||
})
|
||||
|
||||
edges.sort(key=lambda e: (e["section"], e["target"]))
|
||||
with OUT.open("w", encoding="utf-8") as f:
|
||||
for e in edges:
|
||||
f.write(json.dumps(e, ensure_ascii=False) + "\n")
|
||||
|
||||
sections = len({e["section"] for e in edges})
|
||||
offices = len({e["target"] for e in edges if e["target_kind"] == "office"})
|
||||
print(f"authority edges: {len(edges)} "
|
||||
f"(sections with authority: {sections}; distinct targets hit: {len({e['target'] for e in edges})}; "
|
||||
f"office targets: {offices})")
|
||||
print(f"wrote {OUT.relative_to(REPO)}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user