Skip to content

Our Image Skill Passed Review, Then We Found It Shipped the Wrong File

An image production skill scored perfect on form. A third check found 18 logic bugs, including one that delivered the wrong file. Here is what changed.

Published
Updated
AI-generated, checked by independent automated gates, no human editorial review.
How this guide was made
Our Image Skill Passed Review, Then We Found It Shipped the Wrong File

AI-generated. Written by an automated system, checked by independent automated gates, and published without human editorial review. How we label and verify.

The surprise inside our image production gate

We built a skill to produce one publication image and prove the delivered file met spec before it left the line. It passed a formal external review with top marks. We celebrated briefly. Then a mandatory third checker read the run outputs and flagged 18 logic errors the reviewer had missed.

That was the moment it clicked.

What happened, concretely

We fed the skill a curated brief. The brief came from a separate curator who distilled five third‑party image guides into a single document; the writer who coded the skill never saw those sources. That barrier was deliberate so copying couldn’t happen.

We ran the skill on a batch of sample briefs. The independent reviewer examined form and structure and gave a perfect score. The report was clean. The run logs looked clean too.

Then the third checker re‑played the same runs against the actual delivered artifacts and found 18 distinct logic issues. Many were subtle. One was catastrophic.

We reproduce the worst one here because it shows how an outwardly perfect verification can still lie. The run performed a crop correction, then executed verification steps. The readout said the corrected file matched the frozen spec. But the packager grabbed a different file — the pre‑crop image — and placed that into the delivery bundle. The verification step had checked one inode, the delivery step shipped another. The fix had been silently discarded.

Result: an image that failed the publisher’s spec went out with a clean proof bundle. The external reviewer did not catch it. The third checker did.

How we proved each issue

We stopped guessing and reproduced the full IO chain for each failing run. For a given sample we intentionally introduced a small, visible crop change. We watched four things.

First: which file the correction wrote to disk. We logged the exact filename and timestamp. Then we read the same path back and compared pixel dimensions against the frozen spec. We recorded a checksum at that moment.

Third: the packager step that selects the artifact to include in the delivery bundle. We let it run, then unzipped the bundle and read the packaged artifact’s checksum. They disagreed. That mismatch was the turning point.

It was obvious in logs once we forced the same readback and checksum comparison after every mutation. When we enforced that readback as the canonical truth, the bug could not repeat.

The rule that fell out

Make the post‑mutation file the canonical artifact for every subsequent step and prove it with an on‑disk readback plus checksum before packaging.

What changed in version 1.1

We closed all 18 issues the same day. The central changes were defensive and surgical.

One representative change: after any image correction the run now immediately reads the file it just wrote, checks the exact pixel dimensions against the frozen spec, computes a checksum and writes that checksum into the proof bundle. The packager then uses that checksum to select the artifact it will include, and refuses to continue if they do not match. That single detail removed the class of “verified one file, delivered another” errors.

We also added hard gates. If optical text detection finds three or more readable characters the run stops and writes a failure file. If a watermark detector scores 0.5 or higher, the run fails hard. If dimensions miss the spec by a single pixel, the system blocks instead of warning. Every run now outputs a proof bundle so any third party can re‑verify delivery without contacting us.

A fair counter‑example

One of the 18 issues came from a false positive: the watermark detector flagged a subtle texture as a potential mark on one sample when human reviewers saw nothing wrong. We kept the detector, but we changed how a failure is handled. It still blocks, which slowed that run. Later manual inspection showed the detector needed tuning, not removal. The system was harsher, but safer.

How we know

All of these findings are from our production line tests. We validated the fixes by re‑running every previously failing case. The new runs produced matching readbacks, matching checksums, and clean proof bundles. The failing artifacts no longer appeared in delivery packages. The most serious pre‑1.1 bug — the wrong file being delivered after a crop — no longer reproduces.

Questions we got

Why did the independent reviewer miss 18 logic errors?

The reviewer assessed form and spec compliance on the outputs it was shown, not the actual packaged artifact on disk. The gap was between “verified in one place” and “what was actually shipped.” The third checker audited the delivery bundle itself and therefore saw mismatches the reviewer could not.

Won’t hard blocking on minor things create too many failed runs?

Some runs will fail more often. We accepted that. The tradeoff is explicit failure modes and immediate remediation rather than noisy warnings that get ignored and bad artifacts slipping out. We tuned detectors to reduce false positives, but blocking remains the fallback.

Can you share the runnable skill file?

The tested, runnable version lives in the members’ library.

Rule, final: make the file on disk the single source of truth, prove it by reading it back and hashing it before you ever package or claim success. That discipline is exactly what our image production gate now guarantees.

Sources: internal production testing and change logs from our content pipeline tests, version 1.0 → 1.1, plus the curated brief provenance described above.

What systems research, CWE and file-integrity standards say about verifying a delivered file

The classic reference here is the 1984 paper “End-to-End Arguments in System Design” by Saltzer, Reed and Clark. It works through the problem of careful file transfer and concludes that checks inside the transfer chain are not enough on their own. The paper’s argument is that such a function can completely and correctly be implemented only with the knowledge and help of the application at the end points. Checks in the middle are useful, but the paper treats them as optimisations, not proof.

The authors describe the remedy as end-to-end check and retry: store a checksum with the file, compare it at the far end, and repeat the transfer if they differ. In an image pipeline the far end is not the step that edited the image. It is the bundle that actually leaves the line.

MITRE’s Common Weakness Enumeration names the gap between checking and using. CWE-367, the time-of-check time-of-use weakness, describes a product that checks a resource, after which the resource’s state can change between the check and the use. One of the listed mitigations is to Recheck the resource after the use call to verify that the action was taken. CWE frames this mainly as a security issue, but the same pattern breaks correctness when the “use” is a packaging step that picks up a different file.

Content provenance standards formalise how to tie a claim to specific bytes. The C2PA specification defines a hard binding as One or more cryptographic hashes that uniquely identifies either the entire asset or a portion of it. A proof that is not bound to the delivered bytes says nothing about the delivered bytes. For computing those hashes, Python’s standard library has a file_digest helper that will Return a digest object that has been updated with contents of file object, and the hashlib docs warn that Some algorithms have known hash collision weaknesses, naming MD5 and SHA1.

Finally, the destination sets its own quality bar. Google Search Central’s image guidance states that High-quality photos appeal to users more than blurry, unclear images. A correct crop that never ships does not help with that, which is why the check has to sit on the shipped file.

How those sources map onto the 18 issues we found

The worst bug in version 1.0 is a textbook end-to-end failure. The crop correction was verified against the frozen spec, and the readout was correct for the file it checked. The packager then placed the pre-crop image into the delivery bundle. The check happened in the middle of the chain. The delivery happened at the end. Nothing compared the two, so a file that failed the publisher’s spec went out with a clean proof bundle.

It is also the CWE-367 pattern, with the packager as the “use” step. The state that changed between check and use was not the file’s content but which file was selected. Our reproduction followed the same logic CWE recommends: write, read the same path back, record a checksum, then unzip the bundle and compare. The two checksums disagreed, and that disagreement was the turning point.

Version 1.1 applies the end-to-end idea directly. After any correction the run reads back the file it just wrote, checks the exact pixel dimensions against the frozen spec, computes a checksum and writes it into the proof bundle. The packager selects the artifact by that checksum and refuses to continue on a mismatch. That is a hard binding in the C2PA sense, applied inside our own pipeline: the proof names specific bytes, and any third party can re-verify delivery from the bundle.

The independent reviewer’s perfect score fits the same picture. It assessed form and spec compliance on the outputs it was shown. The third checker audited the delivery bundle itself, which is the end point the 1984 paper says only the application can check.

Checklist for proving the file you ship is the file you checked

  1. After every change to an image, read the file back from disk by path instead of trusting the in-memory result.
  2. Check exact pixel dimensions against the frozen spec and block on any miss, even one pixel.
  3. Compute a checksum with a current algorithm such as SHA-256, not MD5 or SHA1.
  4. Write that checksum into the proof bundle at the moment of verification.
  5. Make the packager select the artifact by checksum, not by filename or “latest file” logic.
  6. After packaging, unpack the bundle and hash the packaged artifact again. Stop if it differs.
  7. Treat text detection and watermark scores as blocking gates, and record each failure in a file.
  8. Rerun every previously failing case after a fix and confirm the old bug no longer reproduces.

More questions

Isn’t checking each step enough if every step is correct?

Not according to the end-to-end argument. Each step in our run was correct in isolation: the crop worked and the verification read the right numbers. The failure lived between steps, in which file the packager picked. Only a check at the end point, on the bundle that ships, could see it.

Why store a checksum instead of just comparing file names?

A file name points to a location, and what sits at that location can change. A checksum describes the content itself. The C2PA specification uses cryptographic hashes for the same reason when it binds a provenance claim to an asset. In our case the names looked fine and only the checksums showed that two different files were involved.


How we know

The factual claims in this article come from our verification store — each with a source type, a confidence label and a reference. The method is documented on How we know.

– It is assumed that a perfect score from an independent AI reviewer means the procedure is sound. This image skill got top marks on form, and behind that verdict a mandatory third checker still found 18 real logic errors, all closed the same day. | source: documented source | conf: mythbuster | ref: EBZ skill-fabrikk kjøring 2026-07-24 + skillfil v1.1
– Every run ends with a proof bundle: the delivered image is read back from disk, its exact pixel dimensions checked against the frozen spec, and checksums written so any third party can re-verify the delivery without asking anyone. | source: documented source | conf: verified | ref: EBZ skill-fabrikk kjøring 2026-07-24 + skillfil v1.1
– The image skill blocks instead of warning: if text reading finds three or more readable characters, a watermark detector scores 0.5 or higher, or dimensions miss the spec by a single pixel, the run writes a failure file and stops before delivery. | source: documented source | conf: verified | ref: EBZ skill-fabrikk kjøring 2026-07-24 + skillfil v1.1
– The most serious bug in version 1.0: after a crop correction, the run verified one file but packaged and delivered a different one, so the fix was silently discarded. Version 1.1 makes the adjusted file the canonical artifact for every later step. | source: documented source | conf: verified | ref: EBZ skill-fabrikk kjøring 2026-07-24 + skillfil v1.1
– Our production line wrote this image skill from a curated brief distilled from five third-party image-generation guides read by a separate curator; the writer never saw the sources, so copying was impossible by design. | source: documented source | conf: verified | ref: EBZ skill-fabrikk kjøring 2026-07-24 + skillfil v1.1

Related guides

Skill Spotlights · Published

Agent Skills: The Four Bytes Four Gates Missed

Four inspection gates checked 22 agent skills but missed four incorrect bytes. This case shows why teams need different verification methods, not simply more checks of the same kind.

Skill Spotlights · Published

What the JetEngine REST API actually reaches

JetEngine's REST API exposes two routes with different authentication behavior. Learn what the live endpoint tests proved, and where reads and writes stop.

Skill Spotlights · Published

The Slide Deck Check That Read Four-Pixel Text

A slide deck passed its checks despite four-pixel text. Learn to measure rendered legibility at delivery resolution and verify citations against their exact source spans.