# Canonical schema — Tokyo 23-ku childcare (保育) open data normalization

Two record types. Emit whichever apply to a given source; most wards will produce some of each.

## 1. `childcare_facility` (per-facility records)

```json
{
  "ward": "港区",
  "ward_romaji": "Minato",
  "facility_id": "ward-local ID if the source has one, else a stable slug you generate (romaji-name-based)",
  "facility_name": "string, as given in source",
  "facility_type": "one of: 認可保育所 | 認証保育所A型 | 認証保育所B型 | 認可外保育施設 | 認定こども園 | 地域型保育事業 | 事業所内保育所 | 学童クラブ | 一時保育 | 病児保育 | other (specify in notes)",
  "address": "string or null",
  "lat": "number or null",
  "lon": "number or null",
  "capacity_total": "number or null (定員)",
  "capacity_by_age": "object {\"0\":n,\"1\":n,...} or null",
  "enrolled_total": "number or null (在籍数)",
  "enrolled_by_age": "object or null",
  "vacancy_count": "number or null (空き数)",
  "as_of_date": "YYYY-MM-DD or null — use the source's stated reference date, do not guess",
  "granularity": "per_facility",
  "source_format": "csv | xlsx | pdf | json | xml | html",
  "source_url": "string — must be a URL you actually retrieved",
  "source_dataset_title": "string",
  "notes": "string or null — caveats: staleness, extraction uncertainty (e.g. PDF table parsed by eye), missing fields, etc."
}
```

## 2. `childcare_ward_stat` (ward/area-aggregate time-series records — waitlist counts, capacity totals, etc. that are NOT broken out per facility)

```json
{
  "ward": "港区",
  "ward_romaji": "Minato",
  "period": "YYYY-MM or YYYY年度 — as granular as the source states",
  "metric": "capacity_total | enrolled_total | waitlist_count | applicants | facility_count | other (specify in notes)",
  "value": "number",
  "unit": "string or null",
  "granularity": "ward_aggregate",
  "source_format": "csv | xlsx | pdf | json | xml | html",
  "source_url": "string — must be a URL you actually retrieved",
  "source_dataset_title": "string",
  "notes": "string or null"
}
```

## Rules

- **Never fabricate a URL, dataset title, or numeric value.** If you cannot access a source, say so in your summary — do not invent plausible-looking data.
- If a ward genuinely has no findable childcare open data after checking all three channels below, write an empty array to its output file and say so plainly in your summary — that is a valid, useful result (a finding of absence), not a failure.
- Three channels to check per ward, in this order of likely yield:
  1. That ward's own organization page on the tocho CKAN catalog (`catalog.data.metro.tokyo.lg.jp` — may be WAF-blocked to direct fetch; try `search.ckan.jp` as a mirror, or web search `site:catalog.data.metro.tokyo.lg.jp <ward name> 保育`).
  2. The Tokyo Open Data API Catalog (`spec.api.metro.tokyo.lg.jp`) — search there for the ward name + 保育/学童.
  3. The ward's own independent open-data portal (web search `<ward name>区 オープンデータ 保育`).
- Output: write one JSON file per ward to `/home/rmondo/repos/open-data-hackason/poc/childcare-data/normalized/<ward_romaji>.json` shaped as `{"facilities": [...], "ward_stats": [...]}`. Save any raw files you download (CSV/Excel/PDF) under `/home/rmondo/repos/open-data-hackason/poc/childcare-data/raw/<ward_romaji>/`.
- For PDFs/Excel you can't parse programmatically, read/view them and transcribe the real numbers into the schema by hand — don't skip a source just because it isn't a clean CSV.
