frontend.presentation.resolve
Generated by docs/scripts/generate-docs.mjs from operators/frontend-presentation-resolve/operator.md and operators/frontend-presentation-resolve/operator.json. Edit the source, not this page.
Binding
| Field | Value |
|---|---|
id | frontend.presentation.resolve |
domain | frontend |
resources.profile | luna |
resources.requires | — |
policy.webSearch | — |
policy.grammarBound | — |
policy.imageGeneration | — |
Job
Resolve every application-owned presentation property on one already-composed tree to exactly one published rule, emit its class and its verifiable contract claim, and stop at the smallest owning gap instead of inventing a value.
Structure arrives decided
Structure, element order, Grammar component selection, copy, data and behaviour arrive decided, and so does the owner ceiling: it is carried by the direction this branch resolves, never re-declared here. This operator only answers, for each node the application owns, which value each presentation property takes and which rule authorizes it. It changes nothing about what the tree renders.
No fabricated rule
A rule exists only if the bound knowledge topic publishes its identifier, and that inventory is
frozen for the whole run. An emitted identifier absent from the inventory is UNKNOWN_RULE. A class
that contradicts its identifier is rejected: the rule number is an ordinal on the value scale, so
GAP-5 renders gap-6 and PADDING-5 renders p-6, and writing the ordinal as the step is the
defect this check exists to catch. When no published case matches the observed condition the run
stops with RULE_MISSING naming that node; it does not choose a nearby value, round to the closest
step, or copy a neighbouring node. The operator never edits knowledge: a missing case goes back to
the knowledge owner, and the same tree is resolved again once the case is published.
Grammar is read as published, and consulted first
The owned relationships come from the published package’s own data-contract claims, never from Grammar source. A property a component already owns resolves to that component, emits no application class, and names the rule the component satisfies; that ordering makes reimplementation impossible rather than merely discouraged. An application class that reimplements an owned relationship, overrides Grammar anatomy or sits off the closed scale is removed with its own row, per node and never silently.
The scope is every folder the write set touches
The tree the direction names is the surface, not the boundary. A page reaches its final appearance
through the leaves and branches it composes, so a leaf that repaints a control, or a branch that
rebuilds a shell band, changes the same surface the page does and is resolved in the same pass. The
scope is therefore every leaf and branch folder the application owns that the declared write set
touches — packages/ui/** and src/components/{leaves,branches}/** as much as
src/components/{pages,blocks}/** — and not only the target surface’s own tree. A folder the write
set does not touch is out of scope, because resolving it would widen a change nobody asked for; a
folder the write set does touch is in scope even when the direction never named it, because the
alternative is a resolved page sitting on an unresolved leaf.
A Grammar object’s className is never a resolution target
There is one thing this operator may not resolve, however the tree presents it: a className on a
Grammar object. Presentation may not “add padding, typography or paint inside Card, Input,
Button or another Grammar object”, so the class is not a property awaiting a value — it is a reach
through an anatomy the family owns. It is removed at step 7 and recorded under ## Removed, with
overrides Grammar anatomy when it repaints anatomy, or with refused by <RULE> Case <n> naming the
case that answered no. When the relationship the class was reaching for is real and the component
publishes no prop for it, the removal is joined by a ## Gaps row and the family owner gets the
question. What never happens is a rule being selected for it: choosing a value would legitimise the
reach and hand the node two owners for one property.
A forbidden class is removed, not ruled
When the only case that names an application class states a condition the node does not meet (an
accent foreground that SURFACE-4 allows solely inside a raised band, written on an unraised row),
the property is not missing a rule: the rule has answered, and the answer is no. The class is removed
in the removal step, the property falls back to what the node inherits, and the removal is recorded
with the case that refused it. RULE_MISSING is reserved for a property no published case addresses
at all.
A missing public path is a gap, not a stop
When Common exposes no public path for a relationship the application legitimately needs, the node
keeps its application class and the branch records a row under ## Gaps naming the node, the
property and the missing path. The branch does not stop: a recorded workaround is visible to the
family owner and to the next audit, while a stop here would only trade one silent value for a
blocked chain.
The contract is a claim, not a verdict
Every application-owned node publishes the identifiers it claims. data-contract records which
rules a node claims to satisfy and never asserts that the node passes; the claim exists so a later
audit can contradict it, and one rule stays selectable as [data-contract~="GAP-4"]. With emission
off the tree carries nothing and the receipt alone holds the claims.
The loop is counted
An audit that sends its findings back here starts another round, and a round that repeats itself is
not progress. The number of audit receipts this session has fed back is counted at the gate, and a
run beyond maxRounds stops with NO_PROGRESS rather than resolving the same tree a third time.
Boundary
Context is read-only. The operator writes only response/ of its own branch: the resolution receipt,
the inventory and the resolved tree. It does not change DOM structure, element order, Grammar
component selection, copy or behaviour, write a class for a property a Grammar component already
owns, reach into Grammar anatomy with a selector or a passed class, edit knowledge, publish Grammar,
write product source, or record a verdict, score or pass claim on any node.
Context
| Alias | Bind | Required |
|---|---|---|
@knowledge/ui/presentation | the closed rule inventory read at its fingerprint; the only source of valid identifiers | yes |
@grammar/core | the published package’s owned relationships, read as published and never from Grammar source | yes |
@workspaces/fe | the routed checkout the composed tree belongs to, read at the frozen head | yes |
Inputs
| Kind | From | Required |
|---|---|---|
frontend-direction-decision | frontend.direction.decide, the intent and the owner ceiling this resolution works inside; never a source of presentation values | yes |
frontend-surface-audit | frontend.surface.audit, the findings that opened this round; present only when this is a loop | no |
Requirements
| Field | Type | Default | Ask |
|---|---|---|---|
maxRounds | number | 2 | How many audit-to-resolve rounds this surface may take before the loop is called off |
contractEmission | choice | on | on writes the claim token list onto the tree, off leaves the receipt as the record |
resume | token | null | The blocked branch’s token when re-entering after a stop |
Steps
| # | Step | Params | Reads | Writes | Stops with |
|---|---|---|---|---|---|
| 1 | Validate the gate and resume, and count the audit rounds | resume, maxRounds | request/request.json, input frontend-surface-audit when this is a loop, @workspaces/fe at the frozen head | — | INVALID_INPUT, SOURCE_DRIFT, NO_PROGRESS |
| 2 | Bind the authority | — | @knowledge/ui/presentation (every topic with its fingerprint and rule inventory), @grammar/core (the published package’s owned relationships), @workspaces/fe (the routed head and the frozen tree), input frontend-direction-decision, @tools/git, @tools/registry | — | KNOWLEDGE_UNBOUND, GRAMMAR_UNPUBLISHED |
| 3 | Walk the tree once under the owner ceiling the direction carries | — | @workspaces/fe (the frozen tree, in document order), input frontend-direction-decision | — | OWNER_CONFLICT |
| 4 | Determine the owner of every present property | — | @grammar/core (the owned relationships), @workspaces/fe (the properties the node presently carries) | response/data/inventory.json | — |
| 5 | Select one presentation rule per remaining application-owned property | — | @knowledge/ui/presentation (the cases the bound topic publishes) | — | RULE_MISSING |
| 6 | Classify a missing public path as a Grammar gap | — | @grammar/core (the relationship under question), @knowledge/ui/presentation (the capability-gap marking) | — | — |
| 7 | Remove what the tree should not carry | — | @workspaces/fe (the application classes on the node), @grammar/core (Grammar anatomy and the closed scale) | — | — |
| 8 | Emit the contract claims onto the application-owned nodes | contractEmission | @knowledge/ui/presentation (the frozen rule inventory) | — | UNKNOWN_RULE |
| 9 | Emit | — | everything above | response/artifacts/<target>.resolved.tsx, response/data/inventory.json, response/response.md, response/response.json | — |
Step 8 claims only what a node can carry: a property the application owns on a Grammar component’s
className carries no attribute, because the component forwards className and publishes no prop for
the relationship, so its rule is recorded under ## Gaps instead of being emitted. Forwarding
data-contract from every Common component that accepts className is a Grammar change and belongs
to the family owner, not to this operator.
The walk visits every node in document order and records a stable node path; a node outside the ceiling the direction carries is observed and never mutated. Steps 4 to 8 run per node, so a single tree yields one decision per node and property. The receipt authorizes a later audit to measure the rendered result against the claims; it proves nothing about how the tree renders.
Outputs
| Kind | File | Type | Required |
|---|---|---|---|
frontend-presentation-resolution | response/response.md | md | yes |
inventory | response/data/inventory.json | data | yes |
resolved-tree | response/artifacts/<target>.resolved.tsx | artifact | yes |
Stops
| Code | Disposition |
|---|---|
INVALID_INPUT | terminate |
SOURCE_DRIFT | terminate |
OWNER_CONFLICT | terminate |
KNOWLEDGE_UNBOUND | terminate |
UNKNOWN_RULE | terminate |
RULE_MISSING | terminate |
GRAMMAR_UNPUBLISHED | terminate |
NO_PROGRESS | terminate |
Next
| When | Operator |
|---|---|
| the tree is resolved and its values must be written into product source | frontend.source.apply |
| a gap needs a family component before the next round, so a person publishes it and the same tree is resolved again | frontend.presentation.resolve |
Source: operators/frontend-presentation-resolve/operator.md.