---
name: blueprint-verify-extract
description: "Extract every dated event, time and amount from the named documents into .blueprint/facts.json, each with a quotation it was read from — deciding nothing yet."
---
# Extract the dates, times and amounts
`.blueprint/answers.json` names the documents (`documents`, one path per line), what kind they are (`kind`),
the year to use for dates written without one (`year`, may be empty) and what the person is worried about
(`focus`). Read every document in full, starting with `focus`.
This step only reads and copies values out. It does **not** judge whether anything is wrong. That is decided by
machine in the next step, so do not skip an entry because it looks wrong. A wrong weekday or a wrong total is
exactly what must be extracted as written. Change nothing in the repository: the documents stay exactly as
they are. Write only under `.blueprint/`. A person reads the table you write before the machine judges it, so a
missed event is theirs to catch.
## Write `.blueprint/facts.json`
```json
{
"events": [
{
"id": "day1-depart",
"date": "2026-10-01",
"weekday": "木",
"start": "09:00",
"end": "11:30",
"title": "東京駅から新大阪駅(のぞみ)",
"citation": { "source": "itinerary.md", "address": "h2.1", "quote": "10月1日(木)9:00 東京駅発 → 11:30 新大阪駅着" }
}
],
"amounts": [
{ "id": "hotel", "label": "宿泊費", "value": 24000, "unit": "円", "citation": { "source": "estimate.md", "address": "h2.2", "quote": "宿泊費 24,000円" } }
],
"totals": [
{ "id": "grand-total", "label": "合計", "value": 36000, "unit": "円", "parts": ["hotel", "train"], "citation": { "source": "estimate.md", "address": "h2.2", "quote": "合計 36,000円" } }
],
"products": [
{ "id": "hotel-line", "label": "宿泊費", "value": 24000, "unit": "円", "of": ["hotel-rate", "hotel-nights"], "citation": { "source": "estimate.md", "address": "h2.2", "quote": "宿泊費 12,000円 × 2泊 = 24,000円" } }
]
}
```
- **One event per thing that happens at a time**: a departure, a check-in, a meeting. Keep them **in the order
the document gives them**, because the next step reads that order as the intended sequence.
- `date` is `YYYY-MM-DD`. When the document omits the year, use `year` from the answers. If that is empty too,
write the date as `MM-DD` (`"10-01"`) and give it no `weekday`: a weekday without a year cannot be checked,
and the check refuses one.
- `weekday` is copied **as written** (「木」「(木)」「Thu」). Leave it out when the document gives none. Never add
one the document does not have, and never correct one.
- `start` / `end` are `HH:MM`, 24-hour. Leave out what the document does not say. A range that writes AM/PM once
covers both times: `1:00–5:00 PM` is 13:00–17:00, `午後1時〜5時` is 13:00–17:00.
- `amounts` are the lines that add up; `totals` are the lines that claim to be their sum (合計, 小計, Total),
with `parts` naming the amount ids they add up. A subtotal that is itself part of a grand total is both: list it
as an amount too, under another id, and name that id in the grand total's `parts`.
- `products` are the lines that claim to be a product: a line's amount that is its unit price times its quantity
(単価 × 数量), a tax that is a subtotal times a rate. `of` names the amount ids multiplied, two or more: the price
and the quantity (`unit` 台, 泊, 個, pcs — as written), or the subtotal and the rate (`value` 10, `unit` `%`).
Like a subtotal, a line that is also added into a total is listed as an amount too, under another id. Extract a
product only where the document gives every factor; a line with no quantity written is not one.
- `value` is a plain number (`24000`, not `"24,000円"`); `unit` is the currency or unit as written (円, USD).
- `id`: lower-case letters, digits and `-`, unique across the whole file.
- `citation.quote` is copied character for character from the document and **must contain every value of its
entry**: the month and day, the weekday, each time, the amount. A quote may run over a line break (for a
date in a heading above the times, quote from the heading through the line). `address` uses `chaff tree`'s
addresses (`sh /checks/chaff.sh tree `).
## Done when
`node /checks/extract.mjs` (with `BLUEPRINT_BASE` and `BLUEPRINT_USECASE` set to the pack folders
from your prompt) passes. It fails on a value that is not in its own quotation (a misread), on a quotation
`chaff cite` cannot find in the document, and on a malformed entry. Fix the extraction, not the check.