Network Matrices — Machine-Readable Graph Data
On this page
This page is the machine-readable layer of the network map. The Mermaid diagrams show the network visually. These matrices show it computationally — every relationship as a cell in a table, every money flow as a row in a ledger.
Download Formats
| Format | URL | Use Case |
|---|---|---|
| JSON Graph | /graph.json | 37 nodes, 57 typed edges. For D3.js, NetworkX, Neo4j, AI agents. |
| CSV Edge List | /graph.csv | One row per edge. For Excel, Gephi, pandas, R. |
| This Page | You’re here | Human-readable matrices for visual inspection. |
Board Membership Matrix Verified
Who governs what. Every cell is a public record. Blank = no documented role.
| Person | PCA | MacDowell | Purpose Foundation | Anchor Rock | Bank on Banks PAC | OFA Michigan |
|---|---|---|---|---|---|---|
| Brian Roderick Banks | Superintendent | Superintendent | President + Agent | — | — | — |
| Joseph Holland Jr. | — | — | Secretary + Treasurer | — | Treasurer | Officer |
| Judge Cylenthia Miller | Board Chair | — | — | Board Chair (dissolved) | — | — |
| Judge Tenisha Yancey | — | Board Chair | — | — | — | — |
| Lamar Moreland (Asst. AG) | Board Vice Chair | — | — | — | — | — |
| Latisha Johnson (City Council) | Board Secretary | — | — | — | — | — |
Pattern: Two convicted felons control the revenue entities (schools + CMO + foundation). Three judges + two government officials govern the boards. The felon and the judge sit on the same org chart.
Court Assignment Matrix Verified
Which judges sit where. The enterprise generates cases in Wayne County courts. These judges have documented connections to the enterprise.
| Judge | Court | Connection to Enterprise | Status |
|---|---|---|---|
| Judge Cylenthia Miller | Wayne 3rd Circuit | PCA Board Chair | Active — ballot Nov 2026 |
| Judge Aliyah Sabree | Wayne 3rd Circuit (Family) | MSU Law classmate · father = Treasurer | Active — appointed May 2025 |
| ramsey | Wayne 3rd Circuit (Criminal) | 2 family on MacDowell payroll | Active |
| evans | Wayne 3rd Circuit | 21-year mentor | Retired (JTC) |
| Judge Tenisha Yancey | 36th District | MacDowell Board Chair · paid $383.82 | Active |
| Judge Adam Sabree | 36th District | Eric Sabree’s son · Metro Property RICO | Active |
| Judge Sean Perkins | 36th District | Brother = Banks’ attorney | Active |
| Judge David Perkins | Probate Court | Family donations · guardianship jurisdiction | Active |
| Judge Denise Langford Morris (Retired) | Oakland County | Wrote book foreword with fake J.D. | Retired (JAMS) |
Coverage: 4 judges in 3rd Circuit, 3 judges in 36th District, 1 in Probate, 1 in Oakland. Any case involving Banks’ network in Wayne County risks landing before a connected judge.
Money Flow Matrix Verified: All amounts from CFRS, TransparencyUSA, or audited financials
School Revenue Extraction
| From | Through | To | Amount | Rate | Source |
|---|---|---|---|---|---|
| State of Michigan | MacDowell Prep | Purpose Group LLC → Banks | $4,285,201/yr | 72.67% | Audited financials |
| State of Michigan | Purpose Charter Academy | Purpose Group LLC → Banks | TBD | TBD | First year FY2026 |
| Purpose Group LLC | Management fee gap | Unaccounted | $348,489/yr | — | Budget analysis |
Campaign → Enterprise Payments
| From | To | Amount | Year | Note | Source |
|---|---|---|---|---|---|
| Yancey campaign | Banks Strategy LLC | $383.82 | 2024 | Sole contribution AND sole expenditure | CFRS |
| Yancey campaign | Inner Link Graphics | $8,025 | Multiple | Campaign vendor | TransparencyUSA |
| Miller campaign | Banks Strategy LLC | Unknown | — | Vendor relationship documented | CFRS |
| McKinney campaign | Darryl Banks Jr. | $2,283 | 2024 | Extended Banks family member | TransparencyUSA |
| McKinney campaign | Darryl Banks Jr. | $4,483 | Total | Cumulative across cycles | TransparencyUSA |
Enterprise Self-Dealing Loop
State per-pupil funding
→ Schools (PCA + MacDowell)
→ Purpose Group LLC (72.67%)
→ Banks (sole member, salary + fees)
→ Banks Strategy LLC (consulting entity)
← Judge campaign payments ($383.82+)
← Judges who hear enterprise cases
← Cases generated by enterprise schools
Family Matrix Verified
| Person A | Relationship | Person B | Institutional Overlap |
|---|---|---|---|
| Eric Sabree | Father | Judge Aliyah Sabree | Treasurer → 3rd Circuit (Family Division) |
| Eric Sabree | Father | Judge Adam Sabree | Treasurer → 36th District Court |
| Todd Perkins | Brother | Judge Sean Perkins | Banks’ attorney → 36th District Court |
| OD Banks | Father | Brian Banks | BMF Defendant #22 → Enterprise leader |
| Kelly Ramsey | Mother/family | 2 employees | Judge → MacDowell payroll |
Institutional Conflict Matrix Verified
Where personal roles conflict with institutional duties.
| Person | Personal Role | Institutional Role | Conflict |
|---|---|---|---|
| Judge Cylenthia Miller | PCA Board Chair | 3rd Circuit Judge | Governs school · hears cases from school families |
| Lamar Moreland | PCA Board Vice Chair | Asst. Attorney General | AG has RICO/nonprofit fraud jurisdiction |
| Latisha Johnson | PCA Board Secretary | City Council Member | Council oversees DPSCD (PCA’s authorizer) |
| Judge Tenisha Yancey | MacDowell Board Chair | 36th District Judge | Chairs school board · paid school’s owner |
| Sherry Gay-Dagnogo | Banks’ political ally | City Ombudsman | Former charter authorizer now handles Detroit complaints |
| Eric Sabree | Father of 2 judges | County Treasurer | Tax foreclosure pipeline intersects enterprise |
For Analysts and AI Agents
Python (NetworkX)
import json, networkx as nx
with open('graph.json') as f:
data = json.load(f)
G = nx.DiGraph()
for n in data['nodes']:
G.add_node(n['id'], **n)
for e in data['edges']:
G.add_edge(e['source'], e['target'], **e)
# Find all paths from state funding to Banks
for path in nx.all_simple_paths(G, 'macdowell', 'banks'):
print(' → '.join(path))
# Centrality — who is the most connected?
cent = nx.degree_centrality(G)
for node, score in sorted(cent.items(), key=lambda x: -x[1])[:5]:
print(f"{G.nodes[node].get('label', node)}: {score:.3f}")
R (igraph)
library(igraph)
edges <- read.csv("https://detroit.primals.eco/graph.csv")
g <- graph_from_data_frame(edges[, c("source_id", "target_id")], directed = TRUE)
plot(g, vertex.label = V(g)$name, vertex.size = degree(g) * 3)
Gephi
- Download graph.csv
- Import as Edge Table (source_id → target_id)
- Use
edge_typefor edge coloring,weightfor thickness
All data derived from public records. Graph data is CC-BY-SA-4.0. Clone the repository for the full evidence package.