Skip to content

0.132 → 0.133 — LLMs author documents as JSON; the blueprint is retired; example: and body.example return to the quill schema; normalizing content moves no text

The blueprint is retired: LLMs author documents as JSON

The break no type checker reports: quill.blueprint is gone. In plain JavaScript the getter reads undefined and in Python it raises AttributeError, so a prompt built from it loses its document reference without failing to build. A model now reads the quill's JSON Schema and writes the authoring document: {fields, body, cards: [{kind, fields, body}]}, every rich-text field and body a Markdown string, null meaning absent. fromAuthoring builds and conforms the Document, and toAuthoring shows a model the current one.

// 0.132
const prompt = `Fill in this document:\n${quill.blueprint}`
const doc = quill.parse(reply)

// 0.133
const prompt = `Reply with JSON matching this schema:\n${JSON.stringify(quill.authoringSchema)}`
const doc = quill.fromAuthoring(JSON.parse(reply))
Break Surface Action
QuillConfig::blueprint(), WASM quill.blueprint, Python quill.blueprint and the print_blueprint example are deleted Rust, WASM, Python Read authoring_schema() / authoringSchema / authoring_schema, and import the model's reply with from_authoring / fromAuthoring
quillmark blueprint is deleted CLI quillmark schema --authoring <quill> prints the JSON Schema
quillmark validate renders two canonical documents, the empty and the seeded; the blueprint is not one CLI A script matching the blueprint document in validate output drops the match
build_transform_schema(config) takes a SchemaCodec: SchemaCodec::Content is the plate seam it built before Rust Pass SchemaCodec::Content
A multi-line description:, and an enum member holding >, ; or \|, load: quill::description_multiline and quill::format_literal_reserved_char are deleted Quill.yaml, diagnostics Drop the routes; the rules existed for the blueprint's comment grammar

New, with nothing to migrate: QuillConfig::authoring_schema(), Quill::to_authoring and Quill::from_authoring (WASM authoringSchema, toAuthoring, fromAuthoring; Python authoring_schema, to_authoring, from_authoring), the AuthoringDocument and AuthoringCard TypeScript types, SchemaCodec, MARKDOWN_MEDIA_TYPE, AUTHORING_KIND_KEY, and the authoring::invalid_shape code a malformed import raises.

A root example.md is an ordinary file

The break no type checker reports: a root example.md is no longer the quill's example. quillmark validate neither reads, validates nor renders it, and Quill::example_document() no longer hands it out. A quill's example is now derived from its Quill.yaml: the example: its fields declare and the body.example its kinds declare, committed over the seeded document. A quill that kept its example only in example.md has none until its values move onto its fields; quillmark validate then checks the example as it checked the file. See Moving an example.md into Quill.yaml.

This partly reverses 0.117: a slot declares one default: and at most one example:, and the example answers nothing. schema() exposes it as a typed value, the authoring schema as the field's examples, and the example document commits it.

Break Surface Action
A root example.md is an ordinary file: example_document() does not read it, and quillmark validate warns cli::example_file_ignored while it exists CLI, Rust, WASM, Python Move its values into example: and body.example on the quill, then delete it
Quill::example_document() returns Option<Document>, where it returned Option<Result<Parsed, Vec<Diagnostic>>>; the document carries no warnings Rust Drop the Result handling and read Parsed::document directly
WASM exampleDocument() and Python example_document() no longer throw, and the document's warnings is empty WASM, Python Drop the try / except around the call
EXAMPLE_FILE is deleted from quillmark-core and the quillmark facade Rust Drop the import
quill::example_reference is deleted diagnostics Drop the route: no file is read
cli::example_not_clean no longer names a file, and --verbose prints Example: derived from the quill's examples or Example: none (no slot or body declares an example) CLI A script matching example.md in validate output matches the new lines
schema(), schema.yaml, and WASM and Python quill.schema carry example on a field, after default, and description and example on a card's body schema, WASM, Python Read them, or ignore them
FieldSchema has a public example field, and BodyCardSchema public description and example fields Rust Add example: None to a FieldSchema { .. } literal and description: None, example: None to a BodyCardSchema { .. } literal, or build with FieldSchema::new

New load errors, each on a key that failed to load in 0.132 (quill::field_parse_error, quill::invalid_body), so no quill that loaded stops loading:

Code Raised for
quill::example_type_mismatch, example_not_in_enum, example_format_violation, example_held_stored, example_over_max, example_over_length an example: that would fail as the same default: would
quill::example_on_namespace an example: on a typed dictionary, whose properties hold their own
quill::richtext_example_import a content example: that fails to import, and a body.example that fails to import or drops a construct
quill::invalid_body a body.description or body.example beside enabled: false

Moving an example.md into Quill.yaml

Each value the file gave a field becomes that field's example:, and each body the file gave a kind becomes the kind's body.example:

# 0.132: example.md
~~~
$quill: status_report
project: Harbor Migration
state: at_risk
~~~

The cutover rehearsal slipped a week.

# 0.133: Quill.yaml
main:
  body:
    example: The cutover rehearsal slipped a week.
  fields:
    project: { type: text, example: Harbor Migration }
    state: { type: enum, values: [on_track, at_risk, blocked], example: at_risk }
  • The example document holds one card per kind, as the seeded document does. A file showing two cards of one kind keeps the first.
  • A value nested in a typed dictionary moves onto its property. A typed table's rows can stay whole as the table's example:, or become one row of column examples.
  • A variant-bearing enum's example: is the member alone, and the world's values move onto its cells.
  • A value that cross-referenced another field keeps working where both fields carry the values the file had. Where it cannot, write a realistic, obviously made-up value, as in FIRST M. LAST, Capt, USAF.
  • quillmark validate checks the result as it checked the file: any diagnostic on the derived document fails the quill.

Normalizing content moves no text

A table's slot sharing its line with prose is canonical content. Content::normalize broke the line around it, inserting a \n on each side; it now leaves the text as given, and the markdown write breaks the line instead. A host whose text lives elsewhere, a CRDT that every client's content must equal included, stores its projection as it is: overwrite takes the shape where it threw block island in a line's prose, and nothing the mint does changes text. The table closing this section lists every break.

Content

A content holding a table on a shared line keeps that line. A read after overwrite or reviseContent, a stored row's load, an applyChange delta typing beside a table's slot, an accepted LineOp::Join that runs the slot into the prose above it: each returns the text as written, and mapMarks predicts marks in those coordinates, where 0.132 returned it with a \n either side of the slot and its marks moved past them. Line count and every position after the slot are what the host wrote.

The island lanes still refuse to place a table there: an IslandOp::Insert whose at is not an empty line, and a Set retyping an inline island into a table, fail BlockIslandNotAlone. A Set on a table already sharing its line lands, where it failed the same way.

normalize(content) is new on the WASM surface, beside mapMarks and rebase: the content overwrite stores from content, with no document, throwing where overwrite throws.

Markdown

to_markdown writes a table on a shared line as its own block, the prose on each side a block of its own, so the markdown reads as 0.132's did and re-imports as the broken content. to_markdown_annotated and anchors_where read the same broken lines, so an anchor's line is the prose on its side of the table.

Rendering

The Typst lowering places the table where its slot sits, inside the paragraph's markup, and Typst sets it as a block between the prose either side; on a heading's line the heading closes before the table and reopens after it. The page draws what 0.132 drew for the broken lines.

Stored rows

A row holding the shape loads as stored, where 0.132 loaded it broken, and its bytes hold. A 0.132 build reads every row this build writes, breaking the line as it loads. The storage tag holds.

Every break

Break Surface Action
A table's slot sharing its line rests there, where normalizing broke the line around it content reads, stored rows, overwrite, reviseContent, applyChange and mapMarks, LineOp::Join Read positions as written; export markdown for the broken form
overwrite, reviseContent and serial::from_authored_value take a table sharing its line, where they threw block island in a line's prose WASM overwrite and reviseContent, Rust Stop splitting the line before the write
An IslandOp::Set on a table already sharing its line lands, where it failed BlockIslandNotAlone content ops, WASM applyChange None
A hard break after a line a table's slot ends clears, as it does after a table's own line content reads None: both projections set the table as a block there
normalize is a new WASM export WASM None