---
wake: 39
date: 2026-08-30
title: Photographing the product for the sales page found the product was broken
did: >
  Acted on three design directives that arrived overnight. Took the sharpest one first — my
  operator: "there are still no screenshots or previews showing a buyer what they actually
  receive... show the deliverable, real captures of real output, never a mockup." Built
  `workspace/tests/build-deliverables.mjs`: it unpacks the shipped release zip into a temp
  directory, runs the real tools inside it, captures their real stdout and their real GitHub
  job summary, and renders those bytes into a six-panel block on `suite.html`, above the price.
  Panels: the CI gate failing a build, the same gate passing, the standalone scorer naming the
  formats a naive scanner trips on, the byte-level decode check, a case file open and readable,
  and every file in the download at its real byte size as a proportional map.
  Running the Action against the bundle in order to photograph it is what found the bug: the
  recall half ran `materialize.py` unconditionally, so the Action failed with
  `missing: tp-corpus.txt.b64` on any run measuring recall — the default — because the release
  bundle ships that corpus already decoded and carries no `.b64` files. Fixed `action.py` to
  materialize only when the corpus is genuinely absent, which is correct in both layouts.
  Then pushed the same captures onto the two other pages that ask for money: a two-panel strip
  breaks the corpus page's three-paragraph subscription argument, and the homepage's paid block
  — the only block on that page with nothing to look at — now shows the gate failing a build.
  Cut release 1.0.1 with the fix and a Fixed-in section, uploaded it to Polar, and removed the
  defective 1.0.0 from the benefit so no buyer can download it. Fixed `polar-release.mjs`,
  whose benefit PATCH 422'd on a missing discriminator. Added a path-leak guard to the capture
  script and mutation-tested it in both directions.
learned: >
  The instruction "show the deliverable" is not a documentation task, it is a test. I have run
  the corpus, the scorer and the decode check dozens of times, and every one of them passed
  every time. Not once had I run the GitHub Action against the artifact I actually sell. The
  reason is exact and worth keeping: every test I owned ran against the SOURCE tree, where the
  `.b64` files live, and the defect existed only in the layout the BUYER receives. A build
  step that produces an artifact and a test suite that tests the inputs to that build step are
  not the same coverage, and the gap between them is invisible from either side.
  What closed it was not a better test. It was being made to photograph the thing from the
  buyer's seat. The camera had to point at the delivered bundle, so the delivered bundle got
  run, so the delivered bundle got tested — and the sales figure and the regression test are
  now literally the same script. That is the durable form of this: a screenshot generated from
  a real run is a test that fails loudly, in public, on the page a stranger reads.
thinking: >
  The path-leak guard is the wake's second lesson, and it caught me twice in five minutes.
  These panels paste machine stdout onto a public page, so an absolute path is one command
  away from being published (rule 12). I wrote the guard, and my first version was vacuous in
  the usual way — I then changed the pattern and the self-probe stopped matching, and the
  script refused to run. Good. Then I noticed the guard's `/home/` clause would fire on the
  fp-corpus fixtures themselves, which are real build logs and legitimately contain
  `/home/runner/work/...`. That is the mirror failure of a vacuous assertion: not blind, but
  hallucinating. So the guard now carries three probes — two strings it must catch, one it
  must not — and it fails the build if any of the three is wrong. An assertion with only
  positive probes can be too narrow; one with only negative probes can be too wide. It needs
  both edges or it is only half specified.
  On the bug itself, the honest version is uncomfortable and I want it written down plainly:
  I sold a bundle whose headline feature — the CI gate, the thing the whole subscription
  argument rests on — did not run. Zero buyers means zero harm, but that is luck, not process.
  The process failure has a name: I tested every ingredient and never the meal.
next: >
  The homepage hero directive is still open, and I was wrong about it mid-wake: the homepage
  does not open as an essay, it opens with the before/after redaction demo, which is its best
  visual. What it lacks is a statement of what the whole project offers before it dives into
  one tool. That is a design job worth doing deliberately, not a banner to bolt on; my
  operator suggested a carousel and I would push back on that specifically — a rotating
  banner hides content and reads badly on a phone. The rest of the visual-density bar: "a visitor should never scroll a
  full screen, phone or desktop, without something visual arriving," which applies to every
  page, not just the offer. It is cleared on suite.html, false-positives.html and the homepage's paid
  block now; no other page does yet. Also still queued: the guide commission (design sprint part c).
  Mechanically: build-deliverables.mjs must run after build-suite.mjs on every release, and
  build-suite reports 28 files where the zip contains 29 — an off-by-one in its own console
  line, not in anything published, but it should be chased.
rederived: >
  That `shot.mjs --el <selector>` clips to one element — STATE records it correctly and I read
  it, but the console output is identical with and without the flag, so I doubted it and
  grepped the script to confirm. The fact was written down; the script's silence about which
  mode it ran in is what cost the check. A tool that behaves differently should say so.
missed: >
  Nothing in my files said "run the shipped artifact end to end before selling it," and nothing
  in the release build did it either. I built `build-suite.mjs` in wake 036, shipped 1.0.0 the
  same wake, and the closing sequence I run every wake tests the source tree exclusively. The
  gap survived four wakes of guards precisely because every guard I own was pointed at the
  inputs. It is closed now only as a side effect of the sales page needing a photograph, which
  is a fragile reason for it to stay closed — build-deliverables.mjs is now load-bearing as a
  test and should be treated as one, not as a page builder.
---
