Skip to content

Feat/resolver (key features) - #998

Merged
AlexAxthelm merged 20 commits into
epic/v2from
feat/resolver
Oct 29, 2026
Merged

AlexAxthelm merged 20 commits into
epic/v2from
feat/resolver

Conversation

@AlexAxthelm

@AlexAxthelm AlexAxthelm commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Resolve key features according to context (sector/geography selection).


Summary

Key features on the pathway detail page now follow the scope ribbon (sector + geography), like the plots and tables already do. Each feature shows the value the pathway records for the selected scope. Where there is none, it falls back to the closest broader scope, and a badge says where the value came from.

How a value is chosen

  • The selected sector is searched first, across the selected geography and then every declared region that contains it (smallest first), across regions, and Global. Only then does it try the same geographies under across sectors. So Power · Global beats across sectors · Thailand.
  • Lookups use exact tokens. A region is only a fallback for a selection it fully contains; overlapping isn't enough.
  • An empty axis means the pathway's widest scope on that axis.
  • "Not applicable at this scope level" and "Not Applicable" cells are skipped: they mean "not recorded here". An authored "No information", "None" or "No new technologies" is the pathway's answer and stops the search.

What readers see

  • Inherited values get a small outlined badge naming their source, e.g. Across sectors · ASEAN. Its tooltip explains why.
  • "No information" looks the same whether it's the pathway's own answer or nothing is recorded anywhere. Only the tooltips differ: "The pathway does not report this" vs "Nothing is recorded for this pathway at any scope".
  • Electrification × Power (per review): Power's "Not Applicable" cell is skipped and the across-sectors value is shown, badged, with the tooltip "Electrification does not apply to the Power sector…". The page never shows "Not applicable". Power-only pathways with nothing across sectors show "No information".
  • Scope ribbon (feat(ui): context filters only clickable when there is relevant data #1017): on the detail page, a sector or geography now counts as having something to show if a key feature records an informative value at exactly that token. This gives 32 pathways their first selectable geography (every Power-only SDSN pathway, PHDOE, IEA STEPS/CPS/NZE 2025 among them), and makes IEA 2025's country-level key features reachable (with Fix/single country regions #1035).
  • SMR is now offered among the new technologies. The schema allowed it, but the UI didn't list it. A test now checks every feature's options against the schema.

Not changed here: the comparison page still shows each pathway's widest value. Resolving it per column is the stacked follow-up PR.

Code

  • keyFeatureRules.ts (new): scope sentinels, the "not applicable" checks, which countries a pathway's own geography token covers, and a pathway's widest sector and geography. It has only type imports, so the schema-check script can import it under ts-node.
  • keyFeatureResolution.ts (new): createKeyFeatureResolver / resolveKeyFeature, geographyChain and sourceScopeLabel.
  • KeyFeatures / FeatureItem render from a resolution when given a pathway and scope. Without them, the output is byte-identical to before (checked across real pathways and every display mode).
  • New scope Badge variant; scopeAvailability takes { keyFeatures: true }; scopeSelectionLabel words the sentinels in prose.

Related issues

Part of #869 (resolver) and #859 (scope badges), for the detail page; the comparison page follows in a stacked PR. Builds on #872, #1017 and #1035.

Testing

  • Unit tests for the rules, the resolver (chain order, skipped vs final values, fallbacks, Electrification) and scope availability. Component tests for every rendering state and tooltip. Detail-page tests that both key-feature panels (At a glance and Assumptions & Dependencies) follow the ribbon, and that a sector with only key features is selectable.
  • Real data: resolved every v2 pathway at its default scope, and checked Electrification on Power across all of them.
  • Browser checks on the preview:

Follow-ups (not in this PR)

  • Comparison page (stacked PR):
    • resolve each column's key features;
    • pass { keyFeatures: true } to its scopeAvailability;
    • drop KeyFeatures' keyFeatures prop;
    • delete widestValue and the breadth helpers.
  • Key-feature validation:
    • Where must "Not Applicable" appear? The cookbook records "No information" for Electrification on Power-only pathways, and today 14 Power-only files say "Not Applicable" while 6 say "No information".
    • Reject an across-sectors Electrification row on a Power-only pathway (there, "across sectors" is Power).
    • Reject arrays that mix the scope-level sentinel with real values.
  • Open question: should a key feature ever be recorded at a country that only appears inside a multi-country region (e.g. ACE Buildings · Thailand)? The ribbon can't select it.
  • Separate issues: the duplicated sentiment/neutral rendering in FeatureItem; the detail page rendering one frame at its widest scope before the ribbon's scope applies.

Checklist

  • PR is focused on a single concern
  • Tests pass locally and in CI
  • Docs updated for user-visible changes
  • AI-assisted portions declared (see CONTRIBUTING.md)

AI assistance: implemented with Claude Code (Claude Opus 5.5) from a written plan, in reviewed steps; the author reviewed each change and directed the design decisions.

🤖 Generated with Claude Code

repro and others added 6 commits October 16, 2026 14:07
First slice of #869. Adds src/utils/keyFeatureRules.ts, holding:
- the scope sentinels
- the forbidden Electrification x Power combination
- the "Not applicable at this scope level" check
- declaredTokenCodes, the countries one of a pathway's own geography
  tokens covers
- widestSector and widestGeography

The module has only type imports, so validateScopes.ts can import it
under ts-node in a later PR. keyFeatureScope.ts now re-exports the
sentinels from it instead of defining its own copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds src/utils/keyFeatureResolution.ts. For the selected sector and
geography, resolveKeyFeature returns the value a pathway reports and
where it was found. The lookup is an exact token match: it walks the
selected sector through the geography chain first, then the same chain
under "across sectors".

- geographyChain: the selection, then every declared token that contains
  it (smallest first), then "across regions", then "Global"
- A missing entry or a "Not applicable at this scope level" cell keeps
  the walk going; an authored "No information", "None" or "No new
  technologies" ends it
- Electrification x Power returns "forbidden" before the walk, so it
  never inherits an "across sectors" value
- An empty selection axis is filled with the pathway's widest scope
- sourceScopeLabel names the source scope for the fallback badge

asEntries is now exported from keyFeatureScope.ts so the resolver reuses
the same malformed-input handling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
KeyFeatures takes optional pathway and scope props. With a pathway, it
resolves each feature for the scope and passes the result to
FeatureItem, which renders:
- an inherited value with an outlined badge beside the label naming
  where it came from, e.g. "Across sectors · South East Asia"
- authored and exhausted "No information" with different tooltips
- a forbidden combination (Electrification x Power) as "Not
  applicable", with nothing selected

Adds the outlined neutral "scope" Badge variant. Without a pathway,
rendering is unchanged; the comparison page keeps using that until 1b.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both KeyFeatures panels on the detail page now receive the pathway and
the ribbon's scope, so each key feature shows the value for the selected
sector and geography, badged when it is inherited from a broader scope.

The scope and tabs page tests now spell the sector sentinel
"across sectors": the resolver looks scopes up exactly, so the retired
"cross-sector" matched nothing. The scope test now checks that changing
the ribbon changes the resolved value and its badge, on both axes.

Also updates comments that still described #869 as future work or
said the resolver uses the search filter regions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 21, 2026 09:46
@AlexAxthelm
AlexAxthelm changed the base branch from main to epic/v2 October 21, 2026 09:46
createKeyFeatureResolver works out the effective scope and the sector
and geography fallback order once for a pathway and selection, and
returns a function that resolves one field at a time. KeyFeatures now
creates one per render instead of rebuilding them for each of the 11
features. resolveKeyFeature remains as a one-field wrapper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Expected version change and release notes

🚨 WARNING: This PR is not expected to trigger a new version

To trigger a version bump, use at least one conventional commit message in this branch. See: https://www.conventionalcommits.org/en/v1.0.0/

@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://proud-glacier-0f640931e-998.westus2.2.azurestaticapps.net

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Valid country-scoped values can be skipped during fallback, and unavailable tooltips overstate the absence of data.

2 open issues
What changed in this PR

Adds scope-aware key-feature resolution to the pathway detail page, while preserving comparison-page rendering.

Changes:

  • Introduces shared scope rules and sector-first fallback resolution.
  • Adds inherited-scope badges and distinct absence states.
  • Expands resolver, component, and detail-page tests.
File Description
src/​utils/​scopeSeed.ts Corrects scope terminology in comments.
src/​utils/​keyFeatureScope.ts Reuses shared constants and exports entry helper.
src/​utils/​keyFeatureRules.ts Defines shared scope and applicability rules.
src/​utils/​keyFeatureRules.test.ts Tests shared rules.
src/​utils/​keyFeatureResolution.ts Implements fallback resolution and source labels.
src/​utils/​keyFeatureResolution.test.ts Tests resolution ordering and edge cases.
src/​utils/​filterRegions.ts Clarifies search versus resolver behavior in comments.
src/​pages/​PathwayDetailPage.tsx Passes ribbon scope into key features.
src/​pages/​PathwayDetailPage.tabs.test.tsx Updates fixture scope tokens.
src/​pages/​PathwayDetailPage.scope.test.tsx Tests scope-dependent values and badges.
src/​components/​KeyFeatures.tsx Renders resolved values and explanatory states.
src/​components/​KeyFeatures.test.tsx Tests resolver-driven rendering.
src/​components/​Badge.tsx Adds neutral scope-badge styling.
src/​components/​Badge.test.tsx Tests scope-badge styling.
PLAN.md Documents implementation and follow-up work.

Review effort: Balanced

Comment thread src/components/KeyFeatures.tsx Resolved
Comment thread src/utils/keyFeatureResolution.ts Resolved
repro and others added 4 commits October 21, 2026 12:14
scopeSelectionLabel now writes "all sectors" for "across sectors" and
"all regions" for "across regions". A scope filled in from empty axes
reads "No value for all sectors in all regions" rather than "across
sectors in across regions". The ribbon never selects either sentinel,
so existing notices are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
KeyFeatureKey in keyFeatureRules.ts replaces FeatureKey in
KeyFeatures.tsx, KeyFeatureSection in tooltipUtils.ts and the inline
keyof in ScopedKeyFeature. It stays in keyFeatureRules so the validator
can import it under ts-node. Type-only change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The scope test now runs on the At a glance tab (the default) as well as
Overview. Each tab renders its own KeyFeatures panel, and until now
only Overview's wiring was covered, so At a glance could lose its scope
without a test failing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The v2 schema added SMR (cookbook decision 0020), but the pill options,
the tooltips and the methodology page never listed it. A pathway that
reported SMR showed nothing selected, or "No information". A new test
checks every feature's options against the schema, so the next value
the schema adds can't go missing the same way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Expected version change and release notes

🚨 WARNING: This PR is not expected to trigger a new version

To trigger a version bump, use at least one conventional commit message in this branch. See: https://www.conventionalcommits.org/en/v1.0.0/

@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://proud-glacier-0f640931e-998.westus2.2.azurestaticapps.net

@AlexAxthelm

Copy link
Copy Markdown
Collaborator Author

@jacobvjk An outstanding question at this point: fallback for single-country regions (IEA STEPS/CPS 2025 have regions like "Japan" = JP, "Brazil" = BR) isn't clearly defined. Selecting the region "Japan" never looks at a value recorded at the country JP, even though they cover the same place. Nothing is recorded that way today, but the data checks allow it.
I think the right answer might be to treat a scope that matches in coverage (but not in name) as an exact match, with no fallback badge. That might also help with some of the ASEAN/SEA naming on the compare page, though only where two publishers' regions list exactly the same countries (ACE's ASEAN has 10 and JRC's South East Asia has 13, so not those two).
Claude's commentary below:


One more point to discuss on the key-features PR: values recorded at a country that sits inside a region.

The data checks let a key feature be recorded at any country inside one of the pathway's regions, even if that country isn't listed on its own. No pathway does this today, but two things go wrong if one does:

  1. The value can't be reached. The geography choices on the detail page are the pathway's own regions and listed countries. If ACE recorded something at Buildings · Thailand, nothing would show it: Thailand isn't offered (only ASEAN is), and selecting ASEAN correctly doesn't look inside it.
  2. Single-country regions are skipped. IEA STEPS/CPS 2025 have regions that are one country each: "Japan" = JP, plus Brazil, India, Russia and United States. A value recorded at JP is skipped when "Japan" is selected, even though it's the same place.

Questions:

  • Should key features ever be recorded at a country that's only part of a region? If not, we can make the data checks reject it. If so, the page needs to offer those countries.
  • Is region "Japan" the same scope as country "JP"? If so, a value at one should count as an exact match for the other, with no "inherited from" badge.

@jacobvjk

Copy link
Copy Markdown
Collaborator

fallback for single-country regions (IEA STEPS/CPS 2025 have regions like "Japan" = JP, "Brazil" = BR) isn't clearly defined. Selecting the region "Japan" never looks at a value recorded at the country JP, even though they cover the same place. Nothing is recorded that way today, but the data checks allow it. I think the right answer might be to treat a scope that matches in coverage (but not in name) as an exact match, with no fallback badge. That might also help with some of the ASEAN/SEA naming on the compare page, though only where two publishers' regions list exactly the same countries (ACE's ASEAN has 10 and JRC's South East Asia has 13, so not those two).

@AlexAxthelm if we treat "Japan" = JP as a region Japan that is an exact match to JP (intuitively right), what would that mean at the level of the UI? does this somehow look different to just a plain country mapping? Ideally I would think it should not.
What happens if we record "Bananas" = DE? if I filter for Germany, will the UI tell me that I am trying to look at "Bananas"?
In consequence, shouldn't we just say that any mapping to one ISO2 code is simply treated as a country, not a region?

@AlexAxthelm

Copy link
Copy Markdown
Collaborator Author

@AlexAxthelm if we treat "Japan" = JP as a region Japan that is an exact match to JP (intuitively right), what would that mean at the level of the UI? does this somehow look different to just a plain country mapping? Ideally I would think it should not.

Probably not too much at the level of the UI immediately, but for example in STEPS 2025, there aren't any "individual countries" in the authored data, but the Japan region happens to only map to one country.

image

We're already doing set comparison between the set of ISOs in the context and the set in each region. I think it's pretty easy to extend that so if the set size is 1, we can see if it matches any individual country codes. That gives us a little bit of "looking down" the resolution stack, rather than strictly country < region < bigger region < Global, but I think that's going to be better on the comparison page, where we can then have a easier time comparing Japan (region) to JP (country)

What happens if we record "Bananas" = DE? if I filter for Germany, will the UI tell me that I am trying to look at "Bananas"?

This is what already happens (like the "Bananas" region pill on the scenario card would float to the front, etc). But right now, if you filter "Bananas", you don't get "DE" results. I think that's the change we want to go with.

In consequence, shouldn't we just say that any mapping to one ISO2 code is simply treated as a country, not a region?

Collapsing this in authoring would also be fine. we could set the schema so that regions have to have at least 2 countries 🤷 What I outlined above gives a bit more authorial flexibility, if there's a reason to use a different name (the "Bananas" example above).ab We also have some regions right now that don't have mappings, so we would need to figure out how we want to handle those

@jacobvjk

Copy link
Copy Markdown
Collaborator

I'm still not sure if "Not applicable" for electrification in the power sector should show as seen here or if it's better to fall back to "across sectors". Point being that if we make sectors that are not covered yet not selectable, then this would mean that you can effectively not get any information about electrification (all pathways would be pre-selecting power and that's it)
Screenshot 2026-10-22 at 10 59 02

@jacobvjk

Copy link
Copy Markdown
Collaborator

The resolver should also filter context in the comparison view and show relevant fallback badges.
This example demonstrates this is ot the case, because electrification is "Not applicable" to the power sector. The across sectors value is shown here, which means the context is not considered.

Screenshot 2026-10-22 at 11 15 00

@jacobvjk

Copy link
Copy Markdown
Collaborator

@AlexAxthelm if we treat "Japan" = JP as a region Japan that is an exact match to JP (intuitively right), what would that mean at the level of the UI? does this somehow look different to just a plain country mapping? Ideally I would think it should not.

Probably not too much at the level of the UI immediately, but for example in STEPS 2025, there aren't any "individual countries" in the authored data, but the Japan region happens to only map to one country.

image We're already doing set comparison between the set of ISOs in the context and the set in each region. I think it's pretty easy to extend that so if the set size is `1`, we can see if it matches any individual country codes. That gives us a little bit of "looking down" the resolution stack, rather than strictly country < region < bigger region < Global, but I think that's going to be better on the comparison page, where we can then have a easier time comparing `Japan` (region) to `JP` (country)

What happens if we record "Bananas" = DE? if I filter for Germany, will the UI tell me that I am trying to look at "Bananas"?

This is what already happens (like the "Bananas" region pill on the scenario card would float to the front, etc). But right now, if you filter "Bananas", you don't get "DE" results. I think that's the change we want to go with.

In consequence, shouldn't we just say that any mapping to one ISO2 code is simply treated as a country, not a region?

Collapsing this in authoring would also be fine. we could set the schema so that regions have to have at least 2 countries 🤷 What I outlined above gives a bit more authorial flexibility, if there's a reason to use a different name (the "Bananas" example above).ab We also have some regions right now that don't have mappings, so we would need to figure out how we want to handle those

I would tend to argue that:

  • We do not need the authorial flexibility for one country-code cases. One country code is always a country.
  • I am also a bit bothered by the unmapped regions. I think they also usually do not have much data. I think we might just drop them and have the importer issue a warning so we can decide if it is worth chasing the publisher or if we just remove them

repro and others added 3 commits October 26, 2026 13:12
Electrification can't apply to the Power sector, and the detail page
opens on Power for almost every pathway, so showing "Not applicable"
hid electrification wherever readers first saw it. The resolver now
skips Power's rows for that field and falls back to across sectors like
any missing value. The badge's tooltip says the feature doesn't apply to
Power. A pathway with nothing across sectors shows "No information", as
any exhausted fallback does.

Replaces the "forbidden" resolution and its "Not applicable" rendering.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The resolver no longer keeps its own list of forbidden field and sector
pairs. A "Not Applicable" cell is skipped like the scope-level sentinel,
so Electrification x Power still falls back to across sectors, and the
badge still says the feature doesn't apply there. Which pairs must be
"Not Applicable", and that it appears nowhere else, becomes PR 2's
validation rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Expected version change and release notes

🚨 WARNING: This PR is not expected to trigger a new version

To trigger a version bump, use at least one conventional commit message in this branch. See: https://www.conventionalcommits.org/en/v1.0.0/

@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://proud-glacier-0f640931e-998.westus2.2.azurestaticapps.net

@jacobvjk

Copy link
Copy Markdown
Collaborator

For "Electrification", when there is only power sector coverage, I realize that we record "No information" (based on the cookbook), not "Not applicable". Does this mean that there is effectively not situation left, when we would display "Not applicable"? https://proud-glacier-0f640931e-998.westus2.2.azurestaticapps.net/pathway/SDSN-CW-BAU-SG-2024?tab=overview

repro and others added 3 commits October 28, 2026 16:08
… fixtures

and tests that treated empty or single-country regions as real data now
describe data the schema rejects. Their fixtures no longer type-check.
This follows e124bd2: comments updated, the empty-set guards kept for
stale tokens and malformed input, fixtures given two or more members,
and the single-country cases rewritten as countries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n select

The detail page resolves key features for the selected scope (#869), so a
sector or geography whose only data is key features now has something to
show. scopeAvailability counts informative key-feature values at exactly
that token when asked: not the not-applicable markers or "No
information", and an across-sectors or Global value doesn't stand in for
other tokens. The detail page turns this on. The comparison page leaves it
off until it resolves key features per column (noted for 1b in PLAN.md).

Gives 32 pathways their first selectable geography, including IEA
STEPS/CPS 2025 and every Power-only SDSN pathway, and makes IEA 2025's
country-level key features reachable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Expected version change and release notes

🚨 WARNING: This PR is not expected to trigger a new version

To trigger a version bump, use at least one conventional commit message in this branch. See: https://www.conventionalcommits.org/en/v1.0.0/

@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://proud-glacier-0f640931e-998.westus2.2.azurestaticapps.net

@github-actions

Copy link
Copy Markdown

Expected version change and release notes

🚨 WARNING: This PR is not expected to trigger a new version

To trigger a version bump, use at least one conventional commit message in this branch. See: https://www.conventionalcommits.org/en/v1.0.0/

@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://proud-glacier-0f640931e-998.westus2.2.azurestaticapps.net

repro and others added 2 commits October 29, 2026 09:47
…its title

Assumptions tab, "Assumptions & Trends Preview" on At a glance), so two
scope tests waiting for "Assumptions & Trends Overview" timed out once
the PR was merged into epic/v2. They now wait for the Emissions group
heading they assert on, which neither tab renames.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Expected version change and release notes

🚨 WARNING: This PR is not expected to trigger a new version

To trigger a version bump, use at least one conventional commit message in this branch. See: https://www.conventionalcommits.org/en/v1.0.0/

@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://proud-glacier-0f640931e-998.westus2.2.azurestaticapps.net

@AlexAxthelm AlexAxthelm changed the title Feat/resolver Feat/resolver (key features) Oct 29, 2026
@AlexAxthelm
AlexAxthelm requested a balanced review from Copilot October 29, 2026 09:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unavailable multi-select resolutions fail to show the “No information” badge, and the absence tooltip incorrectly implies that no values exist at any scope.

1 open issue
2 resolved since last review

Review effort: Balanced

Comment on lines +448 to +450
: feature.options.map((opt) =>
pill(opt, selectedArr.includes(opt)),
)}
@AlexAxthelm

Copy link
Copy Markdown
Collaborator Author

@jacobvjk

Opening for review. I'll have a followup PR to handle a last edge case around the forbidden combos stuff (electrification/power), but that one is going to be a lot smaller than this.

My general approach there (if you agree) is going to be:

  • reject authored values for forbidden combos
  • if there's no fallback value, show a "Not Applicable"
  • if there is a fallback (electrification/across sectors), show that with a tooltip "X does not apply to Y sector; showing closest broader scope this pathway reports"

other than that, there's a few small wording things that I may bother opening PRs for, but none of them are for paths/combos that exist in the current data.

Claude outlines all of it below:

following up on your question about Electrification on Power-only pathways (whether there's any case left where we'd show "Not applicable"):

Today: no. Electrification on Power never shows "Not applicable" any more. Power's "Not Applicable" cell is skipped and the across-sectors value is shown with a badge, e.g. IEA NZE 2024. On a Power-only pathway there's nothing across sectors, so it falls through to "No information", and the hover wrongly says "Nothing is recorded for this pathway at any scope" (e.g. JETP CIPP; 57 pages like this).

Proposed approach:

  1. Data: no authored values at all for forbidden combinations (Electrification · Power). The validator rejects them and "Not Applicable" leaves the schema. This replaces decision 0023's "Not Applicable" and the "No information" convention for Power-only pathways. The pair is declared once and shared by the validator and the page.
  2. With a fallback: as today, the across-sectors value with a badge, hover "Electrification does not apply to the Power sector; showing the closest broader scope this pathway reports."
  3. Without a fallback (Power-only pathways): show "Not applicable" (not "No information") with the hover "Electrification does not apply to the Power sector." That way "No information" keeps meaning "the pathway could say something here and doesn't".

The page side is a small change and could go into this PR before merge. The validator rule and the data clean-up would go in the validation PR, which will fail CI until the workbook is updated. Does that work for you, and is the cookbook OK with dropping these rows?

Two smaller wording points:

  • For other features, an exhausted fallback still says "Nothing is recorded for this pathway at any scope", which overstates: we only search broader scopes, not other sectors. Suggest: "Nothing is recorded for this scope or any broader one." No current page hits this.
  • Multi-select features with nothing to show leave every pill unselected, with no "No information". No current page hits this either. Fine to defer to Distinguish badge style in Key Features more cleanly from badge style in Coverage #852, or fix here if you prefer.

@AlexAxthelm
AlexAxthelm marked this pull request as ready for review October 29, 2026 10:20
@AlexAxthelm
AlexAxthelm requested a review from jacobvjk October 29, 2026 10:20
@AlexAxthelm
AlexAxthelm merged commit 43fe5bb into epic/v2 Oct 29, 2026
12 checks passed
@AlexAxthelm
AlexAxthelm deleted the feat/resolver branch October 29, 2026 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants