# hatake > A definition-first framework: business screens (Flutter) and backend API logic (Java / TypeScript — validation, query building, API shapes) are generated from one business definition (YAML / JSON / a builder DSL). An AI does not read the implementation (`src/`); it only needs "how to write a definition" and "the names it may use". All editions converge on the same definition, and their outputs are pinned to identical results by a conformance suite. This file is the English entry point for LLMs. The project's primary language is Japanese, so a few documents are Japanese-only — those are marked (ja). ## Start here (enough to write a definition) - [AI cheat sheet](https://github.com/ASIL-E-Hatake/hatake/raw/main/docs/api-cheatsheet.md): page kinds, field types, formatters / converters / validators, plus minimal examples - [DSL reference (machine readable)](https://github.com/ASIL-E-Hatake/hatake/raw/main/spec/reference.json): **an index of every key** — per node the keys, types, defaults, allowed values, which page kinds they are valid on, plus `keyIndex` (key name → where it may be written). Generated from the JSON Schema, so it cannot drift from the spec. Look things up here instead of reading the specification - [Example catalog (machine readable)](https://github.com/ASIL-E-Hatake/hatake/raw/main/spec/examples/index.json): task → example. Copying the nearest example and editing it is the fastest correct route - [Common mistakes (machine readable)](https://github.com/ASIL-E-Hatake/hatake/raw/main/spec/pitfalls.json): wrong form → why → correct form. Every entry is verified by CI (the wrong one really fails, the correct one really passes) - [DSL specification](https://github.com/ASIL-E-Hatake/hatake/raw/main/spec/dsl-spec.md): the full spec, as prose - [JSON Schema](https://github.com/ASIL-E-Hatake/hatake/raw/main/spec/hatake-page.schema.json): for machine validation (put `# yaml-language-server: $schema=` at the top of a YAML file to get completion and validation in an editor) ## MCP server (the fastest route for a capable client) Connecting it lets an agent look things up on demand instead of being handed documents. Tools: `hatake_reference` (look up a key), `hatake_examples` (fetch the nearest example), `hatake_validate` (validate, with fixes for structural mistakes and warnings for definitions that parse but misbehave), `hatake_new_page` (scaffold), `hatake_pitfalls` (common mistakes), `hatake_diff` (what changing a definition breaks, plus the changes a human should confirm), `hatake_explain` (read back, in Japanese, what the definition actually does, or restate a change), `hatake_fix` (apply only the repairs that are uniquely determined), `hatake_minimize` (drop specifications equal to the default, without changing meaning), `hatake_refs` (what the definition expects the application to register), `hatake_api_shape` (the API shapes a definition implies). Tool descriptions are in Japanese. - Setup: [MCP guide](https://github.com/ASIL-E-Hatake/hatake/raw/main/docs/guide/mcp.ja.md) (ja) — `claude mcp add hatake -- node /typescript/dist/mcp.js` ## Validate what you wrote (CLI) Never leave a definition unverified: unknown keys are dropped silently by default, so a typo in an optional key does nothing at all. Exit code is 1 when something is wrong. ```bash npx hatake validate page.yaml # strict by default. --json for machine-readable output npx hatake reference # type, default, allowed values, where it may be written npx hatake examples # find the nearest example npx hatake pitfalls # common mistake → correct form npx hatake new --id --title # crud/search/master/detail/form/wizard/dashboard/report npx hatake diff <old> <new> # what a change breaks, and what to confirm npx hatake fix page.yaml --todo # hand the leftovers (what a machine cannot decide) to the next round npx hatake refs app.yaml --unused # the reverse: registrations no definition uses npx hatake paper report.yaml # read a report as the paper it would print (text; makes sample rows) npx hatake explain page.yaml # read back what this screen does (Japanese) npx hatake explain page.yaml --brief # one-line summary (a table for an app) npx hatake explain --diff <old> <new> # what changed, in the screen's own words npx hatake explain --diff --git main...HEAD <file> # take the "before" from git (a PR's own diff) npx hatake explain page.yaml --review # one sheet for review (explanation + advice; exit code unchanged) npx hatake explain page.yaml --markdown # paste-ready for a PR body (also with --review / --diff / --brief) npx hatake fix page.yaml # apply only uniquely-determined repairs (--write to overwrite) npx hatake advise page.yaml # what is worth adding (advice, not warnings) npx hatake advise page.yaml --rules team.json # judge by the project's own ruler (silence a rule / tune a knob / demand a key) npx hatake index definitions/ --find "customer search" # which screen is where npx hatake diagram app.yaml --out app.svg # screens, menu and navigation as a picture npx hatake diagram app.yaml --role admin # only the paths that role can walk npx hatake minimize page.yaml # drop defaults; meaning is unchanged npx hatake failures <key> # real failures: what was written, what the tools said npx hatake refs page.yaml --needs-registration # what the application must register (repositories, plugins, sinks) npx hatake wire app.yaml --base /api # a draft of the wiring (Flutter HatakeScope); the bodies stay TODO npx hatake registry lib/main.dart --out hatake-registry.json # what the application does register ``` `validate` also warns about definitions that **parse but do not do what they say** (a row action with no matching declaration, navigation to a page that does not exist, `groupBy` without `sort`, an operator a condition cannot understand, an aggregate with no field). These are not errors, but you cannot spot them by looking at the screen — fix what it reports. `--warn-as-error` fails CI on them. An unknown key reports its location and the fix: `page.table.columns[0]: unknown key "witdh" (did you mean width?)` It can also check **names the definition expects from outside**: a `repository:` or `plugin:` the application never registered renders a screen with no data, or a button that does nothing. `refs` lists what must be registered, `registry` reads what the application actually registers, and `validate --registry <file>` compares them (a `hatake-registry.json` next to the definition is picked up automatically). `registry` reads only the strings written at the registration site, so anything built from a variable is reported and exits 1 rather than being dropped — a dropped name would become a false "not registered" warning. **Validation only sees spelling and structure.** A condition pointing the wrong way, or the wrong field made required, passes everything — so read the definition back with `explain` (Japanese prose, no DSL key names) and compare it against what you were asked for. `failures` collects real incidents, **including the ones no tool catches**, each with a note on what a reviewer should look for. `diff` grades every change: breaking (callers break), caution (nothing breaks but a human should confirm — a column, button or option disappeared, permissions changed, a page or menu entry is gone), safe (additions). **Never pass over cautions silently.** **When reporting a change to a human, use `explain --diff`.** `diff` answers in machine terms (`ui / column-format-changed / …`); this one says it the way a reviewer reads it (「枠「請求先」は、区分 が 法人 のときだけ出るようになりました」). Judgement (does it break) is `diff`; restating (what changed) is `explain --diff`, which never changes the exit code. **Give a reviewer one sheet.** `explain --review` prints the explanation (what the screen does and what it **cannot** do) together with the advice. Advice is a preference, so a project with its own decisions supplies its own ruler: `--rules team.json` (an unknown key or rule name is an error — a setting that silently does nothing is the worst outcome). **Cross-field rules use `compare`.** 「開始日 ≤ 終了日」or 「合計=明細の和」cannot be written on one field, so `validators` takes `{ type: compare, operator: gte, field: startDate }` (`operator`: equals/notEquals/gt/gte/lt/lte, default gte). To compare with a child table, add `aggregate: sum, of: amount`. Compared **as numbers when both read as numbers, as text otherwise** (an ISO date's text order is its date order). It **passes when it cannot judge** (an empty own value is `required`'s job). A typo'd target would pass silently, so `validate` warns about it. **Roles can only be answered by following the way in.** A page cannot carry `roles` (menu items and buttons can, plus columns, fields and cards), so "who can see this screen" is counted from the menu and button `roles`. `diagram` writes that inside each box and colours the two things a screen-by-screen read never surfaces: **anyone can open it and it can delete/export** (red border) and **nobody can open it** (dashed — the ways in disagree about roles). **The data door and the URL are provided.** For REST there is the opt-in `hatake_http`: a `Repository` that speaks exactly the API `hatake openapi` declares, with no transport dependency (you pass one send function) and typed failures (401/403, a 400 carrying per-field errors, a shape that is not the declared one). Rendering an `app:` with `HatakeApp` keeps **the web URL in step with the screen** (`/<pageId>?<params>` — links, reload and the back button all work; params come back as strings). `npx hatake refs --needs-registration` lists what the application must register — repositories, plugins and sinks — and `validate --registry` reports the ones that are not wired. **Paper comes out of the definition.** Put `{ id: printPdf, type: print, label: Print }` on a report and the print button appears (`print` is reports only — on a page with no `report` it is a warning). The framework hands over the paper's *contents* — the report, the rows on screen, the roles, the formatters — never bytes: the opt-in `hatake_print` makes the PDF and the application gets it to a printer or a file (`HatakeScope(printSink:)`). Read the paper first with `npx hatake paper`. **Every edition has the screen index.** The same thing the CLI's `index` builds exists in Dart (`ScreenIndex.ofApp(app)` / `buildScreenIndex`) and Java (`ScreenIndex.build`), so an app can search its own screens. The heading word per page kind comes from `spec/vocabulary.json`, which all three editions transcribe. ## Examples (copy them; all are schema-checked in CI) - [Customers / crud](https://github.com/ASIL-E-Hatake/hatake/raw/main/spec/examples/customer_master.yaml) - [Product search / search](https://github.com/ASIL-E-Hatake/hatake/raw/main/spec/examples/product_search.yaml) - [Customer detail / detail](https://github.com/ASIL-E-Hatake/hatake/raw/main/spec/examples/customer_detail.yaml) - [Customer form / form](https://github.com/ASIL-E-Hatake/hatake/raw/main/spec/examples/customer_form.yaml) - [Registration / wizard (stepped input)](https://github.com/ASIL-E-Hatake/hatake/raw/main/spec/examples/customer_wizard.yaml) - [Order entry / master-detail (subTable)](https://github.com/ASIL-E-Hatake/hatake/raw/main/spec/examples/order_entry.yaml) - [Sales dashboard / dashboard](https://github.com/ASIL-E-Hatake/hatake/raw/main/spec/examples/sales_dashboard.yaml) - [Sales detail / report (groups, subtotals, CSV)](https://github.com/ASIL-E-Hatake/hatake/raw/main/spec/examples/sales_report.yaml) - [Sales admin / app (menu + 8 pages + navigation)](https://github.com/ASIL-E-Hatake/hatake/raw/main/spec/examples/sales_app.yaml) - Index by task: [examples/README](https://github.com/ASIL-E-Hatake/hatake/raw/main/spec/examples/README.md) (ja) ## Rules that matter when generating code - Write a **definition**, not Flutter widgets or API request/response classes. If a definition already exists, do not write UI code. - When something is missing from the DSL, propose extending the DSL or a plugin — do not modify the framework. - The framework holds no business logic, workflow engine, database, ORM, authentication or authorization. `roles` gates display only. - Repositories are implemented by the user; the framework knows only the interface. - Definitions must stay backward compatible (`dsl_version`). ## Deeper (only when needed; Japanese) - [Concepts and responsibilities](https://github.com/ASIL-E-Hatake/hatake/raw/main/docs/guide/concepts.ja.md) (ja) - [Choosing a page kind](https://github.com/ASIL-E-Hatake/hatake/raw/main/docs/guide/page-types.ja.md) (ja) - [Validation](https://github.com/ASIL-E-Hatake/hatake/raw/main/docs/guide/validation.ja.md) (ja) - [Backend integration](https://github.com/ASIL-E-Hatake/hatake/raw/main/docs/guide/backend.ja.md) (ja) - [Plugin guide](https://github.com/ASIL-E-Hatake/hatake/raw/main/flutter/docs/plugins.ja.md) (ja) - [Roadmap](https://github.com/ASIL-E-Hatake/hatake/raw/main/docs/roadmap.ja.md) (ja) - Japanese entry point: [llms.txt](https://github.com/ASIL-E-Hatake/hatake/raw/main/llms.txt)