Reference

Reference

This chapter is the desk reference: the CLI, every format, every stable report code, every limit, and the design records, collected beside one another. Everything here is taken from the code’s own tables. Where the book and the binary disagree, trust the binary and file the difference as a bug.

The command line

usage: zenfmt [options] INPUT

INPUT is a file path, or - for stdin. Stdin requires --from and either -o PATH or --stdout. The reason is plain: a stream has no extension to detect from and no name to derive the output path from.

FlagValueMeaning
--from, -fFORMATInput format. Default: from the extension, then from content signatures.
--to, -tFORMATOutput format. Default: markdown.
--output, -oPATHOutput file. Default: INPUT with the writer’s extension.
--stdoutWrite the document to stdout instead of a file. No artifact or manifest file is committed.
--metadata-outPATHPersist the manifest produced with --stdout. Only meaningful with --stdout.
--overwriteReplace existing artifact and manifest paths. Without it an existing destination is a refusal (core.destination-exists).
--preserve-facetsSerialize full facet rows into the manifest instead of the default digest-and-count summaries.
--filtersRun the filter pipeline compiled into this binary.
--list-formatsPrint the bundle’s readers and writers with their extensions.
--list-filtersPrint the filters compiled into this binary, in pipeline order.
--strictRefuse declared loss before anything commits. Graded: bare --strict (content), --strict=structure, --strict=exact.
--quietSuppress notes.
--reportsFORMtext (default) or json.
--limitNAME=VALUEOverride one resource limit. Repeatable. The names are in the limits table below.
--help, -hShow the generated help.
--version, -VShow the version.

Exit codes

CodeClassMeaning
0successThe artifact committed, and on path output the manifest with it. Notes and warnings may still be present. Read the reports.
1conversionThe input could not be converted: malformed content, an invalid tree, an I/O failure, or a graded --strict refusal of declared loss.
2usageThe invocation is wrong: an unknown format, an undetectable input, a flag mistake. Fixable at the command line.
3limitA resource limit refused the input: archive bombs, depth bombs, oversized inputs, refused encryption. The security refusals have no override.

The formats

19 readers, one writer. Every reader’s plugin id is ai.insan.zenfmt.<format>. Detection weighs both kinds of evidence: for in-memory input the content signature always runs, and when it contradicts the extension, content wins with a core.extension-mismatch note. File inputs whose extension routes are read directly. --from overrides everything.

FormatExtensionsContent signatureFacetsRecord
docx.docx .docmZIP central directory names word/document.xmlstyle, revision, layout, media0003
doc.docCFB magic + WordDocument streamstyle, provenance0012
odt.odtZIP + OpenDocument text mimetypestyle, revision, media0006
rtf.rtfLeading {\rtfstyle0004
xlsx.xlsx .xlsmZIP names xl/workbook.xmlgrid0005
xlsb.xlsbZIP names xl/workbook.bingrid0012
xls.xlsCFB magic + Workbook or Book streamgrid0012
ods.odsZIP + OpenDocument spreadsheet mimetypegrid0008
csv.csv .tsvextension onlynone0002
pptx.pptx .pptm .ppsx .ppsmZIP names ppt/presentation.xmllayout, media0007
ppt.ppt .pps .potCFB magic + PowerPoint Document streamprovenance0012
odp.odpZIP + OpenDocument presentation mimetypelayout0009
epub.epubZIP + application/epub+zip mimetypeprovenance0010
pdf.pdfLeading %PDFlayout, provenance, media0011
html.html .htmextension onlyextension nodes0002
markdown.md .markdownextension onlynone0002
asciidoc.adoc .asciidocextension onlynone0002
rst.rstextension onlynone0002
text.txt .textextension only. The fallback is never silent: an undetectable input is a usage refusal.none0002

Word processing. DOCX maps styles to headings through basedOn chains, synthesizes lists from numbering properties, folds merged table cells, and carries footnotes. Comments and text boxes are counted omissions; tracked insertions and deletions additionally ride as revision facets, and style names, page size, and image bytes are carried too. Legacy DOC resolves Heading 1 through 9 from the binary stylesheet and extracts hyperlink fields; other named styles survive as style facets. ODT resolves automatic styles, images, sections, and inline footnotes. RTF covers tables, lists, fields, footnotes, and outline headings.

Spreadsheets. All five spreadsheet readers project one sheet to one h2 plus one table, first row as header, with typed cells. Dates render ISO. Percentages multiply out. Formulas keep their cached values, and a note says so.

Presentations. A slide projects to a title heading plus body content: lists, tables, links, images. Speaker notes land in a container classed notes. Every presentation conversion carries its projection warning. Charts and animation do not survive, and the reader says so rather than pretending; shape geometry, though, now rides in layout facets in EMU.

Publishing. EPUB walks container, then package, then spine, and parses chapters with the HTML machinery. DRM is refused outright. PDF is native Zig text extraction: xref and object streams, FlateDecode, ToUnicode CMaps, width metrics, heading tiers from font sizes. It carries a layout-projection note on every conversion, because a PDF has pages, not structure.

Report codes

Every diagnostic carries a stable code, asserted by at least one test. The catalog below groups the codes by namespace. Severity is the worst the code is issued at. Class is the exit class when the code is fatal; “none” marks notes and warnings, which fail a conversion only under --strict.

Engine (core.*)

CodeSeverityClassMeaning
core.out-of-memoryerrorconversionThe reserved allocation-failure report. Always available, never allocated.
core.destination-existserrorconversionThe output exists and --overwrite was not given.
core.file-operation-failederrorconversionAn open, write, flush, or rename failed. The report names the operation and path.
core.host-io-unavailableerrorusageA file path was given to a build with no filesystem access compiled in, such as the browser module. Convert the bytes instead, or use the CLI or Python library.
core.writer-output-failederrorconversionA writer or direct output sink stopped during emission. The result says whether a streamed prefix had already been delivered.
core.input-too-largeerrorlimitThe input exceeds max_input_bytes.
core.output-too-largeerrorlimitWriter emission reached max_output_bytes before finishing, in any output mode. Nothing was published.
core.invalid-limit-configurationerrorlimitA library caller supplied a zero limit or exceeded a fixed hard cap.
core.invalid-document-treeerrorconversionA plugin or filter produced a tree the validator rejects.
core.nested-table-flattenedwarningnoneThe flatten-nested-tables filter replaced an inner table.
core.stale-or-invalid-manifestwarningnoneAn adjacent input manifest failed digest or schema checks and was ignored.
core.strict-refusederrorconversionThe graded --strict predicate refused the priced loss. Nothing was committed.
core.strict-unavailableerrorconversionThe selected writer has no total capability declaration, so strictness cannot be proved before emission.
core.construct-refusederrorconversionThe document contains a construct the selected writer refuses to degrade in any mode.
core.invalid-lowering-planerrorconversionA writer plugin failed to provide a bounded, complete lowering plan.
core.manifest-encoding-failederrorconversionGenerated metadata or preservation data violated the canonical JSON contract; path output remains unpublished.
core.invalid-preservation-dataerrorconversionA reader’s preservation JSON was malformed, oversized, or used a schema version different from its descriptor.
core.lowering-limiterrorlimitThe bounded lowering planner reached its alternatives, work, or depth limit before opening output.
core.reports-truncatednotenoneThe report-group budget was reached and additional distinct groups were counted but omitted.
core.extension-mismatchnotenoneThe file extension and the content signature disagreed; content evidence routed the file.
cli.usageerrorusageThe command line itself was invalid; the report highlights the offending argument.
core.undetectable-input-formaterrorusageNo extension match and no content signature. The report lists every known format.
core.unknown-input-formaterrorusage--from or --to named a format this bundle does not carry. The report suggests the nearest name.

Markdown writer (markdown.*)

The writer’s codes are loss notes. Markdown cannot represent the construct, the writer degraded it deliberately, and the manifest says so.

CodeSeverityMeaning
markdown.style-droppednoteUnderline, small caps, and similar styling have no Markdown syntax. The text is kept plain.
markdown.extension-fallbacknoteA namespaced plugin extension the writer does not understand rendered as its source-neutral fallback content.
markdown.container-attributes-droppednoteA container’s id, classes, or attributes have no plain-Markdown form.
markdown.cell-span-degradednoteGFM tables cannot span. Merged cells flatten into their first cell.
markdown.table-cell-flattenednoteBlock content inside a cell became one line.
markdown.table-caption-degradednoteA table caption became one flow line after the table because GFM has no caption association.
markdown.nested-table-droppedwarningA table inside a table cell cannot be written. Its text content was kept.
markdown.definition-list-degradednoteDefinition lists render as emphasized terms plus indented paragraphs.
markdown.list-number-style-degradednoteAlpha and roman list numbering becomes decimal.
markdown.citation-droppednoteCitations render as their text. Keys are not preserved in Markdown.
markdown.raw-droppednoteA raw block for another format was omitted.
markdown.invalid-utf8errorThe tree contained invalid UTF-8. That is an engine invariant violation surfaced at the writer.

Office Open XML (docx.*, xlsx.*, pptx.*)

CodeSeverityClassMeaning
docx.not-an-archiveerrorconversionNot a ZIP container.
docx.hostile-archiveerrorlimitPath traversal names or other hostile central-directory content. No override exists.
docx.archive-limiterrorlimitAn entry count, size, ratio, or name-length limit tripped: the zip-bomb family.
docx.encryptederrorconversionOOXML encryption. zenfmt never attempts decryption.
docx.unsupported-compressionerrorconversionAn entry uses a method other than stored or deflate.
docx.doctype-refusederrorlimitA DOCTYPE in a part. The XML parser refuses DTDs outright.
docx.xml-too-deeperrorlimitElement nesting beyond max_xml_depth.
docx.malformed-xmlerrorconversionA part fails to parse.
docx.missing-document-parterrorconversionThe package relationships name no main document.
docx.unhandled-constructwarningnoneRecognized WordprocessingML handled by nobody. Named in the report.
docx.media-limitnotenoneImage extraction stopped at the resource limits; later images keep their in-archive references.
docx.merged-cells-degradednotenonegridSpan and vMerge folded for the Markdown table.
docx.comment-droppedwarningnoneComments are review apparatus, not content.
xlsx.not-an-archiveerrorconversionNot a ZIP container.
xlsx.missing-workbookerrorconversionNo readable xl/workbook.xml.
xlsx.formula-without-cached-valuenotenoneFormulas are not evaluated. Cells without cached values are empty.
pptx.not-an-archiveerrorconversionNot a ZIP container.
pptx.missing-presentationerrorconversionNo readable ppt/presentation.xml.
pptx.presentation-projectionwarningnoneThe standing loss statement: geometry, charts, and animation are absent.
pptx.merged-cellsnotenoneTable span folding, as in DOCX.
pptx.media-limitnotenoneEmbedded picture extraction stopped at the resource limits; the rest keep path references.

OpenDocument (odt.*, ods.*, odp.*)

CodeSeverityClassMeaning
odt.not-an-archiveerrorconversionNot a ZIP container.
odt.missing-contenterrorconversionNo content.xml.
odt.malformed-xmlerrorconversioncontent.xml fails to parse.
odt.annotations-droppedwarningnoneReview annotations are not content.
odt.media-limitnotenoneImage extraction stopped at the resource limits; later images keep their in-archive references.
odt.frame-droppedwarningnoneA frame with neither image source nor text.
ods.not-an-archiveerrorconversionAs above, for spreadsheets.
ods.missing-contenterrorconversionNo content.xml.
ods.malformed-xmlerrorconversionParse failure.
ods.annotations-droppedwarningnoneCell annotations omitted.
ods.formula-without-cached-valuenotenoneFormulas keep cached values only.
odp.not-an-archiveerrorconversionAs above, for presentations.
odp.missing-contenterrorconversionNo content.xml.
odp.malformed-xmlerrorconversionParse failure.
odp.annotations-droppedwarningnoneAnnotations omitted.
odp.presentation-projectionwarningnoneThe projection statement, as in PPTX.

Legacy binary Office (doc.*, xls.*, ppt.*, xlsb.*)

CodeSeverityClassMeaning
doc.not-a-compound-fileerrorconversionNot a CFB container.
doc.missing-word-streamerrorconversionNo WordDocument stream.
doc.encryption-refusederrorconversionfEncrypted is set in the FIB. Never decrypted.
doc.styles-omittednotenoneThe document carries no readable stylesheet, so headings could not be resolved.
doc.tables-flattenednotenoneBinary table structure degrades to paragraphs.
doc.page-breaks-droppednotenonePage breaks have no Markdown meaning.
doc.embedded-objects-droppednotenoneOLE objects omitted.
xls.not-a-compound-fileerrorconversionNot a CFB container.
xls.missing-workbookerrorconversionNo Workbook stream.
xls.encryption-refusederrorconversionA FILEPASS record. Never decrypted.
xls.unsupported-bifferrorconversionPre-BIFF8 workbooks are refused, not misread.
xls.formula-without-cached-valuenotenoneCached values only, as in XLSX.
ppt.not-a-compound-fileerrorconversionNot a CFB container.
ppt.missing-document-streamerrorconversionNo PowerPoint
Document
stream.
ppt.encryption-refusederrorconversionA crypt-session container, detected before any output.
ppt.presentation-projectionwarningnoneThe projection statement.
xlsb.not-an-archiveerrorconversionNot a ZIP container.
xlsb.missing-workbookerrorconversionNo xl/workbook.bin.
xlsb.sheets-unreadableerrorconversionThe workbook lists sheets but none loaded. An empty result is never silent.
xlsb.sheet-skippedwarningnoneSome sheets loaded and some did not. The count is in the report.

Publishing (epub.*, pdf.*, html.*)

CodeSeverityClassMeaning
epub.drm-refusederrorlimitMETA-INF/encryption.xml is present. Refused with no override.
epub.missing-containererrorlimitNo META-INF/container.xml.
epub.missing-packageerrorconversionNo OPF package, or no chapter loaded.
epub.malformed-packageerrorconversionThe OPF fails to parse.
epub.bad-archiveerrorlimitThe ZIP layer refused the container.
epub.archive-limiterrorlimitA ZIP limit tripped.
epub.missing-chapterwarningnoneA spine item’s file is absent. Counted.
epub.skipped-spine-itemnotenoneA non-XHTML spine item (cover image, stylesheet) was skipped. Counted.
pdf.not-pdferrorconversionNo %PDF- header.
pdf.malformederrorconversionUnrecoverable file structure: xref, trailer, or object syntax.
pdf.encryption-refusederrorconversionAn /Encrypt dictionary. Even empty-password encryption is refused.
pdf.limiterrorlimitAn object-count, size, or indirection bound tripped.
pdf.unsupported-filterwarningnoneA stream filter zenfmt does not decode (CCITT, JBIG2, and others), named in the report.
pdf.unmappable-textwarningnoneA font without a usable Unicode mapping. Counted per font.
pdf.layout-projectionnotenoneThe standing statement that page layout became linear text with heuristic structure.
pdf.media-limitwarningnoneImage extraction stopped at the media limits; the remainder is omitted.
pdf.images-omittednotenoneImages that could not be extracted as-is.
pdf.links-omittednotenoneLink annotations not carried.
pdf.no-textwarningnoneNo extractable text. Likely a scanned document; the report suggests OCR.
html.invalid-utf8errorconversionThe input is not UTF-8.
html.too-deeperrorlimitElement nesting beyond max_depth.
html.skipped-embedded-contentwarningnoneAn inline SVG graphic or a framed document was not converted. Script, style, template, and metadata elements are not reported: they are not document content.

Lightweight markup (text.*, csv.*, rtf.*, asciidoc.*, rst.*)

CodeSeverityClassMeaning
text.invalid-utf8errorconversionPlain text must be UTF-8. zenfmt does not guess encodings.
csv.invalid-utf8errorconversionAs above.
csv.unterminated-quoteerrorconversionA quoted field never closes. The position is in the report.
csv.ragged-rownotenoneRows of differing width were padded to the widest.
rtf.not-rtferrorconversionNo {\rtf group.
rtf.groups-too-deeperrorlimitGroup nesting beyond the reader’s bound.
rtf.unknown-control-wordsnotenoneControl words zenfmt does not know, counted and sampled.
rtf.images-droppedwarningnone\pict data was not extracted.
rtf.objects-droppedwarningnoneOLE objects omitted.
rtf.nested-table-flattenednotenoneNested tables flatten into the outer cell.
asciidoc.invalid-utf8errorconversionNot UTF-8.
asciidoc.include-refusedwarningnoneinclude:: never reads other files. The directive is dropped and named.
rst.invalid-utf8errorconversionNot UTF-8.
rst.include-refusedwarningnoneAs above, for reStructuredText.

Server (server.*)

The zenfmt server (ZDS 0016) reuses the engine’s report shape for every server-origin failure: same fields, same JSON, the server. prefix. The HTTP status travels beside the envelope; the exit class mirrors the engine’s mapping.

CodeSeverityExit classMeaning
server.head-too-largeerrorusageThe request head exceeded the connection’s fixed 16 KiB buffer. HTTP 431.
server.body-too-largeerrorlimitThe request body exceeds --max-body; refused at the declared length when possible, at the cap otherwise. HTTP 413.
server.unsupported-mediaerrorusageA content type or multipart shape the route does not accept. HTTP 415.
server.missing-inputerrorusageAn empty body where a document was required. HTTP 400.
server.invalid-queryerrorusageA query parameter carries a value the route does not recognize. HTTP 400.
server.invalid-requesterrorusageA JSON body is malformed or contains a value the route does not accept. HTTP 400.
server.unknown-routeerrorusageNo route matches the path; the admin plane in open mode answers identically. HTTP 404.
server.method-not-allowederrorusageThe path exists under another method; Allow enumerates them. HTTP 405.
server.unauthorizederrorusageNo usable principal on an authenticated route. HTTP 401.
server.invalid-credentialserrorusageLogin failed; identical timing and body whether the account exists or not. HTTP 401.
server.forbiddenerrorusageThe principal’s role is below the route’s requirement, or an ownership rule was violated. HTTP 403.
server.password-change-requirederrorusageThe account carries a one-time password; only the password-change route is permitted. HTTP 403.
server.last-administratorerrorusageRefused deletion, demotion, or disabling of the final administrator. HTTP 409.
server.rate-limitederrorlimitThe caller’s rate bucket is exhausted; Retry-After is set. HTTP 429.
server.busyerrorconversionConnection slots or the conversion cap are exhausted; Retry-After is set. HTTP 503.
server.limit-override-forbiddenerrorusage?limit= from a principal below administrator. HTTP 403.
server.store-unavailableerrorconversionA store read or write failed or timed out; the log carries the detail, the envelope does not. HTTP 503.
server.shutting-downerrorconversionThe request arrived after the drain began. HTTP 503.
server.out-of-memoryerrorconversionThe reserved static report, mirroring core.out-of-memory: preallocated, allocation-free to emit. HTTP 500.
server.open-network-bindwarningnoneStartup warning, not an HTTP response: open mode bound a non-loopback address.

Limits

Every bound has a name, a default, and a --limit NAME=VALUE override. Depth overrides above the hard cap of 4096 are refused. The cap sizes the walker stacks, and no input is worth an unbounded stack.

NameDefaultBounds
max_input_bytes512 MiBBytes read from one input document.
max_depth256Nesting of either node tree, and so every explicit walker stack.
max_archive_entries4096Entries admitted from one ZIP central directory.
max_entry_uncompressed256 MiBExpanded size of one archive entry.
max_total_uncompressed1 GiBExpanded size across all read entries.
max_compression_ratio200Expansion ratio, checked during streaming decompression.
max_entry_name_bytes1024Archive entry name length.
max_xml_depth256XML element nesting.
max_scan_chunk_bytes1 MiBScanner scratch per chunk.
max_manifest_bytes16 MiBSize of an adjacent manifest accepted on input.
max_plugin_data_bytes4 MiBOne plugin-data namespace value.
max_manifest_depth64JSON nesting in an accepted manifest.
max_report_samples4Locations an aggregated report lists before counting the rest.
max_reports_total16 KiDistinct aggregated report groups.
max_resources256Resources a reader may extract from one document.
max_resource_bytes128 MiBTotal extracted resource bytes per document.
max_nodes16 MiKernel nodes, blocks plus inlines, per document.
max_facet_rows1 MiFacet rows across all facet tables.
max_decoded_text_bytes256 MiBDecoded text pool bytes, distinct from max_input_bytes.
max_lowering_alternatives8Lowering alternatives a writer may declare per construct.
max_lowering_work64 MiLowering rule applications per conversion.
max_output_bytes512 MiBArtifact bytes a writer may emit, checked at the shared sink in every output mode (ZDS 0014).

Environment

Building and testing zenfmt needs exactly Zig 0.16.0. Building the design records and this book additionally needs Typst 0.15 or later. The benchmark optionally uses pandoc and Node.js (for anydoc). Both are competitors, not dependencies.

zig build                 # the CLI into zig-out/bin/
zig build test            # the full suite
zig build fmt-check       # formatting
zig build docs            # ZDS records, index, and site
zig build benchmark       # the conversion benchmark (see its chapter)

The design records

The Zen Discussion records under docs/zds/ carry the decisions this book describes. Each format record states its mapping table, its deliberate omissions with their report codes, and its round-trip expectations. That is the review-time half of the honesty contract. The report system is the runtime half.

RecordTitle and scope
0001The Zen Discussion Process: the lifecycle, numbering, and registry these records live in.
0002zenfmt: Architecture and Implementation. The AST, the engine, filters, bundles, the manifest, diagnostics, the coding standard, and the delivery plan.
0003The DOCX Reader.
0004The RTF Reader.
0005The XLSX Reader.
0006The ODT Reader.
0007The PPTX Reader.
0008The ODS Reader.
0009The ODP Reader.
0010The EPUB Reader.
0011The PDF Reader.
0012The Legacy Binary Office Readers: DOC, XLS, PPT, and XLSB, plus the CFB container.
0013Layered Document IR and Writer Lowering: the IR v2 kernel schema, entities and sparse facets, extension nodes, the resource store, the lowering planner with graded strict, and the core contract repairs. Committed: the system this book describes.
The most consulted page of a reference is the one that admits what the system does not do.
the omissions tables, in every format record