Install a GraphCompose harness into your coding agent. Drop in a document reference. Ask Codex or Claude Code to recreate it. The agent generates, renders, compares and iterates until the template is ready for your approval.
Create a GraphCompose CV template from resume.png
The output is not a drawing that happens to match one screenshot. It is a maintainable Java template built from semantic GraphCompose primitives — sections, rows, weights, anchors — with the content in a JSON data file, the assets resolved and recorded, and every revision kept.
/plugin marketplace add DemchaAV/graphcompose-ai-flow
/plugin install graphcompose-flow@graphcompose
Then, once: npm run setup — two of the tools are TypeScript compiled
into dist/, which is not committed, so a fresh install has no build
output. Until setup has run, those two exit with code 69 and say so.
Full instructions and troubleshooting:
docs/plugin-installation.md.
git clone https://github.com/DemchaAV/graphcompose-ai-flow
cd graphcompose-ai-flow
npm run setup
node adapters/codex/install.mjsThat copies the runtime to ~/.codex/graphcompose-flow/<version>/ and
installs four skills pointing into it, so the clone is not needed
afterwards — move it, rename it or delete it and the skills keep
working. See adapters/codex/README.md.
You need Node 20+, Java 21+, Maven and ImageMagick, plus a Java project that pins GraphCompose — the version in your build file decides which skill pack the agent authors against.
Every render rewrites current.pdf next to the project's
template-project.json, so one open window follows the whole run — you
watch the layout arrive instead of hunting for the newest file under
revisions/. current-debug.pdf beside it is the same page with layout
guides drawn on.
That only works in a viewer which reloads a file when it changes and does not hold it open. A viewer that keeps a lock on the PDF makes the next render fail, which reads as a harness bug and is not one. On Windows the one to use is SumatraPDF — free, open source, reloads on change, and lets go of the file. On macOS and Linux, Preview and Evince both reload in place.
Open it once, at the start, and leave it there.
Open your Java project in the agent, give it the reference, and say what you want. The skills fire from the words, so no command is needed:
| You say | What happens |
|---|---|
| "An invoice like the one we did before" | the catalog of published templates is checked first — a match is a file copy into your project, not the loop |
| "Create this in GraphCompose" (+ a screenshot) | analyse → architecture → assets → code → compile → render → diff → fix the largest mismatch → repeat |
| "Make the sidebar wider" | a new revision under the narrowest scope that fits, gated against the right baseline |
| "What's still different?" | a measured verdict and a ranked mismatch list, without changing anything |
| "approve" | DRAFT → APPROVED, the previous approved superseded, the bundle published |
Reuse is checked before reconstruction because the two cost different
orders of magnitude. node scripts/templates.mjs lists what has already
been published and inspect <id> says how to use it;
node scripts/use-template.mjs <id> --target <java-project> copies the
sources, assets and data in, or --new-project <dir> stands up a
runnable project from scratch. A published bundle carries no dependency
on this harness — it is Java, a JSON data file and a pom.
See docs/demo.md for a real transcript of the
deterministic half — version resolution, workspace creation, the chain,
the loop gate.
Two runs against the current harness. The middle column is what one request produced — the reference, the sentence "create this", and no further input. The right column is after the corrections.
That split is the thing worth judging. A first render is never right; the question is how close one request gets, and what it costs to close the rest.
Two runs on 2.2.0, recorded revision by revision. The left panel is the reference; the right is what the harness rendered; the rail underneath is every revision it took to get there. Nothing in either frame is regenerated imagery — each step is the render that revision actually produced.
Invoice — 12 revisions, 113 minutes. The first two did not compile,
which is the point of recording them: revision-001 and revision-002
are FAILED and still on disk, with what broke and what was tried. The
last two were plain sentences with no instructions attached — "пропали
разделители почему то" (the dividers disappeared), then a note that the
SVG logo aligned left where the PNG did not. Approved at revision-012.
CV — 10 revisions, 120 minutes, from a screenshot and the sentence
"Create this screenshot as a GraphCompose template." The corrections in
the second half are the ones worth reading: initials that must derive
from the name rather than be hardcoded, a LinkedIn href that has to apply
to the icon as well as the text, a timeline rail that should not run
above its first marker. Approved at revision-010.
Both were published as standalone bundles — template, typed spec, data JSON, assets, previews — which is what the harness exists to produce. The document is Java you can read and change; the content is a JSON file next to it.
| Reference | One request | After 2 corrections |
|---|---|---|
![]() |
![]() |
![]() |
Five revisions on its own, then it stopped and asked. The corrections were about the timeline: the rail overran its markers, and a job title drifted off centre. Three more revisions closed both. 8 revisions, 77 minutes end to end.
The interesting part is what the loop did unprompted. Twice it could not tell a layout fault from a painting fault, so it wrote a probe — a throwaway document that renders one arrangement and measures the pixels — and settled it. That is how it found that a shape container paints its bottom margin above its box, and that an over-tall child is clamped to the top rather than centred. Both are now recorded observations with probes that re-confirm them, so the next run does not pay for them again.
| Reference | One request | After 3 corrections |
|---|---|---|
![]() |
![]() |
![]() |
Eight revisions on its own — the reference is denser: a display serif against a sans body, proportional skill bars, five icon-badged certification cards, three achievement rows. Then three corrections, each a plain sentence about what looked wrong, none of them explaining how to fix it:
вот только sertification и achivment разделитель вертикальный
The measured cost of that run, from the harness's own telemetry:
create from the reference 68 min · 280.4k output · 61.0M cache read · 211 requests
first correction 7 min · 25.2k output · 16.0M cache read · 32 requests
second correction 10 min · 36.4k output · 21.8M cache read · 39 requests
approve and publish 2 min · 8.1k output · 6.5M cache read · 11 requests
A correction costs roughly a tenth of the original run. That ratio is the one to watch, and it is why the harness measures itself rather than guessing — see telemetry and the benchmark protocol.
Neither run was pixel-perfect from one request, and the pixel-similarity figure stayed unimpressive throughout both: the references are rasterised in typefaces no bundled family reproduces, so glyph edges dominate the comparison. What the runs show is that one request gets close enough to correct in sentences, and that correcting it is cheap. Judge the images.
The host agent supplies the model, the reasoning and the shell. This project supplies the workflow, the GraphCompose knowledge and the gates. Anything a script can decide is decided by a script:
your words the loop the gate
────────── ──────── ────────
reference → analyse · architect · code → render · diff · evaluate
↑ │
└────── fix one mismatch ──────┘
│
READY_FOR_APPROVAL / BLOCKED
Five things make that more than a prompt:
- The version decides the API.
scripts/resolve-version.mjsreads yourpom.xmlorbuild.gradle, maps the line to a skill pack, and stops if there is no pack — rather than authoring against an API your version does not have. - The gate is arithmetic. A refactor must produce
AE == 0against its parent. A data edit may differ only in the regions it touched. The metric is quoted, never paraphrased. - The loop is bounded.
scripts/iterate-status.mjscounts the iterations, the consecutive build failures and the repeats of the same mismatch, and answers 0 ready / 2 revise / 3 blocked. An agent going round in circles is the last thing qualified to notice it. - Nothing is overwritten. Every change opens a revision; approving supersedes rather than replaces; a single component can be restored from any earlier one.
- The geometry is measured, not guessed at. The renderer writes
GraphCompose's own post-layout snapshot beside the PDF, so "this block
is too far right" is arithmetic rather than an argument about a
screenshot.
node scripts/layout.mjs explain <node> xanswers it with the additive chain —canvas.margin.left 0 + Sidebar.padding.left 17 + Heading.padding.left 9 = 26— naming the node that owns the offset rather than the one that shows it.diffsays whether a patch moved only what it meant to,doctorsays whether the geometry sits on the node that owns it, and each of them will answer "I cannot derive this" rather than produce a number it cannot support.
docs/architecture.md has the full picture,
including what this project deliberately does not build: no LLM API
integration, no MCP server, no standalone runtime.
- The four workflow skills, the tools, the schemas, the packaging and
the CI gates are in place;
npm run verifyruns every gate locally. The eleven-agent prompt chain they replaced has been removed. - Claude Code acceptance has been run three times. Twice on the
templates above — the skill fired from a plain sentence, the version
came from the project's
pom.xml, the workspace landed in the Java project, and both reached an approved published bundle. A third, an invoice, walked the flowing-document path end to end: five line items render one page reading "Page 1 of 1", thirty render three pages numbered through with the table header repeated and no row lost. It stopped at ready-for-approval and was not approved. - Codex fires the skill from a plain sentence too — observed, with Codex announcing the workflow by name before doing anything. So skill discovery and natural-language activation are no longer open questions on either host, and the install is proven self-contained with the clone deleted. What is not recorded there is a full run carried through to an approved published bundle; until it is, host parity rests on the contract test rather than on a second measured run.
- The GraphCompose 2.2 pack ships and its five fixtures compile,
test and render against 2.2.0 with every render identical to its
baseline. The conceptual skills stay
needs-validationon coverage — five fixtures are a subset of what fourteen skills describe. Seeskills/README.md. - The layout diagnostics are built and their effect is not proven.
The tools measurably do what they were built to do: 749 of 988
coordinate queries on a real CV resolve to an exact derivation, an
evidence package is 78× smaller than the snapshot it replaces, the font
matcher names the right family first six times out of six. But no
project has yet been authored with them in place, so the corpus has
not moved and all three headline metrics — owner correct on first
attempt, renders per geometry correction, collateral nodes per revision
— are still null. Capability and effect are different claims;
docs/benchmarks.mdkeeps them apart and says exactly what would settle the second. - Details and scope limits:
docs/limitations.md, progress:docs/roadmap.md.
AGENTS.md dispatches: which skill owns the task, the
seven invariants, the commands, and where each contract is declared.
Start there, not here.
Clone it, run npm run setup, and read
docs/quickstart.md — that is the contributor
path, where the workspace is this repository's own examples/ rather
than a user's project. npm run verify runs every gate CI runs.
| Path | What |
|---|---|
skills/workflows/ |
the four workflow skills and their shared references |
skills/versions/ |
GraphCompose knowledge, one pack per library line |
config/pipeline.json |
scope → stages, gates, loop bounds, failure categories |
schemas/ |
every on-disk contract |
tools/ |
revision manager, renderer, visual diff, asset resolver |
scripts/ |
version resolver, workspace init, render, pipeline, loop gate, publish, verify |
examples/cv-reference/ |
a worked chain — revisions 001 → 009 |
MIT.







