The drift between your AI session and your second box is a contract problem.
It is not a model problem. It is not a luck problem. It is a missing file.
You asked for code in one window. It ran there, so you shipped it. Then it met a different host and quietly fell over.
Who is surprised by that? Only someone who has not done it twice yet.
Here are four anti-patterns I keep seeing, with the replacement pattern for each. Then comes the script I actually run.
Anti-pattern 1: The Chat-Only Spec
Symptom: You cannot rebuild the change without scrolling a transcript.
The instructions lived in a conversation. The repo has no record of the goal, the constraints, or the stop condition.
A week later you ask the same assistant for a fix. It guesses at your conventions, because it has nothing to read.
Root cause: The spec was treated as conversation, not as an artifact. Conversation is ephemeral and per-window. A repo is neither.
Replacement: Put the contract in the repo as a file. Keep it short and boring.
<!-- CONTRACT.md -->
# Task contract
Goal: add /healthz returning 200 with a JSON body
Constraints:
- no new runtime dependencies
- do not touch src/billing/**
Stop when: tests pass and diff is under 200 lines
Verify with: npm test && ./preflight.sh
Now every session reads the same file. The stop condition is visible to you too, which matters more.
Is the constraint list longer than five items? Then the task is too big. Split it.
Anti-pattern 2: The Inherited Runtime
Symptom: Works locally, dies on the second box with a syntax or API error.
Your laptop has the runtime you installed months ago. The other host has whatever its image shipped with.
Root cause: The runtime version was never written down, so it was never checked. Nobody can diff a value that does not exist.
Replacement: Pin it in a one-line file and assert it at startup.
# .runtime-version
v22.11.0
# assert-runtime.sh
want="$(cat .runtime-version)"
have="$(node --version)"
if [ "$want" != "$have" ]; then
echo "runtime drift: want $want, have $have" >&2
exit 1
fi
Call the assertion from your start script, not from your memory. Memory is the thing under test here.
Anti-pattern 3: The Unwritten Environment
Symptom: Boot fails with an undefined key, or worse, silently uses a default.
Your .env has eleven keys. The other box has nine. Nobody knows which two are missing until something 500s.
Root cause: The set of required keys was never declared. Absence is invisible without a checklist.
Replacement: Commit a sample file with keys and empty values. Check every key on boot.
# .env.sample (committed)
DATABASE_URL=
HEALTH_PORT=8080
# every key listed in .env.sample must exist in the environment
missing=0
while IFS= read -r line; do
key="${line%%=*}"
case "$key" in ''|\#*) continue ;; esac
if [ -z "${!key:-}" ]; then
echo "missing env key: $key" >&2
missing=1
fi
done < .env.sample
exit "$missing"
Remember to export before checking: set -a; . ./.env; set +a.
A missing key should stop the boot. A default value should be a decision, not an accident.
Anti-pattern 4: The Unbounded Diff
Symptom: The change touches files you never asked about, and you approve it anyway.
An assistant with no stop condition keeps improving things. Formatting drifts. A helper gets "cleaned up." Review becomes archaeology.
Root cause: There is no review budget, so there is no signal that the task escaped its box.
Replacement: Set a diff budget and fail loudly when it is exceeded.
total="$(git diff --numstat | awk '{a+=$1; d+=$2} END {print a+d+0}')"
budget="${DIFF_BUDGET:-200}"
if [ "$total" -gt "$budget" ]; then
echo "diff is $total lines, budget is $budget: split the task" >&2
exit 1
fi
Exceeding the budget is not a failure of the model. It is a signal that your contract was vague.
The artifact: one preflight script, run on two boxes
Here is the whole thing. It is plain bash and has no dependencies beyond git and curl.
#!/usr/bin/env bash
# preflight.sh - run before you accept any change, on every box.
set -uo pipefail
fail=0
say() { printf '%-4s %s\n' "$1" "$2"; }
# 1. Runtime matches the pin.
want="$(cat .runtime-version 2>/dev/null || echo missing)"
have="$(node --version 2>/dev/null || echo none)"
if [ "$want" = "missing" ]; then
say FAIL "no .runtime-version file"; fail=1
elif [ "$want" != "$have" ]; then
say FAIL "runtime drift: want $want, have $have"; fail=1
else
say OK "runtime $have"
fi
# 2. Every declared env key is present.
if [ -f .env.sample ]; then
while IFS= read -r line; do
key="${line%%=*}"
case "$key" in ''|\#*) continue ;; esac
if [ -z "${!key:-}" ]; then
say FAIL "env key not set: $key"; fail=1
fi
done < .env.sample
fi
# 3. The service answers on the box you think you are on.
url="${HEALTH_URL:-http://127.0.0.1:8080/healthz}"
code="$(curl -s -o /dev/null -w '%{http_code}' --max-time 5 "$url" || echo 000)"
if [ "$code" = "200" ]; then
say OK "health $url"
else
say FAIL "health $url -> $code"; fail=1
fi
# 4. The change is small enough to read.
total="$(git diff --numstat | awk '{a+=$1; d+=$2} END {print a+d+0}')"
if [ "$total" -gt "${DIFF_BUDGET:-200}" ]; then
say FAIL "diff is $total lines; split the task"; fail=1
else
say OK "diff $total lines"
fi
# 5. Print a receipt you can compare across boxes.
say OK "host $(hostname) | $(date -u +%FT%TZ)"
if [ "$fail" -eq 0 ]; then say OK "preflight passed"; else say FAIL "preflight blocked"; fi
exit "$fail"
Run it like this:
set -a; . ./.env; set +a
chmod +x preflight.sh
./preflight.sh
Then run it on the other box, with the same commit checked out. Compare the receipts.
Same runtime, same env keys, same health answer, same budget verdict? The two boxes agree. That is all a contract is.
On the second host, hostname differs by design. Everything else should match. When it does not, you found the drift before a user did.
Where the second box comes from
This is the part of my workflow where a free server option is genuinely useful. I need a second, cheap host to run the same script against, and I do not want it on my laptop.
MonkeyCode bundles free model access and a free server option. I use the free models for the small mechanical changes, and the free server as the second box in the receipt comparison. That is the whole role it plays here.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
One honest caveat: free tiers are offered as-is by whoever runs them. Do not treat any free host as permanent infrastructure. Do not assume it keeps your data, your uptime, or your configuration.
A decision table for what belongs where
| Work type | Laptop | Second box | Notes |
|---|---|---|---|
| Prompt drafting, renames, test scaffolds | Yes | No | Cheap and revertible |
| Environment parity check | Yes | Yes | This is the point of the second box |
| Anything touching secrets or customer data | Yes | No | Keep it off shared hosts |
| Long-running jobs, queues, cron | No | No | Use a host you actually control |
| Production traffic | No | No | Nothing here is a prod story |
Print the table in your repo if your team argues about this. Arguing about a table is cheaper than arguing about an outage.
What the script will not catch
Be clear about the limits. This is a drift detector, not a test suite.
- It does not tell you the code is correct. It tells you the boxes agree.
- It cannot see missing data, permissions, or network policy you never declared.
- It trusts
.env.sampleto be complete. A stale sample passes happily. - It measures line counts, not risk. A two-line change can still ruin your week.
So keep real tests. Keep a rollback. Keep a human who reads the diff.
Who should skip this
You should not use this pattern if any of these are true.
- You handle regulated or personal data and cannot use a third-party box for the check.
- Your workload needs GPUs, persistent storage, or long-lived background processes.
- Your team already has staging parity and CI that runs the same assertions per commit.
- You cannot pin a runtime because the platform controls the image.
For those cases, keep the four replacement patterns and drop the free host. The contract file and the budget check cost nothing.
The short version
Two sessions drift because nothing forces them to agree.
So write the contract down. Pin the runtime. Declare the env keys. Cap the diff. Run the same script on both boxes and compare receipts.
If you want a second box without a credit card, the free server option is the cheapest way I have found to get one. Just keep the receipt, and read it before you merge.
Top comments (0)