Impact Dashboard v2 — reframe around field acceleration (stacks on #29) - #98
Merged
Conversation
Adds /impact — a public, filterable dashboard that tracks PL R&D's impact via the twelve pre-registered inflection points, one set per focus area. What it does: - Filterable by focus area (vertical tab rail); a user always lands in one area rather than seeing all twelve at once. - Each inflection point is a card with a Defined -> Emerging -> Reached -> Scaling field-progress meter and a PL-role tag (Substrate / Originator / Funder & convener). Clicking opens a detail modal. - The modal traces Q1 (did it happen — the pre-registered threshold), Q2 (did it matter — the cascade), and Q3 (did our work make it happen) as Inputs -> Activities -> Outputs. - Field progress and PL contribution are kept on separate axes and never collapsed into one score: a point can be reached with little PL involvement and that is still a win for the field. - For the two Economies & Governance points with live data, the modal pulls live OUTPUTS from the same sources as the FA2 live dashboard (GainForest, Glow, Simocracy) — labelled strictly as Q3 contribution evidence, never as Q1 progress. Fetched server-side with 60s ISR and graceful fallback. - A "Measuring impact" explainer covers the logic model and the three questions. - Adds an "Impact" item to the main nav. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Inflection section intro: drop the "pre-registering keeps us honest / reading not an argument" tail; "pre-registered" -> "defined" threshold. - Cards: remove the redundant "Defined" status pill (the field meter already shows stage); rename the teaser label "Signal it happened" -> "Inflection point". - Detail modal: tag Q1 with "Impact" and Q2 with "Outcome" so all three questions share the logic-model row layout used by Q3's Inputs / Activities / Outputs. - Measuring impact: move the "each inflection point instantiates this chain" note above the logic-model strip; style the strip labels as grey uppercase to match the detail cards. - Three-questions explainer: surface each question's logic-model stage(s) — Impact, Outcomes, and Inputs/Activities/Outputs — to tie the section back to the cards. - Hoist LOGIC_MODEL into lib/inflection-points so the strip, the explainer, and the modal share one vocabulary. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the single contributionLevel (substrate/originator/funder-convener) with an array of PL roles named by the bottleneck each releases: Infrastructure, Legibility, Connection, Capital, Translation, Permission. Cards now render one pill per role; the Measuring-impact Q3 tab lists all six roles and its copy reflects 'one or more' instruments.
The role pill descriptions in the inflection-point modal duplicated the 'Measuring impact' Q3 explainer. Keep the role pills (with hover titles) but remove the description list so the explanation lives in one place.
…tcome) + self-contained role tooltips - Q1 is now 'Did it matter?' (impact) and Q2 'Did it happen?' (outcome), consistent across the inflection-point detail modal and the Measuring- impact tabs (and doc comments / live-evidence notes). - Role pills now carry a label + description tooltip matching the Measuring-impact Q3 role explainer.
Native title was unreliable; replace with a scoped CSS tooltip (group/role) that shows the role's label + description on hover, pulled from the same ROLE_META used by the Measuring-impact Q3 section.
Add FIELD_COLOR (teal) / HAND_COLOR (violet) tokens; update ROLE_META and LOGIC_MODEL copy to the mockup wording.
Drop focus-area color coding (neutral icons). Card now shows a teal 'field' axis (meter + did it happen & matter) and a violet 'our hand' axis (role pills + did our work help), plus a LIVE SIGNAL block for points with live outputs. Modal recolored/reordered to A (our hand) / B, C (the field).
… section Measuring-impact section: color-code the logic-model chain by axis, dot legend (not tick-boxes), and three always-visible A/B/C question cards. Extract the six PL roles into a separate 'toolkit' section.
- Swap axis colors: field = purple, our hand = PL blue (#1982F4); teal removed - Live signal now a pulsing green dot; 'Live outputs' -> 'Live signal' - Cards: 'Detail' affordance (subtle top-right, not a full row); 'Methodology' removed - Detail modal: wider + two-column (our hand | the field) with full-width live signal; remove repeated status badge and the field explainer; 'the signal' -> 'the inflection point'; 'Did our work help?' -> 'Is our work making a difference?' - AI & Robotics empty state: 'inflection points' instead of 'pre-registered bets'
- Detail modal: inputs/activities/outputs are now headers over their text (aligned with the field side); rename 'Field progress' to 'Progress against Inflection Point'; drop 'The only axis we control' subheading. - Generic 'Live signal' footnote on cards + detail that carry live data. - Mark communication / provenance / public-goods / verified-outcomes as Emerging (early-signal). - Measuring: remove the dot legend (already conveyed in the subheader).
- Hero: add 'Our methodology' scroll link (landing-page style); rename the section to 'Our methodology' with a #methodology anchor. - Field axis color -> black (drop purple); hand stays PL blue, live green. - Methodology block: A card is wide with role pills + a subtle 'See the roles we play' link opening a pop-out roles modal; B/C narrow. Remove the standalone toolkit section. - Copy: 'Is our work making a difference?' -> 'Our contribution to field progress'; A axis line -> 'The axis we control with our partners'.
- Remove the inputs->impact logic-model boxes; keep just the three evenly-spaced question cards. - Measuring copy: A 'What difference are we making?', B 'Did the inflection point happen?', C 'Did reaching the inflection point matter?' - Detail modal keeps short B/C; A reworded to 'How is PL making a difference?' (card hint too).
Card A is now a button that opens the roles modal (like the inflection detail cards), with 'See the roles we play' as a subtle hover affordance instead of the only click target.
- Detail card bottom band now spans full width: live-signal metrics (when present) plus a 'See the latest <focus area> insights' link. - Deep-link: /insights?area=<slug> pre-selects that focus-area filter (InsightsExplorer takes an initialArea; page reads searchParams). - Measuring copy: A 'Did PL's work make a difference?', B 'Were the inflection points reached?'.
Integrated into the /impact dashboard (stacked on PR #29, not amending it): - src/lib/market-signals.ts — maps each inflection point to its closest market, choosing Polymarket vs Kalshi per match quality, with a liquidity fallback. Public Gamma + Kalshi APIs, hourly ISR. - ImpactDashboard: crowd read on the FIELD axis (card + modal), platform badge, fallback tag, gap state; never conflated with PL contribution. - impact/page.tsx: resolveAllSignals() alongside existing live outputs. For discussion only.
Per review: the crowd read now sits inside the modal's full-width Live signal bar (alongside PL-backed live outputs) instead of under 'Impact — the cascade' in the field column. Gap points show a separate crowd-forecast note. Field-vs-contribution caveat preserved.
Thread per-market USD volume through MarketSignal (Polymarket volumeNum; Kalshi dollar_volume, falling back to contract count) and render a compact '$15k at stake' chip next to the crowd probability in the modal's Live signal band.
Per review, simplify the inflection-point detail modal into a single column with three stacked sections: - The field: card title, progress meter, Outcome and Impact (moved up under the title; drop the 'Did it happen?' / 'Did it matter?' questions and A/B/C badges). - Our hand: 'How PL is making a difference' with each PL contribution category (role) as a header + description, replacing the Inputs/Activities/Outputs split. - Live signal: unchanged (live outputs + crowd forecast with money at stake). Also rename the 'Permission' PL role to 'Policy' (methodology + modal). This commit sits on top of the crowd-forecast + volume work so it all lands in the /impact dashboard PR.
…ills
- The field: move Outcome and Impact above the progress bar; wrap the whole
field section in a subtle grey card for clear visual grouping.
- Add clear separation (top border + spacing) before Our hand and Live signal.
- Our hand: restore PL interventions as pills with the definition on hover
(RoleChips), and show the point's actual activities / examples underneath
('In practice') instead of the generic role definitions.
Match The field's grey card treatment for Our hand and the Live-signal band so all three detail sections sit on separated grey cards against the white modal backdrop, stacked and left-aligned. Live signal is now a titled card (keeping the pulsing green globe) that holds the live-output box, crowd forecast, and the 'See the latest ... insights' link.
Preview cards no longer render the crowd-forecast odds or live-output metrics inline — they just show a small pulsing 'Live signal' marker so there's a reason to open the card. The full crowd forecast, live metrics, and evidence links stay in the detail modal. Also make liveEvidence a list so a point can carry multiple real-world signals, and add two to 'Provenance becomes the default for truth': Starling Lab's content-authenticity displays and Wikipedia-on-IPFS during Turkey's block.
…annot be switched off' The censorship-shutdown example fits the resilient-comms inflection point, not provenance. Provenance keeps the Starling Lab authenticity signal.
The 'field' axis used a hard black (#131316) via inline styles, so in dark mode the field labels, the progress-bar fill, the active focus-area tab icon, and the B/C badges all went black-on-black. Route FIELD_COLOR / HAND_COLOR (plus new FIELD_INK and FIELD_TRACK) through theme-aware CSS variables that flip in dark mode: the field ink becomes light, the badge fill flips with dark ink, and the progress track darkens. Light mode is unchanged.
Populate contribution.outputs on the six capital inflection points with concrete PL-network ventures as examples of the Capital instrument (the HAND/contribution axis — not field progress): - Comms that can't be switched off: Fluence, Huddle01 - Personhood without the state: Tools for Humanity (World), SpruceID, Privy - Provenance as default for truth: EQTY Lab - Agents on open rails: Fluence, Spheron, Expanso, Impossible Cloud, Lava, Fleek - Public goods financeable: + Molecule - Capital paid on verified outcomes: + WeatherXM Unverified funding relationships are hedged inline pending confirmation.
- Remove the 'funding relationship to be confirmed' qualifiers from the identity / provenance / comms outputs. - Add a TEAM_LINKS registry (team name -> website) and a Linkify renderer so each mentioned venture in the 'In practice' activities/outputs lines links to its own site. Links open in a new tab (target=_blank, rel=noopener noreferrer), consistent with the live-evidence links.
…ide box; add inflection-points explainer - Remove draft/discussion language: the 'Draft for review' badge, the velocity modal's 'being wired / n/a until source connected' note, and the forthcoming empty state's 'coming soon / plan of attack' copy. - Intro jump link: 'How we measure this' -> 'Learn more about our methodology'. - Move the 'Field velocity - Is the field speeding up?' label outside the box, matching the 'Inflection points we're tracking' label style. - Make the vertical focus-area tabs sticky while scrolling the velocity section. - Add an 'Inflection points' box to the methodology's Observed velocity section with a short explainer, opening a modal.
added 3 commits
August 3, 2026 09:19
…arts Task 1/2/5: move the five instrument definitions into src/lib/velocity-instruments.ts as the single source of truth for that prose (rendered only in the definition modal). Declare per-focus-area instrument records with three states (reading / unwired / not_applicable), ragged by field, enforced by a build-time assertion (reading needs value+asOf+>=1 source; unwired needs candidateMetric+blocker; not_applicable needs reason). Task 3: velocity box and aggregate modal become chart slots. Add an inline SVG sparkline (log axis, confidence band, dashed unreliable tail, optional secondary normalizer line) for readings-with-series, a compact stat block for readings-without-series, an identical abstract blurred aria-hidden ghost chart for unwired, and a muted line for not_applicable. The aggregate modal is readings-and-charts only; each instrument title links to its definition modal. Task 5: seed readings from public sources (AI performance curve = METR time horizon; Neurotech performance curve = Stevenson & Kording neuron series; DHR revealed commitments = Electric Capital). Everything else is honest unwired or not_applicable. Task 6: verbatim copy for the intro, the field-velocity standfirst, the aggregate modal intro, the Observed-velocity standfirst, the instrument footnote, and the state microcopy. Stacks on #98. Draft gating unchanged.
Split marker resolution into independent outcome (pending/reached/missed/retired) and mattered (unknown/too_early/yes/no) so a marker can resolve true while the field goes nowhere. Derived label in one helper; mattered is never inferred from outcome. Build-time assertion requires matteredEvidence when mattered is yes/no and retiredReason when retired. Every existing marker seeded pending/unknown with predictedBy/falsifiesIf null, rendered visibly as 'date not yet set' / 'condition not yet set'. Card face shows the derived label, review date, and the two null-aware fields; the modal adds evidence/retired-reason when present. A misses ledger near the list surfaces missed/retired/reached-without-lift markers and renders at zero count.
Follow-up to the field-velocity work. One instrument has a real data path, so it leaves the ghost state. - Ingestion: src/lib/velocity-openalex.ts parses one CSV per focus area at build time (never in the browser), retaining the # provenance lines and surfacing the frozen query string + generated date in the modal. Missing CSV => the documented unwired record (candidateMetric 'median reference age from OpenAlex', blocker 'awaiting first run of scripts/velocity/field_velocity_openalex.py', owner Lukas). - idea_vintage: series = median reference age with a ci_lo/ci_hi band; reliable=0 years render as a dashed tail and are excluded from direction. Direction is INVERTED (a falling median = building on fresher ideas = accelerating), computed in scripts/velocity/vintage-direction.mjs and covered by a node:test unit test (npm test). - revealed_commitments: the same CSV wires first_time_authors (talent entry) as the primary line with corpus_share_per_100k as a dashed normalizer; metric names it as the talent-entry component, with capital and job postings still unwired. Where a field already had a sourced reading (DHR / Electric Capital) the chart augments it. - Chart component gains a confidence band, a dashed unreliable tail, and a secondary normalizer line. Caveat rendered in both instrument modals. - Docs: src/data/velocity/README.md (CSV contract + frozen query strings) and scripts/velocity/README.md. No CSVs committed; the generator .py is added separately from Lukas's copy. - Demo screenshots (light + dark) captured from a throwaway CSV, which was deleted before this commit so no synthetic data lands. Stacks on #98. Draft gating unchanged.
…enAlex generator UI/copy pass on the field-velocity page: - Hero: retitle to 'PL R&D's impact on field velocity' and let the intro paragraphs run full width. - Inflection cards: drop the Defined/Emerging/Reached/Scaling progress bar, keep the status label. - Move the 'How to read this' button into the sticky focus-area column (under the last tab) so it stays visible while scrolling. - Field-velocity modal: remove the 'Owner: Lukas' line from unwired instruments. - Markets instrument: bring it back for Neurotech, and surface the live forecast markets already mapped to each field's inflection points (Polymarket / Kalshi / Metaculus) both in the box (compact) and the modal (full list + reflexivity caveat). EG markets becomes the not_applicable example (its markers are white space); DHR markets becomes unwired since it has proxy markets. Generator: - Add scripts/velocity/field_velocity_openalex.py (real, CC0). It queries the OpenAlex FILTER cluster (title_and_abstract.search, | = OR) to dodge the gated anonymous fulltext search, samples works per year, resolves referenced-work years, and bootstraps the idea-vintage median + CI. certifi TLS; capped backoff so an anonymous multi-hour 429 fails fast instead of sleeping. first_time_authors is intentionally left blank (a robust count needs per-author history, not a constant-size sample). No CSVs committed. Stacks on #98.
Pulled via scripts/velocity/field_velocity_openalex.py (OpenAlex, CC0) with the frozen per-field query strings. Each CSV carries its query + generated date in the # provenance block. idea vintage now renders a live chart with CI band, dashed unreliable tail (2024+), and the inverted direction; markets already read the mapped live forecasts. first_time_authors left blank by design. Regenerate + overwrite to refresh; git history is the time series. No secrets in the data (API key passed only at runtime). Stacks on #98.
…odology modals
- Sparkline extracted to a shared component (src/components/VelocitySparkline.tsx)
and given an optional labelled vertical axis (min/max of the series). Enabled on
the idea-vintage charts (box + modal) so the reader can see what the curve
indexes to (years).
- Idea vintage reading now states a start->latest comparison in its trend line
(e.g. '8.x y in 2005 -> 6.0 y in 2023, lower = fresher ideas') instead of only a
direction word.
- Methodology idea-vintage modal now renders the real per-field series as small
multiples ('What it looks like today').
- Methodology inflection-points modal gains the abbreviated named x mattered
framing: the two axes, the four quadrants (good case / hit-that-doesn't-lift /
unnamed acceleration / noise), canonical examples (k genome, AlphaFold, Watson,
AlexNet, transformers, HTS magnets), and the design implication.
Stacks on #98.
Bug: E&G showed '6.0y -> 7.0y' (references getting OLDER) yet a green 'Accelerating' chip. The chip used a trailing single-year slope while the text used two raw endpoints, and on a noisy sampled series they disagreed and over-claimed. Fix: derive BOTH the direction chip and the comparison text from one calculation — the mean of the earliest 3 reliable years vs the most recent 3 — with a 0.75y flat band so an in-noise wobble reads 'flat', not a trend. The comparison now shows those same window averages (e.g. '6.0y avg (2005-2007) -> 6.3y avg (2021-2023)'). Result on the real data: E&G flat (6.0->6.3), DHR decelerating (5.0->7.0), AI accelerating (5.3->3.7), Neurotech decelerating (6.3->8.7). Unit test updated to cover the in-noise = flat case. Stacks on #98.
…from OpenAlex, and the guards Address three OpenAlex pitfalls, and make the previously-bare sparklines legible: - 'How the chart is built': per-year keyword-cohort sample -> resolve each reference's publication year -> pooled median age -> bootstrap CI band -> early-vs-recent direction with a flat band. States it is a sampled estimate. - 'What we guard against in OpenAlex': (1) size is not velocity, so we read an age not a count and normalize any counts against corpus growth; (2) labels drift, so cohorts are frozen title+abstract keyword queries, not OpenAlex topic labels, with the query + retrieval date stored per series; (3) recent years lag, so the last ~2 years are dashed, excluded from direction, and compared like windows. - Aggregate-modal provenance now reads 'Keyword cohort (title + abstract): <query> retrieved <date>' to make the cohort + snapshot explicit at the point of use. Copy only; the underlying pipeline already used keyword cohorts, an age metric, and a reliable-year cutoff. Stacks on #98.
…ful use Lukas-style pass on the idea-vintage methodology copy: - 'How we build this from OpenAlex' now names the source up front (an open, CC0 catalogue of 250M+ works and their reference lists) and walks the build: keyword-cohort sample -> resolve each reference year -> pooled median age -> bootstrap CI -> early-vs-recent direction with a flat band. - Guards retitled 'Reading OpenAlex without its artefacts' with a one-line lead that OpenAlex is a moving target, then the three habits (age not count; frozen keyword cohort not topic labels; dash and drop lagging recent years). - Tightened wording (plain verbs, no em-dashes, specific numbers). Copy only. Stacks on #98.
added 2 commits
August 3, 2026 15:27
The four-step Defined -> Emerging -> Reached -> Scaling bar mixed a state of our own naming with states of the world; outcome x mattered now carries resolution. Drop it from the detail modal and the card stage label, delete the unused maturity field/type/helpers (InflectionStatus, FIELD_STAGES, stageIndexForStatus, STATUS_META, FIELD_TRACK), and fix the status line to read 'not yet reviewed' instead of 'reviewed not yet'.
Under 'PL R&D interventions', add a short, honest note: we don't claim our interventions directly cause a field to accelerate (attribution at the field level isn't cleanly identifiable); for now we name what we run and watch whether the field moves, and intend to make the link clearer and publish it later. No separate section, no grading machinery.
lksbrssr
force-pushed
the
lukas/impact-v2
branch
from
August 3, 2026 21:42
c0576e1 to
75b89d4
Compare
- Move /impact -> /impact-preview-eb61fba1b98e (cryptic, unguessable slug) - Remove Impact from main nav so it isn't discoverable on the site - Add robots noindex/nofollow (page + googleBot); already absent from sitemap - Deliberately NOT added to robots.txt (would publish the secret path) - Update stale /impact doc reference
lksbrssr
marked this pull request as ready for review
August 3, 2026 22:20
This was referenced Aug 3, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
👉 Clean, v2-only diff (excludes #29's commits): lksbrssr/plresearch.org@lukas/impact-dashboard...lukas/impact-v2
Routes to preview:
/impact-v2(new) ·/impact(unchanged from #29, for side-by-side)Why
The current dashboard measures success by "were the inflection points reached, and did that matter?" — which over-commits us to inflection points as the target. They're proxies: our current best guesses about what acceleration looks like. We can be wrong about a marker and still accelerate the field; a marker can resolve true without mattering.
The reframe
Side-by-side intent
/impact-v2is a separate route/component tree so the team can compare it against the original/impactbefore deciding anything. Neither replaces the other yet. A low-key cross-link on v2 points back to the original methodology.Scope / safety
/impactis byte-identical to Impact Dashboard #29 — the reframe lives entirely in new files (src/lib/field-velocity.ts,ImpactDashboardV2.tsx,MeasuringQuestionsV2.tsx,app/impact-v2/page.tsx) that import frominflection-points.ts/market-signals.tsrather than forking them.// TODO(lukas)"curating" states.npm run buildpasses; both routes prerender static.Review notes
pending; theretiredandmissed + field-movedexamples demonstrate the mechanic with transparent draft post-mortems. No real marker is markedhit(that would be a world-claim we can't yet make).Screenshots
See
docs/screenshots/README-impact-v2.md(v1 vs v2, cards + modals, light + dark).Update (2026-08-03) — folded in from the (now-closed) #102
Since the write-up above, the field-velocity dashboard was promoted to
/impact(the canonical route now rendersImpactDashboardV2), and two follow-up changes landed on this branch (1c8ab38,75b89d4). #102 was closed and folded in here.1 — Removed the maturity progress bar. The four-step
Defined → Emerging → Reached → Scalingbar is out of the detail modal and the cards;outcome × matteredalready carries resolution. Deleted the now-unused maturity field/type/helpers (no dead paths) and fixed the status line to readnot yet reviewed.2 — Attribution held honestly, folded into the interventions block. No grading ladder and no per-marker claim UI. Under "PL R&D interventions" in the methodology, a short note now reads: we don't claim these interventions directly cause a field to accelerate — attribution at the field level isn't cleanly identifiable; for now we name what we run and watch whether the field moves, and intend to make the link clearer and publish it here later.
npm run buildcompiles; tsc +node --testgreen.Screenshots (these changes)
Methodology — attribution note under "PL R&D interventions" (light / dark)