Compare commits

..
Author SHA1 Message Date
Abdul WahabandCursor 4ce2f451db Remove evidence images from the diff; they live on the pr-evidence branch
AI-assisted change (Cursor), prepared under maintainer direction.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 22:14:10 +05:00
Abdul WahabandCursor 0cce8456e2 Address review findings on the provenance gate
- Hoist the provenance rule out of the fix disposition into its own
  paragraph binding rebuild and fix alike, gated before either round's
  result goes back for review or verdict (Bugbot: rebuild skipped the
  scan when its fresh review shipped).
- A scan-flagged raster gets the record it is missing embedded, exact
  prompt for produced, origin for sourced/stock/pre-existing; deletion
  is reserved for abandoned rasters, never scan hits (Bugbot: gate hit
  non-generated assets on extensions).
- Document the scan command with its required directory argument
  (Greptile: literal command exited before scanning).
- Align the FINISH line on the provenance token.

AI-assisted change (Cursor), prepared under maintainer direction.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 19:45:31 +05:00
Abdul WahabandCursor cafe88ffa8 Add cursor-control-9 comp vs final screenshots for PR evidence
AI-assisted change (Cursor), prepared under maintainer direction.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 19:40:01 +05:00
Abdul WahabandCursor 4badffd1f0 Add cursor-control-8 comp vs final screenshots for PR evidence
AI-assisted change (Cursor), prepared under maintainer direction.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 19:38:55 +05:00
Abdul WahabandCursor 947a8507f2 Fix: keep raster provenance through the finish-review fix loop
Three runs (two harnesses) showed the parent generating production
rasters after the producer returned: no exact embedded prompt, no
inventory row, orphan files. The asset contract in visualize.md was
phase-scoped to the build while new-work.md's fix loop licensed
"produce the named assets" with no rules attached.

- visualize.md: name the provenance contract, require the exact tool
  payload, and scope it to the run, fix rounds and rebuilds included.
- new-work.md: bind fix/rebuild rasters to the contract, add an
  embed-prompt --scan step before the verdict round, and extend the
  FINISH line to carry the condition through long builds.
- embed-prompt.mjs: add --scan mode listing rasters missing a prompt
  (exit 3 when any), reusing the existing read path.

AI-assisted change, prepared with Cursor under maintainer direction.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 19:18:22 +05:00
4 changed files with 50 additions and 6 deletions
+1 -1
View File
@@ -28,7 +28,7 @@ Expect: the original request; the confirmed user answers; the artifact path(s);
0. **Evidence.** Before any other check, verify the required captures exist and every capture is valid. Required: the platform's full viewport set (web: `desktop.png` and `mobile.png`; native: one capture per shipped device class), plus every capture the calling brief names as required, a reported user viewport (`user-<width>.png`) included. Valid: no black or blank regions, content matching what the filename claims (a visit capture showing the About section is invalid), the document top visible where the file claims a full page, dimensions that make sense for the named viewport. A required capture that is absent fails exactly like one that is malformed: a viewport nobody captured is a viewport nobody inspected, and it cannot ship. When any capture fails, the whole review changes shape: return `disposition: recapture` as the first line, then one section, `recapture`, listing each missing or invalid file and what a valid capture of it shows, and stop. Never build a matrix on malformed evidence; a verdict derived from a broken capture launders the breakage into an approval, and the parent owes you a full re-review on valid captures, not a scoring round.
1. **Persistence.** PRODUCT.md exists. On a comp-led build, `.impeccable/review/hero-repro.png` exists: the hero reproduction checkpoint's capture at the comp's own dimensions; its absence means the reproduction phase ran unproven, a material finding. When DESIGN.md predates this build (an extension or redesign), it matches the built world; on a new world it is written after this review by the documenter, so its absence here is not a finding. When comp-round comps exist under `.impeccable/mocks/`, an approval record exists too: the surface brief naming the approved comp, or an `approved` flag in its sidecar. Comp-round comps with no recorded pick mean the approval point was skipped, a material finding. Files under `.impeccable/mocks/decision/` are exempt: they are the direction round's dealt hand, produced before any comp round, and imply no approval whatever the build path; a code-led build has no comp round at all.
2. **Fidelity.** Against your own element inventory of the approved comp, never against the contract's summary of it: topology, reading order, focal scale, overlaps and z-order, density, signature geometry, the primary action's treatment (a CTA the comp physically works, dissolves, or stamps is a signature element; its plain-rectangle rendition is contradicted), navigation items and icons, headline levels and scale relationships. Classify every salient element: match, acceptable adaptation, missing, contradicted, or added without approval. Three rows are mandatory in every matrix. TYPE: the display lettering's character, compression, width, weight, contrast, terminals, against the comp's; a face of a different character is contradicted however the layout matches. MATERIAL: an element rendered as flat CSS or clean vector where the comp shows painted, textured, dimensional, or photographic material is contradicted regardless of placement; medium is part of the promise. GROUND: the page field's value and temperature against the comp's, sampled from pixels on both sides when tooling allows rather than judged from memory, and read as the net on-screen result where a texture or tile paints over the base color; a ground warmer or cooler than the comp's is contradicted however faithfully the layout matches, and drift toward the rendition prior (warm cream on light grounds, blue-black slate on dark) is the direction to hunt. With no approved comp, TYPE and MATERIAL do not lapse: judge them against the contract's OWN-WORLD and the world's real materials, and treat faked physicality (CSS bevels, embossing, stamped-metal or chalk effects imitating a material the page never renders) as contradicted on its face; imitation material is the single most reliable mark of machine-made design. GROUND narrows rather than lapses: with no comp to sample, a color OWN-WORLD names is the target and the same warmer-or-cooler judgment applies; when OWN-WORLD names none, there is no GROUND authority, and the review says so in place of a verdict, because a target the reviewer invents turns the check into taste. A critique-reference comp on such a build is provocation, not spec: no element matrix, no adaptation citations, no asset obligations; its one contribution is what the image dared that the build did not, and dares worth adopting enter material_fixes as ordinary ordered fixes. An adaptation counts as intentional only when it cites the user answer, surface brief, accessibility need, or product truth that forced it; an uncited deviation is a defect. A missing signature element, a changed topology, or content added without approval fails fidelity and outranks every craft point in material_fixes. When MATERIAL is contradicted on the focal element, or contradiction is the page rather than the exception, stop ordering repairs: make the first material fix a rebuild directive naming the comp regions to re-derive and the assets to produce; a list of patches against a rejected page launders the rejection into an approval. A fix that requires producing an asset says so explicitly ("produce: <region> as a raster asset"), never phrased as a style adjustment the parent will answer with CSS. The comp is the spec for composition, topology, element inventory, density, lettering character, and material; it is not a pixel spec for semantics, accessibility, or responsive reflow, and that allowance covers translation, never replacement.
2. **Fidelity.** Against your own element inventory of the approved comp, never against the contract's summary of it: topology, reading order, focal scale, overlaps and z-order, density, signature geometry, the primary action's treatment (a CTA the comp physically works, dissolves, or stamps is a signature element; its plain-rectangle rendition is contradicted), navigation items and icons, headline levels and scale relationships. Classify every salient element: match, acceptable adaptation, missing, contradicted, or added without approval. Two rows are mandatory in every matrix. TYPE: the display lettering's character, compression, width, weight, contrast, terminals, against the comp's; a face of a different character is contradicted however the layout matches. MATERIAL: an element rendered as flat CSS or clean vector where the comp shows painted, textured, dimensional, or photographic material is contradicted regardless of placement; medium is part of the promise. With no approved comp, TYPE and MATERIAL do not lapse: judge them against the contract's OWN-WORLD and the world's real materials, and treat faked physicality (CSS bevels, embossing, stamped-metal or chalk effects imitating a material the page never renders) as contradicted on its face; imitation material is the single most reliable mark of machine-made design. A critique-reference comp on such a build is provocation, not spec: no element matrix, no adaptation citations, no asset obligations; its one contribution is what the image dared that the build did not, and dares worth adopting enter material_fixes as ordinary ordered fixes. An adaptation counts as intentional only when it cites the user answer, surface brief, accessibility need, or product truth that forced it; an uncited deviation is a defect. A missing signature element, a changed topology, or content added without approval fails fidelity and outranks every craft point in material_fixes. When MATERIAL is contradicted on the focal element, or contradiction is the page rather than the exception, stop ordering repairs: make the first material fix a rebuild directive naming the comp regions to re-derive and the assets to produce; a list of patches against a rejected page launders the rejection into an approval. A fix that requires producing an asset says so explicitly ("produce: <region> as a raster asset"), never phrased as a style adjustment the parent will answer with CSS. The comp is the spec for composition, topology, element inventory, density, lettering character, and material; it is not a pixel spec for semantics, accessibility, or responsive reflow, and that allowance covers translation, never replacement.
3. **Ceiling.** Against the QUALITY BAR card: name the world's native devices the build left unused, frame, depth, lettering treatment, ornament density, motion. The card governs commitment and finish, never composition.
4. **Contract, promise by promise.** First verify FORM carries the seed key the concept roll printed; a contract with no seed key, or one the parent cannot corroborate, means the roll was skipped, a material fix ahead of any craft point. Then, for each of the five blocks: does the render keep the promise? Apply the memory test to the first viewport.
5. **Truth.** Demonstration data authored and labeled synthetic; no invented commercial claims; unanswered claims present as marked placeholders, not omissions. Every image-native region of the approved comp shipped as a real asset, not a gradient standing in for one, and every produced asset visibly present in the screenshots; an asset applied at near-zero opacity or buried behind other paint is a compliance token, not a shipped material.
+4 -2
View File
@@ -72,7 +72,7 @@ Your measured rendition prior: warm, bookish, family, and child-facing subjects
## 5. Record the decision
Before code, state the chosen direction as a contract in the artifact's opening comment, five short blocks, 150 words at most, in a form that survives the production build: an HTML comment in the emitted markup, never only a templating-frontmatter comment, placed as the first child of the document's body in the root layout, never inside a slotted or child component (some compilers, Astro among them, strip a slot's leading comment while keeping deeper ones). After the first production build, grep the built output for the seed key; a contract the build erased is a contract nobody can audit. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, and DESIGN.md". The comment tops the artifact you re-open on every edit, the one reminder that survives a long build: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract. <!-- rule:skill-decide-then-build -->
Before code, state the chosen direction as a contract in the artifact's opening comment, five short blocks, 150 words at most, in a form that survives the production build: an HTML comment in the emitted markup, never only a templating-frontmatter comment, placed as the first child of the document's body in the root layout, never inside a slotted or child component (some compilers, Astro among them, strip a slot's leading comment while keeping deeper ones). After the first production build, grep the built output for the seed key; a contract the build erased is a contract nobody can audit. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance". The comment tops the artifact you re-open on every edit, the one reminder that survives a long build: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract. <!-- rule:skill-decide-then-build -->
On a new or replacement world, DESIGN.md is written at finish, from the built world, by the shipped documenter (section 7); a rulebook written before the build gets defended against reality instead of describing it, and hands the design-system detector an unstable target. A new world shipped with no DESIGN.md is still an incomplete run. An ordinary extension does not rewrite DESIGN.md. <!-- rule:skill-design-md-from-the-build -->
@@ -90,7 +90,7 @@ For `shape`, return the selected direction to [shape.md](shape.md) and stop befo
## 6. Build with full commitment
When an approved comp exists, the comp is king, and the build happens in phases. The comp is a spatial contract, not a mood board: only the user can downgrade its authority, in explicit words, and difficulty never infers a downgrade. Phase one is reproduction: rebuild the comp at its own breakpoint until a screenshot at the comp's width and height overlaps it near pixel-perfectly, materials, components, elevation, assets, and implied design language included. Exactly three concessions exist: fonts (the closest obtainable face), icons (exact match unless the user already chose an icon library), and genuine defects in the generated comp such as spelling errors. Everything else must match, and models systematically believe their HTML, CSS, and SVG recreation succeeded when it did not, so the overlap comparison is the authority, never your conviction: set the screenshot beside the freshly reopened comp image at identical dimensions after every region, never beside your memory of it, and when a region keeps losing that comparison, stop recreating it in code and produce it as a rendered asset composited into the page. The comp also outranks every written record of it: when the recorded brief or inventory commits to less than the comp shows, a softer texture, a sparser field, a sculpted plate reduced to flat CSS, correct the record upward to the comp; qualifiers like subtle, restrained, and low-contrast, and counts rounded down to a comfortable fraction, are how approved materials die between approval and build. A produced material must then survive to the screen: a texture buried under a nearly opaque color wash ships the wash, not the material, so judge every material by the screenshot beside the comp, never by the stylesheet. Every color the brief records gets that comparison by number, not by eye: sample the build screenshot's ground, dominant fields, and accents the same way each record was taken (an interior patch average where the record is an average, both end colors where the record is a gradient) and set each value against its recorded counterpart (sampled from the comp itself when the brief lacks one), and when a texture or tile paints over a base token, measure the net on-screen value, because the eye files a drifted color under the same color word and the number is what catches it. Judge the gap like a colorist, not a diff tool: a difference with a color name (warmer, grayer, darker than the record) is drift to fix, while a few digits of render and compression noise are the same color. <!-- rule:skill-color-by-number --> Only when reproduction holds does phase two begin: static regions that should live become animated or interactive, reveals and motion are added, then responsiveness across the surface's devices. Where the comp does not cover the whole surface, continue building the remainder inside the comp's recorded world and design language; a component the comp never shows inherits the recorded system's corner language, line weights, and materials, and may not introduce container styles, border weights, or chrome the comp never uses. <!-- rule:skill-comp-is-king -->
When an approved comp exists, the comp is king, and the build happens in phases. The comp is a spatial contract, not a mood board: only the user can downgrade its authority, in explicit words, and difficulty never infers a downgrade. Phase one is reproduction: rebuild the comp at its own breakpoint until a screenshot at the comp's width and height overlaps it near pixel-perfectly, materials, components, elevation, assets, and implied design language included. Exactly three concessions exist: fonts (the closest obtainable face), icons (exact match unless the user already chose an icon library), and genuine defects in the generated comp such as spelling errors. Everything else must match, and models systematically believe their HTML, CSS, and SVG recreation succeeded when it did not, so the overlap comparison is the authority, never your conviction: set the screenshot beside the freshly reopened comp image at identical dimensions after every region, never beside your memory of it, and when a region keeps losing that comparison, stop recreating it in code and produce it as a rendered asset composited into the page. The comp also outranks every written record of it: when the recorded brief or inventory commits to less than the comp shows, a softer texture, a sparser field, a sculpted plate reduced to flat CSS, correct the record upward to the comp; qualifiers like subtle, restrained, and low-contrast, and counts rounded down to a comfortable fraction, are how approved materials die between approval and build. A produced material must then survive to the screen: a texture buried under a nearly opaque color wash ships the wash, not the material, so judge every material by the screenshot beside the comp, never by the stylesheet. Only when reproduction holds does phase two begin: static regions that should live become animated or interactive, reveals and motion are added, then responsiveness across the surface's devices. Where the comp does not cover the whole surface, continue building the remainder inside the comp's recorded world and design language; a component the comp never shows inherits the recorded system's corner language, line weights, and materials, and may not introduce container styles, border weights, or chrome the comp never uses. <!-- rule:skill-comp-is-king -->
Build the assigned direction, not a safer interpretation of it. The form supplies structure, reading order, component conventions, and native motion; the product supplies every fact. Commit every atom: nav, buttons, inputs, and links are rebuilt in the form's vocabulary, and a stock component inside a committed form is a lapse. Land the first build fully committed; committing is the hard part, and the passes that follow exist to make the committed thing clear and effective, never to dilute it. In unattended work, the safe rendition is the known risk. <!-- rule:skill-commit-every-atom -->
@@ -117,6 +117,8 @@ Then spawn the shipped finish reviewer, `impeccable-finish-reviewer` (`impeccabl
Act on the disposition word; there are exactly four. **recapture**: the evidence failed, not the build. Recapture what the return names under the capture-validity rules, then run a full review over the new evidence. A review conducted on invalid evidence binds nothing, and a verdict pass may never follow it. **rebuild**: fidelity failed wholesale, not in patches. Skip the fix batch and execute the rebuild immediately: re-derive the named regions, produce the named assets, and send the result back for a fresh full review, never a verdict pass; a rebuild replaces regions wholesale, so the whole matrix runs again over the recaptures. Tell the user what is happening rather than asking permission to fix a failure. Consult the user only on a second rebuild directive, both verdicts on the table, or when rebuilding would discard content the user approved. **ship**: nothing is owed; report the verdict at its scope and continue to the documenter. **fix**: apply the material fixes in one batch, rebuild once, and recapture the same viewports over the same files. A recapture measures positions, loading, and overflow; it cannot measure whether a fix reached the quality the finding named, so send the recaptured screenshots back to the same reviewer for a verdict scoring every material fix resolved, partial, or unresolved (through the harness's agent continuation; without one, run the scoring fresh from [degraded/finish-reviewer.md](degraded/finish-reviewer.md)'s Verdict Pass). Fixes scored partial or unresolved get another batch, recapture, and verdict. Two rounds is the budget an unattended run ends at; an attended session's ceiling belongs to the user, so when the second verdict still lists open items, put the table in front of them and let them choose between shipping as it stands and funding another round. Whoever decides, stop the moment a round resolves nothing, and the reviewer's findings are the only list you work from, never your own re-opened hunt. Do not run a second detector. <!-- rule:skill-verdict-bounds-the-finish -->
A rebuild and a fix round share one asset rule: a raster either round creates or replaces is still asset work under [visualize.md](visualize.md)'s Produce section and keeps its **provenance** like every build raster, and a raster the round abandons is deleted in the same batch. Before either round's result goes back for review or verdict, run `node {{scripts_path}}/embed-prompt.mjs --scan <asset-dir...>` over the directories the artifact's rasters ship from and clear every file it reports by embedding what it is missing: the exact generation prompt for a produced raster, the origin for a sourced, stock, or pre-existing one. The scan only reads; deletion is reserved for rasters the round abandoned, never for a file the scan flagged. <!-- rule:skill-late-raster-provenance -->
Report the final verdict under the reviewer's own disposition word and at its actual scope. A verdict pass scores the listed fixes and nothing else: "the reviewer scored all three fixes resolved" is a claim it supports, "no material issues remain" is not. A table with open material findings is never announced as a pass, never softened, and never dressed as whole-surface approval when only a fix list was scored. When the user answers a ship with evidence against it, their own screenshot, a named mismatch with the comp, that evidence outranks every capture you made: put their material in the packet and spawn a fresh reviewer for a new full review. Patching inline and self-certifying is how a rejected page ships twice. <!-- rule:skill-user-evidence-reopens-review -->
Then spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, the artifact path, the direction contract, PRODUCT.md, the [document.md](document.md) reference path, and the boundary to write at; it records DESIGN.md and the sidecar from the built world, ground truth over intention; without subagents the pass runs from [degraded/documenter.md](degraded/documenter.md). The documenter runs after the last correction lands: when any fix round follows the documentation, re-run the documenter over the changed surface, because a DESIGN.md describing a layout that no longer exists turns defects into system guidance. A clean detector pass is not finished; finished is the contract kept, the comp honored, the review closed, and the system recorded. <!-- rule:skill-documenter-records-the-world -->
+3 -3
View File
@@ -33,8 +33,6 @@ After approval, record the choice where tools can find it: the approved comp's p
Before building, read the approved comp as a design system and record it in the brief: component grammar, corner language, line weights, elevation treatment, and the type ramp. Everything the comp does not show gets built from this record; without it the fallback is the model's stock kit of square boxes, 1px grids, bento cells, and hard shadows. Then inventory the comp's major visible ingredients in writing (a short table in the surface brief or working notes; the finish reviewer audits shipped assets against it) and choose an implementation medium for each: semantic HTML/CSS/SVG, existing project asset, generated raster, sourced raster, icon library, canvas/WebGL, or accepted omission. The same inventory names the comp's compositional commitments: navigation items and icons, headline levels and their scale relationship, signature geometry such as seams, masks, and overlaps, and each section's arrangement and density. The primary action gets its own row with its own medium: when the comp dissolves, stamps, erodes, or otherwise physically works the main CTA, that treatment is signature material on the page's most important element, and shrinking it to a border trick is the compliance-token version of commitment. An element never written down is the element the build silently drops; the direction contract's 150 words cannot carry this list, so it lives here.
The record is sampled, never estimated: read the comp's page **ground**, each dominant field, and each accent's actual hex from its pixels (ImageMagick, Python with PIL, any pixel-reading tool on the machine) and write the values into the same record. Take a flat field from any interior pixel, a textured or grainy one as the average of an interior patch (crop a swatch, scale it to one pixel), and a gradient as its two end colors; never sample an edge, where antialiasing blends neighbors into colors the design never chose. An adjective is a direction, not a record: cream covers everything from near-white to beige, charcoal a third of the value scale, and wherever no number pins a color, the rendition prior picks the spot. Sampled values supersede the palette chips on the decision and composition cards: those were authored before this comp existed, and a chip that disagrees with the comp's pixels is a draft the approval retired.
The medium column is where an approved design most often dies, so it obeys a gate: the medium is decided by what the comp region shows, never by what feels buildable in the current stack. A human figure, a product object, machinery, or any material with lighting and depth is raster whatever the stack; so is any texture by name alone: woven cloth, paper grain, fabric, leather, brushed metal need no depth argument, because a CSS gradient is not a texture medium and "layered CSS textures" is not a medium at all. Writing "silhouette" for a photographic figure, or "CSS" for a sculpted panel's finish, is not a medium choice; it is the quiet deletion of the approved design, and it is how a comp full of physical material becomes a flat page with the same section order. Style does not move this boundary: a comp region with perspective, shading, figure drawing, or dense mechanical detail is illustration however line-drawn it looks, and no build session can author illustration as vectors, so it regenerates as raster like any photograph. Authored SVG covers what a session can specify exactly (diagrams with countable elements, controls, flat shape systems) and ends where drawing skill begins; an instruction-manual world keeps its illustrations as line-art illustrations, not diagrams. Produce such regions by regenerating them cleanly, with the approved comp and its embedded prompt as the reference for a fresh render at asset resolution; never crop pixels out of the comp itself, whose effective resolution sits far below asset grade. Dropping an image-native region is a scope decision the user makes at the approval point, never a silent flattening after it. Generated imagery is a material, not a claim: evidence rules bind assertions, specs, testimonials, and photographs presented as real, never render fidelity; "no photography on hand" forbids fake proof, not an illustrated hero.
The gate runs both ways: precise geometry, hard-edged shape systems, diagrams, expressive motion, shaders, and anything interactive are vector and GPU territory (SVG, canvas, WebGL), where a raster flattens what should move, scale, and respond. A field or texture built from many small elements carries a quantity commitment either way: write down its approximate density and coverage ("thousands of glyphs over two-thirds of the fold, dense at the top fading into the path"), because a field rebuilt at a tenth of its density passes every checklist and still is not the design. TYPE rows carry the same discipline: name the face's compression class, and render one headline word against the comp before building on it; a visibly wider or lighter silhouette means the face is wrong, and every section built on it inherits the miss. Raster is for what the world paints; code is for what the world draws, animates, or reacts with, and choosing code there is ambition, not economy. Every `produce` entry is produced before the build ships, through the asset producer or in the current thread; an inventory with unproduced entries is an unfinished build, and this gate is where imagery-free pages come from when it is skipped.
@@ -45,7 +43,9 @@ The comp is a north star, not something to trace, and know what that allows: tra
## Produce only the assets the build needs
Generation context is part of the asset: a build composed by a thread that never saw the prompts places assets it does not understand. Prefer generating build-critical imagery in the build thread when the budget allows; when a subagent produces assets instead, every asset carries its prompt, and the builder reads those prompts before composing. The carrier is uniform across harnesses: after generating any image with any tool, native or `generate-image.mjs` (which does it automatically), run `node {{scripts_path}}/embed-prompt.mjs <image> --prompt "<the prompt used>"` so the intent lives inside the file and survives copies between machines and harnesses; `--read` recovers it from any impeccable-generated image.
Generation context is part of the asset: a build composed by a thread that never saw the prompts places assets it does not understand. Prefer generating build-critical imagery in the build thread when the budget allows; when a subagent produces assets instead, every asset carries its prompt, and the builder reads those prompts before composing. The carrier is uniform across harnesses: after generating any image with any tool, native or `generate-image.mjs` (which does it automatically), run `node {{scripts_path}}/embed-prompt.mjs <image> --prompt "<prompt>"` with the exact string the generation tool received, pasted whole, so the intent lives inside the file and survives copies between machines and harnesses; a summary reconstructed from memory records an asset that was never made. `--read` recovers the prompt from any impeccable-generated image, and `--scan <dir>` lists every raster in a directory still missing one. The embedded prompt plus the asset's row in the written inventory is the raster's **provenance**, and every raster the artifact references carries it; a sourced, stock, or pre-existing raster with no generation prompt embeds its origin instead.
Provenance is owed for the run, not the build phase: a raster created or replaced later, in a fix batch or a reviewer's rebuild, is produced under this same section, prompt embedded and inventory row added, because the inventory is how the next thread knows what ships. A raster a fix abandons or supersedes is deleted from the assets directory in the same batch; an unreferenced raster with no record is a provenance leak, not a spare.
When the harness runs subagents, spawn the shipped asset producer every time, even when the inventory's produce bucket looks empty: its manifest is the independent second opinion on your media, and the runs that skipped the spawn are the runs whose cotton became CSS. An honestly empty manifest costs one cheap spawn; a wrongly empty produce bucket costs the build its materials. Use `impeccable-asset-producer` (`impeccable_asset_producer` in codex; `/impeccable-asset-producer` in Cursor; on GitHub Copilot say "Use the impeccable-asset-producer agent"): give it the approved comp, output paths, required dimensions and formats, transparency needs, crop notes, and what must remain semantic code. Without subagents, produce the minimum required assets in the current thread by the book: load [degraded/asset-producer.md](degraded/asset-producer.md) and follow it inline, with whatever generation exists.
+42
View File
@@ -5,6 +5,7 @@
// node embed-prompt.mjs <image> --prompt "the prompt text"
// node embed-prompt.mjs <image> --prompt-file prompt.txt
// node embed-prompt.mjs <image> --read
// node embed-prompt.mjs --scan <dir...> # list rasters missing a prompt; exit 3 when any
//
// Formats: PNG (tEXt chunk, keyword "impeccable:prompt"), JPEG (COM segment).
// WebP and anything else fall back to a `<image>.json` sidecar; --read checks
@@ -21,8 +22,49 @@ const KEYWORD = 'impeccable:prompt';
const args = process.argv.slice(2);
const file = args.find(a => !a.startsWith('--'));
const readMode = args.includes('--read');
const scanMode = args.includes('--scan');
const argOf = (name) => { const i = args.indexOf(name); return i !== -1 ? args[i + 1] : null; };
function promptOf(imagePath) {
const b = fs.readFileSync(imagePath);
let prompt = null;
if (b.length > 8 && b.readUInt32BE(0) === 0x89504e47) prompt = readPngText(b);
else if (b.length > 3 && b[0] === 0xff && b[1] === 0xd8) prompt = readJpegCom(b);
if (prompt == null && fs.existsSync(`${imagePath}.json`)) {
try { prompt = JSON.parse(fs.readFileSync(`${imagePath}.json`, 'utf8')).prompt ?? null; } catch { /* stays null */ }
}
return prompt;
}
if (scanMode) {
const targets = args.filter(a => !a.startsWith('--'));
if (targets.length === 0) { console.error('embed-prompt: --scan needs at least one directory'); process.exit(1); }
const RASTER = /\.(png|jpe?g|webp)$/i;
const rasters = [];
const walk = (p, isRoot) => {
const stat = fs.statSync(p);
if (stat.isDirectory()) {
const base = p.replace(/\/+$/, '').split('/').pop();
// Skip installed deps and hidden dirs found during the walk, but honor a
// hidden dir the caller passed explicitly (e.g. .impeccable/mocks).
if (!isRoot && (base === 'node_modules' || base.startsWith('.'))) return;
for (const entry of fs.readdirSync(p)) walk(`${p.replace(/\/+$/, '')}/${entry}`, false);
} else if (RASTER.test(p)) {
rasters.push(p);
}
};
for (const target of targets) {
if (!fs.existsSync(target)) { console.error(`embed-prompt: no such path ${target}`); process.exit(1); }
walk(target, true);
}
let missing = 0;
for (const raster of rasters) {
if (promptOf(raster) == null) { console.log(`MISSING: ${raster}`); missing++; }
}
console.log(`SCAN: ${rasters.length} raster${rasters.length === 1 ? '' : 's'}, ${missing} missing`);
process.exit(missing > 0 ? 3 : 0);
}
if (!file || !fs.existsSync(file)) { console.error('embed-prompt: image file required'); process.exit(1); }
const buf = fs.readFileSync(file);