# Graph Family Public Specification

This document describes the public specification of the graph family centered on `graph.html`.

Scope:

- `graph.html`
- `party-proportional.html`
- `party-constituency.html`

Primary goals:

- let humans confirm the role and boundary of the graph family
- give AI systems a stable public reading path
- state what the graph surface reads, renders, and does not promise
- summarize what the current public graph can actually do

## 1. Public routes

- canonical public route: `/graph.html`
- route family:
  - `/graph.html`
  - `/party-proportional.html`
  - `/party-constituency.html`
- canonical public base: `https://jp-election-public-ja.pages.dev`

This specification is published as an independent document linked from the lower part of the graph page.

## 2. Role of the graph family

`graph.html` is a presentation surface for municipality, prefecture, and national series exploration.

The page:

- reads published packets
- uses a selector index to choose municipalities
- does not recompute aggregate series on its own in the browser
- handles locale, theme, and layout as presentation-layer concerns

The page does not:

- read `ops/status/` as its authority source
- expose internal worklogs or private-viewer-only material
- invent series that are not present in the public packet

## 3. Main inputs

### 3.1 graph packet

Primary packet:

- `/analysis/graph-family/latest/graph-page.json`

This packet carries the shell contract for the graph family.

Main roles:

- page metadata
- source release version
- scope coverage
- page asset paths
- dataset entry public keys
- pipeline stage status

### 3.2 selector index

Municipality selector:

- resolved through `selector_index_path`

Main fields:

- `jis_code`
- `prefecture_code`
- `prefecture_name`
- `municipality_name_ja`
- `graph_payload_path`
- `stats_series_path`
- `party_votes_path`

The graph page uses the selector index to determine both available municipality choices and the payload path to read.

### 3.3 graph payload

Municipality-scoped payloads are read from `graph_payload_path`.

Main contents:

- `summary`
- `timeline_slots`
- `components`
- `stats_series`
- `stats_component_series`
- `parties`
- `party_vote_series`
- `party_series`

The public page uses this payload for rendering. Canonical fact judgment stays outside the page and depends on public packets and dictionaries.

## 4. Coverage

Primary scopes of `graph.html`:

- municipality
- prefecture
- national

The current page is organized as a municipality-first explorer.

It also carries auxiliary:

- prefecture series
- national series

inside the same family.

## 5. What This Graph Can Do

The current `graph.html` should be treated as a public explorer with these capabilities.

- explore municipality, prefecture, and national series
- switch between `ja / en`
- switch between `mobile / desktop / auto`
- switch between party-vote series and turnout/stat series
- filter by vote system (`proportional / constituency / block / multi`, etc.)
- limit the visible time range with start / end selectors
- add a bar overlay when needed
- inspect per-series tooltips with date, election type, vote system, and scope
- show party-leader labels for some parties when public leader data exists
- create up to three custom comparison series (`custom_a`, `custom_b`, `custom_c`)
- read an on-page legend for the currently rendered series

AI systems should treat this page as an interactive explorer over public packets, not as a static narrative page.

## 6. UI contract

### 6.1 layout

Layout modes:

- `auto`
- `mobile`
- `desktop`

Default is `auto`, which resolves to mobile or desktop from viewport width.

### 6.2 locale

Locales:

- `ja`
- `en`

In English mode, party labels prefer `name_en` when available. When no English name exists, the page falls back to a public presentation label.

### 6.3 party blocks

The party selector is split into two blocks:

- `As of 2026-02-08`
- `Merged / dissolved`

Meaning:

- the upper block is the main group for series present in the `2026-02-08` election set
- the lower block contains older series that are not in the main group

Inside the upper block, the page also separates:

- `Proportional`
- `Constituency`

Within each family:

- series that contest in the `2026-02-08` election set appear first
- continuing series that do not contest there are placed after them

On mobile:

- `As of 2026-02-08` is open by default
- `Merged / dissolved` is collapsed by default

### 6.4 custom series

The page exposes three synthetic comparison series:

- `custom_a`
- `custom_b`
- `custom_c`

Meaning:

- user-defined aggregates of existing displayed series
- combined in the browser for presentation
- not canonical release-fact categories

Current UI contract:

- each custom series has its own visibility toggle
- each custom series has its own member selection
- the custom editor follows the same current / legacy ordering used by the main selector

### 6.5 year selector

Election years use the existing range selector.

It is treated as:

- start
- end

range selection.

### 6.6 axis / legend / tooltip

Current rendering contract:

- the X axis follows actual `election_date`
- visible labels use `YYYY/M/D + short election type`
- the Y axis is recalculated from the visible series
- the top bound uses the nearest upper tick above the maximum visible value
- the legend sits below the graph
- custom series appear as independent legend rows

Tooltip contract:

- election date
- election type
- vote system
- selected scope
- value
- party leader label when available

## 7. Display priorities

This page is a series explorer, so it prioritizes showing the graph itself first.

Especially on mobile, the preferred order is:

- graph first
- selector second
- auxiliary controls later

## 8. AI reading guide

When AI systems read this surface, they should proceed in this order.

1. Read `graph-page.json` to confirm the page contract and scope status
2. Read the selector index to obtain available municipality choices and payload paths
3. Read the graph payload for `timeline_slots / party_series / stats_series / party_vote_series`
4. Read public party continuity dictionaries when lineage interpretation matters
5. Treat locale labels as presentation fields and prefer `party_id / jis_code / election_set_key / seriesId` for joins

Additional public dictionaries relevant to AI interpretation:

- `party_master`
- `party_lineage_link`
- `party_graph_stream`
- `party_graph_stream_member`
- `party_leader_term`

Current UI semantics that AI should understand:

- `Merged / dissolved` means “older series not in the 2026-02-08 main block,” not necessarily a legal dissolution label
- custom series are user-defined aggregates, not canonical lineage classes
- on-screen colors are visual aids, not authority keys

Notes:

- UI chips and button labels are not authority sources
- do not infer canonical ordering from on-screen order alone
- a missing series may reflect packet coverage rather than a rendering error

## 9. Public boundary

This specification and the graph family are part of the public surface.

Allowed:

- graph packets
- selector indices
- public docs
- public analysis payloads

Not allowed:

- internal ops memos
- private-viewer-only routes
- internal paths that leak provenance
- ad hoc notes that overwrite release truth

Canonical release truth remains in the public release manifest and public catalog.

## 10. Related public documents

- `/docs/README.md`
- `/docs/english-conversion-guide.md`
- `/docs/tidy-rule.md`
- `/docs/artifact-layers.md`
- `/docs/normalization-rules.md`

## 11. AI Short Summary

For a fast AI-oriented understanding:

- `graph.html` is a municipality-first public explorer
- authority comes from public packets and public dictionaries, not from the UI itself
- current / legacy / custom are UI groupings, not release-truth layers
- `party_id`, `seriesId`, `election_set_key`, and `jis_code` are the main join keys
- tooltips and legends help users read the page but do not replace canonical fact tables

## 12. Stability

This document describes the public contract of the graph family.

Likely to change:

- visual layout
- link placement
- selector grouping

Expected to remain relatively stable:

- packet-first reading
- first-class selector index
- no browser-side aggregate regeneration
- no mixing of public and internal boundaries
