kami · diff
git:20260920.a489e39 to git:20260925.6ec0272
98 added, 380 removed. Audit A to A.
---
name: kami
description: 'Typeset professional documents with Kami templates: resumes, one-pagers, white papers, letters, portfolios, and slide decks. Use when asked to 做 PDF / 排版 / 简历 / 一页纸 / PPT / slides, or to create a Kami landing page. Not for auditing or restyling an existing product site.'
---
# kami · 紙
**紙 · かみ** means paper in Japanese.
Good content deserves good paper. Use Kami’s templates and layout rules to create documents and landing pages with serif fonts, warm backgrounds, and ink-blue accents.
Part of `Kaku · Waza · Kami` - Kaku writes code, Waza drills habits, **Kami delivers documents**.
- **Update check (non-blocking).** At the start of a task, run `bash scripts/check-update.sh`. On the first run each calendar day, it writes a marker under the local XDG cache directory and then resolves Kami's latest published GitHub Release. It uploads no user document or task content. When a newer Kami is available it prints one line; relay that line to the user, then continue. It fails silently when offline, sandboxed, or without `curl`, and must never block the work.
-
- ## Step 0 · Load brand profile (if exists)
+ Commands and paths below are relative to this skill's directory. Keep the document in the user's working directory and call the scripts from there by their full path (`python3 <skill>/scripts/build.py ...`); relative file arguments resolve from your working directory first.
- Check `~/.config/kami/brand.md` (preferred) or `~/.kami/brand.md` (legacy fallback). If found, read `references/brand-profile.md` for the full four-layer application spec (placeholder substitution, session defaults, visual customization, habit notes) and its six guardrails. If no profile exists, continue without interruption.
+ **Update check (non-blocking).** At the start of a task, run `bash scripts/check-update.sh`. It keeps a local daily marker and, at most once a day, reads Kami's latest published GitHub Release; it uploads no document or task content and stays silent when offline or sandboxed. When it prints a line about a newer Kami, relay it and continue.
- Key rule: explicit prompt > editorial judgment > habit notes > frontmatter defaults > built-in defaults. Profile fills gaps silently; it never overrides the current conversation.
+ **Brand profile.** If `~/.config/kami/brand.md` (or the legacy `~/.kami/brand.md`) exists, read `references/brand-profile.md` and apply it. Precedence: explicit prompt > editorial judgment > habit notes > frontmatter defaults > built-in defaults. The profile fills gaps silently and never overrides the current conversation. When the user names another project as the visual reference, run the style scan in the same file.
- ## Step 0.5 · User project style scan (opt-in)
+ ## 1 · Lock the contract
- Run this only when the user explicitly references a sibling project as a visual reference: "like my <project> site", "match the style of <repo>", "use the look from <directory>". Skip silently when no such reference exists.
+ Before creating or changing an output, lock six things: language, template, output formats, page or length target, visual acceptance, and the verification command. Infer them from the request, then state the contract to the user in one short line in their language (template, length, formats, the figures you plan, any missing material) and continue without waiting. If they push back, adjust.
- When triggered, before generating: locate the referenced project's declared design tokens (CSS variables, tailwind/theme config, token files) and extract dominant colors, font stack, spacing scale, and border-radius scale; prefer declared tokens over inline literals. Merge into the in-session brand profile as Layer C (visual customization), not Layer B (session defaults); never override an explicit `--brand` flag or values the user typed this turn. Report back in one line before continuing: "scanned <project>, extracted N colors / M fonts; using as visual reference."
+ **Question budget.** Infer first. Ask at most once, in one compact question with at most two parts, and only when two or more of purpose, audience, hard constraints, or success are genuinely unresolvable, or two templates genuinely both fit. Otherwise take the smallest reasonable assumption and report it at the end.
- Skip and fall back to the brand profile defaults if the referenced path does not exist, no CSS-like files are found, or the extraction would conflict with the user's explicit values in the current message.
+ Route by the artifact's current state:
- ---
+ | Current task | Mode | Contract |
+ |---|---|---|
+ | New document or substantial restructuring | **New document** | Lock the contract, write `content.json` with `brief` + `content`, then fill and deliver |
+ | Text replacement, translation, or factual correction in an existing artifact | **Content-only** | Preserve CSS and layout unless the new copy proves a fit defect |
+ | User supplies a render or screenshot and rejects how it looks | **Visual repair** | Treat the render as the brief; follow «Feedback protocol» |
+ | Standalone generated illustration, cover, social card, or redraw | **Generated asset** | Lock the semantic brief before pixels (`references/diagrams.md` section 11); preserve accepted parts across iterations |
- ## Step 1 · Decide the language
+ Use the nearest existing template and check. Do not add a template, shared CSS layer, dependency, script flag, or optional mode unless the request cannot be met without it.
- **Match the user's language.** Chinese -> `*.html` / `slides-weasy.html`. English -> `*-en.html` / `slides-weasy-en.html`. Japanese -> CJK path (`.html` / `slides-weasy.html` / `slides-marp.md`) as best-effort, JP Mincho first, visual QA before shipping. Korean -> dedicated `*-ko.html` / `slides-weasy-ko.html` family, with `slides-marp.md` as the best-effort Markdown path, visual QA before shipping. Reference docs are shared English specs.
+ ### Language
- | User language | HTML templates | Slides (PDF default) | Slides (PPTX fallback) | Slides (Marp) |
+ | User language | HTML templates | Slides (PDF default) | Slides (PPTX, only when an editable deck is requested) | Slides (Marp) |
|---|---|---|---|---|
| Chinese (primary) | `*.html` | `slides-weasy.html` | `slides.py` | `slides-marp.md` |
| English | `*-en.html` | `slides-weasy-en.html` | `slides-en.py` | `slides-marp-en.md` |
- | Japanese (best-effort) | `*.html` | `slides-weasy.html` | `slides.py` | `slides-marp.md` |
- | Korean (best-effort) | `*-ko.html` | `slides-weasy-ko.html` | n/a (use `slides-en.py` only if PPTX is required) | `slides-marp.md` |
- | Other languages (best-effort) | choose CJK or EN path by script coverage, then verify manually | choose `slides-weasy.html` or `slides-weasy-en.html`, then verify manually | use `slides.py` / `slides-en.py` only if PPTX is required | choose `slides-marp.md` or `slides-marp-en.md`, then verify manually |
-
- > Default to the WeasyPrint HTML path; fall back to PPTX (`slides*.py`) only when the user explicitly needs an editable deck.
-
- Design, writing, production, and diagram guidance live in `CHEATSHEET.md` and `references/*.md`. Step 3's tier table decides how much of it to open; read the lowest tier that covers the task, not all of it.
-
- Code blocks with `class="language-*"` are highlighted only when optional `Pygments` is installed in the build environment. Without it, PDFs still render and code blocks stay monochrome.
-
- **Mathematics is strict LaTeX, never pseudo-math.** When a document contains mathematics, author formulas only as standard LaTeX delimiters in rendered body text: inline `\( ... \)` and display `\[ ... \]`. Delimiters inside title metadata, form options, literal/code, script, style, SVG, template, and MathML regions are treated as text. Do not replace formulas with Unicode approximations, ASCII fractions, screenshots, or raw TeX printed on the page. The renderer requires Node.js 20 or Node.js 22 and newer. Before shipping HTML/PDF, run `bash scripts/ensure_mathjax.sh`, then `python3 scripts/math_render.py --in-place filled.html`; this converts every formula into MathJax SVG. `render_pdf` also performs this conversion in memory as a hard fallback and fails if MathJax or the TeX is invalid. Finish with `python3 scripts/math_render.py --check filled.html`; a completed HTML must contain no raw TeX delimiters in rendered body text.
-
- ## Step 1.5 · Intent extraction (silent)
-
- Before picking a template, silently confirm purpose, audience, hard constraints, and what outcome counts as success. Skip any dimension the conversation or the document type already answers (a resume's purpose is always "get an interview").
-
- Question budget, global for this skill: infer first, from the decision tree and context. Ask at most once, in one compact question (max 2 sub-questions), and only when 2+ intent dimensions are genuinely unresolvable or two templates genuinely both fit. Never present the dimensions as a checklist.
-
- ## Execution contract
-
- Before creating or modifying an output, lock the contract: language, template, output format, page or length target, visual acceptance check, and verification command. Infer from the user's request when clear; ask only when missing fields materially change the deliverable.
-
- Use the nearest existing template and verification path. Do not add a new template, shared CSS layer, dependency, script flag, or optional mode unless the current request cannot be satisfied without it.
-
- A change to `SKILL.md`, templates, scripts, or references reaches `npx skills add` and plugin installs on the next push to `main`; Claude Desktop users get it only when the next release rebuilds `kami.zip`. Name the channel that carries the change before calling it shipped.
-
- ### Work mode
-
- Route by the artifact's current state before loading more guidance. This is an internal branch, not a new user-facing command.
-
- | Current task | Mode | Contract |
- |---|---|---|
- | New document or substantial restructuring | **New document** | Lock the execution contract, write `content.json` with `brief` + `content`, then fill and verify |
- | Text replacement, translation, or factual correction in an existing artifact | **Content-only** | Preserve CSS and layout unless the new copy proves a fit defect |
- | User supplies a render or screenshot and rejects how it looks | **Visual repair** | Treat the render as the current brief, lock target + preserve boundary, make the smallest fix, then verify the affected matrix |
- | Standalone generated illustration, cover, social card, or redraw | **Generated asset** | Lock the semantic image brief before pixels; preserve accepted parts across iterations |
+ | Japanese (best-effort) | `*.html`, JP Mincho first | `slides-weasy.html` | `slides.py` | `slides-marp.md` |
+ | Korean | `*-ko.html` | `slides-weasy-ko.html` | `slides-en.py` only if PPTX is required | `slides-marp.md` |
+ | Other (best-effort) | CJK or EN path by script coverage | `slides-weasy.html` or `-en` | `slides.py` / `slides-en.py` | `slides-marp.md` or `-en` |
- ---
+ Japanese, Korean, and other languages need a visual pass on the page images before shipping. Reference docs are shared English specs.
- ## Step 2 · Pick the document type
+ ### Document type
| User says | Document | CN template | EN template | KO template |
|---|---|---|---|---|
| "one-pager / 方案 / 执行摘要 / exec summary" | One-Pager | `one-pager.html` | `one-pager-en.html` | `one-pager-ko.html` |
| "white paper / 白皮书 / 长文 / 年度总结 / technical report" | Long Doc | `long-doc.html` | `long-doc-en.html` | `long-doc-ko.html` |
| "formal letter / 信件 / 辞职信 / 推荐信 / memo" | Letter | `letter.html` | `letter-en.html` | `letter-ko.html` |
| "portfolio / 作品集 / case studies" | Portfolio | `portfolio.html` | `portfolio-en.html` | `portfolio-ko.html` |
| "resume / CV / 简历 / 履歴書" | Resume | `resume.html` | `resume-en.html` | `resume-ko.html` |
| "slides / PPT / deck / 演示" | Slides | `slides-weasy.html` | `slides-weasy-en.html` | `slides-weasy-ko.html` |
| "个股研报 / equity report / 估值分析 / investment memo / 股票分析" | Equity Report | `equity-report.html` | `equity-report-en.html` | `equity-report-ko.html` |
| "更新日志 / changelog / release notes / 版本记录" | Changelog | `changelog.html` | `changelog-en.html` | `changelog-ko.html` |
| "landing page / 落地页 / 官网 / product page / 产品页" | Landing Page | `landing-page.html` | `landing-page-en.html` | `landing-page-ko.html` |
- > **Changelog vs. release notes**: The changelog template above is for styled document output. GitHub release notes are a separate deliverable; use `/write` with Release Note Template Mode.
-
- > **Landing Page**: Screen-first interactive template. No PDF output. Includes gallery carousel with auto-rotate, hero entrance animation, responsive breakpoints (880px / 480px), and prefers-reduced-motion support. Deploy as static HTML to Vercel / Netlify / any host. The agent fills {{PLACEHOLDER}} values and HTML comment blocks, then saves as a ready-to-serve `.html` file.
-
- > **Landing Page companion files**: For a production multilingual deploy, copy the five `landing-page-*.example` files alongside the main HTML and drop the `.example` suffix. `{{SITE_ORIGIN}}` is the scheme + host of your `{{CANONICAL_URL}}` (e.g. `https://example.com`). What each file covers, and the opt-in Accept-Language redirect: `references/design.md` Section 11 «Companion assets».
-
- > **Production product site mode**: docs, help, releases, changelog, roadmap, legal pages, or more than two locales means a site system, not a page. Lock the five items below from the source material before filling any template, asking only where a missing item would change the deliverable. Then follow `references/design.md` Section 11 «Product site system», and «Documentation site» in the same section once the page grows a docs or help shell.
-
- | # | Lock |
- |---|---|
- | 1 | **Product category** - first-viewport category: app, CLI, terminal, utility, skill, template system, or another user-provided label. |
- | 2 | **Real assets** - available product screenshots, logo, icon, or UI captures, mapped to hero/gallery/feature/social slots. Missing assets must stay marked, not replaced with stock imagery. |
- | 3 | **Site shape** - single page, or home plus docs/help/releases/changelog/roadmap/legal pages? |
- | 4 | **Locales** - exact locale list, canonical paths, and whether a generator/check mode is needed. |
- | 5 | **Truth surfaces** - install path, price, version, support route, FAQ, `llms.txt`, and `llms-full.txt` that must stay synchronized. |
-
- Keep project-specific release artifacts, payment providers, appcast rules, and private local paths out of Kami.
-
- ### Decision tree (use before asking)
-
- Ask only when two cells genuinely both fit.
+ When two cells both fit, decide from the signals before asking:
| Signal | Document |
|---|---|
- | Length target unknown | Infer from the content and document type; ask only if the choice materially changes the deliverable, within the question budget |
- | ≤ 1 page + investor / recruiter / exec summary audience | one-pager |
- | ≤ 1 page + formal correspondence (sales, hiring, resignation, memo) | letter |
- | 1.5-2 pages + career narrative + project bullets | resume |
- | 3-6 pages + project showcase + visual heavy | portfolio |
- | 6-15 pages + sustained argument + low visual density | long-doc |
- | Presentation flow + speaker support + per-slide assertion | slides |
- | Financial / metrics dashboard + thesis + price or risk view | equity-report |
- | Version-by-version log + release facts | changelog |
- | Product showcase + pricing + screenshots + FAQ for browser | landing-page |
-
- Ambiguity examples that justify a one-liner:
- - "1.5 page career story with heavy visuals" -> ask "resume or portfolio?"
- - "2 page exec summary with metric tiles" -> ask "one-pager or equity-report?"
- - "5 page argument with several charts" -> ask "long-doc or portfolio?"
-
- ### Diagrams (primitives, not a separate template type)
-
- When the user asks for **a diagram inside** a long-doc / portfolio / slide (not a standalone document), route to `assets/diagrams/` rather than a template. Eighteen types ship there; `references/diagrams.md` section 1 «Selection» maps each to what it shows, and section 7 lists the AI-slop patterns to avoid. Read it before drawing. Extract the `<svg>` block from the chosen file and drop it into a `<figure>` inside the document.
-
- Three routes inside that file, by trigger:
-
- | Trigger | Section |
- |---|---|
- | Full-system panorama, control plane, roadmap, or owner map in one artifact | «Architecture boards». Do not inflate the single architecture figure past its node budget. |
- | A diagram that lives in the user's repo (README figure, "给项目画张架构图", updating an existing one) | «Maintained diagram assets». Evidence pass first, keep the `index.html` + PNG + `prompt.md` trio consistent, never redraw from memory or hand-edit the PNG. |
- | A standalone raster illustration or a redraw of a photo or screenshot | «Illustration briefs», plus the Illustrations rules below. |
-
- **Auto-select charts from data.** When content carries numbers, pick the chart type yourself and embed it without asking. Two house calls that differ from the common default: a ~100% share renders as a donut only up to 6 items, and 7 or more becomes a horizontal bar; a single time series whose absolute count changes dominate (not rate) renders as bars, not a line. When several types fit, prefer the one that shows variance most clearly. Always embed inside a `<figure>` whose caption states the insight, not the data range.
-
- ### Illustrations (host image model, not inline SVG)
-
- Inline diagrams above are vector SVGs you assemble by hand. For a standalone raster illustration, or a redraw of a figure, photo, or screenshot in the Kami look, delegate the drawing to the host's own image generation. Never call an external image API or require a key; rendering is the host's job.
-
- - If the running host exposes image generation, apply the brief below and render the image directly.
- - If image generation is unavailable, output the same complete brief as text. Route from observed capability, not a remembered list of host names.
-
- Brief: first state the claim the image must communicate, its destination and smallest display size, the accepted reference it should sit beside, and what must not appear. Then apply the Kami visual system: warm parchment (`#f5f4ed`) background, never pure white; one accent only, ink blue (`#1B365D`); all else warm gray with a yellow-brown undertone, no other colors; thin single-line geometric strokes and simple flat icons; no gradients, drop shadows, or 3D; serif labels; generous whitespace, composed like a figure in a well-typeset report. Full brief skeleton, icon rules, and QC checklist: `references/diagrams.md` «Illustration briefs».
-
- Switch to this path (instead of enlarging a hand-assembled SVG) when a figure needs more detail than SVG assembly holds at the target display width, typically web-article figures at teaching depth (see `references/diagrams.md` density tiers). When one deliverable needs several generated images, drive them through a single handoff file: one line per image (slot, aspect ratio, shared style anchor, prompt, status), generate in batches of at most 5, update the status column after each batch, and check existing generated output before regenerating. The style anchor is shared by the whole batch; per-image style drift is the failure mode.
-
- ## Step 2.1 · Source and material pass
-
- Run this before distilling or filling when the document depends on facts or materials outside the user's draft. Skip it for personal drafts where the user already supplied everything.
-
- **Source check** fires when the document names a company, product, person, release date, version, funding round, metric, market fact, or technical spec. Work from primary sources, note the source and date for facts that drive the document, and ask the user when sources conflict rather than choosing silently. `references/writing.md` «5. Sources before phrasing» owns the detail, including which current-sounding claims are banned until checked ("latest", "recent", "new", version numbers, launch dates, financial figures).
-
- **Material check** fires when the subject is a company, product, project, venue, or personal brand. Confirm what makes it recognizable before layout:
-
- | Need | Required when | Accept |
- |---|---|---|
- | Logo | Any branded document | User file or official SVG/PNG |
- | Product image | Physical product / venue / object | Official image, user image, or marked gap |
- | UI screenshot | App / SaaS / website / tool | Current screenshot, official product image, or user capture |
- | Brand colors | Branded one-pager / portfolio / deck | Official value, extracted asset value, or keep kami ink-blue |
- | Fonts | Only if brand typography matters | Official font, close system fallback, or kami default |
-
- A missing item gets a compact gap table and one question, never a generic stand-in, an approximated logo, or an invented value. `references/writing.md` «6. Materials serve recognition» carries the writing-side rules.
-
- Logo fallback: when the request names no logo but the brand profile has a `logo` path, fill the commented `.brand-logo` slot in `one-pager` / `portfolio` / `slides-weasy` per `references/brand-profile.md` Layer C. Expand `~` to an absolute path; if the file is missing or the template has no slot, leave it commented and render without a logo, never a broken image. An explicit logo in the current request always wins.
-
- ### Materials status block
-
- After the material check, output a structured status block before continuing. This is a one-shot transparency display, not a question:
-
- ```
- Materials status:
- - Logo: OK /absolute/path/to/client-logo.svg
- - Brand colors: OK #1B365D mapped to --brand
- - Product screenshot: MISSING (using a pure-text layout; no placeholder image)
- - UI screenshot: not required for this doc type
- ```
-
- Use `OK`, `MISSING`, or `not required`. If a required item is missing and no user input arrived, ask once with the gap table; otherwise continue silently.
+ | 1 page for investors, recruiters, or an executive summary | one-pager |
+ | 1 page of formal correspondence (sales, hiring, resignation, memo) | letter |
+ | Exactly 2 pages of career narrative with project bullets | resume |
+ | 3-6 visual-heavy pages showcasing projects | portfolio |
+ | 6-15 pages of sustained argument, low visual density | long-doc |
+ | Presentation flow, one assertion per slide | slides |
+ | Metrics dashboard plus thesis plus price or risk view | equity-report |
+ | Version-by-version release facts | changelog |
+ | Product showcase, pricing, screenshots, FAQ for a browser | landing-page |
- ## Step 2.5 · Distill raw content (if applicable)
+ Ask only in cases like "1.5 pages of career story, heavy visuals" (resume or portfolio?) or "2 pages of exec summary with metric tiles" (one-pager or equity-report?).
- **Auto-detect whether to distill.** Do not ask the user; judge from the input. Skip distill only when the content already maps one-to-one onto the template's sections with quantified metrics in place, or the user said "use as-is" / "直接用这个". When in doubt, run distill.
+ - **Changelog vs. release notes**: the changelog template is a styled document. GitHub release notes are a separate deliverable; use `/write`.
+ - **Landing page**: screen-first HTML, no PDF. Fill the `{{PLACEHOLDER}}` values and comment blocks and save a ready-to-serve file. Companion files (`landing-page-*.example`) and the production site mode (docs, help, releases, legal pages, or more than two locales) live in `references/design.md` Section 11. Keep project-specific release artifacts, payment providers, appcast rules, and private local paths out of Kami.
+ - **Diagrams inside a document** come from `assets/diagrams/` (eighteen types), not a template. `references/diagrams.md` section 1 picks the type; extract the `<svg>` block into a `<figure>`. The same file owns architecture boards, diagrams maintained in the user's repo, charts chosen from data (pick and embed them without asking), and generated raster illustrations.
+ - **Slides**: read `references/deck-preflight.md` before drafting.
- Distill acceptance: every factual claim, number, date, name, source, and material reference from the raw input must land either in a template section (per-doc structure in `references/writing.md`) or in a gap table of what the template needs but the content lacks. Share the gap table once; never guess to fill a gap.
+ ## 2 · Sources, materials, and content
- Example gap-check:
+ **Source check.** When the document names a company, product, person, release date, version, funding round, metric, market fact, or technical spec, work from primary sources, note source and date for the facts that drive it, and ask when sources conflict (`references/writing.md` «5. Sources before phrasing»). Skip it for personal drafts where the user supplied everything.
- | Template needs | Found | Missing |
- |---|---|---|
- | 4 metric cards | "8 years", "50-person team" | 2 more quantifiable results |
- | 3-5 core projects | 2 mentioned | at least 1 more with outcome |
- | Materials | logo file provided | product screenshot source |
+ **Material check.** A branded subject needs what makes it recognizable: logo, product image or current UI screenshot, and brand colors when the document is branded (`references/writing.md` «6. Materials serve recognition»). When the request names no logo but the brand profile has one, fill the commented `.brand-logo` slot in `one-pager` / `portfolio` / `slides-weasy` (expand `~` to an absolute path; leave the slot commented if the file is missing). An explicit logo in the current request always wins.
- Then proceed to Step 2.6 (slides) or the layout note (all other doc types) with structured, distilled content.
+ **Gap report.** Everything the template needs that the input lacks, missing facts and missing materials alike, goes into one compact table shown once, with one question only when a missing item would change the deliverable. Inside the document, mark a gap as `[DATA NEEDED: what]`. Never fill a gap with a guess, a stock image, an approximated logo, or an invented value.
- ### Persist the distilled content as a content IR (new documents)
+ **Distill.** Unless the content already maps one-to-one onto the template sections or the user said to use it as-is, distill it. Every factual claim, number, date, name, source, and material reference from the input must land in a template section or in the gap report.
- When building a new document (not a text tweak on an existing one), write the distilled result and the locked execution contract to a `content.json` next to your working HTML before filling:
+ **Content IR (new documents).** Write the distilled content and the locked contract to `content.json` next to the working HTML before filling. Read `references/schemas/<type>.json` first: its `$comment` notes carry the per-field quality bar. The envelope is strict: only `type`, `lang` (`cn`, `en`, `ko`, `zh-TW`, ...), `brief`, and `content`.
```json
{
"type": "resume",
"lang": "cn",
"brief": {
"audience": "Hiring manager for a senior product role",
"job": "Earn an interview by proving scope and outcomes",
"template": "resume",
"formats": ["html", "pdf"],
"page_target": 2,
"narrative": "Scope first, then evidence, then fit",
"required_facts": ["team size", "measured outcomes"],
"required_assets": [],
"acceptance_checks": ["two pages", "all atomic facts survive"],
"preserve": [],
"explicit_deviations": []
},
"content": { ... }
}
```
- `type` is one of the schema names in `references/schemas/` (one-pager, letter, resume, long-doc, portfolio, slides, equity-report, changelog, landing-page). `brief` records why this artifact exists and how it will be judged; it is not audience copy. Only `brief.required_assets` joins the content-to-HTML coverage gate. For a visual repair, add `target`, `evidence`, and `preserve` so the fix cannot silently grow beyond the reported surface. Older IR files without `brief` remain valid, but every new document should write it. Read the matching content schema before writing: its `$comment` notes carry the per-field quality bar. Then validate before any layout work:
-
- The top-level envelope is strict: it contains only `type`, `lang`, `brief`, and `content`.
- Use a language tag such as `cn`, `en`, `ko`, or `zh-TW`; misspelled tags and extra
- top-level fields fail before template filling begins.
-
- ```bash
- python3 scripts/build.py --check-content content.json
- ```
-
- Fix schema errors by fixing the content (or asking the user for the missing fact), not by loosening structure. After filling the template, re-run with the filled HTML to confirm no fact was dropped on the way in:
-
- ```bash
- python3 scripts/build.py --check-content content.json filled.html
- ```
-
- Values longer than 80 characters are treated as prose you may rephrase; short atomic values (names, metrics, dates, bullets) must survive verbatim.
-
- ## Step 2.6 · Deck pre-flight (slides only)
-
- Slides only. Every other doc type skips to Step 2.7.
-
- Load `references/deck-preflight.md` before drafting for path selection (WeasyPrint HTML by default), page size, unresolved delivery choices, and slide content rules. Its intake follows the shared question budget.
-
- ## Step 2.7 · Layout note (transparent, non-blocking)
-
- Before loading specs and filling the template, write a short editor-style note stating the layout intent: template choice, length target, narrative arc, embedded diagrams, material status, and output formats. Match the document's language. Keep it under 80 words, written as prose, not a status panel. Continue immediately after; do not wait.
-
- Example (CN):
-
- > 使用中文财报模板,制作 2 页 A4,输出 HTML 和 PDF。内容依次为投资判断、目标价、估值、催化剂与风险,加入营收趋势和 FY26 收入构成图,使用已有 Logo,缺少产品图的页眉采用文字。
-
- Example (EN):
-
- > Layout intent: Equity Report (EN), two pages A4. Open with thesis and price target, run through valuation (DCF and comparables), close on catalysts and risks. A revenue line chart and an FY26 waterfall sit mid-doc. Logo is in hand; product image is absent, so the header stays text-only. Output: HTML and PDF.
-
- If the user pushes back, adjust; otherwise proceed to Step 3.
-
- ---
-
- ## Step 3 · Load the right amount of spec
-
- Pick the tier that matches the task. Default to the lowest tier that covers the work.
-
- | Tier | When | Read |
- |---|---|---|
- | **Content-only** | Updating text, swapping bullets, translating an existing doc. CSS stays untouched. | `CHEATSHEET.md` only |
- | **Layout tweak** | Adjusting spacing, moving sections, changing font size within spec. CSS touched. | `CHEATSHEET.md` + template (tokens already inline) |
- | **New document** | Building from scratch or from raw content. | Full design spec + writing spec + template + `references/schemas/<type>.json` |
- | **Resume content** | Resume-specific bullet structure, project framing, scope-result-outcome rules. | `resume-writing.md` + template |
- | **Sources / materials** | Company, product, market, launch, funding, specs, or branded subject. | `writing.md` source rules + user/source material |
- | **Deck (>20 slides)** | Long presentation needing Part Divider, Code Cards, section headers. | Full design spec + Deck Recipe (design.md section 8) |
- | **Troubleshoot** | Rendering bug, font issue, page overflow. | `production.md` (+ design spec if CSS is the cause) |
- | **Anti-patterns** | Reviewing AI-generated drafts before shipping. | `anti-patterns.md` (nine-category checklist) |
- | **Diagram** | Embedding SVG in a doc, or maintaining a repo-owned diagram (trio: HTML + PNG + prompt.md). | `diagrams.md` (has its own token map); add `references/mermaid.md` when the source is Mermaid text, and `references/production.md` Part 4 when a figure renders wrong in the PDF |
-
-
- ## Step 4 · Fill content into the template
-
- - Copy the template into your working directory; don't write HTML from scratch
- - **CSS stays untouched during content fill.** Layout adjustments go through the Layout-tweak tier (Step 3) and stay within spec; any real style change syncs `references/design.md` and the sibling templates, never a single file
- - Content follows `writing.md`: data over adjectives, distinctive phrasing over industry clichés
- - Avoid patterns listed in `references/anti-patterns.md`: emptiness, fabrication, mimicry, excess, source gaps, tone contamination, landing page, image slots, slides
- - **Before filling, read the quality bar for your document type** in `writing.md` section "Quality bars by document type". Structure is necessary but not sufficient: a resume bullet needs Action + Honest Scope + Observable Result, with business outcomes when relevant; an equity report needs variant perception + quantified catalysts; slides need assertion-evidence titles. Meeting the quality bar is as important as filling every placeholder.
-
- ### Do not generate
-
- These are the most common AI document failures. Cross-reference `references/anti-patterns.md` for the full list; `--check-placeholders` catches leftover template tokens mechanically.
-
- - Do not invent metrics, financial data, or statistics; mark gaps with `[DATA NEEDED: description]`
- - Do not use stock-image descriptions as image placeholders ("A diverse team collaborating in a modern office")
- - Do not pad content to fill template slots (a resume with 3 real projects does not need 5 fabricated ones)
-
- ### Fill PDF metadata (WeasyPrint reads these into the PDF)
-
- Every template has meta placeholders in `<head>`. Fill all four before building:
-
- | Placeholder (CN) | Placeholder (EN) | Rule |
- |---|---|---|
- | `{{作者}}` | `{{AUTHOR}}` | Resume/letter/portfolio: use the person's name from the doc. All others: leave as-is (build script infers from git config or env) |
- | `{{摘要}}` | `{{DESCRIPTION}}` | Extract one sentence (≤150 chars) from the first 2 paragraphs |
- | `{{关键词}}` | `{{KEYWORDS}}` | 3-5 keywords from the title + section headings, comma-separated |
- | `{{文档标题}}` / `{{信件主题}}` etc. | `{{DOC_TITLE}}` / `{{LETTER_SUBJECT}}` etc. | Infer from the H1 or `.header .title` text |
-
- `<meta name="generator" content="Kami">` is already fixed in the template; do not change it.
+ `type` is a schema name in `references/schemas/` (one-pager, letter, resume, long-doc, portfolio, slides, equity-report, changelog, landing-page). For a visual repair, add `target`, `evidence`, and `preserve` to `brief`. Validate before layout with `python3 scripts/build.py --check-content content.json` and fix errors by fixing the content (or asking for the fact), never by loosening structure. Short atomic values (names, metrics, dates, bullets) must survive into the document verbatim; values over 80 characters may be rephrased.
- **Author inference**: `build.py` automatically sets PDF `/Author` metadata from:
- 1. `git config user.name` (primary)
- 2. `KAMI_AUTHOR` environment variable (fallback)
- 3. `"Kami"` (final fallback)
+ ## 3 · Read the right amount
- For personal documents (resume/letter/portfolio), the HTML `<meta name="author">` should match the person's name in the content. For non-personal documents (one-pager/long-doc), leave the placeholder as-is and let the build script infer it.
+ Read the lowest tier that covers the task. The templates already carry every token and component, so a new document does not need the full design spec.
- ## Step 4.1 · Per-page density target (multi-page templates only)
+ | Task | Read |
+ |---|---|
+ | Content-only change | `CHEATSHEET.md` |
+ | Layout tweak within spec | `CHEATSHEET.md` + the template |
+ | New document | the template + `CHEATSHEET.md` + `references/schemas/<type>.json` + the `references/writing.md` sections for that type («Per-document strategies», «Quality bars by document type»); open `references/design.md` only for the component or rule you are about to change |
+ | Resume | + `references/resume-writing.md` |
+ | Slides, long-doc, portfolio, equity-report, changelog | + `references/writing.md` «Page density» |
+ | Slides | + `references/deck-preflight.md` and the `references/design.md` section 8 «Deck Recipe» it points to |
+ | Diagram | `references/diagrams.md`; `references/mermaid.md` when the source is Mermaid text |
+ | Company, product, market, or branded subject | `references/writing.md` sections 5-6 |
+ | Rendering bug, font issue, overflow | `references/production.md` Part 4 (and the design spec if CSS is the cause) |
+ | Reviewing an AI-generated draft | `references/anti-patterns.md` |
- 适用:slides-weasy / long-doc / portfolio / equity-report / changelog。不适用 resume / one-pager / letter(这些有独立的长度合约)。
+ ## 4 · Fill the template
- 正文页填充率目标 60-80%。封面 / 目录 / 末尾署名页豁免。这条规则解决的是 AI 生成多页文档时最常见的 draft 缺陷:把内容拆得太散,结果几页都填不满。
+ - Copy the template into the working directory; never write HTML from scratch. CSS stays untouched during a content fill. A layout change stays within spec, and a real style change moves `references/design.md` and the sibling templates together, never one file.
+ - Meet the quality bar for the type in `references/writing.md` «Quality bars by document type»: a resume bullet needs action, honest scope, and an observable result; an equity report needs variant perception and quantified catalysts; slides need assertion titles. Structure is necessary, not sufficient.
+ - Do not invent metrics, financial data, or statistics; do not describe stock images as placeholders; do not pad slots (three real projects do not become five). Avoid the patterns in `references/anti-patterns.md`.
+ - Tables separate rows with whitespace first and neutral hairlines second; decoration earns its place only by encoding data, state, grouping, or a relationship (`references/design.md` «Table (kami-table)» and «Subtractive rule»).
+ - Resume: run the recruiter pass in `references/resume-writing.md` before building.
+ - Mathematics is strict LaTeX: author formulas only as inline `\( ... \)` or display `\[ ... \]` in rendered body text, never as Unicode approximations, ASCII fractions, screenshots, or raw TeX on the page. `--deliver` renders them to MathJax SVG in place; it needs Node.js 20 or 22+ and `bash scripts/ensure_mathjax.sh` once.
+ - Code blocks with `class="language-*"` are highlighted when optional `Pygments` is installed; without it they render monochrome.
- ### Items-per-page contract
+ Fill the four metadata placeholders in `<head>`; WeasyPrint writes them into the PDF:
- | Template | Typical body page | Hard floor (merge if below) |
+ | CN | EN | Rule |
|---|---|---|
- | slides-weasy | 1 assertion title + 3-5 supporting items, or 1 chart + 2-3 callouts | <3 items and no chart → merge into adjacent slide |
- | long-doc | 1 chapter heading + 2-4 paragraphs + at most 1 figure | Chapter renders to <40% page → merge into neighbor chapter |
- | portfolio | 1 project header + 1 hero image + 3-5 outcome bullets | No image and <3 outcomes → merge with adjacent project |
- | equity-report | 1 section + 1 table/chart + supporting prose | Only a 2-row table on the page → combine sections |
- | changelog | 1 version block + 4-8 entries | Version has <4 entries → place on the same page as the prior version |
-
- ### Sparse-page merge rule
-
- Before finalizing, scan the draft. Any body page that would render under 50% full → apply one of, in order:
-
- 1. Merge upward into the previous section.
- 2. Merge downward into the next section.
- 3. Remove the page and fold its one useful assertion or proof into a neighbor.
- 4. Convert existing information to a small diagram or table only when that form is clearer even without the density problem.
-
- Forbidden ways to "fill" a sparse page: padding with filler prose, repeating the heading as a sentence, inventing statistics, restating the prior page in different words, or adding a callout, chart, icon, or image whose only job is to occupy space. If the merge options don't apply, the page itself shouldn't exist.
-
- ### Last-page exemption
-
- The last body page is allowed to run 40-60% fill. Forcing balance on the last page usually means padding. The colophon / closing slide may have any fill level.
-
- ### Verify after build
-
- ```bash
- python3 scripts/build.py --check-density # flags >25% (WARN) / >50% (SPARSE) trailing whitespace
- ```
-
- If a body page (not cover, not last page) gets a SPARSE warning, treat it as a draft defect and re-author with the merge rule.
-
- ## Step 4.2 · Resume recruiter pass (resume only)
-
- Mechanical checks (`--check-placeholders`, `--check-resume-balance`, `--check-density`) validate structure and layout, not prose. A resume can pass all of them and still read broken. After filling and before building, reread every project card the way a recruiter would, against the row definitions in `references/resume-writing.md` ("What goes in each row"): Role carries your position in the project, not background alone; Actions are verb-led, one concrete approach per sentence; Impact reads as an outcome, not a restatement of the process. One cross-row check on top: no row repeats another row's information.
-
- Fix a failing row by rewriting from the source material. If the source cannot support a row (for example, no outcome fact exists), ask the user for the missing fact. Do not pad, and do not fall back to generic claims ("保障稳定运行", "improved efficiency").
-
- This pass is internal: run it silently; surface it only when a row cannot be fixed without new information from the user.
-
- ## Step 4.3 · Table editorial pass (any table)
-
- Run this whenever the artifact contains a table. A Kami table should separate rows through alignment and breathing room first; rules are only quiet guides.
-
- - **One chromatic system:** keep table text in the neutral ink hierarchy and use `var(--border)` for header, body, and total-row rules. Do not color values by category, use `--brand` borders, add per-column hues, tint the header, or draw vertical rules. Use weight, signs, and labels for meaning instead.
- - **Hairline hierarchy:** header and total rules are `0.6pt`; body row rules are `0.25pt`. If the line is noticed before the values, it is too heavy. Total rows gain weight from typography plus the slightly stronger neutral rule, not from a blue line.
- - **Vertical padding floor:** normal tables target at least `6pt` on headers and `5pt` on cells. One-page and resume templates may step down once to `5pt` / `4pt` after a real render proves the page contract needs it. `.compact` still keeps at least `3pt` on headers and `2.5pt` on cells.
- - **Compact is earned:** use `.compact` for five or more columns, eight or more body rows, or a verified page-fit constraint. Do not use it by reflex, and do not reduce padding again before merging or re-authoring nearby content.
- - **Striping is exceptional:** start without `.striped`. Add its neutral fill only when a table has at least eight body rows and the normal-size render still makes row tracking difficult. Do not use striping merely to decorate the table.
-
- Verify the rendered page at normal viewing size. Each row must read as a separate unit without the rules forming a grid, the first and last lines of text must not crowd a rule, and changing the padding must re-pass neighboring pages plus the page-count contract.
-
- ## Step 4.4 · Subtractive visual pass
-
- Before rendering, remove every visual primitive that does not encode data, state, grouping, or a relationship. Kami hierarchy should come from type, whitespace, labels, alignment, and restrained fills before it comes from a line.
-
- - Do not add decorative eyebrow ticks, short cover or contact rules, side-border accents on headings, quotations, or callouts, or fake dash bullets.
- - A filled callout or analyst box needs only its fill, padding, and typography. A quotation needs only indentation, olive text, and reading space. A section title needs only type scale and margin.
- - Keep rules that do real work: table hairlines, chart axes, diagram connectors, input boundaries, full-width separators between content regions, and current-state indicators.
- - Use the deletion test: hide the line. If meaning, state, grouping, and navigation remain clear, delete it. Restore spacing rather than replacing it with another ornament.
-
- Render every affected page after the pass. Confirm that the removed primitive did not collapse the intended pause, alter the page-count contract, or leave neighboring elements visually unanchored.
-
- ## Step 4.5 · Auto-select output format
+ | `{{作者}}` | `{{AUTHOR}}` | Resume, letter, portfolio: the person's name from the document. Others: leave it, the build infers it from `git config user.name`, then `KAMI_AUTHOR` |
+ | `{{摘要}}` | `{{DESCRIPTION}}` | One sentence (≤150 chars) from the first two paragraphs |
+ | `{{关键词}}` | `{{KEYWORDS}}` | 3-5 keywords from the title and section headings |
+ | `{{文档标题}}` etc. | `{{DOC_TITLE}}` etc. | From the H1 or `.header .title` |
- Do not ask the user which format to export. Decide from context:
+ Keep `<meta name="generator" content="Kami">` as is.
- | Signal | Output | Why |
- |---|---|---|
- | Any document request | HTML + PDF | PDF is the default deliverable, HTML is the source |
- | Slides / PPT / deck | HTML + PDF; add PPTX only when explicitly requested as editable output | PDF is the default presentation format |
- | "分享" / "发朋友圈" / "share" / "post" / "preview" | + PNG | Social platforms and messaging need images |
- | "嵌入" / "插图" / "embed in another doc" | PNG only | Used as material inside other documents |
- | User explicitly says a format | Follow the user | Explicit request overrides auto-selection |
+ **Output formats.** Do not ask; decide from context. Any document: HTML + PDF (PDF is the deliverable, HTML the source). Slides: HTML + PDF, plus PPTX only when an editable deck is requested. "分享 / 发朋友圈 / share / post / preview": add PNG. "嵌入 / 插图 / embed in another doc": PNG only. Landing page: the static HTML file. An explicit format request overrides all of this.
- PDF is the default for document templates; an explicit format request takes precedence. Landing pages ship as a ready-to-serve static HTML file. Add PPTX only when the user explicitly needs an editable deck. PNG follows sharing context.
+ ## 5 · Deliver
- ## Step 5 · Build & verify
+ One command finishes a document. Run it from the document's directory, fix every `ERROR`, and re-run until it reports `READY`:
```bash
- python3 scripts/build.py --verify # build all templates + page count + font check + slides
- python3 scripts/build.py --verify resume-en # single target full verification
- python3 scripts/build.py landing-page # screen-first static HTML template check
- python3 scripts/build.py --verify slides # single slide deck verification
- python3 scripts/build.py --check-placeholders path/to/filled.html
- python3 scripts/build.py --check-markdown path/to/filled.pdf
- bash scripts/ensure_mathjax.sh # strict TeX renderer dependency
- python3 scripts/math_render.py --in-place filled.html # TeX -> MathJax SVG in delivered HTML
- python3 scripts/math_render.py --check filled.html # fail on raw/unrendered TeX
- python3 scripts/build.py --check-content content.json path/to/filled.html
- python3 scripts/build.py --check-visual path/to/filled.pdf
- python3 scripts/build.py --check-fonts path/to/filled.pdf # which family actually drew the CJK text
- python3 scripts/build.py --check-style path/to/filled.html # template rules against the produced document
- python3 scripts/build.py --check-resume-balance path/to/resume.pdf
- python3 scripts/build.py --check-density path/to/filled.pdf # page whitespace (one-page docs included)
- python3 scripts/build.py --check-density # repo sweep (skips cover and template skeletons)
- python3 scripts/build.py --check-rhythm slides slides-en # warn on monotonous slide sequences
- python3 scripts/build.py --doctor # installed render/check/font capability report
- python3 scripts/build.py --check # lint + token/theme + public-site fact checks
+ python3 scripts/build.py --deliver filled.html content.json
```
- > **Strict LaTeX mathematics**: Use only `\( inline \)` / `\[ display \]` as formula source. The delivered HTML/PDF must contain MathJax SVG, not Unicode pseudo-formulas, raw TeX, or formula screenshots. Run `ensure_mathjax.sh`, `math_render.py --in-place`, and `math_render.py --check` before render/hand-off.
-
- > **Screen verify**: `--check-density` is a print gate. For ANY browser-delivered surface (landing page, docs page, dashboard, testimonial wall, article index), screenshotting the rendered page across the responsive matrix in every locale is a hard step before declaring done, not an on-request extra: scan for line widows, sparse blocks, and single-line-surface wraps, and report the result. Do not wait for the user to ask "does it work on mobile". See `references/design.md` Section 12 «Responsive screenshot verification».
-
- > **Perceptual verify (PDF deliverables)**: geometry checks cannot see a fallback glyph or an arrow crossing a label. Before shipping a filled PDF, run `python3 scripts/build.py --check-visual path/to/filled.pdf`, then view every exported page image against the printed checklist. One hit means a whole-document sweep for that class of issue. If your host cannot view images, send the image paths and checklist to the user instead of skipping the pass. `--check-visual` runs the font gate for you and prints its verdict above the checklist.
-
- > **Font verify (CJK deliverables)**: a missing CJK serif produces no fallback boxes. It silently substitutes a sans that still reads, so the page passes an eyeball pass while carrying typography the parchment metrics were never tuned for, and the result reads heavy and flat without anything looking obviously broken. `--check-fonts` settles it from the rendered PDF's own span table: it names the family that drew the body ideographs and fails on a sans substitution or on text split across two families. Never report a CJK document as visually verified without it, and never assume a sandbox has the fonts: the commercial TsangerJinKai02 files never ship inside the skill package.
-
- > **Fresh review**: after the mechanical and perceptual checks pass, review once from the artifact contract rather than from the builder's rationale. Read `brief`, the content-coverage result, and the rendered evidence; check every acceptance item and every `preserve` boundary; report P0/P1 findings with the page, viewport, or element that proves them. Use an isolated reviewer when the host supports one. Otherwise reload those three evidence surfaces and do a distinct second pass. Fix P0/P1 findings before handoff; do not let the same pass that made the artifact approve its own intentions.
-
- Source templates intentionally keep `{{...}}` fields. Run placeholder checks on completed documents, not on the template library.
-
- For Markdown-sourced long documents, also run `--check-markdown` on the rendered PDF. It catches visible raw `---`, `**bold**`, and inline-code backticks that should have been converted or removed before delivery.
-
- Visual anomalies (tag double rectangle, font fallback, page break issues) -> `production.md` Part 4.
+ It checks the HTML (placeholders, strict math rendered in place, Markdown residue, template style, content coverage), renders the PDF next to it, then checks the PDF (page contract, resume balance, the font that actually drew CJK text, residue, density, orphans) and exports page images. `WARN` lines point at where to look, not at failures. `GAP` lines are the `[DATA NEEDED]` markers you must report.
- ### Definition of done
+ Then do the part no script can: open every page image and walk the printed checklist. One hit means a whole-document sweep for that class of issue. If the host cannot view images, send the image paths and the checklist to the user instead of skipping the pass. A missing CJK serif shows no fallback boxes, only a heavier, flatter page, which is why the font gate exists; never call a CJK document visually verified without it.
- A task is done when the user receives, in the closing message:
+ Other surfaces:
- 1. The path of every deliverable, in every promised format (Step 4.5).
- 2. Which checks ran and their results, including the page-count contract.
- 3. Every remaining `[DATA NEEDED]` gap, listed explicitly. Never declare done with an unreported gap.
- 4. The visual verdict, stated honestly by surface: for PDFs the `--check-visual` pass status (which includes the font gate); for screen surfaces the responsive-matrix screenshot result; when rendering could not be inspected, say "build verified, visuals unconfirmed", not "done".
- 5. For documents containing mathematics, the strict LaTeX result: MathJax SVG rendering and `scripts/math_render.py --check` both passed.
+ - **Landing pages and any browser surface**: `--deliver` checks the HTML only. Screenshot the responsive matrix in every shipped locale before calling it done (`references/design.md` «Responsive screenshot verification»); do not wait for the user to ask about mobile.
+ - **Editable PPTX**: `python3 scripts/build.py --verify slides` (or `slides-en`) and `--check-rhythm`.
+ - **Missing dependencies or fonts**: `python3 scripts/build.py --doctor` reports what is installed; `bash scripts/ensure-fonts.sh` recovers CJK fonts (the commercial TsangerJinKai02 never ships inside the skill package). Render failures and their fixes: `references/production.md` Part 4.
- ## Fonts
+ **Fresh review.** After `READY` and the image pass, review once from the contract rather than from your own rationale: reread `brief`, the coverage result, and the page images; check every acceptance item and `preserve` boundary; fix P0/P1 findings, each tied to the page or element that proves it. Use an isolated reviewer when the host has one.
- When `--check-fonts` reports a sans substitution or a split family, or a render fails on a missing font: run `bash scripts/ensure-fonts.sh`, then read `references/production.md` Part 1 «Fonts» for the stacks, the fallback chains, and where the recovered files land. Waiting for visible fallback glyphs is not a strategy; the common failure has none.
+ **Definition of done.** The closing message gives:
- Two facts worth carrying here: the commercial TsangerJinKai02 files stay in the repo for local preview and CDN fallback but never go inside a Claude Desktop skill ZIP, and `Source Han Serif KR` is the real family name inside the OTFs, so it must stay in the KO chain for offline fontconfig to resolve it.
+ 1. The path of every deliverable, in every promised format.
+ 2. The `--deliver` verdict and page count against the contract.
+ 3. Every `[DATA NEEDED]` gap and every assumption you made, listed.
+ 4. The visual verdict stated honestly: when page images could not be inspected, say "build verified, visuals unconfirmed", not "done".
## Feedback protocol
When the user gives visual feedback ("looks off", "太挤了", "not elegant"), inspect the current render before asking them to choose a value. The render is the evidence; the user's negative label is the acceptance signal.
- 1. Name the concrete defect in one sentence: page or surface, viewport or state, and whether the problem is density, hierarchy, alignment, type, color, cropping, or text fit.
- 2. Lock the repair boundary: `target` is allowed to change; `preserve` names the adjacent pages, sections, content, and shared tokens that must remain stable. Ask only when two plausible targets would produce materially different artifacts.
+ 1. Name the concrete defect in one sentence: page or surface, viewport or state, and whether it is density, hierarchy, alignment, type, color, cropping, or text fit.
+ 2. Lock the repair boundary: `target` is allowed to change; `preserve` names the adjacent pages, sections, content, and shared tokens that must stay stable. Ask only when two plausible targets would produce materially different artifacts.
3. Make the smallest content, geometry, spacing, typography, crop, or token change that fixes the defect. Never hide a content problem by shrinking type first.
4. Verify the affected matrix rather than one screenshot:
- PDF: target page, neighboring pages, total page count, font result, and every locale or template variant reached by a shared token.
- - Screen: the breakpoint, tablet, and baseline matrix in `references/design.md` «Responsive screenshot verification»; every shipped locale; affected default, focus/selected, loading, empty/error, and transition state only when the surface actually has them.
+ - Screen: the breakpoint, tablet, and baseline matrix in `references/design.md` «Responsive screenshot verification»; every shipped locale; affected default, focus/selected, loading, empty/error, and transition states only when the surface has them.
- PPTX: editable source plus a rendered PDF or opened-deck inspection.
- Generated asset: target slot at its smallest display size plus sibling assets in the same deliverable.
- If no rendered evidence exists and the feedback still leaves two materially different fixes, ask once by naming the current property and offering two in-spec alternatives. Never say "I'll adjust the spacing" without naming the exact property and its new value.
-
- **Escalate after two rounds.** If the same element is still not approved after two adjustment rounds, stop nudging values: produce one comparison artifact instead: the current state plus 2-3 labeled variants (A/B/C) of the same content in the product’s actual frame and background, retaining neighboring components and changing only the compared property, and let the user pick. For choices with no objective criterion (typeface, accent color, logo), skip the nudging entirely and start with a specimen sheet: up to 5 candidates, each a labeled half-page block of identical title-plus-paragraph content. One round of "pick one" converges where five rounds of "try again" do not; after the pick, apply it everywhere and rebuild affected demos in the same round.
+ Never say "I'll adjust the spacing" without naming the exact property and its new value.
- ---
+ **Escalate after two rounds.** If the same element is still not approved after two adjustment rounds, stop nudging values and produce one comparison artifact: the current state plus 2-3 labeled variants (A/B/C) of the same content in the product's actual frame and background, changing only the compared property. For choices with no objective criterion (typeface, accent color, logo), start there: a specimen sheet of up to 5 labeled half-page blocks with identical title-plus-paragraph content. After the pick, apply it everywhere and rebuild what it touches in the same round.
## When not to use this skill
- - User explicitly wants Material / Fluent / Tailwind default - different design language
- - Need dark / cyberpunk / futurist aesthetic (this is deliberately anti-future)
- - Need saturated multi-color (this has one accent)
- - Need cartoon / animation / illustration style (this is editorial)
- - Web dynamic app UI (this is for print / static documents)
+ - The user explicitly wants Material, Fluent, or a Tailwind default: a different design language.
+ - Dark, cyberpunk, or futurist aesthetics (this is deliberately anti-future).
+ - Saturated multi-color palettes (this has one accent).
+ - Cartoon, animation, or illustration style (this is editorial).
+ - Dynamic web app UI (this is for print and static documents).