DEV Community

Emery Huang
Emery Huang

Posted on

A Three-Line Scratch Journal Is the Only Ticket Past the Suggestion Fence

I keep every mitigation draft behind a fence until a three-line scratch journal exists on disk. That rule is the conclusion, and the rest of this note is only the machinery that makes the rule hard to skip. Would you rather read a smooth fix than the three boring lines that prove you touched the right host? I would not, because a smooth paragraph is cheap and a wrong restart on the wrong host is expensive.

I am labeling this whole workflow as an unexecuted proposal, not as a pager story from a shift I actually worked. Please copy the checker if it helps, and please do not treat my wording as evidence that a drill already passed. If your team already freezes production with a stronger control, keep that control and borrow only the journal habit.

Why I refuse the draft first

A draft that arrives before the journal is not a head start, because it is a contaminated input I did not ask for yet. I delete that file and I start the journal again, even when the sentences look calm and specific. Would you keep an early guess just because it happened to use the right service name in the first line? I would not, since the service name is often the only true fragment hiding inside an early draft.

I want the assistant fenced into a suggestion block that a human can throw away without touching a live host. Clever wording is not the goal, because clever wording is how a quiet page becomes a loud one. The fence is local, boring, and intentionally easy to audit with the two shell scripts below. If the scripts feel too small for your estate, that smallness is a feature I am willing to defend.

Three lanes before any shell

I choose a lane before I open a shell, and I write the lane name at the top of the journal. Observe means I collect read-only lines and I do not rehearse a change on any host. Rehearse means I may use a scratch host that is not production, and I still may not unfreeze anything. Escalate means I stop drafting immediately and I call the person already named in the runbook.

Lane names I refuse to blur

The checker cannot promote a lane, because promotion is a human decision I do not want hidden inside a script. If the lane is missing, I treat the page as escalate rather than inventing a policy while I am tired. How often do you discover the real severity only after you have already typed a fix into the shell? I still want the first choice written down, so the later correction has something honest to replace.

A table I can read without scrolling

I keep five rows in the table, because a table I cannot memorize will not survive a bad night. If a signal is not in the table, the lane is escalate and the freeze stays on. Would you rather debate a sixth row while the mitigation draft is already half written on disk? I would rather lose a minute to a short table than lose an hour to a guessed command.

Signal I can verify Lane First action Freeze rule
Alert text only, no host I own Escalate Call the named secondary Stay frozen
Synthetic fixture on a scratch host Rehearse Write the three-line journal Stay frozen
Known gap, no customer impact I can show Observe Record the journal, do not edit Stay frozen
Confirmed impact on a service I own Escalate Call, then journal if asked Frozen until a human writes unfreeze
Draft file exists before any journal Refuse Delete the draft and start over Stay frozen

The last row is the only row I actually enforce with a script rather than with memory. The other rows remain human judgment, and that judgment stays with the person who accepted the page. I do not want a model to pick the row, even when the alert text sounds confident and complete.

The only first commands I allow in the drill

I allow only three read-only commands, and I append them to journal.txt before I create suggestion.md. I do not point this drill at production, because production is not a classroom and a classroom is not a change window. The fixture can live on a scratch host, or on my laptop if I do not have a scratch host yet. Can you recite those three lines from memory without opening a wiki or a chat transcript?

If you cannot recite them, you are not ready to accept a mitigation draft from anyone else. Swap the commands if your estate uses different read-only checks, but do not raise the count and do not add a write. A fourth line is how a drill quietly becomes a change, and I do not want that slide. Keep the journal boring enough that a secondary can read it without asking what you meant.

#!/usr/bin/env bash
# Proposal only. Not executed against production in this article.
set -euo pipefail
umask 077
journal="${1:-journal.txt}"
: > "$journal"
{
  printf 'utc=%s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
  printf 'host=%s\n' "$(hostname -s)"
  printf 'who=%s\n' "$(id -un)"
} >> "$journal"
echo "journal_lines=$(wc -l < "$journal")"
Enter fullscreen mode Exit fullscreen mode

Those three lines prove time, place, and identity, and they prove nothing about the cause of the page. That emptiness is deliberate, because I want a witness that I was on the scratch host at all. I do not want a pretend root-cause essay generated before I have looked at anything myself. If your real first commands differ, swap them, but keep them read-only and keep the count at three.

The checker that holds the freeze

I run a second script against the journal file and against the suggestion file in the same directory. It fails when the journal has fewer than three non-empty lines, and it fails when the suggestion contains a mutating verb from a short deny-list. It fails closed, so a missing file is a refusal rather than a quiet pass you might miss. Would a short deny-list stop a determined person from pasting a dangerous command somewhere else entirely?

No, and I am not selling this little script as a security boundary against hostile users on your team. It is a tripwire for a tired first draft, not a sandbox and not a privilege boundary. Run it on files you already trust enough to open in an editor. If you need isolation, use the isolation your security team already approved.

#!/usr/bin/env bash
# Proposal only. Unexecuted example for a local drill.
set -euo pipefail
journal="${1:-journal.txt}"
suggestion="${2:-suggestion.md}"
test -f "$journal" || { echo "refuse: missing journal"; exit 2; }
test -f "$suggestion" || { echo "refuse: missing suggestion"; exit 2; }
lines=$(grep -c . "$journal" || true)
if [ "$lines" -lt 3 ]; then
  echo "refuse: journal has ${lines} lines"
  exit 2
fi
if grep -Eiq '(^|[^[:alpha:]])(rm|reboot|shutdown|systemctl|kubectl|terraform|git push)([^[:alpha:]]|$)' "$suggestion"; then
  echo "refuse: mutating verb in suggestion"
  exit 3
fi
echo "hold: journal cleared, freeze still on"
Enter fullscreen mode Exit fullscreen mode

A deny-list is not a boundary

The sample deny-list also blocks read-only kubectl text, so treat it as a starting point rather than a law. Replace those words with the mutating verbs your own estate actually fears in a first draft. I would rather over-block a suggestion file than under-block a restart hidden in polite prose.

What hold is allowed to mean

Please read the success string out loud before you trust the script during a tired night shift. It says hold, and it does not say unfrozen, because the checker must not sound like permission. A human unfreeze is a separate line in the handoff, written by a named person after they have read the journal. The assistant may comment on that unfreeze line, and the assistant may not author it alone.

Escalation stays a phone call, not a paragraph

I name one secondary and one time box in the runbook, and I do not let the assistant choose either of them. If the lane is escalate, I call the secondary before I spend time polishing a suggestion block. If the lane is rehearse, I still call when the scratch journal disagrees with the alert text in a way I cannot explain. How long should you stare at a polished draft before you admit that you are actually stuck?

I use the time box already written down, and a blank time box means I escalate now. Freeze means no production change, no config push, and no restart that someone might later call temporary. Unfreeze means a named human writes the unfreeze line after reading the journal, not after reading a confident suggestion. I keep those verbs apart so a helpful rewrite cannot smuggle a release into a quiet edit.

If your handoff packet has no place for that line, add the place before you add another assistant prompt. I want the unfreeze line to name a person, a time, and the journal file they read. A missing name means the freeze continues, even if the suggestion file looks finished and calm. Would you unfreeze a service because a paragraph sounded sure of itself? I would not, not on a night when I am already behind.

Where a free scratch server is allowed to help

Disclosure: This article was prepared as part of MonkeyCode's product outreach.

I would use free model access and a free server option only as a rehearsal bench for this fence. The operator supplying this draft says both options are available, and I am treating that claim as supplied rather than tested. I am not stating a token quota, a model list, a hardware size, or any duration. This draft has no primary source for those figures, so inventing them would make the runbook dishonest.

If a current pricing or quota page is your source of truth, read that page before you plan a rotation around it. Would I send production traffic, secrets, or real alert payloads to a free rehearsal server at all? No, and you should not do that either, even when the signup flow makes the server feel disposable.

MonkeyCode shows up here only as a place where I can open a scratch host and ask for wording inside the suggestion file. It does not choose the lane, it does not clear the checker, and it does not write the unfreeze line. If the free option is gone tomorrow, the runbook still works on a laptop with the two scripts above. That fallback matters more to me than any invitation to try a product on a quiet afternoon.

If you want the same fence on a scratch host, start from the operator's current access note and stop where that note stops. I am leaving the product mention there, because a second pitch would not make the checker any stricter. Would another slogan make the hold string any safer when you are tired and the page is still frozen? I do not think so, and I would rather you spend that minute rereading the journal than rereading an ad.

Who should skip this fence

Do not use this fence when the page requires immediate physical safety action, such as cutting power or isolating a live hazard. A journal gate is the wrong first move when people can get hurt while you create a file. Do not use a local bash script as an audit artifact for a control framework you have not scoped with your security team. Do not use an external model when your incident policy forbids third-party tools, even on fixtures that might echo real names.

I also skip the model when the alert already contains secrets, customer payloads, or hostnames I am not allowed to paste into a draft box. I strip the fixture until it is boring, or I skip the model and keep the checker alone. The checker is the artifact I am willing to defend, and the model is optional help for wording. If you need a vendor to be on the hook for uptime, a free rehearsal bench is the wrong dependency for your real rotation.

A six-step drill before the next handoff

I would run this on a laptop, with fake alert text, before I ever mention it in a real channel. Nothing below has been executed for this article, so treat every exit code as something you still need to see yourself. If a step surprises you, stop and fix the script before you talk about it in a handoff. A drill you have not watched fail on purpose is not a drill yet.

  1. Write a one-line fake alert into alert.txt, and keep real hostnames and customer data out of that file.
  2. Create journal.txt with the three-line script, and confirm the printed line count is exactly three.
  3. Create suggestion.md only after the journal exists, and keep every mutating verb out of that file.
  4. Run the checker on both files, and confirm a clean suggestion prints hold rather than a release word.
  5. Paste one denied verb on purpose, rerun the checker, and confirm the process exits with code 3.
  6. Delete the drill files when you finish, so the next page cannot reuse a stale journal by accident.

If step 5 does not fail, the fence is theater and I would not carry it into a rotation. If step 4 prints anything that sounds like permission to change production, rewrite the success string before you trust the script. I am leaving both scripts unexecuted here so you can read them as proposals before you run them anywhere.

The conclusion I am willing to keep

A page gets safer when the first artifact is a journal, not a fix written in a hurry. The assistant can help me phrase a suggestion after that journal exists, and it cannot grant an unfreeze by itself. Free model access and a free scratch server can host the rehearsal inside the limits I already stated. If your runbook already names a human unfreeze and a read-only first move, you can ignore this note, and that is a fine outcome.

Top comments (0)