Declared Presentation — `FORMAT`, `VALIDATE`, `PRESENT`, `##` notes
Declared Presentation — FORMAT, VALIDATE, PRESENT, ## notes
A model's meaning lives in its formulas; how a value should look, what writes it accepts, and why it exists are usually scattered across UI state. Declared presentation brings all three next to the cell, in source:
## Quarterly revenue, gross of returns.
input revenue is currency = 100000
FORMAT "$#,##0.00"
VALIDATE BETWEEN 0 AND 10000000 MESSAGE "Revenue must be a positive dollar amount."Record input fields can instead use a standalone VALIDATE FIELD declaration.
It names an exact member path on the owning input; whole-input and field rules
are checked together against the proposed batch. See the
field-rule reference for syntax,
limits and the development verification status. These contracts do not add a
browser evaluator or extend write ownership to computed fields or private locals.
Clauses trail the declaration — inline or on directly following indented lines. They are declarations, not statements: the cell's formula stays exactly what it was.
Layering
Presentation resolves through four layers, weakest to strongest:
tag-implied default a currency tag suggests currency rendering
< tag policy top-level FORMAT <tag> <expr>
< declared per-cell trailing FORMAT/VALIDATE clause, ## note
< override layer rule FORMAT actions + UI/API editsRESET FORMAT x (a rule action) clears the override layer and drops
back to the declared layer. Overridden cells report their provenance
("overridden (declared: …)") so a declared format is never silently
lost.
Doc notes — ##
A ## line documents the next declaration; a trailing ## documents
its own line:
## Discount applied before tax.
## Negotiated annually with the vendor.
discount = 0.15
tax_rate = 0.0875 ## City + state combined.A blank line detaches a ## block, so decorative comment banners stay
inert. Notes ride module metadata into the UI (cell inspection,
tooltips) — they are documentation, not evaluated content.
FORMAT
Three placements, one vocabulary (spreadsheet format patterns):
price = 19.99 FORMAT "$#,##0.00" # per-cell declaration
FORMAT percentage "0.0%" # tag policy: every percentage-tagged cell
WHEN audit_mode THEN
FORMAT price "$#,##0.0000" # dynamic override from a rule
ENDFormat operands are expressions: FORMAT IF(compact_view, "$#,##0,,\"M\"", "$#,##0.00")
re-derives when its inputs change. Tag policies resolve
most-specific-first through the type lattice, so a USD policy beats a
currency policy beats a number one.
PRESENT
A trailing PRESENT <Kind> chooses the usual Grid View element for a binding:
input qty = 2 VALIDATE 1..10 PRESENT Slider
SURFACE Order
qty
NumberInput qty
show qty
ENDThe first line inside the view uses Slider; the second explicitly uses
NumberInput; show qty remains a read-only presentation. The preference never
changes the cell's formula, type, ownership, or validation. A control preference
applies to editable placements and a display preference applies to read-only
placements. The opposite direction uses its normal presentation.
The priority is an explicit kind on the view line, then the binding's PRESENT,
then the most specific tag policy (PRESENT <tag> AS <Kind>), then the inferred
root default. A preferred kind must accept the binding's subject type. local
declarations can also carry PRESENT. Like FORMAT and VALIDATE, it may appear
inline or on a directly following line, at most once per declaration.
VALIDATE
The clause vocabulary reuses the language's predicate keywords with the subject implicit:
input qty is integer = 1 VALIDATE BETWEEN 1 AND 100
input qty2 is integer = 1 VALIDATE 1..100 # sugar for BETWEEN
input margin is percentage = 5pct VALIDATE >= 0
input region = "EMEA" VALIDATE IN ["EMEA", "AMER", "APAC"]
input invoice = "" VALIDATE LIKE "INV-%"
input code = "" VALIDATE STARTS WITH "GRID-"Accepted clause heads: the comparisons (=, <>, <, <=, >,
>=), BETWEEN … AND … (and the lo..hi sugar), IN, LIKE /
ILIKE, STARTS WITH, ENDS WITH, CONTAINS. An optional
MESSAGE "…" supplies the rejection text. Bounds are expressions —
VALIDATE 1..max_qty re-derives when max_qty changes.
VALIDATE means one of two things depending on where it sits:
On an input cell: a write contract
Every write surface — the grid UI and the model-binding ABI, so API and connector writes too — checks the incoming value (after type-tag coercion) against the clause. A rejected write returns the violation and leaves the cell unchanged. Native batched writes validate their complete proposed state before committing any member: a clause can depend on another input in the same batch, including a default restored by a clear. The detached check does not launch external work or commit rule events. Unresolved operands and unsupported clone capabilities refuse the batch. The contract gates writes only; changing a bound later does not retro-invalidate a stored value.
Grid View controls show the declared message for text predicates and text/Boolean equality before saving. Forms retain invalid drafts, read staged values for direct input operands, and refresh feedback when those inputs change. Computed operands continue to use committed native results. Numeric/structured equality feedback remains native-owned. See Grid Views for the canonical order-details example and Code's checked validation editor.
On a computed cell: a static assertion
The compiler's interval analysis propagates value ranges through formulas and discharges the assertion at compile time:
input x = 0 VALIDATE 0..1
y = x / (x + 1) VALIDATE 0..1 # proven — recorded in module metadata
z = x + 2 VALIDATE 0..1 # GRID_VALIDATE_UNSATISFIABLE: can never hold
w = x * 3 VALIDATE 0..1 # GRID_VALIDATE_UNVERIFIED: not provableAn input's write contract seeds the range other formulas observe —
that is what lets y above be proven outright. Refuted assertions are
warnings by default and hard errors under strict (see
reference §5.4);
unverified ones stay warnings, an honest signal that nothing checks the
assertion at runtime.
Where clauses may not appear
Compound assignments (+=), graph bindings, and table bindings do not
take presentation clauses — declare them where the cell is defined.
See also
- reference.md §5.4 — the strictness umbrella and the static analyses behind it
- cell-metadata.md — the document-state layer these declarations merge under
- assignments.md —
input,default, and type tags