From b3a5d140a2127c39abfea5a625a19b0095f76663 Mon Sep 17 00:00:00 2001 From: Martin Wainstein Date: Fri, 12 Jun 2026 12:44:56 -0600 Subject: [PATCH 01/14] Make the Readiness Engine profile-driven (pluggable per MDB) Extract IDB SFP's hardcoded eligibility logic into a pluggable 'readiness profile' (readiness-profiles.js). scoring.js now derives weights, tiers, the project-eligibility gate and the documentary checklist from the active profile; the default 'idb-sfp' profile reproduces prior behavior byte-for-byte (verified: 567 assertions across 63 SNGs, 0 diffs). Other MDBs (CAF, World Bank, EIB, GCF) plug in their own profile. This makes readiness the bridge between the City-Funder Matching Engine and any funder's pipeline. Co-Authored-By: Claude Opus 4.8 --- .../control-tower/READINESS-PROFILES.md | 110 ++++++++++ .../justagiraffe/control-tower/index.html | 1 + .../control-tower/readiness-profiles.js | 189 ++++++++++++++++++ .../justagiraffe/control-tower/scoring.js | 127 ++++++------ 4 files changed, 367 insertions(+), 60 deletions(-) create mode 100644 events/2026-06-11-unlock-the-money/justagiraffe/control-tower/READINESS-PROFILES.md create mode 100644 events/2026-06-11-unlock-the-money/justagiraffe/control-tower/readiness-profiles.js diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/READINESS-PROFILES.md b/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/READINESS-PROFILES.md new file mode 100644 index 0000000..9f204bd --- /dev/null +++ b/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/READINESS-PROFILES.md @@ -0,0 +1,110 @@ +# Readiness Profiles — the pluggable contract behind the Readiness Engine + +> **TL;DR** You are never "ready" in the abstract — you are ready *for a specific +> funder's criteria*. A **readiness profile** packages one MDB instrument's +> criteria (pillars, weights, tiers, eligibility gate, documentary checklist, +> preparation track) as a plug-in. The Readiness Engine (`scoring.js`) runs +> whatever profile is active. **IDB SFP is profile #1**; CAF / World Bank / EIB / +> GCF add their own. This is what turns justagiraffe from *an IDB tool* into +> *the readiness layer for any MDB.* + +## Why this exists + +The original `scoring.js` hardcoded the IDB Sub-Sovereign Finance Program: the +four pillars, their weights, the tier thresholds, the §4.3 project-eligibility +gate, and the OP-301 documentary checklist. That made the engine IDB-only. + +Two things in this repo wanted it to be more than that: + +1. **The platform vision** — the same engine should serve every MDB running a + sub-sovereign / urban-finance pilot (the SPEC's "repeatable to any MDB" + revenue framing). Each MDB has *different* criteria. +2. **The City-Funder Matching Engine** — it narrows a city's plan to a few + *candidate funding targets*. For a chosen target, *someone* has to answer "is + this city ready **for that target**?" That someone is the Readiness Engine, + parameterized by the target's profile. + +So readiness is the **bridge** between matching ("where could this city go?") and +submission ("can it actually get there, and how does it prepare?"). + +## Files + +| File | What it is | +|---|---| +| `readiness-profiles.js` | The profile registry + schema. `window.ReadinessProfiles` (browser) / `module.exports` (Node). Holds `idb-sfp` (canonical) + `generic-mdb-template` (illustrative). | +| `scoring.js` | The Readiness Engine. Now **profile-driven** — derives weights/tiers/gates/checklist from the *active* profile. Default `idb-sfp` reproduces the prior behavior exactly. | +| `index.html` | Loads `readiness-profiles.js` **before** `scoring.js`. Otherwise unchanged. | + +## The profile schema + +```js +{ + id, funder, instrument, version, source, summary, + pillars: [{ key, label, weight, basis, source }], // weights sum to 1 → composite 0–100 + tiers: { + thresholds: { ready, developing }, // >=ready Ready, >=developing Developing, else Early + labels: { ready, developing, early }, + actions: { Ready, Developing, Early }, // recommended next action per tier + }, + clearanceBlockers: [{ key, label, test(signals) -> bool }], // hard gates (block even a Ready score) + projectEligibility: [{ key, label, test(sng) -> bool, note? }],// the funder's project gate + documentaryChecklist:[{ key, label, test(sng) -> bool }], // intake documents → pipeline state + preparation: { Developing: {track, funding}, Early: {track, funding} }, // the TC / readiness route + signalSources?: [{ pillar, dataset, field, note }], // provenance: where real pillar inputs come from +} +``` + +`test(...)` predicates are tiny and pure. `clearanceBlockers`/`documentaryChecklist` +receive different inputs (`signals` vs the whole `sng`) to match the existing +`scoring.js` call sites — see those functions for the exact shapes returned. + +## How the engine consumes it + +`scoring.js` keeps every previous export and return shape, so `index.html` is +untouched apart from the one extra ` + {children} diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/page.tsx b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/page.tsx index 0521640..f582e1c 100644 --- a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/page.tsx +++ b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/page.tsx @@ -2,328 +2,292 @@ import { useMemo, useState } from "react"; import Link from "next/link"; -import TopBar from "@/components/TopBar"; -import data from "@/data/valdivia.json"; -import { SM, Profiles, PILLAR_ORDER, provenanceKind, type Comuna, type Scored } from "@/lib/engine"; +import Sidebar, { type StageDef } from "@/components/Sidebar"; +import MapView from "@/components/MapView"; +import { SCOPES, mapPoints, scopeLegend, journeyCity, DATA } from "@/lib/adapters"; +import { SM, provenanceKind, type Scored, type Comuna } from "@/lib/engine"; +import { getCityContext, agentAssist } from "@/lib/context"; +import { assembleDossier } from "@/lib/dossier"; -const STEPS = [ - { n: 1, key: "enter", title: "Enter", sub: "Your city" }, - { n: 2, key: "discover", title: "Discover", sub: "Funders open" }, - { n: 3, key: "target", title: "Pick target", sub: "Choose a path" }, - { n: 4, key: "diagnose", title: "Diagnose", sub: "Readiness" }, - { n: 5, key: "prepare", title: "Prepare", sub: "Close the gap" }, - { n: 6, key: "pool", title: "Pool", sub: "If too small" }, - { n: 7, key: "submit", title: "Submit", sub: "To the funder" }, +const STAGES: StageDef[] = [ + { key: "explore", title: "Explore", sub: "Map & scope" }, + { key: "context", title: "City context", sub: "Source: inventory + plan" }, + { key: "readiness", title: "Readiness pathways", sub: "Assess & route" }, + { key: "portfolio", title: "Portfolio", sub: "Instrument · pool · prepare" }, + { key: "intake", title: "Funder intake", sub: "Dossier & submit" }, ]; -const comunas = (data as any).comunas as Comuna[]; -const hero = comunas.find((c) => c.isAnchor)!; - function ProvBadge({ prov }: { prov: string }) { const kind = provenanceKind(prov); - const label = kind === "real" ? "real" : kind === "intake" ? "intake" : "estimated"; - return {label}; + return {kind}; } function Pillars({ city }: { city: Comuna }) { const expl = SM.explainScore(city.readiness); return (
- {PILLAR_ORDER.map((k) => { - const e = expl.find((x) => x.key === k)!; - return ( -
-
- {SM.PILLAR_LABELS[k]} - {city.readiness[k]} -
-
-
contributes {e.points} pts ({Math.round(e.weight * 100)}% weight)
+ {expl.map((e) => ( +
+
+ {e.label} + {city.readiness[e.key as keyof typeof city.readiness]}
- ); - })} -
- ); -} - -function Gate({ scored }: { scored: Scored }) { - const elig = scored.eligibility; - const profile = SM.activeProfile(); - const labels: Record = {}; - profile.projectEligibility.forEach((c: any) => (labels[c.key] = c.label)); - return ( -
- {Object.entries(elig).filter(([k]) => k !== "eligible").map(([k, v]) => ( -
- - {labels[k] || k} +
+
{e.points} pts · {Math.round(e.weight * 100)}% weight
))}
); } +function pathwayOf(s: Scored): "instrument" | "pool" | "capacity-building" { + if (!s.canEnterProjectReview) return "capacity-building"; + if (s.eligibility.eligible) return "instrument"; + return "pool"; +} + export default function Page() { - const [step, setStep] = useState(1); - const [target, setTarget] = useState(null); - const [pooled, setPooled] = useState(false); + const [scopeId, setScopeId] = useState("cl-losrios"); + const [cityId, setCityId] = useState(null); + const [entry, setEntry] = useState<"entity" | "project">("entity"); + const [stage, setStage] = useState(0); + const [maxReached, setMaxReached] = useState(0); const [submitState, setSubmitState] = useState<{ id: string } | null>(null); const [submitting, setSubmitting] = useState(false); - const heroScored = useMemo(() => SM.scoreSNG(hero), []); - const poolScored = useMemo(() => SM.scoreSNG({ ...hero, proposal: (data as any).pool.pooledProposal }), []); - const profiles = Profiles.listProfiles(); + const scope = SCOPES.find((s) => s.id === scopeId)!; + const points = useMemo(() => mapPoints(scopeId), [scopeId]); + const legend = scopeLegend(scopeId); + + const scored = cityId ? journeyCity(cityId) : null; + const ctx = cityId ? getCityContext(cityId) : null; + const pathway = scored ? pathwayOf(scored) : null; + const pool = scopeId === "cl-losrios" ? DATA.cl.pool : null; + const poolScored = scored && pool ? SM.scoreSNG({ ...(scored as any), proposal: pool.pooledProposal }) : null; - const max = STEPS.length; - const go = (n: number) => setStep(Math.min(max, Math.max(1, n))); + function goto(i: number) { setStage(i); setMaxReached((m) => Math.max(m, i)); } + function pickCity(id: string) { setCityId(id); setSubmitState(null); goto(1); } async function submit() { + if (!scored || !pathway) return; setSubmitting(true); - const handoff = { - candidateId: pooled ? "POOL-LosRios-U11" : hero.id, - kind: pooled ? "pool" : "city", - name: pooled ? (data as any).pool.bundle?.sector ? "Los Ríos unit 11 (transport bundle)" : "Los Ríos pool" : hero.name, - locode: hero.locode, - cityId: hero.cityId, - anchorLocode: (data as any).pool.anchorLocode, - members: pooled ? (data as any).pool.members.map((m: any) => m.locode).filter(Boolean) : [hero.locode], - targetProfileId: SM.activeProfile().id, - compositeReadiness: (pooled ? poolScored : heroScored).compositeReadiness, - tier: (pooled ? poolScored : heroScored).tier, - clearancePassed: (pooled ? poolScored : heroScored).canEnterProjectReview, - proposal: pooled - ? { title: (data as any).pool.pooledProposal.title, askUSDm: (data as any).pool.pooledProposal.askUSDm, sector: "transport" } - : { title: hero.proposal.title, askUSDm: hero.proposal.askUSDm, sector: hero.proposal.sector }, - provenance: hero.provenance, - }; - const res = await fetch("/api/submissions", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(handoff) }); + let opts: any; + if (pathway === "pool" && pool) { + opts = { scored: poolScored, kind: "pool", pathway: "pool", + pool: { anchor: scored.name, members: pool.members.map((m: any) => ({ name: m.name, role: m.isAnchor ? "anchor" : "member", cofinance: m.cofinanceScore })) }, + proposal: pool.pooledProposal }; + } else if (pathway === "capacity-building") { + opts = { scored, kind: "city", pathway: "capacity-building", instrumentName: "Capacity-building / PPF + blended finance", + pool: null, proposal: scored.proposal }; + } else { + opts = { scored, kind: "city", pathway: "instrument", pool: null, proposal: scored.proposal }; + } + const dossier = assembleDossier(opts); + const res = await fetch("/api/submissions", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(dossier) }); const rec = await res.json(); setSubmitState({ id: rec.id }); setSubmitting(false); } return ( - <> - -
-
-

Unlock financing for {hero.name}'s climate plan

-

- See which funders your plan can reach, how ready you are for the IDB Sub-Sovereign Finance Program, - and what to do next — then submit. Real fiscal signals from the City-Funder Matching Engine, scored live by - the Readiness Engine. -

-
- -
- {STEPS.map((s) => ( - - ))} -
+
+ +
+
{scope.country} · {scope.region} · adapter: {scope.adapter}
- {/* STEP 1 — ENTER */} - {step === 1 && ( -
-

1 · Your city

-

Loaded from your CityCatalyst profile. (Live CityCatalyst city-context wiring is Phase 4; here it's the locode-keyed record.)

-
-
-
City{hero.name}
-
UN/LOCODE{hero.locode}
-
RegionRegión de Los Ríos
-
-
-
Population{hero.population?.toLocaleString()}
-
CountryChile (IDB member)
-
CityCatalyst id{hero.cityId?.slice(0, 12)}…
-
+ {/* 0 — EXPLORE */} + {stage === 0 && ( + <> +
Explore financial readiness
+

A geographic view of readiness across a scope, from real national fiscal data. Pick a highlighted city to open its readiness journey.

+
+ {SCOPES.map((s) => ( + + ))}
-
+ +
+ {legend.map((l) => {l.label})} + · data: {scope.adapter} +
+
+

Open a city

+

Cities with a full readiness profile in this scope:

+ {points.filter((p) => p.journeyable).map((p) => ( +
+ {p.name} · {p.capag ? `CAPAG ${p.capag}` : p.tier} + +
+ ))} +
+ )} - {/* STEP 2 — DISCOVER */} - {step === 2 && ( -
-

2 · Funders your plan can reach

-

From the City-Funder Matching Engine — instruments matched to {hero.name}'s prioritized actions, tagged by the role you can play.

-
-
{(data as any).funders.counts.applicant} funds you can apply to directly · {(data as any).funders.counts.facilitator} facilitator · {(data as any).funders.counts.referrer} referrer-only · {(data as any).funders.counts.total} reachable in total
-
IDB SFP appears as a structural debt path for your transport plan — explored in steps 3–6.
+ {/* 1 — CITY CONTEXT */} + {stage === 1 && scored && ctx && ( + <> +
{scored.name}
+

Loaded from {scored.name}'s CityCatalyst context — GHG inventory and HIAP-prioritized actions. (Live CityCatalyst MCP wiring is the seam; here it's simulated context.)

+
+ +
- - - - {(data as any).funders.sample.slice(0, 10).map((f: any, i: number) => ( - - - - - +
+
+

GHG inventory

+

{ctx.inventory.source} · {ctx.inventory.year}

+ {ctx.inventory.topSectors.map((s) => ( +
{s.sector}{s.sharePct}%
))} -
-
ProgramFunderRole
{f.program}{f.funder}{f.role}
-
- )} - - {/* STEP 3 — PICK TARGET */} - {step === 3 && ( -
-

3 · Pick a financing path

-

Each path has its own readiness profile — the criteria you're assessed against. Readiness is target-specific.

- {profiles.map((p: any) => { - const prof = Profiles.getProfile(p.id); - const selected = (target || "idb-sfp") === p.id; - return ( -
{ if (!p.illustrative) { setTarget(p.id); SM.setActiveProfile(p.id); } }}> -
-

{prof.funder}{p.illustrative && (template)}

- {selected && !p.illustrative && selected} +
+
+

HIAP priorities

+

Top prioritized climate actions

+ {ctx.hiap.map((a) => ( +
+ {a.rank}. {a.name} + {a.type}
-

{prof.instrument} — {prof.summary}

- {!p.illustrative && ( -
- Pillars: {prof.pillars.map((pl: any) => `${pl.label} ${Math.round(pl.weight * 100)}%`).join(" · ")} -
- )} -
- ); - })} -
Same engine, different profile. Other MDBs (CAF, World Bank, GCF) plug in their own criteria — the city app doesn't change.
-
+ ))} +
+
+ {entry === "project" && ( +
Project-first: import a prepared project (a Concept Note from the Project Preparator) — it enters at the Portfolio step (②). For this demo the entity-first path is wired; project import is the interop seam.
+ )} +
+ )} - {/* STEP 4 — DIAGNOSE */} - {step === 4 && ( -
-

4 · Readiness for IDB SFP

-

Scored live by the Readiness Engine against the IDB profile. Badges show real vs. estimated signals.

+ {/* 2 — READINESS PATHWAYS */} + {stage === 2 && scored && ( + <> +
Readiness pathways
+

The early creditworthiness assessment for the {SM.activeProfile().instrument}, scored on real fiscal data. The diagnosis routes the next step.

-
+
- {heroScored.compositeReadiness}/100 - {heroScored.tier} + {scored.compositeReadiness}/100 + {scored.tier}
- +
-

IDB project-eligibility gate

- -
- {hero.name} is {heroScored.tier} and cleared on creditworthiness — but its transport project alone is below the US$15M high-impact threshold, so it isn't project-eligible on its own. That gap is solved in step 6. +
+

Eligibility gate

+ {Object.entries(scored.eligibility).filter(([k]) => k !== "eligible").map(([k, v]) => { + const lbl = (SM.activeProfile().projectEligibility.find((c: any) => c.key === k) || {}).label || k; + return
{lbl}
; + })} +
+
+

Recommended pathway

+ {pathway === "instrument" &&

Ready and eligible — proceed directly to the instrument.

} + {pathway === "pool" &&

Ready, but sub-scale. {scored.name} clears creditworthiness, but its project is below the instrument's ticket size. Route → portfolio / pooling.

} + {pathway === "capacity-building" &&

Not yet eligible. Route → capacity-building: targeted TC / PPF before the instrument. Not a debt problem — see the signals.

}
-
+ {(() => { const a = agentAssist({ cityName: scored.name, tier: scored.tier, cleared: scored.canEnterProjectReview, pathway: pathway! }); + return
CityCatalyst agent simulated
{a.text}
; })()} +
+ )} - {/* STEP 5 — PREPARE */} - {step === 5 && ( -
-

5 · Close the gap

-

What each readiness level is routed to — the funded path to becoming loan-ready (IDB Subprogram 2 TC, ~US$13M envelope).

- - - - {comunas.map((c) => { - const s = SM.scoreSNG(c); - return ( - - - - - - ); - })} - -
ComunaTierRecommended action
{c.name}{c.isAnchor && (you)}{s.tier}{s.readinessAction}
-
- {hero.name}'s gap isn't readiness — it's scale. Its neighbours aren't ready to borrow alone. Pooling (next step) fixes both at once. -
-
- )} - - {/* STEP 6 — POOL */} - {step === 6 && ( -
-

6 · The gap becomes the deal

-

Your transport actions have no instrument that fits {hero.name} alone — so the engine pools the unit into one financeable package.

-
- Transport: {(data as any).transportGap.nActions} actions, best single-city fit {(data as any).transportGap.bestFit} ({(data as any).transportGap.bestFunder}) — no dedicated instrument. For one city, a dead end. -
- - - - {comunas.map((c) => { - const s = SM.scoreSNG(c); - return ( - - - - - - - ); - })} - -
ComunaCo-financeReadinessRole
{c.name}{c.cofinanceScore ?? "—"}{s.tier}{c.isAnchor ? Anchor : Member}
-
-
Pooled askUS${(data as any).pool.pooledProposal.askUSDm}M
-
Pool readiness (anchor-led){poolScored.tier} · {poolScored.eligibility.eligible ? "eligible ✓" : "not eligible"}
-
-
- -
-
+ {/* 3 — PORTFOLIO / CAPACITY */} + {stage === 3 && scored && ( + <> + {pathway === "capacity-building" ? ( + <> +
Capacity-building track
+

{scored.name} routes here instead of the loan instrument — what to fix to become eligible, and the funded routes to do it.

+ {(scored as any).capag && ( +
+

Why — the CAPAG signals

+

Real Tesouro Nacional indicators. The gap is not debt.

+
Debt / RCL (endividamento)grade {(scored as any).capag.nota1} ✓
+
Current savings (poupança)grade {(scored as any).capag.nota2}
+
Liquidity (liquidez)grade {(scored as any).capag.nota3}
+
Accounting quality (ICF){(scored as any).capag.icf}
+
+ )} +
+

Funded routes to readiness

+
Accounting / fiscal management TA → lift the ICF ratingPPF · regular TC
+
Build cash reserves & current savingsreform + TC
+
Grant / blended finance for adaptation nowCCFLA / blended
+
+
Once the city re-rates (CAPAG B/A), it re-enters the instrument path. Submitting here registers a capacity-building referral, not a loan.
+
+ + ) : pathway === "pool" && pool ? ( + <> +
Build a financeable portfolio
+

The gap between {scored.name}'s project and the instrument's ticket size is closed by pooling neighbours into one package — portfolio design.

+
Transport: {DATA.cl.transportGap.nActions} actions, best single-city fit {DATA.cl.transportGap.bestFit} — no instrument fits {scored.name} alone.
+
+ + + + {(DATA.cl.comunas as Comuna[]).map((c) => { + const cs = SM.scoreSNG(c); + return ; + })} + +
ComunaCo-finance indexReadinessRole
{c.name}{c.cofinanceScore ?? "—"} /100{cs.tier}{c.isAnchor ? Anchor : Member}
+
+
Pooled askUS${pool.pooledProposal.askUSDm}M
+
Pool readiness{poolScored!.tier} · {poolScored!.eligibility.eligible ? "eligible ✓" : "not eligible"}
+
+
+
+ + ) : ( + <> +
Instrument
+

{scored.name} is ready and eligible — proceed to the instrument.

+
Instrument{SM.activeProfile().instrument}
AskUS${scored.proposal.askUSDm}M
+
+ + )} + )} - {/* STEP 7 — SUBMIT */} - {step === 7 && ( -
-

7 · Submit to IDB

+ {/* 4 — FUNDER INTAKE */} + {stage === 4 && scored && pathway && ( + <> +
Funder intake
{!submitState ? ( <> -

This sends a pre-scored candidate to the IDB-side pipeline (the Control Tower), with your CityCatalyst data attached.

-
-
-
Submitting{pooled ? "Pooled package (6 comunas)" : `${hero.name} (city)`}
-
Anchor{hero.name}
-
TargetIDB SFP
-
-
-
Readiness{(pooled ? poolScored : heroScored).compositeReadiness} · {(pooled ? poolScored : heroScored).tier}
-
AskUS${pooled ? (data as any).pool.pooledProposal.askUSDm : hero.proposal.askUSDm}M
-
Eligible{(pooled ? poolScored : heroScored).eligibility.eligible ? "Yes ✓" : "No"}
-
+

Assemble the machine-readable candidate dossier (Concept Note + creditworthiness + instrument + pool) and submit it to the funder's pipeline.

+
+
Candidate{pathway === "pool" ? `${scored.name} pool (6 comunas)` : scored.name}
+
Pathway{pathway}
+
Target{pathway === "capacity-building" ? "Capacity-building / PPF" : SM.activeProfile().instrument}
+
Readiness{(pathway === "pool" ? poolScored! : scored).compositeReadiness} · {(pathway === "pool" ? poolScored! : scored).tier}
+
AskUS${pathway === "pool" ? pool.pooledProposal.askUSDm : scored.proposal.askUSDm}M
- {!pooled &&
Tip: go back to step 6 and use the pooled package — {hero.name} alone isn't project-eligible (sub-scale).
}
- +
) : ( <> -

Submitted. The candidate is now on the funder's side of the screen.

-
{submitState.id} — {pooled ? "Los Ríos transport pool" : hero.name} is in the IDB pipeline.
-
- See it in the funder pipeline → -
+

Submitted — the dossier is now on the funder's side of the screen.

+
{submitState.id} — {scored.name} ({pathway}) is in the funder pipeline.
+
See it in the funder pipeline →
)} -
+ )} - {/* Nav */} -
- {step > 1 && } - {step < max && } -
-
- + {stage > 0 && ( +
+ +
+ )} +
+
); } diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/pipeline/page.tsx b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/pipeline/page.tsx index b68cd32..9882b6f 100644 --- a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/pipeline/page.tsx +++ b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/pipeline/page.tsx @@ -1,12 +1,13 @@ "use client"; import { useEffect, useState } from "react"; -import TopBar from "@/components/TopBar"; -import type { Submission } from "@/lib/store"; +import Link from "next/link"; +import type { Dossier } from "@/lib/dossier"; export default function PipelinePage() { - const [subs, setSubs] = useState([]); + const [subs, setSubs] = useState([]); const [loading, setLoading] = useState(true); + const [open, setOpen] = useState(null); async function load() { const res = await fetch("/api/submissions", { cache: "no-store" }); @@ -16,52 +17,75 @@ export default function PipelinePage() { useEffect(() => { load(); }, []); return ( - <> - -
-
-

IDB pipeline — incoming candidates

-

The funder side of the screen. Pre-scored cities and pools submitted from CityCatalyst land here, ready for Project Review. (Stands in for the justagiraffe Control Tower receiving the handoff.)

-
+
+
+
IDB · Control Tower — Intake & Triage
+ funder side +
+ +
-
- - {subs.length} candidate{subs.length === 1 ? "" : "s"} -
+
+

Incoming candidate dossiers

+

The funder side of the screen. Pre-scored candidates submitted from CityCatalyst arrive here as machine-readable dossiers, ready for the IDB Sub-Sovereign Finance Program (SFP) review. (Stands in for the justagiraffe Control Tower receiving the handoff.)

+
- {loading ? ( -
Loading…
- ) : subs.length === 0 ? ( -
No candidates yet. Submit one from the city journey.
- ) : ( - subs.map((s) => ( -
-
-

{s.name} {s.kind}

- {s.tier} · {s.compositeReadiness} -
-

{s.proposal.title}

-
-
-
Submission{s.id}
-
Target{s.targetProfileId}
-
Anchor{s.anchorLocode}
-
Members{s.members.length}
-
-
-
AskUS${s.proposal.askUSDm}M
-
Clearance{s.clearancePassed ? "Passed ✓" : "Blocked"}
-
Sector{s.proposal.sector}
-
Received{new Date(s.submittedAt).toLocaleTimeString()}
-
+
+ + {subs.length} dossier{subs.length === 1 ? "" : "s"} +
+ + {loading ? ( +
Loading…
+ ) : subs.length === 0 ? ( +
No dossiers yet. Submit one from the city journey.
+ ) : ( + subs.map((d) => ( +
+
+

{d.name} {d.country} {d.pathway}

+ {d.readiness.tier} · {d.readiness.composite} +
+

{d.conceptNote.title} — {d.instrument.name} ({d.instrument.funder})

+
+
+
Dossier{d.id}
+
AskUS${d.financials.askUSDm}M
+
Clearance{d.readiness.cleared ? "Passed ✓" : "Capacity-building"}
+ {d.pool &&
Pool{d.pool.members.length} members · anchor {d.pool.anchor}
}
-
- Trust layer: fiscal health & governance scored on real SINIM/FCM data via the City-Funder Matching Engine. +
+
Sector{d.conceptNote.sector}
+
City id{d.locode}
+
Received{new Date(d.submittedAt).toLocaleTimeString()}
- )) - )} -
- +
+ +
+ {open === d.id && ( +
+

Concept note — plan

+

{d.conceptNote.summary}

+ {d.conceptNote.actions.map((a, i) => ( +
{a.name}{a.type}
+ ))} +

Readiness — early creditworthiness assessment

+ {d.readiness.pillars.map((p) => ( +
{p.label} ({p.provenance}){p.score}
+ ))} +

Documentary due diligence

+ {d.dueDiligence.map((c, i) => ( +
{c.label}
+ ))} +
{d.provenanceNote}
+
+ )} +
+ )) + )} +
); } diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/components/MapView.tsx b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/components/MapView.tsx new file mode 100644 index 0000000..2c14b81 --- /dev/null +++ b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/components/MapView.tsx @@ -0,0 +1,65 @@ +"use client"; + +import { useEffect, useRef } from "react"; +import type { MapPoint } from "@/lib/adapters"; + +const COLOR: Record = { + Ready: "#2ca36a", bankable: "#2ca36a", + Developing: "#d9942a", constrained: "#d9942a", + Early: "#cf4b41", unrated: "#9aa5b1", +}; + +export default function MapView({ + scopeId, points, center, zoom, onSelect, +}: { + scopeId: string; + points: MapPoint[]; + center: [number, number]; + zoom: number; + onSelect: (id: string) => void; +}) { + const elRef = useRef(null); + const mapRef = useRef(null); + const layerRef = useRef(null); + + useEffect(() => { + let cancelled = false; + function init() { + const L = (window as any).L; + if (!L) { setTimeout(init, 150); return; } + if (cancelled) return; + if (!mapRef.current && elRef.current) { + mapRef.current = L.map(elRef.current, { scrollWheelZoom: false }).setView(center, zoom); + L.tileLayer("https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png", { + attribution: "© OpenStreetMap © CARTO", maxZoom: 19, + }).addTo(mapRef.current); + } + const map = mapRef.current; + map.setView(center, zoom); + if (layerRef.current) { map.removeLayer(layerRef.current); } + const group = L.layerGroup(); + for (const p of points) { + const m = L.circleMarker([p.lat, p.lon], { + radius: p.isHero ? 9 : 5, + color: p.isHero ? "#0f172a" : "#ffffff", + weight: p.isHero ? 2 : 1, + fillColor: COLOR[p.tierClass] || "#9aa5b1", + fillOpacity: 0.9, + }); + const tag = p.capag ? `CAPAG ${p.capag}` : p.tier; + m.bindTooltip(`${p.name}
${tag}${p.journeyable ? " · click to open" : ""}`, { direction: "top" }); + if (p.journeyable) m.on("click", () => onSelect(p.id)); + group.addLayer(m); + } + group.addTo(map); + layerRef.current = group; + } + init(); + return () => { cancelled = true; }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [scopeId, points]); + + useEffect(() => () => { if (mapRef.current) { mapRef.current.remove(); mapRef.current = null; } }, []); + + return
; +} diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/components/Sidebar.tsx b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/components/Sidebar.tsx new file mode 100644 index 0000000..49f89d9 --- /dev/null +++ b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/components/Sidebar.tsx @@ -0,0 +1,43 @@ +"use client"; + +import Link from "next/link"; + +export interface StageDef { key: string; title: string; sub: string } + +export default function Sidebar({ + stages, active, maxReached, onSelect, +}: { + stages: StageDef[]; + active: number; + maxReached: number; + onSelect: (i: number) => void; +}) { + return ( + + ); +} diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/components/TopBar.tsx b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/components/TopBar.tsx deleted file mode 100644 index f408ae8..0000000 --- a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/components/TopBar.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import Link from "next/link"; - -export default function TopBar({ active }: { active: "city" | "pipeline" }) { - return ( -
-
- CityCatalyst · Readiness Navigator -
- IDB SFP -
- -
- ); -} diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/data/brazil.json b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/data/brazil.json new file mode 100644 index 0000000..e0cc41d --- /dev/null +++ b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/data/brazil.json @@ -0,0 +1,4551 @@ +{ + "generated": "2026-06-14", + "source": "CAPAG — Tesouro Nacional (ODbL), via the CAPAG Funder Scan hackday team (Joaquin van Peborgh, Carole Viaene). Screening signal, not a credit decision.", + "scope": { + "country": "Brazil", + "region": "Rio Grande do Sul (RS)", + "note": "state hit by the catastrophic 2024 floods" + }, + "hero": { + "id": "SNG-BR-4304606", + "name": "Canoas", + "locode": "IBGE 4304606", + "cityId": "4304606", + "country": "Brazil", + "iso": "BR", + "type": "City", + "population": 347000, + "isAnchor": false, + "cofinanceScore": null, + "anchorScore": null, + "readiness": { + "creditworthiness": 38, + "fiscalHealth": 52, + "governance": 50, + "legalCapacity": 38 + }, + "provenance": { + "creditworthiness": "real:CAPAG rating C (Tesouro Nacional)", + "fiscalHealth": "real:CAPAG indicators (debt A · savings C · liquidity C)", + "governance": "real:CAPAG ICF Cicf + transparency (RGF/RREO)", + "legalCapacity": "real:CAPAG C — blocked from Union-guaranteed credit" + }, + "signals": { + "capagRating": "C", + "ownSourceRevenuePct": null, + "debtServiceRatioPct": null, + "currentBalancePct": null, + "independentAudit": false, + "canBorrowWithoutSovereignGuarantee": false + }, + "capag": { + "rating": "C", + "ind1": 0.1932645582, + "nota1": "A", + "ind2": 0.9855266178, + "nota2": "C", + "ind3": -0.0234503149, + "nota3": "C", + "icf": "Cicf" + }, + "proposal": { + "title": "Flood resilience & drainage program (post-2024)", + "sector": "water / resilience", + "askUSDm": 45, + "stage": "Readiness Review", + "cofinance": false + } + }, + "stateMap": [ + { + "name": "Aceguá", + "codIbge": "4300034", + "capag": "C", + "tier": "constrained", + "lat": -31.8665, + "lon": -54.1615, + "isHero": false + }, + { + "name": "Água Santa", + "codIbge": "4300059", + "capag": "B", + "tier": "bankable", + "lat": -28.1672, + "lon": -52.031, + "isHero": false + }, + { + "name": "Agudo", + "codIbge": "4300109", + "capag": "A+", + "tier": "bankable", + "lat": -29.6447, + "lon": -53.2515, + "isHero": false + }, + { + "name": "Ajuricaba", + "codIbge": "4300208", + "capag": "B", + "tier": "bankable", + "lat": -28.2342, + "lon": -53.7757, + "isHero": false + }, + { + "name": "Alecrim", + "codIbge": "4300307", + "capag": "C", + "tier": "constrained", + "lat": -27.6579, + "lon": -54.7649, + "isHero": false + }, + { + "name": "Alegrete", + "codIbge": "4300406", + "capag": "A", + "tier": "bankable", + "lat": -29.7902, + "lon": -55.7949, + "isHero": false + }, + { + "name": "Alegria", + "codIbge": "4300455", + "capag": "A", + "tier": "bankable", + "lat": -27.8345, + "lon": -54.0557, + "isHero": false + }, + { + "name": "Almirante Tamandaré do Sul", + "codIbge": "4300471", + "capag": "A+", + "tier": "bankable", + "lat": -28.1149, + "lon": -52.9142, + "isHero": false + }, + { + "name": "Alpestre", + "codIbge": "4300505", + "capag": "A", + "tier": "bankable", + "lat": -27.2502, + "lon": -53.0341, + "isHero": false + }, + { + "name": "Alto Alegre", + "codIbge": "4300554", + "capag": "A", + "tier": "bankable", + "lat": -28.7769, + "lon": -52.9893, + "isHero": false + }, + { + "name": "Alto Feliz", + "codIbge": "4300570", + "capag": "A", + "tier": "bankable", + "lat": -29.3919, + "lon": -51.3123, + "isHero": false + }, + { + "name": "Alvorada", + "codIbge": "4300604", + "capag": "A", + "tier": "bankable", + "lat": -29.9914, + "lon": -51.0809, + "isHero": false + }, + { + "name": "Amaral Ferrador", + "codIbge": "4300638", + "capag": "B+", + "tier": "bankable", + "lat": -30.8756, + "lon": -52.2509, + "isHero": false + }, + { + "name": "Ametista do Sul", + "codIbge": "4300646", + "capag": "C", + "tier": "constrained", + "lat": -27.3607, + "lon": -53.183, + "isHero": false + }, + { + "name": "André da Rocha", + "codIbge": "4300661", + "capag": "A", + "tier": "bankable", + "lat": -28.6283, + "lon": -51.5797, + "isHero": false + }, + { + "name": "Anta Gorda", + "codIbge": "4300703", + "capag": "A", + "tier": "bankable", + "lat": -28.9698, + "lon": -52.0102, + "isHero": false + }, + { + "name": "Antônio Prado", + "codIbge": "4300802", + "capag": "A+", + "tier": "bankable", + "lat": -28.8565, + "lon": -51.2883, + "isHero": false + }, + { + "name": "Arambaré", + "codIbge": "4300851", + "capag": "A", + "tier": "bankable", + "lat": -30.9092, + "lon": -51.5046, + "isHero": false + }, + { + "name": "Araricá", + "codIbge": "4300877", + "capag": "C", + "tier": "constrained", + "lat": -29.6168, + "lon": -50.9291, + "isHero": false + }, + { + "name": "Aratiba", + "codIbge": "4300901", + "capag": "A+", + "tier": "bankable", + "lat": -27.3978, + "lon": -52.2975, + "isHero": false + }, + { + "name": "Arroio do Meio", + "codIbge": "4301008", + "capag": "C", + "tier": "constrained", + "lat": -29.4014, + "lon": -51.9557, + "isHero": false + }, + { + "name": "Arroio do Sal", + "codIbge": "4301057", + "capag": "B+", + "tier": "bankable", + "lat": -29.5439, + "lon": -49.8895, + "isHero": false + }, + { + "name": "Arroio do Padre", + "codIbge": "4301073", + "capag": "A", + "tier": "bankable", + "lat": -31.4389, + "lon": -52.4246, + "isHero": false + }, + { + "name": "Arroio dos Ratos", + "codIbge": "4301107", + "capag": "C", + "tier": "constrained", + "lat": -30.0875, + "lon": -51.7275, + "isHero": false + }, + { + "name": "Arroio do Tigre", + "codIbge": "4301206", + "capag": "B", + "tier": "bankable", + "lat": -29.3348, + "lon": -53.0966, + "isHero": false + }, + { + "name": "Arroio Grande", + "codIbge": "4301305", + "capag": "B", + "tier": "bankable", + "lat": -32.2327, + "lon": -53.0862, + "isHero": false + }, + { + "name": "Arvorezinha", + "codIbge": "4301404", + "capag": "B+", + "tier": "bankable", + "lat": -28.8737, + "lon": -52.1781, + "isHero": false + }, + { + "name": "Augusto Pestana", + "codIbge": "4301503", + "capag": "A+", + "tier": "bankable", + "lat": -28.5172, + "lon": -53.9883, + "isHero": false + }, + { + "name": "Áurea", + "codIbge": "4301552", + "capag": "B", + "tier": "bankable", + "lat": -27.6936, + "lon": -52.0505, + "isHero": false + }, + { + "name": "Bagé", + "codIbge": "4301602", + "capag": "C", + "tier": "constrained", + "lat": -31.3297, + "lon": -54.0999, + "isHero": false + }, + { + "name": "Balneário Pinhal", + "codIbge": "4301636", + "capag": "C", + "tier": "constrained", + "lat": -30.2419, + "lon": -50.2337, + "isHero": false + }, + { + "name": "Barão", + "codIbge": "4301651", + "capag": "A", + "tier": "bankable", + "lat": -29.3725, + "lon": -51.4949, + "isHero": false + }, + { + "name": "Barão de Cotegipe", + "codIbge": "4301701", + "capag": "A", + "tier": "bankable", + "lat": -27.6208, + "lon": -52.3798, + "isHero": false + }, + { + "name": "Barão do Triunfo", + "codIbge": "4301750", + "capag": "n.d.", + "tier": "unrated", + "lat": -30.3891, + "lon": -51.7384, + "isHero": false + }, + { + "name": "Barracão", + "codIbge": "4301800", + "capag": "B", + "tier": "bankable", + "lat": -27.6739, + "lon": -51.4585, + "isHero": false + }, + { + "name": "Barra do Guarita", + "codIbge": "4301859", + "capag": "A", + "tier": "bankable", + "lat": -27.1927, + "lon": -53.7109, + "isHero": false + }, + { + "name": "Barra do Quaraí", + "codIbge": "4301875", + "capag": "A", + "tier": "bankable", + "lat": -30.2029, + "lon": -57.5497, + "isHero": false + }, + { + "name": "Barra do Ribeiro", + "codIbge": "4301909", + "capag": "B", + "tier": "bankable", + "lat": -30.2939, + "lon": -51.3014, + "isHero": false + }, + { + "name": "Barra do Rio Azul", + "codIbge": "4301925", + "capag": "A", + "tier": "bankable", + "lat": -27.4069, + "lon": -52.4084, + "isHero": false + }, + { + "name": "Barra Funda", + "codIbge": "4301958", + "capag": "A", + "tier": "bankable", + "lat": -27.9205, + "lon": -53.0391, + "isHero": false + }, + { + "name": "Barros Cassal", + "codIbge": "4302006", + "capag": "C", + "tier": "constrained", + "lat": -29.0947, + "lon": -52.5836, + "isHero": false + }, + { + "name": "Benjamin Constant do Sul", + "codIbge": "4302055", + "capag": "A", + "tier": "bankable", + "lat": -27.5086, + "lon": -52.5995, + "isHero": false + }, + { + "name": "Bento Gonçalves", + "codIbge": "4302105", + "capag": "C", + "tier": "constrained", + "lat": -29.1662, + "lon": -51.5165, + "isHero": false + }, + { + "name": "Boa Vista das Missões", + "codIbge": "4302154", + "capag": "A", + "tier": "bankable", + "lat": -27.6671, + "lon": -53.3102, + "isHero": false + }, + { + "name": "Boa Vista do Buricá", + "codIbge": "4302204", + "capag": "A", + "tier": "bankable", + "lat": -27.6693, + "lon": -54.1082, + "isHero": false + }, + { + "name": "Boa Vista do Cadeado", + "codIbge": "4302220", + "capag": "A", + "tier": "bankable", + "lat": -28.5791, + "lon": -53.8108, + "isHero": false + }, + { + "name": "Boa Vista do Incra", + "codIbge": "4302238", + "capag": "A", + "tier": "bankable", + "lat": -28.8185, + "lon": -53.391, + "isHero": false + }, + { + "name": "Boa Vista do Sul", + "codIbge": "4302253", + "capag": "A+", + "tier": "bankable", + "lat": -29.3544, + "lon": -51.6687, + "isHero": false + }, + { + "name": "Bom Jesus", + "codIbge": "4302303", + "capag": "B", + "tier": "bankable", + "lat": -28.6697, + "lon": -50.4295, + "isHero": false + }, + { + "name": "Bom Princípio", + "codIbge": "4302352", + "capag": "A+", + "tier": "bankable", + "lat": -29.4856, + "lon": -51.3548, + "isHero": false + }, + { + "name": "Bom Progresso", + "codIbge": "4302378", + "capag": "C", + "tier": "constrained", + "lat": -27.5399, + "lon": -53.8716, + "isHero": false + }, + { + "name": "Bom Retiro do Sul", + "codIbge": "4302402", + "capag": "A", + "tier": "bankable", + "lat": -29.6071, + "lon": -51.9456, + "isHero": false + }, + { + "name": "Boqueirão do Leão", + "codIbge": "4302451", + "capag": "C", + "tier": "constrained", + "lat": -29.3046, + "lon": -52.4284, + "isHero": false + }, + { + "name": "Bossoroca", + "codIbge": "4302501", + "capag": "A", + "tier": "bankable", + "lat": -28.7291, + "lon": -54.9035, + "isHero": false + }, + { + "name": "Bozano", + "codIbge": "4302584", + "capag": "A+", + "tier": "bankable", + "lat": -28.3659, + "lon": -53.772, + "isHero": false + }, + { + "name": "Braga", + "codIbge": "4302600", + "capag": "A", + "tier": "bankable", + "lat": -27.6173, + "lon": -53.7405, + "isHero": false + }, + { + "name": "Brochier", + "codIbge": "4302659", + "capag": "A", + "tier": "bankable", + "lat": -29.5501, + "lon": -51.5945, + "isHero": false + }, + { + "name": "Butiá", + "codIbge": "4302709", + "capag": "C", + "tier": "constrained", + "lat": -30.1179, + "lon": -51.9601, + "isHero": false + }, + { + "name": "Caçapava do Sul", + "codIbge": "4302808", + "capag": "C", + "tier": "constrained", + "lat": -30.5144, + "lon": -53.4827, + "isHero": false + }, + { + "name": "Cacequi", + "codIbge": "4302907", + "capag": "C", + "tier": "constrained", + "lat": -29.8883, + "lon": -54.822, + "isHero": false + }, + { + "name": "Cachoeira do Sul", + "codIbge": "4303004", + "capag": "A+", + "tier": "bankable", + "lat": -30.033, + "lon": -52.8928, + "isHero": false + }, + { + "name": "Cachoeirinha", + "codIbge": "4303103", + "capag": "A", + "tier": "bankable", + "lat": -29.9472, + "lon": -51.1016, + "isHero": false + }, + { + "name": "Cacique Doble", + "codIbge": "4303202", + "capag": "A", + "tier": "bankable", + "lat": -27.767, + "lon": -51.6597, + "isHero": false + }, + { + "name": "Caibaté", + "codIbge": "4303301", + "capag": "C", + "tier": "constrained", + "lat": -28.2905, + "lon": -54.6454, + "isHero": false + }, + { + "name": "Caiçara", + "codIbge": "4303400", + "capag": "B", + "tier": "bankable", + "lat": -27.2791, + "lon": -53.4257, + "isHero": false + }, + { + "name": "Camaquã", + "codIbge": "4303509", + "capag": "A", + "tier": "bankable", + "lat": -30.8489, + "lon": -51.8043, + "isHero": false + }, + { + "name": "Camargo", + "codIbge": "4303558", + "capag": "A", + "tier": "bankable", + "lat": -28.588, + "lon": -52.2003, + "isHero": false + }, + { + "name": "Cambará do Sul", + "codIbge": "4303608", + "capag": "C", + "tier": "constrained", + "lat": -29.0474, + "lon": -50.1465, + "isHero": false + }, + { + "name": "Campestre da Serra", + "codIbge": "4303673", + "capag": "A", + "tier": "bankable", + "lat": -28.7926, + "lon": -51.0941, + "isHero": false + }, + { + "name": "Campina das Missões", + "codIbge": "4303707", + "capag": "A+", + "tier": "bankable", + "lat": -27.9888, + "lon": -54.8416, + "isHero": false + }, + { + "name": "Campinas do Sul", + "codIbge": "4303806", + "capag": "B", + "tier": "bankable", + "lat": -27.7174, + "lon": -52.6248, + "isHero": false + }, + { + "name": "Campo Bom", + "codIbge": "4303905", + "capag": "B", + "tier": "bankable", + "lat": -29.6747, + "lon": -51.0606, + "isHero": false + }, + { + "name": "Campo Novo", + "codIbge": "4304002", + "capag": "A+", + "tier": "bankable", + "lat": -27.6792, + "lon": -53.8052, + "isHero": false + }, + { + "name": "Campos Borges", + "codIbge": "4304101", + "capag": "A", + "tier": "bankable", + "lat": -28.8871, + "lon": -53.0008, + "isHero": false + }, + { + "name": "Candelária", + "codIbge": "4304200", + "capag": "B", + "tier": "bankable", + "lat": -29.6684, + "lon": -52.7895, + "isHero": false + }, + { + "name": "Cândido Godói", + "codIbge": "4304309", + "capag": "A", + "tier": "bankable", + "lat": -27.9515, + "lon": -54.7517, + "isHero": false + }, + { + "name": "Candiota", + "codIbge": "4304358", + "capag": "n.d.", + "tier": "unrated", + "lat": -31.5516, + "lon": -53.6773, + "isHero": false + }, + { + "name": "Canela", + "codIbge": "4304408", + "capag": "C", + "tier": "constrained", + "lat": -29.356, + "lon": -50.8119, + "isHero": false + }, + { + "name": "Canguçu", + "codIbge": "4304507", + "capag": "A+", + "tier": "bankable", + "lat": -31.396, + "lon": -52.6783, + "isHero": false + }, + { + "name": "Canoas", + "codIbge": "4304606", + "capag": "C", + "tier": "constrained", + "lat": -29.9128, + "lon": -51.1857, + "isHero": true + }, + { + "name": "Canudos do Vale", + "codIbge": "4304614", + "capag": "A", + "tier": "bankable", + "lat": -29.3271, + "lon": -52.2374, + "isHero": false + }, + { + "name": "Capão Bonito do Sul", + "codIbge": "4304622", + "capag": "A", + "tier": "bankable", + "lat": -28.1254, + "lon": -51.3961, + "isHero": false + }, + { + "name": "Capão da Canoa", + "codIbge": "4304630", + "capag": "A", + "tier": "bankable", + "lat": -29.7642, + "lon": -50.0282, + "isHero": false + }, + { + "name": "Capão do Cipó", + "codIbge": "4304655", + "capag": "B", + "tier": "bankable", + "lat": -28.9312, + "lon": -54.5558, + "isHero": false + }, + { + "name": "Capão do Leão", + "codIbge": "4304663", + "capag": "C", + "tier": "constrained", + "lat": -31.7565, + "lon": -52.4889, + "isHero": false + }, + { + "name": "Capivari do Sul", + "codIbge": "4304671", + "capag": "A+", + "tier": "bankable", + "lat": -30.1383, + "lon": -50.5152, + "isHero": false + }, + { + "name": "Capela de Santana", + "codIbge": "4304689", + "capag": "C", + "tier": "constrained", + "lat": -29.6961, + "lon": -51.328, + "isHero": false + }, + { + "name": "Capitão", + "codIbge": "4304697", + "capag": "A+", + "tier": "bankable", + "lat": -29.2674, + "lon": -51.9853, + "isHero": false + }, + { + "name": "Carazinho", + "codIbge": "4304705", + "capag": "A", + "tier": "bankable", + "lat": -28.2958, + "lon": -52.7933, + "isHero": false + }, + { + "name": "Caraá", + "codIbge": "4304713", + "capag": "C", + "tier": "constrained", + "lat": -29.7869, + "lon": -50.4316, + "isHero": false + }, + { + "name": "Carlos Barbosa", + "codIbge": "4304804", + "capag": "A", + "tier": "bankable", + "lat": -29.2969, + "lon": -51.5028, + "isHero": false + }, + { + "name": "Carlos Gomes", + "codIbge": "4304853", + "capag": "A", + "tier": "bankable", + "lat": -27.7167, + "lon": -51.9121, + "isHero": false + }, + { + "name": "Casca", + "codIbge": "4304903", + "capag": "A+", + "tier": "bankable", + "lat": -28.5605, + "lon": -51.9815, + "isHero": false + }, + { + "name": "Caseiros", + "codIbge": "4304952", + "capag": "A", + "tier": "bankable", + "lat": -28.2582, + "lon": -51.6861, + "isHero": false + }, + { + "name": "Catuípe", + "codIbge": "4305009", + "capag": "B", + "tier": "bankable", + "lat": -28.2554, + "lon": -54.0132, + "isHero": false + }, + { + "name": "Caxias do Sul", + "codIbge": "4305108", + "capag": "A+", + "tier": "bankable", + "lat": -29.1629, + "lon": -51.1792, + "isHero": false + }, + { + "name": "Centenário", + "codIbge": "4305116", + "capag": "A", + "tier": "bankable", + "lat": -27.7615, + "lon": -51.9984, + "isHero": false + }, + { + "name": "Cerrito", + "codIbge": "4305124", + "capag": "B+", + "tier": "bankable", + "lat": -31.8419, + "lon": -52.8004, + "isHero": false + }, + { + "name": "Cerro Branco", + "codIbge": "4305132", + "capag": "A+", + "tier": "bankable", + "lat": -29.657, + "lon": -52.9406, + "isHero": false + }, + { + "name": "Cerro Grande", + "codIbge": "4305157", + "capag": "B", + "tier": "bankable", + "lat": -27.6106, + "lon": -53.1672, + "isHero": false + }, + { + "name": "Cerro Grande do Sul", + "codIbge": "4305173", + "capag": "C", + "tier": "constrained", + "lat": -30.5905, + "lon": -51.7418, + "isHero": false + }, + { + "name": "Cerro Largo", + "codIbge": "4305207", + "capag": "C", + "tier": "constrained", + "lat": -28.1463, + "lon": -54.7428, + "isHero": false + }, + { + "name": "Chapada", + "codIbge": "4305306", + "capag": "A", + "tier": "bankable", + "lat": -28.0559, + "lon": -53.0665, + "isHero": false + }, + { + "name": "Charqueadas", + "codIbge": "4305355", + "capag": "n.d.", + "tier": "unrated", + "lat": -29.9625, + "lon": -51.6289, + "isHero": false + }, + { + "name": "Charrua", + "codIbge": "4305371", + "capag": "A+", + "tier": "bankable", + "lat": -27.9493, + "lon": -52.015, + "isHero": false + }, + { + "name": "Chiapetta", + "codIbge": "4305405", + "capag": "B", + "tier": "bankable", + "lat": -27.923, + "lon": -53.9419, + "isHero": false + }, + { + "name": "Chuí", + "codIbge": "4305439", + "capag": "C", + "tier": "constrained", + "lat": -33.6866, + "lon": -53.4594, + "isHero": false + }, + { + "name": "Chuvisca", + "codIbge": "4305447", + "capag": "A", + "tier": "bankable", + "lat": -30.7504, + "lon": -51.9737, + "isHero": false + }, + { + "name": "Cidreira", + "codIbge": "4305454", + "capag": "C", + "tier": "constrained", + "lat": -30.1604, + "lon": -50.2337, + "isHero": false + }, + { + "name": "Ciríaco", + "codIbge": "4305504", + "capag": "B", + "tier": "bankable", + "lat": -28.3419, + "lon": -51.8741, + "isHero": false + }, + { + "name": "Colinas", + "codIbge": "4305587", + "capag": "A", + "tier": "bankable", + "lat": -29.3948, + "lon": -51.8556, + "isHero": false + }, + { + "name": "Colorado", + "codIbge": "4305603", + "capag": "B", + "tier": "bankable", + "lat": -28.5258, + "lon": -52.9928, + "isHero": false + }, + { + "name": "Condor", + "codIbge": "4305702", + "capag": "B+", + "tier": "bankable", + "lat": -28.2075, + "lon": -53.4905, + "isHero": false + }, + { + "name": "Constantina", + "codIbge": "4305801", + "capag": "A", + "tier": "bankable", + "lat": -27.732, + "lon": -52.9938, + "isHero": false + }, + { + "name": "Coqueiro Baixo", + "codIbge": "4305835", + "capag": "A", + "tier": "bankable", + "lat": -29.1802, + "lon": -52.0942, + "isHero": false + }, + { + "name": "Coqueiros do Sul", + "codIbge": "4305850", + "capag": "A", + "tier": "bankable", + "lat": -28.1194, + "lon": -52.7842, + "isHero": false + }, + { + "name": "Coronel Barros", + "codIbge": "4305871", + "capag": "A+", + "tier": "bankable", + "lat": -28.3921, + "lon": -54.0686, + "isHero": false + }, + { + "name": "Coronel Bicaco", + "codIbge": "4305900", + "capag": "C", + "tier": "constrained", + "lat": -27.7197, + "lon": -53.7022, + "isHero": false + }, + { + "name": "Coronel Pilar", + "codIbge": "4305934", + "capag": "A", + "tier": "bankable", + "lat": -29.2695, + "lon": -51.6847, + "isHero": false + }, + { + "name": "Cotiporã", + "codIbge": "4305959", + "capag": "A", + "tier": "bankable", + "lat": -28.9891, + "lon": -51.6971, + "isHero": false + }, + { + "name": "Coxilha", + "codIbge": "4305975", + "capag": "A", + "tier": "bankable", + "lat": -28.128, + "lon": -52.3023, + "isHero": false + }, + { + "name": "Crissiumal", + "codIbge": "4306007", + "capag": "A+", + "tier": "bankable", + "lat": -27.4999, + "lon": -54.0994, + "isHero": false + }, + { + "name": "Cristal", + "codIbge": "4306056", + "capag": "B+", + "tier": "bankable", + "lat": -31.0046, + "lon": -52.0436, + "isHero": false + }, + { + "name": "Cristal do Sul", + "codIbge": "4306072", + "capag": "A", + "tier": "bankable", + "lat": -27.452, + "lon": -53.2422, + "isHero": false + }, + { + "name": "Cruz Alta", + "codIbge": "4306106", + "capag": "B+", + "tier": "bankable", + "lat": -28.645, + "lon": -53.6048, + "isHero": false + }, + { + "name": "Cruzaltense", + "codIbge": "4306130", + "capag": "A", + "tier": "bankable", + "lat": -27.6672, + "lon": -52.6522, + "isHero": false + }, + { + "name": "Cruzeiro do Sul", + "codIbge": "4306205", + "capag": "B", + "tier": "bankable", + "lat": -29.5148, + "lon": -51.9928, + "isHero": false + }, + { + "name": "David Canabarro", + "codIbge": "4306304", + "capag": "B+", + "tier": "bankable", + "lat": -28.3849, + "lon": -51.8482, + "isHero": false + }, + { + "name": "Derrubadas", + "codIbge": "4306320", + "capag": "A", + "tier": "bankable", + "lat": -27.2642, + "lon": -53.8645, + "isHero": false + }, + { + "name": "Dezesseis de Novembro", + "codIbge": "4306353", + "capag": "n.e.", + "tier": "unrated", + "lat": -28.219, + "lon": -55.0617, + "isHero": false + }, + { + "name": "Dilermando de Aguiar", + "codIbge": "4306379", + "capag": "A", + "tier": "bankable", + "lat": -29.7054, + "lon": -54.2122, + "isHero": false + }, + { + "name": "Dois Irmãos", + "codIbge": "4306403", + "capag": "A+", + "tier": "bankable", + "lat": -29.5836, + "lon": -51.0898, + "isHero": false + }, + { + "name": "Dois Irmãos das Missões", + "codIbge": "4306429", + "capag": "A", + "tier": "bankable", + "lat": -27.6621, + "lon": -53.5304, + "isHero": false + }, + { + "name": "Dois Lajeados", + "codIbge": "4306452", + "capag": "A", + "tier": "bankable", + "lat": -28.983, + "lon": -51.8396, + "isHero": false + }, + { + "name": "Dom Feliciano", + "codIbge": "4306502", + "capag": "C", + "tier": "constrained", + "lat": -30.7004, + "lon": -52.1026, + "isHero": false + }, + { + "name": "Dom Pedro de Alcântara", + "codIbge": "4306551", + "capag": "A+", + "tier": "bankable", + "lat": -29.3639, + "lon": -49.853, + "isHero": false + }, + { + "name": "Dom Pedrito", + "codIbge": "4306601", + "capag": "A+", + "tier": "bankable", + "lat": -30.9756, + "lon": -54.6694, + "isHero": false + }, + { + "name": "Dona Francisca", + "codIbge": "4306700", + "capag": "A+", + "tier": "bankable", + "lat": -29.6195, + "lon": -53.3617, + "isHero": false + }, + { + "name": "Doutor Maurício Cardoso", + "codIbge": "4306734", + "capag": "A", + "tier": "bankable", + "lat": -27.5103, + "lon": -54.3577, + "isHero": false + }, + { + "name": "Doutor Ricardo", + "codIbge": "4306759", + "capag": "C", + "tier": "constrained", + "lat": -29.084, + "lon": -51.9972, + "isHero": false + }, + { + "name": "Eldorado do Sul", + "codIbge": "4306767", + "capag": "A+", + "tier": "bankable", + "lat": -30.0847, + "lon": -51.6187, + "isHero": false + }, + { + "name": "Encantado", + "codIbge": "4306809", + "capag": "B", + "tier": "bankable", + "lat": -29.2351, + "lon": -51.8703, + "isHero": false + }, + { + "name": "Encruzilhada do Sul", + "codIbge": "4306908", + "capag": "A", + "tier": "bankable", + "lat": -30.543, + "lon": -52.5204, + "isHero": false + }, + { + "name": "Engenho Velho", + "codIbge": "4306924", + "capag": "A", + "tier": "bankable", + "lat": -27.706, + "lon": -52.9145, + "isHero": false + }, + { + "name": "Entre-Ijuís", + "codIbge": "4306932", + "capag": "B+", + "tier": "bankable", + "lat": -28.3686, + "lon": -54.2686, + "isHero": false + }, + { + "name": "Entre Rios do Sul", + "codIbge": "4306957", + "capag": "C", + "tier": "constrained", + "lat": -27.5298, + "lon": -52.7347, + "isHero": false + }, + { + "name": "Erebango", + "codIbge": "4306973", + "capag": "n.e.", + "tier": "unrated", + "lat": -27.8544, + "lon": -52.3005, + "isHero": false + }, + { + "name": "Erechim", + "codIbge": "4307005", + "capag": "A+", + "tier": "bankable", + "lat": -27.6364, + "lon": -52.2697, + "isHero": false + }, + { + "name": "Ernestina", + "codIbge": "4307054", + "capag": "A", + "tier": "bankable", + "lat": -28.4977, + "lon": -52.5836, + "isHero": false + }, + { + "name": "Herval", + "codIbge": "4307104", + "capag": "A", + "tier": "bankable", + "lat": -32.024, + "lon": -53.3944, + "isHero": false + }, + { + "name": "Erval Grande", + "codIbge": "4307203", + "capag": "C", + "tier": "constrained", + "lat": -27.3926, + "lon": -52.574, + "isHero": false + }, + { + "name": "Erval Seco", + "codIbge": "4307302", + "capag": "C", + "tier": "constrained", + "lat": -27.5443, + "lon": -53.5005, + "isHero": false + }, + { + "name": "Esmeralda", + "codIbge": "4307401", + "capag": "B", + "tier": "bankable", + "lat": -28.0518, + "lon": -51.1933, + "isHero": false + }, + { + "name": "Esperança do Sul", + "codIbge": "4307450", + "capag": "n.d.", + "tier": "unrated", + "lat": -27.3603, + "lon": -53.9891, + "isHero": false + }, + { + "name": "Espumoso", + "codIbge": "4307500", + "capag": "B", + "tier": "bankable", + "lat": -28.7286, + "lon": -52.8461, + "isHero": false + }, + { + "name": "Estação", + "codIbge": "4307559", + "capag": "B", + "tier": "bankable", + "lat": -27.9135, + "lon": -52.2635, + "isHero": false + }, + { + "name": "Estância Velha", + "codIbge": "4307609", + "capag": "B", + "tier": "bankable", + "lat": -29.6535, + "lon": -51.1843, + "isHero": false + }, + { + "name": "Esteio", + "codIbge": "4307708", + "capag": "C", + "tier": "constrained", + "lat": -29.852, + "lon": -51.1841, + "isHero": false + }, + { + "name": "Estrela", + "codIbge": "4307807", + "capag": "A", + "tier": "bankable", + "lat": -29.5002, + "lon": -51.9495, + "isHero": false + }, + { + "name": "Estrela Velha", + "codIbge": "4307815", + "capag": "A", + "tier": "bankable", + "lat": -29.1713, + "lon": -53.1639, + "isHero": false + }, + { + "name": "Eugênio de Castro", + "codIbge": "4307831", + "capag": "A+", + "tier": "bankable", + "lat": -28.5315, + "lon": -54.1506, + "isHero": false + }, + { + "name": "Fagundes Varela", + "codIbge": "4307864", + "capag": "A+", + "tier": "bankable", + "lat": -28.8794, + "lon": -51.7014, + "isHero": false + }, + { + "name": "Farroupilha", + "codIbge": "4307906", + "capag": "A", + "tier": "bankable", + "lat": -29.2227, + "lon": -51.3419, + "isHero": false + }, + { + "name": "Faxinal do Soturno", + "codIbge": "4308003", + "capag": "A+", + "tier": "bankable", + "lat": -29.5788, + "lon": -53.4484, + "isHero": false + }, + { + "name": "Faxinalzinho", + "codIbge": "4308052", + "capag": "C", + "tier": "constrained", + "lat": -27.4238, + "lon": -52.6789, + "isHero": false + }, + { + "name": "Fazenda Vilanova", + "codIbge": "4308078", + "capag": "A", + "tier": "bankable", + "lat": -29.5885, + "lon": -51.8217, + "isHero": false + }, + { + "name": "Feliz", + "codIbge": "4308102", + "capag": "A+", + "tier": "bankable", + "lat": -29.4527, + "lon": -51.3032, + "isHero": false + }, + { + "name": "Flores da Cunha", + "codIbge": "4308201", + "capag": "A", + "tier": "bankable", + "lat": -29.0261, + "lon": -51.1875, + "isHero": false + }, + { + "name": "Floriano Peixoto", + "codIbge": "4308250", + "capag": "A", + "tier": "bankable", + "lat": -27.8614, + "lon": -52.0838, + "isHero": false + }, + { + "name": "Fontoura Xavier", + "codIbge": "4308300", + "capag": "B", + "tier": "bankable", + "lat": -28.9817, + "lon": -52.3445, + "isHero": false + }, + { + "name": "Formigueiro", + "codIbge": "4308409", + "capag": "A", + "tier": "bankable", + "lat": -30.0035, + "lon": -53.4959, + "isHero": false + }, + { + "name": "Forquetinha", + "codIbge": "4308433", + "capag": "A", + "tier": "bankable", + "lat": -29.3828, + "lon": -52.0981, + "isHero": false + }, + { + "name": "Fortaleza dos Valos", + "codIbge": "4308458", + "capag": "A+", + "tier": "bankable", + "lat": -28.7986, + "lon": -53.2249, + "isHero": false + }, + { + "name": "Frederico Westphalen", + "codIbge": "4308508", + "capag": "B", + "tier": "bankable", + "lat": -27.3586, + "lon": -53.3958, + "isHero": false + }, + { + "name": "Garibaldi", + "codIbge": "4308607", + "capag": "A", + "tier": "bankable", + "lat": -29.259, + "lon": -51.5352, + "isHero": false + }, + { + "name": "Garruchos", + "codIbge": "4308656", + "capag": "A+", + "tier": "bankable", + "lat": -28.1944, + "lon": -55.6383, + "isHero": false + }, + { + "name": "Gaurama", + "codIbge": "4308706", + "capag": "A", + "tier": "bankable", + "lat": -27.5856, + "lon": -52.0915, + "isHero": false + }, + { + "name": "General Câmara", + "codIbge": "4308805", + "capag": "C", + "tier": "constrained", + "lat": -29.9032, + "lon": -51.7612, + "isHero": false + }, + { + "name": "Gentil", + "codIbge": "4308854", + "capag": "B", + "tier": "bankable", + "lat": -28.4316, + "lon": -52.0337, + "isHero": false + }, + { + "name": "Getúlio Vargas", + "codIbge": "4308904", + "capag": "A", + "tier": "bankable", + "lat": -27.8911, + "lon": -52.2294, + "isHero": false + }, + { + "name": "Giruá", + "codIbge": "4309001", + "capag": "A", + "tier": "bankable", + "lat": -28.0297, + "lon": -54.3517, + "isHero": false + }, + { + "name": "Glorinha", + "codIbge": "4309050", + "capag": "C", + "tier": "constrained", + "lat": -29.8798, + "lon": -50.7734, + "isHero": false + }, + { + "name": "Gramado", + "codIbge": "4309100", + "capag": "B", + "tier": "bankable", + "lat": -29.3734, + "lon": -50.8762, + "isHero": false + }, + { + "name": "Gramado dos Loureiros", + "codIbge": "4309126", + "capag": "B", + "tier": "bankable", + "lat": -27.4429, + "lon": -52.9149, + "isHero": false + }, + { + "name": "Gramado Xavier", + "codIbge": "4309159", + "capag": "B+", + "tier": "bankable", + "lat": -29.2706, + "lon": -52.5795, + "isHero": false + }, + { + "name": "Gravataí", + "codIbge": "4309209", + "capag": "C", + "tier": "constrained", + "lat": -29.9413, + "lon": -50.9869, + "isHero": false + }, + { + "name": "Guabiju", + "codIbge": "4309258", + "capag": "A", + "tier": "bankable", + "lat": -28.5421, + "lon": -51.6948, + "isHero": false + }, + { + "name": "Guaíba", + "codIbge": "4309308", + "capag": "A", + "tier": "bankable", + "lat": -30.1086, + "lon": -51.3233, + "isHero": false + }, + { + "name": "Guaporé", + "codIbge": "4309407", + "capag": "A", + "tier": "bankable", + "lat": -28.8399, + "lon": -51.8895, + "isHero": false + }, + { + "name": "Guarani das Missões", + "codIbge": "4309506", + "capag": "B", + "tier": "bankable", + "lat": -28.1491, + "lon": -54.5629, + "isHero": false + }, + { + "name": "Harmonia", + "codIbge": "4309555", + "capag": "A", + "tier": "bankable", + "lat": -29.5456, + "lon": -51.4185, + "isHero": false + }, + { + "name": "Herveiras", + "codIbge": "4309571", + "capag": "A", + "tier": "bankable", + "lat": -29.4552, + "lon": -52.6553, + "isHero": false + }, + { + "name": "Horizontina", + "codIbge": "4309605", + "capag": "A", + "tier": "bankable", + "lat": -27.6282, + "lon": -54.3053, + "isHero": false + }, + { + "name": "Hulha Negra", + "codIbge": "4309654", + "capag": "A", + "tier": "bankable", + "lat": -31.4067, + "lon": -53.8667, + "isHero": false + }, + { + "name": "Humaitá", + "codIbge": "4309704", + "capag": "B", + "tier": "bankable", + "lat": -27.5691, + "lon": -53.9695, + "isHero": false + }, + { + "name": "Ibarama", + "codIbge": "4309753", + "capag": "A", + "tier": "bankable", + "lat": -29.4203, + "lon": -53.1295, + "isHero": false + }, + { + "name": "Ibiaçá", + "codIbge": "4309803", + "capag": "C", + "tier": "constrained", + "lat": -28.0566, + "lon": -51.8599, + "isHero": false + }, + { + "name": "Ibiraiaras", + "codIbge": "4309902", + "capag": "A+", + "tier": "bankable", + "lat": -28.3741, + "lon": -51.6377, + "isHero": false + }, + { + "name": "Ibirapuitã", + "codIbge": "4309951", + "capag": "B", + "tier": "bankable", + "lat": -28.6247, + "lon": -52.5158, + "isHero": false + }, + { + "name": "Ibirubá", + "codIbge": "4310009", + "capag": "B+", + "tier": "bankable", + "lat": -28.6302, + "lon": -53.0961, + "isHero": false + }, + { + "name": "Igrejinha", + "codIbge": "4310108", + "capag": "B", + "tier": "bankable", + "lat": -29.5693, + "lon": -50.7919, + "isHero": false + }, + { + "name": "Ijuí", + "codIbge": "4310207", + "capag": "B+", + "tier": "bankable", + "lat": -28.388, + "lon": -53.92, + "isHero": false + }, + { + "name": "Ilópolis", + "codIbge": "4310306", + "capag": "A", + "tier": "bankable", + "lat": -28.9282, + "lon": -52.1258, + "isHero": false + }, + { + "name": "Imbé", + "codIbge": "4310330", + "capag": "B+", + "tier": "bankable", + "lat": -29.9753, + "lon": -50.1281, + "isHero": false + }, + { + "name": "Imigrante", + "codIbge": "4310363", + "capag": "A+", + "tier": "bankable", + "lat": -29.3508, + "lon": -51.7748, + "isHero": false + }, + { + "name": "Independência", + "codIbge": "4310405", + "capag": "A+", + "tier": "bankable", + "lat": -27.8354, + "lon": -54.1886, + "isHero": false + }, + { + "name": "Inhacorá", + "codIbge": "4310413", + "capag": "B", + "tier": "bankable", + "lat": -27.8752, + "lon": -54.015, + "isHero": false + }, + { + "name": "Ipê", + "codIbge": "4310439", + "capag": "A+", + "tier": "bankable", + "lat": -28.8171, + "lon": -51.2859, + "isHero": false + }, + { + "name": "Ipiranga do Sul", + "codIbge": "4310462", + "capag": "A", + "tier": "bankable", + "lat": -27.9404, + "lon": -52.4271, + "isHero": false + }, + { + "name": "Iraí", + "codIbge": "4310504", + "capag": "A+", + "tier": "bankable", + "lat": -27.1951, + "lon": -53.2543, + "isHero": false + }, + { + "name": "Itaara", + "codIbge": "4310538", + "capag": "A+", + "tier": "bankable", + "lat": -29.6013, + "lon": -53.7725, + "isHero": false + }, + { + "name": "Itacurubi", + "codIbge": "4310553", + "capag": "A", + "tier": "bankable", + "lat": -28.7913, + "lon": -55.2447, + "isHero": false + }, + { + "name": "Itapuca", + "codIbge": "4310579", + "capag": "A+", + "tier": "bankable", + "lat": -28.7768, + "lon": -52.1693, + "isHero": false + }, + { + "name": "Itaqui", + "codIbge": "4310603", + "capag": "A", + "tier": "bankable", + "lat": -29.1311, + "lon": -56.5515, + "isHero": false + }, + { + "name": "Itati", + "codIbge": "4310652", + "capag": "B", + "tier": "bankable", + "lat": -29.4974, + "lon": -50.1016, + "isHero": false + }, + { + "name": "Itatiba do Sul", + "codIbge": "4310702", + "capag": "A", + "tier": "bankable", + "lat": -27.3846, + "lon": -52.4538, + "isHero": false + }, + { + "name": "Ivorá", + "codIbge": "4310751", + "capag": "n.d.", + "tier": "unrated", + "lat": -29.5232, + "lon": -53.5842, + "isHero": false + }, + { + "name": "Ivoti", + "codIbge": "4310801", + "capag": "A", + "tier": "bankable", + "lat": -29.5995, + "lon": -51.1533, + "isHero": false + }, + { + "name": "Jaboticaba", + "codIbge": "4310850", + "capag": "A", + "tier": "bankable", + "lat": -27.6347, + "lon": -53.2762, + "isHero": false + }, + { + "name": "Jacuizinho", + "codIbge": "4310876", + "capag": "A+", + "tier": "bankable", + "lat": -29.0401, + "lon": -53.0657, + "isHero": false + }, + { + "name": "Jacutinga", + "codIbge": "4310900", + "capag": "B", + "tier": "bankable", + "lat": -27.7291, + "lon": -52.5372, + "isHero": false + }, + { + "name": "Jaguarão", + "codIbge": "4311007", + "capag": "B+", + "tier": "bankable", + "lat": -32.5604, + "lon": -53.377, + "isHero": false + }, + { + "name": "Jaguari", + "codIbge": "4311106", + "capag": "C", + "tier": "constrained", + "lat": -29.4936, + "lon": -54.703, + "isHero": false + }, + { + "name": "Jaquirana", + "codIbge": "4311122", + "capag": "A", + "tier": "bankable", + "lat": -28.8811, + "lon": -50.3637, + "isHero": false + }, + { + "name": "Jari", + "codIbge": "4311130", + "capag": "A", + "tier": "bankable", + "lat": -29.2922, + "lon": -54.2237, + "isHero": false + }, + { + "name": "Jóia", + "codIbge": "4311155", + "capag": "A+", + "tier": "bankable", + "lat": -28.6435, + "lon": -54.1141, + "isHero": false + }, + { + "name": "Júlio de Castilhos", + "codIbge": "4311205", + "capag": "C", + "tier": "constrained", + "lat": -29.2299, + "lon": -53.6772, + "isHero": false + }, + { + "name": "Lagoa Bonita do Sul", + "codIbge": "4311239", + "capag": "A", + "tier": "bankable", + "lat": -29.4939, + "lon": -53.017, + "isHero": false + }, + { + "name": "Lagoão", + "codIbge": "4311254", + "capag": "C", + "tier": "constrained", + "lat": -29.2348, + "lon": -52.7997, + "isHero": false + }, + { + "name": "Lagoa dos Três Cantos", + "codIbge": "4311270", + "capag": "A+", + "tier": "bankable", + "lat": -28.5676, + "lon": -52.8618, + "isHero": false + }, + { + "name": "Lagoa Vermelha", + "codIbge": "4311304", + "capag": "A", + "tier": "bankable", + "lat": -28.2093, + "lon": -51.5248, + "isHero": false + }, + { + "name": "Lajeado", + "codIbge": "4311403", + "capag": "A+", + "tier": "bankable", + "lat": -29.4591, + "lon": -51.9644, + "isHero": false + }, + { + "name": "Lajeado do Bugre", + "codIbge": "4311429", + "capag": "B", + "tier": "bankable", + "lat": -27.6913, + "lon": -53.1818, + "isHero": false + }, + { + "name": "Lavras do Sul", + "codIbge": "4311502", + "capag": "A", + "tier": "bankable", + "lat": -30.8071, + "lon": -53.8931, + "isHero": false + }, + { + "name": "Liberato Salzano", + "codIbge": "4311601", + "capag": "B", + "tier": "bankable", + "lat": -27.601, + "lon": -53.0753, + "isHero": false + }, + { + "name": "Lindolfo Collor", + "codIbge": "4311627", + "capag": "A", + "tier": "bankable", + "lat": -29.5859, + "lon": -51.2141, + "isHero": false + }, + { + "name": "Linha Nova", + "codIbge": "4311643", + "capag": "A", + "tier": "bankable", + "lat": -29.4679, + "lon": -51.2003, + "isHero": false + }, + { + "name": "Machadinho", + "codIbge": "4311700", + "capag": "B", + "tier": "bankable", + "lat": -27.5667, + "lon": -51.6668, + "isHero": false + }, + { + "name": "Maçambará", + "codIbge": "4311718", + "capag": "A", + "tier": "bankable", + "lat": -29.1445, + "lon": -56.0674, + "isHero": false + }, + { + "name": "Mampituba", + "codIbge": "4311734", + "capag": "A", + "tier": "bankable", + "lat": -29.2136, + "lon": -49.9311, + "isHero": false + }, + { + "name": "Manoel Viana", + "codIbge": "4311759", + "capag": "A", + "tier": "bankable", + "lat": -29.5859, + "lon": -55.4841, + "isHero": false + }, + { + "name": "Maquiné", + "codIbge": "4311775", + "capag": "B", + "tier": "bankable", + "lat": -29.6798, + "lon": -50.2079, + "isHero": false + }, + { + "name": "Maratá", + "codIbge": "4311791", + "capag": "A+", + "tier": "bankable", + "lat": -29.5457, + "lon": -51.5573, + "isHero": false + }, + { + "name": "Marau", + "codIbge": "4311809", + "capag": "A+", + "tier": "bankable", + "lat": -28.4498, + "lon": -52.1986, + "isHero": false + }, + { + "name": "Marcelino Ramos", + "codIbge": "4311908", + "capag": "A", + "tier": "bankable", + "lat": -27.4676, + "lon": -51.9095, + "isHero": false + }, + { + "name": "Mariana Pimentel", + "codIbge": "4311981", + "capag": "B", + "tier": "bankable", + "lat": -30.353, + "lon": -51.5803, + "isHero": false + }, + { + "name": "Mariano Moro", + "codIbge": "4312005", + "capag": "A+", + "tier": "bankable", + "lat": -27.3568, + "lon": -52.1467, + "isHero": false + }, + { + "name": "Marques de Souza", + "codIbge": "4312054", + "capag": "A+", + "tier": "bankable", + "lat": -29.3311, + "lon": -52.0973, + "isHero": false + }, + { + "name": "Mata", + "codIbge": "4312104", + "capag": "B", + "tier": "bankable", + "lat": -29.5649, + "lon": -54.4641, + "isHero": false + }, + { + "name": "Mato Castelhano", + "codIbge": "4312138", + "capag": "C", + "tier": "constrained", + "lat": -28.28, + "lon": -52.1932, + "isHero": false + }, + { + "name": "Mato Leitão", + "codIbge": "4312153", + "capag": "A", + "tier": "bankable", + "lat": -29.5285, + "lon": -52.1278, + "isHero": false + }, + { + "name": "Mato Queimado", + "codIbge": "4312179", + "capag": "A", + "tier": "bankable", + "lat": -28.252, + "lon": -54.6159, + "isHero": false + }, + { + "name": "Maximiliano de Almeida", + "codIbge": "4312203", + "capag": "n.d.", + "tier": "unrated", + "lat": -27.6325, + "lon": -51.802, + "isHero": false + }, + { + "name": "Minas do Leão", + "codIbge": "4312252", + "capag": "A", + "tier": "bankable", + "lat": -30.1346, + "lon": -52.0423, + "isHero": false + }, + { + "name": "Miraguaí", + "codIbge": "4312302", + "capag": "C", + "tier": "constrained", + "lat": -27.497, + "lon": -53.6891, + "isHero": false + }, + { + "name": "Montauri", + "codIbge": "4312351", + "capag": "A+", + "tier": "bankable", + "lat": -28.6462, + "lon": -52.0767, + "isHero": false + }, + { + "name": "Monte Alegre dos Campos", + "codIbge": "4312377", + "capag": "A", + "tier": "bankable", + "lat": -28.6805, + "lon": -50.7834, + "isHero": false + }, + { + "name": "Monte Belo do Sul", + "codIbge": "4312385", + "capag": "B", + "tier": "bankable", + "lat": -29.1607, + "lon": -51.6333, + "isHero": false + }, + { + "name": "Montenegro", + "codIbge": "4312401", + "capag": "A", + "tier": "bankable", + "lat": -29.6824, + "lon": -51.4679, + "isHero": false + }, + { + "name": "Mormaço", + "codIbge": "4312427", + "capag": "A", + "tier": "bankable", + "lat": -28.6968, + "lon": -52.6999, + "isHero": false + }, + { + "name": "Morrinhos do Sul", + "codIbge": "4312443", + "capag": "C", + "tier": "constrained", + "lat": -29.3578, + "lon": -49.9328, + "isHero": false + }, + { + "name": "Morro Redondo", + "codIbge": "4312450", + "capag": "A", + "tier": "bankable", + "lat": -31.5887, + "lon": -52.6261, + "isHero": false + }, + { + "name": "Morro Reuter", + "codIbge": "4312476", + "capag": "A+", + "tier": "bankable", + "lat": -29.5379, + "lon": -51.0811, + "isHero": false + }, + { + "name": "Mostardas", + "codIbge": "4312500", + "capag": "B+", + "tier": "bankable", + "lat": -31.1054, + "lon": -50.9167, + "isHero": false + }, + { + "name": "Muçum", + "codIbge": "4312609", + "capag": "n.d.", + "tier": "unrated", + "lat": -29.163, + "lon": -51.8714, + "isHero": false + }, + { + "name": "Muitos Capões", + "codIbge": "4312617", + "capag": "n.d.", + "tier": "unrated", + "lat": -28.3132, + "lon": -51.1836, + "isHero": false + }, + { + "name": "Muliterno", + "codIbge": "4312625", + "capag": "A", + "tier": "bankable", + "lat": -28.3253, + "lon": -51.7697, + "isHero": false + }, + { + "name": "Não-Me-Toque", + "codIbge": "4312658", + "capag": "A", + "tier": "bankable", + "lat": -28.4548, + "lon": -52.8182, + "isHero": false + }, + { + "name": "Nicolau Vergueiro", + "codIbge": "4312674", + "capag": "A", + "tier": "bankable", + "lat": -28.5298, + "lon": -52.4676, + "isHero": false + }, + { + "name": "Nonoai", + "codIbge": "4312708", + "capag": "B", + "tier": "bankable", + "lat": -27.3689, + "lon": -52.7756, + "isHero": false + }, + { + "name": "Nova Alvorada", + "codIbge": "4312757", + "capag": "A+", + "tier": "bankable", + "lat": -28.6822, + "lon": -52.1631, + "isHero": false + }, + { + "name": "Nova Araçá", + "codIbge": "4312807", + "capag": "A", + "tier": "bankable", + "lat": -28.6537, + "lon": -51.7458, + "isHero": false + }, + { + "name": "Nova Bassano", + "codIbge": "4312906", + "capag": "A", + "tier": "bankable", + "lat": -28.7291, + "lon": -51.7072, + "isHero": false + }, + { + "name": "Nova Boa Vista", + "codIbge": "4312955", + "capag": "A+", + "tier": "bankable", + "lat": -27.9926, + "lon": -52.9784, + "isHero": false + }, + { + "name": "Nova Bréscia", + "codIbge": "4313003", + "capag": "A", + "tier": "bankable", + "lat": -29.2182, + "lon": -52.0319, + "isHero": false + }, + { + "name": "Nova Candelária", + "codIbge": "4313011", + "capag": "A+", + "tier": "bankable", + "lat": -27.6137, + "lon": -54.1074, + "isHero": false + }, + { + "name": "Nova Esperança do Sul", + "codIbge": "4313037", + "capag": "A", + "tier": "bankable", + "lat": -29.4066, + "lon": -54.8293, + "isHero": false + }, + { + "name": "Nova Hartz", + "codIbge": "4313060", + "capag": "A", + "tier": "bankable", + "lat": -29.5808, + "lon": -50.9051, + "isHero": false + }, + { + "name": "Nova Pádua", + "codIbge": "4313086", + "capag": "A", + "tier": "bankable", + "lat": -29.0275, + "lon": -51.3098, + "isHero": false + }, + { + "name": "Nova Palma", + "codIbge": "4313102", + "capag": "A+", + "tier": "bankable", + "lat": -29.471, + "lon": -53.4689, + "isHero": false + }, + { + "name": "Nova Petrópolis", + "codIbge": "4313201", + "capag": "A", + "tier": "bankable", + "lat": -29.3741, + "lon": -51.1136, + "isHero": false + }, + { + "name": "Nova Prata", + "codIbge": "4313300", + "capag": "C", + "tier": "constrained", + "lat": -28.7799, + "lon": -51.6113, + "isHero": false + }, + { + "name": "Nova Ramada", + "codIbge": "4313334", + "capag": "A+", + "tier": "bankable", + "lat": -28.0667, + "lon": -53.6992, + "isHero": false + }, + { + "name": "Nova Roma do Sul", + "codIbge": "4313359", + "capag": "A", + "tier": "bankable", + "lat": -28.9882, + "lon": -51.4095, + "isHero": false + }, + { + "name": "Nova Santa Rita", + "codIbge": "4313375", + "capag": "A", + "tier": "bankable", + "lat": -29.8525, + "lon": -51.2837, + "isHero": false + }, + { + "name": "Novo Cabrais", + "codIbge": "4313391", + "capag": "A+", + "tier": "bankable", + "lat": -29.7338, + "lon": -52.9489, + "isHero": false + }, + { + "name": "Novo Hamburgo", + "codIbge": "4313409", + "capag": "B", + "tier": "bankable", + "lat": -29.6875, + "lon": -51.1328, + "isHero": false + }, + { + "name": "Novo Machado", + "codIbge": "4313425", + "capag": "n.d.", + "tier": "unrated", + "lat": -27.5765, + "lon": -54.5036, + "isHero": false + }, + { + "name": "Novo Tiradentes", + "codIbge": "4313441", + "capag": "B", + "tier": "bankable", + "lat": -27.5649, + "lon": -53.1837, + "isHero": false + }, + { + "name": "Novo Xingu", + "codIbge": "4313466", + "capag": "A", + "tier": "bankable", + "lat": -27.749, + "lon": -53.0639, + "isHero": false + }, + { + "name": "Novo Barreiro", + "codIbge": "4313490", + "capag": "A", + "tier": "bankable", + "lat": -27.9077, + "lon": -53.1103, + "isHero": false + }, + { + "name": "Osório", + "codIbge": "4313508", + "capag": "B", + "tier": "bankable", + "lat": -29.8881, + "lon": -50.2667, + "isHero": false + }, + { + "name": "Paim Filho", + "codIbge": "4313607", + "capag": "B", + "tier": "bankable", + "lat": -27.7075, + "lon": -51.763, + "isHero": false + }, + { + "name": "Palmares do Sul", + "codIbge": "4313656", + "capag": "A+", + "tier": "bankable", + "lat": -30.2535, + "lon": -50.5103, + "isHero": false + }, + { + "name": "Palmeira das Missões", + "codIbge": "4313706", + "capag": "A", + "tier": "bankable", + "lat": -27.9007, + "lon": -53.3134, + "isHero": false + }, + { + "name": "Palmitinho", + "codIbge": "4313805", + "capag": "B", + "tier": "bankable", + "lat": -27.3596, + "lon": -53.558, + "isHero": false + }, + { + "name": "Panambi", + "codIbge": "4313904", + "capag": "A", + "tier": "bankable", + "lat": -28.2833, + "lon": -53.5023, + "isHero": false + }, + { + "name": "Pantano Grande", + "codIbge": "4313953", + "capag": "C", + "tier": "constrained", + "lat": -30.1902, + "lon": -52.3729, + "isHero": false + }, + { + "name": "Paraí", + "codIbge": "4314001", + "capag": "A", + "tier": "bankable", + "lat": -28.5964, + "lon": -51.7896, + "isHero": false + }, + { + "name": "Paraíso do Sul", + "codIbge": "4314027", + "capag": "A+", + "tier": "bankable", + "lat": -29.6717, + "lon": -53.144, + "isHero": false + }, + { + "name": "Pareci Novo", + "codIbge": "4314035", + "capag": "C", + "tier": "constrained", + "lat": -29.6365, + "lon": -51.3974, + "isHero": false + }, + { + "name": "Parobé", + "codIbge": "4314050", + "capag": "B", + "tier": "bankable", + "lat": -29.6243, + "lon": -50.8312, + "isHero": false + }, + { + "name": "Passa Sete", + "codIbge": "4314068", + "capag": "A", + "tier": "bankable", + "lat": -29.4577, + "lon": -52.9599, + "isHero": false + }, + { + "name": "Passo do Sobrado", + "codIbge": "4314076", + "capag": "B", + "tier": "bankable", + "lat": -29.748, + "lon": -52.2748, + "isHero": false + }, + { + "name": "Passo Fundo", + "codIbge": "4314100", + "capag": "A", + "tier": "bankable", + "lat": -28.2576, + "lon": -52.4091, + "isHero": false + }, + { + "name": "Paulo Bento", + "codIbge": "4314134", + "capag": "B", + "tier": "bankable", + "lat": -27.7051, + "lon": -52.4169, + "isHero": false + }, + { + "name": "Paverama", + "codIbge": "4314159", + "capag": "B", + "tier": "bankable", + "lat": -29.5486, + "lon": -51.7339, + "isHero": false + }, + { + "name": "Pedras Altas", + "codIbge": "4314175", + "capag": "A+", + "tier": "bankable", + "lat": -31.7365, + "lon": -53.5814, + "isHero": false + }, + { + "name": "Pedro Osório", + "codIbge": "4314209", + "capag": "n.d.", + "tier": "unrated", + "lat": -31.8642, + "lon": -52.8184, + "isHero": false + }, + { + "name": "Pejuçara", + "codIbge": "4314308", + "capag": "B+", + "tier": "bankable", + "lat": -28.4283, + "lon": -53.6579, + "isHero": false + }, + { + "name": "Pelotas", + "codIbge": "4314407", + "capag": "C", + "tier": "constrained", + "lat": -31.7649, + "lon": -52.3371, + "isHero": false + }, + { + "name": "Picada Café", + "codIbge": "4314423", + "capag": "A+", + "tier": "bankable", + "lat": -29.4464, + "lon": -51.1367, + "isHero": false + }, + { + "name": "Pinhal", + "codIbge": "4314456", + "capag": "A+", + "tier": "bankable", + "lat": -27.508, + "lon": -53.2082, + "isHero": false + }, + { + "name": "Pinhal da Serra", + "codIbge": "4314464", + "capag": "n.d.", + "tier": "unrated", + "lat": -27.8751, + "lon": -51.1673, + "isHero": false + }, + { + "name": "Pinhal Grande", + "codIbge": "4314472", + "capag": "B", + "tier": "bankable", + "lat": -29.345, + "lon": -53.3206, + "isHero": false + }, + { + "name": "Pinheirinho do Vale", + "codIbge": "4314498", + "capag": "C", + "tier": "constrained", + "lat": -27.2109, + "lon": -53.608, + "isHero": false + }, + { + "name": "Pinheiro Machado", + "codIbge": "4314506", + "capag": "A", + "tier": "bankable", + "lat": -31.5794, + "lon": -53.3798, + "isHero": false + }, + { + "name": "Pinto Bandeira", + "codIbge": "4314548", + "capag": "C", + "tier": "constrained", + "lat": -29.0975, + "lon": -51.4503, + "isHero": false + }, + { + "name": "Pirapó", + "codIbge": "4314555", + "capag": "A", + "tier": "bankable", + "lat": -28.0439, + "lon": -55.2001, + "isHero": false + }, + { + "name": "Piratini", + "codIbge": "4314605", + "capag": "B", + "tier": "bankable", + "lat": -31.4473, + "lon": -53.0973, + "isHero": false + }, + { + "name": "Planalto", + "codIbge": "4314704", + "capag": "B", + "tier": "bankable", + "lat": -27.3297, + "lon": -53.0575, + "isHero": false + }, + { + "name": "Poço das Antas", + "codIbge": "4314753", + "capag": "A+", + "tier": "bankable", + "lat": -29.4481, + "lon": -51.6719, + "isHero": false + }, + { + "name": "Pontão", + "codIbge": "4314779", + "capag": "B", + "tier": "bankable", + "lat": -28.0585, + "lon": -52.6791, + "isHero": false + }, + { + "name": "Ponte Preta", + "codIbge": "4314787", + "capag": "A", + "tier": "bankable", + "lat": -27.6587, + "lon": -52.4848, + "isHero": false + }, + { + "name": "Portão", + "codIbge": "4314803", + "capag": "A", + "tier": "bankable", + "lat": -29.7015, + "lon": -51.2429, + "isHero": false + }, + { + "name": "Porto Alegre", + "codIbge": "4314902", + "capag": "A+", + "tier": "bankable", + "lat": -30.0318, + "lon": -51.2065, + "isHero": false + }, + { + "name": "Porto Lucena", + "codIbge": "4315008", + "capag": "B", + "tier": "bankable", + "lat": -27.8569, + "lon": -55.01, + "isHero": false + }, + { + "name": "Porto Mauá", + "codIbge": "4315057", + "capag": "A", + "tier": "bankable", + "lat": -27.5796, + "lon": -54.6657, + "isHero": false + }, + { + "name": "Porto Vera Cruz", + "codIbge": "4315073", + "capag": "A", + "tier": "bankable", + "lat": -27.7405, + "lon": -54.8994, + "isHero": false + }, + { + "name": "Porto Xavier", + "codIbge": "4315107", + "capag": "B", + "tier": "bankable", + "lat": -27.9082, + "lon": -55.1379, + "isHero": false + }, + { + "name": "Pouso Novo", + "codIbge": "4315131", + "capag": "B+", + "tier": "bankable", + "lat": -29.1738, + "lon": -52.2136, + "isHero": false + }, + { + "name": "Presidente Lucena", + "codIbge": "4315149", + "capag": "A+", + "tier": "bankable", + "lat": -29.5175, + "lon": -51.1798, + "isHero": false + }, + { + "name": "Progresso", + "codIbge": "4315156", + "capag": "C", + "tier": "constrained", + "lat": -29.2441, + "lon": -52.3197, + "isHero": false + }, + { + "name": "Protásio Alves", + "codIbge": "4315172", + "capag": "A", + "tier": "bankable", + "lat": -28.7572, + "lon": -51.4757, + "isHero": false + }, + { + "name": "Putinga", + "codIbge": "4315206", + "capag": "A+", + "tier": "bankable", + "lat": -29.0045, + "lon": -52.1569, + "isHero": false + }, + { + "name": "Quaraí", + "codIbge": "4315305", + "capag": "C", + "tier": "constrained", + "lat": -30.384, + "lon": -56.4483, + "isHero": false + }, + { + "name": "Quatro Irmãos", + "codIbge": "4315313", + "capag": "A+", + "tier": "bankable", + "lat": -27.8257, + "lon": -52.4424, + "isHero": false + }, + { + "name": "Quevedos", + "codIbge": "4315321", + "capag": "n.d.", + "tier": "unrated", + "lat": -29.3504, + "lon": -54.0789, + "isHero": false + }, + { + "name": "Quinze de Novembro", + "codIbge": "4315354", + "capag": "B+", + "tier": "bankable", + "lat": -28.7466, + "lon": -53.1011, + "isHero": false + }, + { + "name": "Redentora", + "codIbge": "4315404", + "capag": "A", + "tier": "bankable", + "lat": -27.664, + "lon": -53.6407, + "isHero": false + }, + { + "name": "Relvado", + "codIbge": "4315453", + "capag": "A", + "tier": "bankable", + "lat": -29.1164, + "lon": -52.0778, + "isHero": false + }, + { + "name": "Restinga Sêca", + "codIbge": "4315503", + "capag": "B", + "tier": "bankable", + "lat": -29.8188, + "lon": -53.3807, + "isHero": false + }, + { + "name": "Rio dos Índios", + "codIbge": "4315552", + "capag": "A", + "tier": "bankable", + "lat": -27.2973, + "lon": -52.8417, + "isHero": false + }, + { + "name": "Rio Grande", + "codIbge": "4315602", + "capag": "A+", + "tier": "bankable", + "lat": -32.0349, + "lon": -52.1071, + "isHero": false + }, + { + "name": "Rio Pardo", + "codIbge": "4315701", + "capag": "B+", + "tier": "bankable", + "lat": -29.988, + "lon": -52.3711, + "isHero": false + }, + { + "name": "Riozinho", + "codIbge": "4315750", + "capag": "A", + "tier": "bankable", + "lat": -29.639, + "lon": -50.4488, + "isHero": false + }, + { + "name": "Roca Sales", + "codIbge": "4315800", + "capag": "C", + "tier": "constrained", + "lat": -29.2884, + "lon": -51.8658, + "isHero": false + }, + { + "name": "Rodeio Bonito", + "codIbge": "4315909", + "capag": "A", + "tier": "bankable", + "lat": -27.4742, + "lon": -53.1706, + "isHero": false + }, + { + "name": "Rolador", + "codIbge": "4315958", + "capag": "B", + "tier": "bankable", + "lat": -28.2566, + "lon": -54.8186, + "isHero": false + }, + { + "name": "Rolante", + "codIbge": "4316006", + "capag": "B", + "tier": "bankable", + "lat": -29.6462, + "lon": -50.5819, + "isHero": false + }, + { + "name": "Ronda Alta", + "codIbge": "4316105", + "capag": "A", + "tier": "bankable", + "lat": -27.7758, + "lon": -52.8056, + "isHero": false + }, + { + "name": "Rondinha", + "codIbge": "4316204", + "capag": "A", + "tier": "bankable", + "lat": -27.8315, + "lon": -52.9081, + "isHero": false + }, + { + "name": "Roque Gonzales", + "codIbge": "4316303", + "capag": "B", + "tier": "bankable", + "lat": -28.1297, + "lon": -55.0266, + "isHero": false + }, + { + "name": "Rosário do Sul", + "codIbge": "4316402", + "capag": "C", + "tier": "constrained", + "lat": -30.2515, + "lon": -54.9221, + "isHero": false + }, + { + "name": "Sagrada Família", + "codIbge": "4316428", + "capag": "A", + "tier": "bankable", + "lat": -27.7085, + "lon": -53.1351, + "isHero": false + }, + { + "name": "Saldanha Marinho", + "codIbge": "4316436", + "capag": "C", + "tier": "constrained", + "lat": -28.3941, + "lon": -53.097, + "isHero": false + }, + { + "name": "Salto do Jacuí", + "codIbge": "4316451", + "capag": "B", + "tier": "bankable", + "lat": -29.0951, + "lon": -53.2133, + "isHero": false + }, + { + "name": "Salvador das Missões", + "codIbge": "4316477", + "capag": "A", + "tier": "bankable", + "lat": -28.1233, + "lon": -54.8373, + "isHero": false + }, + { + "name": "Salvador do Sul", + "codIbge": "4316501", + "capag": "A", + "tier": "bankable", + "lat": -29.4386, + "lon": -51.5077, + "isHero": false + }, + { + "name": "Sananduva", + "codIbge": "4316600", + "capag": "B", + "tier": "bankable", + "lat": -27.947, + "lon": -51.8079, + "isHero": false + }, + { + "name": "Santa Bárbara do Sul", + "codIbge": "4316709", + "capag": "A", + "tier": "bankable", + "lat": -28.3653, + "lon": -53.251, + "isHero": false + }, + { + "name": "Santa Cecília do Sul", + "codIbge": "4316733", + "capag": "B", + "tier": "bankable", + "lat": -28.1609, + "lon": -51.9279, + "isHero": false + }, + { + "name": "Santa Clara do Sul", + "codIbge": "4316758", + "capag": "A+", + "tier": "bankable", + "lat": -29.4747, + "lon": -52.0843, + "isHero": false + }, + { + "name": "Santa Cruz do Sul", + "codIbge": "4316808", + "capag": "C", + "tier": "constrained", + "lat": -29.722, + "lon": -52.4343, + "isHero": false + }, + { + "name": "Santa Maria", + "codIbge": "4316907", + "capag": "C", + "tier": "constrained", + "lat": -29.6868, + "lon": -53.8149, + "isHero": false + }, + { + "name": "Santa Maria do Herval", + "codIbge": "4316956", + "capag": "A", + "tier": "bankable", + "lat": -29.4902, + "lon": -50.9919, + "isHero": false + }, + { + "name": "Santa Margarida do Sul", + "codIbge": "4316972", + "capag": "A", + "tier": "bankable", + "lat": -30.3393, + "lon": -54.0817, + "isHero": false + }, + { + "name": "Santana da Boa Vista", + "codIbge": "4317004", + "capag": "A+", + "tier": "bankable", + "lat": -30.8697, + "lon": -53.11, + "isHero": false + }, + { + "name": "Sant'Ana do Livramento", + "codIbge": "4317103", + "capag": "B", + "tier": "bankable", + "lat": -30.8773, + "lon": -55.5392, + "isHero": false + }, + { + "name": "Santa Rosa", + "codIbge": "4317202", + "capag": "A+", + "tier": "bankable", + "lat": -27.8702, + "lon": -54.4796, + "isHero": false + }, + { + "name": "Santa Tereza", + "codIbge": "4317251", + "capag": "A", + "tier": "bankable", + "lat": -29.1655, + "lon": -51.7351, + "isHero": false + }, + { + "name": "Santa Vitória do Palmar", + "codIbge": "4317301", + "capag": "A+", + "tier": "bankable", + "lat": -33.525, + "lon": -53.3717, + "isHero": false + }, + { + "name": "Santiago", + "codIbge": "4317400", + "capag": "A", + "tier": "bankable", + "lat": -29.1897, + "lon": -54.8666, + "isHero": false + }, + { + "name": "Santo Ângelo", + "codIbge": "4317509", + "capag": "C", + "tier": "constrained", + "lat": -28.3001, + "lon": -54.2668, + "isHero": false + }, + { + "name": "Santo Antônio do Palma", + "codIbge": "4317558", + "capag": "C", + "tier": "constrained", + "lat": -28.4956, + "lon": -52.0267, + "isHero": false + }, + { + "name": "Santo Antônio da Patrulha", + "codIbge": "4317608", + "capag": "B+", + "tier": "bankable", + "lat": -29.8268, + "lon": -50.5175, + "isHero": false + }, + { + "name": "Santo Antônio das Missões", + "codIbge": "4317707", + "capag": "B", + "tier": "bankable", + "lat": -28.514, + "lon": -55.2251, + "isHero": false + }, + { + "name": "Santo Antônio do Planalto", + "codIbge": "4317756", + "capag": "A", + "tier": "bankable", + "lat": -28.403, + "lon": -52.6992, + "isHero": false + }, + { + "name": "Santo Augusto", + "codIbge": "4317806", + "capag": "A", + "tier": "bankable", + "lat": -27.8526, + "lon": -53.7776, + "isHero": false + }, + { + "name": "Santo Cristo", + "codIbge": "4317905", + "capag": "A", + "tier": "bankable", + "lat": -27.8263, + "lon": -54.662, + "isHero": false + }, + { + "name": "Santo Expedito do Sul", + "codIbge": "4317954", + "capag": "B", + "tier": "bankable", + "lat": -27.9074, + "lon": -51.6434, + "isHero": false + }, + { + "name": "São Borja", + "codIbge": "4318002", + "capag": "B+", + "tier": "bankable", + "lat": -28.6578, + "lon": -56.0036, + "isHero": false + }, + { + "name": "São Domingos do Sul", + "codIbge": "4318051", + "capag": "B", + "tier": "bankable", + "lat": -28.5312, + "lon": -51.886, + "isHero": false + }, + { + "name": "São Francisco de Assis", + "codIbge": "4318101", + "capag": "B+", + "tier": "bankable", + "lat": -29.5547, + "lon": -55.1253, + "isHero": false + }, + { + "name": "São Francisco de Paula", + "codIbge": "4318200", + "capag": "n.d.", + "tier": "unrated", + "lat": -29.4404, + "lon": -50.5828, + "isHero": false + }, + { + "name": "São Gabriel", + "codIbge": "4318309", + "capag": "C", + "tier": "constrained", + "lat": -30.3337, + "lon": -54.3217, + "isHero": false + }, + { + "name": "São Jerônimo", + "codIbge": "4318408", + "capag": "A", + "tier": "bankable", + "lat": -29.9716, + "lon": -51.7251, + "isHero": false + }, + { + "name": "São João da Urtiga", + "codIbge": "4318424", + "capag": "B", + "tier": "bankable", + "lat": -27.8195, + "lon": -51.8257, + "isHero": false + }, + { + "name": "São João do Polêsine", + "codIbge": "4318432", + "capag": "A", + "tier": "bankable", + "lat": -29.6194, + "lon": -53.4439, + "isHero": false + }, + { + "name": "São Jorge", + "codIbge": "4318440", + "capag": "A+", + "tier": "bankable", + "lat": -28.4984, + "lon": -51.7064, + "isHero": false + }, + { + "name": "São José das Missões", + "codIbge": "4318457", + "capag": "B", + "tier": "bankable", + "lat": -27.7789, + "lon": -53.1226, + "isHero": false + }, + { + "name": "São José do Herval", + "codIbge": "4318465", + "capag": "A+", + "tier": "bankable", + "lat": -29.052, + "lon": -52.295, + "isHero": false + }, + { + "name": "São José do Hortêncio", + "codIbge": "4318481", + "capag": "A", + "tier": "bankable", + "lat": -29.528, + "lon": -51.245, + "isHero": false + }, + { + "name": "São José do Inhacorá", + "codIbge": "4318499", + "capag": "A", + "tier": "bankable", + "lat": -27.7251, + "lon": -54.1275, + "isHero": false + }, + { + "name": "São José do Norte", + "codIbge": "4318507", + "capag": "A+", + "tier": "bankable", + "lat": -32.0151, + "lon": -52.0331, + "isHero": false + }, + { + "name": "São José do Ouro", + "codIbge": "4318606", + "capag": "C", + "tier": "constrained", + "lat": -27.7707, + "lon": -51.5966, + "isHero": false + }, + { + "name": "São José do Sul", + "codIbge": "4318614", + "capag": "A", + "tier": "bankable", + "lat": -29.5448, + "lon": -51.4821, + "isHero": false + }, + { + "name": "São José dos Ausentes", + "codIbge": "4318622", + "capag": "n.d.", + "tier": "unrated", + "lat": -28.7476, + "lon": -50.0677, + "isHero": false + }, + { + "name": "São Leopoldo", + "codIbge": "4318705", + "capag": "C", + "tier": "constrained", + "lat": -29.7545, + "lon": -51.1498, + "isHero": false + }, + { + "name": "São Lourenço do Sul", + "codIbge": "4318804", + "capag": "B", + "tier": "bankable", + "lat": -31.3564, + "lon": -51.9715, + "isHero": false + }, + { + "name": "São Luiz Gonzaga", + "codIbge": "4318903", + "capag": "A", + "tier": "bankable", + "lat": -28.412, + "lon": -54.9559, + "isHero": false + }, + { + "name": "São Marcos", + "codIbge": "4319000", + "capag": "A", + "tier": "bankable", + "lat": -28.9677, + "lon": -51.0696, + "isHero": false + }, + { + "name": "São Martinho", + "codIbge": "4319109", + "capag": "A", + "tier": "bankable", + "lat": -27.7112, + "lon": -53.9699, + "isHero": false + }, + { + "name": "São Martinho da Serra", + "codIbge": "4319125", + "capag": "A", + "tier": "bankable", + "lat": -29.5397, + "lon": -53.859, + "isHero": false + }, + { + "name": "São Miguel das Missões", + "codIbge": "4319158", + "capag": "A", + "tier": "bankable", + "lat": -28.556, + "lon": -54.5559, + "isHero": false + }, + { + "name": "São Nicolau", + "codIbge": "4319208", + "capag": "B", + "tier": "bankable", + "lat": -28.1834, + "lon": -55.2654, + "isHero": false + }, + { + "name": "São Paulo das Missões", + "codIbge": "4319307", + "capag": "B", + "tier": "bankable", + "lat": -28.0195, + "lon": -54.9404, + "isHero": false + }, + { + "name": "São Pedro da Serra", + "codIbge": "4319356", + "capag": "A", + "tier": "bankable", + "lat": -29.4193, + "lon": -51.5134, + "isHero": false + }, + { + "name": "São Pedro das Missões", + "codIbge": "4319364", + "capag": "A", + "tier": "bankable", + "lat": -27.7706, + "lon": -53.2513, + "isHero": false + }, + { + "name": "São Pedro do Butiá", + "codIbge": "4319372", + "capag": "A", + "tier": "bankable", + "lat": -28.1243, + "lon": -54.8926, + "isHero": false + }, + { + "name": "São Pedro do Sul", + "codIbge": "4319406", + "capag": "C", + "tier": "constrained", + "lat": -29.6202, + "lon": -54.1855, + "isHero": false + }, + { + "name": "São Sebastião do Caí", + "codIbge": "4319505", + "capag": "A", + "tier": "bankable", + "lat": -29.5885, + "lon": -51.3749, + "isHero": false + }, + { + "name": "São Sepé", + "codIbge": "4319604", + "capag": "C", + "tier": "constrained", + "lat": -30.1643, + "lon": -53.5603, + "isHero": false + }, + { + "name": "São Valentim", + "codIbge": "4319703", + "capag": "A", + "tier": "bankable", + "lat": -27.5583, + "lon": -52.5237, + "isHero": false + }, + { + "name": "São Valentim do Sul", + "codIbge": "4319711", + "capag": "A+", + "tier": "bankable", + "lat": -29.0451, + "lon": -51.7684, + "isHero": false + }, + { + "name": "São Valério do Sul", + "codIbge": "4319737", + "capag": "A", + "tier": "bankable", + "lat": -27.7906, + "lon": -53.9368, + "isHero": false + }, + { + "name": "São Vendelino", + "codIbge": "4319752", + "capag": "A", + "tier": "bankable", + "lat": -29.3729, + "lon": -51.3675, + "isHero": false + }, + { + "name": "São Vicente do Sul", + "codIbge": "4319802", + "capag": "A", + "tier": "bankable", + "lat": -29.6882, + "lon": -54.6826, + "isHero": false + }, + { + "name": "Sapiranga", + "codIbge": "4319901", + "capag": "A", + "tier": "bankable", + "lat": -29.6349, + "lon": -51.0064, + "isHero": false + }, + { + "name": "Sapucaia do Sul", + "codIbge": "4320008", + "capag": "B", + "tier": "bankable", + "lat": -29.8276, + "lon": -51.145, + "isHero": false + }, + { + "name": "Sarandi", + "codIbge": "4320107", + "capag": "B+", + "tier": "bankable", + "lat": -27.942, + "lon": -52.9231, + "isHero": false + }, + { + "name": "Seberi", + "codIbge": "4320206", + "capag": "C", + "tier": "constrained", + "lat": -27.4829, + "lon": -53.4026, + "isHero": false + }, + { + "name": "Sede Nova", + "codIbge": "4320230", + "capag": "A+", + "tier": "bankable", + "lat": -27.6367, + "lon": -53.9493, + "isHero": false + }, + { + "name": "Segredo", + "codIbge": "4320263", + "capag": "B", + "tier": "bankable", + "lat": -29.3523, + "lon": -52.9767, + "isHero": false + }, + { + "name": "Selbach", + "codIbge": "4320305", + "capag": "A+", + "tier": "bankable", + "lat": -28.6294, + "lon": -52.9498, + "isHero": false + }, + { + "name": "Senador Salgado Filho", + "codIbge": "4320321", + "capag": "A+", + "tier": "bankable", + "lat": -28.025, + "lon": -54.5507, + "isHero": false + }, + { + "name": "Sentinela do Sul", + "codIbge": "4320354", + "capag": "A+", + "tier": "bankable", + "lat": -30.6107, + "lon": -51.5862, + "isHero": false + }, + { + "name": "Serafina Corrêa", + "codIbge": "4320404", + "capag": "A", + "tier": "bankable", + "lat": -28.7126, + "lon": -51.9352, + "isHero": false + }, + { + "name": "Sério", + "codIbge": "4320453", + "capag": "A", + "tier": "bankable", + "lat": -29.3904, + "lon": -52.2685, + "isHero": false + }, + { + "name": "Sertão", + "codIbge": "4320503", + "capag": "B", + "tier": "bankable", + "lat": -27.9798, + "lon": -52.2588, + "isHero": false + }, + { + "name": "Sertão Santana", + "codIbge": "4320552", + "capag": "A", + "tier": "bankable", + "lat": -30.4562, + "lon": -51.6017, + "isHero": false + }, + { + "name": "Sete de Setembro", + "codIbge": "4320578", + "capag": "A", + "tier": "bankable", + "lat": -28.1362, + "lon": -54.4637, + "isHero": false + }, + { + "name": "Severiano de Almeida", + "codIbge": "4320602", + "capag": "A+", + "tier": "bankable", + "lat": -27.4362, + "lon": -52.1217, + "isHero": false + }, + { + "name": "Silveira Martins", + "codIbge": "4320651", + "capag": "A+", + "tier": "bankable", + "lat": -29.6467, + "lon": -53.591, + "isHero": false + }, + { + "name": "Sinimbu", + "codIbge": "4320677", + "capag": "A+", + "tier": "bankable", + "lat": -29.5357, + "lon": -52.5304, + "isHero": false + }, + { + "name": "Sobradinho", + "codIbge": "4320701", + "capag": "C", + "tier": "constrained", + "lat": -29.4194, + "lon": -53.0326, + "isHero": false + }, + { + "name": "Soledade", + "codIbge": "4320800", + "capag": "A", + "tier": "bankable", + "lat": -28.8306, + "lon": -52.5131, + "isHero": false + }, + { + "name": "Tabaí", + "codIbge": "4320859", + "capag": "B", + "tier": "bankable", + "lat": -29.643, + "lon": -51.6823, + "isHero": false + }, + { + "name": "Tapejara", + "codIbge": "4320909", + "capag": "A", + "tier": "bankable", + "lat": -28.0652, + "lon": -52.0097, + "isHero": false + }, + { + "name": "Tapera", + "codIbge": "4321006", + "capag": "A", + "tier": "bankable", + "lat": -28.6277, + "lon": -52.8613, + "isHero": false + }, + { + "name": "Tapes", + "codIbge": "4321105", + "capag": "A+", + "tier": "bankable", + "lat": -30.6683, + "lon": -51.3991, + "isHero": false + }, + { + "name": "Taquara", + "codIbge": "4321204", + "capag": "B", + "tier": "bankable", + "lat": -29.6505, + "lon": -50.7753, + "isHero": false + }, + { + "name": "Taquari", + "codIbge": "4321303", + "capag": "B", + "tier": "bankable", + "lat": -29.7943, + "lon": -51.8653, + "isHero": false + }, + { + "name": "Taquaruçu do Sul", + "codIbge": "4321329", + "capag": "A", + "tier": "bankable", + "lat": -27.4005, + "lon": -53.4702, + "isHero": false + }, + { + "name": "Tavares", + "codIbge": "4321352", + "capag": "A+", + "tier": "bankable", + "lat": -31.2843, + "lon": -51.088, + "isHero": false + }, + { + "name": "Tenente Portela", + "codIbge": "4321402", + "capag": "n.d.", + "tier": "unrated", + "lat": -27.3711, + "lon": -53.7585, + "isHero": false + }, + { + "name": "Terra de Areia", + "codIbge": "4321436", + "capag": "A", + "tier": "bankable", + "lat": -29.5782, + "lon": -50.0644, + "isHero": false + }, + { + "name": "Teutônia", + "codIbge": "4321451", + "capag": "B", + "tier": "bankable", + "lat": -29.4482, + "lon": -51.8044, + "isHero": false + }, + { + "name": "Tio Hugo", + "codIbge": "4321469", + "capag": "A", + "tier": "bankable", + "lat": -28.5712, + "lon": -52.5955, + "isHero": false + }, + { + "name": "Tiradentes do Sul", + "codIbge": "4321477", + "capag": "A", + "tier": "bankable", + "lat": -27.4022, + "lon": -54.0814, + "isHero": false + }, + { + "name": "Toropi", + "codIbge": "4321493", + "capag": "B", + "tier": "bankable", + "lat": -29.4782, + "lon": -54.2244, + "isHero": false + }, + { + "name": "Torres", + "codIbge": "4321501", + "capag": "A+", + "tier": "bankable", + "lat": -29.3334, + "lon": -49.7333, + "isHero": false + }, + { + "name": "Tramandaí", + "codIbge": "4321600", + "capag": "A", + "tier": "bankable", + "lat": -29.9841, + "lon": -50.1322, + "isHero": false + }, + { + "name": "Travesseiro", + "codIbge": "4321626", + "capag": "C", + "tier": "constrained", + "lat": -29.2977, + "lon": -52.0532, + "isHero": false + }, + { + "name": "Três Arroios", + "codIbge": "4321634", + "capag": "A", + "tier": "bankable", + "lat": -27.5003, + "lon": -52.1448, + "isHero": false + }, + { + "name": "Três Cachoeiras", + "codIbge": "4321667", + "capag": "B", + "tier": "bankable", + "lat": -29.4487, + "lon": -49.9275, + "isHero": false + }, + { + "name": "Três Coroas", + "codIbge": "4321709", + "capag": "B+", + "tier": "bankable", + "lat": -29.5137, + "lon": -50.7739, + "isHero": false + }, + { + "name": "Três de Maio", + "codIbge": "4321808", + "capag": "A", + "tier": "bankable", + "lat": -27.78, + "lon": -54.2357, + "isHero": false + }, + { + "name": "Três Forquilhas", + "codIbge": "4321832", + "capag": "C", + "tier": "constrained", + "lat": -29.5384, + "lon": -50.0708, + "isHero": false + }, + { + "name": "Três Palmeiras", + "codIbge": "4321857", + "capag": "B", + "tier": "bankable", + "lat": -27.6139, + "lon": -52.8437, + "isHero": false + }, + { + "name": "Três Passos", + "codIbge": "4321907", + "capag": "A", + "tier": "bankable", + "lat": -27.4555, + "lon": -53.9296, + "isHero": false + }, + { + "name": "Trindade do Sul", + "codIbge": "4321956", + "capag": "A", + "tier": "bankable", + "lat": -27.5239, + "lon": -52.8956, + "isHero": false + }, + { + "name": "Triunfo", + "codIbge": "4322004", + "capag": "C", + "tier": "constrained", + "lat": -29.9291, + "lon": -51.7075, + "isHero": false + }, + { + "name": "Tucunduva", + "codIbge": "4322103", + "capag": "B", + "tier": "bankable", + "lat": -27.6573, + "lon": -54.4439, + "isHero": false + }, + { + "name": "Tunas", + "codIbge": "4322152", + "capag": "C", + "tier": "constrained", + "lat": -29.1039, + "lon": -52.9538, + "isHero": false + }, + { + "name": "Tupanci do Sul", + "codIbge": "4322186", + "capag": "B", + "tier": "bankable", + "lat": -27.9241, + "lon": -51.5383, + "isHero": false + }, + { + "name": "Tupanciretã", + "codIbge": "4322202", + "capag": "A+", + "tier": "bankable", + "lat": -29.0858, + "lon": -53.8445, + "isHero": false + }, + { + "name": "Tupandi", + "codIbge": "4322251", + "capag": "A", + "tier": "bankable", + "lat": -29.4772, + "lon": -51.4174, + "isHero": false + }, + { + "name": "Tuparendi", + "codIbge": "4322301", + "capag": "A", + "tier": "bankable", + "lat": -27.7598, + "lon": -54.4814, + "isHero": false + }, + { + "name": "Turuçu", + "codIbge": "4322327", + "capag": "C", + "tier": "constrained", + "lat": -31.4173, + "lon": -52.1706, + "isHero": false + }, + { + "name": "Ubiretama", + "codIbge": "4322343", + "capag": "A", + "tier": "bankable", + "lat": -28.0404, + "lon": -54.686, + "isHero": false + }, + { + "name": "União da Serra", + "codIbge": "4322350", + "capag": "A+", + "tier": "bankable", + "lat": -28.7833, + "lon": -52.0238, + "isHero": false + }, + { + "name": "Unistalda", + "codIbge": "4322376", + "capag": "A", + "tier": "bankable", + "lat": -29.04, + "lon": -55.1517, + "isHero": false + }, + { + "name": "Uruguaiana", + "codIbge": "4322400", + "capag": "B+", + "tier": "bankable", + "lat": -29.7614, + "lon": -57.0853, + "isHero": false + }, + { + "name": "Vacaria", + "codIbge": "4322509", + "capag": "C", + "tier": "constrained", + "lat": -28.5079, + "lon": -50.9418, + "isHero": false + }, + { + "name": "Vale Verde", + "codIbge": "4322525", + "capag": "A", + "tier": "bankable", + "lat": -29.7864, + "lon": -52.1857, + "isHero": false + }, + { + "name": "Vale do Sol", + "codIbge": "4322533", + "capag": "B+", + "tier": "bankable", + "lat": -29.5967, + "lon": -52.6839, + "isHero": false + }, + { + "name": "Vale Real", + "codIbge": "4322541", + "capag": "B", + "tier": "bankable", + "lat": -29.3919, + "lon": -51.2559, + "isHero": false + }, + { + "name": "Vanini", + "codIbge": "4322558", + "capag": "A+", + "tier": "bankable", + "lat": -28.4758, + "lon": -51.8447, + "isHero": false + }, + { + "name": "Venâncio Aires", + "codIbge": "4322608", + "capag": "A+", + "tier": "bankable", + "lat": -29.6143, + "lon": -52.1932, + "isHero": false + }, + { + "name": "Vera Cruz", + "codIbge": "4322707", + "capag": "A+", + "tier": "bankable", + "lat": -29.7184, + "lon": -52.5152, + "isHero": false + }, + { + "name": "Veranópolis", + "codIbge": "4322806", + "capag": "A", + "tier": "bankable", + "lat": -28.9312, + "lon": -51.5516, + "isHero": false + }, + { + "name": "Vespasiano Corrêa", + "codIbge": "4322855", + "capag": "C", + "tier": "constrained", + "lat": -29.0655, + "lon": -51.8625, + "isHero": false + }, + { + "name": "Viadutos", + "codIbge": "4322905", + "capag": "A+", + "tier": "bankable", + "lat": -27.5716, + "lon": -52.0211, + "isHero": false + }, + { + "name": "Viamão", + "codIbge": "4323002", + "capag": "C", + "tier": "constrained", + "lat": -30.0819, + "lon": -51.0194, + "isHero": false + }, + { + "name": "Vicente Dutra", + "codIbge": "4323101", + "capag": "A", + "tier": "bankable", + "lat": -27.1607, + "lon": -53.4022, + "isHero": false + }, + { + "name": "Victor Graeff", + "codIbge": "4323200", + "capag": "A", + "tier": "bankable", + "lat": -28.5632, + "lon": -52.7495, + "isHero": false + }, + { + "name": "Vila Flores", + "codIbge": "4323309", + "capag": "C", + "tier": "constrained", + "lat": -28.8598, + "lon": -51.5504, + "isHero": false + }, + { + "name": "Vila Lângaro", + "codIbge": "4323358", + "capag": "A", + "tier": "bankable", + "lat": -28.1062, + "lon": -52.1438, + "isHero": false + }, + { + "name": "Vila Maria", + "codIbge": "4323408", + "capag": "A+", + "tier": "bankable", + "lat": -28.5359, + "lon": -52.1486, + "isHero": false + }, + { + "name": "Vila Nova do Sul", + "codIbge": "4323457", + "capag": "A+", + "tier": "bankable", + "lat": -30.3461, + "lon": -53.876, + "isHero": false + }, + { + "name": "Vista Alegre", + "codIbge": "4323507", + "capag": "A", + "tier": "bankable", + "lat": -27.3686, + "lon": -53.4919, + "isHero": false + }, + { + "name": "Vista Alegre do Prata", + "codIbge": "4323606", + "capag": "A", + "tier": "bankable", + "lat": -28.8052, + "lon": -51.7947, + "isHero": false + }, + { + "name": "Vista Gaúcha", + "codIbge": "4323705", + "capag": "A", + "tier": "bankable", + "lat": -27.2902, + "lon": -53.6974, + "isHero": false + }, + { + "name": "Vitória das Missões", + "codIbge": "4323754", + "capag": "C", + "tier": "constrained", + "lat": -28.3516, + "lon": -54.504, + "isHero": false + }, + { + "name": "Westfália", + "codIbge": "4323770", + "capag": "A", + "tier": "bankable", + "lat": -29.4263, + "lon": -51.7645, + "isHero": false + }, + { + "name": "Xangri-lá", + "codIbge": "4323804", + "capag": "B", + "tier": "bankable", + "lat": -29.8065, + "lon": -50.0519, + "isHero": false + } + ], + "legend": [ + { + "tier": "bankable", + "label": "CAPAG A/B — bankable (guaranteed credit)", + "count": 404 + }, + { + "tier": "constrained", + "label": "CAPAG C/D — creditless (grants / blended)", + "count": 76 + }, + { + "tier": "unrated", + "label": "n.d. — unrated (TA first)", + "count": 17 + } + ] +} \ No newline at end of file diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/adapters.ts b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/adapters.ts new file mode 100644 index 0000000..1442f46 --- /dev/null +++ b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/adapters.ts @@ -0,0 +1,89 @@ +// Fiscal Data Adapter layer — normalizes country-specific fiscal sources into the +// readiness model, keyed by city id (locode / IBGE). Chile = SINIM/FCM (via the +// City-Funder Matching Engine); Brazil = CAPAG (Tesouro Nacional). New countries +// add an adapter without touching the rest of the app. +import { SM, type Comuna, type Scored } from "./engine"; +import clData from "@/data/valdivia.json"; +import brData from "@/data/brazil.json"; + +export interface Scope { + id: string; + country: string; + region: string; + adapter: string; // the fiscal data source + center: [number, number]; + zoom: number; + tierKind: "readiness" | "capag"; +} + +export const SCOPES: Scope[] = [ + { id: "cl-losrios", country: "Chile", region: "Los Ríos", adapter: "SINIM / FCM", center: [-39.85, -72.9], zoom: 8, tierKind: "readiness" }, + { id: "br-rs", country: "Brazil", region: "Rio Grande do Sul", adapter: "CAPAG (Tesouro Nacional)", center: [-29.7, -53.2], zoom: 6, tierKind: "capag" }, +]; + +// Approx coordinates for the Chilean unit-11 comunas (by locode, name fallback). +const CL_COORDS: Record = { + "CL ZAL": [-39.814, -73.246], "CL PAO": [-40.069, -72.872], "CL LLG": [-39.851, -72.831], + "CL CRR": [-39.887, -73.43], "CL MAF": [-39.665, -72.949], Mariquina: [-39.526, -72.969], +}; + +export interface MapPoint { + id: string; + name: string; + lat: number; + lon: number; + tier: string; // readiness tier OR capag tier + tierClass: string; // css class for color + isHero: boolean; + capag?: string | null; + journeyable: boolean; // can you enter the journey for this city? +} + +const clComunas = (clData as any).comunas as Comuna[]; +const brHero = (brData as any).hero as Comuna; +const brStateMap = (brData as any).stateMap as any[]; + +function readinessTierClass(t: string) { + return t; // "Ready" | "Developing" | "Early" map to css .tier. +} + +export function mapPoints(scopeId: string): MapPoint[] { + if (scopeId === "cl-losrios") { + return clComunas + .map((c) => { + const co = CL_COORDS[c.locode || ""] || CL_COORDS[c.name]; + if (!co) return null; + const s = SM.scoreSNG(c); + return { id: c.id, name: c.name, lat: co[0], lon: co[1], tier: s.tier, tierClass: readinessTierClass(s.tier), isHero: c.isAnchor, journeyable: c.isAnchor }; + }) + .filter(Boolean) as MapPoint[]; + } + // Brazil — CAPAG tiers across RS (cheap; uses precomputed tier, only hero is journeyable) + return brStateMap.map((m) => ({ + id: `SNG-BR-${m.codIbge}`, name: m.name, lat: m.lat, lon: m.lon, + tier: m.tier, tierClass: m.tier, isHero: m.isHero, capag: m.capag, journeyable: m.isHero, + })); +} + +export function scopeLegend(scopeId: string): { cls: string; label: string }[] { + if (scopeId === "cl-losrios") + return [ + { cls: "Ready", label: "Ready" }, + { cls: "Developing", label: "Developing" }, + { cls: "Early", label: "Early" }, + ]; + const lg = (brData as any).legend as any[]; + return lg.map((l) => ({ cls: l.tier, label: l.label })); +} + +// The cities you can actually run the journey for (have full readiness detail). +export function journeyCity(cityId: string): Scored | null { + const c = clComunas.find((x) => x.id === cityId) || (brHero.id === cityId ? brHero : null); + return c ? SM.scoreSNG(c) : null; +} + +export function heroFor(scopeId: string): Scored { + return scopeId === "br-rs" ? SM.scoreSNG(brHero) : SM.scoreSNG(clComunas.find((c) => c.isAnchor)!); +} + +export const DATA = { cl: clData as any, br: brData as any }; diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/context.ts b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/context.ts new file mode 100644 index 0000000..2ec7b58 --- /dev/null +++ b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/context.ts @@ -0,0 +1,63 @@ +// CityCatalyst context provider — the AI-agent / shared-context SEAM. +// Today this returns simulated context (inventory + HIAP) and a canned "agent +// assist". In production these calls go to CityCatalyst's MCP / agent layer +// (get_city_profile, get_inventory_emissions, HIAP get_prioritization) so context +// is shared across modules. Keep this interface stable; swap the body for live MCP. + +export interface CityContext { + cityId: string; + inventory: { topSectors: { sector: string; sharePct: number }[]; year: number; source: string }; + hiap: { actionId: string; name: string; sector: string; type: "mitigation" | "adaptation"; rank: number }[]; + source: "simulated" | "citycatalyst-mcp"; +} + +const CONTEXT: Record = { + // Valdivia (Chile) + "SNG-CLZAL": { + cityId: "SNG-CLZAL", + inventory: { year: 2022, source: "CityCatalyst GHGI (simulated)", topSectors: [ + { sector: "Transportation", sharePct: 38 }, { sector: "Stationary energy", sharePct: 31 }, { sector: "Waste", sharePct: 19 }, + ] }, + hiap: [ + { actionId: "c40_0023", name: "Adopt zero-emission bus fleets", sector: "transportation", type: "mitigation", rank: 1 }, + { actionId: "ipcc_0001", name: "Transit-oriented development", sector: "transportation", type: "mitigation", rank: 2 }, + { actionId: "ipcc_0105", name: "Active mobility / road space reallocation", sector: "transportation", type: "mitigation", rank: 3 }, + ], + source: "simulated", + }, + // Canoas (Brazil) + "SNG-BR-4304606": { + cityId: "SNG-BR-4304606", + inventory: { year: 2022, source: "CityCatalyst GHGI (simulated)", topSectors: [ + { sector: "Stationary energy", sharePct: 41 }, { sector: "Transportation", sharePct: 27 }, { sector: "Waste", sharePct: 21 }, + ] }, + hiap: [ + { actionId: "ipcc_0210", name: "Urban drainage & flood defences", sector: "water", type: "adaptation", rank: 1 }, + { actionId: "ipcc_0233", name: "Nature-based riverine buffers", sector: "afolu", type: "adaptation", rank: 2 }, + { actionId: "c40_0061", name: "Early-warning & resilient infrastructure", sector: "water", type: "adaptation", rank: 3 }, + ], + source: "simulated", + }, +}; + +export function getCityContext(cityId: string): CityContext | null { + return CONTEXT[cityId] || null; +} + +// Simulated agent assist. In production this is a CityCatalyst agent call that can +// read the city's shared context across modules. Returns guidance + a flag. +export function agentAssist(opts: { cityName: string; tier: string; cleared: boolean; pathway: string }): { + simulated: true; + text: string; +} { + const { cityName, tier, cleared, pathway } = opts; + let text: string; + if (tier === "Ready" && cleared) { + text = `${cityName} clears the early creditworthiness assessment. Its plan is strong but a single project may be below the instrument's ticket size — I'd route it to the portfolio/pooling step to combine with neighbours, then assemble the dossier.`; + } else if (pathway === "capacity-building") { + text = `${cityName} isn't yet eligible. Looking at the signals, the gap is not debt — it's liquidity, savings and accounting quality. I'd recommend a capacity-building track (fix accounting to lift the ICF rating, build cash reserves) plus grant/blended finance for adaptation now, rather than a guaranteed-credit application.`; + } else { + text = `${cityName} is on the readiness path. Close the named gaps via targeted TC, then re-assess for the instrument.`; + } + return { simulated: true, text }; +} diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/dossier.ts b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/dossier.ts new file mode 100644 index 0000000..c28e45b --- /dev/null +++ b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/dossier.ts @@ -0,0 +1,64 @@ +// Candidate dossier = the machine-readable handoff into a funder's intake. +// It extends the project Concept Note (plan + actions) with the entity +// creditworthiness, the instrument, the pool, and the due-diligence checklist — +// one document a funder (IDB Control Tower) can intake. +import { SM, PILLAR_ORDER, type Scored } from "./engine"; +import { getCityContext } from "./context"; + +export interface Dossier { + id: string; + submittedAt: string; + candidateId: string; + kind: "city" | "pool"; + name: string; + locode: string | null; + cityId: string | null; + country: string; + pathway: "instrument" | "pool" | "capacity-building"; + targetProfileId: string; + instrument: { funder: string; name: string }; + conceptNote: { title: string; sector: string; askUSDm: number; actions: { name: string; type: string }[]; summary: string }; + readiness: { composite: number; tier: string; cleared: boolean; pillars: { key: string; label: string; score: number; provenance: string }[] }; + pool: { anchor: string; members: { name: string; role: string; cofinance: number | null }[] } | null; + dueDiligence: { label: string; done: boolean }[]; + financials: { askUSDm: number; cofinance: boolean }; + provenanceNote: string; +} + +export interface AssembleOpts { + scored: Scored; + kind: "city" | "pool"; + pathway: "instrument" | "pool" | "capacity-building"; + instrumentName?: string; + pool?: { anchor: string; members: { name: string; role: string; cofinance: number | null }[] } | null; + proposal: { title: string; sector: string; askUSDm: number; cofinance: boolean }; +} + +export function assembleDossier(o: AssembleOpts): Omit { + const s = o.scored; + const profile = SM.activeProfile(); + const ctx = getCityContext(s.id); + const pillars = SM.explainScore(s.readiness).map((e) => ({ + key: e.key, label: e.label, score: s.readiness[e.key], provenance: (s.provenance as any)[e.key], + })); + void PILLAR_ORDER; + return { + candidateId: o.kind === "pool" ? `POOL-${s.id}` : s.id, + kind: o.kind, + name: o.kind === "pool" ? `${s.name} pool (anchor)` : s.name, + locode: s.locode, cityId: s.cityId, country: s.country, + pathway: o.pathway, + targetProfileId: profile.id, + instrument: { funder: profile.funder, name: o.instrumentName || profile.instrument }, + conceptNote: { + title: o.proposal.title, sector: o.proposal.sector, askUSDm: o.proposal.askUSDm, + actions: (ctx?.hiap || []).map((a) => ({ name: a.name, type: a.type })), + summary: `Plan derived from ${s.name}'s CityCatalyst HIAP priorities; ${ctx?.hiap.length || 0} prioritized actions.`, + }, + readiness: { composite: s.compositeReadiness, tier: s.tier, cleared: s.canEnterProjectReview, pillars }, + pool: o.pool || null, + dueDiligence: SM.intakeChecklist(s), + financials: { askUSDm: o.proposal.askUSDm, cofinance: o.proposal.cofinance }, + provenanceNote: "Fiscal pillars from real national data (CAPAG · SINIM/FCM), locode-keyed. Screening signal, not a credit decision.", + }; +} diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/store.ts b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/store.ts index 9609557..15ed6e5 100644 --- a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/store.ts +++ b/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/store.ts @@ -1,24 +1,9 @@ -// In-memory submission store (demo only — resets when the dev server restarts). -// This stands in for the IDB-side Control Tower receiving the handoff object. -// Uses globalThis so it survives Next.js hot-reloads in dev. -export interface Submission { - id: string; - candidateId: string; - kind: "city" | "pool"; - name: string; - locode: string | null; - cityId: string | null; - anchorLocode: string | null; - members: string[]; - targetProfileId: string; - compositeReadiness: number; - tier: string; - clearancePassed: boolean; - proposal: { title: string; askUSDm: number; sector: string }; - provenance: Record; - submittedAt: string; -} +// In-memory dossier store (demo only — resets when the dev server restarts). +// Stands in for the IDB-side Control Tower receiving the candidate dossier. +import type { Dossier } from "./dossier"; -const g = globalThis as unknown as { __CRN_SUBMISSIONS__?: Submission[] }; -if (!g.__CRN_SUBMISSIONS__) g.__CRN_SUBMISSIONS__ = []; -export const submissions: Submission[] = g.__CRN_SUBMISSIONS__; +export type { Dossier }; + +const g = globalThis as unknown as { __CRN_DOSSIERS__?: Dossier[] }; +if (!g.__CRN_DOSSIERS__) g.__CRN_DOSSIERS__ = []; +export const dossiers: Dossier[] = g.__CRN_DOSSIERS__; diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/index.html b/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/index.html index 99c02d6..a6a476f 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/index.html +++ b/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/index.html @@ -197,8 +197,14 @@

Sub-Sovereign Finance Program (SFP) · Control Tower

+
+ What this is — a screening room for the IDB Sub-Sovereign Finance Program (SFP): a 5-year pilot that lends directly to subnational governments without a sovereign guarantee. One candidate record, three lenses — Readiness Scoring (is this SNG creditworthy?) · Project Review (where is its proposal in the IDB process, and what's blocking it?) · Monitoring & Evaluation (M&E) & Board (is the pilot proving itself to the Board and OVE?). +
+ SNG subnational government (city / state / region) · sovereign guarantee the national government backing the loan · non-accrual already behind on IDB payments · OVE IDB's independent evaluation office · TC technical cooperation · Subprogram 1 / 2 the US$1B investment envelope / the ~US$13M readiness-TC envelope +
+
From f42257a014f5cb61aac5d27fbc3c7eeab1cf7bc4 Mon Sep 17 00:00:00 2001 From: Martin Wainstein Date: Mon, 15 Jun 2026 00:59:19 -0600 Subject: [PATCH 08/14] Refine 5a diagram + PRD reframe; add presentation diagrams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - INTEGRATED-ARCHITECTURE.md §5a: Preparator as a peer module on the CityCatalyst host; Navigator as a 3-step vertical (creditworthiness → readiness pathways/coaching → portfolio & pooling); capacity building as a standalone support track (no longer wired into the Preparator). - PRD: new §1a "two-layer model" reframe; journey steps aligned (Choose the instrument, Readiness pathways, dossier, dual entry). - diagrams/: standalone SVGs for presenting (5a module view + process timeline) + README; the mermaid stays the source of truth. Co-Authored-By: Claude Opus 4.8 --- .../justagiraffe/.gitkeep | 1 - .../justagiraffe/INTEGRATED-ARCHITECTURE.md | 40 +++- .../PRD-city-facing-readiness-app.md | 46 +++- .../{ => archive}/ITERATION-2-PLAN.md | 0 .../justagiraffe/{ => archive}/ROADMAP.md | 0 .../IMPLEMENTATION_PLAN.md | 0 .../control-tower/MandE-questions.md | 36 +++ .../control-tower/Monitoring_Evaluation.md | 206 ++++++++++++++++++ .../justagiraffe/{ => control-tower}/SPEC.md | 0 .../diagrams/5a-integrated-architecture.svg | 66 ++++++ .../justagiraffe/diagrams/README.md | 16 ++ .../diagrams/process-timeline.svg | 65 ++++++ ...s regions - Document proposal - Public.pdf | Bin .../justagiraffe/{ => reference}/idb.txt | 0 .../{ => reference}/teammembers.md | 0 15 files changed, 459 insertions(+), 17 deletions(-) delete mode 100644 events/2026-06-11-unlock-the-money/justagiraffe/.gitkeep rename events/2026-06-11-unlock-the-money/justagiraffe/{ => archive}/ITERATION-2-PLAN.md (100%) rename events/2026-06-11-unlock-the-money/justagiraffe/{ => archive}/ROADMAP.md (100%) rename events/2026-06-11-unlock-the-money/justagiraffe/{ => control-tower}/IMPLEMENTATION_PLAN.md (100%) create mode 100644 events/2026-06-11-unlock-the-money/justagiraffe/control-tower/MandE-questions.md create mode 100644 events/2026-06-11-unlock-the-money/justagiraffe/control-tower/Monitoring_Evaluation.md rename events/2026-06-11-unlock-the-money/justagiraffe/{ => control-tower}/SPEC.md (100%) create mode 100644 events/2026-06-11-unlock-the-money/justagiraffe/diagrams/5a-integrated-architecture.svg create mode 100644 events/2026-06-11-unlock-the-money/justagiraffe/diagrams/README.md create mode 100644 events/2026-06-11-unlock-the-money/justagiraffe/diagrams/process-timeline.svg rename events/2026-06-11-unlock-the-money/justagiraffe/{ => reference}/IDB cities regions - Document proposal - Public.pdf (100%) rename events/2026-06-11-unlock-the-money/justagiraffe/{ => reference}/idb.txt (100%) rename events/2026-06-11-unlock-the-money/justagiraffe/{ => reference}/teammembers.md (100%) diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/.gitkeep b/events/2026-06-11-unlock-the-money/justagiraffe/.gitkeep deleted file mode 100644 index 8b13789..0000000 --- a/events/2026-06-11-unlock-the-money/justagiraffe/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/INTEGRATED-ARCHITECTURE.md b/events/2026-06-11-unlock-the-money/justagiraffe/INTEGRATED-ARCHITECTURE.md index 6bd2aec..91b169b 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/INTEGRATED-ARCHITECTURE.md +++ b/events/2026-06-11-unlock-the-money/justagiraffe/INTEGRATED-ARCHITECTURE.md @@ -110,25 +110,28 @@ CityCatalyst: GHG inventory ──┐ ┌── CCRA climate risk ```mermaid flowchart TB - subgraph CC["CityCatalyst — host & shared context"] + subgraph CC["CityCatalyst — host & shared context (infrastructure)"] HIAP["HIAP prioritized actions"] INV["GHG inventory · CCRA risk"] AGENT(["AI agents / MCP — shared context across modules"]) end + subgraph PREPM["Project Preparator — module on CityCatalyst"] + PREP["Project bankability (Tech/Fin/Pol)
→ Concept Note"] + end + DATA["Fiscal Data Adapters (locode-keyed) + map view
CAPAG · Brazil  |  SINIM/FCM · Chile"] MATCH(["Matching & Pooling — core service
action→instrument  |  entity/pool→instruments + pooling"]) - PREP["Project Preparator
project bankability (Tech/Fin/Pol)
→ Concept Note"] - subgraph NAV["City Readiness Navigator — entity / portfolio (one vertical)"] - N1["① Entity creditworthiness"] - N2["② Portfolio & pooling → submit"] - N1 --> N2 + N1["① Entity creditworthiness
diagnose for chosen instrument"] + N2["② Readiness pathways
close the gap · coach to funder requirements (IDB SFP first)"] + N3["③ Portfolio & pooling → submit
pool only if sub-scale"] + N1 --> N2 --> N3 end - CAP["Capacity building / PPF
(entity or project, when not ready)"] + CAP["Capacity building / PPF
standalone support · entity or project, when not ready"] subgraph FUND["Funder pipelines"] IDB["IDB Control Tower
Intake & Triage · Readiness Scoring · M&E & Board"] @@ -136,22 +139,35 @@ flowchart TB end HIAP --> PREP - PREP -- "Concept Note (Path A)" --> N2 + PREP -- "Concept Note (Path A)" --> N3 DATA -- "Path B · entity-first" --> N1 - N1 -- "not ready" --> CAP - CAP -.-> PREP + N2 -- "not ready → gap" --> CAP MATCH -.-> PREP MATCH -.-> NAV - N2 -- "dossier = Concept Note + creditworthiness" --> IDB - AGENT -.-> PREP + N3 -- "dossier = Concept Note + creditworthiness" --> IDB + AGENT -.-> PREPM AGENT -.-> NAV AGENT -.-> IDB ``` +> **Module hierarchy:** Preparator and Navigator are drawn as **peer modules on the +> CityCatalyst host** (intended end-state — the Preparator is a separate-repo POC today, +> `joaquinOEF/NBS-Project-Preparation`). **Navigator = one vertical, three steps:** +> ① diagnose entity creditworthiness → ② readiness pathways (close the gap / coach to the +> funder's requirements, IDB SFP first) → ③ portfolio & pooling (pool only if sub-scale) → +> submit. **Capacity building / PPF is a standalone support track** reached from a "not +> ready" diagnosis — not wired into the Preparator. Path A (a Concept Note) enters at ③; +> Path B (entity-first) enters at ①. + > Refinements behind this diagram (matching-as-core-service, entity-first naming, > capacity-building as a branch, single-vertical Navigator, AI-agent context) are detailed in > [`ITERATION-2.1-PLAN.md` §F–G](ITERATION-2.1-PLAN.md). +> **Polished renders for presenting** (open & screenshot): the module-boundary view +> [`diagrams/5a-integrated-architecture.svg`](diagrams/5a-integrated-architecture.svg) and the +> pipeline view [`diagrams/process-timeline.svg`](diagrams/process-timeline.svg). See +> [`diagrams/README.md`](diagrams/README.md). The mermaid above remains the source of truth. + ## 6. Module boundaries & contracts (to agree) - **HIAP → Preparator / Navigator:** prioritized actions (`actionId`, sector, type). diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/PRD-city-facing-readiness-app.md b/events/2026-06-11-unlock-the-money/justagiraffe/PRD-city-facing-readiness-app.md index d409dd4..e459ffb 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/PRD-city-facing-readiness-app.md +++ b/events/2026-06-11-unlock-the-money/justagiraffe/PRD-city-facing-readiness-app.md @@ -34,6 +34,40 @@ profile #1; other MDBs add their own). a de-risked deal pipeline for any MDB. Repeatable to CAF, World Bank, EIB, GCF by adding a readiness profile — no new app. +### 1a. The model (v2.1 reframe — read before §4) + +After reviewing the **Project Preparator** POC, **CAPAG** (Brazil), and the Matching +Engine, the product sharpened from "one app" to **two readiness layers on a shared +spine** (full rationale in [`INTEGRATED-ARCHITECTURE.md`](INTEGRATED-ARCHITECTURE.md)): + +- **Project bankability** ("is *this project* fundable?") — owned by the **Project + Preparator** (Tech/Fin/Pol → Concept Note). The Navigator **consumes** these; it does + **not** rebuild project preparation. +- **Entity creditworthiness** ("can *this city/pool* take on *this instrument*?") — this + app. The Navigator is the **entity / instrument / portfolio** layer. + +What this changes in the spec below: +1. **Navigator = one vertical, three steps:** ① diagnose entity creditworthiness for the + chosen instrument → ② **readiness pathways** (assess-and-route: ready → proceed; + not-ready → close the gap / coach to the funder's requirements, or a funded + capacity-building/PPF track; sub-scale → pool) → ③ portfolio & pooling → submit. + Pooling is **conditional** — a large-enough city skips it. +2. **Dual entry.** *Project-first* (Path A): a prepared Concept Note enters at step ③. + *Entity-first* (Path B): a city asking "can I access IDB SFP?" enters at step ①. Offer + **import** at entry (pull a Concept Note from the Preparator, pull a fiscal profile from + an adapter) rather than re-entry. ("Capacity-first" is *not* an entry path — capacity + building is a support track off the readiness diagnosis.) +3. **Matching + Pooling is a shared core service** (action→instrument and + entity/pool→instruments), not Chile-only data. SINIM is its current data instance. +4. **Fiscal Data Adapters** (`locode → {pillars, provenance}`) feed creditworthiness: + **CAPAG** (Brazil), **SINIM/FCM** (Chile); a **map view** badges readiness by geography. +5. **The handoff is the dossier = Concept Note + creditworthiness + instrument + pool.** +6. **Shell is a left-hand process menu** (Source · Readiness pathways · Portfolio · Funder + intake), not a horizontal stepper — the flow reads as a pipeline. + +The 7-step journey in §4 remains the functional spec; the names below reflect this reframe +(e.g. "Pick a target" → "Choose the instrument"; "Prepare" → "Readiness pathways"). + ## 2. Goals / non-goals **Goals** @@ -74,14 +108,18 @@ acceptance behavior. |---|------|--------------------|--------| | 1 | **Enter** | The city's existing profile (name, locode, population, region, GPC emissions, HIAP priorities) auto-loaded — no re-entry. | CityCatalyst app `/api/v1` (OAuth) + Global API city context | | 2 | **Discover** | "Funders your plan can reach" — instruments matched to the city's prioritized actions, each tagged applicant / facilitator / referrer, with gaps named. IDB SFP appears when eligible. | Matching Engine outputs (`valdivia_funders_open.csv`, `*_action_matches.csv`); HIAP for priorities | -| 3 | **Pick a target** | The user selects a financing path (default IDB SFP). The app loads that target's **readiness profile**. | `readiness-profiles.js` registry | +| 3 | **Choose the instrument** | The user selects a financing instrument (default IDB SFP). The app loads that instrument's **readiness profile**. (formerly "Pick a target") | `readiness-profiles.js` registry | | 4 | **Diagnose** | Readiness score (composite + four pillars), tier (Ready/Developing/Early), "why this score" per-pillar contribution, the eligibility gate pass/fail, and the documentary checklist — all for the chosen target. Real-vs-estimated badges per signal. | `scoring.js` (active profile) over CityCatalyst + Matching Engine capacity data | -| 5 | **Prepare** | For each gap: the concrete fix and the funded route. For IDB that's **Subprogram 2 TC** (~US$13M envelope: regular + contingent-recovery). Turns "rejected" into "here's funded help." | Profile `preparation` track + checklist gaps | +| 5 | **Readiness pathways** | Assess-and-route, not just "prepare." For each gap: the concrete fix and its route — self-serve coaching to the funder's requirements, or a funded capacity-building/PPF track (for IDB, **Subprogram 2 TC**, ~US$13M envelope: regular + contingent-recovery). Turns "rejected" into "here's the path." (formerly "Prepare") | Profile `preparation` track + checklist gaps | | 6 | **Pool (if needed)** | If the city is below the target's ticket size, the engine pools it with neighbours into one financeable bundle, names the anchor, flags TA-needed members. Readiness then evaluates the anchor/pool. | Matching Engine `coordination_units.csv`, `unit_bundle_candidates.csv` | -| 7 | **Submit** | When readiness for the target is met (score ≥ tier + clearance gates pass), "Submit to IDB" emits the handoff object; the city/pool appears in the Control Tower's Project Review. | Handoff contract (§6) | +| 7 | **Submit** | When readiness for the instrument is met (score ≥ tier + clearance gates pass), "Submit to IDB" emits the **dossier** (= Concept Note + creditworthiness + instrument + pool); the city/pool appears in the Control Tower's Project Review. | Handoff contract (§6) | Steps 1–6 are city-facing (inside CityCatalyst); step 7 crosses the boundary to -the funder-facing Control Tower. +the funder-facing Control Tower. **Dual entry** (see §1a): *entity-first* (Path B) starts +at step 1; *project-first* (Path A) imports a Concept Note and enters at step 6/7. **Step 6 +(Pool) is conditional** — a city at or above the instrument's ticket size proceeds straight +to Submit. Present the flow as a **left-hand process menu** (Source · Readiness pathways · +Portfolio · Funder intake), not a horizontal stepper. ## 5. Integration architecture (CityCatalyst) diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/ITERATION-2-PLAN.md b/events/2026-06-11-unlock-the-money/justagiraffe/archive/ITERATION-2-PLAN.md similarity index 100% rename from events/2026-06-11-unlock-the-money/justagiraffe/ITERATION-2-PLAN.md rename to events/2026-06-11-unlock-the-money/justagiraffe/archive/ITERATION-2-PLAN.md diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/ROADMAP.md b/events/2026-06-11-unlock-the-money/justagiraffe/archive/ROADMAP.md similarity index 100% rename from events/2026-06-11-unlock-the-money/justagiraffe/ROADMAP.md rename to events/2026-06-11-unlock-the-money/justagiraffe/archive/ROADMAP.md diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/IMPLEMENTATION_PLAN.md b/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/IMPLEMENTATION_PLAN.md similarity index 100% rename from events/2026-06-11-unlock-the-money/justagiraffe/IMPLEMENTATION_PLAN.md rename to events/2026-06-11-unlock-the-money/justagiraffe/control-tower/IMPLEMENTATION_PLAN.md diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/MandE-questions.md b/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/MandE-questions.md new file mode 100644 index 0000000..ef9a37e --- /dev/null +++ b/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/MandE-questions.md @@ -0,0 +1,36 @@ +# M&E Questions (for Prototype Scoring) + +## Pillar 1 — Fiscal & Financial Management +1. Does the SNG have an updated Public Financial Management (PFM) system? +2. Are budget execution reports published on time? +3. Is there an updated debt management strategy? +4. Has revenue autonomy improved in the last 3 years? +5. Does the SNG have a credit rating or shadow rating? + +## Pillar 2 — Project Pipeline & Technical Capacity +1. Are ex-ante evaluations conducted for major projects? +2. Are projects screened for regulatory compliance? +3. Does the SNG maintain a risk management framework? +4. Are land-use and sectoral plans up to date? +5. Is there an annual capital budget for infrastructure? + +## Pillar 3 — Service Delivery & Infrastructure Outcomes +1. Have service quality indicators improved? +2. Has service coverage increased? +3. Have emissions or pollution levels decreased? +4. Has disaster vulnerability been reduced? +5. Is quality-of-work monitored during implementation? + +## Pillar 4 — Private Sector & Market Readiness +1. Does the SNG have a PPP framework? +2. Has the SNG conducted investor consultations? +3. Does the SNG have tariff-setting capacity? +4. Are procurement systems modernized and transparent? +5. Has the SNG conducted market sounding for major projects? + +## Pillar 5 — Sustainability & Long-Term Viability +1. Is there an O&M plan for major assets? +2. Are institutional roles and responsibilities clearly defined? +3. Is the financial sustainability of services monitored? +4. Are climate resilience measures integrated into planning? +5. Are monitoring systems in place to track project outcomes? diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/Monitoring_Evaluation.md b/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/Monitoring_Evaluation.md new file mode 100644 index 0000000..f977e89 --- /dev/null +++ b/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/Monitoring_Evaluation.md @@ -0,0 +1,206 @@ +# Monitoring & Evaluation (M&E) Module – Sub‑Sovereign Pilot Control Tower + +## 1. Purpose + +The M&E module provides a unified framework to track: + +1. **Pilot‑level early outcomes** required for IDB Board reporting (Annex IV). +2. **City‑level readiness progress** over time, aligned with the SFP Theory of Change. +3. **Program‑wide performance signals** that demonstrate whether the Sub‑Sovereign Finance Program (SFP) is feasible, scalable, and delivering value. + +This module integrates Annex IV with a forward‑looking readiness approach to support SNGs in accessing finance and to give the IDB team a real‑time view of the pilot’s performance. + +--- + +## 2. M&E Architecture + +The M&E module is built around **two complementary layers**: + +### **A. Pilot‑Level Early Outcome Tracking (Annex IV)** +Tracks indicators required to evaluate the pilot’s feasibility, operational efficiency, and early outcomes across participating SNGs. + +### **B. City‑Level Readiness Progress (Forward‑Looking)** +Tracks how each SNG is progressing toward investment readiness using a simple, digital‑tool‑friendly scoring model. + +Together, these layers form the **Control Tower** view of the pilot. + +--- + +## 3. Pilot‑Level Early Outcome Indicators (Annex IV) + +These indicators come directly from Annex IV and are grouped into four domains. + +### **3.1 Fiscal & Financial Management** +- Revenue autonomy +- Fiscal transparency (timely and complete reporting) +- Updated debt management strategy +- Credit rating or shadow rating improvements + +### **3.2 Project Pipeline & Technical Capacity** +- Ex‑ante project evaluations +- Regulatory compliance screening +- Risk management systems +- Updated land‑use and sectoral plans +- Capital budgeting for infrastructure + +### **3.3 Service Delivery & Infrastructure** +- Improved service quality +- Increased service coverage +- Reduced emissions or pollution +- Reduced disaster vulnerability +- Quality‑of‑work monitoring + +### **3.4 Private Sector Engagement** +- PPP readiness +- Investor consultations / market sounding +- Tariff‑setting capacity +- Private sector participation in capital plans + +These indicators are aggregated across all SNGs to show the pilot’s overall performance. + +--- + +## 4. City‑Level Readiness Journey (Forward‑Looking) + +To complement Annex IV, the Control Tower includes a readiness journey that helps SNGs understand where they stand and what they need to improve to access financing. + +### **4.1 Readiness Ladder** +Cities are classified into four levels: + +1. **Foundational** – basic governance, limited data +2. **Emerging** – some plans, weak financials +3. **Capable** – strong financials, pipeline exists +4. **Investment‑ready** – bankable projects, strong systems + +### **4.2 Readiness Pillars (5‑Pillar Model)** + +Each SNG is assessed across **five forward‑looking pillars**: + +#### **Pillar 1 — Fiscal & Financial Management** +- Updated PFM system +- Revenue autonomy +- Debt management strategy +- Fiscal transparency +- Credit rating or shadow rating + +#### **Pillar 2 — Project Pipeline & Technical Capacity** +- Ex‑ante project evaluation +- Regulatory compliance +- Risk management +- Land‑use and sectoral plans +- Capital budgeting + +#### **Pillar 3 — Service Delivery & Infrastructure Outcomes** +- Service quality +- Service coverage +- Emissions reduction +- Disaster resilience +- Quality of work + +#### **Pillar 4 — Private Sector & Market Readiness** +- PPP framework +- Investor engagement +- Tariff‑setting capacity +- Procurement systems +- Market sounding + +#### **Pillar 5 — Sustainability & Long‑Term Viability** +- O&M planning +- Institutional continuity +- Financial sustainability +- Climate resilience +- Monitoring systems + +--- + +## 5. Scoring Model + +Each question is scored: + +- **0** = No progress +- **1** = Partial progress +- **2** = Achieved / Implemented + +Pillar scores are normalized and aggregated into a **0–100 readiness score**. + +### **Readiness Levels** +- **0–25** → Foundational +- **26–50** → Emerging +- **51–75** → Capable +- **76–100** → Investment‑ready + +--- + +## 6. M&E Outputs + +The M&E module generates four types of outputs for the Control Tower dashboard. + +### **6.1 Readiness Score** +A composite 0–100 score showing where the SNG stands on its readiness journey. + +### **6.2 Pillar Dashboard** +A radar or bar chart visualizing strengths and weaknesses across the five pillars. + +### **6.3 Narrative Summary** +Automatically generated text explaining: +- what is strong +- what is weak +- what is blocking readiness +- how the SNG compares to peers + +Examples: +- “Fiscal transparency is strong, but project pipeline evaluation is weak.” +- “You are close to investment‑ready but need stronger risk management systems.” + +### **6.4 Recommended Actions** +Tailored next steps based on low‑scoring pillars, such as: +- Update debt management strategy +- Conduct feasibility studies +- Strengthen procurement systems +- Engage private investors +- Improve safeguards and risk management + +--- + +## 7. Integration with Intake & Readiness Modules + +The M&E module integrates with the other components of the Control Tower: + +### **7.1 Intake & Triage** +- Pulls project information from the intake form +- Uses legal and fiscal signals to populate early‑outcome indicators + +### **7.2 Readiness Scoring** +- Shares data with the readiness engine (creditworthiness, fiscal health, governance) +- Tracks improvements over time + +### **7.3 Program‑Level Monitoring** +- Aggregates early outcomes across all SNGs +- Supports IDB Board reporting +- Provides evidence on pilot feasibility and scalability + +--- + +## 8. Data Sources + +The M&E module can ingest data from: +- CityCatalyst (land use, emissions, service coverage, risk exposure) +- SNG financial statements +- IDB internal systems +- Intake forms and readiness assessments +- Surveys and interviews (as needed) + +--- + +## 9. Summary + +This M&E module: + +- Aligns with Annex IV +- Supports the Control Tower’s real‑time monitoring vision +- Helps SNGs understand and improve their readiness +- Provides IDB with the evidence needed to evaluate the pilot +- Integrates cleanly with intake and readiness scoring +- Is simple enough to implement in a hackday prototype + +It is both **rigorous** (for IDB) and **practical** (for cities). diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/SPEC.md b/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/SPEC.md similarity index 100% rename from events/2026-06-11-unlock-the-money/justagiraffe/SPEC.md rename to events/2026-06-11-unlock-the-money/justagiraffe/control-tower/SPEC.md diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/diagrams/5a-integrated-architecture.svg b/events/2026-06-11-unlock-the-money/justagiraffe/diagrams/5a-integrated-architecture.svg new file mode 100644 index 0000000..0be3918 --- /dev/null +++ b/events/2026-06-11-unlock-the-money/justagiraffe/diagrams/5a-integrated-architecture.svg @@ -0,0 +1,66 @@ + +Revised 5a integrated architecture +CityCatalyst as host infrastructure; Project Preparator and City Readiness Navigator as peer modules; the Navigator is a three-step vertical (entity creditworthiness, readiness pathways/coaching, portfolio and pooling); capacity building is a standalone support track; funder pipelines at the bottom. + + + + +Integrated architecture — 5a (City Readiness Navigator) + + +CityCatalyst — host & shared context (infrastructure) +HIAP prioritized actions +GHG inventory · CCRA risk +AI agents · MCP (shared) + + +Project Preparator — module on CityCatalyst + +Project bankability (Tech/Fin/Pol) +→ Concept Note + +Fiscal Data Adapters · CAPAG / SINIM + map +Matching & Pooling — core service + + +Capacity building / PPF +standalone support · entity or project + + +City Readiness Navigator — entity / portfolio (one vertical) + +① Entity creditworthiness +diagnose for chosen instrument + +② Readiness pathways +close the gap · coach to funder reqs +(IDB SFP first) + +③ Portfolio & pooling → submit +pool only if sub-scale +→ dossier + + + + +Funder pipelines +IDB Control Tower · Intake & Triage · Readiness Scoring · M&E & Board +Other funders · BNDES / CCFLA + + + +Concept Note · Path A + +Path B · entity-first + + +not ready → gap + +dossier + + +CityCatalyst (host) +Preparator +Navigator +services / funders + diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/diagrams/README.md b/events/2026-06-11-unlock-the-money/justagiraffe/diagrams/README.md new file mode 100644 index 0000000..80eda4f --- /dev/null +++ b/events/2026-06-11-unlock-the-money/justagiraffe/diagrams/README.md @@ -0,0 +1,16 @@ +# Diagrams — integrated architecture (hack-day visuals) + +Standalone SVGs (open in a browser, screenshot for slides). The mermaid in +[`../INTEGRATED-ARCHITECTURE.md`](../INTEGRATED-ARCHITECTURE.md) §5a is the canonical, +GitHub-rendering source of truth; these are the polished versions for presenting. + +| File | What it shows | Pairs with | +|---|---|---| +| [`5a-integrated-architecture.svg`](5a-integrated-architecture.svg) | Module-boundary view: CityCatalyst host, **Preparator & Navigator as peer modules**, the Navigator's **three-step vertical** (① creditworthiness → ② readiness pathways/coaching → ③ portfolio & pooling), **standalone** capacity building, funder pipelines. | `INTEGRATED-ARCHITECTURE.md` §5a | +| [`process-timeline.svg`](process-timeline.svg) | Pipeline view: the top-to-bottom process (Source → Readiness pathways → Portfolio → Funder intake) with Path A / Path B and the shared-services rail (AI agents, Matching+Pooling, Fiscal adapters). | `ITERATION-2.1-PLAN.md` §F-7, §F-1, §G | + +> The `process-timeline` SVG is a rebuild of a diagram that previously existed only as an +> in-session rendered artifact (never committed) — now persisted so it survives. + +Colors are consistent across both: **CityCatalyst** (purple/indigo) · **Preparator** (blue) · +**Navigator** (teal/green) · **services & funders** (gray). diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/diagrams/process-timeline.svg b/events/2026-06-11-unlock-the-money/justagiraffe/diagrams/process-timeline.svg new file mode 100644 index 0000000..d6a9080 --- /dev/null +++ b/events/2026-06-11-unlock-the-money/justagiraffe/diagrams/process-timeline.svg @@ -0,0 +1,65 @@ + +Process timeline — readiness pipeline and shared services +A top-to-bottom process (Source, Readiness pathways, Portfolio, Funder intake) running through CityCatalyst, the Navigator's readiness pathways with Path A (Preparator) and Path B (entity creditworthiness), portfolio and pooling, and the IDB Control Tower — with AI agents, Matching+Pooling, and Fiscal adapters as shared services on the right. + + + + + +PROCESS +SHARED SERVICES + + + +Source +Readiness pathways +Portfolio +Funder intake + + + +CityCatalyst +GHG inventory · HIAP actions · CCRA risk + + +Readiness pathways +assess, then route → ready · capacity-building · pool +Project bankability · Preparator → Portfolio · Path A +① Entity creditworthiness · CAPAG · SINIM · map · Path B + + +② Portfolio & pooling → submit +pool to reach the instrument's ticket size + + +IDB Control Tower +Intake & Triage · Readiness Scoring · M&E & Board + + + +AI agents +shared context (MCP) + +Matching + Pooling +core service + +Fiscal adapters +CAPAG · SINIM · map + + + + + +dossier + + + + + + + +CityCatalyst +Preparator +Navigator +funders / services + diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/IDB cities regions - Document proposal - Public.pdf b/events/2026-06-11-unlock-the-money/justagiraffe/reference/IDB cities regions - Document proposal - Public.pdf similarity index 100% rename from events/2026-06-11-unlock-the-money/justagiraffe/IDB cities regions - Document proposal - Public.pdf rename to events/2026-06-11-unlock-the-money/justagiraffe/reference/IDB cities regions - Document proposal - Public.pdf diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/idb.txt b/events/2026-06-11-unlock-the-money/justagiraffe/reference/idb.txt similarity index 100% rename from events/2026-06-11-unlock-the-money/justagiraffe/idb.txt rename to events/2026-06-11-unlock-the-money/justagiraffe/reference/idb.txt diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/teammembers.md b/events/2026-06-11-unlock-the-money/justagiraffe/reference/teammembers.md similarity index 100% rename from events/2026-06-11-unlock-the-money/justagiraffe/teammembers.md rename to events/2026-06-11-unlock-the-money/justagiraffe/reference/teammembers.md From 540707b3dc643a387d8afe39432dbe5c1b6263a3 Mon Sep 17 00:00:00 2001 From: Martin Wainstein Date: Mon, 15 Jun 2026 00:59:31 -0600 Subject: [PATCH 09/14] Organize justagiraffe branch + fold in Mirco's M&E framework MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add README.md as the branch map (reading order, the two apps and where each lives, canonical vs superseded, the one-line model). - archive/ ← ITERATION-2-PLAN.md (superseded), ROADMAP.md (historical) - reference/ ← IDB program PDF, idb.txt, teammembers.md - control-tower/ ← SPEC.md + IMPLEMENTATION_PLAN.md (the app's own docs; fixes SPEC's relative links) and Mirco's M&E framework (Monitoring_Evaluation.md, MandE-questions.md) brought over from justagiraffe/mr/working-branch so his work is present on this branch. - Fix all internal links affected by the moves; drop vestigial .gitkeep. Note: Mirco's control-tower index.html/scoring.js edits were NOT merged — this branch's scoring.js is the newer profile-driven engine, and his versions contained no M&E-unique logic (the M&E substance is the two .md files above). His code edits are superseded, not lost. Co-Authored-By: Claude Opus 4.8 --- .../justagiraffe/ITERATION-2.1-PLAN.md | 2 +- .../justagiraffe/README.md | 70 +++++++++++++++++++ .../justagiraffe/archive/ROADMAP.md | 2 +- .../control-tower/IMPLEMENTATION_PLAN.md | 6 +- .../justagiraffe/control-tower/SPEC.md | 2 +- 5 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 events/2026-06-11-unlock-the-money/justagiraffe/README.md diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/ITERATION-2.1-PLAN.md b/events/2026-06-11-unlock-the-money/justagiraffe/ITERATION-2.1-PLAN.md index fef5cd2..edd96c5 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/ITERATION-2.1-PLAN.md +++ b/events/2026-06-11-unlock-the-money/justagiraffe/ITERATION-2.1-PLAN.md @@ -1,6 +1,6 @@ # Iteration 2.1 — City Readiness Navigator + SFP Control Tower upgrade -**Supersedes:** [`ITERATION-2-PLAN.md`](ITERATION-2-PLAN.md) (all its points still hold; +**Supersedes:** [`ITERATION-2-PLAN.md`](archive/ITERATION-2-PLAN.md) (all its points still hold; this refines them with the integrated architecture). **Reads with:** [`INTEGRATED-ARCHITECTURE.md`](INTEGRATED-ARCHITECTURE.md). **Why 2.1:** after reviewing the **Project Preparator** POC, the **CAPAG** project (Brazil diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/README.md b/events/2026-06-11-unlock-the-money/justagiraffe/README.md new file mode 100644 index 0000000..6a71362 --- /dev/null +++ b/events/2026-06-11-unlock-the-money/justagiraffe/README.md @@ -0,0 +1,70 @@ +# justagiraffe — "Unlock the Money" workstream + +**What this team is building:** the city→funder climate-finance chain, as **two runnable +apps on a shared readiness spine** plus the architecture that ties them (and the other +hackday modules) together. + +> **Start here →** read in this order: this file → [`INTEGRATED-ARCHITECTURE.md`](INTEGRATED-ARCHITECTURE.md) +> (the system map) → [`PRD-city-facing-readiness-app.md`](PRD-city-facing-readiness-app.md) +> (what the city app is) → [`ITERATION-2.1-PLAN.md`](ITERATION-2.1-PLAN.md) (what we're +> building now). The two diagrams in [`diagrams/`](diagrams/) are the 1-screen version. + +## The two apps + +| App | Faces | Lives in | Run | +|---|---|---|---| +| **City Readiness Navigator** | the **city** — match → readiness pathways → portfolio → submit | [`../apps/city-readiness-navigator/`](../apps/city-readiness-navigator/) | Next.js (`npm i && npm run dev`) | +| **SFP Control Tower** | the **IDB** — Intake & Triage · Readiness Scoring · M&E & Board | [`control-tower/`](control-tower/) | static — open `index.html` | + +They share a **readiness engine** (`readiness-profiles.js` + `scoring.js`). It currently +exists in **both** apps (`control-tower/` and `…/navigator/src/lib/readiness/`) — extracting +one shared `@oef/readiness` package is an open decision (architecture §8). + +## Folder layout + +``` +justagiraffe/ +├── README.md ← you are here (the map) +├── INTEGRATED-ARCHITECTURE.md canonical · system map (§5a diagram) +├── PRD-city-facing-readiness-app.md canonical · city app definition +├── ITERATION-2.1-PLAN.md canonical · current execution plan +├── diagrams/ polished SVGs for presenting +├── control-tower/ the IDB-facing app (code + its own docs + M&E) +├── archive/ superseded / historical (not current) +└── reference/ source material (IDB PDF, notes, team) +``` +The **city-facing app** lives outside this folder, in [`../apps/city-readiness-navigator/`](../apps/city-readiness-navigator/) (repo convention). + +## The documents + +**Canonical (current — read these):** +- [`INTEGRATED-ARCHITECTURE.md`](INTEGRATED-ARCHITECTURE.md) — how all modules fit (the system map; §5a diagram). +- [`PRD-city-facing-readiness-app.md`](PRD-city-facing-readiness-app.md) — the City Readiness Navigator product definition (the durable *what/why*). +- [`ITERATION-2.1-PLAN.md`](ITERATION-2.1-PLAN.md) — the current execution plan (the *how/now*). +- [`diagrams/`](diagrams/) — polished SVGs for presenting (5a module view + process timeline). + +**Control Tower (IDB-facing app) — in [`control-tower/`](control-tower/):** +- [`control-tower/README.md`](control-tower/README.md) — how the Control Tower works. +- [`control-tower/SPEC.md`](control-tower/SPEC.md) — product spec (next-iteration fidelity + IDB branding). +- [`control-tower/IMPLEMENTATION_PLAN.md`](control-tower/IMPLEMENTATION_PLAN.md) — split readiness from project review. +- [`control-tower/READINESS-PROFILES.md`](control-tower/READINESS-PROFILES.md) — the profile-driven scoring schema. +- [`control-tower/Monitoring_Evaluation.md`](control-tower/Monitoring_Evaluation.md) + [`control-tower/MandE-questions.md`](control-tower/MandE-questions.md) — **M&E framework** (Annex IV + forward-looking readiness), authored by Mirco. + +**Historical / superseded — in [`archive/`](archive/):** +- [`archive/ITERATION-2-PLAN.md`](archive/ITERATION-2-PLAN.md) — *superseded by* `ITERATION-2.1-PLAN.md`. +- [`archive/ROADMAP.md`](archive/ROADMAP.md) — original 24h hackday roadmap (11–12 Jun). + +**Source material / reference — in [`reference/`](reference/):** +- `reference/IDB cities regions - Document proposal - Public.pdf` — the IDB SFP program doc. +- `reference/idb.txt` — raw IDB notes. · `reference/teammembers.md` — team. + +## The model in one line + +Two readiness questions, kept modular: **is the _project_ bankable?** (Project Preparator) +vs. **is the _entity_ creditworthy for this instrument?** (this Navigator). A city enters from +either side; the Navigator adds creditworthiness + pooling and hands a **dossier** to the IDB +Control Tower. Full rationale in [`INTEGRATED-ARCHITECTURE.md`](INTEGRATED-ARCHITECTURE.md). + +--- +*Status (15 Jun 2026): both apps run locally; architecture + PRD reflect the v2.1 two-layer +reframe; Mirco's M&E framework folded into `control-tower/`; iteration 2.1 build in progress.* diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/archive/ROADMAP.md b/events/2026-06-11-unlock-the-money/justagiraffe/archive/ROADMAP.md index a13da13..9569b2c 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/archive/ROADMAP.md +++ b/events/2026-06-11-unlock-the-money/justagiraffe/archive/ROADMAP.md @@ -14,7 +14,7 @@ One control room for the IDB Subnational Finance Pilot: **intake** subnational p A working single-page dashboard over 63 mock candidate SNGs across 8 LAC countries with three connected views — **Intake & Triage** (pipeline kanban), **Readiness Scoring** (transparent weighted model + per-candidate file), and **M&E & Board** (indicators vs. milestone timeline). Ugly-but-real beats a slide. -> A runnable scaffold already exists in `control-tower/` — open `index.html`. The plan below is about turning that skeleton into a confident 5-minute demo, not starting from zero. +> A runnable scaffold already exists in `../control-tower/` — open `index.html`. The plan below is about turning that skeleton into a confident 5-minute demo, not starting from zero. --- diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/IMPLEMENTATION_PLAN.md b/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/IMPLEMENTATION_PLAN.md index b85de6b..e28867d 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/IMPLEMENTATION_PLAN.md +++ b/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/IMPLEMENTATION_PLAN.md @@ -15,7 +15,7 @@ This turns readiness into the first filter and moves project-level proposal deta ### Current Issue -Today, `control-tower/index.html` defines proposal stages as: +Today, `index.html` defines proposal stages as: ```js const STAGES = ["Intake","Screening","Readiness Review","Structuring","Board Pipeline"]; @@ -164,7 +164,7 @@ Future production model should support multiple proposals per SNG, because one c ### 1. Make Readiness Scoring the First Tab -Change navigation order in `control-tower/index.html`: +Change navigation order in `index.html`: Current: @@ -406,7 +406,7 @@ This makes the Board story clearer: the pilot is not only tracking projects, it ### Phase 4: Demo Story and Docs - Update `SPEC.md` to reflect the two-stage model. -- Update `ROADMAP.md` demo script: +- Update `../archive/ROADMAP.md` demo script: 1. Readiness Scoring: "Which cities are ready?" 2. Project Review: "For ready cities, which projects advance?" 3. M&E & Board: "Is the pilot proving itself?" diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/SPEC.md b/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/SPEC.md index 025d083..3418bcd 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/SPEC.md +++ b/events/2026-06-11-unlock-the-money/justagiraffe/control-tower/SPEC.md @@ -1,7 +1,7 @@ # Sub-Sovereign Pilot Control Tower — Product Specification **Status:** Hackday prototype (working scaffold) · **Audience:** the Claude Code session that will improve this app -**Inputs you should load alongside this spec:** `index.html`, `scoring.js`, `data/sngs.js`, and the IDB program PDF (`IDB cities regions - Document proposal - Public.pdf`). +**Inputs you should load alongside this spec:** `index.html`, `scoring.js`, `data/sngs.js`, and the IDB program PDF (`../reference/IDB cities regions - Document proposal - Public.pdf`). **Goal of the next iteration:** deepen the app's fidelity to the real IDB program, polish each of the three features, and re-skin the UI in **IDB branding** (reference https://www.iadb.org/en). --- From ec14db0e2bf217ad17675402ad3d22647d8299e0 Mon Sep 17 00:00:00 2001 From: Martin Wainstein Date: Mon, 15 Jun 2026 01:17:57 -0600 Subject: [PATCH 10/14] Consolidate both apps under justagiraffe/ (move Navigator out of apps/) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The team folder is now self-contained: city-readiness-navigator/ and control-tower/ sit as siblings under justagiraffe/, alongside the docs. Rationale: there is no workspace/build tooling that requires apps/ (it's an inconsistently-followed convention — civic-climate-action split the same way on main), and main is shared by every team's branch, so a single team-named folder avoids collisions and reviews as one unit. - git mv apps/city-readiness-navigator -> justagiraffe/city-readiness-navigator - Fix path refs in README, INTEGRATED-ARCHITECTURE, and the app's own README. - apps/ now holds only the shared _template. Co-Authored-By: Claude Opus 4.8 --- .../justagiraffe/INTEGRATED-ARCHITECTURE.md | 2 +- events/2026-06-11-unlock-the-money/justagiraffe/README.md | 8 +++++--- .../city-readiness-navigator/.gitignore | 0 .../city-readiness-navigator/README.md | 2 +- .../city-readiness-navigator/data/README.md | 0 .../city-readiness-navigator/data/source/capag_rs.json | 0 .../data/source/centroids_rs.json | 0 .../data/source/comuna_capacity_scores_u11.csv | 0 .../data/source/coordination_units_u11.csv | 0 .../data/source/unit_bundle_candidates_u11.csv | 0 .../data/source/valdivia_action_matches.csv | 0 .../data/source/valdivia_funders_open.csv | 0 .../city-readiness-navigator/next.config.mjs | 0 .../city-readiness-navigator/package-lock.json | 0 .../city-readiness-navigator/package.json | 0 .../city-readiness-navigator/scripts/build-brazil.mjs | 0 .../city-readiness-navigator/scripts/build-data.mjs | 0 .../src/app/api/submissions/route.ts | 0 .../city-readiness-navigator/src/app/globals.css | 0 .../city-readiness-navigator/src/app/layout.tsx | 0 .../city-readiness-navigator/src/app/page.tsx | 0 .../city-readiness-navigator/src/app/pipeline/page.tsx | 0 .../city-readiness-navigator/src/components/MapView.tsx | 0 .../city-readiness-navigator/src/components/Sidebar.tsx | 0 .../city-readiness-navigator/src/data/brazil.json | 0 .../city-readiness-navigator/src/data/valdivia.json | 0 .../city-readiness-navigator/src/lib/adapters.ts | 0 .../city-readiness-navigator/src/lib/context.ts | 0 .../city-readiness-navigator/src/lib/dossier.ts | 0 .../city-readiness-navigator/src/lib/engine.ts | 0 .../src/lib/readiness/readiness-profiles.d.ts | 0 .../src/lib/readiness/readiness-profiles.js | 0 .../src/lib/readiness/scoring.d.ts | 0 .../city-readiness-navigator/src/lib/readiness/scoring.js | 0 .../city-readiness-navigator/src/lib/store.ts | 0 .../city-readiness-navigator/tsconfig.json | 0 36 files changed, 7 insertions(+), 5 deletions(-) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/.gitignore (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/README.md (97%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/data/README.md (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/data/source/capag_rs.json (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/data/source/centroids_rs.json (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/data/source/comuna_capacity_scores_u11.csv (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/data/source/coordination_units_u11.csv (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/data/source/unit_bundle_candidates_u11.csv (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/data/source/valdivia_action_matches.csv (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/data/source/valdivia_funders_open.csv (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/next.config.mjs (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/package-lock.json (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/package.json (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/scripts/build-brazil.mjs (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/scripts/build-data.mjs (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/app/api/submissions/route.ts (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/app/globals.css (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/app/layout.tsx (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/app/page.tsx (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/app/pipeline/page.tsx (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/components/MapView.tsx (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/components/Sidebar.tsx (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/data/brazil.json (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/data/valdivia.json (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/lib/adapters.ts (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/lib/context.ts (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/lib/dossier.ts (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/lib/engine.ts (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/lib/readiness/readiness-profiles.d.ts (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/lib/readiness/readiness-profiles.js (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/lib/readiness/scoring.d.ts (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/lib/readiness/scoring.js (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/src/lib/store.ts (100%) rename events/2026-06-11-unlock-the-money/{apps => justagiraffe}/city-readiness-navigator/tsconfig.json (100%) diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/INTEGRATED-ARCHITECTURE.md b/events/2026-06-11-unlock-the-money/justagiraffe/INTEGRATED-ARCHITECTURE.md index 91b169b..b379c5d 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/INTEGRATED-ARCHITECTURE.md +++ b/events/2026-06-11-unlock-the-money/justagiraffe/INTEGRATED-ARCHITECTURE.md @@ -34,7 +34,7 @@ projects and adds creditworthiness + pooling + the funder handoff. | **CityCatalyst** | `Open-Earth-Foundation/CityCatalyst` | Host: GHG inventory, **HIAP** (prioritized actions), CCRA risk, Journey Navigator module catalog, OAuth, Global API | Production | | **Project Preparator** | `joaquinOEF/NBS-Project-Preparation` | Project bankability (Tech/Fin/Pol), project-funder matching, Concept Note | POC | | **justagiraffe Control Tower** | hackdays `justagiraffe/control-tower` | IDB-facing: Intake & Triage, Readiness Scoring (profile-driven engine), Results/Board | Hackday | -| **City Readiness Navigator** | hackdays `apps/city-readiness-navigator` | City-facing: the 7-step journey; entity readiness + pooling + submit | Hackday (ours) | +| **City Readiness Navigator** | hackdays `justagiraffe/city-readiness-navigator` | City-facing: the 7-step journey; entity readiness + pooling + submit | Hackday (ours) | | **City-Funder Matching Engine** | hackdays `city–funder-matching` + `apps/funder-scan` | **Chile** capacity (SINIM/FCM), action→funder matching, **pooling/aggregation** | Hackday | | **CAPAG Funder Scan** | hackdays `apps/capag-funder-scan` | **Brazil** creditworthiness (Treasury CAPAG A/B/C/D for 5,570 munis) | Hackday | | **Political-will signal** | hackdays `codex/8-political-will-score` | LLM-derived governance/political-will sub-score from news/articles | Hackday (early) | diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/README.md b/events/2026-06-11-unlock-the-money/justagiraffe/README.md index 6a71362..82414f3 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/README.md +++ b/events/2026-06-11-unlock-the-money/justagiraffe/README.md @@ -13,7 +13,7 @@ hackday modules) together. | App | Faces | Lives in | Run | |---|---|---|---| -| **City Readiness Navigator** | the **city** — match → readiness pathways → portfolio → submit | [`../apps/city-readiness-navigator/`](../apps/city-readiness-navigator/) | Next.js (`npm i && npm run dev`) | +| **City Readiness Navigator** | the **city** — match → readiness pathways → portfolio → submit | [`city-readiness-navigator/`](city-readiness-navigator/) | Next.js (`npm i && npm run dev`) | | **SFP Control Tower** | the **IDB** — Intake & Triage · Readiness Scoring · M&E & Board | [`control-tower/`](control-tower/) | static — open `index.html` | They share a **readiness engine** (`readiness-profiles.js` + `scoring.js`). It currently @@ -23,17 +23,19 @@ one shared `@oef/readiness` package is an open decision (architecture §8). ## Folder layout ``` -justagiraffe/ +justagiraffe/ everything the team builds lives here ├── README.md ← you are here (the map) ├── INTEGRATED-ARCHITECTURE.md canonical · system map (§5a diagram) ├── PRD-city-facing-readiness-app.md canonical · city app definition ├── ITERATION-2.1-PLAN.md canonical · current execution plan ├── diagrams/ polished SVGs for presenting +├── city-readiness-navigator/ the city-facing app (Next.js) ├── control-tower/ the IDB-facing app (code + its own docs + M&E) ├── archive/ superseded / historical (not current) └── reference/ source material (IDB PDF, notes, team) ``` -The **city-facing app** lives outside this folder, in [`../apps/city-readiness-navigator/`](../apps/city-readiness-navigator/) (repo convention). +Both apps are siblings under `justagiraffe/` — the team folder is self-contained +(no team code outside it), which keeps things clean when branches merge to `main`. ## The documents diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/.gitignore b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/.gitignore similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/.gitignore rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/.gitignore diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/README.md b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/README.md similarity index 97% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/README.md rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/README.md index 8d381d7..f6aa033 100644 --- a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/README.md +++ b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/README.md @@ -13,7 +13,7 @@ embed (OAuth, live city context, HIAP) is Phase 4. ## Run it ```bash -cd events/2026-06-11-unlock-the-money/apps/city-readiness-navigator +cd events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator npm install npm run dev # open http://localhost:3000 diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/README.md b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/README.md similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/README.md rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/README.md diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/source/capag_rs.json b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/source/capag_rs.json similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/source/capag_rs.json rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/source/capag_rs.json diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/source/centroids_rs.json b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/source/centroids_rs.json similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/source/centroids_rs.json rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/source/centroids_rs.json diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/source/comuna_capacity_scores_u11.csv b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/source/comuna_capacity_scores_u11.csv similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/source/comuna_capacity_scores_u11.csv rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/source/comuna_capacity_scores_u11.csv diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/source/coordination_units_u11.csv b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/source/coordination_units_u11.csv similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/source/coordination_units_u11.csv rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/source/coordination_units_u11.csv diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/source/unit_bundle_candidates_u11.csv b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/source/unit_bundle_candidates_u11.csv similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/source/unit_bundle_candidates_u11.csv rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/source/unit_bundle_candidates_u11.csv diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/source/valdivia_action_matches.csv b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/source/valdivia_action_matches.csv similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/source/valdivia_action_matches.csv rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/source/valdivia_action_matches.csv diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/source/valdivia_funders_open.csv b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/source/valdivia_funders_open.csv similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/data/source/valdivia_funders_open.csv rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/data/source/valdivia_funders_open.csv diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/next.config.mjs b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/next.config.mjs similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/next.config.mjs rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/next.config.mjs diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/package-lock.json b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/package-lock.json similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/package-lock.json rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/package-lock.json diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/package.json b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/package.json similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/package.json rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/package.json diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/scripts/build-brazil.mjs b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/scripts/build-brazil.mjs similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/scripts/build-brazil.mjs rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/scripts/build-brazil.mjs diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/scripts/build-data.mjs b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/scripts/build-data.mjs similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/scripts/build-data.mjs rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/scripts/build-data.mjs diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/api/submissions/route.ts b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/api/submissions/route.ts similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/api/submissions/route.ts rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/api/submissions/route.ts diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/globals.css b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/globals.css similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/globals.css rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/globals.css diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/layout.tsx b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/layout.tsx similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/layout.tsx rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/layout.tsx diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/page.tsx b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/page.tsx similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/page.tsx rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/page.tsx diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/pipeline/page.tsx b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/pipeline/page.tsx similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/app/pipeline/page.tsx rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/pipeline/page.tsx diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/components/MapView.tsx b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/components/MapView.tsx similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/components/MapView.tsx rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/components/MapView.tsx diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/components/Sidebar.tsx b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/components/Sidebar.tsx similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/components/Sidebar.tsx rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/components/Sidebar.tsx diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/data/brazil.json b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/data/brazil.json similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/data/brazil.json rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/data/brazil.json diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/data/valdivia.json b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/data/valdivia.json similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/data/valdivia.json rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/data/valdivia.json diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/adapters.ts b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/adapters.ts similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/adapters.ts rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/adapters.ts diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/context.ts b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/context.ts similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/context.ts rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/context.ts diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/dossier.ts b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/dossier.ts similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/dossier.ts rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/dossier.ts diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/engine.ts b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/engine.ts similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/engine.ts rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/engine.ts diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/readiness/readiness-profiles.d.ts b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/readiness/readiness-profiles.d.ts similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/readiness/readiness-profiles.d.ts rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/readiness/readiness-profiles.d.ts diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/readiness/readiness-profiles.js b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/readiness/readiness-profiles.js similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/readiness/readiness-profiles.js rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/readiness/readiness-profiles.js diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/readiness/scoring.d.ts b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/readiness/scoring.d.ts similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/readiness/scoring.d.ts rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/readiness/scoring.d.ts diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/readiness/scoring.js b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/readiness/scoring.js similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/readiness/scoring.js rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/readiness/scoring.js diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/store.ts b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/store.ts similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/src/lib/store.ts rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/store.ts diff --git a/events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/tsconfig.json b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/tsconfig.json similarity index 100% rename from events/2026-06-11-unlock-the-money/apps/city-readiness-navigator/tsconfig.json rename to events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/tsconfig.json From 91a47f546182f7d56cfe1d504e9ce28cbad042b8 Mon Sep 17 00:00:00 2001 From: Martin Wainstein Date: Mon, 15 Jun 2026 01:27:17 -0600 Subject: [PATCH 11/14] Navigator v2.2: instrument-selection step, enriched context, state layer, intra/cross portfolio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From Martin's v2.1 review: - New 'Choose instrument' step between context and readiness ('readiness against whom?') — IDB SFP card with the 'direct line' eligibility note; entity- vs project-first framing; CAF/WB/GCF as template. - Explore: upstream 'identity & context come from CityCatalyst' framing; a State/region vs Cities view toggle with a region readiness summary; a data-source toggle (current source + 'Import data…'). - City context enriched: GHG inventory + CCRA + HIAP + climate plan; project-first shows an 'import project from Preparator' affordance. - Portfolio now distinguishes INTRA-city (the city's own project pipeline pooled to the ticket) vs CROSS-city pooling (with neighbours, showing their readiness). - Six-stage left menu; dossier/submit handle all three pathways. Co-Authored-By: Claude Opus 4.8 --- .../city-readiness-navigator/src/app/page.tsx | 234 ++++++++++++------ .../src/lib/context.ts | 34 ++- 2 files changed, 183 insertions(+), 85 deletions(-) diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/page.tsx b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/page.tsx index f582e1c..47675e0 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/page.tsx +++ b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/page.tsx @@ -10,10 +10,11 @@ import { getCityContext, agentAssist } from "@/lib/context"; import { assembleDossier } from "@/lib/dossier"; const STAGES: StageDef[] = [ - { key: "explore", title: "Explore", sub: "Map & scope" }, - { key: "context", title: "City context", sub: "Source: inventory + plan" }, + { key: "explore", title: "Explore", sub: "Region & data" }, + { key: "context", title: "City context", sub: "From CityCatalyst" }, + { key: "instrument", title: "Choose instrument", sub: "Readiness for whom" }, { key: "readiness", title: "Readiness pathways", sub: "Assess & route" }, - { key: "portfolio", title: "Portfolio", sub: "Instrument · pool · prepare" }, + { key: "portfolio", title: "Portfolio", sub: "Reach the ticket" }, { key: "intake", title: "Funder intake", sub: "Dossier & submit" }, ]; @@ -48,8 +49,11 @@ function pathwayOf(s: Scored): "instrument" | "pool" | "capacity-building" { export default function Page() { const [scopeId, setScopeId] = useState("cl-losrios"); + const [viewLevel, setViewLevel] = useState<"cities" | "state">("cities"); const [cityId, setCityId] = useState(null); const [entry, setEntry] = useState<"entity" | "project">("entity"); + const [instrument, setInstrument] = useState(null); + const [portfolioMode, setPortfolioMode] = useState<"intra" | "cross">("intra"); const [stage, setStage] = useState(0); const [maxReached, setMaxReached] = useState(0); const [submitState, setSubmitState] = useState<{ id: string } | null>(null); @@ -62,25 +66,36 @@ export default function Page() { const scored = cityId ? journeyCity(cityId) : null; const ctx = cityId ? getCityContext(cityId) : null; const pathway = scored ? pathwayOf(scored) : null; + + // Cross-city pool (Chile) and intra-city portfolio (the city's own projects). const pool = scopeId === "cl-losrios" ? DATA.cl.pool : null; const poolScored = scored && pool ? SM.scoreSNG({ ...(scored as any), proposal: pool.pooledProposal }) : null; + const intraTotal = ctx ? ctx.projects.reduce((a, p) => a + p.askUSDm, 0) : 0; + const intraScored = scored && ctx ? SM.scoreSNG({ ...(scored as any), proposal: { title: `${scored.name} climate portfolio`, sector: "multi-sector", askUSDm: intraTotal, stage: "Structuring", cofinance: true } }) : null; function goto(i: number) { setStage(i); setMaxReached((m) => Math.max(m, i)); } - function pickCity(id: string) { setCityId(id); setSubmitState(null); goto(1); } + function pickCity(id: string) { setCityId(id); setSubmitState(null); setInstrument(null); goto(1); } + + // Region-level summary (the "state layer"). + const regionSummary = useMemo(() => { + const counts: Record = {}; + for (const p of points) counts[p.tier] = (counts[p.tier] || 0) + 1; + return counts; + }, [points]); async function submit() { if (!scored || !pathway) return; setSubmitting(true); let opts: any; - if (pathway === "pool" && pool) { + if (pathway === "capacity-building") { + opts = { scored, kind: "city", pathway: "capacity-building", instrumentName: "Capacity-building / PPF + blended finance", pool: null, proposal: scored.proposal }; + } else if (portfolioMode === "cross" && pool) { opts = { scored: poolScored, kind: "pool", pathway: "pool", pool: { anchor: scored.name, members: pool.members.map((m: any) => ({ name: m.name, role: m.isAnchor ? "anchor" : "member", cofinance: m.cofinanceScore })) }, proposal: pool.pooledProposal }; - } else if (pathway === "capacity-building") { - opts = { scored, kind: "city", pathway: "capacity-building", instrumentName: "Capacity-building / PPF + blended finance", - pool: null, proposal: scored.proposal }; } else { - opts = { scored, kind: "city", pathway: "instrument", pool: null, proposal: scored.proposal }; + opts = { scored: intraScored, kind: "city", pathway: "instrument", pool: null, + proposal: { title: `${scored.name} climate portfolio (${ctx!.projects.length} projects)`, sector: "multi-sector", askUSDm: intraTotal, cofinance: true } }; } const dossier = assembleDossier(opts); const res = await fetch("/api/submissions", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(dossier) }); @@ -93,13 +108,14 @@ export default function Page() {
-
{scope.country} · {scope.region} · adapter: {scope.adapter}
+
{scope.country} · {scope.region} · adapter: {scope.adapter}{scored ? ` · ${scored.name}` : ""}
{/* 0 — EXPLORE */} {stage === 0 && ( <>
Explore financial readiness
-

A geographic view of readiness across a scope, from real national fiscal data. Pick a highlighted city to open its readiness journey.

+

Identity & context for a city come from CityCatalyst (inventory, CCRA, HIAP, plan). Here — for the demo — pick a region and a city to open its readiness journey.

+
{SCOPES.map((s) => ( ))}
+ +
+
+ + +
+ +
+
{legend.map((l) => {l.label})} - · data: {scope.adapter} -
-
-

Open a city

-

Cities with a full readiness profile in this scope:

- {points.filter((p) => p.journeyable).map((p) => ( -
- {p.name} · {p.capag ? `CAPAG ${p.capag}` : p.tier} - -
- ))}
+ + {viewLevel === "state" ? ( +
+

{scope.region} — region readiness summary

+

Aggregate across the region (from {scope.adapter}). Useful for a GORE / state / development bank scanning where to act.

+ {Object.entries(regionSummary).map(([t, n]) => ( +
{t}{n} {n === 1 ? "city" : "cities"}
+ ))} +
Switch to Cities to open an individual city's readiness journey.
+
+ ) : ( +
+

Open a city

+

Cities with a full readiness profile in this region:

+ {points.filter((p) => p.journeyable).map((p) => ( +
+ {p.name} · {p.capag ? `CAPAG ${p.capag}` : p.tier} + +
+ ))} +
+ )} )} @@ -129,39 +171,68 @@ export default function Page() { {stage === 1 && scored && ctx && ( <>
{scored.name}
-

Loaded from {scored.name}'s CityCatalyst context — GHG inventory and HIAP-prioritized actions. (Live CityCatalyst MCP wiring is the seam; here it's simulated context.)

+

Loaded from {scored.name}'s CityCatalyst context. (Live CityCatalyst MCP wiring is the seam; here it's simulated.)

- - + +

GHG inventory

{ctx.inventory.source} · {ctx.inventory.year}

- {ctx.inventory.topSectors.map((s) => ( -
{s.sector}{s.sharePct}%
- ))} + {ctx.inventory.topSectors.map((s) =>
{s.sector}{s.sharePct}%
)} +
+
+

CCRA — climate risk

+

{ctx.ccra.source}

+ {ctx.ccra.hazards.map((h) =>
{h.hazard}{h.risk}
)}

HIAP priorities

Top prioritized climate actions

- {ctx.hiap.map((a) => ( -
- {a.rank}. {a.name} - {a.type} -
- ))} + {ctx.hiap.map((a) =>
{a.rank}. {a.name}{a.type}
)} +
+
+

Climate plan

+

{ctx.plan.status}

+
Plan{ctx.plan.name}
+
Actions{ctx.plan.actionsCount}
+
Own project pipeline{ctx.projects.length} projects
{entry === "project" && ( -
Project-first: import a prepared project (a Concept Note from the Project Preparator) — it enters at the Portfolio step (②). For this demo the entity-first path is wired; project import is the interop seam.
+
Project-first: import a prepared project (a Concept Note from the Project Preparator) — it enters at the Portfolio step.
)} -
+
)} - {/* 2 — READINESS PATHWAYS */} + {/* 2 — CHOOSE INSTRUMENT */} {stage === 2 && scored && ( + <> +
Readiness against which instrument?
+

Readiness is instrument-specific — it depends on the funder, their institutional requirements, and the nature of the financial product. {entry === "entity" ? "Entity-first: a direct line for the city." : "Project-first: instruments that fund a specific project."}

+
{ setInstrument("idb-sfp"); SM.setActiveProfile("idb-sfp"); }}> +
+

Inter-American Development Bank — Sub-Sovereign Finance Program (SFP)

+ {instrument === "idb-sfp" && selected} +
+

Direct lending to subnational governments without a sovereign guarantee.

+
You may be eligible for a direct line from the IDB. Assess readiness against this instrument and program line.
+
+
+

CAF · World Bank · GCF template

+

Other MDBs plug in their own readiness profile — same engine, different criteria. (Illustrative for now.)

+
+ {entry === "project" && ( +
Project-first also surfaces grants & project-preparation facilities (PPFs) via the matching service / Project Preparator — for actions that aren't loan-shaped.
+ )} +
+ + )} + + {/* 3 — READINESS PATHWAYS */} + {stage === 3 && scored && ( <>
Readiness pathways

The early creditworthiness assessment for the {SM.activeProfile().instrument}, scored on real fiscal data. The diagnosis routes the next step.

@@ -183,20 +254,20 @@ export default function Page() {

Recommended pathway

- {pathway === "instrument" &&

Ready and eligible — proceed directly to the instrument.

} - {pathway === "pool" &&

Ready, but sub-scale. {scored.name} clears creditworthiness, but its project is below the instrument's ticket size. Route → portfolio / pooling.

} - {pathway === "capacity-building" &&

Not yet eligible. Route → capacity-building: targeted TC / PPF before the instrument. Not a debt problem — see the signals.

} + {pathway === "instrument" &&

Ready and eligible — proceed to the instrument.

} + {pathway === "pool" &&

Ready, but a single project is sub-scale. Reach the ticket size via a portfolio — the city's own projects, or pooling with neighbours.

} + {pathway === "capacity-building" &&

Not yet eligible. Route → capacity-building before the instrument. Not a debt problem — see the signals.

}
{(() => { const a = agentAssist({ cityName: scored.name, tier: scored.tier, cleared: scored.canEnterProjectReview, pathway: pathway! }); return
CityCatalyst agent simulated
{a.text}
; })()} -
+
)} - {/* 3 — PORTFOLIO / CAPACITY */} - {stage === 3 && scored && ( + {/* 4 — PORTFOLIO / CAPACITY */} + {stage === 4 && scored && ctx && ( <> {pathway === "capacity-building" ? ( <> @@ -219,54 +290,63 @@ export default function Page() {
Grant / blended finance for adaptation nowCCFLA / blended
Once the city re-rates (CAPAG B/A), it re-enters the instrument path. Submitting here registers a capacity-building referral, not a loan.
-
+
- ) : pathway === "pool" && pool ? ( + ) : ( <>
Build a financeable portfolio
-

The gap between {scored.name}'s project and the instrument's ticket size is closed by pooling neighbours into one package — portfolio design.

-
Transport: {DATA.cl.transportGap.nActions} actions, best single-city fit {DATA.cl.transportGap.bestFit} — no instrument fits {scored.name} alone.
-
- - - - {(DATA.cl.comunas as Comuna[]).map((c) => { - const cs = SM.scoreSNG(c); - return ; - })} - -
ComunaCo-finance indexReadinessRole
{c.name}{c.cofinanceScore ?? "—"} /100{cs.tier}{c.isAnchor ? Anchor : Member}
-
-
Pooled askUS${pool.pooledProposal.askUSDm}M
-
Pool readiness{poolScored!.tier} · {poolScored!.eligibility.eligible ? "eligible ✓" : "not eligible"}
-
+

A single project is below the {SM.activeProfile().funder} ticket size. Two ways to reach it:

+
+ +
-
- - ) : ( - <> -
Instrument
-

{scored.name} is ready and eligible — proceed to the instrument.

-
Instrument{SM.activeProfile().instrument}
AskUS${scored.proposal.askUSDm}M
-
+ + {portfolioMode === "intra" ? ( +
+

{scored.name}'s own projects

+

Bundle the city's own pipeline into one financeable portfolio — a single creditworthy borrower.

+ + + {ctx.projects.map((p) => )} +
ProjectSectorAsk
{p.title}{p.sector}US${p.askUSDm}M
+
+
Portfolio askUS${intraTotal}M
+
Readiness{intraScored!.tier} · {intraScored!.eligibility.eligible ? "eligible ✓" : "not eligible"}
+
+
+ ) : ( +
+

Pool with neighbouring cities

+

Pool credit lines across cities — {scored.name} anchors; small comunas ride the anchor. Other cities' readiness shown.

+ + + {(DATA.cl.comunas as Comuna[]).map((c) => { const cs = SM.scoreSNG(c); return ; })} +
CityCo-financeReadinessRole
{c.name}{c.cofinanceScore ?? "—"} /100{cs.tier}{c.isAnchor ? Anchor : Member}
+
+
Pooled askUS${pool!.pooledProposal.askUSDm}M
+
Pool readiness{poolScored!.tier} · {poolScored!.eligibility.eligible ? "eligible ✓" : "not eligible"}
+
+
+ )} +
{portfolioMode === "intra" ? "Intra-city: one ready city, its own projects — cleanest path to the ticket." : "Cross-city: a pooled pipeline for a region / development bank — the deal that no single small city could reach alone."}
+
)} )} - {/* 4 — FUNDER INTAKE */} - {stage === 4 && scored && pathway && ( + {/* 5 — FUNDER INTAKE */} + {stage === 5 && scored && pathway && ( <>
Funder intake
{!submitState ? ( <> -

Assemble the machine-readable candidate dossier (Concept Note + creditworthiness + instrument + pool) and submit it to the funder's pipeline.

+

Assemble the machine-readable candidate dossier (Concept Note + creditworthiness + portfolio) and submit it to the funder's pipeline.

-
Candidate{pathway === "pool" ? `${scored.name} pool (6 comunas)` : scored.name}
-
Pathway{pathway}
+
Candidate{pathway === "capacity-building" ? scored.name : portfolioMode === "cross" ? `${scored.name} pool (6 cities)` : `${scored.name} portfolio (${ctx!.projects.length} projects)`}
+
Pathway{pathway === "capacity-building" ? "capacity-building" : portfolioMode === "cross" ? "cross-city pool" : "intra-city portfolio"}
Target{pathway === "capacity-building" ? "Capacity-building / PPF" : SM.activeProfile().instrument}
-
Readiness{(pathway === "pool" ? poolScored! : scored).compositeReadiness} · {(pathway === "pool" ? poolScored! : scored).tier}
-
AskUS${pathway === "pool" ? pool.pooledProposal.askUSDm : scored.proposal.askUSDm}M
+
AskUS${pathway === "capacity-building" ? scored.proposal.askUSDm : portfolioMode === "cross" ? pool!.pooledProposal.askUSDm : intraTotal}M
@@ -275,7 +355,7 @@ export default function Page() { ) : ( <>

Submitted — the dossier is now on the funder's side of the screen.

-
{submitState.id} — {scored.name} ({pathway}) is in the funder pipeline.
+
{submitState.id} — {scored.name} is in the funder pipeline.
See it in the funder pipeline →
)} diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/context.ts b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/context.ts index 2ec7b58..1b751e6 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/context.ts +++ b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/context.ts @@ -1,13 +1,16 @@ // CityCatalyst context provider — the AI-agent / shared-context SEAM. -// Today this returns simulated context (inventory + HIAP) and a canned "agent -// assist". In production these calls go to CityCatalyst's MCP / agent layer -// (get_city_profile, get_inventory_emissions, HIAP get_prioritization) so context -// is shared across modules. Keep this interface stable; swap the body for live MCP. +// Today this returns simulated context (identity + inventory + CCRA + HIAP + plan) +// and a canned "agent assist". In production these calls go to CityCatalyst's MCP / +// agent layer so context is shared across modules. Keep this interface stable. export interface CityContext { cityId: string; inventory: { topSectors: { sector: string; sharePct: number }[]; year: number; source: string }; + ccra: { hazards: { hazard: string; risk: "high" | "medium" | "low" }[]; source: string }; hiap: { actionId: string; name: string; sector: string; type: "mitigation" | "adaptation"; rank: number }[]; + plan: { name: string; status: string; actionsCount: number }; + // the city's own project pipeline — for an INTRA-city portfolio + projects: { title: string; sector: string; askUSDm: number }[]; source: "simulated" | "citycatalyst-mcp"; } @@ -18,11 +21,21 @@ const CONTEXT: Record = { inventory: { year: 2022, source: "CityCatalyst GHGI (simulated)", topSectors: [ { sector: "Transportation", sharePct: 38 }, { sector: "Stationary energy", sharePct: 31 }, { sector: "Waste", sharePct: 19 }, ] }, + ccra: { source: "CityCatalyst CCRA (simulated)", hazards: [ + { hazard: "River / coastal flooding", risk: "high" }, { hazard: "Wildfire", risk: "medium" }, { hazard: "Water scarcity", risk: "medium" }, + ] }, hiap: [ { actionId: "c40_0023", name: "Adopt zero-emission bus fleets", sector: "transportation", type: "mitigation", rank: 1 }, { actionId: "ipcc_0001", name: "Transit-oriented development", sector: "transportation", type: "mitigation", rank: 2 }, { actionId: "ipcc_0105", name: "Active mobility / road space reallocation", sector: "transportation", type: "mitigation", rank: 3 }, ], + plan: { name: "Valdivia Climate Action Plan", status: "Adopted 2023", actionsCount: 102 }, + projects: [ + { title: "Zero-emission transport (e-bus + BRT)", sector: "transport", askUSDm: 8 }, + { title: "Organic waste & biogas", sector: "waste", askUSDm: 6 }, + { title: "Riverfront flood resilience", sector: "water", askUSDm: 9 }, + { title: "Municipal building energy retrofit", sector: "energy", askUSDm: 5 }, + ], source: "simulated", }, // Canoas (Brazil) @@ -31,11 +44,18 @@ const CONTEXT: Record = { inventory: { year: 2022, source: "CityCatalyst GHGI (simulated)", topSectors: [ { sector: "Stationary energy", sharePct: 41 }, { sector: "Transportation", sharePct: 27 }, { sector: "Waste", sharePct: 21 }, ] }, + ccra: { source: "CityCatalyst CCRA (simulated)", hazards: [ + { hazard: "River flooding (Guaíba basin)", risk: "high" }, { hazard: "Extreme rainfall", risk: "high" }, { hazard: "Heat stress", risk: "medium" }, + ] }, hiap: [ { actionId: "ipcc_0210", name: "Urban drainage & flood defences", sector: "water", type: "adaptation", rank: 1 }, { actionId: "ipcc_0233", name: "Nature-based riverine buffers", sector: "afolu", type: "adaptation", rank: 2 }, { actionId: "c40_0061", name: "Early-warning & resilient infrastructure", sector: "water", type: "adaptation", rank: 3 }, ], + plan: { name: "Canoas Resilience & Adaptation Plan", status: "Draft 2025", actionsCount: 64 }, + projects: [ + { title: "Flood drainage & defences (post-2024)", sector: "water", askUSDm: 45 }, + ], source: "simulated", }, }; @@ -44,8 +64,6 @@ export function getCityContext(cityId: string): CityContext | null { return CONTEXT[cityId] || null; } -// Simulated agent assist. In production this is a CityCatalyst agent call that can -// read the city's shared context across modules. Returns guidance + a flag. export function agentAssist(opts: { cityName: string; tier: string; cleared: boolean; pathway: string }): { simulated: true; text: string; @@ -53,9 +71,9 @@ export function agentAssist(opts: { cityName: string; tier: string; cleared: boo const { cityName, tier, cleared, pathway } = opts; let text: string; if (tier === "Ready" && cleared) { - text = `${cityName} clears the early creditworthiness assessment. Its plan is strong but a single project may be below the instrument's ticket size — I'd route it to the portfolio/pooling step to combine with neighbours, then assemble the dossier.`; + text = `${cityName} clears the early creditworthiness assessment. A single project may be below the instrument's ticket size — you can either bundle ${cityName}'s own projects into an intra-city portfolio, or pool credit lines with neighbouring cities. Then assemble the dossier.`; } else if (pathway === "capacity-building") { - text = `${cityName} isn't yet eligible. Looking at the signals, the gap is not debt — it's liquidity, savings and accounting quality. I'd recommend a capacity-building track (fix accounting to lift the ICF rating, build cash reserves) plus grant/blended finance for adaptation now, rather than a guaranteed-credit application.`; + text = `${cityName} isn't yet eligible. The gap is not debt — it's liquidity, savings and accounting quality. I'd recommend a capacity-building track (fix accounting to lift the ICF rating, build cash reserves) plus grant / blended finance for adaptation now, rather than a guaranteed-credit application.`; } else { text = `${cityName} is on the readiness path. Close the named gaps via targeted TC, then re-assess for the instrument.`; } From 5ab23b7e23a686824a6597cf669a125333fcfe35 Mon Sep 17 00:00:00 2001 From: Martin Wainstein Date: Mon, 15 Jun 2026 01:46:33 -0600 Subject: [PATCH 12/14] Upgrade architecture + PRD to v2.2 reality + funder hierarchy / finance-readiness naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Reflect the built v2.2 Navigator (6-stage flow, CAPAG+SINIM adapters, map, state/region toggle, instrument step, intra/cross portfolio, dossier, agent seam, Valdivia/Canoas pathways); update 'what's real vs to-build'. - Naming note: this is finance / climate-finance readiness, not generic 'readiness'. - Funder hierarchy: funder/bank -> program -> instrument. SFP is a PROGRAM, not an instrument; 'Choose instrument' should become a funder navigator drilling the hierarchy, fed by a converged funder sourcing service (today fragmented). Captured in architecture §4.3 + PRD §0/§4. Co-Authored-By: Claude Opus 4.8 --- .../justagiraffe/INTEGRATED-ARCHITECTURE.md | 48 +++++++++++++++---- .../PRD-city-facing-readiness-app.md | 32 ++++++++++++- 2 files changed, 69 insertions(+), 11 deletions(-) diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/INTEGRATED-ARCHITECTURE.md b/events/2026-06-11-unlock-the-money/justagiraffe/INTEGRATED-ARCHITECTURE.md index b379c5d..be78673 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/INTEGRATED-ARCHITECTURE.md +++ b/events/2026-06-11-unlock-the-money/justagiraffe/INTEGRATED-ARCHITECTURE.md @@ -2,9 +2,15 @@ **Purpose:** define how the hackday modules fit into one coherent system, so the city-facing app (City Readiness Navigator) is built against the right boundaries. -**Status:** proposal for review (12–14 Jun 2026). Pairs with +**Status:** reflects the **v2.2 build** (12–15 Jun 2026) — the Navigator is built through +the city-facing flow below; CityCatalyst embed (OAuth/MCP) remains. Pairs with [`ITERATION-2.1-PLAN.md`](ITERATION-2.1-PLAN.md). +> **Naming.** "Readiness" alone is too broad — this stack assesses **finance readiness** +> (specifically **climate-finance readiness**): is a city/pool ready to access a *specific +> financing instrument* for its climate plan. The app's subtitle carries this ("Climate-finance +> readiness for cities & regions"); keep that framing in any rename. + --- ## 1. The core principle — two readiness questions, kept modular @@ -34,7 +40,7 @@ projects and adds creditworthiness + pooling + the funder handoff. | **CityCatalyst** | `Open-Earth-Foundation/CityCatalyst` | Host: GHG inventory, **HIAP** (prioritized actions), CCRA risk, Journey Navigator module catalog, OAuth, Global API | Production | | **Project Preparator** | `joaquinOEF/NBS-Project-Preparation` | Project bankability (Tech/Fin/Pol), project-funder matching, Concept Note | POC | | **justagiraffe Control Tower** | hackdays `justagiraffe/control-tower` | IDB-facing: Intake & Triage, Readiness Scoring (profile-driven engine), Results/Board | Hackday | -| **City Readiness Navigator** | hackdays `justagiraffe/city-readiness-navigator` | City-facing: the 7-step journey; entity readiness + pooling + submit | Hackday (ours) | +| **City Readiness Navigator** | hackdays `justagiraffe/city-readiness-navigator` | City-facing: 6-stage finance-readiness journey; entity creditworthiness + intra/cross-city portfolio + dossier handoff | Hackday (built, v2.2) | | **City-Funder Matching Engine** | hackdays `city–funder-matching` + `apps/funder-scan` | **Chile** capacity (SINIM/FCM), action→funder matching, **pooling/aggregation** | Hackday | | **CAPAG Funder Scan** | hackdays `apps/capag-funder-scan` | **Brazil** creditworthiness (Treasury CAPAG A/B/C/D for 5,570 munis) | Hackday | | **Political-will signal** | hackdays `codex/8-political-will-score` | LLM-derived governance/political-will sub-score from news/articles | Hackday (early) | @@ -71,9 +77,22 @@ The readiness engine consumes the normalized output; the UI badges provenance. - *Entity/instrument profiles* (justagiraffe: IDB SFP #1; CAF/WB/GCF next). Extract as a shared package so there aren't 3 divergent models. 2. **Fiscal Data Adapters** (§3) — CAPAG, SINIM, … -3. **Funder/instrument catalog** — today split (Preparator's 18 LatAm instruments; - Matching Engine's Chile funds; CAPAG's BNDES/CCFLA angle). Converge to one catalog - with eligibility metadata (borrower type, ticket window, sovereign-guarantee flag). +3. **Funder catalog + funder navigator (a 3-level hierarchy).** Financing is specified at + three levels of granularity, and readiness is ultimately assessed against the most + specific one: + - **Funder / bank** — IDB, CAF, World Bank, GCF, BNDES… + - **Program** within the funder — e.g. IDB's **Sub-Sovereign Finance Program (SFP)**. *The + SFP is a **program**, not an instrument.* + - **Instrument** within the program — e.g. under SFP Subprogram 1, an **investment loan** or + **investment guarantee** (without sovereign guarantee); Subprogram 2's TC instruments. + + So the city app's "choose instrument" step is really a **funder navigator** that drills + *funder → program → instrument*. It is fed by a **funder sourcing database / service** — the + converged catalog (today fragmented: Preparator's 18 LatAm instruments; Matching Engine's + Chile funds; CAPAG's BNDES/CCFLA angle; and funder data living in *different areas of + CityCatalyst*). Consolidating these into one sourcing service, plugged into the navigator, + is the target; each entry carries eligibility metadata (borrower type, ticket window, + sovereign-guarantee flag) and links to the readiness profile it implies. 4. **Candidate dossier = the Concept Note, extended** — the machine-readable handoff into a funder pipeline. Reuse the Preparator's GCF/C40 Concept Note and add the entity-creditworthiness + instrument + pooling layer; don't invent a new schema. @@ -178,11 +197,20 @@ flowchart TB ## 7. What's real today vs. to-build -- **Real now:** CityCatalyst inventory/HIAP/CCRA; CAPAG (5,570 munis); SINIM/FCM (Chile); - Preparator readiness + Concept Note; justagiraffe profile-driven engine; Navigator 7-step - flow + handoff. -- **To build (v2.1+):** Fiscal Data Adapter interface (CAPAG + SINIM); shared readiness - package; Concept-Note-as-dossier; converged funder catalog; the two explicit entry paths. +- **Built (Navigator v2.2):** the 6-stage city-facing flow — Explore (map + **state/region vs + city** view + data-source toggle) → City context (inventory + CCRA + HIAP + plan) → **Choose + instrument** → Readiness pathways (assess + route) → **Portfolio (intra-city vs cross-city + pool)** → Funder intake (dossier). **Fiscal Data Adapters** for **CAPAG (Brazil)** and + **SINIM (Chile)** with the readiness map; the profile-driven readiness engine; the **dossier** + handoff to a funder-pipeline view; a simulated **CityCatalyst context + agent** seam. Two + worked cities/pathways: **Valdivia** (Ready → portfolio → IDB SFP) and **Canoas** (CAPAG C → + capacity-building). Control Tower copy upgrade (orientation banner, glosses, M&E explicit). +- **Real data:** CAPAG (5,570 munis), SINIM/FCM (Chile), CityCatalyst inventory/HIAP/CCRA + (live in CityCatalyst; simulated in the Navigator pending embed). +- **To build:** live CityCatalyst embed (OAuth/MCP, real inventory/HIAP); the **funder + navigator** drill-down (funder → program → instrument) + converged **funder sourcing service** + (§4.3); shared `@oef/readiness` package (de-dupe Navigator/Control Tower); real Navigator↔ + Control Tower wiring (dossier writes into Intake & Triage); the Preparator handoff (Path A). ## 8. Open decisions (for the review) diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/PRD-city-facing-readiness-app.md b/events/2026-06-11-unlock-the-money/justagiraffe/PRD-city-facing-readiness-app.md index e459ffb..1dca5de 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/PRD-city-facing-readiness-app.md +++ b/events/2026-06-11-unlock-the-money/justagiraffe/PRD-city-facing-readiness-app.md @@ -11,6 +11,30 @@ --- +## 0. Build status & key clarifications (v2.2, 15 Jun 2026) + +**Built (runs locally):** a **6-stage** city-facing flow — **Explore** (readiness map with a +**state/region ↔ city** toggle + a data-source toggle) → **City context** (inventory + CCRA + +HIAP + climate plan, from the CityCatalyst seam) → **Choose instrument** → **Readiness +pathways** (assess + route) → **Portfolio** (**intra-city** vs **cross-city pool**) → **Funder +intake** (dossier → pipeline). Real fiscal data via **CAPAG (Brazil)** and **SINIM (Chile)** +adapters; two worked cities — **Valdivia** (Ready → portfolio → IDB SFP) and **Canoas** (CAPAG +C → capacity-building). The 7-step spec in §4 is the origin; the built structure is the 6 stages +above (left-hand process menu). + +**Naming.** "Readiness" is too broad — this is **finance readiness** / **climate-finance +readiness**. Keep the app's subtitle ("Climate-finance readiness for cities & regions") front +and center; a rename should preserve that. + +**Funder hierarchy (3 levels) — refines "Choose instrument".** Financing has three levels of +specificity and readiness is assessed against the most specific: **funder/bank → program → +instrument**. The **IDB SFP is a *program***, not an instrument; its instruments are the +investment loan / guarantee (Subprogram 1) and TC (Subprogram 2). So this step should become a +**funder navigator** that drills funder → program → instrument, fed by a converged **funder +sourcing database / service** (today fragmented across CityCatalyst and the hackday apps; see +[`INTEGRATED-ARCHITECTURE.md` §4.3](INTEGRATED-ARCHITECTURE.md)). *Not yet built — current step +selects IDB SFP directly.* + ## 1. Why this exists Two hackday prototypes each built half of the "unlock the money" chain and neither @@ -108,7 +132,7 @@ acceptance behavior. |---|------|--------------------|--------| | 1 | **Enter** | The city's existing profile (name, locode, population, region, GPC emissions, HIAP priorities) auto-loaded — no re-entry. | CityCatalyst app `/api/v1` (OAuth) + Global API city context | | 2 | **Discover** | "Funders your plan can reach" — instruments matched to the city's prioritized actions, each tagged applicant / facilitator / referrer, with gaps named. IDB SFP appears when eligible. | Matching Engine outputs (`valdivia_funders_open.csv`, `*_action_matches.csv`); HIAP for priorities | -| 3 | **Choose the instrument** | The user selects a financing instrument (default IDB SFP). The app loads that instrument's **readiness profile**. (formerly "Pick a target") | `readiness-profiles.js` registry | +| 3 | **Choose instrument** *(→ funder navigator)* | Today: selects IDB SFP and loads its **readiness profile**. Target (§0): a **funder navigator** drilling **funder → program → instrument** (SFP is a *program*), fed by the funder sourcing service. Carries the "you may be eligible for a direct line" note. | `readiness-profiles.js` registry; funder sourcing service (to build) | | 4 | **Diagnose** | Readiness score (composite + four pillars), tier (Ready/Developing/Early), "why this score" per-pillar contribution, the eligibility gate pass/fail, and the documentary checklist — all for the chosen target. Real-vs-estimated badges per signal. | `scoring.js` (active profile) over CityCatalyst + Matching Engine capacity data | | 5 | **Readiness pathways** | Assess-and-route, not just "prepare." For each gap: the concrete fix and its route — self-serve coaching to the funder's requirements, or a funded capacity-building/PPF track (for IDB, **Subprogram 2 TC**, ~US$13M envelope: regular + contingent-recovery). Turns "rejected" into "here's the path." (formerly "Prepare") | Profile `preparation` track + checklist gaps | | 6 | **Pool (if needed)** | If the city is below the target's ticket size, the engine pools it with neighbours into one financeable bundle, names the anchor, flags TA-needed members. Readiness then evaluates the anchor/pool. | Matching Engine `coordination_units.csv`, `unit_bundle_candidates.csv` | @@ -237,6 +261,12 @@ Match CityCatalyst so the module feels native: ## 8. Build phases (for the autonomous agent) +> **Status (v2.2):** Phases 0–3 are **built** (the 6-stage flow, CAPAG+SINIM adapters, map, +> instrument step, intra/cross portfolio, dossier → pipeline, simulated context/agent seam). +> **Remaining:** Phase 4 (live CityCatalyst embed — OAuth/MCP), the **funder navigator** +> drill-down + funder sourcing service (§0), shared `@oef/readiness` package, and real +> Navigator↔Control Tower wiring. + **Phase 0 — Skeleton.** Next.js 15 + Chakra 3 app from `apps/_template`, CityCatalyst theme tokens, i18n scaffold, the 7-step flow shell with mock data. Hero city: **Valdivia (`CL ZAL`)**, the cross-team worked example. From 162f4f93a72f0413f845a284dd9a92368abe76f9 Mon Sep 17 00:00:00 2001 From: Martin Wainstein Date: Mon, 15 Jun 2026 01:49:08 -0600 Subject: [PATCH 13/14] Add pitch deck (self-contained HTML) for the 5-7 min demo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit justagiraffe/deck/index.html — a single-file, dependency-free slide deck (opens by double-click; arrow keys / space to navigate, f = fullscreen, n = speaker notes). 9 slides: problem → the two apps → dossier handoff → the 5a architecture SVG → the process-timeline SVG → how the other hackday projects plug in → revenue → demo close (Valdivia Ready / Canoas CAPAG-C). Both diagrams are inlined for portability; theme matches the SVG palette. Co-Authored-By: Claude Opus 4.8 --- .../justagiraffe/deck/index.html | 393 ++++++++++++++++++ 1 file changed, 393 insertions(+) create mode 100644 events/2026-06-11-unlock-the-money/justagiraffe/deck/index.html diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/deck/index.html b/events/2026-06-11-unlock-the-money/justagiraffe/deck/index.html new file mode 100644 index 0000000..3939737 --- /dev/null +++ b/events/2026-06-11-unlock-the-money/justagiraffe/deck/index.html @@ -0,0 +1,393 @@ + + + + + +Unlock the Money — the Readiness Layer · justagiraffe + + + +
+
🦒 justagiraffe
+
+ + +
+
Hackday Q2 2026 · Unlock the Money
+

Unlock the
Money

+
The readiness layer that gets subnational climate finance actually flowing — from a city's plan to a funder's pipeline.
+
+ City Readiness Navigator · city-facing + SFP Control Tower · IDB-facing +
+ +
0:20 One sentence: "We built the trust layer between a city's climate plan and the money that funds it — two apps, one shared readiness model." Don't explain the apps yet.
+
+ + +
+
The problem
+

If funders can't trust cities, the money doesn't move.

+
+
Question 1

Is the project bankable?

Is this specific investment fundable, and by whom?

+
Question 2

Is the entity creditworthy?

Can this city — or a pool of them — take on this instrument?

+
+

Two different questions, answered by different actors today — and never assembled in one place a funder can act on.

+
0:45 These two questions gate every deal. They're independent: a great project in a city that can't borrow goes nowhere; a creditworthy city with no bankable project goes nowhere. Keeping them separate is the core insight.
+
+ + +
+
What we built · two sides of the table
+

Two apps, one shared readiness model.

+
+ +
+

SFP Control Tower

+

The IDB's view: "Which candidates are ready, and why?"

+
    +
  • Intake & Triage — where each candidate sits
  • +
  • Readiness Scoring — the creditworthiness gate
  • +
  • M&E & Board — proving the pilot works
  • +
+
+
+

One dossier crosses the boundary between them — same readiness engine scores both sides.

+
0:50 Navigator = the front door for cities (lots of hand-holding). Control Tower = the screening room for the funder (expert, dense). Same scoring model under both, so a city is judged on the exact criteria the funder uses.
+
+ + +
+
How they interact
+

The handoff is a single dossier.

+
+

The city app builds a defensible candidate package.

+
+

2 · Crosses the boundary

City-facing → funder-facing. No re-keying, no email.

+
+

3 · Control Tower intake

Lands as a scored candidate in Intake & Triage.

+
+

Dossier = + Concept Note + creditworthiness + instrument + pool +

+

The city app produces a defensible candidate — not an approval. The funder still does due diligence.

+
0:45 Key point: the dossier reuses the Project Preparator's Concept Note format and extends it. We didn't invent a new schema. That's what makes the handoff real instead of a slide.
+
+ + +
+
The integrated architecture
+
+ +Revised 5a integrated architecture +CityCatalyst as host infrastructure; Project Preparator and City Readiness Navigator as peer modules; the Navigator is a three-step vertical; capacity building is a standalone support track; funder pipelines at the bottom. + + + + +Integrated architecture — 5a (City Readiness Navigator) + +CityCatalyst — host & shared context (infrastructure) +HIAP prioritized actions +GHG inventory · CCRA risk +AI agents · MCP (shared) + +Project Preparator — module on CityCatalyst + +Project bankability (Tech/Fin/Pol) +→ Concept Note +Fiscal Data Adapters · CAPAG / SINIM + map +Matching & Pooling — core service + +Capacity building / PPF +standalone support · entity or project + +City Readiness Navigator — entity / portfolio (one vertical) + +① Entity creditworthiness +diagnose for chosen instrument + +② Readiness pathways +close the gap · coach to funder reqs +(IDB SFP first) + +③ Portfolio & pooling → submit +pool only if sub-scale +→ dossier + + + +Funder pipelines +IDB Control Tower · Intake & Triage · Readiness Scoring · M&E & Board +Other funders · BNDES / CCFLA + + +Concept Note · Path A + +Path B · entity-first + + +not ready → gap + +dossier + +CityCatalyst (host) +Preparator +Navigator +services / funders + +
+
1:00 CityCatalyst is the host (inventory, HIAP actions, climate risk, AI agents). Preparator and our Navigator are peer modules on top. Navigator is one vertical: creditworthiness → readiness pathways → portfolio → submit. Capacity building is a standalone track. Everything ends in the funder pipelines.
+
+ + +
+
The pipeline, end to end
+
+ +Process timeline — readiness pipeline and shared services +A top-to-bottom process (Source, Readiness pathways, Portfolio, Funder intake) running through CityCatalyst, the Navigator's readiness pathways with Path A and Path B, portfolio and pooling, and the IDB Control Tower — with AI agents, Matching+Pooling, and Fiscal adapters as shared services on the right. + + + + +PROCESS +SHARED SERVICES + +Source +Readiness pathways +Portfolio +Funder intake + +CityCatalyst +GHG inventory · HIAP actions · CCRA risk + +Readiness pathways +assess, then route → ready · capacity-building · pool +Project bankability · Preparator → Portfolio · Path A +① Entity creditworthiness · CAPAG · SINIM · map · Path B + +② Portfolio & pooling → submit +pool to reach the instrument's ticket size + +IDB Control Tower +Intake & Triage · Readiness Scoring · M&E & Board + +AI agents +shared context (MCP) + +Matching + Pooling +core service + +Fiscal adapters +CAPAG · SINIM · map + + + +dossier + + + +CityCatalyst +Preparator +Navigator +funders / services + +
+
0:50 Read it top to bottom: Source (CityCatalyst) → Readiness pathways → Portfolio → Funder intake. Two ways in: Path A (project-first, via the Preparator) and Path B (entity-first, via fiscal data). The right rail is the shared services every step calls.
+
+ + +
+
We didn't build in a silo
+

Our two apps plug into the rest of the room.

+
+

CityCatalyst

we get → GHG inventory · HIAP actions · CCRA risk · AI-agent context

+

Project Preparator

we get → a bankable project as a Concept Note (Path A)

+

Matching Engine

we get → action→funder matching + pooling (Chile / SINIM)

+

CAPAG Funder Scan

we get → Brazil Treasury creditworthiness (the fiscal adapter)

+

Political-will signal

we get → an LLM governance / political-will sub-score

+ +
+
1:00 This is the "ecosystem" slide. Every other team's project is an input or an output to our chain. CAPAG and the Matching Engine feed our readiness; the Preparator feeds our portfolio; we feed the Control Tower. One stack, many hands.
+
+ + +
+
Why it matters · the revenue angle
+

A premium capability for cities, a de-risked pipeline for any MDB.

+
+

A premium CityCatalyst capability: turn a climate plan into a fundable, submitted candidate.

+

For funders

A pre-screened, de-risked deal pipeline — candidates arrive already scored on your criteria.

+
+

Repeatable: swap the readiness profileCAF · World Bank · GCF. Same app, new MDB — no rebuild.

+
0:40 Hackday required a revenue angle — this is it. The profile-driven engine means the second MDB is a config file, not a new product. That's the scaling story.
+
+ + +
+
What we'll show
+

Two real cities, two outcomes.

+

Valdivia (Chile) — Ready → builds a portfolio → dossier submitted to IDB SFP.
+ Canoas (Brazil, CAPAG C) — not yet creditworthy → routed to a funded capacity-building path.

+

Real fiscal data in (SINIM + CAPAG); a defensible dossier out. Both branches of "readiness pathways," live.

+
+ City Readiness Navigator + SFP Control Tower +
+

Open-Earth-Foundation/hackdays · branch justagiraffe · thank you 🦒

+
0:30 End on the demo promise + thanks. If you're tight on time, you can jump straight from slide 7 to here.
+
+ +
+ +
1 / 9
+
+ + + + +
+ + + + From 12ffe77a7784bd9332cb32ed21d82aad30f9eff7 Mon Sep 17 00:00:00 2001 From: Martin Wainstein Date: Mon, 15 Jun 2026 02:03:36 -0600 Subject: [PATCH 14/14] Navigator: funder navigator drill-down + finance-readiness naming - 'Choose instrument' -> 'Find financing': a 3-level funder navigator that drills funder -> program -> instrument (src/lib/funders.ts). IDB -> SFP (a PROGRAM) -> investment loan / guarantee / TC. CAF/WB/GCF shown as templates. Selecting a program sets the readiness profile; the dossier carries the full instrument label. Framed as fed by a 'funder sourcing service' (converged catalog, mock for now). - Naming: app is now 'Climate-Finance Readiness Navigator' (sidebar + metadata) so 'readiness' reads as finance/climate-finance readiness, not generic. Co-Authored-By: Claude Opus 4.8 --- .../src/app/layout.tsx | 4 +- .../city-readiness-navigator/src/app/page.tsx | 80 ++++++++++++++----- .../src/components/Sidebar.tsx | 4 +- .../src/lib/funders.ts | 48 +++++++++++ 4 files changed, 110 insertions(+), 26 deletions(-) create mode 100644 events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/lib/funders.ts diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/layout.tsx b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/layout.tsx index 49a94d7..03feb9d 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/layout.tsx +++ b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/layout.tsx @@ -2,9 +2,9 @@ import type { Metadata } from "next"; import "./globals.css"; export const metadata: Metadata = { - title: "City Readiness Navigator — CityCatalyst × IDB", + title: "Climate-Finance Readiness Navigator — CityCatalyst × IDB", description: - "Find which funders your climate plan can reach, see how ready you are for a financing instrument, and submit when ready.", + "Get cities & regions ready to access climate finance: find a financing line, assess readiness, and submit when ready.", }; export default function RootLayout({ children }: { children: React.ReactNode }) { diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/page.tsx b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/page.tsx index 47675e0..5d00fb1 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/page.tsx +++ b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/app/page.tsx @@ -8,11 +8,12 @@ import { SCOPES, mapPoints, scopeLegend, journeyCity, DATA } from "@/lib/adapter import { SM, provenanceKind, type Scored, type Comuna } from "@/lib/engine"; import { getCityContext, agentAssist } from "@/lib/context"; import { assembleDossier } from "@/lib/dossier"; +import { FUNDERS, getFunder } from "@/lib/funders"; const STAGES: StageDef[] = [ { key: "explore", title: "Explore", sub: "Region & data" }, { key: "context", title: "City context", sub: "From CityCatalyst" }, - { key: "instrument", title: "Choose instrument", sub: "Readiness for whom" }, + { key: "instrument", title: "Find financing", sub: "Funder · program · instrument" }, { key: "readiness", title: "Readiness pathways", sub: "Assess & route" }, { key: "portfolio", title: "Portfolio", sub: "Reach the ticket" }, { key: "intake", title: "Funder intake", sub: "Dossier & submit" }, @@ -52,7 +53,9 @@ export default function Page() { const [viewLevel, setViewLevel] = useState<"cities" | "state">("cities"); const [cityId, setCityId] = useState(null); const [entry, setEntry] = useState<"entity" | "project">("entity"); - const [instrument, setInstrument] = useState(null); + const [selFunderId, setSelFunderId] = useState(null); + const [selProgramId, setSelProgramId] = useState(null); + const [selInstrumentId, setSelInstrumentId] = useState(null); const [portfolioMode, setPortfolioMode] = useState<"intra" | "cross">("intra"); const [stage, setStage] = useState(0); const [maxReached, setMaxReached] = useState(0); @@ -67,6 +70,11 @@ export default function Page() { const ctx = cityId ? getCityContext(cityId) : null; const pathway = scored ? pathwayOf(scored) : null; + const selFunder = getFunder(selFunderId); + const selProgram = selFunder?.programs.find((p) => p.id === selProgramId) || null; + const selInstrument = selProgram?.instruments.find((i) => i.id === selInstrumentId) || null; + const instrLabel = selProgram && selInstrument ? `${selProgram.name} · ${selInstrument.name}` : SM.activeProfile().instrument; + // Cross-city pool (Chile) and intra-city portfolio (the city's own projects). const pool = scopeId === "cl-losrios" ? DATA.cl.pool : null; const poolScored = scored && pool ? SM.scoreSNG({ ...(scored as any), proposal: pool.pooledProposal }) : null; @@ -74,7 +82,7 @@ export default function Page() { const intraScored = scored && ctx ? SM.scoreSNG({ ...(scored as any), proposal: { title: `${scored.name} climate portfolio`, sector: "multi-sector", askUSDm: intraTotal, stage: "Structuring", cofinance: true } }) : null; function goto(i: number) { setStage(i); setMaxReached((m) => Math.max(m, i)); } - function pickCity(id: string) { setCityId(id); setSubmitState(null); setInstrument(null); goto(1); } + function pickCity(id: string) { setCityId(id); setSubmitState(null); setSelFunderId(null); setSelProgramId(null); setSelInstrumentId(null); goto(1); } // Region-level summary (the "state layer"). const regionSummary = useMemo(() => { @@ -90,11 +98,11 @@ export default function Page() { if (pathway === "capacity-building") { opts = { scored, kind: "city", pathway: "capacity-building", instrumentName: "Capacity-building / PPF + blended finance", pool: null, proposal: scored.proposal }; } else if (portfolioMode === "cross" && pool) { - opts = { scored: poolScored, kind: "pool", pathway: "pool", + opts = { scored: poolScored, kind: "pool", pathway: "pool", instrumentName: instrLabel, pool: { anchor: scored.name, members: pool.members.map((m: any) => ({ name: m.name, role: m.isAnchor ? "anchor" : "member", cofinance: m.cofinanceScore })) }, proposal: pool.pooledProposal }; } else { - opts = { scored: intraScored, kind: "city", pathway: "instrument", pool: null, + opts = { scored: intraScored, kind: "city", pathway: "instrument", pool: null, instrumentName: instrLabel, proposal: { title: `${scored.name} climate portfolio (${ctx!.projects.length} projects)`, sector: "multi-sector", askUSDm: intraTotal, cofinance: true } }; } const dossier = assembleDossier(opts); @@ -203,31 +211,59 @@ export default function Page() { {entry === "project" && (
Project-first: import a prepared project (a Concept Note from the Project Preparator) — it enters at the Portfolio step.
)} -
+
)} - {/* 2 — CHOOSE INSTRUMENT */} + {/* 2 — FIND FINANCING (funder navigator: funder → program → instrument) */} {stage === 2 && scored && ( <> -
Readiness against which instrument?
-

Readiness is instrument-specific — it depends on the funder, their institutional requirements, and the nature of the financial product. {entry === "entity" ? "Entity-first: a direct line for the city." : "Project-first: instruments that fund a specific project."}

-
{ setInstrument("idb-sfp"); SM.setActiveProfile("idb-sfp"); }}> -
-

Inter-American Development Bank — Sub-Sovereign Finance Program (SFP)

- {instrument === "idb-sfp" && selected} -
-

Direct lending to subnational governments without a sovereign guarantee.

-
You may be eligible for a direct line from the IDB. Assess readiness against this instrument and program line.
+
Find a financing line
+

Readiness is specific to the product. Drill down funder → program → instrument. {entry === "entity" ? "Entity-first: a direct line for the city." : "Project-first: also surfaces grants & PPFs via the matching service / Preparator."}

+ +
+ {selFunder ? {selFunder.short} : "Funder"} › {selProgram ? {selProgram.name} : "Program"} › {selInstrument ? {selInstrument.name} : "Instrument"}
-
-

CAF · World Bank · GCF template

-

Other MDBs plug in their own readiness profile — same engine, different criteria. (Illustrative for now.)

+ +
+

1 · Funder

+ {FUNDERS.map((f) => ( +
+ {f.name} {f.template && template} + +
+ ))}
- {entry === "project" && ( -
Project-first also surfaces grants & project-preparation facilities (PPFs) via the matching service / Project Preparator — for actions that aren't loan-shaped.
+ + {selFunder && ( +
+

2 · Program within {selFunder.short}

+ {selFunder.programs.map((p) => ( +
{ setSelProgramId(p.id); setSelInstrumentId(null); SM.setActiveProfile(p.profileId); }}> +

{p.name}

{selProgramId === p.id && selected}
+

{p.summary}

+ {p.eligibilityNote && selProgramId === p.id &&
{p.eligibilityNote}
} +
+ ))} +
)} -
+ + {selProgram && ( +
+

3 · Instrument within {selProgram.name}

+ {selProgram.instruments.map((i) => ( +
+ {i.name} {i.note && · {i.note}} + +
+ ))} +
+ )} + +
Fed by the funder sourcing service — a converged catalog (today fragmented across CityCatalyst + the hackday apps). Mock for the demo.
+
)} diff --git a/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/components/Sidebar.tsx b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/components/Sidebar.tsx index 49f89d9..43a1e05 100644 --- a/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/components/Sidebar.tsx +++ b/events/2026-06-11-unlock-the-money/justagiraffe/city-readiness-navigator/src/components/Sidebar.tsx @@ -14,8 +14,8 @@ export default function Sidebar({ }) { return (