press v2.0.0
The composable press. A new design major: trim, binding, cover material, and
print vendor are configurable; typography and web design are profile-driven;
chapters may open with a drop cap; and books extend the press by declaration.
A @v1 book is unaffected and keeps rendering byte-for-byte; a book opts into
v2 by repinning (press migrate), and until it selects a non-house profile,
even a @v2 build is unchanged.
Fixed
- The cover wrap is now print-safe (#189). The wrap embedded the raw
assets/cover.jpgand imprint logo, so a transparent logo (a soft mask) or
an over-resolution source reached the cover and tripped a print-on-demand
preflight (Lulu, KDP), even though the interior had been cleared. The
generator now embeds flattened, resolution-capped copies via
print_safe.prepare_cover: the logo is composited onto the exact field
colour it lies on (so it stays invisible against the field, with no soft
mask), and both cover art and logo are capped from the wrap geometry, since
the logo prints small on the cover (a 1000px logo at 1.1in is 909 PPI, over
the limit) where the same file clears the interior's roomier placement.
verify_coverwrapnow refuses a wrap that carries transparency or an image
over 600 PPI, so a regression cannot ship a cover a printer would reject.
Verified end to end on a real 46-page 6×9 wrap: the logo drops from 1024²
RGBA at 909 PPI to an opaque 649² at 590 PPI, with zero soft masks.
Added (v2)
- Semantic chapter-opening drop caps (#192). A design may open each
chapter with a dropped or raised initial, and the manuscript stays ordinary
prose: no\lettrine, no CSS floats, no font commands. The decision is made
at the document-tree layer by a pandoc Lua filter that finds the first
eligible paragraph after each chapter heading (skipping an epigraph or other
non-prose opener) and splits its opening word into a Unicode grapheme
initial (a base letter with its combining marks, never a stranded accent),
the leading punctuation kept with it, and the remainder of the first word.
For the PDF it emits a single centralized\PressDropCapmacro (built on
lettrine, with aneedspaceguard so a chapter opening is never stranded
at the foot of a page); for HTML and EPUB it emits semantic
chapter-opening/drop-capspans a floated stylesheet renders, with a
clearfix so a short opening paragraph never overlaps the initial. Enabled
through the profile (design default) or a book's ownchapter-opening
override (style,lines,small-caps-remainder); off by default, so a
book that does not opt in renders byte-for-byte unchanged (proven by the
house visual baseline showing zero drift with the filter installed). The
literary-novella gallery example opts in to show it. Guaranteed by
INV-dropcap-opening, proven at the grapheme level intest_dropcapsand
at the emission level by running the filter through pandoc. - A gallery of very different example books (#190), proving nothing is
hardcoded. Five complete books underexamples/— a naturalist field guide,
a poetry chapbook, an academic monograph, a literary novella, and a seasonal
cookbook — each produced by the same pipeline with only its own config
differing: two trims (house 6×9 and novella 5×8), five aesthetics, footnotes,
a subject index, a custom web stylesheet, four kinds of front matter, three
kinds of appended matter, and a per-book jargon allowance. Every example is
proven a valid press book on each test run (the config passes the typed
model, the design surfaces genuinely vary, and each passespress check),
and the docs site gains a gallery page cross-linked from the parts-of-a-book
and configuration guides. - Registrations automation: ONIX 3.0, PCN prep, and ISBN conversions
(#191).press onixgenerates the ONIX 3.0 metadata record distributors
ingest (dist/<slug>.onix.xml) from config: a product per sellable edition
(the print ISBN as a physical product whose form follows the binding, the
EPUB ISBN as anEAproduct), the ISBN asProductIDType15, title,
contributors, publisher, and a year-only publishing date — degrading
honestly where the press holds nothing (no<Price>, because a book
repository holds no price by design).press pcnassembles the Library of
Congress PrePub Book Link field values (dist/<slug>-pcn.txt) for the LCCN
application, flagging any gap the form needs. Newregistrationshelpers
round out the arithmetic: ISBN-10↔13 conversion and the ISBN-10 / ISSN
mod-11 check digits. There is no API that issues an identifier or accepts a
feed without human onboarding; the automation is the generate/validate/
format side, and the manual gates are documented honestly. - Typography and web design are now profile-driven (#172): a design
profile carries not just trim and margins but the structural type treatment
(paragraph indent, leading) and the web reading measure (max width, base
size, line height). The house profile projects exactly the v1 values, so a
house book renders byte-for-byte unchanged — proven against the committed
visual baseline with zero drift — whilenovella-5x8becomes a genuinely
different qualified design (its own type treatment and measure, not just a
resized house). The split is deliberate: the profile seals the structural
typography that defines a design, and the aesthetic keeps owning identity
(font family, palette), overriding the profile. Each profile has a stable
digestover its design-affecting data, so a sealed value cannot change
without the key that scopes its visual baseline moving; a new
INV-profile-geometryproves every profile renders at its declared trim. - The v1→v2 migration and rollback contract (#174):
press migrate
moves a book to the next press major by repinning it — the press major in
requirements.txtand the CI workflow — and nothing else. The
manuscript, config, and accepted art come out byte-for-byte identical; a
dry run (press migrate plan) reports every change and design consequence
before any mutation;applywrites an exact backup first;rollback
restores the pre-migration bytes exactly. Because the house profile
reproduces the sealed v1 geometry, a v1 book that repins to v2 and keeps
the house profile renders unchanged — the design moves only when the
author selects a non-house profile. Custom overrides the profile does not
govern (tex/title-page.tex,assets/web/*.css,config/aesthetic.yaml)
are named by the plan, never silently carried. Guaranteed by
INV-migration-safeandINV-migration-preview, proven by
check_migration's scaffolded-book round-trip, and documented in
docs/MIGRATION.md. - The extension contract (#171): the decision record and executable gate
for what a book or third party may add to the press. Everything extensible —
a design profile, provider spec, artifact, skill, or workflow — is a named
data file selected by id, never an imported plugin, so behavior cannot come
from import or entry-point order. An extension carries a manifest declaring
the names it claims, the contract major it targets, the invariants it takes
on and their proofs, and its capabilities;press'sconformancegate
refuses a manifest that collides with a core name, targets an unsupported
contract major, is malformed, names an unknown dependency, claims a sealed
capability, or leaves an invariant unproven — before anything is built. The
mandatory verification, path containment, artifact graph, config validation,
and release gate stay sealed. Modelled byINV-extension-conformanceand
INV-extension-seal, proven bycheck_extension_conformanceover a
reference and five hostile fixtures, and documented in
docs/EXTENSION-CONTRACT.md.
Changed (v2 — breaking, configurable print formats)
- Trim, binding, cover material, and print vendor are now configurable, a v2
(design-major) change: a book pins@v2to opt in, and a@v1book stays
a 6×9 paperback, byte-for-byte. Design is modelled as versioned print
profiles (print.profile) carrying trim and interior geometry; the house
6×9 profile reproduces the v1 output exactly.print.binding
(perfect-bound, saddle-stitch, coil, casewrap, dust-jacket),print.material
(paperback, casewrap, linen), andprint.providerselect the rest. Trim is
derived from the profile, not hand-entered; theINV-config-triminvariant
is rewritten around it. - Provider manufacturing specs for Lulu, KDP, and IngramSpark (from
sourced, attributed research): the spine caliper, cover bleed, safety, and
hardcover wrap geometry are vendor-specific and no longer hardcoded. The
spine model branches on binding (a paperback formula vs a hardcover lookup
or caliper), and the cover generator composes per-binding geometry that
matches IngramSpark's published casewrap and jacket formulas. Unsupported
combinations (a dust jacket at KDP, an uncut trim, a page count out of
range) are refused before rendering. - A user guide,
trim & binding,
and the internal design recorddocs/PRINT-PROFILES-PLAN.md.