DEV Community

Haley
Haley

Posted on

Show the Source Gap Before You Publish

I watched a designer hover over Publish last Tuesday. The portfolio line looked clean, calm, and confident. It claimed the checkout flow had lifted completion. No study, no date, and no owner sat beneath that line. Would you still ship that line to the public web?

That scene is a composite rehearsal, not a client metric. I use it when a team treats a smooth sentence as proof. The decision owner is the publishing designer, not the model. The consequence is a public claim a stranger can quote. The point of reversibility is the moment before the publish control fires.

Think of the line as a coat with no receipt. You can still like the cut of that coat. You still should not swear that you paid for it. The missing receipt is the source gap I care about. Extra praise about the fabric is just noise.

This walkthrough is a from-zero research gate for one claim. You will freeze one line, file a card, and fail closed. Each stage ends with a check you can run. I am not asking you to restyle the whole portfolio. One risky line is enough to learn the habit.

Freeze one risky line

Start in an empty folder on your own machine. Make a home for the rehearsal, then stop. If the folder is not empty, you picked a messy desk. Would you review a claim inside a junk drawer?

mkdir -p source-gap-rehearsal
cd source-gap-rehearsal
git init
printf '%s\n' "Lifted checkout completion after the redesign." > line.txt
wc -w line.txt
Enter fullscreen mode Exit fullscreen mode

Verification: wc should print a small word count, not an error. Read line.txt aloud before you touch the wording. If you cannot point to a study, the gap is real. A ticket or a dated note can also be the pointer. Do not edit the line into something safer yet. You need the risky version for the test.

Write the card before any model speaks

The card is the receipt stub, not a trust essay. Fill only the fields a human can defend. Leave the model out until the stub exists. A charming rewrite can wait in the hall.

{
  "owner": "",
  "line": "Lifted checkout completion after the redesign.",
  "source_type": "",
  "source_pointer": "",
  "date_window": "",
  "reversibility": "before publish control fires",
  "model_role": "hypothesis",
  "publish_name": "Publish blocked. Source pointer is missing.",
  "stop_not_color_only": true,
  "keyboard_order": ["source_pointer", "owner", "publish"]
}
Enter fullscreen mode Exit fullscreen mode

Save that object as card.json in the folder. Verification is visual before any script runs. Open the file and confirm owner is an empty string. Confirm that source_pointer is an empty string too. If you filled them from memory, you skipped the point. Those empty fields are the missing evidence on purpose.

Fail closed on blanks

Paste this checker into check-source-gap.mjs in that folder. It is a proposed local script, not a product feature. It tests field presence, not the truth of the claim. A full pointer can still be a lie. Hold that limit in your head while you run it.

import { readFileSync } from "node:fs";

const card = JSON.parse(readFileSync(process.argv[2], "utf8"));
const required = [
  "owner",
  "line",
  "source_type",
  "source_pointer",
  "date_window",
  "reversibility",
  "model_role"
];
const missing = required.filter((key) => !String(card[key] || "").trim());

if (card.model_role === "evidence") {
  console.error("STOP: model output is not evidence.");
  process.exit(2);
}
if (String(card.owner || "").toLowerCase().includes("ai")) {
  console.error("STOP: owner cannot be the model.");
  process.exit(3);
}
if (missing.length) {
  console.error(`STOP: missing ${missing.join(", ")}`);
  process.exit(1);
}
console.log("PASS: required source fields are present.");
Enter fullscreen mode Exit fullscreen mode

Run the checker against that still-empty card now.

node check-source-gap.mjs card.json
echo "exit:$?"
Enter fullscreen mode Exit fullscreen mode

You want a STOP line and an exit code of 1. If you see PASS, the card was already filled. That is a failed rehearsal, not a win. Fix the card back to blanks and run it again.

Now fill only the fields a human can point at. Use a real pointer you control, even a local note path. Then run the same command and read the exit code. A pass prints the PASS sentence and exit code 0. If the exit code is 2 or 3, stop and reread the owner. You let the model pretend to be the owner or the proof. Back up and ask who signs the sentence.

Let a draft speak, then demote it

Here is the only product note in this rehearsal. Disclosure: This article was prepared as part of MonkeyCode's product outreach. I mention it because a free model can draft the line. A free server can also host a scratch review. I am not naming a model, a quota, or a duration. I am not naming a machine shape either. Those details were not verified for this piece. So I will not invent them in this note.

Ask the free model for two phrasings of line.txt. Tell it to mark any number it cannot source. Save the reply as draft.md on disk. Do not paste that reply into the source pointer.

printf '%s\n' "HYPOTHESIS ONLY" | cat - draft.md > labeled.md
grep -n "HYPOTHESIS ONLY" labeled.md
Enter fullscreen mode Exit fullscreen mode

Verification: grep should print a line number for the label. If the label is missing, you mixed a draft with a receipt. Would you staple a guess onto an expense report?

The model may sound sure of a number. A sure tone is not a source type. A confidence badge is noise, not a gate. A prettier verb is also noise in this gate. The pointer, the owner, and the date window can stop you. The reversibility line can stop the click too. If any one of those is blank, approval stops. Extra adjectives do not earn the publish click.

What supports that stop rule? You can observe a blank field, and the script can exit. What does not support it? I have no study showing that this card changes publish rates. Treat the behavior hope as a design hypothesis. Keep it far from the PASS line.

Park the review, do not crown the host

If a free server option is already available, use it lightly. Treat that host as a scratch pad only. Put labeled.md and the checker output where a teammate can read them. Then leave that host alone after the upload. The record of truth stays in the folder you can diff.

I will not give you a vendor command here. I do not have a verified setup sequence. A made-up flag would be a false manual. Use a plain host you already trust if the free option is unclear. The gate is the script, not the address bar.

mkdir -p review-export
cp card.json labeled.md review-export/
node check-source-gap.mjs card.json > review-export/check.txt
test -s review-export/check.txt && echo "export ok"
Enter fullscreen mode Exit fullscreen mode

Verification: export ok means the check text exists. It also means that file is not empty. Open check.txt before anyone else on the team reads it. If it says STOP, do not upload a publishable page. Upload the stop text, or upload nothing at all.

flowchart LR
  A[Risky line] --> B[Source card]
  B --> C{Checker pass?}
  C -->|No| D[Hand back with missing fields]
  C -->|Yes| E[Human reads pointer]
  E --> F{Pointer still true?}
  F -->|No| D
  F -->|Yes| G[Publish with owner named]

Read that flow like a hallway, not a mood. The model never sits in the pass box. The signing human sits there with the pointer. If you remove the hand-back arrow, you built a slide. A slide is not a review you can defend.

Make the stop hearable

A red border alone is not an explanation. I want the publish control to say why it is blocked. That reason should live in text, not hue. The accessible name can be the publish_name field. Keyboard order should hit the missing field before the button. Color may support the stop, but it cannot be the stop.

node --input-type=module -e '
import { readFileSync } from "node:fs";
const card = JSON.parse(readFileSync("card.json", "utf8"));
const name = String(card.publish_name || "");
const lowered = name.toLowerCase();
if (!lowered.includes("blocked") && !lowered.includes("missing")) {
  console.error("STOP: publish name hides the gap");
  process.exit(4);
}
if (card.stop_not_color_only !== true) {
  console.error("STOP: color-only stop");
  process.exit(5);
}
const order = card.keyboard_order || [];
if (order.indexOf("source_pointer") > order.indexOf("publish")) {
  console.error("STOP: publish comes before the gap");
  process.exit(6);
}
console.log("A11Y PASS: stop is named, textual, and ordered.");
'
Enter fullscreen mode Exit fullscreen mode

You should see the A11Y PASS sentence in the terminal. Exit 4 means the button hides the gap. That fails a screen reader user in a hurry. It also fails a keyboard user who never sees the hue. Fix the accessible name, then rerun the check. Do not skip this because the mock looks obvious.

Recovery when someone already shipped

Sometimes that hover becomes a real public click. I do not pretend the web has an undo button. Recovery is a correction note beside the line. The named owner writes it, not the model. It names the missing source in plain words. It does not quietly swap an adjective and leave.

Hand the line back with the STOP text attached. The writer fills the pointer or cuts the claim. A cut claim stays in the review record. Deleting the argument is how the silence returns. Would you trust a history that only keeps the smile?

If the pointer later breaks, run the checker again. Do not polish the prose and call that recovery. Replace the source pointer, or unpublish the line. A free host going away is not a reason to keep a false line. The line's home is the claim, not the scratch server.

What this does not prove

The checker proves a field is non-empty on your machine. It does not prove that the study happened. It does not prove the number is fair. It does not measure whether designers behave better next week. That behavior claim is only a design hypothesis. I have not run that study with a real team. So I will not decorate it with a percent.

Do not use this gate for medical or legal claims. Do not use it for safety-critical public claims either. Do not use it to let an agent approve its own click. Do not use it if you cannot name a human owner. Do not use it as permission to pull private data into a portfolio. Presence checks are a porch light, not a courthouse.

Free model access and a free server can change. Build the habit so the script still matters later. The scratch tools may not stay available for you. If a quota is not in your current docs, leave it out. A duration or a hardware promise belongs in those docs too. If they are missing, keep them out of the card.

What should actually stop you

Stop when the owner is blank, fictional, or the model. Stop when the source pointer is only a memory. Stop when another model's sentence is the only pointer. Stop when the date window is still missing. Stop when reversibility is already behind the click. Also stop when nobody has a correction plan. Stop when the publish name hides the gap.

Let the extra noise stay noise on the card. Tone notes and synonym lists can sit in the file. Confidence badges can sit in that file too. They must not flip the exit code to success. I would rather see a blunt gap than a charming paragraph.

Which missing field would pull your hand off Publish? Which extra sentence would only make the card louder? Write those two answers in a sibling note. Then run the checker once more before you close the laptop.

Use the free options only as a scratch pair. Discard the host when the rehearsal is done. Keep the card, because the pass is local. A teammate should be able to hear the stop.

Top comments (0)