This release includes breaking changes for platform teams planning a safe upgrade.
✓ No known CVEs patched in this version
Topics
+12 more
Summary
AI summaryBroad release touches Build, Public API, Engine internals, and docs/api-stability.md.
Full changelog
v1.6.6 — 2026-05-31
First Maven Central release. GraphCompose now ships under
io.github.demchaav:graph-compose:1.6.6 — note the hyphenated
artifactId, chosen for readability ahead of the Central debut. The
release adds publishable sources/javadoc jars, GPG-signed artefacts,
a binary-compatibility gate against v1.6.5, the metadata Maven
Central requires, and a substantial documentation polish for the
maturity / stability / migration story.
Zero breaking changes from v1.6.5. Existing JitPack callers continue
to resolve through the same coordinates (com.github.DemchaAV:GraphCompose:v1.6.5);
existing API surface compiles and runs unchanged (validated by the new
japicmp gate against the v1.6.5 baseline). New: the @Beta
annotation marker, the @since 1.0.0 class-level Javadoc on
entry-point packages, and a curated docs pass (decision guide for
the two template surfaces, examples maturity index, explicit API
stability policy).
Migration from v1.6.5: no code changes required. Swap the
JitPack <dependency> for the Maven Central form
(io.github.demchaav:graph-compose:1.6.6). The legacy JitPack URL
keeps resolving for callers pinned to v1.6.5 and earlier.
Build
- Binary-compatibility gate against v1.6.5 (
japicmpprofile,
Track E1). The newbinary-compatCI job builds the artifact on every
pull request and diffs it againstcom.github.DemchaAV:GraphCompose:v1.6.5
pulled from JitPack. Binary-incompatible modifications to the public
surface fail the build; source-incompatible changes are reported only
(phased policy, will tighten after the 1.6.6 cut). Run locally with
./mvnw -DskipTests -P japicmp verify -pl .; HTML/MD/XML reports
land intarget/japicmp/. JitPack repository is scoped to the
japicmpprofile, so downstream consumers do not inherit it. - Maven Central publish workflow (Track D4). New
.github/workflows/publish.ymlfires
on the samev*tag push that triggers the existing
release.yml. It re-runsmvnw verifyat the tagged commit, imports
the GPG key (Track D2) into the runner keyring, writes the
<server id="central">credentials block into~/.m2/settings.xml
viaactions/setup-java@v5, then invokes
./mvnw -P release -Dgpg.skip=false deploy— the
central-publishing-maven-plugin(Track D3) uploads to Central and
blocks until Sonatype's validator responds. Hyphenated tags
(-rc,-alpha,-beta,-snapshot) are explicitly skipped — those
ship only to JitPack and the GitHub Release pre-release surface.
Aworkflow_dispatchinput lets the maintainer re-publish an
existing tag without re-cutting it if Central had a transient
validator hiccup. The workflow is dormant until four GitHub repo
secrets are wired:MAVEN_GPG_PRIVATE_KEY,MAVEN_GPG_PASSPHRASE,
CENTRAL_USERNAME,CENTRAL_TOKEN. docs/contributing/release-process.mdupdated with the
end-to-end Maven Central runbook (Track D4 docs). New § 2.C
"One-time Maven Central setup (maintainer)" walks through GPG key
generation, keyserver upload, Sonatype account / namespace
verification, Central user-token generation, the four GitHub
secrets, and the release-candidate dry-run strategy. § 2.B
post-release checklist gains a new step 9 for the Central publish
alongside the existing JitPack step.- Hosted Javadocs via
javadoc.io(Track H3). README's
distribution-status note now points callers at
javadoc.io/doc/io.github.demchaav/graph-compose,
which auto-mirrors any artefact published to Maven Central within
minutes — no separate hosting infrastructure required. The note
also pins Maven Central as the going-forward primary distribution
starting v1.6.6 (JitPack stays available alongside for existing
callers). The full Central install snippet ("Central as primary,
JitPack as fallback") lands in the v1.6.6 release-prep PR after the
first Central publish proves the pipeline end-to-end. central-publishing-maven-pluginin thereleaseprofile
(Track D3). Adds Sonatype'scentral-publishing-maven-plugin0.7.0
to the existingreleaseprofile as a packaging extension. Replaces
the legacynexus-staging-maven-plugin+ manual staging-repository
workflow with a singledeploycall. Configuration:
publishingServerId=central(matches the<server id="central">
entry the publish workflow writes fromCENTRAL_USERNAME/
CENTRAL_TOKENsecrets),autoPublish=false(validation gate before
the artefact goes live — flips totrueonce we're confident
post-D4),waitUntil=validated(the build waits for Sonatype's
validator so any rejection surfaces in the workflow run, not a
silent stuck upload). Requires theio.github.demchaavnamespace to
be verified oncentral.sonatype.com(one-time human step via
GitHub auth or DNS TXT record). The plugin loads inert until D4's
workflow provides the credentials.- GPG signing in the
releaseprofile (Track D2). Adds
maven-gpg-plugin3.2.7 to the existingreleaseprofile, binding
to theverifyphase to sign main / sources / javadoc / pom
artefacts — Maven Central rejects unsigned uploads. Off by
default: a new property<gpg.skip>true</gpg.skip>keeps local
mvn -P release packageruns working without a configured GPG key.
The publish workflow (Track D4) flips it explicitly with
-Dgpg.skip=falseonce theMAVEN_GPG_PRIVATE_KEYand
MAVEN_GPG_PASSPHRASEsecrets are wired.gpgArgumentsdeclares
--pinentry-mode loopbackso non-interactive CI runs accept the
passphrase from-Dgpg.passphrase/MAVEN_GPG_PASSPHRASEwithout
needing a TTY forgpg-agent. releaseMaven profile with sources + javadoc jars (Track D1).
Activated with-P release, attaches*-sources.jarand
*-javadoc.jarto thepackagephase via the standard
maven-source-plugin(3.3.1) andmaven-javadoc-plugin(3.12.0)
configurations Maven Central requires. The Javadoc plugin runs with
doclint=noneandfailOnError=falseso Lombok-generated members
and@Internalengine surface don't block a publish; warnings are
surfaced quietly. Defaultmvnw verifystill does not pay the
~30 s of extra packaging — the profile is off by default and turned
on bycut-release.ps1(once Track D3's central-publishing plugin
lands) and the publish workflow (Track D4).- SCM block canonicalised in
pom.xml(Track D1 polish). The
Central metadata validator is strict about the<scm>block:
<connection>now usesscm:git:https://…(HTTPS, not the legacy
git://transport) and<developerConnection>now uses
scm:git:ssh://[email protected]/…(the canonical SSH URL with the
git@user, not the olderssh://github.com:…form). Matches the
shape every Central artefact's POM carries. - New
benchmarks/README.md(Track B1). Honest framing for the
manual benchmark layer ahead of the Maven Central debut: explicitly
positions the harness as a smoke / diff / endurance tool — not a
JMH-grade benchmark — and tells callers when not to use it
(publishable performance claims, architectural decisions,
cross-library comparisons that read too much into a single number).
Documents the file-by-file role of each runner / report tool, the
exact CI smoke invocation, and a "How to read a report" cheat sheet.
Cross-links the planned JMH chain (Track C, B3 → B6 in 1.7.0) so a
reader knows what's coming and how to identify "rigorous"
measurements when they arrive. - Class-level
@since 1.0.0Javadoc on the public entry-point
surface (Track H1). 26 public types in the canonical user-reached
packages (com.demcha.compose.GraphCompose,com.demcha.compose.document.api.{DocumentSession, DocumentPageSize, PageBackgroundFill},
com.demcha.compose.document.dsl.{DocumentDsl, RichText, Transformable}plus all 19 DSL builders)
now carry class-level@since 1.0.0Javadoc tags so callers can see
the introduction version at IDE quick-doc / generated Javadoc time
without trawling CHANGELOG history. New guard test
PublicApiSinceTagCoverageTestsource-scans the three entry-point
roots and fails the build if a new public top-level type lands
without a class-level@sincetag;internal/sub-packages are
excluded by convention (InternalAnnotationCoverageTestcovers those).
Method-level@sincebackfill for the ~380 public methods in these
packages is intentionally out of scope here and tracked separately. maven-enforcer-plugingate (Track E2). Binds three rules to the
validatephase so the build refuses to start when a precondition is
broken:requireJavaVersion(≥ 17 — the declared baseline, catches
accidental JDK 11 / 15 attempts),requireMavenVersion(≥ 3.8.0 —
the oldest version the planned central-publishing pipeline supports),
andrequirePluginVersions(every plugin must declare an explicit
non-LATEST/ non-RELEASE/ non-SNAPSHOTversion — the
generalisation of the PR-7.1 exec-plugin drift lesson).
Default-lifecycle plugins (clean/install/site/resources/
deploy) are now pinned in a new<pluginManagement>block so
requirePluginVersionshas nothing to flag. Minimums and versions
live in<properties>(enforcer.requireMavenVersion,
enforcer.requireJavaVersion,maven.enforcer.plugin.version).- Parallel-session stress test (Track I2). New
DocumentSessionParallelStressTestdrives 32 independent
DocumentSessioninstances on a fixed-size thread pool through 4
iterations and asserts (a) all parallel renders produce a layout-graph
signature byte-equal to the sequential baseline — exercising the
shared font registry, glyph cache, built-in node definitions, and
shape-outline cache for race conditions; (b) every PDF output starts
with the%PDFmagic, is at least 256 bytes, and has size variance
under 256 bytes across threads (catching corruption or rare
non-determinism without locking exact byte counts that timestamps
could drift). 128 + 128 = 256 renders complete in ~1.6 s locally, so
the test does not bloat CI. The contract is that each
DocumentSessionis single-threaded but the process-wide machinery
handles concurrent independent sessions safely; this test pins that. no-poiMaven profile + CI job (Track I1). Thepoi-ooxml
dependency is declared<optional>true</optional>so callers that
render only PDFs don't pay the ~10 MB POI footprint; this PR adds a
regression gate that proves it. Running./mvnw -P no-poi test -pl .
excludespoi-ooxml(and itspoi/poi-ooxml-litetransitives)
from the surefire test classpath and sets the system property
no.poi=true. DOCX-specific tests (DocxSemanticBackendTestand the
one DOCX export inDocumentSessionTest) now carry
@DisabledIfSystemProperty(named = "no.poi", matches = "true")and
skip cleanly. The rest of the canonical suite (1029 tests, 4 skipped
under-P no-poi) runs green without POI on the classpath. A new
no-poi-suiteCI job exercises the profile on every pull request.
Public API
- New
@Betaannotation (Track H2). Companion to the existing
@Internal
marker:
com.demcha.compose.document.api.Beta
signals an Extension SPI or Experimental surface — a
deliberately-exposed seam library users can implement or call, but
whose shape may still evolve between minor releases per the
API stability policy § 1. First application:
com.demcha.compose.document.layout.NodeDefinition
— the canonical custom-node-type seam, carved out of the otherwise
@Internaldocument.layoutpackage. New
BetaAnnotationDocumentationTestpins the annotation's retention /
target /@Documented-ness / source-Javadoc contract in the same
shapeInternalAnnotationDocumentationTestalready pins for
@Internal. Additional Extension SPI surfaces (render-handler
interfaces, fragment-payload interfaces) will gain the marker
incrementally as their contract solidifies.
Documentation
- New flagship example:
EngineShowcase+ regenerated
assets/readme/repository_showcase_render.pnghero image ahead of
the Maven Central debut. A presentation audit before v1.6.6 flagged
that the existing hero PDF was a dated single-page render and the
GitHub Pages showcase had 20 broken asset paths (CV v2 migration
added-v2suffixes thatdocs/index.htmlnever picked up). Fixed
in three commits: (a)docs/index.htmlpath repair so every CV /
cover-letter preview resolves; (b) new flagship
examples/.../flagships/EngineShowcase.javarenders a single-page
cinematic brand promo — a navy + electric-orange composition with a
rounded clip-frame hero (semantic-graph → polished-PDFs visual
metaphor), a magazine-headline lockup ("Documents as code. /
Cinematic by default."), three KPI cards (Templates v2 · 1,033
tests · v1.6.6 Maven Central), a three-column capability grid
(Semantic DSL · Deterministic Layout · Cinematic Themes), and a
footer brand stripe — exercisingShapeContainerNode+
ClipPolicy.CLIP_PATHfor the hero frame, classpath-loaded image
embedding (examples/src/main/resources/engine-hero.png),
softPanel(...)+accentLeft(...)decorators on V2 sections, and
mixed serif/sans typography; (c) page 1 rasterised to
assets/readme/repository_showcase_render.pngvia the new persistent
helpercom.demcha.examples.support.PdfPageRasterizer(PDFBox-based,
no external Ghostscript / ImageMagick dependency). The hero now
reads as the engine's brand register rather than a Lorem-ipsum
template render. docs/architecture/package-map.mdupdated alongside H2. A new
intro paragraph documents the stability-marker convention (Stable
default; engine packages are package-level@Internal; individual
Extension SPI seams carved out of@Internalpackages carry
@Beta), and thedocument.layoutrow calls outNodeDefinition
as the current@Betaseam.docs/api-stability.mdrevised alongside H2 —@Betaannotation
reference cells in §1 are no longer hedged as "pending"; the
associated quote block lists both annotations side-by-side with the
guard tests that pin them.
Engine internals (no behaviour change)
RowSlotshelper extracted fromLayoutCompilerand
NodeDefinitionSupport. The defence-in-depthIllegalArgumentException
guard added in v1.6.5 (PR-7.3) for the row weights / children size
mismatch lived as duplicated inline code at both engine call sites
with no direct test — a future refactor could have silently deleted
either copy. The validation now lives in
com.demcha.compose.document.layout.RowSlots#validateWeightsMatchChildren
(package-private), withRowSlotsTestdriving it directly. Error
message is unchanged.GraphCompose.DocumentBuilder#pageBackgrounds(...)
Javadoc now spells out the empty-list-clears semantics in prose, not
only in the@paramline.
Documentation
- New decision guide:
docs/templates/which-template-system.md
(Track G1). The repo ships two parallel canonical template surfaces —
cv.presets.*(the "classic" v1.6 rebuild) andcv.v2.presets.*(the
layered architecture, recommended) — under confusingly similar names.
The new page pins the terminology once, gives a status matrix
(Recommended / Supported / Legacy / Internal) for every template
surface and the canonical DSL, walks a decision tree for new code, and
provides a preset-by-preset migration table fromclassicto
layeredplus a 1.x → 2.0 deprecation inventory naming every type
scheduled for removal.CanonicalSurfaceGuardTestallowlist updated
so the deprecation-inventory section's literal mentions of
GraphCompose.pdf(...),PdfComposer, etc. don't trip the
legacy-token scan (same allowlist class as the v1.5 → v1.6 migration
log already in there). examples/README.mdreorganised by maturity (Track G2). The
gallery section was grouped by the GraphCompose release that
introduced each example (Built-in templates / Cinematic v1.5 /
v1.5 feature showcases / v1.6 feature showcases / Public-API
surface / Production patterns / Operational documents) — useful
history for maintainers, less useful for someone landing on the
examples folder for the first time. The gallery now categorises
by maturity / intent: 🚀 Start here, 🧱 Core DSL,
📋 Templates recommended, 🔧 Advanced SPI, 🗄️ Legacy.
All 26 examples retained their anchor IDs, so existing deep links
continue to resolve; only the gallery index is restructured. A
maturity legend introduces the five tiers and links to
docs/templates/which-template-system.mdfor the V1 → V2 path that
the Legacy tier points at.- New API stability policy:
docs/api-stability.md
(Track G3). User-facing companion to
ADR-0003: pins
the four stability tiers (Stable, Extension SPI, Internal,
Experimental) with what each one promises in patch / minor /
major releases, the sealed-hierarchy permit-list policy (additive
variants must degrade gracefully withoutdefault-branch failures),
the deprecation window (≥ 1 minor release with@Deprecated, removed
in next major), a per-package tier-lookup table for the canonical
surface plus the legacy packages headed for 2.0 removal, and an
"anti-policy" section (no pixel-stable PDFs, no bit-stable artefact
bytes, no sealed-permit exhaustiveness across minor releases for
Stable hierarchies).CanonicalSurfaceGuardTestallowlist extended
so the page can namecom.demcha.templates.*/com.demcha.compose.v2.*
and the legacypdf(Path)factory in the package-tier and
deprecation-example sections.
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About GraphCompose 2.0
All releases →Related context
Related tools
Earlier breaking changes
- v2.0.0 Package rename: layered template packages dropped `.v2` suffix; update imports.
- v2.0.0 Removed dormant ECS engine internals (EntityManager, SystemECS, Entity components, render pipeline).
- v2.0.0 Removed linkOptions() accessor; use linkTarget() and ExternalLinkTarget.options().
- v2.0.0 Removed PDF‑typed document‑chrome overloads on DocumentSession; use backend‑neutral metadata/watermark/protect/header/footer.
- v2.0.0 Removed DSL name-aliases DocumentSession.builder() and DocumentDsl.text(); use builder() and paragraph().
Beta — feedback welcome: [email protected]