{"lf-suggestion":{"description":"One proposed change to content the user has already seen, with accept and reject controls.","x-space":"column","x-instructions":"Copy the current markup verbatim into lf-old and put the proposed markup in lf-new. Both slots replace, lf-new alone inserts, and lf-old alone deletes; a proposed widget change uses complete old and new markup too. Write fresh content directly, and use lf-draft for words the user owns. Suggestions cannot nest, contain a draft, or appear in a reply. Set resolves to the comment whose thread acceptance should resolve. To withdraw an undecided proposal, retain lf-old\u2019s contents and remove both wrappers and lf-new; dropping the wrapper must not silently accept the proposal.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"resolves":{"type":"string","pattern":"^[a-z0-9]+$"},"restated":{"type":"boolean"}},"required":["id"],"additionalProperties":false,"x-content":"members","x-inline":true,"x-upgrade":true,"x-awaits":{"answered":{"decide":{}},"all":"accept"},"x-withdrawn-as":"reject","x-word":"module","x-face":[":scope > lf-old",":scope > lf-new"],"x-state":{"decide":{"detail":{"type":"object","properties":{"outcome":{"enum":["accept","reject"]}},"required":["outcome"],"additionalProperties":false},"unit":"widget"}},"x-example":"<p>Refill rules for the season:</p>\n<lf-suggestion id=\"sug-refill\">\n  <lf-old><p id=\"refill-rule\">Refill every feeder each morning.</p></lf-old>\n  <lf-new><p>Refill a feeder when its camera shows it half-empty.</p></lf-new>\n</lf-suggestion>"},"lf-old":{"description":"The current markup a suggestion proposes to replace or delete.","x-instructions":"Copy the current markup verbatim, including its ids. Omit this slot for an insertion.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"}},"additionalProperties":false,"x-owners":["lf-suggestion"],"x-content":"markup","x-inline":true,"x-upgrade":false,"x-retired-when":"accept"},"lf-new":{"description":"The proposed markup in a suggestion.","x-instructions":"Omit this slot for a deletion.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"}},"additionalProperties":false,"x-owners":["lf-suggestion"],"x-content":"markup","x-inline":true,"x-upgrade":false,"x-retired-when":"reject"},"$languages":{"description":"The languages this page's layer can color, and what a filename means. `names` is the whole vocabulary: what an author may declare, what the lint refuses a word outside, and what the shared syntax grammars in build/vendor.py are built from. It is a property of the page rather than of any widget, which is why it lives here and not under the schema of whichever tag happens to take a `language` \u2014 a widget declares that one of its attributes names a language (x-language) and the lint reads the list from here, so a second tag taking one costs a declaration and no new reader. `paths` is the half nobody writes: the one place a language is derived rather than declared, because a unified diff spans files and so has no attribute to carry one. An extension is the diff's own statement about what a file holds, which is a declaration like any other; an extension absent here leaves that file plain.","why-diff-is-not-a-path":"`diff` is in `names` and deliberately not in `paths`: a .patch inside a diff would be colored by the diff grammar, whose addition and deletion ink is the same statement the widget's own tints already make \u2014 said twice, in two channels, about the same line.","names":["bash","css","diff","go","html","java","javascript","json","markdown","python","rust","sql","toml","typescript","yaml"],"paths":{"bash":"bash","cjs":"javascript","css":"css","go":"go","htm":"html","html":"html","java":"java","js":"javascript","json":"json","jsx":"javascript","md":"markdown","mjs":"javascript","py":"python","rs":"rust","sh":"bash","sql":"sql","toml":"toml","ts":"typescript","tsx":"typescript","yaml":"yaml","yml":"yaml"}},"$data":{"description":"Reusable evidence from one guided website visual run.","contracts":{"measured-scalar":{"description":"The latest scalar emitted by a repeatable measurement source. Authored lf-num text freezes the value a version states; the source snapshot records whether that measurement ran again.","schema":{"type":["number","string"]}},"text-document":{"description":"UTF-8 text from a file or a selected line range.","schema":{"type":"string"}},"unified-diff":{"description":"A unified patch, either as one text value or as a file manifest whose patch fields Leaf delivers separately on demand.","instructions":{"producer":"Pipe the exact Git patch, with Git's default `a/` and `b/` prefixes, through this package's producer script into the source:\n\n```bash\ngit diff <base>...<head> | leaf package run diff patch_manifest.py | leaf data set \"$PAGE\" <source-id>\n```\n\nThe script writes the file manifest, whose `patch` fields Leaf sends only when their files open, and refuses what `lf-diff` cannot present \u2014 binary, mode-only, copy, and empty added or deleted files \u2014 naming the entry on stderr. State those changes in prose rather than setting a patch that omits them silently."},"records":{"items":"files","key":"key","deferred":"patch"},"schema":{"type":["string","object"],"properties":{"files":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1},"path":{"type":"string","minLength":1},"previousPath":{"type":"string","minLength":1},"kind":{"enum":["patch","rename"]},"additions":{"type":"integer","minimum":0},"deletions":{"type":"integer","minimum":0},"patch":{"type":"string","minLength":1}},"required":["key","path","kind","additions","deletions","patch"],"additionalProperties":false}}},"required":["files"],"additionalProperties":false}},"visual-run":{"description":"An ordered set of aligned before-and-after website states captured against one base and one candidate.","instructions":{"producer":"Capture the same authored journey at the same viewport against immutable base and candidate revisions. Include a target URL only when that captured revision has a real replayable destination; omit it for archive-only captures. Wait on a product readiness fact, disable animation, and freeze seeded data and time. Authenticate the capture browser, not the visual run: store clean target URLs, and never put query keys, cookies, or headers into page data or media. Inspect every image for credentials or personal data, import it with `leaf page media`, then replace the complete source with `leaf data set`. Each case keeps a stable `id` across refreshes, a short action and observed result, both image paths, and the browser conditions and observation time under which that pair was captured. Keep each capture's observedAt with that case, so refreshing one case preserves the provenance of retained evidence. When a small change is hard to find in a large capture, give its case one optional `focus` rectangle, `x`, `y`, `width`, and `height` in captured CSS pixels from the image's top-left, shared by both images so movement stays visible; keep it inside both decoded images with enough surrounding context to show displacement. A second area that makes a separate claim is another case reusing the image pair, not a nested region. Use a new source id when the run changes meaning."},"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1},"base":{"$ref":"#/$defs/target"},"candidate":{"$ref":"#/$defs/target"},"cases":{"type":"array","minItems":1,"items":{"$ref":"#/$defs/case"}}},"required":["title","base","candidate","cases"],"additionalProperties":false,"$defs":{"target":{"type":"object","properties":{"revision":{"type":"string","minLength":1},"url":{"type":"string","format":"uri","pattern":"^https?://\\S+$"}},"required":["revision"],"additionalProperties":false},"capture":{"type":"object","properties":{"observedAt":{"type":"string","format":"date-time"},"browser":{"type":"string","minLength":1},"browserVersion":{"type":"string","minLength":1},"viewport":{"type":"object","properties":{"width":{"type":"integer","minimum":1},"height":{"type":"integer","minimum":1}},"required":["width","height"],"additionalProperties":false},"deviceScaleFactor":{"type":"number","exclusiveMinimum":0},"colorScheme":{"enum":["light","dark"]},"locale":{"type":"string","minLength":1},"timezone":{"type":"string","minLength":1}},"required":["observedAt","browser","browserVersion","viewport","deviceScaleFactor","colorScheme","locale","timezone"],"additionalProperties":false},"focus":{"type":"object","properties":{"x":{"type":"number","minimum":0},"y":{"type":"number","minimum":0},"width":{"type":"number","exclusiveMinimum":0},"height":{"type":"number","exclusiveMinimum":0}},"required":["x","y","width","height"],"additionalProperties":false},"case":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"title":{"type":"string","minLength":1},"path":{"type":"string","pattern":"^/\\S*$"},"action":{"type":"string","minLength":1},"result":{"type":"string","minLength":1},"classification":{"enum":["changed","clean"]},"capture":{"$ref":"#/$defs/capture"},"focus":{"$ref":"#/$defs/focus"},"before":{"type":"string","pattern":"^/media/\\S+$"},"after":{"type":"string","pattern":"^/media/\\S+$"},"traceUrl":{"type":"string","format":"uri","pattern":"^https?://\\S+$"}},"required":["id","title","path","action","result","classification","capture","before","after"],"additionalProperties":false}}}},"playwright-trace":{"description":"A review index derived from one immutable Playwright format-9 trace archive. Times are native monotonic milliseconds within each stream; screenshots and saved accessibility trees have separate capture times.","instructions":{"producer":"Initialize a page with package playwright and bind an lf-trace widget to its source id. Import the native archive through the producer and Leaf canonical media writer: leaf package run playwright import_trace.py TRACE --page PAGE --leaf /absolute/path/to/bin/leaf --viewer-url URL | leaf data set PAGE SOURCE. The viewer URL must open the same unchanged trace.zip. Keep the original archive; its SHA-256 scopes every imported action, image and saved-tree node identity. Use a new source id for another recording. Format 9 only; other versions are refused explicitly. Review the recording for credentials and personal data before sharing. PNG checkpoints and accessibility trees are sequential captures: tree boxes describe the saved tree, not an exact pixel target in the neighboring image. Imported action titles, timings and action errors are retained. DOM inspection, network, console, source, test-runner hierarchy, attachments and complete assertion results remain in the linked Playwright viewer."},"schema":{"type":"object","properties":{"archive":{"type":"object","properties":{"sha256":{"type":"string","pattern":"^[a-f0-9]{64}$"},"format":{"const":9}},"required":["sha256","format"],"additionalProperties":false},"viewerUrl":{"type":"string","format":"uri","pattern":"^https?://\\S+$"},"streams":{"type":"array","items":{"$ref":"#/$defs/stream"}},"pages":{"type":"array","items":{"$ref":"#/$defs/page"}},"actions":{"type":"array","items":{"$ref":"#/$defs/action"}},"images":{"type":"array","items":{"$ref":"#/$defs/image"}}},"required":["archive","viewerUrl","streams","pages","actions","images"],"additionalProperties":false,"$defs":{"box":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"}},"required":["x","y","width","height"],"additionalProperties":false},"node":{"type":"object","properties":{"path":{"type":"string"},"role":{"type":["string","null"]},"name":{"type":["string","null"]},"text":{"type":["string","null"]},"box":{"anyOf":[{"$ref":"#/$defs/box"},{"type":"null"}]}},"required":["path","role","name","text","box"],"additionalProperties":false},"tree":{"type":"object","properties":{"timestamp":{"type":"number"},"nodes":{"type":"array","items":{"$ref":"#/$defs/node"}}},"required":["timestamp","nodes"],"additionalProperties":false},"phase":{"type":"object","properties":{"pageId":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"timestamp":{"type":"number"},"imageId":{"type":["string","null"]},"tree":{"anyOf":[{"$ref":"#/$defs/tree"},{"type":"null"}]}},"required":["pageId","timestamp","imageId","tree"],"additionalProperties":false},"action":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"stream":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"callId":{"type":"string"},"pageId":{"type":["string","null"]},"title":{"type":"string"},"startTime":{"type":"number"},"endTime":{"type":["number","null"]},"error":{"type":["string","null"]},"phases":{"type":"object","properties":{"before":{"$ref":"#/$defs/phase"},"action":{"$ref":"#/$defs/phase"},"after":{"$ref":"#/$defs/phase"}},"additionalProperties":false}},"required":["id","stream","callId","pageId","title","startTime","endTime","error","phases"],"additionalProperties":false},"image":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"pageId":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"stream":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"timestamp":{"type":"number"},"kind":{"enum":["frame","checkpoint"]},"url":{"type":"string","pattern":"^/media/[a-f0-9]+\\.(jpg|png)$"},"width":{"type":"integer","minimum":1},"height":{"type":"integer","minimum":1},"callId":{"type":["string","null"]},"phase":{"enum":["before","action","after",null]}},"required":["id","pageId","stream","timestamp","kind","url","width","height","callId","phase"],"additionalProperties":false},"page":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"stream":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"pageId":{"type":"string"}},"required":["id","stream","pageId"],"additionalProperties":false},"stream":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"origin":{"type":"string"},"playwrightVersion":{"type":["string","null"]},"wallTime":{"type":["number","null"]},"monotonicTime":{"type":["number","null"]}},"required":["id","origin","playwrightVersion","wallTime","monotonicTime"],"additionalProperties":false}}},"resources":["images[].url"]}}},"$events":{"description":"Leaf's fixed kernel event contract. Each kind carries the closed `record` schema for the complete event read from the log. Admission stamps the server-owned boolean `attention` from the change to canonical answers, work in hand (a started move or an open task on a thread or widget) and its inputs, or sign-off approval; reports and errors always carry it. Carriers select this recorded meaning rather than classifying event kinds. A `browser` schema opts that kind into POST /api/event and adds the browser writer's assertions. Layers extend widget behavior through x-state; they cannot add or change transport kinds. `page init` checks the existing log against these records before it re-vendors, so a recorded event never becomes unreadable. A kind declaring `bookkeeping` records a fact about the user's view of the page rather than a move: it never asks the agent for anything, and the browser sends it outside the ordered gesture queue, so it neither waits behind a gesture nor holds one back. A `pickup` is the page-owned durable transport fact that named attention-bearing inputs reached their next consumer, or with phase `failed` and a harness `failure` code that the harness gave up on them with no answer coming; it is never a claim that work has begun. A `comment` or `reply` carrying `token` instead of `text` is a reaction \u2014 one word from $reactions, aimed where the comment's anchor or the reply's parent points, or with neither at the page whole. It starts as a mark rather than a thread: no thread opens until someone replies to it, `resolve` on it is the floor after which it stops painting, and while nothing has answered it the user takes it back with an ordinary `undo` naming it. `handling` and `answering` remain layer-owned. `handling` holds, per kernel kind, an ordered list of clauses, each a `text` and an optional `when` JSON Schema; `answering` holds the same per answer kind (`reply`, `markup`), for the event that owes that answer. A `when` matches the delivered event: its record plus the `answer` it owes and its `thread`'s entry in the batch's digest, each if any, so a clause states one case plainly rather than naming a condition the delivery already settles. What differs by route is not a clause: the delivery states once who acknowledges it, and names its `writer` as `turn` where the turn carrying it writes the reply. Each delivered event carries its kind's matching clauses and then its answer's, so an event is told only its own case and only the answer it owes, and a later layer may restate one kind at a time.","handling":{"comment":[{"when":{"required":["drawing"]},"text":"The user drew on the page. `drawing.says`, when present, holds the page's words from the first to the last inside the ink's extents: the neighbourhood of the mark rather than the mark, so an arrow across a paragraph says the whole paragraph. It is absent where the extents hold no words, as over a picture or in a margin. `drawing.strokes` are local coordinates in one frame: HTML CSS pixels, SVG user units, or intrinsic image, canvas and video pixels. Optional `drawing.frame` identifies that visual inside the semantic comment target by a structural path; `drawing.box` is the frame's size. Prefer `leaf page picture PAGE ID`, given the comment's `id`, to see what the mark covers: it prints the path of a PNG of the comment's revision laid out in their window and color scheme (`drawing.viewport`, `drawing.scheme`), with the ink over it. Any `text` explains the mark. Otherwise it is an ordinary comment, answered the same way."},{"when":{"required":["text"],"properties":{"text":{"pattern":"\\]\\(/media/"}}},"text":"The message carries an image as a Markdown link to `/media/<digest>.<ext>`, a path under the page directory the batch names. Open the image itself before answering: its alt text is a label, not a description of what it shows."},{"when":{"required":["suggestion"],"properties":{"suggestion":{"const":true}}},"text":"A suggestion proposes exact replacement text. Apply it verbatim, or reply with your reason for declining."},{"when":{"required":["about"],"properties":{"about":{"const":"design"}}},"text":"A design comment is about how the page looks or behaves rather than what it says. Its anchor's `section` is an authored element's id or, when it starts `lf-`, a part of Leaf's own chrome, such as `lf-banner`, `lf-threads` (the Threads panel), `lf-queue` (the Questions panel), `lf-versions` or `lf-composer`; `part`, when present, describes the control, region or picture the click landed on. Find the source that produces what it names and fix it in this page's own source, unless the behavior belongs to a package's widget or the user asks for a wider fix: then change the package as the Leaf skill's `references/packages.md` says, re-vendor, and note the re-vendor on the stamp. A fix that belongs in Leaf itself is the user's to raise, as the Leaf skill's \"Improve Leaf through use\" says. The stamped version that carries the fix is the result the reply reports."},{"when":{"required":["thread","answer"],"properties":{"thread":{"required":["title"],"properties":{"title":{"type":"null"}}},"answer":{"properties":{"kind":{"const":"reply"},"writer":{"const":"agent"}}}}},"text":"This event's thread has no title yet: name it by adding `--title \"<a few words>\"` to the reply that answers it, so the thread panel lists its subject rather than its opening words. If Leaf has named it from its opening message by then, that name stands."},{"when":{"required":["token"]},"text":"A reaction is a mark, not a question. Read the token and the `means` its package gives, if any, and act on it if it calls for a change; reply only if its meaning is unclear. Once the page reflects it, close it with `leaf thread resolve <page> <event-id>`. It never blocks publishing a version, and it does not wait on an answer."}],"reply":[{"when":{"not":{"required":["token"]}},"text":"The user answered in a thread; the batch's `threads` carries the thread's context, and `leaf page state <page> <thread-id>` reads its history in pages."},{"when":{"required":["text"],"properties":{"text":{"pattern":"\\]\\(/media/"}}},"text":"The message carries an image as a Markdown link to `/media/<digest>.<ext>`, a path under the page directory the batch names. Open the image itself before answering: its alt text is a label, not a description of what it shows."},{"when":{"required":["thread","answer"],"properties":{"thread":{"required":["title"],"properties":{"title":{"type":"null"}}},"answer":{"properties":{"kind":{"const":"reply"},"writer":{"const":"agent"}}}}},"text":"This event's thread has no title yet: name it by adding `--title \"<a few words>\"` to the reply that answers it, so the thread panel lists its subject rather than its opening words. If Leaf has named it from its opening message by then, that name stands."},{"when":{"required":["thread"],"properties":{"thread":{"required":["summary_hint"]}},"not":{"required":["token"]}},"text":"This thread's entry in the batch's `threads` carries a `summary_hint`, a suggested earlier range to review. Follow the Leaf skill's `references/threads.md`, \"Summarize a long discussion\", as you answer this input. The hint adds no separate response obligation."},{"when":{"required":["token"]},"text":"A reaction on your message. It needs no reply, and Leaf already records whether it answers what you asked."}],"resolve":[{"text":"The user closed the thread. You owe no reply in it; a task you opened on it still stands until you end it."}],"unresolve":[{"text":"The user reopened a closed thread. The reopening owes nothing of its own; if the thread's latest user message was never answered, `leaf page state <page> <thread-id>` shows the `answer` its workflow still owes."}],"task_end":[{"text":"The user pressed Done on a task you put on them: `task` names the task you opened with `--on user`. It ends that task and owes no reply of its own. Carry on with whatever the task was waiting for, reading the page where you need to see what they did; if you still need something from them, ask again."}],"done":[{"text":"The user approved the page's sign-off. The page stays open: keep it watched while you do what the approval unblocks, and show that work on the page as a task (`leaf task open <page> page \"<the work>\"`, then `leaf task start`)."}],"action":[{"text":"The user already sees the action applied."},{"when":{"allOf":[{"not":{"required":["answer"]}},{"not":{"required":["meaning"],"properties":{"meaning":{"required":["scope"],"properties":{"scope":{"const":"thread"}}}}}}]},"text":"The log carries the action onto every later version, so the page keeps it without an edit."},{"when":{"allOf":[{"required":["action"],"properties":{"action":{"const":"add"}}},{"not":{"required":["meaning"],"properties":{"meaning":{"required":["scope"],"properties":{"scope":{"const":"thread"}}}}}}]},"text":"When you write it into the markup, the added option becomes an ordinary lf-option in the group, keeping the id and words the event gives."},{"when":{"required":["action"],"properties":{"action":{"const":"decide"}}},"text":"The user decided a suggestion, and `detail.outcome` says which way: `accept` keeps the lf-new branch and `reject` keeps the lf-old branch. The next version writes the kept branch in as settled prose with its ids and drops the suggestion."},{"when":{"not":{"required":["meaning"],"properties":{"meaning":{"required":["scope"],"properties":{"scope":{"const":"thread"}}}}}},"text":"If you need clarification, ask in a thread on the picked option. To override the pick in a later version, mark the element `restated` and say why in the version note."},{"when":{"not":{"required":["answer"]}},"text":"This move owes no answer of its own: it answers no Ask, a later move on the same widget carries the answer, or it does not finish the answer yet, such as a pick before the Done its group waits for."}],"undo":[{"text":"The user took back the gesture that `undoes` names. Treat the two as cancelling out: do not answer or record the withdrawn gesture. Undoing an action that answered or closed a thread reopens that thread."}],"report":[{"text":"A worker reported provisional state for a page widget, which the page shows until a stamped version answers it. Answer it in a stamped version before the page ends: write the reported state into the markup, or mark the element `overruled` and say why in the version note. A version that leaves the widget as it was leaves the report standing, and `page check` refuses one whose markup contradicts the report without answering it."}],"error":[{"text":"The page's runtime reported a failure the user saw. Fix the page or widget and save the fix. It is a diagnostic: reply only if the user asked about it."}]},"answering":{"reply":[{"text":"When the event asks for work, say in its thread what you will do before any other command, including reading the source it concerns: `leaf response reply <answer.ref> --ephemeral --text \"<what you will do, in a line>\"`. The user reads it in the thread at once, and it takes the move in hand: the move reads Working, and the line stands in the banner until you answer. Do the work and put its result on the page, with whatever shows it (captures, a figure, the numbers), then answer with `leaf response reply <answer.ref> < reply.md`: what changed, in a sentence or two, linking the section that shows it. When the event asks for no work, as a question may not, answer it with that reply at once. The page carries the work, and the thread only the conversation about it. `leaf response reply` checks any saved page edit and makes it live before posting. If a revision removes what the thread is anchored on, move the thread in the reply that reports it with `--section <id>` (narrowed by `--quote` or `--part` if needed), or `--detach` it if its subject has left the page. Add `--awaits` only if your reply's prose asks the user something.","when":{"properties":{"answer":{"properties":{"writer":{"const":"agent"}}}}}},{"text":"Leaf streams your opening into the thread and commits your completed final unless an explicit successful reply already answered this input. Before your first tool call, open with a short message to the user: the answer, or what you are about to do. Later working messages stay in Codex. Finish with the answer or what changed and where it appears. For an explicit answer, including widgets, a question awaiting the user, a title or relocation, use `leaf response reply <answer.ref>` and the rich options in `references/threads.md`; it validates saved edits and commits immediately. Your later final yields to that recorded answer.","when":{"properties":{"answer":{"properties":{"writer":{"const":"turn"}}}}}},{"text":"Your reply renders as Markdown in a narrow column: give each point its own short paragraph or list item, link a page section as `[its name](#section-id)`, and fence code or markup."},{"when":{"required":["meaning"],"properties":{"meaning":{"required":["scope"],"properties":{"scope":{"const":"thread"}}}}},"text":"The widget is in a thread message: continue the work the user's answer selects or unblocks, and answer in that thread."}],"markup":[{"text":"It answers the page's Ask, so the page shows it as waiting on you until the markup records it. Name the work it selects or unblocks with `leaf task start <page> <event-id> \"<the work, in a line>\"` before starting it, then do it, write it in, and stamp a version."}]},"kinds":{"comment":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"type":"string","minLength":1},"kind":{"const":"comment"},"seq":{"type":"integer","minimum":1},"revision":{"type":"integer","minimum":1},"text":{"type":"string","minLength":1},"token":{"type":"string","minLength":1},"anchor":{"type":"object","properties":{"section":{"type":["string","null"]},"quote":{"type":"string"},"datum":{"type":"string","minLength":1},"source":{"type":"string","pattern":"^[a-z][a-z0-9-]*$"},"source_revision":{"type":"string","pattern":"^[0-9a-f]{16}$"},"identity":{"type":"string","minLength":1},"visual":{"type":"string","minLength":1},"prefix":{"type":"string"},"suffix":{"type":"string"},"detached":{"const":true},"part":{"type":"string"}},"anyOf":[{"required":["section"],"properties":{"section":{"type":"string","minLength":1}}},{"required":["quote"],"properties":{"quote":{"type":"string","minLength":1}}},{"required":["datum"],"properties":{"datum":{"type":"string","minLength":1}}}],"dependentRequired":{"datum":["section"],"source":["datum","source_revision"],"source_revision":["datum","source"],"identity":["datum"],"part":["section"],"detached":["quote"],"visual":["section"]},"additionalProperties":false},"drawing":{"type":"object","properties":{"format":{"const":"leaf-drawing/3"},"strokes":{"type":"array","minItems":1,"maxItems":32,"items":{"type":"array","minItems":2,"maxItems":256,"items":{"type":"array","minItems":2,"maxItems":2,"prefixItems":[{"type":"number","minimum":-33554432,"maximum":33554432},{"type":"number","minimum":-33554432,"maximum":33554432}],"items":false}}},"box":{"type":"array","minItems":2,"maxItems":2,"prefixItems":[{"type":"number","exclusiveMinimum":0,"maximum":33554432},{"type":"number","exclusiveMinimum":0,"maximum":33554432}],"items":false},"frame":{"type":"object","properties":{"root":{"type":"string","maxLength":128,"pattern":"^[A-Za-z][A-Za-z0-9_.:-]*$"},"path":{"type":"array","maxItems":32,"items":{"type":"object","properties":{"tag":{"type":"string","maxLength":128,"pattern":"^[A-Za-z][A-Za-z0-9_.:-]*$"},"index":{"type":"integer","minimum":0,"maximum":65535},"siblings":{"type":"integer","minimum":1,"maximum":65536},"shadow":{"type":"boolean"}},"required":["tag","index","siblings"],"additionalProperties":false}}},"required":["root","path"],"additionalProperties":false},"says":{"type":"string","minLength":1,"maxLength":500},"viewport":{"type":"array","minItems":2,"maxItems":2,"prefixItems":[{"type":"number","exclusiveMinimum":0,"maximum":33554432},{"type":"number","exclusiveMinimum":0,"maximum":33554432}],"items":false},"scheme":{"enum":["light","dark"]}},"required":["format","strokes","box","viewport","scheme"],"additionalProperties":false},"suggestion":{"type":"boolean"},"about":{"const":"design"},"title":{"type":"string","minLength":1,"maxLength":80,"pattern":"\\S","not":{"pattern":"[\\r\\n]"}},"agent":{"type":"string","minLength":1},"session":{"type":"string","minLength":1},"markup":{"type":"string","minLength":1},"attempt":{"type":"string","pattern":"^[A-Za-z0-9_-]{16,128}$"},"holds":{"type":"string","minLength":1}},"required":["attention","id","ts","author","kind","seq","revision"],"additionalProperties":false,"oneOf":[{"required":["text"]},{"required":["token"]},{"required":["drawing"],"not":{"required":["text"]}}],"dependentSchemas":{"title":{"properties":{"author":{"const":"agent"}}},"token":{"not":{"anyOf":[{"required":["suggestion"]},{"required":["holds"]},{"required":["markup"]}]}},"drawing":{"required":["anchor"],"properties":{"anchor":{"not":{"anyOf":[{"required":["quote"]},{"required":["part"]}]}}},"not":{"anyOf":[{"required":["suggestion"]},{"required":["about"]},{"required":["holds"]},{"required":["markup"]}]}}}},"browser":{"required":["kind","revision"],"not":{"required":["markup"]}}},"reply":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"type":"string","minLength":1},"kind":{"const":"reply"},"seq":{"type":"integer","minimum":1},"parent":{"type":"string","minLength":1},"revision":{"type":"integer","minimum":1},"publication":{"type":"string","pattern":"^r[1-9][0-9]*-[a-f0-9]{16}$"},"text":{"type":"string","minLength":1},"token":{"type":"string","minLength":1},"anchor":{"type":["object","null"],"properties":{"section":{"type":["string","null"]},"quote":{"type":"string"},"datum":{"type":"string","minLength":1},"source":{"type":"string","pattern":"^[a-z][a-z0-9-]*$"},"source_revision":{"type":"string","pattern":"^[0-9a-f]{16}$"},"identity":{"type":"string","minLength":1},"visual":{"type":"string","minLength":1},"prefix":{"type":"string"},"suffix":{"type":"string"},"detached":{"const":true},"part":{"type":"string"}},"anyOf":[{"required":["section"],"properties":{"section":{"type":"string","minLength":1}}},{"required":["quote"],"properties":{"quote":{"type":"string","minLength":1}}},{"required":["datum"],"properties":{"datum":{"type":"string","minLength":1}}}],"dependentRequired":{"datum":["section"],"source":["datum","source_revision"],"source_revision":["datum","source"],"identity":["datum"],"part":["section"],"detached":["quote"],"visual":["section"]},"additionalProperties":false},"title":{"type":"string","minLength":1,"maxLength":80,"pattern":"\\S","not":{"pattern":"[\\r\\n]"}},"agent":{"type":"string","minLength":1},"session":{"type":"string","minLength":1},"markup":{"type":"string","minLength":1},"awaits":{"const":true},"ephemeral":{"const":true},"start":{"type":"object","properties":{"item":{"type":"string","minLength":1},"turn":{"type":"string","minLength":1}},"required":["item"],"additionalProperties":false},"failure":{"type":"string","minLength":1},"responds":{"type":"string","minLength":1},"attempt":{"type":"string","pattern":"^[A-Za-z0-9_-]{16,128}$"}},"required":["attention","id","ts","author","kind","seq","parent"],"additionalProperties":false,"oneOf":[{"required":["text"]},{"required":["token"]}],"dependentSchemas":{"start":{"required":["ephemeral","text"],"properties":{"author":{"const":"agent"}}},"title":{"properties":{"author":{"const":"agent"}}},"publication":{"required":["revision"],"properties":{"author":{"const":"agent"}}},"ephemeral":{"required":["text"],"properties":{"author":{"const":"agent"}},"not":{"anyOf":[{"required":["responds"]},{"required":["awaits"]},{"required":["markup"]},{"required":["failure"]},{"required":["anchor"]}]}},"token":{"not":{"required":["markup"]}},"failure":{"required":["text","responds"],"properties":{"author":{"const":"agent"}}},"anchor":{"required":["revision","text"],"properties":{"author":{"const":"agent"}}}}},"browser":{"required":["kind","parent","revision"],"not":{"anyOf":[{"required":["markup"]},{"required":["awaits"]},{"required":["anchor"]},{"required":["responds"]},{"required":["failure"]},{"required":["ephemeral"]},{"required":["start"]},{"required":["title"]}]}}},"edit":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"const":"agent"},"kind":{"const":"edit"},"seq":{"type":"integer","minimum":1},"message":{"type":"string","minLength":1},"text":{"type":"string","minLength":1},"agent":{"type":"string","minLength":1},"session":{"type":"string","minLength":1}},"required":["attention","id","ts","author","kind","seq","message","text","agent","session"],"additionalProperties":false}},"summary":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"const":"agent"},"kind":{"const":"summary"},"seq":{"type":"integer","minimum":1},"thread":{"type":"string","minLength":1},"from":{"type":"string","minLength":1},"through":{"type":"string","minLength":1},"text":{"type":"string"},"label":{"type":"string","minLength":1},"agent":{"type":"string","minLength":1},"session":{"type":"string","minLength":1}},"required":["attention","id","ts","author","kind","seq","thread","from","through","text","agent","session"],"additionalProperties":false}},"read":{"bookkeeping":true,"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"const":"user"},"kind":{"const":"read"},"seq":{"type":"integer","minimum":1},"messages":{"type":"array","minItems":1,"uniqueItems":true,"items":{"type":"object","properties":{"message":{"type":"string","minLength":1},"version":{"type":"string","minLength":1}},"required":["message","version"],"additionalProperties":false}},"attempt":{"type":"string","pattern":"^[A-Za-z0-9_-]{16,128}$"}},"required":["attention","id","ts","author","kind","seq","messages"],"additionalProperties":false},"browser":{"required":["kind","messages"]}},"thread_title":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"const":"agent"},"kind":{"const":"thread_title"},"seq":{"type":"integer","minimum":1},"thread":{"type":"string","minLength":1},"title":{"type":"string","minLength":1,"maxLength":80,"pattern":"\\S","not":{"pattern":"[\\r\\n]"}},"agent":{"type":"string","minLength":1},"session":{"type":"string","minLength":1}},"required":["attention","id","ts","author","kind","seq","thread","title","agent","session"],"additionalProperties":false}},"task":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"const":"agent"},"kind":{"const":"task"},"seq":{"type":"integer","minimum":1},"owner":{"enum":["agent","user"]},"subject":{"oneOf":[{"type":"object","properties":{"kind":{"enum":["thread","widget","element"]},"id":{"type":"string","minLength":1}},"required":["kind","id"],"additionalProperties":false},{"type":"object","properties":{"kind":{"const":"page"}},"required":["kind"],"additionalProperties":false}]},"revision":{"type":"integer","minimum":1},"title":{"type":"string","minLength":1,"maxLength":80,"pattern":"\\S","not":{"pattern":"[\\r\\n]"}},"agent":{"type":"string","minLength":1},"session":{"type":"string","minLength":1}},"required":["attention","id","ts","author","kind","seq","owner","subject","title"],"additionalProperties":false}},"start":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"const":"agent"},"kind":{"const":"start"},"seq":{"type":"integer","minimum":1},"item":{"type":"string","minLength":1},"text":{"type":"string","minLength":1,"pattern":"\\S","not":{"pattern":"[\\r\\n]"}},"turn":{"type":"string","minLength":1},"agent":{"type":"string","minLength":1},"session":{"type":"string","minLength":1}},"required":["attention","id","ts","author","kind","seq","item","text"],"additionalProperties":false}},"put_down":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"const":"agent"},"kind":{"const":"put_down"},"seq":{"type":"integer","minimum":1},"agent":{"type":"string","minLength":1},"session":{"type":"string","minLength":1}},"required":["attention","id","ts","author","kind","seq"],"additionalProperties":false}},"task_end":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"enum":["agent","user"]},"kind":{"const":"task_end"},"seq":{"type":"integer","minimum":1},"task":{"type":"string","minLength":1},"outcome":{"enum":["done","failed","dropped"]},"attempt":{"type":"string","pattern":"^[A-Za-z0-9_-]{16,128}$"},"detail":{"type":"string","minLength":1,"maxLength":500,"pattern":"\\S"},"agent":{"type":"string","minLength":1},"session":{"type":"string","minLength":1}},"required":["attention","id","ts","author","kind","seq","task","outcome"],"additionalProperties":false},"browser":{"required":["kind","task","outcome"],"properties":{"outcome":{"const":"done"}},"not":{"required":["detail"]}}},"reanchor":{"bookkeeping":true,"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"const":"page"},"publication":{"type":"string","pattern":"^r[1-9][0-9]*-[a-f0-9]{16}$"},"kind":{"const":"reanchor"},"seq":{"type":"integer","minimum":1},"thread":{"type":"string","minLength":1},"revision":{"type":"integer","minimum":1},"anchor":{"type":["object","null"],"properties":{"section":{"type":"string","minLength":1}},"required":["section"],"additionalProperties":false}},"required":["attention","id","ts","author","kind","seq","thread","revision","anchor"],"additionalProperties":false}},"resolve":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"type":"string","minLength":1},"kind":{"const":"resolve"},"seq":{"type":"integer","minimum":1},"parent":{"type":"string","minLength":1},"agent":{"type":"string","minLength":1},"session":{"type":"string","minLength":1},"attempt":{"type":"string","pattern":"^[A-Za-z0-9_-]{16,128}$"}},"required":["attention","id","ts","author","kind","seq","parent"],"additionalProperties":false},"browser":{"required":["kind","parent"]}},"unresolve":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"type":"string","minLength":1},"kind":{"const":"unresolve"},"seq":{"type":"integer","minimum":1},"parent":{"type":"string","minLength":1},"attempt":{"type":"string","pattern":"^[A-Za-z0-9_-]{16,128}$"}},"required":["attention","id","ts","author","kind","seq","parent"],"additionalProperties":false},"browser":{"required":["kind","parent"]}},"done":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"type":"string","minLength":1},"kind":{"const":"done"},"seq":{"type":"integer","minimum":1},"version":{"type":"integer","minimum":1},"attempt":{"type":"string","pattern":"^[A-Za-z0-9_-]{16,128}$"}},"required":["attention","id","ts","author","kind","seq","version"],"additionalProperties":false},"browser":{"required":["kind","version"]}},"action":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"type":"string","minLength":1},"kind":{"const":"action"},"seq":{"type":"integer","minimum":1},"widget":{"type":"string","minLength":1},"action":{"type":"string","minLength":1},"detail":{"type":"object"},"meaning":{"type":"object","properties":{"scope":{"enum":["page","thread"]},"unit":{"type":"string","minLength":1},"depends":{"type":"array","items":{"type":"string","minLength":1},"uniqueItems":true},"answer":{"type":["string","null"],"minLength":1},"creates":{"type":"string","pattern":"^lf-[a-z0-9]+(-[a-z0-9]+)*$"},"among":{"type":"array","items":{"type":"string","minLength":1}},"state":{"type":"object","properties":{"origin":{"type":"string","pattern":"^lf-[a-z0-9]+(-[a-z0-9]+)*$"},"unit":{"type":"string","minLength":1},"record":{"type":["object","null"]},"creates":{"type":["object","null"]},"update":{"type":"boolean"},"detail":{"type":["object","boolean"]}},"required":["origin","unit","record","creates","update","detail"],"additionalProperties":false}},"required":["scope","unit","depends"],"additionalProperties":false},"revision":{"type":"integer","minimum":1},"attempt":{"type":"string","pattern":"^[A-Za-z0-9_-]{16,128}$"}},"required":["attention","id","ts","author","kind","seq","widget","action","detail","revision","meaning"],"additionalProperties":false},"browser":{"required":["kind","widget","action","detail","revision"]}},"pickup":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"const":"page"},"kind":{"const":"pickup"},"seq":{"type":"integer","minimum":1},"events":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"uniqueItems":true},"phase":{"enum":["queued","opened","failed"]},"session":{"type":["string","null"],"minLength":1},"turn":{"type":["string","null"],"minLength":1},"failure":{"type":"string","minLength":1}},"required":["attention","id","ts","author","kind","seq","events","phase","session","turn"],"if":{"properties":{"phase":{"const":"failed"}}},"then":{"required":["failure"]},"else":{"not":{"required":["failure"]}},"additionalProperties":false}},"undo":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"type":"string","minLength":1},"kind":{"const":"undo"},"seq":{"type":"integer","minimum":1},"undoes":{"type":"string","minLength":1},"attempt":{"type":"string","pattern":"^[A-Za-z0-9_-]{16,128}$"}},"required":["attention","id","ts","author","kind","seq","undoes"],"additionalProperties":false},"browser":{"required":["kind","undoes"]}},"report":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"type":"string","minLength":1},"kind":{"const":"report"},"seq":{"type":"integer","minimum":1},"widget":{"type":"string","minLength":1},"action":{"type":"string","minLength":1},"detail":{"type":"object"},"meaning":{"type":"object","properties":{"scope":{"enum":["page","thread"]},"unit":{"type":"string","minLength":1},"depends":{"type":"array","items":{"type":"string","minLength":1},"uniqueItems":true},"state":{"type":"object","properties":{"origin":{"type":"string","pattern":"^lf-[a-z0-9]+(-[a-z0-9]+)*$"},"unit":{"type":"string","minLength":1},"record":{"type":["object","null"]},"creates":{"type":["object","null"]},"update":{"type":"boolean"},"detail":{"type":["object","boolean"]}},"required":["origin","unit","record","creates","update","detail"],"additionalProperties":false}},"required":["scope","unit","depends"],"additionalProperties":false},"revision":{"type":"integer","minimum":1},"agent":{"type":"string","minLength":1},"session":{"type":"string","minLength":1}},"required":["attention","id","ts","author","kind","seq","widget","action","detail","revision","meaning"],"additionalProperties":false}},"note":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"type":"string","minLength":1},"kind":{"const":"note"},"seq":{"type":"integer","minimum":1},"version":{"type":"integer","minimum":1},"revision":{"type":"integer","minimum":1},"publication":{"type":"string","pattern":"^r[1-9][0-9]*-[a-f0-9]{16}$"},"text":{"type":"string","minLength":1},"restated":{"type":"array","items":{"type":"string","minLength":1},"uniqueItems":true},"settles":{"type":"array","items":{"type":"object","properties":{"kind":{"enum":["report","task"]},"id":{"type":"string","minLength":1}},"required":["kind","id"],"additionalProperties":false},"uniqueItems":true},"agent":{"type":"string","minLength":1},"session":{"type":"string","minLength":1}},"required":["attention","id","ts","author","kind","seq","version","revision","text"],"dependentSchemas":{"publication":{"properties":{"author":{"const":"agent"}}}},"additionalProperties":false}},"error":{"record":{"type":"object","properties":{"attention":{"type":"boolean"},"id":{"type":"string","minLength":1},"ts":{"type":"string","minLength":1},"author":{"type":"string","minLength":1},"kind":{"const":"error"},"seq":{"type":"integer","minimum":1},"revision":{"type":"integer","minimum":1},"text":{"type":"string","minLength":1}},"required":["attention","id","ts","author","kind","seq","text"],"additionalProperties":false},"browser":{"required":["kind","text"]}}}},"$keys":{"description":"What each x- key an element declaration may carry means, one member per key. The keys are the layer's and the lint closes the set, so a layer overriding a member here documents its own reading of that key and declares no new one; a member for a key the lint doesn't admit, or a key with no member, refuses the registry. Authors query this entry beside element declarations, and the site's table of keys is generated from it, so an author, the lint and the documentation read one thing.","x-ask-surface":"What x-ask-surface declares: a Leaf element is the complete reading and arrival region for exactly one non-quoted nested local Ask declared by x-awaits. The region begins with one direct heading, then carries any context and evidence the user needs before the control; the nested widget still owns the answer and its fold. The banner, Questions panel, `q`/`Q` queue walk, standing ring, and the Ask's task in `page state` name the region while replay names the nested widget. An arrival targets the region's opening; the widget's answering controls remain available through Tab. `page check` requires the leading heading and one non-quoted nested Ask source so the two identities cannot be ambiguous.","x-awaits":"What x-awaits declares: a tag originates a standing Ask for the user, which is a task on the user under the Ask's id (its x-ask-surface region's, where one frames it) from the version that adds it until its widget answers it, or a version removes it or marks it `restated`. The Ask states when it is answered as a condition on the widget's standing state (`answered`), so the answer is a reading of state the fold already keeps rather than a flag beside it, and the action whose admission makes that condition hold is the one admission marks as the answer. The banner's count, the Asks the `q`/`Q` queue walk stops at, and the command reference dialog's row are readings of one projection, so nothing names a tag and a new widget joins by declaring. Quoted material decides nothing \u2014 an exhibited Ask is a mention (x-exhibit). A widget that also declares x-thread-seat puts a box under its own Ask, and a thread standing in that box takes the Ask off the user's queue for as long as it waits on the agent \u2014 whoever opened it. That is not an answer: the widget's state is untouched, so a version still has to record what the words settled. An ordinary reply or resolve hands the thread back. A widget inside a thread presents an Ask like one on the page, with one bound set by frozen thread markup: the thread's own reply box is already that seat, so only an action can answer it there. `when` selects Leaf elements that originate Asks, `answered` says which standing state answers one, and `all` names a blanket answer offered by the banner.","x-thread-seat":"The module places a threadBox in each matching Leaf element, selected by authored, static `when` attributes (an attribute written by an x-state value record cannot drive this predicate). It projects exact-section threads textually from the whole log; Threads keeps the complete interactive view. Thread markup and quoted material take no second view. Where the widget also originates a local x-awaits Ask, the seat is where the user deals with it in words: the Ask leaves their queue while that thread waits on the agent, rather than being counted a second time under a box they have already used. It is not an answer \u2014 the widget's own state is untouched, so its controls still work and the Ask still reads as unanswered. A `hold` comment is a seat thread like any other. `hold` labels a stronger send route whose comment carries `holds` naming this widget: that route remains available after ordinary roots, the unresolved held thread is the hold, resolution releases it, and undoing resolution restores it atomically. Dropping the widget drops only the inline view.","x-content":"The content model: `markup` (children are the author's markup), `members` (children are this element's own member elements and nothing else), `data` (one <pre> holding text in the notation the description names, with & < > escaped as &amp; &lt; &gt; \u2014 <pre> because it is the only thing in HTML that says whitespace is load-bearing without a stylesheet to read), or `empty`. Required.","x-data":"The widget's named external-data inputs. Each input names a `$data.contracts` contract and the declared canonical string attribute whose authored value is this page's source id. The input follows the source's current value. An optional source attribute leaves that input absent; `watchData` delivers null. Several widgets may bind the same source to the same contract. A document binds a source to one contract. Later documents may replace that binding; each captured document reads the current value against its own declared contract and reports incompatible values as source errors. A module subscribes by widget and input name, never by a package-owned source name.","x-example":"Authored markup exhibiting the widget, valid against the merged registry: an agent reads it with the element declaration, writes from it, and the lint refuses one that does not validate.","x-exhibit":"The element quotes what it holds rather than speaking it \u2014 a mention, not a use: interactive widgets inside take no input (a choose group no clicks, a board no drags, a suggestion no decision), and an Ask inside it counts for nothing. A module asks `quoted(el)` before wiring any input, and the theme's affordance rules \u2014 the hand, the lift, the joined shape \u2014 stand down inside it on their own.","x-instructions":"Author instructions for using this widget, read after selecting it and before writing markup. A flat nonempty string, separate from its short discovery description and its structured schema.","x-inline":"The element is set among the words around it, so the render gate holds its box to no width of its own and the rule that a block widget stands in a block slot passes over it.","x-language":"The attribute that names a code language, held to `$languages.names` \u2014 the one list this page colors from \u2014 so a second tag taking a language costs a declaration and no new reader.","x-reading-role":"The structural role an element supplies: `pane`, the one role, is a labeled reading region whose body scrolls on its own while the workspace is full-height. A pane holds exactly one body element between an optional direct native `header` first and `footer` last. Role-derived validation reads this declaration rather than tag names. The role keeps markup content so packages may contribute differently named panes without joining a closed parent-child vocabulary. A pane requires a string `id` and a string `label`, which names its accessible region while a visible heading belongs in its authored header.","x-lines":"Attributes holding line references into the nearest data body \u2014 the element's own <pre>, or its enclosing data element's (a note's `at` names a line of its code block) \u2014 which `page check` refuses outside the body. A reference names a line by the number that body's x-numbering gives it, 1-based when it has none; a number inside a gap the numbering leaves is in the body.","x-numbering":"The attribute giving the source line numbers a data body quotes, as ascending ranges (\"1505-1507,1520-1527\"). `page check` holds it to one number per body line, counting the <pre>'s text without its leading blank lines and trailing whitespace; a gap between ranges is lines the body leaves out, and every x-lines reference into that body names lines by these numbers.","x-measured":"A scalar in authored content pinned to one x-data input at an aware instant. `input` names the widget's data input and `at` names its required date-time attribute. The authored words remain frozen with the version; when that source's stored `updated` instant moves past `at`, `page check` advises that the measurement is stale and `page state` reports the same debt. The declaration compares runs, not age: a source that never updates creates no warning.","x-paints":"Attributes the theme renders as paint alone \u2014 for example, a status marker's tint. The runtime speaks each to a user listening (the value, or a flag attribute's own name), silently on screen and out of every selection, so a fact stated in ink is not silent to whoever cannot see it.","x-patch":"How a revision reaches an upgraded widget the user has open. By default its module owns everything under the element, so a revision that changes any of the widget's markup replaces the whole widget and rebuilds whatever the user had open in it. `members` says the module builds its own controls beside its members, leaves them where the author wrote them, and reads nothing of them but their attributes: while a revision keeps the element's attributes and each member's tag and attributes, in order, it edits inside the members in place and the widget stays. Requires `x-content: members` and x-upgrade.","x-owners":"The element declarations that may directly own a Leaf element. Read from an owner, this defines which direct child Leaf elements are its members rather than nested elements it merely contains; a gesture the owner takes on its whole box stops at those members.","x-refers":"A map from attributes whose values name another element to their target contracts. An empty contract accepts any element id (an option's `for`). A typed contract names a shared registry map with `via` and an equality predicate with `where`; `page check` then requires both an existing id and a target tag whose declaration in that package-owned map matches the predicate. This lets a package distinguish a goal, worker, or evidence reference without Leaf knowing those roles or tags. A typed contract with `owns: true` says the referrer fills its target, as a command fills the readings seat it names: `page check` requires the target in the referrer's own document, and every element there that the predicate selects named by exactly one referrer. In the browser a declared attribute is what a module hands `navigateToDatum` and the experimental `indicate` to reach the named widget, which each resolves in the owner's own authored document first (its message's markup, for a widget in a reply) and then in the page.","x-retired-when":"On a member: the owner's decision outcome that takes this element off the page (a suggestion's `lf-old` under `accept`). Requires x-owners. The outcome is a value of the `outcome` detail field on the owner's one deciding verb, so only one settlement can stand. The layer renders the settlement whole, following the log's standing state both ways \u2014 reconciliation paints data-lf-state=\"<outcome>\" on the owner and data-lf-retired on the members that outcome retires, takes both off when undo or a retraction removes the deciding action from the fold, and one theme rule hides the marked members \u2014 so no module owes any of it, though one may paint the same sooner as its own gesture (renderRetired). Those attributes are rendered output for CSS, export, and checks; semantic consumers read the publisher's explicit outcome rather than reading them back. The file's reading takes the fact from the log, and `page check` licenses dropping the member's ids on it; `page check --render` reports a settled member still showing words, or a mark the log never decided.","x-says":"Attributes whose values the user sees as words, and where each renders. `after` goes inside the element's own content, ahead of the apparatus that ends it, so a word does not land on the far side of a control that closes the row. `before` goes at the element's start, ahead of chrome as well: leading chrome is not something the words stand beside, it is a module speaking for the whole element, so an element's opening words go above it; where a declaration names two at that edge they render in the order the declaration lists them. The runtime writes them as selectable text the user can quote and comment on, where `content: attr()` would paint glyphs into no text node.","x-shadow":"The module renders the page's words into an open shadow tree, which the passage walk, the selection capture and every question asked by id cross; a shadow root on a host whose entry lacks it is a render-gate finding.","x-state":"What x-state declares, once per widget with state: each verb's fold unit, who writes it, and either its recorded effect or its custom unrecorded detail schema. A recorded effect derives its closed payload from the effect kind and destination attribute; it declares no separate detail schema or payload-field mappings. A verb is the user's unless it declares `writer: \"agent\"`: the user writes theirs through the page as `action` events, and the agent reports its own through `leaf page report` as `report` events, so every coordinate has one writer. A user verb may declare a created child (`creates`). An agent verb requires a record form other than `body`, since a report moves declared state and never the page's words, which keeps the passage reading untouched by it; it may declare `update: true` to require non-empty `detail.text` as the report's short human-readable news, which the canonical update feed exposes without guessing from a widget, verb, or field name. The runtime paints a standing report live (data-lf-reported); it is provisional news, standing only until a version answers it, as $report says. Each verb is its own state: the owning Leaf element, the unit, and the verb together name one independently standing fact, the latest surviving action of that verb there supersedes its predecessors, and different verbs coexist. The framework composes the last surviving action per coordinate with typed authored values and gives every widget its complete state through renderState, keyed by verb, and one declaration drives POST validation, complete-state replay, construction-linked inspection, the runtime's user- and report-origin readings, and the version diff's state half. When an action's admission makes its widget's x-awaits `answered` condition hold, admission records meaning.answer on it: the widget's authored `resolves` attribute, read from the sending document, names the comment thread the answer closes, and null answers without closing one, which is also what a decision whose outcome is the widget's x-withdrawn-as records: it leaves the page as if nothing had been proposed. Historical settlement uses the admitted owner-unit-verb coordinate even after the widget retires. One detail field name is reserved: `outcome`, on the one user widget-unit verb that decides which retirable members leave the page (x-retired-when). The unit, creates, and record forms are $state's.","x-thread-surface":"The upgraded widget can seat the canonical response composer and Thread views beside exact projected datums. Its module registers through placeThreads, receives one ordered batch of admitted exact targets, and returns matching outlet Elements or null. Core maps those outlets to their Threads or the active composer and commits their placement and lifetime. The returned handle can open Comment from one of the widget's projected elements. Leaf owns anchors, drafts, response modes, submission, Thread rendering, reply and reaction state, settlement, focus, receipts, and margin-projection fallback. A placement claims that active composer or Thread locally for the current reconciliation; unloaded, filtered, collapsed, outdated, or otherwise undisplayable datums receive no placement and remain in the global Threads index plus the ordinary fallback.","x-text-format":"Text format: inline-markdown formats this element's direct text nodes; markdown renders its exact data body as safe block Markdown. A body record retains Markdown source while passages read visible words. Its existing element children remain HTML. The browser formats those words with the shared safe Markdown parser, while file-side passage and revision readings use the same visible words. A generated child with this declaration interprets the user's line breaks as hard breaks; source HTML line wraps remain ordinary whitespace.","x-tone":"The attribute that names one of the layer's semantic tints, held to `$tones.names`, which the theme has a rule for.","x-upgrade":"A module at widgets/<tag>.js enhances the element in the browser, imported where a page's markup carries the tag rather than for the whole layer. `page init` refuses a layer declaring it with no module beside it, and the render gate a module that defines no element for a widget the page contains. Required.","x-verbatim":"An upgraded element that preserves its own authored words and the order and identity of nested upgraded widget boundaries, which makes those words quotable. Each nested upgraded widget keeps its own word and fence contract, so its generated rendering is not a claim by the wrapper. Without this promise the passage reader treats the widget as opaque, since its module may insert or replace words. The render gate refuses changed wrapper prose or removed and reordered nested ownership boundaries.","x-initial":"The rooted path of a captured classic JavaScript bundle registering the widget's synchronous initial renderer with document.documentElement.lfInitial.register(tag, render). Delivery inlines each used bundle once in the head, buffers each outer host in an inert template until its source is complete, and inserts and draws it in one synchronous turn, nested hosts deepest-first. render(host, {tabStore, offer, offerElement}) builds the instance's real markup using authored values and tab-local mechanical state; it performs no network or asynchronous work and returns the structure the behavior module adopts with initialRender(host). The widget loader imports that same bundle before the behavior module for later revision and thread arrivals, only where it has not already registered. The coordinator preserves the original authored markup and node routes before rendering, so source comparisons and semantic readings do not consume the drawing. Requires x-upgrade: true and excludes x-prepaint.","x-prepaint":"Markup an upgraded element shows at its first paint, before its module draws: one element holding the structure the module will draw, with words that size it as the drawing's will. Delivery writes it into every occurrence in the served document, as the element's first child marked data-lf-prepaint, so the browser lays the widget out from its real structure, wrapping as its drawing will, rather than in a room summed from line heights; the theme holds that room and paints none of it, and a reading without the runtime hides it. The module takes it out in the same step that draws its replacement, so nothing moves, and draws by filling in a copy of the same markup, so the declaration is the one statement of that structure. `{\"as\": tag}` declares the markup of the named widget, for one that first paints as that widget will stand in it, as a command with no seat draws a readings seat at its head. It is written exactly as the parser reads it back, every element closed, since delivery inserts it as written and markup left open would take in the occurrence's own children; and it carries no id, no custom element and no script, since every occurrence gets a copy. Declare it on a widget whose drawn structure is fixed while its values come from the log, as a command's outcome and count tiles are; a drawing whose rows the log decides has no structure to write in.","x-views":"`true`: the element shows one of its members at a time, as a tab set shows one panel, and its module opens it on the member the runtime names (`openingView`) and records each member it shows (`keepView`). The runtime opens it on the member holding the element the address's fragment names, else on the member this browser tab last showed, else on the first; a reload puts the member last shown before the fragment's. Delivery paints it into the served document as data-lf-views, and before the first paint Leaf marks the member it will open `data-lf-opening`, so the package theme can show that member alone until the module upgrades the element.","x-visual":"How a rendered picture exposes stable Comment targets. `whole` anchors the picture on the authored widget. Every declared provider also supplies its own visual surface for whole-widget aim and marks, so chrome paint stays above the widget's drawing. For `{parts: ATTR}` or `{prefixes: [PREFIX, \u2026]}`, its module calls `registerVisualParts(source, read)` once; `read` returns the complete current `{id, element, label, surface?}` inventory. Core admits only ids authored in ATTR or, under `prefixes`, any longer id one of them begins, such as `commit:3f2a` under `commit:`: a picture drawn from data whose parts the author cannot list declares their kinds rather than enumerating them. Core derives token lookup and deepest-part hit testing from that inventory. `surface` defaults to `element` and may name one descendant whose native paint excludes decoration from the contour. It changes paint only: `element` remains the semantic hit and travel target. Marks and aim follow an SVG surface's painted geometry primitives; a surface with none, and every other element, uses the shown box. Targeting a mapped part stores its id as `anchor.visual` while the widget remains the semantic seat. A missing token or registration detaches on replay rather than widening to the whole picture. A visual that draws its parts over time passes `registerVisualParts(source, read, {reveal})`: `reveal(id)` synchronously draws a state whose inventory holds that declared part. A declared part absent from the current state then places its threads on the whole picture, and travel to the part, whether a thread anchored there or a module's `navigateToDatum`, calls `reveal` before landing on it. The registration's `update()` signals any rendering or geometry change, including an in-place attribute or style change. The render gate validates every record, requires each authored token to resolve, in the current state or after its `reveal`, and refuses a registered id its prefixes do not admit. A `{parts: ATTR, complete: true}` declaration also refuses a nonempty authored list that omits a registered part; omitting ATTR keeps the whole picture as one target.","x-space":"The default width an element takes in a flow wider than the prose measure: `column` keeps that measure and starts where the prose does, for an element or idiom whose content is read as lines of text or that frames prose (an Ask, `.callout`), and it widens to the widest allocation among its own blocks; `wide` takes the vocabulary's shared capped evidence width; `available` takes all room the page shell can give after enclosing frames, chrome, and actual margin residents. An element that declares none fills the box it stands in. The declaration says nothing about how the package arranges content inside that allocation. An authored occurrence may override the default with data-width=column|wide|available; delivery paints that choice into the served document as data-lf-space and the theme allocates it without moving the prose axis.","x-face":"Child selectors, each `:scope > ` and then a tag, classes, or both (`:scope > lf-new`, `:scope > .lf-shotrail`), naming the light-DOM children that are painted boxes that draw the element's own face rather than separate things it holds: a suggestion's tinted slots, a screenshot's caption rail. A margin pin whose target is this element may stand on them, as it stands on the element itself, and still keeps off their words; every other box inside the target that paints its own extent counts whole, since a pin on it reads as that box's, as a choice's pin on its first option's card would read as that option's. Declare it only where a pin on the part reads as the whole element's.","x-bound":"The element holds its own height and scrolls inside it, so a long log or feed never grows the page: `start` opens at its first line and `end` follows its newest entry while the user is at the end, and stays where the user scrolled back to otherwise. An authored occurrence may state or override it with data-bound=start|end; delivery paints it into the served document as data-lf-bound.","x-height":"The height, in CSS pixels, the page reserves for the element before its module draws: the declaration's number, or an authored occurrence's data-height, which overrides it; `true` declares no number, so only an occurrence's data-height reserves. Delivery paints it into the served document as data-lf-height, and wherever the runtime runs the theme holds the box to it from the first paint until the module marks the element drawn (`lf-rendered`), when the box becomes the drawing's own. Declare it on a widget whose drawing cannot be sized from its markup before the module draws. A module that can draw to any height, as a chart's can, draws at the stated one, so nothing moves when the reservation ends; one whose content has a height of its own draws that, and the reservation is the author's estimate of it. A failure takes the height of the message it shows.","x-history":"`true`: the module renders the page's history, so a page whose markup holds one is served the `history` reading beside its state and a page without one does not pay for it. The reading is the newest 50 logged moves, newest first, each naming who moved, what they did, the thread it belongs to and that thread's title, whether a later undo took it back, and for a widget gesture the words its ids had in the document it was made in, so a later version rewording or removing what was chosen leaves the row as made. The module reads it through `watchHistory`.","x-withdrawn-as":"A declared deciding outcome that declines the proposal. It answers the Ask without closing the widget's `resolves` thread. A revision may also remove an unanswered proposal directly, whether or not it has retirable slots; historical ids do not veto the edit.","x-name":"The attribute whose value is this tag's title: what the page calls one of these elements when it names it away from itself, as the activity feed does for where something happened. Leave it off where the authoring contract already titles the element: a section by its heading, a disclosure by its summary, a titled member by its leading <strong>. Declare it where an attribute is the title instead, as a column's or a tab's `label` is. An attribute the element merely shows first, such as a metric's value or a chronology entry's time, is not its title.","x-word":"What x-word declares: this tag's own word for what it is comes from its module, which answers `lfWord()` on the element, rather than from the tag's name. Almost no widget declares it, and none needs to while one tag is one kind of thing: a name away from the page is then the tag with its prefix dropped. It is wrong where a tag holds several kinds. Every shape of lf-suggestion came out as \"suggestion\", so a row in the Questions panel named a deletion by the words it proposed to remove and read exactly like the insertion above it. The word is asked for wherever the page names an element away from itself \u2014 a drawer row, a comment's anchor label \u2014 and an element that has not upgraded yet, or answers nothing, falls back to the tag. The same declaration lets the module answer `lfSays()` with its own words, for a tag whose text nodes run together away from its paint (a rewrite's old and new); an element answering nothing is read as text.","x-work":"`true`: this widget is a block prose seat that can admit `leaf task open` without a pending user move, so the task shows as local chrome beside its authored markup. Only a block widget whose x-content is markup may declare it. Once admitted, a page-widget task appears at the page edge through its target margin entry even if a later layer drops x-work. The declaration is permission for runtime chrome, not a consequence of x-content: markup may itself be an owner gesture or sit in a hidden panel."},"$state":{"unit":"\"widget\" for a verb absolute across the group (choose toggles every sibling), or the detail field naming the element the verb is absolute per. Recorded positions use \"unit\"; custom commands name their own field.","creates":"An optional created-child contract `{child, words}` on an x-state verb. The verb's fold unit names the detail field carrying the new child's canonical element id, and `words` names the detail field carrying its non-empty prose; the detail holds exactly those two required fields and the verb declares no record form. While the action stands, the sender has a direct `child` with that id and words, on the action's own owner-unit-verb coordinate: an action of another verb leaves it standing, and undoing or retracting the action removes it. Admission stamps the child tag in `meaning.creates`, so registry-free readers keep the action resting on its child before any markup holds it. The append door refuses an id the sending document already holds. Admission also captures the semantic state definition in meaning.state. A later incompatible definition does not reinterpret that historical action as current state.","record":"How the state reads in markup: {kind: \"attribute\", attr} \u2014 every element inside the unit carrying attr, sorted, vs the ids `detail.value` lists, which is why that field is an array however many the widget allows at once; {kind: \"position\", within} \u2014 the enclosing `within` element and the nearest unit both documents list before it there, with `detail.unit` naming the moved item, `detail.value` its destination and `detail.rank` its rank among its container's siblings: a base-36 fraction key, digits 0-9a-z not ending in 0, that sorts as a string, so a container lists its units by rank (ties by id) and a unit's placement stands whichever other moves stand or are undone. Authored units rank by authored index, and a widget computes a dropped unit's rank between its new neighbours' with `rankAt` from `runtime/widget-api.js`. A rank lies among the container's authored units on the revision the move was made on, which admission records as `meaning.among`. While a later revision authors that container the same way, the rank lands in the same gap and places the unit; a revision that authors it differently absorbs the move, writing the unit where the fold left it, which becomes its authored position, and its markup places the unit from then on. Later revisions may change that placement, and an absorbed move can no longer be undone; a new move changes where the unit stands. The append door refuses a move made on an older revision whose container the newest one authors differently. Equal ranks are a known limit: two tabs dropping into one gap tie, and the id order can put the later drop outside the gap it was dropped into. A position record's unit is always a part (a widget cannot place itself), because only the widget holding the container can read the neighbours a rank lies between; {kind: \"body\"} \u2014 the unit's own words; {kind: \"value\", attr} \u2014 the unit's own attr holding one scalar, whose `detail.value` carries the attribute's own schema so the log's contract and the markup's cannot drift. Within one tag and unit, body and position are each one physical slot; value slots are keyed by their host attr, and attribute-set slots by their descendant attr. Distinct verbs cannot claim the same slot. A node has one place across tags as well: the nearest recording widget above it places it. Recorded verbs declare no `detail` schema or input-field mappings: the effect defines a closed object requiring `value`, plus `unit` and `rank` for positions. An agent verb with `update: true` also requires nonempty string `text`. The framework captures the typed initial value once, composes it with surviving winners and local gestures, and renders the resulting complete widget state. An absent value attribute starts at null, an attribute set at its authored ids, and a recordless verb at null (undecided). Position records compose ordered containers before rendering, so undo and refusal do not reset or rebuild the DOM."},"$report":{"answering":"Explicit, by typed id. `page stamp` puts a report target in the note's settles relation when the stamped revision absorbs its recorded state or marks its element overruled. Replay stops a settled report at that revision. An unchanged baseline settles nothing, so the report keeps painting. Changing authored content never requires a historical-state permission gate.","overruled":"A boolean attribute on the reported element, declared by every widget with an agent-written x-state verb: this revision keeps its own state over the standing report. It belongs to the revision whose stamp does the overruling \u2014 stamping records the answer on the note, so later revisions leave it off.","updates":"Reports share one derived update feed in log-causal order. Every entry has a typed target (`widget` or `thread`), source (`report`), action, structured detail, optional declared text, speaker, timestamp, version, sequence, and one closed disposition: `effective` contributes to current state on its semantic coordinate, `standing` still awaits settlement but is presently outranked, and `settled` has been answered by a version note that names it. The work the agent has in hand is no update: it is the workflows' Working stage and the open tasks' running start.","wakes":"A report joins the watcher's batch: `leaf wait` prints it beside user events, the same `ack` acknowledges it, and idling is refused over one nobody read. The user's banner counts none of this \u2014 a report is news the agent owes the page, not something the user owes an answer."},"$settlement":{"description":"The typed `settles` relation on a version note ends provisional agent facts. Each target is `{kind, id}` so independently allocated id namespaces cannot collide and adding a kind does not add another parallel note field. The relation is explicit and durable: chronology alone ends nothing, and a later note need not repeat a settlement.","report":"The id is a report event. Stamping derives these targets from reported state the source absorbs or explicitly overrules.","task":"The id is an open task on a page widget. `page stamp --completes <widget>` writes this target for every open task on that widget opened before the stamped revision, which ends it `done` citing the version, and licenses the revision to remove the widget.","why-restated-is-separate":"`restated` is not a settlement. It retracts a user decision because authored words or state invalidated what the decision rested on, while `settles` completes provisional information supplied by the agent. Conflating them would make ending work look like taking back the user's action."},"$awaits":{"when":"The attribute condition that makes a local Leaf element an Ask: each attribute maps to the values that require an Ask, a flag attribute's values being true and false. Every named condition must match. A group takes picks only with `choose` and stops requiring an Ask once it is `settled`. An entry with no `when` is an Ask on every Leaf element, which is what a pending suggestion is.","answered":"When a local Ask is answered, as a map from each answering x-state verb to the condition its standing state meets; the Ask is answered while any one holds. `{}` holds while the verb's state stands: an attribute or value record that is not empty, read through authored markup as well as the fold so a version that honors the answer keeps it answered and a cleared value opens the Ask again, and otherwise a standing action of the verb on the widget. `when` narrows a verb to instances whose attributes match, which is how a `multiple` group is answered by its Done press (`answer`) while a single-choice group is answered by its pick (`choose`). `empty: {within, when}` holds while the one member container of that tag and static authored attributes inside the widget holds no members under the standing positions, which is how a queue is answered once its designated column is empty; it needs a verb with a position record, and a verb folding on a part needs it. The action whose admission makes a condition hold is the answer, and admission marks it in meaning.answer (x-state). Naming the answering verbs keeps orthogonal actions, such as adding an option, from answering. A thread in the widget's own seat (x-thread-seat) is not an answer; it only takes the Ask off the user's list while the next word there is the agent's.","all":"The outcome a blanket yes takes, where one banner control can answer every Ask of this kind at once (`Accept all (3)`). It is one of the `outcome` values of the widget's deciding verb, which must be one of its answering verbs, and the widget's module exposes a method named for that verb taking the outcome, so the control records each decision separately rather than one blanket consent. Leave it off and the Ask is answered where the user is, one at a time."},"$restated":{"description":"A boolean attribute saying this revision has rewritten words the user already decided on, so what they decided no longer applies and they are being asked again. It goes on the element the decision rests on \u2014 a lf-draft or lf-suggestion, or the lf-card or lf-option inside a board or group \u2014 and retracts every action that named it: a move names one card, so a rewritten card drops that card's moves, leaving the rest of the board arranged as the user left it; a pick names every option chosen at once, so a rewritten option takes back the whole answer it was part of.","why":"Decisions are recorded against the revision the user saw and survive ordinary edits. Change presentation and wording directly when needed. Use this attribute when the decision itself should no longer apply; the log records the retraction without erasing the original answer.","when":"When a revision invalidates a decision and needs a fresh answer, write the new content, mark the element the decision names, and explain the retraction in the stamp note. Revisions do not require this attribute merely to change decided wording or presentation. An unused or repeated marker is harmless.","once":"The marker belongs to the revision that retracts the decision. Stamping records the retraction; leave it off later revisions unless another decision is being withdrawn.","example":"<lf-draft id=\"note-cli\" restated><pre>\nAdds --dry-run to every mutating command. It defaults on for `purge`.</pre></lf-draft>"},"$series":{"description":"The categorical steps this layer paints a chart's series in, and how many of them there are. It is a property of the page rather than of any widget: the colours are --series-1 through --series-N in the theme, so a project that restates the palette with a step more says so once, here and beside the tokens, and every consumer reads the same number. `steps` is how many series a chart can colour apart, and what the palette's own check counts the tokens against. A chart with more series than steps folds the small ones together or splits, since two series in one colour is worse than either. The list is short on purpose: past five, the steps stop clearing the separation a user with colour-vision deficiency needs, and a sixth is a chart that lies to some users and to no others.","steps":5},"$reactions":{"description":"The reaction vocabulary: the one-press words a user can put on a passage, an element, a message in a thread, or the page whole, each recorded as a `comment` or `reply` carrying `token` in place of `text` ($events). The kernel declares the namespace and no word; the default package ships the working set, and any selected package reshapes it merge-patch style: an entry under a token's name replaces that token, a new name adds one, `null` removes one. Core never names or interprets a token. Everything a consumer needs rides the entry: `glyph` is the mark of at most four Unicode code points the page paints for it \u2014 including one emoji \u2014 in the margin, in the reaction list, and on a thread's strip; optional `means` lets a package explain a specialized vocabulary to off-page users without making prose part of Leaf's default tokens; `settles`, where true, says a reaction of this kind standing on the latest agent message of a thread takes that thread out of \"waiting on you\" \u2014 a projection rule the panel reads, never a second event. POST refuses a token outside the merged set, the way $languages gates a language name. Tokens stand independently on one target; reaction lists and their optional digit accelerators follow this declared order, so a digit survives any layer's renaming without changing a chip's label.","tokens":{"keep":{"glyph":"\ud83d\udc4d","settles":true},"change":{"glyph":"\u274c"},"clarify":{"glyph":"\ud83e\udd14"},"shorten":{"glyph":"\u2702\ufe0f"},"support":{"glyph":"\ud83d\udd0e"},"prioritize":{"glyph":"\ud83c\udfaf"}}},"$tones":{"description":"The semantic tints this layer paints, and the whole vocabulary an author may declare: what the lint refuses a word outside, and what the theme has a rule for. It is a property of the page rather than of any widget, which is why it lives here and not under the schema of whichever tag happens to take a `tone` \u2014 a widget declares that one of its attributes names one (x-tone) and the lint reads the list from here, so a second tag taking a tone costs a declaration and no new reader. The list is short on purpose: a page that can paint anything paints nothing, and three is what the palette already answers for. Which facts earn a tint is never the theme's to decide \u2014 `ok` on one page's chip and `danger` on another's may be the same word, because the author is the only one who knows whether the answer is good news.","names":["ok","warn","danger"]},"$idioms":{"description":"Recurring shapes the theme styles directly \u2014 no element declaration, no JS. Plain semantic HTML gets the theme's voice for free; these classes cover what HTML lacks an element for. Each key is the CSS selector the shape is written as, and the example beside it is that markup. A layer adds one by declaring it here and styling it in its theme.css; members merge across layers, so the declaration joins this catalog rather than replacing it.","button.button":{"description":"A page-local action button. The button class supplies the layer's control typography, frame, hover and focus treatment. A toggle states its selection with aria-pressed; true draws the selected face. These classes supply presentation; the page module owns the action and state.","example":"<button type=\"button\" class=\"button\" aria-pressed=\"true\">Anchored threads</button>"},"select.field, input.field":{"description":"A labeled page-local select or single-line text field, using the same typography, frame and height as the layer's buttons. Use the existing control face rather than rebuilding it in page CSS; page CSS arranges the row.","example":"<label for=\"preview-case\">Conversation</label>\n<select id=\"preview-case\" class=\"field\"><option>Short exchange</option><option>Long exchange</option></select>"},".eyebrow":{"description":"A small-caps label above a heading.","example":"<p class=\"eyebrow\">design proposal</p>\n<h1>Widgets</h1>"},".lede":{"description":"The opening paragraph, set slightly larger.","example":"<p class=\"lede\">One paragraph saying what this page decides.</p>"},".tag":{"description":"An inline chip label. Add `ok`, `warn` or `danger` to draw it in that status tone.","example":"<span class=\"tag\">experimental</span>"},".callout":{"description":"An aside set off from the prose \u2014 a tinted field with a hairline border. For something the user must not miss; a note they lose nothing by skipping goes in the margin (aside.sidenote). Add `ok`, `warn` or `danger` when the callout reports a status, as `class=\"callout warn\"` for a paused release; its tint and title take the tone and its prose stays in the body's ink. On a wide page it keeps the prose's width; one holding a chart or table that needs more takes `data-width`.","x-space":"column","example":"<aside class=\"callout\" id=\"rollback-note\">Rollback is one flag flip; the backfill is idempotent.</aside>"},"section.panel":{"description":"One titled region of a wide page (`<main class=\"layout-sidebar\">` or another wide Layout): a card holding one surface, such as a table, a log or a list of steps, with a short heading that names it. Lay a dashboard out as panels in the Layout's tracks so every region is drawn alike; the page's argument stays in the prose and the callout.","example":"<section class=\"panel\" id=\"checks\">\n  <h2>Checks</h2>\n  <table>\u2026</table>\n</section>"},"aside.sidebar":{"description":"Page-level supporting material in the left margin: local navigation, a compact legend, or stable reference facts that remain useful while the user moves through a long page. Use one, as a direct child of main near the page's opening, rather than beside the one paragraph it concerns; that local annotation is an aside.sidenote. On a roomy live screen the first such child of a column page sits left of the prose and sticks beneath Leaf's banner, the column moving right to make the room; a fine-pointer lf-toc can use that margin as a fixed reading map instead. Where the window has no room for the strip beside the column and its rail, and on paper, the sidebar returns to ordinary flow where it was authored. An accidental second sidebar also stays in flow instead of occupying the first. Keep the contents compact enough to scan in about 240px. The wrapper supplies placement, not a visual panel, so what it holds keeps its own voice; an lf-toc is the usual navigation occupant but the idiom is not coupled to that widget. Its content remains part of the page and may be selected or commented on unless the occupant itself declares apparatus.","example":"<aside class=\"sidebar\" id=\"page-route\">\n  <nav aria-label=\"On this page\"><strong>On this page</strong><ol><li><a href=\"#prepare\">Prepare</a></li><li><a href=\"#move\">Move</a></li></ol></nav>\n</aside>"},"aside.sidenote":{"description":"A note in the page's right margin: a caveat, a provenance, a figure the sentence had no room for. It is read where it stands and skipped at no cost, where a .callout sits in the column the user is reading down and a <details> asks for a click. Write it immediately before the paragraph, list or block it annotates, and it comes out level with that block's first line; before a heading it sits above the heading instead, a heading carrying more room over it than the block before it leaves. A second note written soon after the first stacks under it, so a long note pushes the next one down the margin and away from its own block. It reaches the margin through any box that doesn't clip \u2014 a section, a tab panel, a disclosure; written inside one that does, a choose group or a board or a table, it is drawn nowhere at all, and `page check --render` refuses the version rather than letting it ship. It stands there where the window holds the strip beside the column, and beside a sidebar, which takes the margin first; the column moves left to make the room. Elsewhere, and on paper, it is a small indented block where it was written, so nothing it says rests on the margin being there. A suggestion's accept and reject controls hang in the same margin, level with the change they decide, and are drawn over a note that stands level with them: write the note a paragraph clear of a change if its first line has to be read. These are the page's own words, so the user can select, quote and comment on one. A stable id lets Alt-click point at the whole note. The margin holds about fifty-six characters to the line; a note running past a few lines wants to be a paragraph in the column instead.","example":"<aside class=\"sidenote\" id=\"logout-frequency\">Support runs \"log out all devices\" during account-takeover response, about twice a month.</aside>\n<p>Logout must revoke immediately, which rules out any store whose invalidation is eventually consistent.</p>"},".facts":{"description":"A label/value grid for summary facts, as a definition list. Inside a card that stands for one alternative in a group, it docks right as a fixed-width rail instead, aligning each item's scalars down the group.","example":"<dl class=\"facts\">\n  <dt>Owner</dt><dd>payments</dd>\n  <dt>Rollout</dt><dd>behind a flag</dd>\n</dl>"},"ol.steps":{"description":"An ordered procedure with numbered markers.","example":"<ol class=\"steps\">\n  <li>Backfill the new store.</li>\n  <li>Verify counts, then flip reads.</li>\n</ol>"},"svg.drawing":{"description":"A schematic drawing the page makes itself \u2014 a layout, a mechanism, alternatives compared in one frame \u2014 as inline SVG inside a `<figure>`, with `role=\"img\"` and a `<title>` stating its claim. Its marks take classes whose paint is theme tokens, so the drawing follows the light and dark palettes: `.frame` and `.frame-head` for a window or pane and its header, `.line` (`.soft`) for a line of text, `.box` (`.hot` for the one that matters), `.highlight`, `.ghost` for where something would be, `.guide` and `.dim` for alignment and dimension lines, `.arrow` with `.tip` (`.hot`) on its marker, `.mark` for an accent dot and `.glyph` for the character on it, `.ok`, `.warn` and `.danger` fills, and `.strong`, `.small` and `.mono` for text, which is muted otherwise. Without a `width` it fills its figure; give a thumbnail one. A mark particular to the subject takes a page-local class on the same tokens.","example":"<figure id=\"sidebar-width\">\n  <svg class=\"drawing\" viewBox=\"0 0 320 120\" role=\"img\" aria-labelledby=\"sidebar-width-t\">\n    <title id=\"sidebar-width-t\">The sidebar takes 240px left of the column</title>\n    <rect class=\"frame\" x=\"4\" y=\"4\" width=\"312\" height=\"112\" rx=\"6\"/>\n    <rect class=\"box hot\" x=\"16\" y=\"20\" width=\"72\" height=\"84\" rx=\"3\"/>\n    <rect class=\"line\" x=\"104\" y=\"24\" width=\"180\" height=\"6\" rx=\"3\"/>\n    <rect class=\"line soft\" x=\"104\" y=\"38\" width=\"150\" height=\"6\" rx=\"3\"/>\n    <text class=\"strong\" x=\"52\" y=\"66\" text-anchor=\"middle\">240</text>\n  </svg>\n  <figcaption>In a narrow window the sidebar returns to the column.</figcaption>\n</figure>"},"table":{"description":"Rows of one shape, compared column by column: ceilings per plan, runs per configuration. Columns take the width of what they hold, and a table wider than the measure wraps its cells or, failing that, scrolls inside itself \u2014 so nothing in one needs a width. An identifier \u2014 a test name, a path \u2014 is one word to the line breaker: in `<code>` it breaks inside its cell where it must, so a column of them takes a share of the measure beside the prose; bare, it holds its column to its own width and squeezes the rest to a word a line, and `page check --render` refuses a table that scrolls sideways with a cell in it wrapped. `<th scope=\"row\">` names a row in the page's own voice; a bare `<th>` is a column heading, set in small caps as one. A `<caption>` above the rows says what the columns mean where the section's heading doesn't. Reach for a KPI widget when the numbers are a handful of headline figures rather than a grid, and a decision widget when the rows are alternatives the user picks between.","example":"<table id=\"tiers\">\n  <caption>Ceilings per plan, and what each is counted against.</caption>\n  <thead><tr><th>Plan</th><th class=\"num\">A minute</th><th>Counted against</th></tr></thead>\n  <tbody>\n    <tr><th scope=\"row\">Free</th><td class=\"num\">60</td><td>the token</td></tr>\n    <tr><th scope=\"row\">Team</th><td class=\"num\">600</td><td>the token</td></tr>\n  </tbody>\n</table>"},"td.num":{"description":"A cell holding a quantity, right-aligned so a column of them lines up on its last digit \u2014 the comparison a column of figures is there for. Say it on the column's heading cell too, or the heading hangs left of its own figures. Nothing is guessed from the text: \"60\" and \"60 sessions\" are the same shape and different things.","example":"<tr><th scope=\"row\">Enterprise</th><td class=\"num\">6,000</td><td class=\"num\">12,000</td></tr>"},"details":{"description":"Evidence: a claim as the <summary>, its backing collapsed beneath. Native disclosure; find-in-page reaches the collapsed content.","example":"<details>\n  <summary>The parser drops the slash on self-closed custom tags</summary>\n  <pre><code>document.querySelector(\"lf-code\").textContent\n// \u2192 \"rest of the paragraph\"</code></pre>\n</details>"},"pre > code[class*=\"language-\"]":{"description":"A literal the user can select and quote: a command to run, a config file, a snippet of output. Name the language to color it \u2014 one of $languages, the same list a widget's own language attribute is held to; a language outside it stays uncolored. Leave the class off where the body isn't source; nothing is guessed from the text. Reach for an annotated code block instead when the block is a walkthrough: numbered lines, highlighted ranges, remarks anchored at a line.","example":"<pre><code class=\"language-bash\">leaf page check ~/.local/state/leaf/pages/auth-diagnosis --render</code></pre>"},"nav.sitenav":{"description":"The product site's compact route bar, written as the first child of main.","example":"<nav class=\"sitenav\" aria-label=\"Site\"><a class=\"brand\" href=\"/\">leaf</a><a href=\"/examples/\">Examples</a></nav>"},"header.hero":{"description":"A product-page opening with extra room and one larger headline.","example":"<header class=\"hero\" id=\"top\"><h1>Generative UI for your agent.</h1><p class=\"lede\">The agent builds the page your task needs.</p></header>"},"footer.site-footer":{"description":"The product site's quiet route and license colophon.","example":"<footer class=\"site-footer\" id=\"colophon\"><p><a href=\"/\">Home</a> \u00b7 <a href=\"/examples/\">Examples</a></p></footer>"}},"lf-ask":{"description":"A complete question for the user, with its context and one answer widget.","x-space":"column","x-instructions":"Begin with a direct heading that states the question without relying on surrounding prose. Include the evidence needed to answer and exactly one non-quoted widget declaring a local Ask through x-awaits. Keep an ordinary semantic section around the Ask when the document needs a section landmark.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"}},"required":["id"],"additionalProperties":false,"x-content":"markup","x-ask-surface":true,"x-upgrade":false,"x-example":"<section id=\"storage-section\">\n  <lf-ask id=\"storage-decision\">\n    <h2>What should a full store do?</h2>\n    <p>The beta never reached the cap. This decides what the first workspace at it sees.</p>\n    <lf-options id=\"full-store\" choose>\n      <lf-option id=\"store-evict\"><small class=\"tag\">editing: continues</small><small class=\"tag ok\">recommended</small><strong>Drop the oldest documents</strong> Editing continues. <em>My take: this keeps work moving without losing server data.</em></lf-option>\n      <lf-option id=\"store-stop\"><small class=\"tag\">editing: paused</small><strong>Pause offline editing</strong> Nothing leaves.</lf-option>\n    </lf-options>\n  </lf-ask>\n</section>"},"lf-gloss":{"description":"A short explanation the reader can open beside a phrase without leaving its sentence.","x-instructions":"Write a self-contained explanation at the first useful occurrence rather than on every repetition. Keep the phrase out of authored parentheses: print adds the explanation as a parenthetical note.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"tip":{"type":"string","minLength":1}},"required":["tip"],"additionalProperties":false,"x-content":"markup","x-inline":true,"x-says":{"tip":"after"},"x-upgrade":true,"x-verbatim":true,"x-example":"Deploy through a <lf-gloss tip=\"A thin, end-to-end path through the real system.\">walking skeleton</lf-gloss> before parallelizing."},"lf-num":{"description":"A measured scalar embedded in prose, tied to the snapshot that established it.","x-instructions":"Write the displayed value with its unit as the element text. Bind source to the repeatable measurement feed and set at to the updated instant leaf data set printed for that snapshot. Read authoring-evidence.md, Measured facts, for measurement and staleness checks. Use via when the source id alone leaves the command or query unclear.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"source":{"type":"string","pattern":"^[a-z][a-z0-9-]*$"},"at":{"type":"string","format":"date-time"},"via":{"type":"string","minLength":1}},"required":["source","at"],"additionalProperties":false,"x-content":"markup","x-data":{"measurement":{"contract":"measured-scalar","source":"source"}},"x-inline":true,"x-measured":{"input":"measurement","at":"at"},"x-upgrade":false,"x-example":"The import now takes <lf-num source=\"import-latency\" at=\"2026-08-27T09:00:00Z\" via=\"uv run bench-import\">184 ms</lf-num> at p95."},"lf-text-document":{"description":"A file-backed text document with optional syntax coloring and rendered Markdown or HTML previews.","x-instructions":"Bind source to the page-owned feed. Use label to name the file. Set preview to markdown or html for Preview and Source tabs over the same text; language optionally overrides the source syntax. HTML is a separate document: its provider owns typography, spacing, and responsive CSS; it inherits no Leaf styles. Both readings share a scrollable viewport sized by --lf-bound (28rem by default). Compose ordinary lf-tabs for other kinds of preview. Put it inside details when it should begin collapsed.","x-name":"label","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"source":{"type":"string","pattern":"^[a-z][a-z0-9-]*$"},"label":{"type":"string","minLength":1},"preview":{"type":"string","enum":["markdown","html"]},"language":{"type":"string"}},"required":["id","source"],"additionalProperties":false,"x-content":"empty","x-data":{"document":{"contract":"text-document","source":"source"}},"x-language":"language","x-upgrade":true,"x-example":"<lf-text-document id=\"leaf-skill\" source=\"leaf-skill\" language=\"markdown\"></lf-text-document>"},"lf-annotation-rail":{"description":"An authored-flow rail for Threads, Asks, action and status contributions, updates, and the active comment editor.","x-instructions":"Select data-annotations=page on body. When the task needs conversations and actions in an independent reading region, place one empty rail with a stable id; page-authoring.md, Bounds and widths, guides that choice. Allocate its width and height in page CSS; it scrolls within that box. Omit it to use the core Threads panel. Native disclosures retain their open state and the shared Thread renderer owns conversations and replies.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"}},"required":["id"],"additionalProperties":false,"x-content":"empty","x-upgrade":true,"x-example":"<lf-annotation-rail id=\"page-annotations\"></lf-annotation-rail>"},"lf-toc":{"description":"An outline of the document\u2019s h2\u2013h6 headings for navigating its sections and showing the reader\u2019s position.","x-instructions":"Set max-level when deeper headings are local detail rather than navigation destinations; omit it to include h2\u2013h6. Use stable authored section, title-group, or heading ids for links that must keep their target across versions; generated heading ids are not addresses for comments or page state. Write the element empty with a stable id.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"max-level":{"type":"string","pattern":"^[2-6]$"}},"required":["id"],"additionalProperties":false,"x-content":"empty","x-upgrade":true,"x-example":"<h1>Migration plan</h1>\n<aside class=\"sidebar\" id=\"plan-sidebar\">\n  <lf-toc id=\"plan-contents\"></lf-toc>\n</aside>\n<section><h2>Prepare</h2><p>Take a snapshot.</p><h3>Check capacity</h3><p>Leave headroom for the copy.</p></section>\n<section><h2>Move</h2><p>Shift one cohort at a time.</p></section>"},"lf-activity":{"description":"A newest-first feed of the page\u2019s comments, actions, reports, and published revisions.","x-instructions":"Write it empty with a stable id.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"}},"required":["id"],"additionalProperties":false,"x-content":"empty","x-bound":"start","x-history":true,"x-upgrade":true,"x-initial":"/vendor/lf-activity-initial.js","x-example":"<section id=\"recent\">\n  <h2>Recent activity</h2>\n  <lf-activity id=\"page-activity\"></lf-activity>\n</section>"},"lf-options":{"description":"Alternatives the user can choose individually or as a set to answer a question.","x-space":"column","x-instructions":"Keep shared premises and evidence with the group; lf-ask can frame its question and context. Keep each alternative's case and decision-relevant evidence inside its lf-option. Use multiple for one answer containing a set of selections; leave it off for mutually exclusive alternatives. Read references/authoring-asks.md to separate independently answerable proposals. The built-in Another option field accepts unlisted answers, so author the alternatives you mean without a catch-all option. Use for only to select sections or work items that exist independently of the decision; do not create sections solely to hold alternatives. To incorporate a user-added option into a revision, keep its id and words as an ordinary lf-option. A multiple-choice Ask still needs the user's Done even when chosen is authored. Use settled to collapse a retired decision while preserving its options and anchors.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"choose":{"type":"boolean"},"multiple":{"type":"boolean"},"settled":{"type":"boolean"},"restated":{"type":"boolean"}},"dependentRequired":{"choose":["id"],"settled":["id"],"multiple":["choose"]},"additionalProperties":false,"x-content":"members","x-word":"module","x-upgrade":true,"x-awaits":{"when":{"choose":[true],"settled":[false]},"answered":{"choose":{"when":{"multiple":[false]}},"answer":{"when":{"multiple":[true]}}}},"x-state":{"choose":{"unit":"widget","record":{"kind":"attribute","attr":"chosen"}},"add":{"detail":{"type":"object","properties":{"option":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"text":{"type":"string","minLength":1}},"required":["option","text"],"additionalProperties":false},"unit":"option","creates":{"child":"lf-option","words":"text"}},"answer":{"detail":{"type":"object","additionalProperties":false},"unit":"widget"}},"x-example":"<lf-ask id=\"run-status-decision\">\n  <h2>Where should run status appear?</h2>\n  <p>Both choices preserve the existing run detail.</p>\n  <lf-options id=\"run-status\" choose>\n    <lf-option id=\"rs-column\">\n      <small class=\"tag\">effort: low</small><small class=\"tag warn\">risk: med</small><small class=\"tag ok\">recommended</small>\n      <strong>Status on the run list</strong> One join; failures are visible without a click.\n      <figure id=\"rs-column-fig\">\n        <svg class=\"drawing\" width=\"240\" viewBox=\"0 0 240 56\" role=\"img\" aria-labelledby=\"rs-column-t\">\n          <title id=\"rs-column-t\">Each run row ends in its status</title>\n          <rect class=\"frame\" x=\"1\" y=\"1\" width=\"238\" height=\"54\" rx=\"4\"/>\n          <rect class=\"line\" x=\"12\" y=\"14\" width=\"150\" height=\"6\" rx=\"3\"/><circle class=\"ok\" cx=\"222\" cy=\"17\" r=\"5\"/>\n          <rect class=\"line\" x=\"12\" y=\"36\" width=\"150\" height=\"6\" rx=\"3\"/><circle class=\"danger\" cx=\"222\" cy=\"39\" r=\"5\"/>\n        </svg>\n      </figure>\n    </lf-option>\n    <lf-option id=\"rs-leave\">\n      <small class=\"tag\">effort: none</small><small class=\"tag ok\">risk: low</small>\n      <strong>Leave the list alone</strong> No work; failures stay one click away.\n      <figure id=\"rs-leave-fig\">\n        <svg class=\"drawing\" width=\"240\" viewBox=\"0 0 240 56\" role=\"img\" aria-labelledby=\"rs-leave-t\">\n          <title id=\"rs-leave-t\">Run rows carry no status</title>\n          <rect class=\"frame\" x=\"1\" y=\"1\" width=\"238\" height=\"54\" rx=\"4\"/>\n          <rect class=\"line\" x=\"12\" y=\"14\" width=\"150\" height=\"6\" rx=\"3\"/><circle class=\"ghost\" cx=\"222\" cy=\"17\" r=\"5\"/>\n          <rect class=\"line\" x=\"12\" y=\"36\" width=\"150\" height=\"6\" rx=\"3\"/><circle class=\"ghost\" cx=\"222\" cy=\"39\" r=\"5\"/>\n        </svg>\n      </figure>\n    </lf-option>\n  </lf-options>\n</lf-ask>"},"lf-option":{"description":"One alternative in a decision, shown as a compact label or a card with supporting evidence.","x-instructions":"Lead a card with matching small.tag comparison labels naming the facts that distinguish the alternatives, then a `<strong>` title and a sentence naming its consequence. Mark the option you recommend with `<small class=\"tag ok\">recommended</small>` after its comparison labels, and give the reason in prose. chosen records the user's pick. Where alternatives differ in arrangement, structure, or mechanism, draw each with an svg.drawing thumbnail in the same frame, alike except where they differ. Add paragraphs or a fact rail when the face alone cannot support the choice. A bare label suits an alternative needing no further case. Direct text uses inline Markdown; use HTML children for block content. A for target must remain useful independently of the decision and does not supply the option's words. Rewriting a picked option needs restated; read $restated for when to rewrite instead of correcting beside the Ask.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"for":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"chosen":{"type":"boolean"},"restated":{"type":"boolean"}},"required":["id"],"additionalProperties":false,"x-owners":["lf-options"],"x-content":"markup","x-text-format":"inline-markdown","x-refers":{"for":{}},"x-upgrade":false},"lf-code":{"description":"A source-code excerpt with syntax coloring, highlighted lines, and line-anchored remarks.","x-instructions":"Write the exact code inside pre at column 0, HTML-escaping & before < and >. Set language for source code and omit it for plain transcripts or command output. For excerpts, set lines to the ascending source ranges quoted, such as 1505-1507,1520-1527; hi and lf-note at then use those source numbers. A note addressed to an omitted line captions the elided row.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"language":{"type":"string"},"hi":{"type":"string","pattern":"^[0-9]+(-[0-9]+)?(,[0-9]+(-[0-9]+)?)*$"},"lines":{"type":"string","pattern":"^[1-9][0-9]*(-[1-9][0-9]*)?(,[1-9][0-9]*(-[1-9][0-9]*)?)*$"}},"required":["id"],"additionalProperties":false,"x-content":"data","x-language":"language","x-lines":["hi"],"x-numbering":"lines","x-upgrade":true,"x-example":"<lf-code id=\"bracket-walk\" language=\"python\" hi=\"2\"><pre>\ndef bracket(temp):\n    if temp &lt; 0:\n        return \"steel\"\n    return \"cedar\"\n</pre>\n  <lf-note at=\"2\">Freezing is the only threshold that matters.</lf-note>\n</lf-code>"},"lf-note":{"description":"A prose remark anchored to a line or omitted range of its lf-code parent.","x-instructions":"Set at to the line number as the parent numbers it: 1-based by default, or the source number declared in lines.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"at":{"type":"string","pattern":"^[0-9]+$"}},"required":["at"],"additionalProperties":false,"x-owners":["lf-code"],"x-content":"markup","x-lines":["at"],"x-upgrade":false},"lf-chart":{"description":"An Observable Plot chart authored with Plot\u2019s API and sized to its place in the page.","x-instructions":"Write a JavaScript expression for Plot.plot's options inside pre, HTML-escaping & before < and >; give the options object rather than calling Plot.plot. Plot and width are the only names in scope, and data stays inline. Use ISO date strings on an explicitly typed time scale; use utc for days and months, and include a timezone on moments, such as 2026-06-01T14:00Z. Supply ariaLabel describing the chart for users who cannot see it. Leave width and height out of the options: use width to adapt ticks, and data-height on the element for a nondefault height. Where page check --render reports overlapping labels, reduce category ticks, choose them by width, or reserve more margin for the axis label. Use var(--series-N) for constant or categorical colors; continuous color scales need a Plot scheme because CSS variables cannot be interpolated. Name the chart in the surrounding heading or prose rather than Plot's title.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"}},"required":["id"],"additionalProperties":false,"x-content":"data","x-upgrade":true,"x-visual":"whole","x-height":400,"x-example":"<lf-chart id=\"review-latency\"><pre>\n{\n  ariaLabel: \"Hours to first review by week: backend fell from 31 to 12, frontend from 18 to 11\",\n  x: {type: \"utc\", ticks: \"monday\", label: null},\n  y: {grid: true, label: \"hours to first review\"},\n  color: {legend: true, range: [\"var(--series-1)\", \"var(--series-2)\"]},\n  marks: [\n    Plot.lineY(\n      [\n        {week: \"2026-05-04\", team: \"backend\", hours: 31},\n        {week: \"2026-05-11\", team: \"backend\", hours: 26},\n        {week: \"2026-05-18\", team: \"backend\", hours: 12},\n        {week: \"2026-05-04\", team: \"frontend\", hours: 18},\n        {week: \"2026-05-11\", team: \"frontend\", hours: 21},\n        {week: \"2026-05-18\", team: \"frontend\", hours: 11},\n      ],\n      {x: \"week\", y: \"hours\", stroke: \"team\", marker: true},\n    ),\n  ],\n}\n</pre></lf-chart>"},"lf-shot":{"description":"A before-and-after screenshot comparison with an operable divider and optional change outlines.","x-instructions":"Use served image paths printed by leaf page media for before and after, and describe the pair in alt. Read authoring-evidence.md, Source files and media, for captures and when to use outlines. Write explanations in surrounding prose rather than element content. When a decision turns on the change, put the pair inside the proposing option.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"before":{"type":"string","pattern":"^/media/\\S+$"},"after":{"type":"string","pattern":"^/media/\\S+$"},"alt":{"type":"string"},"outlines":{"type":"boolean"}},"required":["id","before","after","alt"],"additionalProperties":false,"x-content":"empty","x-face":[":scope > .lf-shotrail"],"x-upgrade":true,"x-visual":"whole","x-example":"<h3>The option cards</h3>\n<p>The chips now sit above the title, so a scanning eye reads cost before prose.</p>\n<lf-shot id=\"shot-cards\" outlines alt=\"the decision page's option cards\" before=\"/media/0f2c91a4b7de3105.png\" after=\"/media/6b40ac7719ee5d82.png\"></lf-shot>"},"lf-board":{"description":"Cards grouped into columns for scanning work and status, with movement and reordering available.","x-instructions":"Use primarily to display grouped work and status. Prefer explicit controls or lf-options when the user needs to make changes or decisions; the board is not the primary interaction surface. When revising, keep each moved card in the column the user chose unless the revision explicitly retracts that decision with restated on the card. Read authoring-revisions.md, Honor user state. A rewrite that invalidates a move restates the card, not the board.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"}},"required":["id"],"additionalProperties":false,"x-content":"members","x-upgrade":true,"x-state":{"move":{"unit":"unit","record":{"kind":"position","within":"lf-column"}}},"x-space":"wide","x-example":"<lf-board id=\"feeder-board\">\n  <lf-column id=\"col-todo\" label=\"To do\">\n    <lf-card id=\"card-heater\"><strong>Heated perch</strong> Wire the south feeder.</lf-card>\n    <lf-card id=\"card-baffle\"><strong>Squirrel baffle</strong></lf-card>\n  </lf-column>\n  <lf-column id=\"col-doing\" label=\"Doing\">\n    <lf-card id=\"card-camera\"><strong>Camera mount</strong></lf-card>\n  </lf-column>\n  <lf-column id=\"col-done\" label=\"Done\"></lf-column>\n</lf-board>"},"lf-column":{"description":"One named board column, including empty columns the user can move a card into.","x-instructions":"Write a label that names the column on its own. Use tone when landing here carries a status judgment, such as blocked, needing review, or done; otherwise leave it neutral.","x-name":"label","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"label":{"type":"string"},"tone":{"type":"string"}},"required":["id","label"],"additionalProperties":false,"x-owners":["lf-board"],"x-content":"members","x-tone":"tone","x-upgrade":false,"x-says":{"label":"before"}},"lf-card":{"description":"One board card whose identity and comments survive user moves.","x-instructions":"Lead with a `<strong>` title and follow with prose. Keep its id stable across moves. Rewriting a card the user moved needs restated; read $restated.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"restated":{"type":"boolean"}},"required":["id"],"additionalProperties":false,"x-owners":["lf-column"],"x-content":"markup","x-work":true,"x-upgrade":false},"lf-tabs":{"description":"Several views of one artifact, as page navigation, a local tabbed section, or a side-list queue.","x-instructions":"Place the first set directly in main for page navigation; other placements make a framed local tabbed section. Put the shared title and lede before page tabs and the primary current view first. Each lf-tab is a self-contained view, while history, Threads, Asks, versions, and sign-off belong to the whole page. Retire obsolete views once current work no longer depends on them, preserving needed context and passages anchoring open threads or standing decisions in details within the relevant tab. Use list=\"side\" for a queue beside its selected item; it remains framed and its list does not stick.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"list":{"type":"string","enum":["side"]}},"required":["id"],"additionalProperties":false,"x-content":"members","x-upgrade":true,"x-patch":"members","x-views":true,"x-example":"<lf-tabs id=\"views\">\n  <lf-tab id=\"tab-implementation\" label=\"Implementation\">\n    <p id=\"rollout-plan\">Wire the first site this week.</p>\n  </lf-tab>\n  <lf-tab id=\"tab-vision\" label=\"Vision\">\n    <p id=\"product-vision\">Keep the original outcome and constraints in reach.</p>\n  </lf-tab>\n</lf-tabs>"},"lf-tab":{"description":"One labeled view in a tab set, optionally summarized and grouped in a side-list queue.","x-instructions":"Use summary for the few words a side-list queue needs for scanning, such as severity, age, or suggested outcome. Where a queue's items fall into kinds the user works through in turn, such as merge, close, and FYI, give each item its kind as group and place each kind's items together in the order the user should take them; neighbouring tabs with the same group stand under one heading. Keep ids distinct across tabs: they share the page's one id space.","x-name":"label","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"label":{"type":"string"},"summary":{"type":"string"},"group":{"type":"string"}},"required":["id","label"],"additionalProperties":false,"x-owners":["lf-tabs"],"x-content":"markup","x-upgrade":false},"lf-draft":{"description":"A block of text the user owns and can rewrite in place, with recorded revision history.","x-space":"column","x-instructions":"Write exact Markdown source as <pre> followed by one newline, the HTML-escaped source, and </pre> immediately after the source. HTML consumes that first newline; every subsequent character, including indentation and trailing newlines, belongs to the draft. HTML-escape & before < and >. Use a suggestion for an agent-proposed change to existing prose. A draft asks for an edit when needed is present; otherwise it is an optional editing surface. Use lf-ask when that request needs its own heading and supporting evidence, or page sign-off to approve the whole page. Preserve the user\u2019s exact source on revision; read authoring-revisions.md, Honor user state. To replace an edited passage deliberately, write the new text and mark the draft restated; read $restated.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"needed":{"type":"boolean"},"restated":{"type":"boolean"}},"required":["id"],"additionalProperties":false,"x-content":"data","x-word":"module","x-awaits":{"when":{"needed":[true]},"answered":{"edit":{}}},"x-upgrade":true,"x-verbatim":true,"x-text-format":"markdown","x-state":{"edit":{"unit":"widget","record":{"kind":"body"}}},"x-example":"<lf-draft id=\"note-cli\"><pre>\nAdds --dry-run to every mutating command.</pre></lf-draft>"},"lf-sample":{"description":"A quotation of page content, either static or an operable child Leaf page.","x-instructions":"For a live child page, put its main content in one direct template[data-sample] with a stable id. Use window for a whole Leaf window including its chrome. Keep invented content visibly fictional. Read page-authoring.md, Live samples, for child-page interaction, reset, and isolation.","x-name":"label","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"label":{"type":"string"},"window":{"type":"boolean"}},"required":["id"],"additionalProperties":false,"x-content":"markup","x-says":{"label":"before"},"x-exhibit":true,"x-upgrade":true,"x-example":"<lf-sample id=\"spec-gear\" label=\"next season's kit\">\n  <lf-options>\n    <lf-option id=\"sp-paper\"><small class=\"tag\">effort: low</small><strong>Paper maps</strong> Nothing to charge.</lf-option>\n    <lf-option id=\"sp-gps\"><small class=\"tag\">effort: med</small><small class=\"tag ok\">recommended</small><strong>Dedicated GPS</strong> Offline maps, week-long battery. <em>My take: this is the better field tool.</em></lf-option>\n  </lf-options>\n</lf-sample>"},"lf-pane":{"description":"A reading region with an optional header and footer, independently scrollable inside a full-height workspace.","x-instructions":"For independent scrolling, place the pane as a full-height workspace\u2019s body or a direct cell; elsewhere the page scrolls. Wrap multiple body blocks in one div or section. Use label to name the region accessibly and its header for the visible heading. Put action widgets in the direct footer when they should remain reachable as the body scrolls.","x-name":"label","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"label":{"type":"string","minLength":1}},"required":["id","label"],"additionalProperties":false,"x-content":"markup","x-reading-role":"pane","x-upgrade":true,"x-verbatim":true,"x-example":"<lf-pane id=\"detail\" label=\"Selected record\"><p>Read the selected record.</p></lf-pane>"},"lf-diagram":{"description":"A Mermaid diagram with optional comment targets on its named boxes.","x-instructions":"Write Mermaid source inside the pre, HTML-escaping & before < and >. Give each diagram an accTitle naming its subject and an accDescr explaining its relationships for a reader who cannot see it. Draw a chain of more than three steps top-down (flowchart TD), since a long horizontal chain scrolls past the page edge. Use classic flowchart node shapes. Unstyled nodes already use Leaf's accent surface; apply classDef only where a node needs a distinct tone, with fill, stroke, and color together, for example fill:var(--ok-tint),stroke:var(--ok),color:var(--ok-ink). Only those properties and stroke-width are honored. Quote labels containing their shape's closing bracket, as in A[\"names: list[str]\"]. Agentic Mermaid ignores click/link targets, frontmatter, and sequence title; omit state-ending semicolons, declare a state's label before a transition names it, use symbolic ER relationships (||--o{), and write literal characters rather than entity codes such as #36;. These differences are not all caught by page check --render. Omit parts for one whole-diagram comment target. Otherwise list every box with a nameable source id as node:SOURCE_ID: flowchart nodes/subgraphs, states/composite states, sequence participants, classes, and ER entities. Edges, sequence messages, and chart marks have no stable source id.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"parts":{"type":"string","minLength":1,"pattern":"^node:[A-Za-z_][A-Za-z0-9_-]*(?:\\s+node:[A-Za-z_][A-Za-z0-9_-]*)*$"}},"required":["id"],"additionalProperties":false,"x-content":"data","x-upgrade":true,"x-visual":{"parts":"parts","complete":true},"x-space":"available","x-height":true,"x-example":"<lf-diagram id=\"checkout-flow\" data-height=\"364\" parts=\"node:Cart node:Pay node:Receipt\"><pre>\nflowchart TD\n  accTitle: Checkout from cart to receipt\n  accDescr: The cart reaches a payment decision; a paid order produces a receipt.\n  Cart([Cart]) --> Pay{Paid?}\n  Pay --> Receipt[(Receipt)]\n  classDef done fill:var(--ok-tint),stroke:var(--ok),color:var(--ok-ink)\n  class Receipt done\n</pre></lf-diagram>"},"lf-diff":{"description":"A unified patch with per-file navigation, commentable source lines, and optional durable review marks.","x-instructions":"Add review when the user needs to inspect every file and retain review progress, and collapsed when every file should start closed. Bind source to a page-owned patch feed or files manifest; the bound form keeps an empty pre. With no source, write the exact patch in pre at column 0. Keep file headers so languages and line targets can be identified. Each changed file needs an @@ header whose old and new counts match its lines. A hunkless path-only rename uses exactly diff --git, similarity index 100%, rename from, and rename to, with matching nonempty paths; a rename with edits needs ordinary hunks. State binary, mode-only, empty added/deleted, and copy entries separately in prose. For an edited copy destination, omit copy metadata and include its textual hunks. Preserve context-line leading spaces; encode a space-only context line as &#32; so HTML parsing keeps it. HTML-escape an inline patch, & before < and >, or entity text in the source will change silently.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"source":{"type":"string","pattern":"^[a-z][a-z0-9-]*$"},"collapsed":{"type":"boolean"},"review":{"type":"boolean"}},"required":["id"],"additionalProperties":false,"x-content":"data","x-data":{"document":{"contract":"unified-diff","source":"source"}},"x-state":{"review":{"detail":{"type":"object","properties":{"file":{"type":"string","minLength":1},"reviewed":{"type":"boolean"}},"required":["file","reviewed"],"additionalProperties":false},"unit":"file"}},"x-upgrade":true,"x-shadow":true,"x-thread-surface":true,"x-height":true,"x-example":"<lf-diff id=\"mount-diff\" data-height=\"169\"><pre>\ndiff --git a/feeders/mount.py b/feeders/mount.py\n--- a/feeders/mount.py\n+++ b/feeders/mount.py\n@@ -1,2 +1,2 @@\n def bracket():\n-    return \"plastic\"\n+    return \"steel\"\n</pre></lf-diff>"},"$diff":{"widgets":{"lf-diff":{"role":"patch"}}},"lf-call-diff":{"description":"A commentable unified call-tree diff with links to its exact patch evidence.","x-instructions":"Point diff at the lf-diff holding the exact patch. Supply authentic CallDiff plain-text output as the source\u2019s string value:\n\n```bash\njq -Rs . calldiff.txt | leaf data set \"$PAGE\" <source-id>\n```\n\nKeep unchanged tree items as stable comparison landmarks. Prefer one focused file or entry point per widget for a large repository. Do not transcribe the output into markup, invent attribute reads as calls, or redraw separate before-and-after diagrams.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"source":{"type":"string","pattern":"^[a-z][a-z0-9-]*$"},"diff":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"}},"required":["id","source","diff"],"additionalProperties":false,"x-content":"empty","x-data":{"document":{"contract":"text-document","source":"source"}},"x-refers":{"diff":{"via":"$diff.widgets","where":{"role":"patch"}}},"x-upgrade":true,"x-height":true,"x-example":"<lf-call-diff id=\"request-calls\" data-height=\"480\" source=\"request-call-diff\" diff=\"request-patch\"></lf-call-diff>"},"lf-playground":{"description":"An interactive playground for exploring one configuration in an operable preview and choosing it.","x-instructions":"Use lf-ask to frame the configuration question and context when they live outside the playground. A page module can add structured values with registerContributor(name, defaultSnapshot, {read, apply}); call the returned notifier after its gestures. Use one optional registerInstructionProvider(values => text) for prose derived from structured or conditional values. Give the page's complete lf-playground declaration an exact action schema for its task-specific values.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"submit-label":{"type":"string","minLength":1},"restated":{"type":"boolean"}},"required":["id"],"additionalProperties":false,"x-content":"members","x-upgrade":true,"x-awaits":{"answered":{"choose":{}}},"x-state":{"choose":{"detail":{"type":"object","properties":{"values":{"type":"object","minProperties":1,"propertyNames":{"pattern":"^[a-z][a-z0-9-]*$"},"additionalProperties":{}},"instruction":{"type":"string","minLength":1}},"required":["values","instruction"],"additionalProperties":false},"unit":"widget"}},"x-example":"<lf-ask id=\"notification-ask\"><h2>Which notification should we build?</h2><lf-playground id=\"notification-playground\" submit-label=\"Create notification\"><lf-playground-control name=\"format\" label=\"Format\" kind=\"choice\" value=\"banner\"><lf-playground-choice value=\"banner\" label=\"Banner\"></lf-playground-choice><lf-playground-choice value=\"status strip\" label=\"Status strip\"></lf-playground-choice></lf-playground-control><lf-playground-control name=\"radius\" label=\"Corner radius\" kind=\"range\" value=\"10\" min=\"0\" max=\"24\" step=\"1\" unit=\"px\"></lf-playground-control><lf-playground-preset label=\"Status strip\"><lf-playground-setting for=\"format\" value=\"status strip\"></lf-playground-setting><lf-playground-setting for=\"radius\" value=\"4\"></lf-playground-setting></lf-playground-preset><lf-playground-preview><section aria-label=\"Notification candidates\"><article data-candidate=\"banner\"><h3>Banner</h3><p>The real banner responds to the shared controls.</p></article><article data-candidate=\"status strip\"><h3>Status strip</h3><p>The real status strip responds to the same controls.</p></article></section></lf-playground-preview><lf-playground-output>Build the <lf-playground-value for=\"format\"></lf-playground-value> notification with <lf-playground-value for=\"radius\"></lf-playground-value> corners. Replace the notification component and show me its browser test.</lf-playground-output></lf-playground></lf-ask>","x-initial":"/vendor/lf-playground-initial.js"},"lf-playground-control":{"description":"One typed input in a playground.","x-instructions":"Use a stable name for the submitted field and a label for its control. Author its initial value as a string: a finite number for range, true or false for toggle, one child value for choice, a six-digit hex colour for color, or arbitrary text for text. Range controls need max; min, step, and unit are optional. Only choice controls contain lf-playground-choice children.","x-name":"label","type":"object","properties":{"name":{"type":"string","pattern":"^[a-z][a-z0-9-]*$"},"label":{"type":"string","minLength":1},"kind":{"enum":["range","toggle","choice","color","text"]},"value":{"type":"string"},"min":{"type":"string","pattern":"^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?$"},"max":{"type":"string","pattern":"^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?$"},"step":{"type":"string","pattern":"^(?:0\\.[0-9]*[1-9][0-9]*|[1-9][0-9]*(?:\\.[0-9]+)?)$"},"unit":{"type":"string"},"placeholder":{"type":"string"}},"required":["name","label","kind","value"],"allOf":[{"if":{"properties":{"kind":{"const":"range"}},"required":["kind"]},"then":{"required":["max"]}}],"additionalProperties":false,"x-owners":["lf-playground"],"x-content":"members","x-upgrade":false},"lf-playground-choice":{"description":"One labeled value offered by a playground choice control.","x-instructions":"Use value for the submitted value and label for the words the user sees.","x-name":"label","type":"object","properties":{"value":{"type":"string","minLength":1},"label":{"type":"string","minLength":1}},"required":["value","label"],"additionalProperties":false,"x-owners":["lf-playground-control"],"x-content":"empty","x-upgrade":false},"lf-playground-preset":{"description":"A named partial playground configuration the user can apply at once.","x-instructions":"Include settings only for values the preset changes; unspecified controls keep their current values.","x-name":"label","type":"object","properties":{"label":{"type":"string","minLength":1}},"required":["label"],"additionalProperties":false,"x-owners":["lf-playground"],"x-content":"members","x-upgrade":false},"lf-playground-setting":{"description":"One control value applied by a playground preset.","x-instructions":"Set for to a control in the same playground and write value in that control's authored string form.","type":"object","properties":{"for":{"type":"string","pattern":"^[a-z][a-z0-9-]*$"},"value":{"type":"string"}},"required":["for","value"],"additionalProperties":false,"x-owners":["lf-playground-preset"],"x-content":"empty","x-upgrade":false},"lf-playground-preview":{"description":"The operable artifact inside a playground.","x-instructions":"For an A/B comparison, mount both candidates here and read the playground package's author instructions for driving them from one state. Page CSS can bind the playground's reflected values. A page module can consume its public values and change event, own gestures and computed state, and load vendored or page-media assets from the page's origin.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"}},"additionalProperties":false,"x-owners":["lf-playground"],"x-content":"markup","x-upgrade":false},"lf-playground-output":{"description":"The task instruction displayed by a playground and sent with the chosen configuration.","x-instructions":"Write a self-contained task rather than a value dump. Insert lf-playground-value where scalar selections make it more precise; use a registered instruction provider for prose that depends on structured or conditional values.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"}},"additionalProperties":false,"x-owners":["lf-playground"],"x-content":"markup","x-upgrade":true},"lf-playground-value":{"description":"A live scalar value embedded in a playground instruction.","x-instructions":"Set for to a control in the enclosing playground. Numeric values already include the control's unit.","type":"object","properties":{"for":{"type":"string","pattern":"^[a-z][a-z0-9-]*$"}},"required":["for"],"additionalProperties":false,"x-owners":["lf-playground-output"],"x-content":"empty","x-inline":true,"x-upgrade":false},"lf-visual-review":{"description":"A guided review of a typed visual run, with before-and-after evidence and recorded case dispositions.","x-instructions":"Author an empty element with a stable id and bind source to the visual run. Supply focus rectangles when a case should open on its changed area; keep case identities tied to the run rather than the user's temporary inspection choices.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"source":{"type":"string","pattern":"^[a-z][a-z0-9-]*$"}},"required":["id","source"],"additionalProperties":false,"x-content":"empty","x-data":{"run":{"contract":"visual-run","source":"source"}},"x-state":{"review":{"detail":{"type":"object","properties":{"case":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"disposition":{"enum":["looks-right","needs-work"]}},"required":["case","disposition"],"additionalProperties":false},"unit":"case"}},"x-thread-surface":true,"x-upgrade":true,"x-space":"available","x-height":true,"x-example":"<lf-visual-review id=\"docs-review\" data-height=\"720\" source=\"docs-visual-run\"></lf-visual-review>"},"lf-trace":{"description":"A commentable Playwright recording with action phases, native captured frames and saved accessibility elements.","x-instructions":"Bind the widget to an imported playwright-trace source. Optional lf-trace-bookmark members mark exact images or action phases on a time-scaled timeline. Numbers match the chronological Moments list and selected readout. Each moment is independently selectable and exposes its name and time on hover or focus. Close times stack; explicit timeline zoom and pan preserve their native times. Image controls provide pan, zoom, fit and actual size. Ordinary wheel scrolling stays with the page. The ruler starts at recording time zero; navigation selects actual captured stops. Evidence grows in page flow. One chronological timeline includes page actions and browser/context calls without a page. A single-page recording needs no selector; multi-page recordings offer All pages and individual page filters. Separate streams retain their own clocks. Show intermediate frames includes native JPEG frames between them. Left and Right step through the displayed stops. Comments on images pin their exact capture, while comments on saved elements pin the selected action phase and tree path. Keep the linked Playwright viewer running for DOM, source, console and network inspection.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"source":{"type":"string","pattern":"^[a-z][a-z0-9-]*$"}},"required":["id","source"],"additionalProperties":false,"x-content":"members","x-data":{"trace":{"contract":"playwright-trace","source":"source"}},"x-upgrade":true,"x-space":"available","x-visual":{"prefixes":["trace-"]},"x-example":"<lf-trace id=\"recorded-checkout\" source=\"checkout-trace\"></lf-trace>","x-prepaint":"<p class=\"lf-trace-waiting\">Waiting for a Playwright recording.</p>"},"lf-trace-bookmark":{"description":"An authored, labeled jump to an exact captured image or action phase in its trace.","x-instructions":"Set target to an existing trace visual coordinate: trace-ARCHIVE_SHA256-image-IMAGE_ID or trace-ARCHIVE_SHA256-phase-ACTION_ID-PHASE. Read those ids from the imported source; phase is before, action, after, start or end. The widget derives elapsed time from the capture. A target absent from the recording is shown as unavailable.","type":"object","properties":{"label":{"type":"string","minLength":1},"target":{"type":"string","pattern":"^trace-[a-f0-9]{64}-(image|phase)-[a-z0-9-]+$"}},"required":["label","target"],"additionalProperties":false,"x-content":"empty","x-owners":["lf-trace"],"x-name":"label","x-example":"<lf-trace id=\"recorded-checkout\" source=\"checkout-trace\"><lf-trace-bookmark label=\"Popup closes\" target=\"trace-0000000000000000000000000000000000000000000000000000000000000000-image-demo\"></lf-trace-bookmark></lf-trace>","x-upgrade":false},"lf-margin-entry-gallery":{"description":"A developer exhibit of page-edge controls and status indicators across their supported states.","x-instructions":"Use this only in the feature gallery. Ordinary pages demonstrate controls through the live widgets that own them.","type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"}},"required":["id"],"additionalProperties":false,"x-content":"empty","x-exhibit":true,"x-upgrade":true,"x-example":"<lf-margin-entry-gallery id=\"margin-entry-gallery\"></lf-margin-entry-gallery>","x-initial":"/vendor/lf-margin-entry-gallery-initial.js"},"$decisions":{"lf-suggestion":{"verb":"decide","retires":{"accept":["lf-old"],"reject":["lf-new"]}}},"$marks":{"x-space":{"paint":"data-lf-space","authored":"data-width","message":false,"idiom":true},"x-inline":{"paint":"data-lf-inline","message":true},"x-exhibit":{"paint":"data-lf-exhibit","message":true},"x-bound":{"paint":"data-lf-bound","authored":"data-bound","message":true},"x-height":{"paint":"data-lf-height","authored":"data-height","message":true},"x-reading-role":{"paint":"data-lf-reading-role","message":true},"x-views":{"paint":"data-lf-views","message":true}},"$layer":{"generation":"991789b8f0f6b77144359028099ebfa0","fingerprint":"sha256:ee415573f06186504ff7ad7a87d340d9e200c12f7a85d5481c5a1932d9955031","server":"sha256:0cae746bffe5e04c263034a1420487b6ab60559aec172c48154cfc44770f4021","runtime":"sha256:cd6a1c278765db52d8c3eb9b7f5b5728dcea0c74202edfd736c1367115b13fe9","packages":["code-review","diagram","diff","playground","monitoring","visual-review","playwright","gallery","./docs/package"],"producer":{"commit":"b2e4c036c048","committed":"2026-10-09T13:41:42-07:00","dirty":false}}}