# Craton: multi-building row detector

You are reading the machine twin of https://oncraton.com/multi-building-detector/,
the page where a person pastes a schedule of values and finds the rows that
describe more than one building.

The page says, in short: one row, several buildings? A catastrophe model
reads each schedule row as one building at one point, with one construction
and one height. A row such as "Bldgs A-D, garden apts" or "Main campus: 3
dorms, library, gym" puts all of those buildings' value on that one point.
For every row, Craton returns the model's probability that the row covers
more than one separate building and whether that probability cleared the
gate. Rows that cleared it are flagged to split; rows that lean that way
below the gate are set apart for a person to read. The rows download as CSV
with a flag column.

- The model: Jev, TypeSafe's decision model, reached through Vercel's AI
  Gateway. It answers one fixed statement per row with a probability; it
  writes no text. Craton flags a row only when that probability is at or
  above the gate the API reports.
- The route behind the page: `POST https://api.oncraton.com/multi-building-flags`
  with a sandbox key. Documentation:
  https://docs.oncraton.com/multi-building-flags
- Response schema: https://docs.oncraton.com/schema/multi-building-flags.v0.schema.json
- The sibling tool, for OED occupancy and construction codes:
  https://oncraton.com/sov-coder/ (machine twin /sov-coder.md)

## The call

Get a free sandbox key first (one call, no card), then send up to 50 rows
of at most 1,000 characters each. The body is the rows and nothing else: the
statement each row is asked about is Craton's, fixed, never the caller's.

```bash
curl -sS -X POST https://api.oncraton.com/signup \
  -H 'Content-Type: application/json' -d '{"label": "my-agent"}'
# keep api_key.secret from the answer as CRATON_KEY

curl -sS -X POST https://api.oncraton.com/multi-building-flags \
  -H "Authorization: Bearer $CRATON_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"rows": ["Bldgs A-D, garden apts, 2 sty wood frame, Charlotte NC", "Office tower, 30 floors, steel frame, Chicago IL"]}'
```

Each entry in `rows` of the answer has a `status` (`flagged`, `below_gate`,
`not_flagged` or `unanswered`), the model's `probability` that the row covers
more than one building, `several_buildings` (that probability read at an even
chance), `cleared` (true exactly when the row is flagged) and the provider's
`generation_id`. The answer also names the model, the question set's SHA-256,
the gate and a `run_id`.

The provider sets the pace: Craton sends about 25 rows a minute across both
of its Jev tools together, spaced evenly across everyone using them. The page
sends ten rows a request and up to 250 rows in one go; a row the provider did
not get to comes back `unanswered`, and a button on the page sends just those
rows again.

When the service is switched off, over its daily budget or cannot reach the
model, the answer is `503 exposure_coding_unavailable` (the same switch as
the SOV coder) and nothing is flagged. Over a limit, `429 rate_limited` with
`Retry-After`.

## Where the rows go

The text of each row goes to an AI provider to be checked: Jev by TypeSafe,
through Vercel's AI Gateway. Craton does not store the rows or the answers.
Leave out personal data, such as people's names.
