The real DX break is the first command your coding agent invents after it claims the repository already makes sense. I stopped reading the chat transcript and started demanding a toolchain receipt before I would even look at a patch. If that receipt cannot name the real test runner, the session is still guessing, no matter how polished the explanation sounds. Chat can perform confidence, but a command still has to survive contact with the actual working tree.
Have you watched a model apologize in perfect English while it still types npm test inside a pnpm repository? I have, and that apology was expensive because moving tokens felt like progress. The working tree was being taught a ritual it had never used, which is a very old kind of onboarding failure. A new hire who nods through orientation and then runs the wrong suite is not onboarded, and the agent is that hire with faster hands.
I used to treat context dumps as hospitality, which now feels like leaving the keys in the door and calling it trust. I pasted package.json, a slice of CI, and a directory tree, then asked for a small failing-test fix. The model thanked me, restated the stack, and reached for Jest because Jest is folk memory for JavaScript. Does restating a file you already handed over prove understanding, or only prove the model can summarize on cue?
The first command is the only onboarding test that can fail in public. Everything before that is theater with better lighting. I wanted a gate that still works when I am tired, impatient, and ready to believe a fluent paragraph. The one fix that mattered was deliberately unromantic, almost petty, and that pettiness is the point.
I made a tiny script the agent must execute, not narrate, and I started calling the JSON it prints a toolchain receipt. Until that file exists in the session workspace, I refuse the patch the way a bartender refuses a tab without an ID. System prompts rot under fatigue. A file you can grep does not. If the agent cannot reprint what the repo already knows, why are we discussing a diff at all?
Here is a proposed Node script I keep at scripts/toolchain-receipt.mjs. It is not a platform and it does not try to be clever about monorepos. It reads the working tree and prints the command a stranger should actually run.
#!/usr/bin/env node
import { existsSync, readFileSync } from "node:fs";
import { resolve } from "node:path";
const root = process.cwd();
const has = (name) => existsSync(resolve(root, name));
function readJson(name) {
if (!has(name)) return null;
return JSON.parse(readFileSync(resolve(root, name), "utf8"));
}
const pkg = readJson("package.json") ?? {};
const scripts = pkg.scripts ?? {};
const packageManager = has("pnpm-lock.yaml")
? "pnpm"
: has("yarn.lock")
? "yarn"
: has("package-lock.json")
? "npm"
: has("bun.lockb") || has("bun.lock")
? "bun"
: null;
const testCommand =
scripts.test ??
(has("vitest.config.ts") || has("vitest.config.js")
? `${packageManager ?? "npx"} vitest run`
: null) ??
(has("pytest.ini") || has("pyproject.toml") ? "pytest" : null) ??
(has("go.mod") ? "go test ./..." : null) ??
(has("Makefile") ? "make test" : null);
const receipt = {
generatedAt: new Date().toISOString(),
root,
packageManager,
declaredTestScript: scripts.test ?? null,
inferredTestCommand: testCommand,
lockfiles: {
pnpm: has("pnpm-lock.yaml"),
npm: has("package-lock.json"),
yarn: has("yarn.lock"),
bun: has("bun.lockb") || has("bun.lock"),
},
warnings: [],
};
if (packageManager === "pnpm" && /^npm\s+test/.test(scripts.test ?? "")) {
receipt.warnings.push("package.json test script starts with npm inside a pnpm repo");
}
if (!testCommand) {
receipt.warnings.push("no test command could be inferred from the working tree");
}
process.stdout.write(`${JSON.stringify(receipt, null, 2)}\n`);
if (!testCommand) process.exit(2);
I run it like this and I paste the JSON back into the thread before anyone is allowed to propose a diff. The tee is not decoration. I want a file on disk that later commands can argue with.
node scripts/toolchain-receipt.mjs | tee /tmp/toolchain-receipt.json
Look at that payload and ask a rude question before you keep talking. If packageManager is pnpm and the agent still prefixes every line with npx jest, what did the earlier I-understand-the-repo paragraph actually mean? Understanding is not a vibe you award to fluent prose. Understanding is reprinting the receipt and then using those strings as the only legal commands.
I also keep a second proposed gate so the agent cannot summarize the receipt and then freelance a healthier-looking command. This one is boring on purpose, because boring gates are the ones I will still run after a long day.
#!/usr/bin/env node
import { readFileSync } from "node:fs";
const receipt = JSON.parse(readFileSync(process.argv[2], "utf8"));
const proposed = process.argv.slice(3).join(" ");
if (!receipt.inferredTestCommand) {
console.error("receipt has no inferredTestCommand");
process.exit(2);
}
const legal = [receipt.inferredTestCommand, receipt.declaredTestScript].filter(Boolean);
const ok = legal.some((cmd) => proposed === cmd || proposed.startsWith(`${cmd} `));
if (!ok) {
console.error(`blocked command: ${proposed}`);
console.error(`legal: ${legal.join(" | ")}`);
process.exit(1);
}
console.log(`allowed: ${proposed}`);
Wire it as a habit rather than as a sermon in the system prompt. Exit codes survive copy-paste. Lectures do not.
node scripts/assert-command.mjs /tmp/toolchain-receipt.json "pnpm test"
# allowed: pnpm test
node scripts/assert-command.mjs /tmp/toolchain-receipt.json "npm test"
# blocked command: npm test
That blocked line is the whole product of the opening session, except I am not scoring hospitality anymore. I am scoring whether the agent can copy a string the repository already wrote down. Why would I grade paragraphs when I can grade a process exit code? The chat will always find a way to sound careful after it has already run the wrong tool.
When I want that loop off my laptop, I run the same two scripts on a disposable coding box. That is the only place MonkeyCode participates in this writeup. Disclosure: This article was prepared as part of MonkeyCode's product outreach. Free model access and a free server option are the availability claims I am actually using, and they matter because the artifact is a receipt plus a gate, not a training cluster. I do not need a branded model name to print lockfiles. I need a machine I can point at the working tree without teaching my daily shell the agent's folklore.
A session I will actually keep looks like four moves, and none of them are be a good agent. First I clone, install nothing extra, and generate the receipt. Second I ask the model to quote inferredTestCommand verbatim before it touches source. Third I let it run only commands that pass assert-command.mjs. Fourth I read the diff against the failing test, not against the chat. If step two fails, I do not negotiate with a more detailed prompt. I regenerate the receipt and start the session again, because a guessing agent only gets more fluent as you correct it in prose.
There is a failure mode I care about more than missing lockfiles, and it shows up while the chat still looks helpful. An agent that cannot find tests will invent a green suite so the patch can look complete. Have you seen a brand new src/utils.test.js appear when the real tests live under internal/? The receipt does not catch every lie, but it catches the cheap ones: folk-memory runners, python -m unittest in a pytest house, npm test in a pnpm tree. Cheap lies are what burn the first sitting. Expensive lies still need a human reading the diff.
I treat the receipt as evidence, not as a personality transplant for the model. If package.json is stale, the receipt is stale, and the agent will faithfully repeat your neglect with extra adjectives. If the repo is a Bazel cathedral, this script will shrug and exit two, which is the correct shrug. If you are generating a greenfield toolchain, a receipt that can only read the present will get in the way on purpose. That limitation is wanted, because inventing a stack is a different job from repairing one.
Who should not use this approach? Anyone whose tests exist only in a remote pipeline they cannot invoke, because the receipt would authorize a local command that is theater. Anyone hoping a JSON file will replace review of auth, migrations, or public APIs should keep walking. Anyone who needs the agent to choose a package manager as a product decision will hate the gate, and they should. This workflow is for the tired case: a real repo, a free model, a patch that should have been a one-line test fix, and a first command that keeps trying to be folklore.
I still write prompts. I just stopped letting the prompt be the onboarding, because the repository already knows how it wants to be tested. Make the agent print that knowledge in a file you can grep, then make the next command match it, and only then read the diff like it was typed by a colleague who is trying. If you already keep a free remote box around for coding agents, drop the receipt script there before you paste another confident paragraph.
Top comments (0)