Skip to Content
BrainstormsBlocksen

Blocks

You are given one region of an accepted layout and you return 3–4 block anatomies, each a JSON structure the owner can choose between — or one refusal naming the product decision that is missing. Like the layout stage this is not a compiler, and for the same reason: which anatomy is right is a product decision, and a single answer would pretend it had already been made.

Law

An anatomy names the parts, how many times the block rests, every state it draws, and who owns its data. It never names a class.

A state the region can enter and the anatomy does not draw is a defect, not a detail for later. The states are enumerated before anything is designed, because an anatomy built for the populated case has to be redesigned rather than extended when the empty case arrives.

Inputs

Seven, and no more.

#InputWithout it
1The accepted region and its business reasonthere is no subject, only a shape
2The accepted layout hash the region came fromanatomies get built on a layout that may be discarded
3Contract: key, why, host, children names, repeats, optional — not the class arraysparts get invented instead of looked up
4Vocabulary: leaf names the contract cites, composite names, blocks that exista part cites a component that does not exist
5How the region’s data actually fails, read from page and block sourceoptional gets mistaken for a full state set
6The closed list of anatomy axesthe 3–4 anatomies differ by decoration
7Precedents accepted for THIS project, the one the workspace route declaredevery region is answered as if it were the first

Input 5 exists because the contract cannot answer it. optional: true states presence and nothing more: pending, failed and empty all reach the same flag. Separating them is read from the page and block source, never assumed from the registry.

Not read at this stage: class arrays, theme variables, locale copy, lints.

Reading an accepted region

  1. Require an accepted layout hash. A proposed layout is not a starting point.
  2. Enumerate the states first. Populated, empty, pending, failed, partial, forbidden — which can this region actually enter? Read it from source; do not infer it from optional.
  3. Look up the parts by why, not by shape, and check every leaf and composite name against the vocabulary.
  4. Choose the axes the anatomies will differ on. Identical axis sets are one anatomy.
  5. Decide who owns the data — the block fetching it and the parent passing it in are different products, not two spellings of one.
  6. Refuse rather than invent. Whether an empty region is a real outcome is the owner’s call, not a default.

Anatomy axes

AxisValues
data ownerthe block fetches it / the parent passes it in
repetitionone instance / repeats with a resting count
weightthe populated state carries the block / an absent state carries it
compositionone part / label with value / label with visual and caption

repeats without a restingCount is refused: a repeating block with no resting count has no shape to review.

Per-part verdict

Every part resolves to exactly one of three, against the contract and the vocabulary:

VerdictWhenEvidence owed
reuse <key>a name’s why already answers this part’s reasonnone
generalize <key> -> <key>it answers it under a feature-bound namethe call-site count of the old name
new <key>nothing answers this reasonthe why the new name will carry

A citation that cannot be checked against the vocabulary is an invented name, whatever its verdict says.

Anatomy laws

Fourteen laws every anatomy must satisfy. An anatomy that breaks one is not a weaker option — it is not an anatomy.

CodeLawWhat it rejects
BLOCK-1A block draws at most one surface that claims page ground. A boundary inside it is legal only when the inner set is a separate, nameable membership that declares itself nested: one border, no shadow, a named outer owner.a card drawn inside a card
BLOCK-2A secondary field in a row is text. A chip is reserved for a real state of the object: a fact that changes on its own, carries a consequence, and whose tone means something.chrome used as emphasis — a pill around a number
BLOCK-3A block owns its inset, its scroll, its measured limits and its own presentation state. The caller supplies position and data, and nothing else.a caller reaching in to style or size the block
BLOCK-4Empty is a state of the block, not the absence of the block. Zero results is an answer the product gives, in the block’s own shell under its own name.removing the block when the data is empty
BLOCK-5A block draws only facts a producer serves. No field means no field — not a constant, not a placeholder, not a plausible number.an invented field, which is worse than a missing one because it is not visibly absent
BLOCK-6Two places that show the same thing share one real owner: the shared visual row is merged, the differing interaction host stays apart.merging on resemblance alone, or quoting half the law
BLOCK-7In a repeated block, columns line up across every row, and content that opens sits flush with the trigger that opened it.alignment decided per row
BLOCK-8Name the group first, choose the spacing second. Spacing cannot substitute for structure.a layout tuned by adjusting distances until it looks right
BLOCK-9The name of a list surface belongs to the list branch. Hiding the name is legal only when an enclosing owner already renders that exact resolved name.a heading drawn outside the list with the name hidden inside it
BLOCK-10List every state before drawing any of them. A state is a situation that picks a different tree; anything drawing the same tree with different words is a prop.designing the populated case and discovering the rest later
BLOCK-11Every action owns its own pending flag, and one block is one settling unit.one shared loading flag across several actions — a spinner on the wrong button
BLOCK-12A failure has a visible owner in every layout. A failure is a settled answer, not a wait.an error rendered as a spinner that never resolves
BLOCK-13A block accepts closed data. It never accepts arbitrary content and never lets the caller decide what appears inside it.arbitrary content, which makes the block a branch
BLOCK-14Proposals are per block. A surface with N blocks yields 3–4 candidates for each of them.turning several blocks into 3–4 page-wide combinations

Rules

  1. An anatomy carries no class, no token, no colour.
  2. The state set is enumerated before the anatomy is designed, and the anatomy draws all of it.
  3. repeats carries a restingCount.
  4. Every part cites a name that exists, or declares a new one with its why.
  5. No two anatomies in a batch share the whole axis set.
  6. 3–4 anatomies when the region admits more than one; fewer with the reason stated, never padded.
  7. A missing product decision is returned to the owner.
  8. The JSON is canonical, and its hash is what approval attaches to.
  9. Feedback opens a new round; an accepted anatomy is never edited in place.

Refusal

Refusal is an output. It is used when:

  • the request does not say whether an empty region is a real outcome;
  • who owns the data cannot be determined from the region or the source;
  • the resting count is unstated and the region gives no basis for one;
  • a part requires a component that does not exist, which makes it a contract or component change rather than an anatomy choice.
refusal: returned-to-owner missing: <the decision nobody has made> blocked: <which parts cannot be resolved without it>

Output

The output is JSON, and its authority is schema.json beside this record. envelope holds what varies between runs — including the accepted layoutHash this region came from — and the hash covers an anatomy only.

{ "schema": 1, "envelope": { "session": "coding-drill-result/2026-08-18", "round": 1, "project": "starci-academy", "region": "criteria", "layoutHash": "f5534ef5e7fbe30c385108fb95702a64ac66d905414e0f7105873d67822be54c" }, "anatomies": [ { "id": "a", "axes": {"dataOwner": "parent", "repetition": "repeats", "weight": "populated", "composition": "label-value"}, "citesPrecedent": "none", "states": ["populated", "empty", "pending"], "restingCount": 4, "parts": [ { "name": "criterion-row", "cites": {"kind": "entry", "verdict": "generalize", "from": "flashcard-result-fact-row", "to": "fact-row", "callSites": 1}, "whyMatch": "a name read against one stored value, repeated as rows on a shared baseline" } ], "reason": "why this anatomy is worth the owner's attention" } ] }

Validate before writing and before hashing:

node <trust>/scripts/validate-artifact.mjs --schema <trust>/brainstorms/blocks/schema.json --data <batch.json> --hash

Beyond the shape, the validator refuses a class token anywhere in the batch, two anatomies sharing an axis set, a repeats anatomy with no restingCount, and a batch where no anatomy cites none.

Worked example

Region. “The criteria list on the coding drill result page: each criterion with its score.”

The states are read from source first: the list is populated when the drill scored criteria, empty when it scored none, and pending while the result loads. Three states, so every anatomy draws three.

Anatomy a reuses the accepted shape with the entry generalised — one call site, so the rename is one edit. Anatomy b keeps the same shape but treats the empty state as the one carrying the region, because a drill that scored nothing is a real outcome and a silent list reads as a load that never finished. Anatomy c is the departure: no repetition at all, the criteria as one grouped visual with a caption, citing profile-breakdown.

Because c cites none, the batch has its departure. Without it, a and b differ on one axis and the owner is shown one anatomy twice.

Scope

This stage decides what a block is made of and which states it owes. It does not decide where the region sits — that was the layout — and it does not decide a class, which is the law’s business. The fourteen laws an anatomy must satisfy are stated above as BLOCK-n codes, so an anatomy is checked against a citable code rather than against a reader’s memory of the legacy tree.