diff --git a/.github/workflows/circuit-briefs.yml b/.github/workflows/circuit-briefs.yml new file mode 100644 index 0000000..779bbfb --- /dev/null +++ b/.github/workflows/circuit-briefs.yml @@ -0,0 +1,35 @@ +name: Circuit brief integrity + +on: + pull_request: + paths: + - "data/map/circuits.json" + - "data/map/orgs.v3.geojson" + - "data/map/stats.v3.json" + - "tools/build-circuit-briefs.py" + - "briefs/**" + - "sitemap.xml" + push: + branches: [master] + paths: + - "data/map/circuits.json" + - "data/map/orgs.v3.geojson" + - "data/map/stats.v3.json" + - "tools/build-circuit-briefs.py" + - "briefs/**" + - "sitemap.xml" + workflow_dispatch: + +permissions: + contents: read + +jobs: + verify: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Verify generated briefs + run: python tools/build-circuit-briefs.py --check diff --git a/.gitignore b/.gitignore index d6953e8..396e61f 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,10 @@ node_modules/ **/node_modules/ npm-debug.log* +# Python +__pycache__/ +*.py[cod] + # Local civic-identity/neighborhood-os runtime artifacts civic-identity.db neighborhood-os.db @@ -54,4 +58,4 @@ fed-a.db* fed-b.db* # Per-node operator config (the example file is in the repo; real one is local) -node.config.json \ No newline at end of file +node.config.json diff --git a/AGENT-TASKS.json b/AGENT-TASKS.json index 688e1a8..5c09ab7 100644 --- a/AGENT-TASKS.json +++ b/AGENT-TASKS.json @@ -160,6 +160,22 @@ "Both link to canonical site URLs (commonweave.earth or simonlpaige.com/commonweave/) where applicable", "Both are kept short enough to be useful (no whole-file dumps)" ] + }, + { + "id": "cw-circuit-brief-audit-001", + "title": "Audit the first four circuit briefs before outreach", + "type": "data", + "agent_ready": true, + "difficulty": "medium", + "goal": "Audit the Hartford, Syracuse, Tulsa, and Durham circuit briefs against current public sources before any brief is delivered through a local channel.", + "files": ["briefs/", "data/map/circuits.json", "OUTREACH-ATTRACTION-PLAN.md"], + "acceptance_criteria": [ + "All listed organizations still have a current public presence", + "Each proposed role is supported by a cited public source or the brief is corrected", + "No listed organization is made more visible than its own public communications support", + "The review records whether the brief should be delivered, revised, or withdrawn", + "No outreach is sent as part of the audit" + ] } ] } diff --git a/OUTREACH-ATTRACTION-PLAN.md b/OUTREACH-ATTRACTION-PLAN.md new file mode 100644 index 0000000..4cf6b68 --- /dev/null +++ b/OUTREACH-ATTRACTION-PLAN.md @@ -0,0 +1,136 @@ +# Attraction Plan: how organizations find Commonweave and want to stay + +*2026-07-03, written as part of the red-team rebuild. Companion to OUTREACH.md +(which governs how we contact people). This document is about the opposite +direction: making the directory useful enough that orgs, networks, and +organizers come to it, claim their place in it, and tell others.* + +The May 2026 automated outreach experiment taught the lesson the hard way: +push doesn't work for a project whose entire value is trust. A cold email +from an unknown directory is spam; the same directory handing you something +you actually need is infrastructure. Everything below is a variation on one +move: **give a specific, verifiable, locally-relevant gift, and make the +next step obvious and voluntary.** + +The asset that makes this possible now exists: `data/map/circuits.json` +identifies groups of nearby organizations that jointly fill the roles of a +documented solution circuit (land + build labor + finance = housing pipeline; +grower + distributor + food access = local food loop; and eight more). That +is information almost no local org has about itself. + +--- + +## Mechanism 1: Circuit introduction briefs (the gift that's also the thesis) + +**What.** A one-page brief per circuit candidate: "Within 12 km of each +other: {Land steward} + {Build labor} + {Community finance}. Together these +three could run a labor-for-housing pipeline. Here's the documented pattern +(LABOR-FOR-HOUSING-GUIDE.md), here's what each role contributes, here's what +usually goes wrong." Rendered from circuits.json with a stable URL per +circuit group (map deep-link + printable page). + +**Why it attracts.** It's the only artifact in this space that tells three +specific orgs something actionable about *each other*. Nobody has to join +anything: the brief is complete without us. If it's wrong, the correction +flow teaches us; if it's right, we're the project that introduced them. + +**How it ships with zero budget.** +- Generator: `tools/build-circuit-briefs.py` renders a static `briefs/` index, + printable page per group, machine-readable manifest, and sitemap entries. + As of 2026-07-22, the source declares 76 candidates but contains 13 groups; + the manifest records that mismatch, and public copy must not claim 76 until + the export is repaired. +- Distribution is NOT bulk email. Route each brief through the most + credible LOCAL channel: the city's co-op development center, a CLT + network's newsletter, one warm human. One brief, hand-delivered, per week + beats 500 sends. +- Every brief ends with: "Are we wrong about one of these three orgs? + Correct us" → prefilled GitHub issue (already wired in map.html). + +**Success metric.** Replies/corrections per brief delivered (target: any +response on 1 in 4); one documented introduction that led to a real meeting +within 90 days. + +## Mechanism 2: Serve federations, not individual orgs + +**What.** Every federation/network in the directory (ICA, RIPESS, Grounded +Solutions, Transition Network, mutual aid hubs...) maintains a member +directory, and every one of those directories is partly stale. We generate +**member-directory health reports**: dead websites, moved orgs, missing +geocodes, members that appear in other networks, members that show up in +circuit candidates. CC0, no strings. + +**Why it attracts.** One conversation with a network reaches hundreds of +orgs with borrowed trust. Networks have a real, unglamorous maintenance +problem we can partially automate. The report is useful even if they ignore +us forever — which is exactly why it works. + +**How it ships.** `tools/federation-health-report.py` reading the DB + +link-checker (a weekend). Deliver v1 to the two networks already curated in +`data/federations.yaml` (ICA, and pick one of RIPESS/Grounded Solutions). +Ask nothing except "is this useful? what did we get wrong?" + +**Success metric.** 1 network integrates or replies substantively per +quarter; their members start appearing in the corrections queue (that means +they're looking). + +## Mechanism 3: Claim your listing (make the directory self-improving) + +**What.** A visible, low-friction path for an org to verify and own its +entry: "This is us" → confirm/fix details → entry gets the reviewed marker +(Tier A path) and a `claimed` badge on the map + a small embeddable badge +("On the Commonweave map — 29,378 organizations weaving healthier +communities") for their site, which links back to their map deep-link. + +**Why it attracts.** The badge is a tiny status good and a backlink engine; +each claimed listing is a unit of Tier A data we didn't have to research; +each embed is organic distribution to exactly the right audience. + +**How it ships.** Phase 1 needs no backend: "Claim this listing" button in +the map detail panel → prefilled GitHub issue with a `claim` label + an +email fallback (hello@commonweave.earth). A maintainer verifies (reply from +an org-domain address or the org's listed site referencing the claim), +flips `review_status`, done. Badge = one static SVG endpoint per org id. + +**Success metric.** Claims per month (target: 5/mo by day 90); % of claims +that arrive via another org's badge or brief (the compounding signal). + +--- + +## Grassroots sequencing (30 / 60 / 90) + +**Days 1–30 — prove the gift works.** Ship brief generator; hand-deliver 4 +circuit briefs (one per week) through one warm channel each, chosen from the +strongest US candidates in circuits.json (Hartford, Syracuse, Tulsa, Durham +are already promising). Add the claim button. Effort: ~2 evenings/week. +Gate: if 0 of 4 briefs get any response, the brief format is wrong — revise +before scaling, don't send more. + +**Days 31–60 — borrow a network's trust.** Federation health report v1 to +ICA + one other. Post ONE show-don't-tell artifact where practitioners +already talk (co-op listservs, a CLT network call, r/cooperatives): the +city-level circuit map for one metro, framed as a question — "we think +these three orgs could build housing together; what are we missing?" — +not an announcement. + +**Days 61–90 — make it a habit.** Monthly "weave report": what got added, +what got corrected, which circuits got stronger, one introduction that +happened. Same post, three places (site, one listserv, one fediverse +account). Invite one guest correction-sprint with a partner network's +members. + +**What we deliberately do NOT do:** bulk email campaigns, GitHub issue +outreach, engagement-bait threads, press releases, "launch" theater. The +directory is infrastructure; infrastructure earns trust by being repeatedly +useful in small ways. + +--- + +## Honesty rails (applies to every mechanism) + +- Every number quoted anywhere comes from `data/map/stats.v3.json` with its + build date. No exceptions (OUTREACH.md rule 6). +- Circuit briefs say "derived, unverified — treat as an introduction worth + making, not an existing partnership" in the body, not a footnote. +- Every artifact carries its correction path. The gift includes the ability + to tell us we're wrong; that's what makes it credible. diff --git a/briefs/briefs.css b/briefs/briefs.css new file mode 100644 index 0000000..14acc22 --- /dev/null +++ b/briefs/briefs.css @@ -0,0 +1,73 @@ +/* Generated support stylesheet for Commonweave circuit briefs. */ +.brief-shell { max-width: 1120px; margin: 0 auto; padding: clamp(42px, 7vw, 92px) clamp(20px, 5vw, 56px) var(--s-9); } +.brief-hero { display: grid; grid-template-columns: minmax(0, 1fr) 210px; gap: var(--s-7); align-items: start; padding-bottom: var(--s-7); border-bottom: var(--rule); } +.brief-hero h1 { font-size: clamp(52px, 8vw, 104px); line-height: .92; font-style: italic; max-width: 13ch; margin: var(--s-4) 0 var(--s-5); text-wrap: balance; } +.brief-hero .lede { color: var(--ink-soft); max-width: 37ch; } +.status-stamp { border: 2px solid var(--clay); color: var(--clay); padding: 18px 14px; font-family: var(--f-mono); font-size: 11px; line-height: 1.45; letter-spacing: .13em; text-transform: uppercase; transform: rotate(2deg); text-align: center; background: color-mix(in oklab, var(--paper) 88%, transparent); } +.status-stamp strong { display: block; font-size: 15px; letter-spacing: .08em; margin-bottom: 6px; } +.brief-meta { display: flex; gap: var(--s-4); flex-wrap: wrap; margin-top: var(--s-5); font-family: var(--f-mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-muted); } +.brief-section { padding: var(--s-8) 0; border-bottom: var(--rule); } +.brief-section h2 { font-size: clamp(38px, 5vw, 66px); max-width: 15ch; margin-bottom: var(--s-6); } +.section-intro { color: var(--ink-soft); font-size: 19px; max-width: 62ch; } +.circuit-loom { position: relative; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-5); margin-top: var(--s-7); } +.circuit-loom::before { content: ""; position: absolute; left: 10%; right: 10%; top: 31px; height: 2px; background: var(--thread); z-index: 0; } +.role-card { position: relative; z-index: 1; border: var(--rule); background: var(--paper); padding: 58px var(--s-5) var(--s-5); min-height: 245px; } +.role-card::before { content: ""; position: absolute; top: 23px; left: 50%; width: 16px; height: 16px; margin-left: -9px; border-radius: 50%; background: var(--clay); border: 2px solid var(--paper); box-shadow: 0 0 0 1px var(--thread); } +.role-label { font-family: var(--f-mono); font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--clay); } +.role-card h3 { font-size: clamp(24px, 2.4vw, 33px); margin: var(--s-3) 0; } +.role-card p { color: var(--ink-muted); font-size: 15px; } +.role-links { display: flex; gap: var(--s-3); flex-wrap: wrap; margin-top: var(--s-5); font-family: var(--f-mono); font-size: 10px; text-transform: uppercase; letter-spacing: .08em; } +.role-links a { text-decoration: none; border-bottom: 1px solid currentColor; } +.finding { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(260px, .6fr); gap: var(--s-7); align-items: start; } +.finding blockquote { margin: 0; font-family: var(--f-display); font-style: italic; font-size: clamp(27px, 3.2vw, 44px); line-height: 1.16; color: var(--moss-deep); } +.field-note { border-left: 3px solid var(--thread); padding-left: var(--s-5); color: var(--ink-soft); } +.unknowns { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--ink); border: var(--rule); margin-top: var(--s-6); } +.unknown { background: var(--paper); padding: var(--s-5); } +.unknown b { display: block; font-family: var(--f-mono); font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--clay); margin-bottom: var(--s-3); } +.brief-actions { display: flex; gap: var(--s-3); flex-wrap: wrap; align-items: center; margin-top: var(--s-6); } +.brief-button { appearance: none; border: 1px solid var(--ink); background: transparent; color: var(--ink); padding: 10px 16px; font: 500 10px/1 var(--f-mono); letter-spacing: .12em; text-transform: uppercase; text-decoration: none; cursor: pointer; } +.brief-button.primary { background: var(--moss); border-color: var(--moss); color: var(--paper); } +.brief-button:hover { background: var(--paper-2); color: var(--moss-deep); } +.brief-button.primary:hover { background: var(--moss-deep); color: var(--paper); } +.source-note { color: var(--ink-muted); font-size: 14px; overflow-wrap: anywhere; } +.source-note code { font-family: var(--f-mono); font-size: 12px; } +.brief-index-hero { padding-bottom: var(--s-7); border-bottom: var(--rule); } +.brief-index-hero h1 { font-size: clamp(56px, 9vw, 112px); line-height: .91; font-style: italic; max-width: 12ch; margin: var(--s-4) 0 var(--s-5); } +.filter-bar { display: grid; grid-template-columns: minmax(220px, 1fr) 220px; gap: var(--s-3); margin: var(--s-7) 0; } +.filter-bar label { display: grid; gap: 6px; font: 500 10px/1.4 var(--f-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-muted); } +.filter-bar input, .filter-bar select { width: 100%; border: 1px solid var(--ink); border-radius: 0; background: var(--paper); color: var(--ink); padding: 12px 13px; font: 16px/1.3 var(--f-body); } +.brief-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-5); } +.brief-card { border: var(--rule); padding: var(--s-5); background: color-mix(in oklab, var(--paper) 82%, var(--paper-2)); display: flex; flex-direction: column; } +.brief-card .card-kicker { display: flex; justify-content: space-between; gap: var(--s-3); font-family: var(--f-mono); font-size: 9px; letter-spacing: .11em; text-transform: uppercase; color: var(--ink-muted); } +.brief-card h2 { font-size: clamp(30px, 3vw, 44px); margin: var(--s-4) 0; } +.brief-card ul { list-style: none; margin: 0 0 var(--s-5); padding: 0; color: var(--ink-soft); } +.brief-card li { padding: 7px 0; border-top: var(--rule-soft); } +.brief-card > a { margin-top: auto; align-self: flex-start; font-family: var(--f-mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase; } +.empty-result { display: none; padding: var(--s-7); border: var(--rule); color: var(--ink-soft); } +.empty-result.visible { display: block; } +body.dark .role-card, body.dark .unknown, body.dark .filter-bar input, body.dark .filter-bar select { background: var(--paper); } +body.dark .status-stamp { background: var(--paper); } +@media (max-width: 820px) { + .brief-hero { grid-template-columns: 1fr; } + .status-stamp { max-width: 210px; transform: none; } + .circuit-loom { grid-template-columns: 1fr; } + .circuit-loom::before { top: 6%; bottom: 6%; left: 31px; right: auto; width: 2px; height: auto; } + .role-card { padding: var(--s-5) var(--s-5) var(--s-5) 62px; min-height: 0; } + .role-card::before { left: 23px; top: 50%; margin: -9px 0 0; } + .finding, .unknowns, .brief-grid { grid-template-columns: 1fr; } + .filter-bar { grid-template-columns: 1fr; } +} +@media (max-width: 600px) { + .nav-links a:not(.nav-cta) { display: none; } + .brief-shell { padding-left: 18px; padding-right: 18px; } +} +@media print { + .site-nav, .site-foot, .brief-actions, .filter-bar { display: none !important; } + body { background: #fff !important; color: #111 !important; font-size: 12pt; } + .brief-shell { max-width: none; padding: 0; } + .brief-hero { grid-template-columns: 1fr 150px; } + .brief-hero h1 { font-size: 52pt; } + .brief-section { padding: 28pt 0; } + .role-card, .unknown { break-inside: avoid; background: #fff !important; } + a { color: #111 !important; } +} diff --git a/briefs/briefs.js b/briefs/briefs.js new file mode 100644 index 0000000..4d21e8c --- /dev/null +++ b/briefs/briefs.js @@ -0,0 +1,38 @@ +(function () { + "use strict"; + var search = document.getElementById("brief-search"); + var country = document.getElementById("brief-country"); + var cards = Array.prototype.slice.call(document.querySelectorAll("[data-brief-card]")); + var count = document.getElementById("brief-visible-count"); + var empty = document.getElementById("brief-empty"); + + function applyFilters() { + var q = search ? search.value.trim().toLowerCase() : ""; + var cc = country ? country.value : ""; + var visible = 0; + cards.forEach(function (card) { + var matchesText = !q || (card.getAttribute("data-search") || "").indexOf(q) !== -1; + var matchesCountry = !cc || card.getAttribute("data-country") === cc; + var show = matchesText && matchesCountry; + card.hidden = !show; + if (show) visible += 1; + }); + if (count) count.textContent = String(visible); + if (empty) empty.classList.toggle("visible", visible === 0); + } + + if (search) search.addEventListener("input", applyFilters); + if (country) country.addEventListener("change", applyFilters); + + document.querySelectorAll("[data-copy-url]").forEach(function (button) { + button.addEventListener("click", function () { + var url = button.getAttribute("data-copy-url") || location.href; + if (!navigator.clipboard) return; + navigator.clipboard.writeText(url).then(function () { + var previous = button.textContent; + button.textContent = "Link copied"; + window.setTimeout(function () { button.textContent = previous; }, 1600); + }); + }); + }); +}()); diff --git a/briefs/community_food_system_7133cc6010.html b/briefs/community_food_system_7133cc6010.html new file mode 100644 index 0000000..41a2316 --- /dev/null +++ b/briefs/community_food_system_7133cc6010.html @@ -0,0 +1,132 @@ + + + + + +Local food security loop in BG + + + + + + + + + + + + + + + + + + +
+
+
+
Solution-circuit field note · BG
+

Local food security loop

+

A local food system that survives supply shocks: growers produce, a cooperative channel distributes, and access organizations get food to people who cannot pay market prices.

+
+ Published map locations span about 2 km + Map snapshot 2026-07-03 + 29,378 mapped records +
+
+ +
+ +
+
The possible circuit
+

grower + distribution + access

+

Commonweave's public map data places these organizations nearby and classifies their public work as complementary. The classification may be wrong or stale.

+
+
+
grower
+

Farmhopping

+

nonprofit
Source: Source not named in public map export

+ +
+
+
distribution
+

Hrancoop

+

cooperative
Source: Source not named in public map export

+ +
+
+
access
+

Bulgarian Food Bank

+

nonprofit
Source: Source not named in public map export

+ +
+
+
+ +
+
+
Why the system connected them
+

A lead worth checking.

+
“Together: Farmhopping (grower) + Hrancoop (distribution) + Bulgarian Food Bank (access) could close a local food loop (grow + distribute + guarantee access).”
+
+ +
+ +
+
What the map cannot know
+

Three questions before anyone acts.

+
+
01 · AccuracyDo these organizations still exist, and are their proposed roles described correctly?
+
02 · ConsentDo they want to be discoverable and introduced in this way?
+
03 · FitIs there a real local need, trust, and capacity for this circuit—or only geographic proximity?
+
+
+ Correct this brief + + + All circuit briefs +
+
+
+ + + + + diff --git a/briefs/community_food_system_947003c3af.html b/briefs/community_food_system_947003c3af.html new file mode 100644 index 0000000..c675781 --- /dev/null +++ b/briefs/community_food_system_947003c3af.html @@ -0,0 +1,132 @@ + + + + + +Local food security loop in Bronx, NY, US + + + + + + + + + + + + + + + + + + +
+
+
+
Solution-circuit field note · Bronx, NY, US
+

Local food security loop

+

A local food system that survives supply shocks: growers produce, a cooperative channel distributes, and access organizations get food to people who cannot pay market prices.

+
+ Published map locations resolve to the same point + Map snapshot 2026-07-03 + 29,378 mapped records +
+
+ +
+ +
+
The possible circuit
+

grower + distribution + access

+

Commonweave's public map data places these organizations nearby and classifies their public work as complementary. The classification may be wrong or stale.

+
+
+
grower
+

RAINBOW LIFE COMMUNITY GARDEN INC

+

Tier C · nonprofit
Source: IRS_EO_BMF

+ +
+
+
distribution
+

BLACK FORUM OF CO-OP CITY

+

Tier C · cooperative
Source: IRS_EO_BMF

+ +
+
+
access
+

FOOD BANK FOR NEW YORK CITY

+

Tier C · nonprofit
Source: IRS_EO_BMF

+ +
+
+
+ +
+
+
Why the system connected them
+

A lead worth checking.

+
“Together: RAINBOW LIFE COMMUNITY GARDEN INC (grower) + BLACK FORUM OF CO-OP CITY (distribution) + FOOD BANK FOR NEW YORK CITY (access) could close a local food loop (grow + distribute + guarantee access).”
+
+ +
+ +
+
What the map cannot know
+

Three questions before anyone acts.

+
+
01 · AccuracyDo these organizations still exist, and are their proposed roles described correctly?
+
02 · ConsentDo they want to be discoverable and introduced in this way?
+
03 · FitIs there a real local need, trust, and capacity for this circuit—or only geographic proximity?
+
+
+ Correct this brief + + + All circuit briefs +
+
+
+ + + + + diff --git a/briefs/community_food_system_b06e2cae36.html b/briefs/community_food_system_b06e2cae36.html new file mode 100644 index 0000000..d7c4494 --- /dev/null +++ b/briefs/community_food_system_b06e2cae36.html @@ -0,0 +1,133 @@ + + + + + +Local food security loop in GB + + + + + + + + + + + + + + + + + + +
+
+
+
Solution-circuit field note · GB
+

Local food security loop

+

A local food system that survives supply shocks: growers produce, a cooperative channel distributes, and access organizations get food to people who cannot pay market prices.

+
+ Published map locations span about 11 km + Map snapshot 2026-07-03 + 29,378 mapped records +
+
+ +
+ +
+
The possible circuit
+

grower + distribution + access

+

Commonweave's public map data places these organizations nearby and classifies their public work as complementary. The classification may be wrong or stale.

+
+
+
grower
+

Hulme Community Garden Centre

+

collective
Source: Source not named in public map export

+ +
+
+
distribution
+

8th Day

+

cooperative
Source: Source not named in public map export

+ +
+ +
+
+ +
+
+
Why the system connected them
+

A lead worth checking.

+
“Together: Hulme Community Garden Centre (grower) + 8th Day (distribution) + Ashton Central Mosque Food Bank for Cov-ID 19 Support (access) could close a local food loop (grow + distribute + guarantee access).”
+
+ +
+ +
+
What the map cannot know
+

Three questions before anyone acts.

+
+
01 · AccuracyDo these organizations still exist, and are their proposed roles described correctly?
+
02 · ConsentDo they want to be discoverable and introduced in this way?
+
03 · FitIs there a real local need, trust, and capacity for this circuit—or only geographic proximity?
+
+
+ Correct this brief + + + All circuit briefs +
+
+
+ + + + + diff --git a/briefs/community_health_mesh_39dfa477c7.html b/briefs/community_health_mesh_39dfa477c7.html new file mode 100644 index 0000000..8ab17c0 --- /dev/null +++ b/briefs/community_health_mesh_39dfa477c7.html @@ -0,0 +1,133 @@ + + + + + +Community health mesh in Worcester, MA, US + + + + + + + + + + + + + + + + + + +
+
+
+
Solution-circuit field note · Worcester, MA, US
+

Community health mesh

+

Clinical care alone misses people; mutual aid alone lacks clinical capacity. A clinic, a neighborhood outreach network, and a health educator together form last-mile public health infrastructure.

+
+ Published map locations span about 0.1 km + Map snapshot 2026-07-03 + 29,378 mapped records +
+
+ +
+ +
+
The possible circuit
+

clinical care + neighborhood outreach + health education

+

Commonweave's public map data places these organizations nearby and classifies their public work as complementary. The classification may be wrong or stale.

+
+
+
clinical care
+

EDWARD M KENNEDY COMMUNITY HEALTH CENTER INC

+

Tier C · nonprofit
Source: IRS_EO_BMF

+ +
+ +
+
health education
+

SALVATION HEALTH EDUCATION AND DISEASE PREVENTION OUTREACH INC

+

Tier C · nonprofit
Source: IRS_EO_BMF

+ +
+
+
+ +
+
+
Why the system connected them
+

A lead worth checking.

+
“Together: EDWARD M KENNEDY COMMUNITY HEALTH CENTER INC (clinical care) + Mutual Aid Worcester (neighborhood outreach) + SALVATION HEALTH EDUCATION AND DISEASE PREVENTION OUTREACH INC (health education) could run last-mile community health (clinic + neighborhood outreach + health education).”
+
+ +
+ +
+
What the map cannot know
+

Three questions before anyone acts.

+
+
01 · AccuracyDo these organizations still exist, and are their proposed roles described correctly?
+
02 · ConsentDo they want to be discoverable and introduced in this way?
+
03 · FitIs there a real local need, trust, and capacity for this circuit—or only geographic proximity?
+
+
+ Correct this brief + + + All circuit briefs +
+
+
+ + + + + diff --git a/briefs/community_health_mesh_749faac21c.html b/briefs/community_health_mesh_749faac21c.html new file mode 100644 index 0000000..2b8777f --- /dev/null +++ b/briefs/community_health_mesh_749faac21c.html @@ -0,0 +1,132 @@ + + + + + +Community health mesh in Syracuse, NY, US + + + + + + + + + + + + + + + + + + +
+
+
+
Solution-circuit field note · Syracuse, NY, US
+

Community health mesh

+

Clinical care alone misses people; mutual aid alone lacks clinical capacity. A clinic, a neighborhood outreach network, and a health educator together form last-mile public health infrastructure.

+
+ Published map locations span about 0.5 km + Map snapshot 2026-07-03 + 29,378 mapped records +
+
+ +
+ +
+
The possible circuit
+

clinical care + neighborhood outreach + health education

+

Commonweave's public map data places these organizations nearby and classifies their public work as complementary. The classification may be wrong or stale.

+
+
+
clinical care
+

Syracuse Community Health Center Inc

+

Tier B · nonprofit
Source: ProPublica

+ +
+
+
neighborhood outreach
+

Westcott Mutual Aid

+

Tier B · mutual aid
Source: mutual_aid_hub

+ +
+
+
health education
+

CENTRAL NEW YORK AREA HEALTH EDUCATION CENTER INC

+

Tier C · nonprofit
Source: IRS_EO_BMF

+ +
+
+
+ +
+
+
Why the system connected them
+

A lead worth checking.

+
“Together: Syracuse Community Health Center Inc (clinical care) + Westcott Mutual Aid (neighborhood outreach) + CENTRAL NEW YORK AREA HEALTH EDUCATION CENTER INC (health education) could run last-mile community health (clinic + neighborhood outreach + health education).”
+
+ +
+ +
+
What the map cannot know
+

Three questions before anyone acts.

+
+
01 · AccuracyDo these organizations still exist, and are their proposed roles described correctly?
+
02 · ConsentDo they want to be discoverable and introduced in this way?
+
03 · FitIs there a real local need, trust, and capacity for this circuit—or only geographic proximity?
+
+
+ Correct this brief + + + All circuit briefs +
+
+
+ + + + + diff --git a/briefs/community_health_mesh_ed3e827f6e.html b/briefs/community_health_mesh_ed3e827f6e.html new file mode 100644 index 0000000..d3b6ba8 --- /dev/null +++ b/briefs/community_health_mesh_ed3e827f6e.html @@ -0,0 +1,133 @@ + + + + + +Community health mesh in Bakersfield, CA, US + + + + + + + + + + + + + + + + + + +
+
+
+
Solution-circuit field note · Bakersfield, CA, US
+

Community health mesh

+

Clinical care alone misses people; mutual aid alone lacks clinical capacity. A clinic, a neighborhood outreach network, and a health educator together form last-mile public health infrastructure.

+
+ Published map locations span about 0.1 km + Map snapshot 2026-07-03 + 29,378 mapped records +
+
+ +
+ +
+
The possible circuit
+

clinical care + neighborhood outreach + health education

+

Commonweave's public map data places these organizations nearby and classifies their public work as complementary. The classification may be wrong or stale.

+
+
+
clinical care
+

COMMUNITY MEDICAL EDUCATION AND RESEARCH FOUNDATION

+

Tier C · foundation
Source: IRS_EO_BMF

+ +
+ +
+
health education
+

COUNCIL FOR BLACK HEALTH EDUCATION & WELLNESS

+

Tier C · nonprofit
Source: IRS_EO_BMF

+ +
+
+
+ +
+
+
Why the system connected them
+

A lead worth checking.

+
“Together: COMMUNITY MEDICAL EDUCATION AND RESEARCH FOUNDATION (clinical care) + Kern County Mutual Aid (neighborhood outreach) + COUNCIL FOR BLACK HEALTH EDUCATION & WELLNESS (health education) could run last-mile community health (clinic + neighborhood outreach + health education).”
+
+ +
+ +
+
What the map cannot know
+

Three questions before anyone acts.

+
+
01 · AccuracyDo these organizations still exist, and are their proposed roles described correctly?
+
02 · ConsentDo they want to be discoverable and introduced in this way?
+
03 · FitIs there a real local need, trust, and capacity for this circuit—or only geographic proximity?
+
+
+ Correct this brief + + + All circuit briefs +
+
+
+ + + + + diff --git a/briefs/disaster_resilience_grid_5bb2dfa1a0.html b/briefs/disaster_resilience_grid_5bb2dfa1a0.html new file mode 100644 index 0000000..1c64fa8 --- /dev/null +++ b/briefs/disaster_resilience_grid_5bb2dfa1a0.html @@ -0,0 +1,133 @@ + + + + + +Disaster resilience grid in Providence, RI, US + + + + + + + + + + + + + + + + + + +
+
+
+
Solution-circuit field note · Providence, RI, US
+

Disaster resilience grid

+

When infrastructure fails, response speed depends on relationships that already exist: neighborhood mutual aid for distribution, clinical capacity for care, and a coordinating body for logistics.

+
+ Published map locations span about 0.2 km + Map snapshot 2026-07-03 + 29,378 mapped records +
+
+ +
+ +
+
The possible circuit
+

neighborhood distribution + clinical care + coordination

+

Commonweave's public map data places these organizations nearby and classifies their public work as complementary. The classification may be wrong or stale.

+
+
+
neighborhood distribution
+

AMOR - COVID19 Community Response Volunteer Sign Up

+

Tier B · mutual aid
Source: mutual_aid_hub

+ +
+
+
clinical care
+

RHODE ISLAND FREE CLINIC INC

+

Tier C · nonprofit
Source: IRS_EO_BMF

+ +
+
+
coordination
+

Rhode Island Pride COVID-19 Emergency Food/Toiletries/Sanitation Supply Drive

+

Tier B · mutual aid
Source: mutual_aid_hub

+ +
+
+
+ +
+
+
Why the system connected them
+

A lead worth checking.

+
“Together: AMOR - COVID19 Community Response Volunteer Sign Up (neighborhood distribution) + RHODE ISLAND FREE CLINIC INC (clinical care) + Rhode Island Pride COVID-19 Emergency Food/Toiletries/Sanitation Supply Drive (coordination) could form a pre-wired disaster response grid (neighborhood distribution + clinical care + coordination).”
+
+ +
+ +
+
What the map cannot know
+

Three questions before anyone acts.

+
+
01 · AccuracyDo these organizations still exist, and are their proposed roles described correctly?
+
02 · ConsentDo they want to be discoverable and introduced in this way?
+
03 · FitIs there a real local need, trust, and capacity for this circuit—or only geographic proximity?
+
+
+ Correct this brief + + + All circuit briefs +
+
+
+ + + + + diff --git a/briefs/disaster_resilience_grid_6c88266798.html b/briefs/disaster_resilience_grid_6c88266798.html new file mode 100644 index 0000000..2f1faaa --- /dev/null +++ b/briefs/disaster_resilience_grid_6c88266798.html @@ -0,0 +1,132 @@ + + + + + +Disaster resilience grid in Durham, NC, US + + + + + + + + + + + + + + + + + + +
+
+
+
Solution-circuit field note · Durham, NC, US
+

Disaster resilience grid

+

When infrastructure fails, response speed depends on relationships that already exist: neighborhood mutual aid for distribution, clinical capacity for care, and a coordinating body for logistics.

+
+ Published map locations span about 0.4 km + Map snapshot 2026-07-03 + 29,378 mapped records +
+
+ +
+ +
+
The possible circuit
+

neighborhood distribution + clinical care + coordination

+

Commonweave's public map data places these organizations nearby and classifies their public work as complementary. The classification may be wrong or stale.

+
+
+
neighborhood distribution
+

COVID-19 Resource Spreadsheet - Durham

+

Tier B · mutual aid
Source: mutual_aid_hub

+ +
+
+
clinical care
+

LINCOLN COMMUNITY HEALTH CENTER INCORPORATED

+

Tier C · nonprofit
Source: IRS_EO_BMF

+ +
+
+
coordination
+

CHRISTIAN ASSEMBLY EMERGENCY FOOD PANTRY

+

Tier C · nonprofit
Source: IRS_EO_BMF

+ +
+
+
+ +
+
+
Why the system connected them
+

A lead worth checking.

+
“Together: COVID-19 Resource Spreadsheet - Durham (neighborhood distribution) + LINCOLN COMMUNITY HEALTH CENTER INCORPORATED (clinical care) + CHRISTIAN ASSEMBLY EMERGENCY FOOD PANTRY (coordination) could form a pre-wired disaster response grid (neighborhood distribution + clinical care + coordination).”
+
+ +
+ +
+
What the map cannot know
+

Three questions before anyone acts.

+
+
01 · AccuracyDo these organizations still exist, and are their proposed roles described correctly?
+
02 · ConsentDo they want to be discoverable and introduced in this way?
+
03 · FitIs there a real local need, trust, and capacity for this circuit—or only geographic proximity?
+
+
+ Correct this brief + + + All circuit briefs +
+
+
+ + + + + diff --git a/briefs/disaster_resilience_grid_f89af5b745.html b/briefs/disaster_resilience_grid_f89af5b745.html new file mode 100644 index 0000000..ab9b430 --- /dev/null +++ b/briefs/disaster_resilience_grid_f89af5b745.html @@ -0,0 +1,132 @@ + + + + + +Disaster resilience grid in Columbia, MD, US + + + + + + + + + + + + + + + + + + +
+
+
+
Solution-circuit field note · Columbia, MD, US
+

Disaster resilience grid

+

When infrastructure fails, response speed depends on relationships that already exist: neighborhood mutual aid for distribution, clinical capacity for care, and a coordinating body for logistics.

+
+ Published map locations span about 2 km + Map snapshot 2026-07-03 + 29,378 mapped records +
+
+ +
+ +
+
The possible circuit
+

neighborhood distribution + clinical care + coordination

+

Commonweave's public map data places these organizations nearby and classifies their public work as complementary. The classification may be wrong or stale.

+
+
+
neighborhood distribution
+

Ffdc Mutual Aid Network Inc

+

Tier B · mutual aid
Source: ProPublica

+ +
+
+
clinical care
+

EMMANUEL HEALTH EDUCATION INC

+

Tier C · nonprofit
Source: IRS_EO_BMF

+ +
+
+
coordination
+

Howard County Community Organizations Active in Disaster

+

Tier B · mutual aid
Source: mutual_aid_hub

+ +
+
+
+ +
+
+
Why the system connected them
+

A lead worth checking.

+
“Together: Ffdc Mutual Aid Network Inc (neighborhood distribution) + EMMANUEL HEALTH EDUCATION INC (clinical care) + Howard County Community Organizations Active in Disaster (coordination) could form a pre-wired disaster response grid (neighborhood distribution + clinical care + coordination).”
+
+ +
+ +
+
What the map cannot know
+

Three questions before anyone acts.

+
+
01 · AccuracyDo these organizations still exist, and are their proposed roles described correctly?
+
02 · ConsentDo they want to be discoverable and introduced in this way?
+
03 · FitIs there a real local need, trust, and capacity for this circuit—or only geographic proximity?
+
+
+ Correct this brief + + + All circuit briefs +
+
+
+ + + + + diff --git a/briefs/index.html b/briefs/index.html new file mode 100644 index 0000000..f160532 --- /dev/null +++ b/briefs/index.html @@ -0,0 +1,175 @@ + + + + + +Possible local collaborations — Commonweave circuit briefs + + + + + + + + + + + + + + + + + + +
+
+
Commonweave field notes · Map snapshot 2026-07-03
+

Possible collaborations, not claimed partnerships.

+

These 13 one-page briefs turn public directory data into specific questions: which nearby organizations might fill complementary roles, and what did the map get wrong?

+

Every brief is derived and unverified. Nothing here says the listed organizations know one another, endorse Commonweave, or want an introduction. Each page carries its uncertainty and a correction path.

+
+ +
+
+ + +
+
13 field notes shown
+
+
+
BGUnverified
+

Local food security loop

+
  • grower: Farmhopping
  • +
  • distribution: Hrancoop
  • +
  • access: Bulgarian Food Bank
+ Open field note → +
+
NGUnverified
+

Land stewardship alliance

+
  • land tenure: Aya International Development Indigenous Knowledge Initiative Nigeria
  • +
  • ecological stewardship: Nigerian Conservation Foundation
  • +
  • regenerative production: Edo Co-operative Farmers
+ Open field note → +
+
Bakersfield, CA, USUnverified
+

Community health mesh

+
  • clinical care: COMMUNITY MEDICAL EDUCATION AND RESEARCH FOUNDATION
  • +
  • neighborhood outreach: Kern County Mutual Aid
  • +
  • health education: COUNCIL FOR BLACK HEALTH EDUCATION & WELLNESS
+ Open field note → +
+
Worcester, MA, USUnverified
+

Community health mesh

+
  • clinical care: EDWARD M KENNEDY COMMUNITY HEALTH CENTER INC
  • +
  • neighborhood outreach: Mutual Aid Worcester
  • +
  • health education: SALVATION HEALTH EDUCATION AND DISEASE PREVENTION OUTREACH INC
+ Open field note → +
+
Providence, RI, USUnverified
+

Disaster resilience grid

+
  • neighborhood distribution: AMOR - COVID19 Community Response Volunteer Sign Up
  • +
  • clinical care: RHODE ISLAND FREE CLINIC INC
  • +
  • coordination: Rhode Island Pride COVID-19 Emergency Food/Toiletries/Sanitation Supply Drive
+ Open field note → +
+
Durham, NC, USUnverified
+

Disaster resilience grid

+
  • neighborhood distribution: COVID-19 Resource Spreadsheet - Durham
  • +
  • clinical care: LINCOLN COMMUNITY HEALTH CENTER INCORPORATED
  • +
  • coordination: CHRISTIAN ASSEMBLY EMERGENCY FOOD PANTRY
+ Open field note → +
+
Syracuse, NY, USUnverified
+

Community health mesh

+
  • clinical care: Syracuse Community Health Center Inc
  • +
  • neighborhood outreach: Westcott Mutual Aid
  • +
  • health education: CENTRAL NEW YORK AREA HEALTH EDUCATION CENTER INC
+ Open field note → +
+
Columbia, MD, USUnverified
+

Disaster resilience grid

+
  • neighborhood distribution: Ffdc Mutual Aid Network Inc
  • +
  • clinical care: EMMANUEL HEALTH EDUCATION INC
  • +
  • coordination: Howard County Community Organizations Active in Disaster
+ Open field note → +
+
Bronx, NY, USUnverified
+

Local food security loop

+
  • grower: RAINBOW LIFE COMMUNITY GARDEN INC
  • +
  • distribution: BLACK FORUM OF CO-OP CITY
  • +
  • access: FOOD BANK FOR NEW YORK CITY
+ Open field note → +
+
Fort Worth, TX, USUnverified
+

Labor-for-housing pipeline

+
  • land: FORT WORTH COMMUNITY LAND TRUST
  • +
  • build labor: HABITAT FOR HUMANITY INTERNATIONAL INC
  • +
  • finance: CREDIT UNION WOMENS LEADERSHIP ALLIANCE INC
+ Open field note → +
+
Tulsa, OK, USUnverified
+

Labor-for-housing pipeline

+
  • land: CROSSOVER COMMUNITY LAND TRUST INC
  • +
  • build labor: HABITAT FOR HUMANITY INTERNATIONAL INC
  • +
  • finance: WESTREET FEDERAL CREDIT UNION
+ Open field note → +
+
Hartford, CT, USUnverified
+

Labor-for-housing pipeline

+
  • land: NORTH HARTFORD COMMUNITY LAND TRUST
  • +
  • build labor: HABITAT FOR HUMANITY OF NORTH CENTRAL CONNECTICUT
  • +
  • finance: AMERICAN EAGLE FINANCIAL CREDIT UNION INCORPORATED
+ Open field note → +
+
GBUnverified
+

Local food security loop

+
  • grower: Hulme Community Garden Centre
  • +
  • distribution: 8th Day
  • +
  • access: Ashton Central Mosque Food Bank for Cov-ID 19 Support
+ Open field note → +
+
+
No briefs match those filters. Clear the search or choose another country.
+
+
+ + + + + diff --git a/briefs/labor_for_housing_062b7d5b5e.html b/briefs/labor_for_housing_062b7d5b5e.html new file mode 100644 index 0000000..7d95ebc --- /dev/null +++ b/briefs/labor_for_housing_062b7d5b5e.html @@ -0,0 +1,132 @@ + + + + + +Labor-for-housing pipeline in Fort Worth, TX, US + + + + + + + + + + + + + + + + + + +
+
+
+
Solution-circuit field note · Fort Worth, TX, US
+

Labor-for-housing pipeline

+

Affordable homeownership without lifelong debt: land held in trust keeps homes permanently affordable, organized labor turns work-hours into equity, and cooperative finance bridges construction costs.

+
+ Published map locations resolve to the same point + Map snapshot 2026-07-03 + 29,378 mapped records +
+
+ +
+ +
+
The possible circuit
+

land + build labor + finance

+

Commonweave's public map data places these organizations nearby and classifies their public work as complementary. The classification may be wrong or stale.

+
+
+
land
+

FORT WORTH COMMUNITY LAND TRUST

+

Tier C · nonprofit
Source: IRS_EO_BMF

+ +
+
+
build labor
+

HABITAT FOR HUMANITY INTERNATIONAL INC

+

Tier C · sweat equity program
Source: IRS_EO_BMF

+ +
+
+
finance
+

CREDIT UNION WOMENS LEADERSHIP ALLIANCE INC

+

Tier C · federation
Source: IRS_EO_BMF

+ +
+
+
+ +
+
+
Why the system connected them
+

A lead worth checking.

+
“Together: FORT WORTH COMMUNITY LAND TRUST (land) + HABITAT FOR HUMANITY INTERNATIONAL INC (build labor) + CREDIT UNION WOMENS LEADERSHIP ALLIANCE INC (finance) could run a labor-for-housing pipeline (land in trust + labor as equity + cooperative finance).”
+
+ +
+ +
+
What the map cannot know
+

Three questions before anyone acts.

+
+
01 · AccuracyDo these organizations still exist, and are their proposed roles described correctly?
+
02 · ConsentDo they want to be discoverable and introduced in this way?
+
03 · FitIs there a real local need, trust, and capacity for this circuit—or only geographic proximity?
+
+
+ Correct this brief + + + All circuit briefs +
+
+
+ + + + + diff --git a/briefs/labor_for_housing_1d488117bc.html b/briefs/labor_for_housing_1d488117bc.html new file mode 100644 index 0000000..ea203b5 --- /dev/null +++ b/briefs/labor_for_housing_1d488117bc.html @@ -0,0 +1,132 @@ + + + + + +Labor-for-housing pipeline in Hartford, CT, US + + + + + + + + + + + + + + + + + + +
+
+
+
Solution-circuit field note · Hartford, CT, US
+

Labor-for-housing pipeline

+

Affordable homeownership without lifelong debt: land held in trust keeps homes permanently affordable, organized labor turns work-hours into equity, and cooperative finance bridges construction costs.

+
+ Published map locations span about 6 km + Map snapshot 2026-07-03 + 29,378 mapped records +
+
+ +
+ +
+
The possible circuit
+

land + build labor + finance

+

Commonweave's public map data places these organizations nearby and classifies their public work as complementary. The classification may be wrong or stale.

+
+
+
land
+

NORTH HARTFORD COMMUNITY LAND TRUST

+

Tier C · nonprofit
Source: IRS_EO_BMF

+ +
+
+
build labor
+

HABITAT FOR HUMANITY OF NORTH CENTRAL CONNECTICUT

+

Tier C · sweat equity program
Source: IRS_EO_BMF

+ +
+
+
finance
+

AMERICAN EAGLE FINANCIAL CREDIT UNION INCORPORATED

+

Tier C · nonprofit
Source: IRS_EO_BMF

+ +
+
+
+ +
+
+
Why the system connected them
+

A lead worth checking.

+
“Together: NORTH HARTFORD COMMUNITY LAND TRUST (land) + HABITAT FOR HUMANITY OF NORTH CENTRAL CONNECTICUT (build labor) + AMERICAN EAGLE FINANCIAL CREDIT UNION INCORPORATED (finance) could run a labor-for-housing pipeline (land in trust + labor as equity + cooperative finance).”
+
+ +
+ +
+
What the map cannot know
+

Three questions before anyone acts.

+
+
01 · AccuracyDo these organizations still exist, and are their proposed roles described correctly?
+
02 · ConsentDo they want to be discoverable and introduced in this way?
+
03 · FitIs there a real local need, trust, and capacity for this circuit—or only geographic proximity?
+
+
+ Correct this brief + + + All circuit briefs +
+
+
+ + + + + diff --git a/briefs/labor_for_housing_e201bdc4d6.html b/briefs/labor_for_housing_e201bdc4d6.html new file mode 100644 index 0000000..dce233e --- /dev/null +++ b/briefs/labor_for_housing_e201bdc4d6.html @@ -0,0 +1,132 @@ + + + + + +Labor-for-housing pipeline in Tulsa, OK, US + + + + + + + + + + + + + + + + + + +
+
+
+
Solution-circuit field note · Tulsa, OK, US
+

Labor-for-housing pipeline

+

Affordable homeownership without lifelong debt: land held in trust keeps homes permanently affordable, organized labor turns work-hours into equity, and cooperative finance bridges construction costs.

+
+ Published map locations resolve to the same point + Map snapshot 2026-07-03 + 29,378 mapped records +
+
+ +
+ +
+
The possible circuit
+

land + build labor + finance

+

Commonweave's public map data places these organizations nearby and classifies their public work as complementary. The classification may be wrong or stale.

+
+
+
land
+

CROSSOVER COMMUNITY LAND TRUST INC

+

Tier C · nonprofit
Source: IRS_EO_BMF

+ +
+
+
build labor
+

HABITAT FOR HUMANITY INTERNATIONAL INC

+

Tier C · sweat equity program
Source: IRS_EO_BMF

+ +
+
+
finance
+

WESTREET FEDERAL CREDIT UNION

+

Tier C · nonprofit
Source: IRS_EO_BMF

+ +
+
+
+ +
+
+
Why the system connected them
+

A lead worth checking.

+
“Together: CROSSOVER COMMUNITY LAND TRUST INC (land) + HABITAT FOR HUMANITY INTERNATIONAL INC (build labor) + WESTREET FEDERAL CREDIT UNION (finance) could run a labor-for-housing pipeline (land in trust + labor as equity + cooperative finance).”
+
+ +
+ +
+
What the map cannot know
+

Three questions before anyone acts.

+
+
01 · AccuracyDo these organizations still exist, and are their proposed roles described correctly?
+
02 · ConsentDo they want to be discoverable and introduced in this way?
+
03 · FitIs there a real local need, trust, and capacity for this circuit—or only geographic proximity?
+
+
+ Correct this brief + + + All circuit briefs +
+
+
+ + + + + diff --git a/briefs/land_stewardship_alliance_5ae95aa3bc.html b/briefs/land_stewardship_alliance_5ae95aa3bc.html new file mode 100644 index 0000000..23ab380 --- /dev/null +++ b/briefs/land_stewardship_alliance_5ae95aa3bc.html @@ -0,0 +1,133 @@ + + + + + +Land stewardship alliance in NG + + + + + + + + + + + + + + + + + + +
+
+
+
Solution-circuit field note · NG
+

Land stewardship alliance

+

Conservation without production becomes a museum; production without stewardship strips the land. A land-holding entity, an ecological steward, and a working farm together keep land healthy and in use.

+
+ Published map locations resolve to the same point + Map snapshot 2026-07-03 + 29,378 mapped records +
+
+ +
+ +
+
The possible circuit
+

land tenure + ecological stewardship + regenerative production

+

Commonweave's public map data places these organizations nearby and classifies their public work as complementary. The classification may be wrong or stale.

+
+
+
land tenure
+

Aya International Development Indigenous Knowledge Initiative Nigeria

+

Tier B · nonprofit
Source: Field research + Wikidata

+ +
+ +
+
regenerative production
+

Edo Co-operative Farmers

+

Tier B · cooperative
Source: Field research + Wikidata

+ +
+
+
+ +
+
+
Why the system connected them
+

A lead worth checking.

+
“Together: Aya International Development Indigenous Knowledge Initiative Nigeria (land tenure) + Nigerian Conservation Foundation (ecological stewardship) + Edo Co-operative Farmers (regenerative production) could hold, restore and work land together (secure tenure + ecological stewardship + regenerative production).”
+
+ +
+ +
+
What the map cannot know
+

Three questions before anyone acts.

+
+
01 · AccuracyDo these organizations still exist, and are their proposed roles described correctly?
+
02 · ConsentDo they want to be discoverable and introduced in this way?
+
03 · FitIs there a real local need, trust, and capacity for this circuit—or only geographic proximity?
+
+
+ Correct this brief + + + All circuit briefs +
+
+
+ + + + + diff --git a/briefs/manifest.json b/briefs/manifest.json new file mode 100644 index 0000000..300d23e --- /dev/null +++ b/briefs/manifest.json @@ -0,0 +1,159 @@ +{ + "schema_version": 1, + "generated_at": "2026-07-03T12:00:42Z", + "source_script": "tools/build-circuit-briefs.py", + "source_files": [ + "data/map/circuits.json", + "briefs/source-records.json (compact fallback from data/map/orgs.v3.geojson)", + "data/map/stats.v3.json" + ], + "stats_build_date": "2026-07-03", + "brief_count": 13, + "source_declared_candidate_count": 76, + "source_count_matches": false, + "briefs": [ + { + "group_id": "community_food_system_7133cc6010", + "circuit": "community_food_system", + "country": "BG", + "location": "BG", + "member_ids": [ + "org_902290", + "org_902364", + "org_902352" + ] + }, + { + "group_id": "land_stewardship_alliance_5ae95aa3bc", + "circuit": "land_stewardship_alliance", + "country": "NG", + "location": "NG", + "member_ids": [ + "org_rec_272eb6fb4fac1ecd", + "org_rec_b29a3b004eccdbdc", + "org_rec_37a96b11038babdc" + ] + }, + { + "group_id": "community_health_mesh_ed3e827f6e", + "circuit": "community_health_mesh", + "country": "US", + "location": "Bakersfield, CA, US", + "member_ids": [ + "org_rec_7335a682f7bb7495", + "org_rec_e6240be1fc6995bb", + "org_rec_76f9053bf4b48edc" + ] + }, + { + "group_id": "community_health_mesh_39dfa477c7", + "circuit": "community_health_mesh", + "country": "US", + "location": "Worcester, MA, US", + "member_ids": [ + "org_rec_b48ad99f198219b7", + "org_rec_85b3a9133bd564c9", + "org_rec_6d449782b86ba9a1" + ] + }, + { + "group_id": "disaster_resilience_grid_5bb2dfa1a0", + "circuit": "disaster_resilience_grid", + "country": "US", + "location": "Providence, RI, US", + "member_ids": [ + "org_rec_132008209b27a30a", + "org_rec_f2678ccdb82700be", + "org_rec_4bc89cc09f8eab58" + ] + }, + { + "group_id": "disaster_resilience_grid_6c88266798", + "circuit": "disaster_resilience_grid", + "country": "US", + "location": "Durham, NC, US", + "member_ids": [ + "org_rec_f5d5c0c8e9ecf69d", + "org_rec_6874025da267e771", + "org_rec_ca4b5ad732a68d31" + ] + }, + { + "group_id": "community_health_mesh_749faac21c", + "circuit": "community_health_mesh", + "country": "US", + "location": "Syracuse, NY, US", + "member_ids": [ + "org_rec_cc6ff11b990520ad", + "org_rec_bbe1926cfd533f6b", + "org_rec_fd28ca9a46d23eca" + ] + }, + { + "group_id": "disaster_resilience_grid_f89af5b745", + "circuit": "disaster_resilience_grid", + "country": "US", + "location": "Columbia, MD, US", + "member_ids": [ + "org_rec_78cf453e090d5916", + "org_rec_64a862832e6379b1", + "org_rec_f6f5e4892a54c342" + ] + }, + { + "group_id": "community_food_system_947003c3af", + "circuit": "community_food_system", + "country": "US", + "location": "Bronx, NY, US", + "member_ids": [ + "org_rec_e778b27d9beec550", + "org_rec_9ea9c8e341b41046", + "org_rec_21fba585e1b64825" + ] + }, + { + "group_id": "labor_for_housing_062b7d5b5e", + "circuit": "labor_for_housing", + "country": "US", + "location": "Fort Worth, TX, US", + "member_ids": [ + "org_rec_3be58a68c5f0bb27", + "org_rec_e191a4704fe52494", + "org_rec_f5de00cce0e9999c" + ] + }, + { + "group_id": "labor_for_housing_e201bdc4d6", + "circuit": "labor_for_housing", + "country": "US", + "location": "Tulsa, OK, US", + "member_ids": [ + "org_rec_e868c1527499c501", + "org_rec_90d53ba7f4daae9d", + "org_rec_c9518232bd6354bb" + ] + }, + { + "group_id": "labor_for_housing_1d488117bc", + "circuit": "labor_for_housing", + "country": "US", + "location": "Hartford, CT, US", + "member_ids": [ + "org_rec_4025e2497718b264", + "org_rec_f2ee3c295daa51da", + "org_rec_80bfcb26fc67a39c" + ] + }, + { + "group_id": "community_food_system_b06e2cae36", + "circuit": "community_food_system", + "country": "GB", + "location": "GB", + "member_ids": [ + "org_902776", + "org_902281", + "org_rec_b06f500ac4bc406e" + ] + } + ] +} diff --git a/briefs/source-records.json b/briefs/source-records.json new file mode 100644 index 0000000..f193d49 --- /dev/null +++ b/briefs/source-records.json @@ -0,0 +1,360 @@ +{ + "schema_version": 1, + "generated_at": "2026-07-03T12:00:42Z", + "source": "data/map/orgs.v3.geojson", + "note": "Compact public-field snapshot for deterministic circuit brief builds; contains only organizations referenced by circuits.json.", + "records": [ + { + "id": "org_902281" + }, + { + "id": "org_902290" + }, + { + "id": "org_902352" + }, + { + "id": "org_902364" + }, + { + "id": "org_902776" + }, + { + "id": "org_rec_132008209b27a30a", + "n": "AMOR - COVID19 Community Response Volunteer Sign Up", + "w": "www.facebook.com/amornetwork", + "src": "mutual_aid_hub", + "t": "B", + "m": "mutual_aid", + "ci": "Providence", + "st": "RI", + "cc": "US" + }, + { + "id": "org_rec_21fba585e1b64825", + "n": "FOOD BANK FOR NEW YORK CITY", + "src": "IRS_EO_BMF", + "t": "C", + "m": "nonprofit", + "ci": "BRONX", + "st": "NY", + "cc": "US" + }, + { + "id": "org_rec_272eb6fb4fac1ecd", + "n": "Aya International Development Indigenous Knowledge Initiative Nigeria", + "src": "Field research + Wikidata", + "t": "B", + "m": "nonprofit", + "cc": "NG" + }, + { + "id": "org_rec_37a96b11038babdc", + "n": "Edo Co-operative Farmers", + "src": "Field research + Wikidata", + "t": "B", + "m": "cooperative", + "cc": "NG" + }, + { + "id": "org_rec_3be58a68c5f0bb27", + "n": "FORT WORTH COMMUNITY LAND TRUST", + "src": "IRS_EO_BMF", + "t": "C", + "m": "nonprofit", + "ci": "FORT WORTH", + "st": "TX", + "cc": "US" + }, + { + "id": "org_rec_4025e2497718b264", + "n": "NORTH HARTFORD COMMUNITY LAND TRUST", + "src": "IRS_EO_BMF", + "t": "C", + "m": "nonprofit", + "ci": "HARTFORD", + "st": "CT", + "cc": "US" + }, + { + "id": "org_rec_4bc89cc09f8eab58", + "n": "Rhode Island Pride COVID-19 Emergency Food/Toiletries/Sanitation Supply Drive", + "src": "mutual_aid_hub", + "t": "B", + "m": "mutual_aid", + "ci": "Providence", + "st": "RI", + "cc": "US" + }, + { + "id": "org_rec_64a862832e6379b1", + "n": "EMMANUEL HEALTH EDUCATION INC", + "src": "IRS_EO_BMF", + "t": "C", + "m": "nonprofit", + "ci": "COLUMBIA", + "st": "MD", + "cc": "US" + }, + { + "id": "org_rec_6874025da267e771", + "n": "LINCOLN COMMUNITY HEALTH CENTER INCORPORATED", + "src": "IRS_EO_BMF", + "t": "C", + "m": "nonprofit", + "ci": "DURHAM", + "st": "NC", + "cc": "US" + }, + { + "id": "org_rec_6d449782b86ba9a1", + "n": "SALVATION HEALTH EDUCATION AND DISEASE PREVENTION OUTREACH INC", + "src": "IRS_EO_BMF", + "t": "C", + "m": "nonprofit", + "ci": "WORCESTER", + "st": "MA", + "cc": "US" + }, + { + "id": "org_rec_7335a682f7bb7495", + "n": "COMMUNITY MEDICAL EDUCATION AND RESEARCH FOUNDATION", + "src": "IRS_EO_BMF", + "t": "C", + "m": "foundation", + "ci": "BAKERSFIELD", + "st": "CA", + "cc": "US" + }, + { + "id": "org_rec_76f9053bf4b48edc", + "n": "COUNCIL FOR BLACK HEALTH EDUCATION & WELLNESS", + "src": "IRS_EO_BMF", + "t": "C", + "m": "nonprofit", + "ci": "BAKERSFIELD", + "st": "CA", + "cc": "US" + }, + { + "id": "org_rec_78cf453e090d5916", + "n": "Ffdc Mutual Aid Network Inc", + "src": "ProPublica", + "t": "B", + "m": "mutual_aid", + "ci": "Columbia", + "st": "MD", + "cc": "US" + }, + { + "id": "org_rec_80bfcb26fc67a39c", + "n": "AMERICAN EAGLE FINANCIAL CREDIT UNION INCORPORATED", + "src": "IRS_EO_BMF", + "t": "C", + "m": "nonprofit", + "ci": "EAST HARTFORD", + "st": "CT", + "cc": "US" + }, + { + "id": "org_rec_85b3a9133bd564c9", + "n": "Mutual Aid Worcester", + "w": "www.facebook.com/groups/MutualAidWorcester", + "src": "mutual_aid_hub", + "t": "B", + "m": "mutual_aid", + "ci": "Worcester", + "st": "MA", + "cc": "US" + }, + { + "id": "org_rec_90d53ba7f4daae9d", + "n": "HABITAT FOR HUMANITY INTERNATIONAL INC", + "src": "IRS_EO_BMF", + "t": "C", + "m": "sweat_equity_program", + "ci": "TULSA", + "st": "OK", + "cc": "US" + }, + { + "id": "org_rec_9ea9c8e341b41046", + "n": "BLACK FORUM OF CO-OP CITY", + "src": "IRS_EO_BMF", + "t": "C", + "m": "cooperative", + "ci": "BRONX", + "st": "NY", + "cc": "US" + }, + { + "id": "org_rec_b06f500ac4bc406e", + "n": "Ashton Central Mosque Food Bank for Cov-ID 19 Support", + "w": "www.ashtoncentralmosque.com/wp/index.php/services/tameside-f", + "src": "Field research + Wikidata", + "t": "C", + "m": "mutual_aid", + "cc": "GB" + }, + { + "id": "org_rec_b29a3b004eccdbdc", + "n": "Nigerian Conservation Foundation", + "w": "ncfnigeria.org", + "src": "Field research + Wikidata", + "t": "B", + "m": "foundation", + "cc": "NG" + }, + { + "id": "org_rec_b48ad99f198219b7", + "n": "EDWARD M KENNEDY COMMUNITY HEALTH CENTER INC", + "src": "IRS_EO_BMF", + "t": "C", + "m": "nonprofit", + "ci": "WORCESTER", + "st": "MA", + "cc": "US" + }, + { + "id": "org_rec_bbe1926cfd533f6b", + "n": "Westcott Mutual Aid", + "src": "mutual_aid_hub", + "t": "B", + "m": "mutual_aid", + "ci": "Syracuse", + "st": "NY", + "cc": "US" + }, + { + "id": "org_rec_c9518232bd6354bb", + "n": "WESTREET FEDERAL CREDIT UNION", + "src": "IRS_EO_BMF", + "t": "C", + "m": "nonprofit", + "ci": "TULSA", + "st": "OK", + "cc": "US" + }, + { + "id": "org_rec_ca4b5ad732a68d31", + "n": "CHRISTIAN ASSEMBLY EMERGENCY FOOD PANTRY", + "src": "IRS_EO_BMF", + "t": "C", + "m": "nonprofit", + "ci": "DURHAM", + "st": "NC", + "cc": "US" + }, + { + "id": "org_rec_cc6ff11b990520ad", + "n": "Syracuse Community Health Center Inc", + "src": "ProPublica", + "t": "B", + "m": "nonprofit", + "ci": "Syracuse", + "st": "NY", + "cc": "US" + }, + { + "id": "org_rec_e191a4704fe52494", + "n": "HABITAT FOR HUMANITY INTERNATIONAL INC", + "src": "IRS_EO_BMF", + "t": "C", + "m": "sweat_equity_program", + "ci": "FORT WORTH", + "st": "TX", + "cc": "US" + }, + { + "id": "org_rec_e6240be1fc6995bb", + "n": "Kern County Mutual Aid", + "w": "www.facebook.com/DSAkerncounty", + "src": "mutual_aid_hub", + "t": "B", + "m": "mutual_aid", + "ci": "Bakersfield", + "st": "CA", + "cc": "US" + }, + { + "id": "org_rec_e778b27d9beec550", + "n": "RAINBOW LIFE COMMUNITY GARDEN INC", + "src": "IRS_EO_BMF", + "t": "C", + "m": "nonprofit", + "ci": "BRONX", + "st": "NY", + "cc": "US" + }, + { + "id": "org_rec_e868c1527499c501", + "n": "CROSSOVER COMMUNITY LAND TRUST INC", + "src": "IRS_EO_BMF", + "t": "C", + "m": "nonprofit", + "ci": "TULSA", + "st": "OK", + "cc": "US" + }, + { + "id": "org_rec_f2678ccdb82700be", + "n": "RHODE ISLAND FREE CLINIC INC", + "src": "IRS_EO_BMF", + "t": "C", + "m": "nonprofit", + "ci": "PROVIDENCE", + "st": "RI", + "cc": "US" + }, + { + "id": "org_rec_f2ee3c295daa51da", + "n": "HABITAT FOR HUMANITY OF NORTH CENTRAL CONNECTICUT", + "src": "IRS_EO_BMF", + "t": "C", + "m": "sweat_equity_program", + "ci": "HARTFORD", + "st": "CT", + "cc": "US" + }, + { + "id": "org_rec_f5d5c0c8e9ecf69d", + "n": "COVID-19 Resource Spreadsheet - Durham", + "src": "mutual_aid_hub", + "t": "B", + "m": "mutual_aid", + "ci": "Durham", + "st": "NC", + "cc": "US" + }, + { + "id": "org_rec_f5de00cce0e9999c", + "n": "CREDIT UNION WOMENS LEADERSHIP ALLIANCE INC", + "src": "IRS_EO_BMF", + "t": "C", + "m": "federation", + "ci": "FORT WORTH", + "st": "TX", + "cc": "US" + }, + { + "id": "org_rec_f6f5e4892a54c342", + "n": "Howard County Community Organizations Active in Disaster", + "src": "mutual_aid_hub", + "t": "B", + "m": "mutual_aid", + "ci": "Columbia", + "st": "MD", + "cc": "US" + }, + { + "id": "org_rec_fd28ca9a46d23eca", + "n": "CENTRAL NEW YORK AREA HEALTH EDUCATION CENTER INC", + "src": "IRS_EO_BMF", + "t": "C", + "m": "nonprofit", + "ci": "SYRACUSE", + "st": "NY", + "cc": "US" + } + ] +} diff --git a/data/map/circuits.json b/data/map/circuits.json new file mode 100644 index 0000000..f505756 --- /dev/null +++ b/data/map/circuits.json @@ -0,0 +1,636 @@ +{ + "generated_at": "2026-07-03T12:00:42Z", + "source_script": "data/build_edges.py", + "note": "Circuit candidates: groups of nearby organizations that jointly fill the roles of a documented solution circuit. Derived, unverified - treat as introductions worth making, not existing partnerships.", + "circuits": [ + { + "id": "labor_for_housing", + "name": "Labor-for-housing pipeline", + "problem": "Affordable homeownership without lifelong debt: land held in trust keeps homes permanently affordable, organized labor turns work-hours into equity, and cooperative finance bridges construction costs.", + "evidence": "LABOR-FOR-HOUSING-GUIDE.md" + }, + { + "id": "community_food_system", + "name": "Local food security loop", + "problem": "A local food system that survives supply shocks: growers produce, a cooperative channel distributes, and access organizations get food to people who cannot pay market prices.", + "evidence": "data/taxonomy.yaml (Food and Nourishment; Local Food Systems; Food Sovereignty)" + }, + { + "id": "housing_justice_pipeline", + "name": "Housing justice pipeline", + "problem": "Stopping displacement takes three capacities at once: tenants organized to resist eviction, legal capacity to fight cases, and a permanent- affordability vehicle to move buildings out of the speculative market.", + "evidence": "data/taxonomy.yaml (Housing Rights [NEW_2026]; Community Land Trusts)" + }, + { + "id": "community_health_mesh", + "name": "Community health mesh", + "problem": "Clinical care alone misses people; mutual aid alone lacks clinical capacity. A clinic, a neighborhood outreach network, and a health educator together form last-mile public health infrastructure.", + "evidence": "data/taxonomy.yaml (Community Health Workers [NEW_2026]; Mutual Aid)" + }, + { + "id": "worker_transition", + "name": "Worker ownership transition", + "problem": "When firms close or owners retire, jobs vanish. A union to organize the workforce, a cooperative developer to structure worker buyouts, and a trainer to reskill make business succession into worker ownership.", + "evidence": "START-A-LABOR-UNION.md; data/taxonomy.yaml (Worker Cooperatives [NEW_2026])" + }, + { + "id": "land_stewardship_alliance", + "name": "Land stewardship alliance", + "problem": "Conservation without production becomes a museum; production without stewardship strips the land. A land-holding entity, an ecological steward, and a working farm together keep land healthy and in use.", + "evidence": "data/taxonomy.yaml (Land Stewardship; Land Return [NEW_2026]; Regenerative Agriculture)" + }, + { + "id": "food_waste_loop", + "name": "Food waste-to-soil loop", + "problem": "Edible surplus feeds people, inedible surplus feeds soil, and gardens close the loop by growing more food. Requires rescue logistics, composting capacity, and growing space in the same city.", + "evidence": "data/taxonomy.yaml (Composting; Recycling and Reuse; Community Gardens via Gardening)" + }, + { + "id": "civic_information_commons", + "name": "Civic information commons", + "problem": "Local news deserts starve local democracy. Community media, an education partner, and civic organizing groups can together rebuild a shared information base that residents actually use.", + "evidence": "data/taxonomy.yaml (Open Source Journalism [NEW_2026]; Media; Democracy Education)" + }, + { + "id": "cooperative_incubator", + "name": "Cooperative development pipeline", + "problem": "New co-ops fail alone: they need an apex body for peer support and standards, patient cooperative finance, and technical education. Together these form a regional co-op incubator.", + "evidence": "data/relationships.csv (apex membership patterns); MAP-V3-PLAN.md phase 2" + }, + { + "id": "disaster_resilience_grid", + "name": "Disaster resilience grid", + "problem": "When infrastructure fails, response speed depends on relationships that already exist: neighborhood mutual aid for distribution, clinical capacity for care, and a coordinating body for logistics.", + "evidence": "data/taxonomy.yaml (Mutual Aid [NEW_2026]; Climate Adaptation [NEW_2026])" + }, + { + "id": "community_energy_transition", + "name": "Community energy transition", + "problem": "Energy bills drain neighborhoods; community-owned generation keeps the money local. Needs a generation co-op, finance for the capital cost, and a civic anchor to aggregate demand and host installations.", + "evidence": "data/taxonomy.yaml (Community Energy [NEW_2026]; Renewable Energy)" + }, + { + "id": "eldercare_commons", + "name": "Eldercare commons", + "problem": "Aging in place fails without three supports: cooperative or co-housing arrangements, day-to-day practical help, and accessible clinical care.", + "evidence": "data/taxonomy.yaml (Eldercare Commons [NEW_2026]; Seniors' Health)" + } + ], + "total_candidates": 76, + "candidates_by_country": { + "BG": [ + { + "group_id": "community_food_system_7133cc6010", + "circuit": "community_food_system", + "circuit_name": "Local food security loop", + "problem": "A local food system that survives supply shocks: growers produce, a cooperative channel distributes, and access organizations get food to people who cannot pay market prices.", + "evidence": "data/taxonomy.yaml (Food and Nourishment; Local Food Systems; Food Sovereignty)", + "score": 0.9, + "avg_km": 1.4, + "span_km": 2.0, + "country": "BG", + "centroid": [ + 42.6877, + 23.3305 + ], + "explanation": "Together: Farmhopping (grower) + Hrancoop (distribution) + Bulgarian Food Bank (access) could close a local food loop (grow + distribute + guarantee access).", + "members": [ + { + "id": "org_902290", + "name": "Farmhopping", + "role": "grower", + "role_label": "grower", + "framework": "food", + "model": "nonprofit" + }, + { + "id": "org_902364", + "name": "Hrancoop", + "role": "distribution", + "role_label": "distribution", + "framework": "food", + "model": "cooperative" + }, + { + "id": "org_902352", + "name": "Bulgarian Food Bank", + "role": "access", + "role_label": "access", + "framework": "food", + "model": "nonprofit" + } + ] + } + ], + "NG": [ + { + "group_id": "land_stewardship_alliance_5ae95aa3bc", + "circuit": "land_stewardship_alliance", + "circuit_name": "Land stewardship alliance", + "problem": "Conservation without production becomes a museum; production without stewardship strips the land. A land-holding entity, an ecological steward, and a working farm together keep land healthy and in use.", + "evidence": "data/taxonomy.yaml (Land Stewardship; Land Return [NEW_2026]; Regenerative Agriculture)", + "score": 0.8709, + "avg_km": 0.0, + "span_km": 0.0, + "country": "NG", + "centroid": [ + 9.08, + 8.67 + ], + "explanation": "Together: Aya International Development Indigenous Knowledge Initiative Nigeria (land tenure) + Nigerian Conservation Foundation (ecological stewardship) + Edo Co-operative Farmers (regenerative production) could hold, restore and work land together (secure tenure + ecological stewardship + regenerative production).", + "members": [ + { + "id": "rec_37a96b11038babdc", + "name": "Edo Co-operative Farmers", + "role": "producer", + "role_label": "regenerative production", + "framework": "food", + "model": "cooperative" + }, + { + "id": "rec_272eb6fb4fac1ecd", + "name": "Aya International Development Indigenous Knowledge Initiative Nigeria", + "role": "tenure", + "role_label": "land tenure", + "framework": "democratic_sovereignty", + "model": "nonprofit" + }, + { + "id": "rec_b29a3b004eccdbdc", + "name": "Nigerian Conservation Foundation", + "role": "steward", + "role_label": "ecological stewardship", + "framework": "ecology", + "model": "foundation" + } + ] + } + ], + "US": [ + { + "group_id": "community_health_mesh_ed3e827f6e", + "circuit": "community_health_mesh", + "circuit_name": "Community health mesh", + "problem": "Clinical care alone misses people; mutual aid alone lacks clinical capacity. A clinic, a neighborhood outreach network, and a health educator together form last-mile public health infrastructure.", + "evidence": "data/taxonomy.yaml (Community Health Workers [NEW_2026]; Mutual Aid)", + "score": 0.8489, + "avg_km": 0.1, + "span_km": 0.1, + "country": "US", + "centroid": [ + 35.3869, + -119.017 + ], + "explanation": "Together: COMMUNITY MEDICAL EDUCATION AND RESEARCH FOUNDATION (clinical care) + Kern County Mutual Aid (neighborhood outreach) + COUNCIL FOR BLACK HEALTH EDUCATION & WELLNESS (health education) could run last-mile community health (clinic + neighborhood outreach + health education).", + "members": [ + { + "id": "rec_76f9053bf4b48edc", + "name": "COUNCIL FOR BLACK HEALTH EDUCATION & WELLNESS", + "role": "education", + "role_label": "health education", + "framework": "healthcare", + "model": "nonprofit" + }, + { + "id": "rec_7335a682f7bb7495", + "name": "COMMUNITY MEDICAL EDUCATION AND RESEARCH FOUNDATION", + "role": "clinic", + "role_label": "clinical care", + "framework": "healthcare", + "model": "foundation" + }, + { + "id": "rec_e6240be1fc6995bb", + "name": "Kern County Mutual Aid", + "role": "outreach", + "role_label": "neighborhood outreach", + "framework": "democratic_sovereignty", + "model": "mutual_aid" + } + ] + }, + { + "group_id": "community_health_mesh_39dfa477c7", + "circuit": "community_health_mesh", + "circuit_name": "Community health mesh", + "problem": "Clinical care alone misses people; mutual aid alone lacks clinical capacity. A clinic, a neighborhood outreach network, and a health educator together form last-mile public health infrastructure.", + "evidence": "data/taxonomy.yaml (Community Health Workers [NEW_2026]; Mutual Aid)", + "score": 0.8487, + "avg_km": 0.1, + "span_km": 0.1, + "country": "US", + "centroid": [ + 42.2623, + -71.803 + ], + "explanation": "Together: EDWARD M KENNEDY COMMUNITY HEALTH CENTER INC (clinical care) + Mutual Aid Worcester (neighborhood outreach) + SALVATION HEALTH EDUCATION AND DISEASE PREVENTION OUTREACH INC (health education) could run last-mile community health (clinic + neighborhood outreach + health education).", + "members": [ + { + "id": "rec_6d449782b86ba9a1", + "name": "SALVATION HEALTH EDUCATION AND DISEASE PREVENTION OUTREACH INC", + "role": "education", + "role_label": "health education", + "framework": "healthcare", + "model": "nonprofit" + }, + { + "id": "rec_b48ad99f198219b7", + "name": "EDWARD M KENNEDY COMMUNITY HEALTH CENTER INC", + "role": "clinic", + "role_label": "clinical care", + "framework": "healthcare", + "model": "nonprofit" + }, + { + "id": "rec_85b3a9133bd564c9", + "name": "Mutual Aid Worcester", + "role": "outreach", + "role_label": "neighborhood outreach", + "framework": "democratic_sovereignty", + "model": "mutual_aid" + } + ] + }, + { + "group_id": "disaster_resilience_grid_5bb2dfa1a0", + "circuit": "disaster_resilience_grid", + "circuit_name": "Disaster resilience grid", + "problem": "When infrastructure fails, response speed depends on relationships that already exist: neighborhood mutual aid for distribution, clinical capacity for care, and a coordinating body for logistics.", + "evidence": "data/taxonomy.yaml (Mutual Aid [NEW_2026]; Climate Adaptation [NEW_2026])", + "score": 0.8474, + "avg_km": 0.1, + "span_km": 0.2, + "country": "US", + "centroid": [ + 41.8245, + -71.4123 + ], + "explanation": "Together: AMOR - COVID19 Community Response Volunteer Sign Up (neighborhood distribution) + RHODE ISLAND FREE CLINIC INC (clinical care) + Rhode Island Pride COVID-19 Emergency Food/Toiletries/Sanitation Supply Drive (coordination) could form a pre-wired disaster response grid (neighborhood distribution + clinical care + coordination).", + "members": [ + { + "id": "rec_4bc89cc09f8eab58", + "name": "Rhode Island Pride COVID-19 Emergency Food/Toiletries/Sanitation Supply Drive", + "role": "coordination", + "role_label": "coordination", + "framework": "democratic_sovereignty", + "model": "mutual_aid" + }, + { + "id": "rec_132008209b27a30a", + "name": "AMOR - COVID19 Community Response Volunteer Sign Up", + "role": "distribution", + "role_label": "neighborhood distribution", + "framework": "democratic_sovereignty", + "model": "mutual_aid" + }, + { + "id": "rec_f2678ccdb82700be", + "name": "RHODE ISLAND FREE CLINIC INC", + "role": "care", + "role_label": "clinical care", + "framework": "healthcare", + "model": "nonprofit" + } + ] + }, + { + "group_id": "disaster_resilience_grid_6c88266798", + "circuit": "disaster_resilience_grid", + "circuit_name": "Disaster resilience grid", + "problem": "When infrastructure fails, response speed depends on relationships that already exist: neighborhood mutual aid for distribution, clinical capacity for care, and a coordinating body for logistics.", + "evidence": "data/taxonomy.yaml (Mutual Aid [NEW_2026]; Climate Adaptation [NEW_2026])", + "score": 0.8456, + "avg_km": 0.2, + "span_km": 0.4, + "country": "US", + "centroid": [ + 35.9958, + -78.8973 + ], + "explanation": "Together: COVID-19 Resource Spreadsheet - Durham (neighborhood distribution) + LINCOLN COMMUNITY HEALTH CENTER INCORPORATED (clinical care) + CHRISTIAN ASSEMBLY EMERGENCY FOOD PANTRY (coordination) could form a pre-wired disaster response grid (neighborhood distribution + clinical care + coordination).", + "members": [ + { + "id": "rec_ca4b5ad732a68d31", + "name": "CHRISTIAN ASSEMBLY EMERGENCY FOOD PANTRY", + "role": "coordination", + "role_label": "coordination", + "framework": "food", + "model": "nonprofit" + }, + { + "id": "rec_f5d5c0c8e9ecf69d", + "name": "COVID-19 Resource Spreadsheet - Durham", + "role": "distribution", + "role_label": "neighborhood distribution", + "framework": "democratic_sovereignty", + "model": "mutual_aid" + }, + { + "id": "rec_6874025da267e771", + "name": "LINCOLN COMMUNITY HEALTH CENTER INCORPORATED", + "role": "care", + "role_label": "clinical care", + "framework": "healthcare", + "model": "nonprofit" + } + ] + }, + { + "group_id": "community_health_mesh_749faac21c", + "circuit": "community_health_mesh", + "circuit_name": "Community health mesh", + "problem": "Clinical care alone misses people; mutual aid alone lacks clinical capacity. A clinic, a neighborhood outreach network, and a health educator together form last-mile public health infrastructure.", + "evidence": "data/taxonomy.yaml (Community Health Workers [NEW_2026]; Mutual Aid)", + "score": 0.8437, + "avg_km": 0.3, + "span_km": 0.5, + "country": "US", + "centroid": [ + 43.0466, + -76.151 + ], + "explanation": "Together: Syracuse Community Health Center Inc (clinical care) + Westcott Mutual Aid (neighborhood outreach) + CENTRAL NEW YORK AREA HEALTH EDUCATION CENTER INC (health education) could run last-mile community health (clinic + neighborhood outreach + health education).", + "members": [ + { + "id": "rec_fd28ca9a46d23eca", + "name": "CENTRAL NEW YORK AREA HEALTH EDUCATION CENTER INC", + "role": "education", + "role_label": "health education", + "framework": "healthcare", + "model": "nonprofit" + }, + { + "id": "rec_cc6ff11b990520ad", + "name": "Syracuse Community Health Center Inc", + "role": "clinic", + "role_label": "clinical care", + "framework": "healthcare", + "model": "nonprofit" + }, + { + "id": "rec_bbe1926cfd533f6b", + "name": "Westcott Mutual Aid", + "role": "outreach", + "role_label": "neighborhood outreach", + "framework": "democratic_sovereignty", + "model": "mutual_aid" + } + ] + }, + { + "group_id": "disaster_resilience_grid_f89af5b745", + "circuit": "disaster_resilience_grid", + "circuit_name": "Disaster resilience grid", + "problem": "When infrastructure fails, response speed depends on relationships that already exist: neighborhood mutual aid for distribution, clinical capacity for care, and a coordinating body for logistics.", + "evidence": "data/taxonomy.yaml (Mutual Aid [NEW_2026]; Climate Adaptation [NEW_2026])", + "score": 0.8279, + "avg_km": 1.2, + "span_km": 1.8, + "country": "US", + "centroid": [ + 39.2146, + -76.8719 + ], + "explanation": "Together: Ffdc Mutual Aid Network Inc (neighborhood distribution) + EMMANUEL HEALTH EDUCATION INC (clinical care) + Howard County Community Organizations Active in Disaster (coordination) could form a pre-wired disaster response grid (neighborhood distribution + clinical care + coordination).", + "members": [ + { + "id": "rec_f6f5e4892a54c342", + "name": "Howard County Community Organizations Active in Disaster", + "role": "coordination", + "role_label": "coordination", + "framework": "democratic_sovereignty", + "model": "mutual_aid" + }, + { + "id": "rec_78cf453e090d5916", + "name": "Ffdc Mutual Aid Network Inc", + "role": "distribution", + "role_label": "neighborhood distribution", + "framework": "economic_democracy", + "model": "mutual_aid" + }, + { + "id": "rec_64a862832e6379b1", + "name": "EMMANUEL HEALTH EDUCATION INC", + "role": "care", + "role_label": "clinical care", + "framework": "healthcare", + "model": "nonprofit" + } + ] + }, + { + "group_id": "community_food_system_947003c3af", + "circuit": "community_food_system", + "circuit_name": "Local food security loop", + "problem": "A local food system that survives supply shocks: growers produce, a cooperative channel distributes, and access organizations get food to people who cannot pay market prices.", + "evidence": "data/taxonomy.yaml (Food and Nourishment; Local Food Systems; Food Sovereignty)", + "score": 0.7959, + "avg_km": 0.0, + "span_km": 0.0, + "country": "US", + "centroid": [ + 40.8222, + -73.9217 + ], + "explanation": "Together: RAINBOW LIFE COMMUNITY GARDEN INC (grower) + BLACK FORUM OF CO-OP CITY (distribution) + FOOD BANK FOR NEW YORK CITY (access) could close a local food loop (grow + distribute + guarantee access).", + "members": [ + { + "id": "rec_e778b27d9beec550", + "name": "RAINBOW LIFE COMMUNITY GARDEN INC", + "role": "grower", + "role_label": "grower", + "framework": "food", + "model": "nonprofit" + }, + { + "id": "rec_9ea9c8e341b41046", + "name": "BLACK FORUM OF CO-OP CITY", + "role": "distribution", + "role_label": "distribution", + "framework": "food", + "model": "cooperative" + }, + { + "id": "rec_21fba585e1b64825", + "name": "FOOD BANK FOR NEW YORK CITY", + "role": "access", + "role_label": "access", + "framework": "democratic_sovereignty", + "model": "nonprofit" + } + ] + }, + { + "group_id": "labor_for_housing_e201bdc4d6", + "circuit": "labor_for_housing", + "circuit_name": "Labor-for-housing pipeline", + "problem": "Affordable homeownership without lifelong debt: land held in trust keeps homes permanently affordable, organized labor turns work-hours into equity, and cooperative finance bridges construction costs.", + "evidence": "LABOR-FOR-HOUSING-GUIDE.md", + "score": 0.7559, + "avg_km": 0.0, + "span_km": 0.0, + "country": "US", + "centroid": [ + 36.0557, + -96.0602 + ], + "explanation": "Together: CROSSOVER COMMUNITY LAND TRUST INC (land) + HABITAT FOR HUMANITY INTERNATIONAL INC (build labor) + WESTREET FEDERAL CREDIT UNION (finance) could run a labor-for-housing pipeline (land in trust + labor as equity + cooperative finance).", + "members": [ + { + "id": "rec_c9518232bd6354bb", + "name": "WESTREET FEDERAL CREDIT UNION", + "role": "finance", + "role_label": "finance", + "framework": "democratic_sovereignty", + "model": "nonprofit" + }, + { + "id": "rec_e868c1527499c501", + "name": "CROSSOVER COMMUNITY LAND TRUST INC", + "role": "land", + "role_label": "land", + "framework": "housing_land", + "model": "nonprofit" + }, + { + "id": "rec_90d53ba7f4daae9d", + "name": "HABITAT FOR HUMANITY INTERNATIONAL INC", + "role": "build_labor", + "role_label": "build labor", + "framework": "housing_land", + "model": "sweat_equity_program" + } + ] + }, + { + "group_id": "labor_for_housing_062b7d5b5e", + "circuit": "labor_for_housing", + "circuit_name": "Labor-for-housing pipeline", + "problem": "Affordable homeownership without lifelong debt: land held in trust keeps homes permanently affordable, organized labor turns work-hours into equity, and cooperative finance bridges construction costs.", + "evidence": "LABOR-FOR-HOUSING-GUIDE.md", + "score": 0.7559, + "avg_km": 0.0, + "span_km": 0.0, + "country": "US", + "centroid": [ + 32.7469, + -97.3268 + ], + "explanation": "Together: FORT WORTH COMMUNITY LAND TRUST (land) + HABITAT FOR HUMANITY INTERNATIONAL INC (build labor) + CREDIT UNION WOMENS LEADERSHIP ALLIANCE INC (finance) could run a labor-for-housing pipeline (land in trust + labor as equity + cooperative finance).", + "members": [ + { + "id": "rec_f5de00cce0e9999c", + "name": "CREDIT UNION WOMENS LEADERSHIP ALLIANCE INC", + "role": "finance", + "role_label": "finance", + "framework": "economic_democracy", + "model": "federation" + }, + { + "id": "rec_3be58a68c5f0bb27", + "name": "FORT WORTH COMMUNITY LAND TRUST", + "role": "land", + "role_label": "land", + "framework": "housing_land", + "model": "nonprofit" + }, + { + "id": "rec_e191a4704fe52494", + "name": "HABITAT FOR HUMANITY INTERNATIONAL INC", + "role": "build_labor", + "role_label": "build labor", + "framework": "housing_land", + "model": "sweat_equity_program" + } + ] + }, + { + "group_id": "labor_for_housing_1d488117bc", + "circuit": "labor_for_housing", + "circuit_name": "Labor-for-housing pipeline", + "problem": "Affordable homeownership without lifelong debt: land held in trust keeps homes permanently affordable, organized labor turns work-hours into equity, and cooperative finance bridges construction costs.", + "evidence": "LABOR-FOR-HOUSING-GUIDE.md", + "score": 0.7403, + "avg_km": 3.9, + "span_km": 5.9, + "country": "US", + "centroid": [ + 41.7692, + -72.663 + ], + "explanation": "Together: NORTH HARTFORD COMMUNITY LAND TRUST (land) + HABITAT FOR HUMANITY OF NORTH CENTRAL CONNECTICUT (build labor) + AMERICAN EAGLE FINANCIAL CREDIT UNION INCORPORATED (finance) could run a labor-for-housing pipeline (land in trust + labor as equity + cooperative finance).", + "members": [ + { + "id": "rec_80bfcb26fc67a39c", + "name": "AMERICAN EAGLE FINANCIAL CREDIT UNION INCORPORATED", + "role": "finance", + "role_label": "finance", + "framework": "democratic_sovereignty", + "model": "nonprofit" + }, + { + "id": "rec_4025e2497718b264", + "name": "NORTH HARTFORD COMMUNITY LAND TRUST", + "role": "land", + "role_label": "land", + "framework": "housing_land", + "model": "nonprofit" + }, + { + "id": "rec_f2ee3c295daa51da", + "name": "HABITAT FOR HUMANITY OF NORTH CENTRAL CONNECTICUT", + "role": "build_labor", + "role_label": "build labor", + "framework": "housing_land", + "model": "sweat_equity_program" + } + ] + } + ], + "GB": [ + { + "group_id": "community_food_system_b06e2cae36", + "circuit": "community_food_system", + "circuit_name": "Local food security loop", + "problem": "A local food system that survives supply shocks: growers produce, a cooperative channel distributes, and access organizations get food to people who cannot pay market prices.", + "evidence": "data/taxonomy.yaml (Food and Nourishment; Local Food Systems; Food Sovereignty)", + "score": 0.7255, + "avg_km": 7.4, + "span_km": 11.1, + "country": "GB", + "centroid": [ + 53.4761, + -2.1912 + ], + "explanation": "Together: Hulme Community Garden Centre (grower) + 8th Day (distribution) + Ashton Central Mosque Food Bank for Cov-ID 19 Support (access) could close a local food loop (grow + distribute + guarantee access).", + "members": [ + { + "id": "org_902776", + "name": "Hulme Community Garden Centre", + "role": "grower", + "role_label": "grower", + "framework": "food", + "model": "collective" + }, + { + "id": "org_902281", + "name": "8th Day", + "role": "distribution", + "role_label": "distribution", + "framework": "food", + "model": "cooperative" + }, + { + "id": "rec_b06f500ac4bc406e", + "name": "Ashton Central Mosque Food Bank for Cov-ID 19 Support", + "role": "access", + "role_label": "access", + "framework": "democratic_sovereignty", + "model": "mutual_aid" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/data/map/stats.v3.json b/data/map/stats.v3.json new file mode 100644 index 0000000..c0f4d42 --- /dev/null +++ b/data/map/stats.v3.json @@ -0,0 +1,163 @@ +{ + "orgs_total_db": 165143, + "orgs_in_directory": 163625, + "orgs_on_map": 29378, + "countries_with_at_least_one_org": 174, + "countries_with_geocoded_org": 102, + "by_tier": { + "A_curated": 0, + "B_verified": 15217, + "C_inferred": 14161, + "D_unverified_off_map": 3800 + }, + "by_tier_full": { + "A": 0, + "B": 144205, + "C": 15620, + "D": 3800 + }, + "by_section": { + "democracy": 9562, + "healthcare": 6071, + "education": 3866, + "food": 3516, + "housing_land": 2637, + "ecology": 2273, + "cooperatives": 1251, + "recreation_arts": 127, + "energy_digital": 74, + "unknown": 1 + }, + "by_country": { + "US": 13545, + "GB": 13309, + "DE": 389, + "CH": 302, + "IT": 157, + "FR": 150, + "AT": 140, + "ES": 125, + "CA": 93, + "AU": 85, + "JP": 54, + "SE": 51, + "NO": 50, + "GR": 47, + "BE": 43, + "ZA": 41, + "KE": 39, + "HU": 37, + "RO": 36, + "EE": 36, + "FI": 34, + "HR": 31, + "BR": 30, + "IE": 30, + "UG": 30, + "PT": 28, + "DK": 25, + "MT": 24, + "IN": 22, + "SI": 22, + "PL": 18, + "CZ": 17, + "PH": 15, + "NZ": 14, + "PE": 14, + "TR": 14, + "CO": 13, + "NG": 13, + "BG": 12, + "CL": 12, + "MX": 12, + "AR": 10, + "TH": 10, + "ZM": 10, + "EC": 9, + "SR": 9, + "BO": 8, + "GT": 8, + "NL": 8, + "BD": 7, + "ID": 7, + "NP": 7, + "PA": 7, + "CR": 6, + "HN": 6, + "PY": 6, + "LK": 5, + "SN": 5, + "TZ": 5, + "HT": 4, + "KH": 4, + "KR": 4, + "MG": 4, + "RW": 4, + "UA": 4, + "VN": 4, + "PR": 4, + "CM": 3, + "JM": 3, + "MA": 3, + "MY": 3, + "PK": 3, + "PS": 3, + "TW": 3, + "LV": 3, + "AM": 2, + "DO": 2, + "FJ": 2, + "GH": 2, + "JO": 2, + "KZ": 2, + "MZ": 2, + "RS": 2, + "TN": 2, + "TT": 2, + "LB": 2, + "SK": 2, + "CI": 1, + "GY": 1, + "UK": 1, + "MK": 1, + "LU": 1, + "CY": 1 + }, + "edges_total": 6471, + "edges_by_type": { + "verified_relationship": 12, + "circuit_candidate": 228, + "cross_section_complementarity": 3367, + "same_section_proximity": 2864 + }, + "sections": [ + "democracy", + "cooperatives", + "healthcare", + "food", + "education", + "housing_land", + "conflict", + "energy_digital", + "recreation_arts", + "ecology" + ], + "sensitive_pins_withheld": { + "CN": 3, + "EG": 5, + "ET": 4, + "MM": 2, + "NI": 6, + "RU": 1, + "VE": 2, + "IR": 2, + "CU": 1 + }, + "sensitive_pins_withheld_total": 26, + "last_built": "2026-07-03T12:00:25Z", + "last_built_date": "2026-07-03", + "source_script": "data/build_map_v2.py", + "circuit_groups_total": 76, + "edges_built_by": "data/build_edges.py", + "edges_built_at": "2026-07-03T12:00:42Z" +} \ No newline at end of file diff --git a/index.html b/index.html index a6b77b5..3620c7b 100644 --- a/index.html +++ b/index.html @@ -397,6 +397,7 @@

Global directory map.

Explore the map → Browse directory + Possible collaborations
29,422 mapped · 102 countries · 153,426 candidates total · full directory diff --git a/sitemap.xml b/sitemap.xml index 4a1db68..07e289b 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1,7 +1,21 @@ - https://commonweave.earth/2026-05-041.0 - https://commonweave.earth/directory.html2026-05-040.9 - https://commonweave.earth/map.html2026-05-040.9 - https://commonweave.earth/doc.html?file=DIRECTORY2026-05-040.7 + https://commonweave.earth/2026-07-031.0 + https://commonweave.earth/directory.html2026-07-030.9 + https://commonweave.earth/map.html2026-07-030.9 + https://commonweave.earth/briefs/index.html2026-07-030.8 + https://commonweave.earth/doc.html?file=DIRECTORY2026-07-030.7 + https://commonweave.earth/briefs/community_food_system_7133cc6010.html2026-07-030.6 + https://commonweave.earth/briefs/land_stewardship_alliance_5ae95aa3bc.html2026-07-030.6 + https://commonweave.earth/briefs/community_health_mesh_ed3e827f6e.html2026-07-030.6 + https://commonweave.earth/briefs/community_health_mesh_39dfa477c7.html2026-07-030.6 + https://commonweave.earth/briefs/disaster_resilience_grid_5bb2dfa1a0.html2026-07-030.6 + https://commonweave.earth/briefs/disaster_resilience_grid_6c88266798.html2026-07-030.6 + https://commonweave.earth/briefs/community_health_mesh_749faac21c.html2026-07-030.6 + https://commonweave.earth/briefs/disaster_resilience_grid_f89af5b745.html2026-07-030.6 + https://commonweave.earth/briefs/community_food_system_947003c3af.html2026-07-030.6 + https://commonweave.earth/briefs/labor_for_housing_062b7d5b5e.html2026-07-030.6 + https://commonweave.earth/briefs/labor_for_housing_e201bdc4d6.html2026-07-030.6 + https://commonweave.earth/briefs/labor_for_housing_1d488117bc.html2026-07-030.6 + https://commonweave.earth/briefs/community_food_system_b06e2cae36.html2026-07-030.6 diff --git a/tools/build-circuit-briefs.py b/tools/build-circuit-briefs.py new file mode 100644 index 0000000..f882132 --- /dev/null +++ b/tools/build-circuit-briefs.py @@ -0,0 +1,766 @@ +#!/usr/bin/env python3 +""" +Build static, printable solution-circuit briefs from the public map export. + +The briefs are attraction artifacts, not outreach messages. They never send +anything, contain no analytics, and state prominently that every circuit is a +derived, unverified possibility rather than an existing partnership. + +Usage: + python tools/build-circuit-briefs.py + python tools/build-circuit-briefs.py --check +""" + +from __future__ import annotations + +import argparse +from collections import Counter +from datetime import datetime, timezone +from html import escape +import json +from pathlib import Path +import re +import sys +from urllib.parse import quote, urlencode, urlparse + + +ROOT = Path(__file__).resolve().parents[1] +CIRCUITS_PATH = ROOT / "data" / "map" / "circuits.json" +ORGS_PATH = ROOT / "data" / "map" / "orgs.v3.geojson" +STATS_PATH = ROOT / "data" / "map" / "stats.v3.json" +OUTPUT_DIR = ROOT / "briefs" +MANIFEST_PATH = OUTPUT_DIR / "manifest.json" +SOURCE_RECORDS_PATH = OUTPUT_DIR / "source-records.json" +SITEMAP_PATH = ROOT / "sitemap.xml" + +SITE_ORIGIN = "https://commonweave.earth" +REPO_ORIGIN = "https://github.com/simonlpaige/commonweave" +ISSUE_BASE = f"{REPO_ORIGIN}/issues/new" +SLUG_RE = re.compile(r"^[a-z0-9][a-z0-9_-]{2,100}$") + +CIRCUIT_ROLE_ORDER = { + "labor_for_housing": ["land", "build_labor", "finance"], + "community_food_system": ["grower", "distribution", "access"], + "land_stewardship_alliance": ["tenure", "steward", "producer"], + "community_health_mesh": ["clinic", "outreach", "education"], + "disaster_resilience_grid": ["distribution", "care", "coordination"], +} + + +BRIEFS_CSS = r"""/* Generated support stylesheet for Commonweave circuit briefs. */ +.brief-shell { max-width: 1120px; margin: 0 auto; padding: clamp(42px, 7vw, 92px) clamp(20px, 5vw, 56px) var(--s-9); } +.brief-hero { display: grid; grid-template-columns: minmax(0, 1fr) 210px; gap: var(--s-7); align-items: start; padding-bottom: var(--s-7); border-bottom: var(--rule); } +.brief-hero h1 { font-size: clamp(52px, 8vw, 104px); line-height: .92; font-style: italic; max-width: 13ch; margin: var(--s-4) 0 var(--s-5); text-wrap: balance; } +.brief-hero .lede { color: var(--ink-soft); max-width: 37ch; } +.status-stamp { border: 2px solid var(--clay); color: var(--clay); padding: 18px 14px; font-family: var(--f-mono); font-size: 11px; line-height: 1.45; letter-spacing: .13em; text-transform: uppercase; transform: rotate(2deg); text-align: center; background: color-mix(in oklab, var(--paper) 88%, transparent); } +.status-stamp strong { display: block; font-size: 15px; letter-spacing: .08em; margin-bottom: 6px; } +.brief-meta { display: flex; gap: var(--s-4); flex-wrap: wrap; margin-top: var(--s-5); font-family: var(--f-mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-muted); } +.brief-section { padding: var(--s-8) 0; border-bottom: var(--rule); } +.brief-section h2 { font-size: clamp(38px, 5vw, 66px); max-width: 15ch; margin-bottom: var(--s-6); } +.section-intro { color: var(--ink-soft); font-size: 19px; max-width: 62ch; } +.circuit-loom { position: relative; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-5); margin-top: var(--s-7); } +.circuit-loom::before { content: ""; position: absolute; left: 10%; right: 10%; top: 31px; height: 2px; background: var(--thread); z-index: 0; } +.role-card { position: relative; z-index: 1; border: var(--rule); background: var(--paper); padding: 58px var(--s-5) var(--s-5); min-height: 245px; } +.role-card::before { content: ""; position: absolute; top: 23px; left: 50%; width: 16px; height: 16px; margin-left: -9px; border-radius: 50%; background: var(--clay); border: 2px solid var(--paper); box-shadow: 0 0 0 1px var(--thread); } +.role-label { font-family: var(--f-mono); font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--clay); } +.role-card h3 { font-size: clamp(24px, 2.4vw, 33px); margin: var(--s-3) 0; } +.role-card p { color: var(--ink-muted); font-size: 15px; } +.role-links { display: flex; gap: var(--s-3); flex-wrap: wrap; margin-top: var(--s-5); font-family: var(--f-mono); font-size: 10px; text-transform: uppercase; letter-spacing: .08em; } +.role-links a { text-decoration: none; border-bottom: 1px solid currentColor; } +.finding { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(260px, .6fr); gap: var(--s-7); align-items: start; } +.finding blockquote { margin: 0; font-family: var(--f-display); font-style: italic; font-size: clamp(27px, 3.2vw, 44px); line-height: 1.16; color: var(--moss-deep); } +.field-note { border-left: 3px solid var(--thread); padding-left: var(--s-5); color: var(--ink-soft); } +.unknowns { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--ink); border: var(--rule); margin-top: var(--s-6); } +.unknown { background: var(--paper); padding: var(--s-5); } +.unknown b { display: block; font-family: var(--f-mono); font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--clay); margin-bottom: var(--s-3); } +.brief-actions { display: flex; gap: var(--s-3); flex-wrap: wrap; align-items: center; margin-top: var(--s-6); } +.brief-button { appearance: none; border: 1px solid var(--ink); background: transparent; color: var(--ink); padding: 10px 16px; font: 500 10px/1 var(--f-mono); letter-spacing: .12em; text-transform: uppercase; text-decoration: none; cursor: pointer; } +.brief-button.primary { background: var(--moss); border-color: var(--moss); color: var(--paper); } +.brief-button:hover { background: var(--paper-2); color: var(--moss-deep); } +.brief-button.primary:hover { background: var(--moss-deep); color: var(--paper); } +.source-note { color: var(--ink-muted); font-size: 14px; overflow-wrap: anywhere; } +.source-note code { font-family: var(--f-mono); font-size: 12px; } +.brief-index-hero { padding-bottom: var(--s-7); border-bottom: var(--rule); } +.brief-index-hero h1 { font-size: clamp(56px, 9vw, 112px); line-height: .91; font-style: italic; max-width: 12ch; margin: var(--s-4) 0 var(--s-5); } +.filter-bar { display: grid; grid-template-columns: minmax(220px, 1fr) 220px; gap: var(--s-3); margin: var(--s-7) 0; } +.filter-bar label { display: grid; gap: 6px; font: 500 10px/1.4 var(--f-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-muted); } +.filter-bar input, .filter-bar select { width: 100%; border: 1px solid var(--ink); border-radius: 0; background: var(--paper); color: var(--ink); padding: 12px 13px; font: 16px/1.3 var(--f-body); } +.brief-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-5); } +.brief-card { border: var(--rule); padding: var(--s-5); background: color-mix(in oklab, var(--paper) 82%, var(--paper-2)); display: flex; flex-direction: column; } +.brief-card .card-kicker { display: flex; justify-content: space-between; gap: var(--s-3); font-family: var(--f-mono); font-size: 9px; letter-spacing: .11em; text-transform: uppercase; color: var(--ink-muted); } +.brief-card h2 { font-size: clamp(30px, 3vw, 44px); margin: var(--s-4) 0; } +.brief-card ul { list-style: none; margin: 0 0 var(--s-5); padding: 0; color: var(--ink-soft); } +.brief-card li { padding: 7px 0; border-top: var(--rule-soft); } +.brief-card > a { margin-top: auto; align-self: flex-start; font-family: var(--f-mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase; } +.empty-result { display: none; padding: var(--s-7); border: var(--rule); color: var(--ink-soft); } +.empty-result.visible { display: block; } +body.dark .role-card, body.dark .unknown, body.dark .filter-bar input, body.dark .filter-bar select { background: var(--paper); } +body.dark .status-stamp { background: var(--paper); } +@media (max-width: 820px) { + .brief-hero { grid-template-columns: 1fr; } + .status-stamp { max-width: 210px; transform: none; } + .circuit-loom { grid-template-columns: 1fr; } + .circuit-loom::before { top: 6%; bottom: 6%; left: 31px; right: auto; width: 2px; height: auto; } + .role-card { padding: var(--s-5) var(--s-5) var(--s-5) 62px; min-height: 0; } + .role-card::before { left: 23px; top: 50%; margin: -9px 0 0; } + .finding, .unknowns, .brief-grid { grid-template-columns: 1fr; } + .filter-bar { grid-template-columns: 1fr; } +} +@media (max-width: 600px) { + .nav-links a:not(.nav-cta) { display: none; } + .brief-shell { padding-left: 18px; padding-right: 18px; } +} +@media print { + .site-nav, .site-foot, .brief-actions, .filter-bar { display: none !important; } + body { background: #fff !important; color: #111 !important; font-size: 12pt; } + .brief-shell { max-width: none; padding: 0; } + .brief-hero { grid-template-columns: 1fr 150px; } + .brief-hero h1 { font-size: 52pt; } + .brief-section { padding: 28pt 0; } + .role-card, .unknown { break-inside: avoid; background: #fff !important; } + a { color: #111 !important; } +} +""" + + +BRIEFS_JS = r"""(function () { + "use strict"; + var search = document.getElementById("brief-search"); + var country = document.getElementById("brief-country"); + var cards = Array.prototype.slice.call(document.querySelectorAll("[data-brief-card]")); + var count = document.getElementById("brief-visible-count"); + var empty = document.getElementById("brief-empty"); + + function applyFilters() { + var q = search ? search.value.trim().toLowerCase() : ""; + var cc = country ? country.value : ""; + var visible = 0; + cards.forEach(function (card) { + var matchesText = !q || (card.getAttribute("data-search") || "").indexOf(q) !== -1; + var matchesCountry = !cc || card.getAttribute("data-country") === cc; + var show = matchesText && matchesCountry; + card.hidden = !show; + if (show) visible += 1; + }); + if (count) count.textContent = String(visible); + if (empty) empty.classList.toggle("visible", visible === 0); + } + + if (search) search.addEventListener("input", applyFilters); + if (country) country.addEventListener("change", applyFilters); + + document.querySelectorAll("[data-copy-url]").forEach(function (button) { + button.addEventListener("click", function () { + var url = button.getAttribute("data-copy-url") || location.href; + if (!navigator.clipboard) return; + navigator.clipboard.writeText(url).then(function () { + var previous = button.textContent; + button.textContent = "Link copied"; + window.setTimeout(function () { button.textContent = previous; }, 1600); + }); + }); + }); +}()); +""" + + +def load_json(path: Path) -> dict: + if not path.exists(): + raise FileNotFoundError(f"Required input is missing: {path}") + with path.open("r", encoding="utf-8") as handle: + return json.load(handle) + + +def html(value: object) -> str: + return escape(str(value if value is not None else ""), quote=True) + + +def normalize_org_id(value: object) -> str: + raw = str(value or "").strip() + return raw if raw.startswith("org_") else f"org_{raw}" + + +def validate_slug(value: object) -> str: + slug = str(value or "").strip().lower() + if not SLUG_RE.fullmatch(slug): + raise ValueError(f"Unsafe or invalid circuit group id: {value!r}") + return slug + + +def safe_website(value: object) -> str | None: + raw = str(value or "").strip() + if not raw: + return None + if not re.match(r"^https?://", raw, flags=re.I): + raw = "https://" + raw + parsed = urlparse(raw) + if parsed.scheme not in {"http", "https"} or not parsed.netloc: + return None + return raw + + +def compact_number(value: object) -> str: + try: + return f"{int(value):,}" + except (TypeError, ValueError): + return "unknown" + + +def most_common_nonempty(values: list[object]) -> str: + cleaned = [str(v).strip() for v in values if str(v or "").strip()] + if not cleaned: + return "" + return Counter(cleaned).most_common(1)[0][0] + + +def location_for(members: list[dict], country: str) -> str: + city = most_common_nonempty([m.get("ci") for m in members]) + state = most_common_nonempty([m.get("st") for m in members]) + pieces = [p for p in (city.title() if city else "", state, country) if p] + return ", ".join(pieces) if pieces else "Location not resolved" + + +def proximity_text(group: dict) -> str: + try: + span = float(group.get("span_km") or 0) + except (TypeError, ValueError): + span = 0 + if span <= 0: + return "Published map locations resolve to the same point" + if span < 1: + return f"Published map locations span about {span:.1f} km" + return f"Published map locations span about {span:.0f} km" + + +def feature_lookup(orgs: dict) -> dict[str, dict]: + result: dict[str, dict] = {} + for feature in orgs.get("features", []): + props = feature.get("properties") or {} + org_id = normalize_org_id(props.get("id") or feature.get("id")) + result[org_id] = props + return result + + +def source_record_lookup(payload: dict) -> dict[str, dict]: + result: dict[str, dict] = {} + for record in payload.get("records", []): + org_id = normalize_org_id(record.get("id")) + result[org_id] = record + return result + + +def member_ids(circuits: dict) -> set[str]: + return { + normalize_org_id(member.get("id")) + for groups in (circuits.get("candidates_by_country") or {}).values() + for group in groups + for member in group.get("members", []) + } + + +def render_source_records(features: dict[str, dict], circuits: dict) -> str: + public_fields = ("id", "n", "w", "src", "t", "m", "ci", "st", "cc") + records = [] + for org_id in sorted(member_ids(circuits)): + props = features.get(org_id, {}) + record = { + key: props.get(key) + for key in public_fields + if props.get(key) not in (None, "") + } + record["id"] = org_id + records.append(record) + payload = { + "schema_version": 1, + "generated_at": circuits.get("generated_at"), + "source": "data/map/orgs.v3.geojson", + "note": ( + "Compact public-field snapshot for deterministic circuit brief builds; " + "contains only organizations referenced by circuits.json." + ), + "records": records, + } + return json.dumps(payload, indent=2, ensure_ascii=False) + "\n" + + +def enrich_group(group: dict, features: dict[str, dict]) -> dict: + enriched_members = [] + for member in group.get("members", []): + org_id = normalize_org_id(member.get("id")) + props = features.get(org_id, {}) + enriched_members.append({ + **member, + **props, + "id": org_id, + "name": member.get("name") or props.get("n") or "Unnamed organization", + "website": safe_website(props.get("w")), + }) + role_order = CIRCUIT_ROLE_ORDER.get(str(group.get("circuit")), []) + rank = {role: index for index, role in enumerate(role_order)} + enriched_members.sort( + key=lambda member: ( + rank.get(str(member.get("role")), len(rank)), + str(member.get("name") or ""), + ) + ) + country = str(group.get("country") or most_common_nonempty([m.get("cc") for m in enriched_members])) + return { + **group, + "group_id": validate_slug(group.get("group_id")), + "members": enriched_members, + "country": country, + "location": location_for(enriched_members, country), + "proximity": proximity_text(group), + } + + +def flatten_groups(circuits: dict, features: dict[str, dict]) -> list[dict]: + groups = [] + for country, country_groups in (circuits.get("candidates_by_country") or {}).items(): + if not isinstance(country_groups, list): + raise ValueError(f"Expected a list of circuit candidates for {country}") + for group in country_groups: + groups.append(enrich_group(group, features)) + groups.sort(key=lambda item: (-float(item.get("score") or 0), item["group_id"])) + if len({g["group_id"] for g in groups}) != len(groups): + raise ValueError("Circuit group ids are not unique") + return groups + + +def logo_markup() -> str: + return """ + + + + + + + + commonweave +""" + + +def nav_markup(prefix: str = "../") -> str: + return f""" +""" + + +def footer_markup() -> str: + return f"""""" + + +def head_markup(title: str, description: str, canonical: str) -> str: + return f""" + + + + +{html(title)} + + + + + + + + + + + + + + +""" + + +def correction_url(group: dict) -> str: + member_lines = "\n".join( + f"- {member['name']} — proposed role: {member.get('role_label') or member.get('role') or 'unknown'}" + for member in group["members"] + ) + body = f"""## Solution-circuit brief correction + +**Circuit brief:** {SITE_ORIGIN}/briefs/{group['group_id']}.html +**Group id:** `{group['group_id']}` + +The page currently presents this as a **derived, unverified possibility**, not an existing partnership: + +{member_lines} + +### What needs correction? + + + +### Public evidence + + +""" + return ISSUE_BASE + "?" + urlencode({ + "title": f"[Circuit correction] {group['group_id']}", + "labels": "org-request", + "body": body, + }, quote_via=quote) + + +def render_role_card(member: dict) -> str: + map_url = f"../map.html#selectedId={quote(member['id'])}" + website = member.get("website") + website_link = "" + if website: + hostname = urlparse(website).netloc.removeprefix("www.") + website_link = ( + f'' + f"{html(hostname)} ↗" + ) + source = member.get("src") or "Source not named in public map export" + model = str(member.get("model") or member.get("m") or "model unknown").replace("_", " ") + tier = member.get("t") + tier_text = f"Tier {html(tier)} · " if tier else "" + role_links = f' View map record' + if website_link: + role_links += f"\n {website_link}" + return f"""
+
{html(member.get("role_label") or member.get("role") or "Possible role")}
+

{html(member["name"])}

+

{tier_text}{html(model)}
Source: {html(source)}

+ +
""" + + +def render_brief(group: dict, stats: dict, generated_at: str) -> str: + title = f"{group.get('circuit_name') or 'Solution circuit'} in {group['location']}" + description = ( + f"A derived, unverified Commonweave field note connecting " + f"{len(group['members'])} nearby organizations with complementary roles." + ) + canonical = f"{SITE_ORIGIN}/briefs/{group['group_id']}.html" + roles = "\n".join(render_role_card(member) for member in group["members"]) + correction = correction_url(group) + built = stats.get("last_built_date") or str(stats.get("last_built") or "")[:10] or "unknown" + mapped = compact_number(stats.get("orgs_on_map")) + members = " + ".join( + html(member.get("role_label") or member.get("role") or "role") + for member in group["members"] + ) + return f"""{head_markup(title, description, canonical)} + +{nav_markup()} +
+
+
+
Solution-circuit field note · {html(group['location'])}
+

{html(group.get('circuit_name') or 'Possible local circuit')}

+

{html(group.get('problem') or '')}

+
+ {html(group['proximity'])} + Map snapshot {html(built)} + {mapped} mapped records +
+
+ +
+ +
+
The possible circuit
+

{members}

+

Commonweave's public map data places these organizations nearby and classifies their public work as complementary. The classification may be wrong or stale.

+
+ {roles} +
+
+ +
+
+
Why the system connected them
+

A lead worth checking.

+
“{html(group.get('explanation') or 'The public descriptions suggest complementary local roles.')}”
+
+ +
+ +
+
What the map cannot know
+

Three questions before anyone acts.

+
+
01 · AccuracyDo these organizations still exist, and are their proposed roles described correctly?
+
02 · ConsentDo they want to be discoverable and introduced in this way?
+
03 · FitIs there a real local need, trust, and capacity for this circuit—or only geographic proximity?
+
+
+ Correct this brief + + + All circuit briefs +
+
+
+{footer_markup()} + + + + +""" + + +def render_index(groups: list[dict], stats: dict, generated_at: str) -> str: + built = stats.get("last_built_date") or str(stats.get("last_built") or "")[:10] or "unknown" + title = "Possible local collaborations — Commonweave circuit briefs" + description = ( + f"{len(groups)} derived, unverified field notes connecting nearby organizations " + "with complementary public roles." + ) + countries = sorted({g["country"] for g in groups if g.get("country")}) + country_options = "\n".join( + f'' for country in countries + ) + cards = [] + for group in groups: + role_lines = "\n".join( + f"
  • {html(member.get('role_label') or member.get('role') or 'Role')}: {html(member['name'])}
  • " + for member in group["members"] + ) + search_blob = " ".join([ + group.get("circuit_name") or "", + group.get("location") or "", + *[member.get("name") or "" for member in group["members"]], + *[member.get("role_label") or member.get("role") or "" for member in group["members"]], + ]).lower() + cards.append(f"""
    +
    {html(group['location'])}Unverified
    +

    {html(group.get('circuit_name') or 'Possible local circuit')}

    + + Open field note → +
    """) + return f"""{head_markup(title, description, f"{SITE_ORIGIN}/briefs/index.html")} + +{nav_markup()} +
    +
    +
    Commonweave field notes · Map snapshot {html(built)}
    +

    Possible collaborations, not claimed partnerships.

    +

    These {len(groups)} one-page briefs turn public directory data into specific questions: which nearby organizations might fill complementary roles, and what did the map get wrong?

    +

    Every brief is derived and unverified. Nothing here says the listed organizations know one another, endorse Commonweave, or want an introduction. Each page carries its uncertainty and a correction path.

    +
    + +
    +
    + + +
    +
    {len(groups)} field notes shown
    +
    + {''.join(cards)} +
    +
    No briefs match those filters. Clear the search or choose another country.
    +
    +
    +{footer_markup()} + + + + +""" + + +def render_manifest(groups: list[dict], circuits: dict, stats: dict) -> str: + payload = { + "schema_version": 1, + "generated_at": circuits.get("generated_at"), + "source_script": "tools/build-circuit-briefs.py", + "source_files": [ + "data/map/circuits.json", + "briefs/source-records.json (compact fallback from data/map/orgs.v3.geojson)", + "data/map/stats.v3.json", + ], + "stats_build_date": stats.get("last_built_date"), + "brief_count": len(groups), + "source_declared_candidate_count": circuits.get("total_candidates"), + "source_count_matches": circuits.get("total_candidates") == len(groups), + "briefs": [ + { + "group_id": group["group_id"], + "circuit": group.get("circuit"), + "country": group.get("country"), + "location": group.get("location"), + "member_ids": [member["id"] for member in group["members"]], + } + for group in groups + ], + } + return json.dumps(payload, indent=2, ensure_ascii=False) + "\n" + + +def render_sitemap(groups: list[dict], stats: dict) -> str: + lastmod = stats.get("last_built_date") or datetime.now(timezone.utc).strftime("%Y-%m-%d") + urls = [ + (f"{SITE_ORIGIN}/", "1.0"), + (f"{SITE_ORIGIN}/directory.html", "0.9"), + (f"{SITE_ORIGIN}/map.html", "0.9"), + (f"{SITE_ORIGIN}/briefs/index.html", "0.8"), + (f"{SITE_ORIGIN}/doc.html?file=DIRECTORY", "0.7"), + ] + urls.extend( + (f"{SITE_ORIGIN}/briefs/{group['group_id']}.html", "0.6") + for group in groups + ) + entries = "\n".join( + f" {html(url)}{html(lastmod)}{priority}" + for url, priority in urls + ) + return ( + '\n' + '\n' + f"{entries}\n" + "\n" + ) + + +def expected_files( + groups: list[dict], + circuits: dict, + stats: dict, + features: dict[str, dict], +) -> dict[Path, str]: + generated_at = str(circuits.get("generated_at") or stats.get("last_built") or "") + files = { + OUTPUT_DIR / "briefs.css": BRIEFS_CSS, + OUTPUT_DIR / "briefs.js": BRIEFS_JS, + OUTPUT_DIR / "index.html": render_index(groups, stats, generated_at), + MANIFEST_PATH: render_manifest(groups, circuits, stats), + SOURCE_RECORDS_PATH: render_source_records(features, circuits), + SITEMAP_PATH: render_sitemap(groups, stats), + } + for group in groups: + files[OUTPUT_DIR / f"{group['group_id']}.html"] = render_brief( + group, stats, generated_at + ) + return files + + +def check_files(files: dict[Path, str]) -> int: + problems = [] + for path, expected in files.items(): + if not path.exists(): + problems.append(f"missing: {path.relative_to(ROOT)}") + continue + actual = path.read_text(encoding="utf-8") + if actual != expected: + problems.append(f"stale: {path.relative_to(ROOT)}") + + expected_brief_files = { + path.name for path in files if path.parent == OUTPUT_DIR + } + if OUTPUT_DIR.exists(): + for path in OUTPUT_DIR.iterdir(): + if path.is_file() and path.name not in expected_brief_files: + problems.append(f"unexpected: {path.relative_to(ROOT)}") + + if problems: + print("Circuit briefs are not current:") + for problem in problems: + print(f" - {problem}") + return 1 + print(f"Circuit briefs are current ({len(files) - 6} briefs).") + return 0 + + +def write_files(files: dict[Path, str]) -> None: + OUTPUT_DIR.mkdir(parents=True, exist_ok=True) + + expected_brief_files = { + path.name for path in files if path.parent == OUTPUT_DIR + } + if MANIFEST_PATH.exists(): + try: + old_manifest = load_json(MANIFEST_PATH) + old_slugs = { + validate_slug(item.get("group_id")) + for item in old_manifest.get("briefs", []) + if item.get("group_id") + } + except (ValueError, json.JSONDecodeError): + old_slugs = set() + for slug in old_slugs: + stale_path = OUTPUT_DIR / f"{slug}.html" + if stale_path.name not in expected_brief_files and stale_path.exists(): + stale_path.unlink() + + for path, content in files.items(): + path.parent.mkdir(parents=True, exist_ok=True) + if not path.exists() or path.read_text(encoding="utf-8") != content: + path.write_text(content, encoding="utf-8", newline="\n") + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument( + "--check", + action="store_true", + help="Fail when committed brief files do not match the current data export.", + ) + args = parser.parse_args() + + circuits = load_json(CIRCUITS_PATH) + stats = load_json(STATS_PATH) + if ORGS_PATH.exists(): + features = feature_lookup(load_json(ORGS_PATH)) + else: + features = source_record_lookup(load_json(SOURCE_RECORDS_PATH)) + groups = flatten_groups(circuits, features) + declared = circuits.get("total_candidates") + if declared is not None and int(declared) != len(groups): + print( + f"WARNING: circuits.json declares {declared} candidates but contains " + f"{len(groups)}; generating only the observable groups.", + file=sys.stderr, + ) + files = expected_files(groups, circuits, stats, features) + + if args.check: + return check_files(files) + + write_files(files) + print( + f"Wrote {len(groups)} circuit briefs to {OUTPUT_DIR.relative_to(ROOT)} " + f"from map snapshot {stats.get('last_built_date') or 'unknown'}." + ) + return 0 + + +if __name__ == "__main__": + try: + sys.exit(main()) + except (FileNotFoundError, ValueError, json.JSONDecodeError) as exc: + print(f"build-circuit-briefs: {exc}", file=sys.stderr) + sys.exit(1) diff --git a/tools/build.py b/tools/build.py index 2a16a65..fd35991 100644 --- a/tools/build.py +++ b/tools/build.py @@ -4,12 +4,13 @@ Steps (in order): 1. data/build_search_index.py 2. data/build_map_v2.py - 3. tools/wiki-update.py (skip with --skip-wiki) - 4. tools/gen-audit-data.py --region usa - 5. tools/gen-audit-data.py --region india - 6. tools/gen-audit-data.py --region latam - (skip 4-6 with --skip-audit) - 7. Write data/generated/MANIFEST.json with built_at, org_count, + 3. tools/build-circuit-briefs.py + 4. tools/wiki-update.py (skip with --skip-wiki) + 5. tools/gen-audit-data.py --region usa + 6. tools/gen-audit-data.py --region india + 7. tools/gen-audit-data.py --region latam + (skip 5-7 with --skip-audit) + 8. Write data/generated/MANIFEST.json with built_at, org_count, country_count, geocoded_count, files_generated, db_path. Each step prints its wall-clock duration. A failing step is logged as a @@ -120,6 +121,7 @@ def list_generated_files(): os.path.join(DATA_DIR, 'search'), os.path.join(DATA_DIR, 'map'), os.path.abspath(os.path.join(WORKSPACE, 'audit')), + os.path.abspath(os.path.join(WORKSPACE, 'briefs')), ] files = [] for root in targets: @@ -171,7 +173,15 @@ def main(): results=results, ) - # 3. wiki update + # 3. printable, shareable circuit briefs + run_step( + 'build-circuit-briefs', + [os.path.abspath(os.path.join(TOOLS_DIR, 'build-circuit-briefs.py'))], + dry_run=args.dry_run, + results=results, + ) + + # 4. wiki update if args.skip_wiki: print('\n>>> [wiki-update] skipped (--skip-wiki)') results.append({'step': 'wiki-update', 'status': 'skipped', 'duration_s': 0.0}) @@ -183,7 +193,7 @@ def main(): results=results, ) - # 4-6. audit data per region + # 5-7. audit data per region if args.skip_audit: print('\n>>> [gen-audit-data] skipped (--skip-audit)') for region in ('usa', 'india', 'latam'):