Skills · Infrastructure & ops

Paper Poster (HTML): measurement-gated poster generation

Unverified36/40

DEFAULT poster pipeline — build an academic conference poster (ICML/NeurIPS/ICLR/CVPR/...) as a single HTML/CSS file with measurement-driven hard gates, real paper figures, a two-hue design-token system, and print-ready PDF via headless Chromium. Use when the

Originally by wanshuiyin · MIT

Claude CodeWorksValid SKILL.md that declares allowed-tools
Cursor·UnknownWe have not crawled the repo tree, so we will not guess
Codex·UnknownWe have not crawled the repo tree, so we will not guess
Gemini CLI·UnknownThe spec defines no detection rule for Gemini
Copilot·UnknownWe have not crawled the repo tree, so we will not guess
npx agentalley add paper-poster-html

This command does not work yet — the CLI is still being built. Until then, use Raw in the reader below to take the file.

Who is stuck, and on what

DEFAULT poster pipeline — build an academic conference poster (ICML/NeurIPS/ICLR/CVPR/...) as a single HTML/CSS file with measurement-driven hard gates, real paper figures, a two-hue design-token system, and print-ready PDF via headless Chromium. Use when the

The whole source

No sign-in, no blur, nothing truncated
paper-poster-html/SKILL.md324 lines18.0 KBRawView on GitHub
Frontmatter — 4 properties
namepaper-poster-html
descriptionDEFAULT poster pipeline — build an academic conference poster (ICML/NeurIPS/ICLR/CVPR/...) as a single HTML/CSS file with measurement-driven hard gates, real paper figures, a two-hue design-token system, and print-ready PDF via headless Chromium. Use when the user says \"做海报\", \"poster\", \"conference poster\", \"paper poster\", or asks to design/redo a research poster. Supersedes the retired LaTeX /paper-poster.
argument-hint[paper-dir-or-pdf] [— venue: ICLR, canvas: 185x90cm landscape, venue-colors: true]
allowed-toolsBash(*), Read, Write, Edit, Grep, Glob, WebFetch, WebSearch, AskUserQuestion, mcp__codex__codex
1---
2name: paper-poster-html
3description: "DEFAULT poster pipeline — build an academic conference poster (ICML/NeurIPS/ICLR/CVPR/...) as a single HTML/CSS file with measurement-driven hard gates, real paper figures, a two-hue design-token system, and print-ready PDF via headless Chromium. Use when the user says \"做海报\", \"poster\", \"conference poster\", \"paper poster\", or asks to design/redo a research poster. Supersedes the retired LaTeX /paper-poster."
4argument-hint: "[paper-dir-or-pdf] [— venue: ICLR, canvas: 185x90cm landscape, venue-colors: true]"
5allowed-tools: Bash(*), Read, Write, Edit, Grep, Glob, WebFetch, WebSearch, AskUserQuestion, mcp__codex__codexA4This skill pulls in web or user content but never says to treat that content as data. A signal, not proof.
6---
7 
8# Paper Poster (HTML): measurement-gated poster generation
9 
10One HTML file styled for an exact print canvas (`@page { size: W H }`), rendered to PDF
11via Playwright print emulation. **Iterate by measuring, not eyeballing** — the screen
12preview lies; only print emulation at the correct viewport tells the truth. Core gate
13machinery is adapted from [posterly](https://github.com/Chenruishuo/posterly) (MIT, ©
142026 Ruishuo Chen — see `NOTICE.md` and `LICENSES/posterly-MIT.txt`); ARIS adds style
15discipline gates, figure-provenance gates, the cross-model review loop, and the
16anti-patch-loop fix vocabulary.
17 
18## Why this skill exists (the failure it prevents)
19 
20A predecessor pipeline produced a poster with **30+ colors, zero real paper figures, a
21screen-pixel canvas, and tiny formulas floating in oversized boxes**, then spent 12+
22review rounds making it *worse* — each round added a new badge color or bespoke SVG
23patch. The cure is structural, not exhortative:
24 
251. **Hard gates run before any aesthetic opinion** (alignment, style, assets must PASS
26 first — a reviewer never sees an unmeasured poster).
272. **A closed fix vocabulary** — visual-review fixes can only touch design tokens,
28 whole catalogued components, content rebalance, assets, or canvas choice. New inline
29 styles / new hex values / bespoke decorations are structurally forbidden.
303. **Two-hue discipline as a machine check**, not a style suggestion.
314. **Real paper figures with provenance manifest**, or the gate fails.
32 
33## Mental model
34 
35```
36paper (.tex / PDF) ──► content plan + claim→evidence audit (codex, fresh)
37
38 figures extracted ─────────┤ FIGURE_MANIFEST.json (provenance, sha256)
39 (real paper figures ONLY) ▼
40 template scaffold ──► fill ──► run_gates.py ◄─── HARD, loop here
41 preflight → style → asset → measure → polish
42 │ all hard gates PASS
43
44 Claude visual review (≤3 issues × ≤3 rounds, fix-vocabulary only)
45 │ score ≥ 9
46
47 codex final cross-model review (fresh thread, full HTML+PDF)
48 │ pass
49
50 verify-final → poster.pdf + GATE_REPORT.json
51```
52 
53## Constants
54 
55- **SKILL_SCRIPTS** = `${CLAUDE_SKILL_DIR}/scripts` — all helpers are single-owner and
56 ship inside this skill (Arch C). If the directory is missing the install is broken:
57 abort and tell the user to re-install the skill (Policy A — the gates ARE the skill;
58 never improvise replacements).
59- **REVIEWER_MODEL** = `gpt-6-astra`, reasoning `xhigh`, **fresh thread per review call**
60 (`mcp__codex__codex`, never `codex-reply` across review boundaries).
61- **CANVAS** — from the venue's official spec, looked up live in Phase 0. Never assume.
62 (Known anchor: ICLR 2026 main = 185×90 cm landscape per its official printing
63 service; ICML/NeurIPS commonly 60×36 in landscape; workshop posters often 61×91 cm
64 portrait. Specs change yearly — verify.)
65- **PALETTE** — default = `templates/tokens/generic.json` (slate-blue `#2D5F8B` accent
66 + gold `#C9A24A` highlight + neutrals) for **all** venues. Venue packs are opt-in via
67 `— venue-colors: true`. Purple-dominant accents (hue 250–285) are banned unless the
68 user passes `— allow-purple: true`.
69- **AUTO_PROCEED = false** — wait for explicit confirmation at every 🚦 checkpoint.
70- **OUTPUT_DIR** = `poster_html/` in the working directory.
71 
72## Workflow
73 
74### Phase 0 — Resume, dependencies, venue spec
75 
761. **Resume**: if `poster_html/POSTER_STATE.json` exists with `status: in_progress`
77 (< 24 h), resume from the saved phase.
782. **Dependencies** (degradation chain, in order):
79 - Playwright + bundled Chromium → if missing, `python3 -m playwright install
80 chromium` → if install fails but system Chrome exists, scripts fall back to
81 `channel="chrome"` → if all fail: you may produce the content plan and scaffold
82 only, label everything **"not print verified"**, and must NOT emit a final PDF.
83 - `pdfinfo` missing → PyMuPDF reads PDF dimensions. At least one of
84 pdftoppm / PyMuPDF must exist for PNG review renders.
85 - MathJax: download `tex-svg.js` once into `poster_html/assets/mathjax/` and
86 reference it locally in the HTML. CDN is acceptable only for drafts; the measure
87 gate hard-fails on unrendered MathJax either way.
883. **Venue spec lookup (live)**: consult the venue's official poster-instructions page
89 (search + fetch). Extract dimensions, orientation, font floor, logo policy,
90 anonymity rules, file format. Record `{spec, source_url, retrieved}` into
91 `POSTER_STATE.json` — specs change yearly; never reuse a cached spec silently.
92 
93**🚦 Checkpoint**: echo the venue spec table (canvas, orientation, source URL) and the
94chosen template. Wait.
95 
96### Phase 0.5 — Design discovery (one AskUserQuestion batch)
97 
98Ask once, ≤4 questions: layout template (from `templates/README.md`), palette
99(default generic pack / venue pack / custom within constraints), logos + venue mark
100(paths or "none" — never fabricate; check the venue's logo policy), QR target (paper /
101code / project page / none — generate **offline** with `qrencode` or python-`qrcode`;
102never a remote QR-service URL). Persist answers in `POSTER_STATE.json` as
103`design_decisions` — re-read before any later "improvement" so deliberate choices are
104never reverted.
105 
106### Phase 1 — Paper ingest, content plan, claim audit
107 
1081. Read the paper source (`.tex` ideal; PDF otherwise). Extract: title/authors/affils,
109 the 3–5 headline numbers, core method (equations verbatim), main results
110 (tables/figures and what they show), takeaways. Build
111 `poster_html/POSTER_CONTENT_PLAN.md` — what goes in which column, word budget per
112 card. **Target density** (excluding table cells, captions, author line, footer):
113 standard poster **550–850 words**; dense theory+empirical poster **750–1050 words**,
114 allowed only when ≥2 compact components are used (`eqn-anatomy`, `flow-strip`,
115 `derived-col`, `claim-pills`, `keybox--4`). Warn yourself below 500 words on a
116 4-column landscape (it will read as sparse next to professionally dense posters)
117 unless the template is hero/visual-first; warn above 1100 unless the user asked for
118 dense mode. Bullets ≤ 8 words when possible — density comes from *structure*, not
119 long prose. **Prefer compact structure over prose**: if the paper contains an
120 explicit objective, algorithm, theorem mechanism, or baseline comparison, extract at
121 least two of: (1) empirical objective / loss stack; (2) term-by-term equation
122 anatomy; (3) a method-flow strip grounded in paper variables; (4) a derived-Δ column
123 for method-vs-baseline rows; (5) a 4-up implementation/theory keybox; (6) a
124 claim/evidence pill table for numeric-heavy posters. **Do not invent an algorithm.**
125 If the paper has only an objective, label the component "objective flow" or "loss
126 anatomy", never "algorithm".
1272. **Cross-model content audit** (fresh codex thread, `xhigh`): give it the content
128 plan path + paper source path(s) — paths only, no summaries — and ask for a
129 claim→evidence table: `| claim on poster | paper file:line | paper says (verbatim) |
130 match? |` with match ∈ {OK, NUMERIC-MISMATCH, OVERCLAIM, MISSING-PRECONDITION,
131 NOT-IN-PAPER, SCOPE-NARROWED}. Save to `poster_html/CLAIM_EVIDENCE.md`.
1323. Fix every non-OK row or record it as a user-acknowledged tradeoff.
133 
134**🚦 Checkpoint**: content plan + audit summary. Wait.
135 
136### Phase 2 — Real paper figures (provenance-gated)
137 
138Source preference chain:
1391. Paper source `figures/` (vector SVG/PDF → convert to SVG via
140 `inkscape`/`pdf2svg` if available, else rasterize ≥ 2× rendered px).
1412. PDF-only: `extract_pdf_figures.py contact-sheet` + `auto` to list candidate
142 regions → pick crops (**🚦 human confirms crop choices**) → `crop` at 300–450 DPI.
1433. Last resort: user supplies explicit `page,x0,y0,x1,y1` bboxes.
144 
145Then `preprocess_figures.py --autocrop` every asset. Every paper-derived image gets a
146`FIGURE_MANIFEST.json` entry (source hash, page, bbox, dpi, sha256, natural_px) and is
147embedded as `<img data-source="paper" data-asset-id="...">`.
148 
149**Hard rule**: ≥ 2 paper-derived visuals or the asset gate fails. Theory-only papers
150may waive the *total-area* rule (`--waive-total-area`) at a human checkpoint — never
151silently. Never draw bespoke decorative SVG "figures" as substitutes.
152 
153**Figure-area bands** (asset gate, fractions of *body*): total target **14–22 %**
154(warn < 12 % / > 24 %, hard < 10 % / > 28 %); per ordinary figure target 4–8 % (warn
155> 10 %, hard > 13 %); `figure--duo` combined 8–12 %. Hero templates pass `--hero`
156(centerpiece may take 30–40 %). The failure mode is symmetric: too small reads as
157decoration, too big crowds out content. Sibling figures that share axes or tell a
158before→after story belong in one `figure--duo` card, not two cards.
159 
160### Phase 3 — Scaffold + tokens
161 
162`cp templates/<chosen>.html poster_html/poster.html`; retarget `@page` + `.poster`
163dims to the venue canvas (two edits, same values); apply the chosen token pack onto the
164`:root` DESIGN TOKENS block; fill content per the plan; embed manifest figures.
165Run `preflight` + `style_check` — both must PASS before any layout iteration. (A fresh
166scaffold is *expected* to fail `measure` — that gate judges a filled poster.)
167 
168### Phase 4 — Layout hard loop
169 
170After every layout change:
171 
172```bash
173python3 "$SKILL_SCRIPTS/run_gates.py" poster_html/poster.html \
174 --tokens <pack.json> --manifest poster_html/FIGURE_MANIFEST.json \
175 --report poster_html/GATE_REPORT.json
176```
177 
178Canonical order: preflight → style → asset → measure → polish. Targets: column-bottom
179**spread < 5 px** (aim < 3), footer gap ∈ [30, 50] px, intercard gap ∈ [12, 50] px,
180canvas-fill ∈ [95, 101] %, poster bbox aligned to page within ±2 px. Fix guidance for
181each failure mode lives in the gate output and `templates/COMPONENTS.md`. **Do not
182proceed while any hard gate fails. Do not let a reviewer see an unmeasured poster.**
183Balance under-filled columns with *content from the paper* (Gate C), never with
184whitespace, `space-between`, or stretched cards.
185 
186### Phase 5 — Claude visual review (gated aesthetics)
187 
188Render and read the result yourself:
189 
190```bash
191python3 "$SKILL_SCRIPTS/render_preview.py" poster_html/poster.html
192pdftoppm -r 100 poster_html/poster_preview.pdf poster_html/review_full -png -f 1 -l 1
193# plus 2-4 region crops at higher res (header / one column / equations) via PIL
194```
195 
196**Calibrate first** (`../shared-references/taste-calibration.md`): if
197**human-curated** `references/good/` + `references/bad/` exist under this skill
198dir (or the project supplies its own pair), score those 3+3 reference posters
199on the axes below BEFORE the target, anchoring the scale. Never select, search
200for, or generate anchors yourself; if no reference sets exist, proceed
201uncalibrated and mark `CALIBRATION: none` — never fabricate anchor scores.
202Axes (weights sum 1.0): Design 0.35 · Craft 0.30 · Functionality 0.20 ·
203Originality 0.15. Mapping: `SCORE = min(round(1 + 9 × COMPOSITE), lowest
204triggered cap)` — caps apply AFTER the mapping, and the loop's `Score ≥ 9`
205threshold below always reads this final capped `SCORE`, never the raw
206composite.
207 
208Score strictly 1–10. **Critical caps** (hard floors — a calibrated composite
209never overrides them): < 2 real paper figures → ≤ 3; broken canvas /
210clipped content / unreadable math → ≤ 4; ≥ 4 visible hue families or gradient-heavy
211header → ≤ 4; large blank cards or columns → ≤ 5; fabricated visual claim → ≤ 3.
212Checks: posterly-showcase gestalt (would this hang next to a professionally designed
213poster without looking like a patched dashboard?), single-accent discipline, real
214figures readable and central, print hierarchy (title → headline stats → figures →
215detail), column fill, **equation prominence** (no tiny math in oversized boxes),
216serif-body/sans-display pairing, no gradient kitsch, component consistency, 60-second
217narrative. Output format:
218 
219```
220SCORE: N/10 (= min(round(1 + 9 × COMPOSITE), lowest cap); drives the loop)
221COMPOSITE: 0.xx (weighted; list the four per-axis scores)
222CALIBRATION: anchored | none
223GAP: <which reference poster the target falls short of / exceeds, on which axis, and why — one paragraph; omit only when CALIBRATION: none>
224CAPS_TRIGGERED: ...
225TOP_ISSUES: (max 3)
226ALLOWED_FIX_TYPE per issue: token | component | rebalance | asset | template/canvas
227PATCH_LOOP_RISK: low | medium | high
228```
229 
230Loop: fix (fix vocabulary below) → re-run Phase 4 gates → re-score. **≤ 3 issues per
231round, ≤ 3 rounds.** Score ≥ 9 → Phase 6. Still < 9 after 3 rounds → STOP patching;
232escalate to template / canvas / content re-choice (back to Phase 3) or a human
233decision. Never enter round 4 of cosmetic patching.
234 
235#### Fix vocabulary (closed set — the anti-patch-loop core)
236 
237Allowed: **(a)** edit a `:root` token value; **(b)** swap/remove/add a whole component
238instance from `templates/COMPONENTS.md`; **(c)** content rebalance (move a card across
239columns, trim/grow text *from the paper*, resize a figure within its AR band);
240**(d)** template/canvas re-choice; **(e)** global edits to an existing component's CSS
241that reference only tokens; **(f)** switching predefined variants (`.eqn--large`,
242`.card--compact`, `.figure--wide`, `.nowrap`, …); **(g)** asset fixes (re-crop, swap
243for a clearer figure from the same paper, re-preprocess).
244 
245Forbidden: new inline styles, new hex values anywhere, bespoke decorative SVG,
246per-element font-size overrides. **A new component may not be born inside the visual
247loop** — stop, get a human checkpoint, add it to `COMPONENTS.md`, re-run from Phase 3.
248 
249### Phase 6 — Codex final review (fresh thread, cross-model)
250 
251All hard gates PASS + polish warnings zero-or-waived + visual ≥ 9 first. Then a fresh
252codex thread (`xhigh`) reviews the **final artifacts** (not the content plan):
253`poster.html`, the rendered PDF/PNG, the paper source, `GATE_REPORT.json`,
254`CLAIM_EVIDENCE.md` — paths only, no executor framing. It checks: (1) fidelity &
255overclaims **re-checked on final text** (polish introduces new claims), (2) residue
256(`\ref{`, `TODO`, raw `<` in math, missing images, remote URLs), (3) visual rhetoric
257(headline numbers prominent, banner readable from 2 m), (4) gate-log coherence. The
258reviewer recommends; it does not edit. Any fix → back through Phase 4/5 gates — never
259straight to re-review.
260 
261### Phase 7 — Final verification + report
262 
263```bash
264python3 "$SKILL_SCRIPTS/poster_check.py" verify-final poster_html/poster_preview.pdf \
265 --from-html poster_html/poster.html --max-size-mb 20
266```
267 
268Page count 1, dimensions match `@page`, size ≤ 20 MB, no TODO/residue, no remote
269assets. Report: PDF path, final spread px, footer-gap range, gate summary table,
270unresolved waivers, codex verdict. Update `POSTER_STATE.json` → `done`.
271 
272## State persistence
273 
274`poster_html/POSTER_STATE.json`: `{phase, venue, canvas{w,h,orientation,source_url,
275retrieved}, template, token_pack, design_decisions{...}, figures_selected[],
276visual_rounds, codex_threads{audit, final}, status, timestamp}` — written after every
277phase; enables compact-recovery resume.
278 
279## Key rules
280 
281- **Measure, don't eyeball.** No layout claim without `run_gates.py` output.
282- **Gates before aesthetics.** Claude/codex review only ever sees a poster whose hard
283 gates PASS. This ordering is what kills the patch-loop death spiral.
284- **Never invent paper numbers or figures.** Numbers come from the paper source;
285 visuals carry manifest provenance. Fabrication = critical cap ≤ 3.
286- **Two hues, one system.** Accent + gold + neutrals. The style gate enforces it;
287 don't negotiate with the gate.
288- **Real figures are the poster.** A poster without the paper's own figures is a
289 dashboard, not a poster.
290- **Fix vocabulary is closed.** If a fix isn't expressible as token / component /
291 rebalance / asset / canvas, it's the wrong fix.
292- **Cross-model verdicts.** Claude drives the loop and scores visuals; acceptance of
293 content fidelity comes from the fresh codex thread (a loop can drive, never acquit).
294- **Preserve user decisions.** Re-read `design_decisions` before "improving" anything.
295- **Vendor boundary.** `poster_check.py`, `render_preview.py`, `_posterly/` are
296 vendored from posterly — keep diffs minimal; ARIS-side logic goes in the new
297 scripts, not in vendored files.
298 
299## Review tracing
300 
301Save every codex reviewer call's trace per `shared-references/review-tracing.md` to
302`.aris/traces/paper-poster-html/<date>_run<NN>/` (audit + final threads, raw responses).
303 
304## Output contract
305 
306```
307poster_html/
308├── poster.html # single-file source of truth
309├── poster_preview.pdf # print-emulated, verify-final-checked
310├── poster_preview.png # thumbnail
311├── POSTER_STATE.json # resume state
312├── GATE_REPORT.json # canonical gate ledger (schema v1)
313├── POSTER_CONTENT_PLAN.md # what-goes-where + word budgets
314├── CLAIM_EVIDENCE.md # codex claim→evidence audit
315├── FIGURE_MANIFEST.json # figure provenance (sha256, page, bbox, dpi)
316└── assets/{paper_figures,logos,qr,mathjax}/
317```
318 
319## When NOT to use
320 
321- Slides, not a poster → `/paper-talk` / `/slides-polish`.
322- The paper's headline isn't stable yet — fix the paper first; a poster amplifies
323 whatever story it's given.
324 

Reviews

Installed this one?Write the first review and take the Trailblazer badge.

Reviews only open after a real install, so this is empty — and we leave it empty rather than invent one.

Alternatives

Also in Infrastructure & ops