Did the free agent box just rewrite your lockfile?
I see that claim inside otherwise careful pull requests.
A green install log is not a pin.
It is a resolver event on someone else's machine.
Why this FAQ exists
Coding agents now draft patches on remote hosts.
Free models make that loop cheap to repeat.
A free server makes the loop feel like a real build.
Then the pull request ships a mutated lockfile.
Reviewers skim the chat. They skip the diff.
Does that sound like your last Friday merge?
I am not talking about p50 or HTTP 200s.
I am talking about the works-on-the-agent-box lie.
Chat confidence is not a frozen graph.
How I use a free box without trusting it
I still want a scratch compiler for a first pass.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
MonkeyCode provides free model access and a free server option.
I use that pair as a draft compiler only.
I do not treat it as the source of truth.
The checklist below stands if you delete that product name.
You still need a lockfile interrogation, not a victory screenshot.
Myth 1: A green install on the free server is reproducible
The claim: "It installed. We are pinned."
What people paste: a chat log with no red lines.
What I ask: which lockfile, which command, which OS?
Run this on your laptop. Do not trust the transcript alone.
uname -s -m
node -v
python --version
git status --short -- package-lock.json yarn.lock pnpm-lock.yaml \
poetry.lock uv.lock Cargo.lock go.sum
Did the agent run npm install or npm ci?
Those commands are not the same contract.
npm install may rewrite the lockfile quietly.
npm ci refuses to guess. It demands an existing pin.
Same split exists outside npm.
pnpm install --frozen-lockfile is the strict door.
uv sync --frozen is the strict door.
Bare install is a shrug with extra progress bars.
Corrected model: a green install is a resolver event.
It is not a reproducibility certificate.
Ask which installer flag actually ran.
Myth 2: The model chose "latest," so the version is safe
The claim: "The agent picked a current package."
What people paste: a version string that looks recent.
What I ask: did the registry move while you were typing?
"Latest" is a moving tag.
It is not a security review.
It is not an SBOM. It is not even a pin.
Check what actually landed in the tree.
# Node
npm ls --depth=0
git diff -- package.json package-lock.json
# Python
git diff -- pyproject.toml poetry.lock uv.lock requirements.txt
python -c "import sys; print(sys.version); print(sys.platform)"
Did a transitive package shift with no direct bump?
That is the usual surprise hiding in a huge lockfile.
Did the agent add a second package manager file?
Now you have two graphs and one confused CI job.
Corrected model: the model suggested a name.
Your lockfile records the graph.
Only the graph is reviewable in git.
Myth 3: Skip the lockfile because the box is disposable
The claim: "Throwaway server. Why pin anything?"
What people paste: a deleted workspace and a shrug.
What I ask: then why is that mutation in the PR?
Disposable compute does not mean a disposable dependency graph.
The box dies. The lockfile commit lives in main.
If the agent regenerated the lockfile, treat it as hostile input.
Read it like you read a vendored blob you did not write.
git log -1 --stat -- package-lock.json pnpm-lock.yaml yarn.lock \
poetry.lock uv.lock Cargo.lock
git diff origin/main -- package-lock.json pnpm-lock.yaml yarn.lock \
poetry.lock uv.lock Cargo.lock
Look for churn you did not request.
Massive lockfile diffs hide version skating.
A one-line manifest change should not explode the graph without a story.
Corrected model: throw away the disk.
Keep the pin. Never keep a pin you did not read.
Myth 4: Tests passed on the agent box, so CI is redundant
The claim: "The free server already ran the suite."
What people paste: an "all tests passed" paragraph.
What I ask: which interpreter, which libc, which extras?
Native addons compile per platform.
Python wheels pick manylinux tags you never said out loud.
Optional extras change the graph after the chat ended.
node -p "process.version + ' ' + process.platform + ' ' + process.arch"
python -c "import platform,sys; print(sys.version, platform.machine(), platform.libc_ver())"
Warm node_modules on a rented disk is not CI.
CI should start from the lockfile, not from leftover directories.
I label the next file as a proposal.
I have not published timings for it. Wire it to your real installer.
# proposed-lockfile-gate.yml — proposal only
name: lockfile-gate
on: [pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Fail if lockfile is missing
run: |
test -f package-lock.json -o -f pnpm-lock.yaml -o -f yarn.lock \
-o -f poetry.lock -o -f uv.lock -o -f Cargo.lock -o -f go.sum
- name: Fail if install would mutate the lockfile
run: |
if [ -f package-lock.json ]; then npm ci; fi
if [ -f pnpm-lock.yaml ]; then pnpm install --frozen-lockfile; fi
git diff --exit-code -- package-lock.json pnpm-lock.yaml yarn.lock \
poetry.lock uv.lock Cargo.lock go.sum
Corrected model: the agent box is one host.
CI is the contract with the rest of the team.
A chat transcript is not a runner.
Myth 5: Linux on the free server matches every laptop
The claim: "We all run Linux containers anyway."
What people paste: one happy uname from the agent.
What I ask: who on the team is on ARM Macs right now?
Apple Silicon versus x86_64 changes optional native builds.
musl versus glibc changes which wheel you actually got.
The agent may install a linux-x64 binary you cannot run locally.
echo "local:"
uname -s -m
echo "lockfile hints (node):"
grep -E '"os"|"cpu"|"libc"' package-lock.json | head
If your lockfile encodes darwin-arm64 optional packages, a linux agent will "helpfully" rewrite them.
That rewrite is a bug, not a cleanup.
Cargo and Go have the same trap with target triples.
If the agent cross-compiled by accident, your CI image may disagree tomorrow.
Corrected model: record the platform that generated the lockfile.
Reject silent platform swaps in review.
Same repo, different CPU, different optional graph.
Artifact: the five-row decision table
I use this table before I approve a dependency diff.
Fill it from commands, not from memory.
Unknown counts as fail.
| Question | Evidence | Pass looks like | Fail looks like |
|---|---|---|---|
| Did install mutate the lockfile? |
git diff --exit-code on lockfiles |
Empty diff | Thousands of unrelated pins |
| Was the installer the strict one? | Chat or CI shows frozen/ci flags | Frozen flag present | Bare install in the transcript |
| Did language version match CI? |
node -v / python --version versus the CI file |
Same major.minor | Agent on a random major |
| Did platform stay still? |
uname -m versus optional packages |
Same arch family | darwin extras dropped on linux |
| Did we intend this package? | Diff of the manifest, not only the lock | Named direct change in the PR | Transitive storm, no story |
Copy the table into the PR.
Answer every row in public, not in a side chat.
If a row is blank, the review is not done.
A short local ritual after any free-server draft
Do this on a clean checkout.
Do not reuse the agent's node_modules or virtualenv.
# Proposed local ritual. Run on YOUR machine.
git fetch origin
git switch --detach origin/the-pr-branch # or: git switch the-pr-branch
git diff origin/main -- package.json package-lock.json \
pyproject.toml poetry.lock uv.lock requirements.txt Cargo.lock go.sum
if [ -f package-lock.json ]; then npm ci; fi
if [ -f pnpm-lock.yaml ]; then pnpm install --frozen-lockfile; fi
if [ -f yarn.lock ]; then yarn install --frozen-lockfile; fi
if [ -f uv.lock ]; then uv sync --frozen; fi
If the frozen install dies, the agent lied about "it works."
If the frozen install rewrites files, your PR is incomplete.
If you cannot even run a frozen install, stop merging dependency PRs.
Limitations
This FAQ does not replace npm audit policy.
It does not replace license scanning.
It does not prove a package is not malware.
It only proves you still own the pin.
That is a smaller claim than it sounds. Keep it small.
I am not claiming a specific free-server CPU.
I am not claiming a model name, a quota, or a benchmark.
Those change. Lockfile hygiene does not.
Hash-pinning Python deps needs a toolchain you already chose.
Do not paste --require-hashes if you never generated hashes.
Do not paste npm ci if the repo never committed package-lock.json.
Who should not use this approach
Do not use a free remote server for private packages.
Do not paste registry tokens into an agent session.
Do not treat this checklist as enough for PCI or medical software.
If your build needs GPUs or licensed compilers, skip the scratch-box path.
If you cannot run a frozen install locally, fix that first.
The FAQ will not save a machine you do not control.
Corrected mental model
The free model drafts.
The free server compiles a guess.
Your lockfile is the only dependency document that ships.
Chat is advertising. CI is the notary.
Ask the five questions. Then merge, or do not.
If you run the table on a real PR, tell me which row failed.
I want the boring row, not another green screenshot.
Top comments (0)