An approval gate that never showed the thing being approved
Shipped
A patch release with one rule in it: my LinkedIn ghostwriting skill must put the complete, final post text inside the approval dialog itself, every time it asks to publish. A real session exposed the gap, and the follow-up commit froze the rule as a CI-enforced invariant so it cannot be quietly deleted later. Small change, but the pattern applies to any agent that asks a human to approve an artifact before an irreversible action.
Approved twice, never seen
The skill’s publish flow was built carefully: never post without explicit approval, show the full draft before asking, re-show after every edit. And in a real session it still asked me to approve a post I had never read in full. Twice in one sitting.
The mechanism is mundane. The skill printed the draft to the chat, then opened the approval dialog as a separate step, and the dialog takes focus over the scrollback. What is on screen at the moment of decision is the dialog: a question and some buttons, with the draft somewhere above, out of view. Every individual step was correct; the artifact and the decision just never shared the screen.
This is precisely what confirmation-dialog research warns about. Nielsen Norman Group’s guidance is that a confirmation must restate what is about to happen with specific information, because users answer vague dialogs automatically, without reading. Dr Maria Panagiotidi’s review of destructive-action modals makes the same point from the psychology side: the dialog has to carry the specifics and force actual processing, or confirming becomes a reflex. For agents this bar matters more, not less: the MCP specification’s tools guidance says applications should keep a human in the loop with confirmation prompts, and a confirmation prompt that does not show what is being confirmed satisfies the letter of that and none of the point.
The fix: the artifact rides inside the dialog
My skill asks for approval through a structured question dialog whose options can each carry a preview pane. The rule change is one sentence in the skill’s instructions: the complete final text goes in the Publish option’s preview, verbatim, with no metadata wrapped around it. In the dialog-call shape:
{
"question": "Publish this post to LinkedIn?",
"options": [
{
"label": "Publish",
"description": "Post exactly this text",
"preview": "<the complete, final post text, verbatim>"
},
{ "label": "Edit", "description": "Give edit instructions instead" },
{ "label": "Scrap", "description": "Discard the draft" }
]
}
The property to preserve in your own version, whatever your dialog toolkit: the approval control and the full artifact must be one surface, so that reading the artifact is on the path to the button. Printing it earlier does not count, and summarizing it in the dialog does not count either, because then the thing approved is the summary.
Then make the rule un-deletable
A rule like this lives in prose instructions, and prose gets rewritten. The next cleanup pass that shortens the publish section could drop the sentence, and nothing would fail. So the follow-up commit registered it in the skill’s invariants file, a list of prose rules CI greps for:
{
"id": "full-text-in-approval-dialog",
"file": "SKILL.md",
"pattern": "complete,?\\s*final\\s+(post\\s+)?text\\s+(goes|rides)\\s+in(side)?\\s+the\\s+approval\\s+dialog",
"rationale": "A real session (2026-08-11) asked for publish approval twice on a post the user had never seen in full: the dialog takes focus over chat scrollback, so text printed above it is not shown."
}
A test walks every entry and fails the build if the pattern no longer matches the file. To verify yours works, delete the sentence and run the suite; it must go red naming the invariant id. The rationale field is half the value: whoever trips the check two years from now gets the incident, not just the rule.
Gotchas
- “I printed it” feels like “I showed it”. The draft genuinely was in the conversation, which is why the gap survived review; every reading of the flow looked correct. The test is not whether the artifact was ever visible, it is what is visible at the moment the button is pressed.
- Re-shows regress first. The first show of a draft gets the careful treatment; the re-ask after an edit is where shortcuts creep in, and an edited draft is exactly the one whose final text the user has not seen. The invariant’s wording covers every show, first and re-show alike.
- A prose rule without a pattern check is a future deletion. This skill already had an invariants file for earlier hard-won rules, which made freezing this one a six-line diff. If your agent’s guardrails live only in instructions, the first one is more work; start with the rule whose silent loss would publish something.
Sources
- Confirmation Dialogs Can Prevent User Errors — dialogs must restate the action with specifics; vague ones get answered on autopilot
- How to design better destructive action modals — habituation, and forcing real processing at the moment of confirmation
- MCP specification: Tools — human-in-the-loop confirmation as a should-level requirement for agent tooling