press v1.10.0
Changed
- Boundary integrity, first half (the v1.10 milestone's verifier and
CI groups). Public artifacts: source publication is now an
allowlist (git's tracked files, inside a repo) stated once in
publication_members()and consumed by both the packager and the
archive verifier, so an appended member, an untracked private
file, or a flipped byte each fail digest-exact verification
(#12, #23); the pages crawler follows stylesheeturl()assets
and fragment anchors (#10); the reader site proves per-chapter
identity witnesses (a duplicated or missing chapter page fails by
name) and an underivable manuscript witness is a refusal, not a
free pass (#20). CI: pull-request toolchain smokes run with read
permissions and no registry credentials, and main publishes the
exact smoked image object with docker push, never a second build
(#67, #27); the composite action passes its command input as an
environment value matched against a target grammar, so shell
metacharacters are data (#68); the release script validates strict
SemVer, preflights remote state, resumes idempotently after any
failed step, and does not float the major until the immutable
tag's contract is green (#69, #70). Every audit-3 damage exploit
is now a selftest fixture. - Retail artifacts tell the truth (the milestone's second half):
press publishbuilds and verifies the interior, wrap, and EPUB
through the registry before checking anything off, exits non-zero
when a required artifact fails, and separates interior and wrap
failures under their own labels;--report-onlysays "NOT
verified" on every line instead of pretending (#71). The cover
wrap gains its own verifier: one page at the exact
trim-plus-bleed-plus-spine size recomputed from the generator's
own functions, embedded fonts, rendered ink, cover art on the
front panel, surviving title text, and a barcode on a white card
whose quiet zones are judged against the expected EAN symbol span,
never against observed ink (#72).press verify-printverifies
the interior first and degrades gracefully for coverless books.
The agent workflows harden too: whole-book editorial suggestions
normalize file paths against the scout list so a basename or
absolute path reaches the right synthesizer and unresolvable paths
are set aside loudly (#57), and research or audit agents that fail
route their claims to an explicit unresolved list with reconciled
counts, never silently out of the ledger (#58). - Contact and imprint identity: the security contact is
clint@lgtm.systems, the license holder is LGTM Systems, LLC, and
books appear under the LGTM Publishing imprint.
Added
-
Every checked-in format has a linter, locally and in CI:
shellcheck, yamllint, pymarkdown (frontmatter-aware; known-bad
fixtures excluded on purpose), TOML/JSON validity, and
merge-conflict/large-file guards join ruff, mypy, and the selftest
in pre-commit; the CI quality job runs the identical battery via
pre-commit run --all-files. -
docs/TUI-PLAN.md records the press desk design (Textual, screens,
integration laws, first milestone) from the three research passes. -
Full CSS freedom for a book's web surfaces:
assets/web/reader.css
replaces the house reader stylesheet outright and
assets/web/extra.cssappends cascade-winning declarations to both
the reader and the pages landing page. The aesthetic palette applies
to either; a book supplying neither renders byte-identically. -
The press publishes its own documentation site
(https://clintecker.github.io/press/):scripts/build_site.py
renders every repo document through pandoc with the site's own
design (self-hosted Source Serif, Space Grotesk, and Plex Mono;
a two-ink letterpress palette), and the docs-site workflow deploys
it on every push to main. Three phase guards keep site and repo in
step: no page is hand-written; every repo Markdown file must be
published or consciously excluded with a reason (the check caught
SUPPORT, SECURITY, ROADMAP, and AGENTS on its first two runs);
and every page footer stamps the commit it was built from, while
CI builds the site pre-merge so a breakage goes red before deploy.
The link check covers stylesheet url() references as well as page
hrefs.
Changed
- The press repository is public (2026-07-19), and the repository
boundary matrix is proven with real repositories (#37):
press-smokeis the standing boundary fixture, exercised as a
private consumer (minimum permissions plus the toolchain grant),
as a public consumer (anonymous action fetch, zero owner-specific
setup), through a cross-boundary Pages deployment, and through a
witness-gate refusal on a vacuous release tag. Fork-PR posture is
proven mechanically (no pull_request_target, default read token,
per-job least privilege); the live second-party proofs are #87.
Fixed
- Bad input now gets a named refusal, never a traceback or an
injection, closing the audit's failure-honesty tail: a malformed or
emptyconfig/metadata.yamlis refused with the file and line
instead of a parser traceback (#53); the installedpresscommand
passes a failing tool's exit code through cleanly instead of
leaking a CalledProcessError traceback (#54); a malformed
banned-patterns regex namesconfig/house-rules.yamland the
offending pattern (#55); a metadata title with quotes or angle
brackets is escaped into the single-file HTML edition's cover
fragment (#43); and index terms pass through the shared print-safe
sanitizer so a backslash inconfig/index-terms.yamlcan never
reach the TeX engine (#44). The selftest proves every refusal. - The release script's version bump is anchored to the
[project]
version line; v1.9.0's cut rewrote[tool.mypy]'spython_version
to the release number, and mypy silently fell back to checking
against the running interpreter instead of 3.10.