You file the next change before any free run starts. A cheap answer still carries your real system. Free capacity never replaces a written architecture review.
You feel the pull when a model replies in seconds. Speed looks like progress, yet it is not. That speed is only a faster untrusted draft.
Your job is the seam between that draft and a host. The seam has constraints, a data flow, and failure domains. You name the next change before you cross.
Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode offers free model access and a free server option. Those two facts are availability claims, not a design.
You still own the architecture of the path. A free model does not know your blast radius. A free server does not inherit your production trust.
Constraints before comfort
You start with the box you cannot move. Your repo holds secrets, licenses, and user data. None of those may ride inside a prompt.
The free model lane writes text and does not merge code. You send the smallest context that can answer one question. You keep apply rights on a host you control.
The free server is a rented bench, not your factory floor. You do not know its neighbors, its lifetime, or its disk after you leave. Treat every file there as public scratch paper.
Confirm current limits on the product page before you plan. Quotas, hardware, and duration are not facts in this note. If the page disagrees with your memory, the page wins.
This review assumes you can read a diff and reject it. It assumes you can run tests on a machine you administer. If either assumption fails, you should stop here.
Walk the data flow
Picture a package that must cross a busy city. The label is the contract you wrote at home. The truck is the model call, and the dock is the server.
You write the contract on your machine first. It lists the question, the allowed files, and the forbidden paths. It also lists the next change you would keep.
The contract leaves your machine as plain text. That exit still counts, even when the vendor is generous. You strip tokens, keys, and customer rows before the text moves.
The model returns a draft, not a verdict. You save that draft beside the contract on disk. You diff it like mail from a careful stranger.
Only a bounded check may travel to the free server. The check is a command with a timeout and a fixture. It must not apply migrations or open production paths.
Results travel back as logs and exit codes. You read them on the host you already trust. The rented server does not get a vote.
Name the domains that break together
A failure domain is the set of things that break together. Free pricing does not draw that set for you. You draw the set before the run begins.
Domain one is the prompt you send away. A bad prompt can leak a key or a private path. The blast radius is every system that key can touch.
Domain two is the draft you might accept. A confident patch can invert a check or drop a guard. The blast radius is the next merge if you skip review.
Domain three is the free server you borrowed. A shared bench can keep files, logs, or a half-written env. The blast radius is whatever you copied onto that disk.
Domain four is the apply host you still own. That host can change real users if you let it. You keep it outside the free loop on purpose.
If two domains share a credential, you have one domain. Split them before you celebrate a green log. A green log on scratch is not a release.
A contract the shell can refuse
The script below is a labeled proposal, not a live client. No live vendor run is claimed in this note. You run it locally, then you judge the ticket.
It reads a small contract from your disk. It refuses secret-shaped strings and a missing next change. It writes a run ticket only when the review fields exist.
#!/usr/bin/env python3
"""Path review for a bounded check. Proposal, not a vendor client."""
import json, re, sys
from pathlib import Path
SECRET = re.compile(r"(?i)(api[_-]?key|secret|token|password)\s*[:=]\s*\S+")
REQUIRED = ("question", "allowed_files", "forbidden_paths",
"failure_domains", "next_change", "check_cmd")
def load(path):
data = json.loads(Path(path).read_text())
if not isinstance(data, dict):
raise SystemExit("contract must be an object")
return data
def review(data):
missing = [k for k in REQUIRED if not data.get(k)]
blob = json.dumps(data)
leaks = SECRET.findall(blob)
notes = []
if missing:
notes.append("missing:" + ",".join(missing))
if leaks:
notes.append("secret_shape_detected")
if "apply" in data.get("check_cmd", "").lower():
notes.append("check_cmd_looks_like_apply")
domains = data.get("failure_domains") or []
if len(domains) < 3:
notes.append("name_at_least_three_domains")
return notes
def main():
data = load(sys.argv[1])
notes = review(data)
if notes:
print(json.dumps({"ok": False, "blockers": notes}, indent=2))
raise SystemExit(2)
ticket = {
"ok": True,
"question": data["question"],
"check_cmd": data["check_cmd"],
"next_change": data["next_change"],
"run_on": "free_server_scratch_only",
"apply_on": "operator_host_after_review",
}
print(json.dumps(ticket, indent=2))
if __name__ == "__main__":
main()
You save a narrow contract next to the script. You keep the question small enough to test once. You keep the check command boring and bounded.
{
"question": "Does the retry helper stop after three attempts?",
"allowed_files": ["src/retry.py", "tests/test_retry.py"],
"forbidden_paths": [".env", "secrets/", "prod.tfvars"],
"failure_domains": ["prompt_text", "draft_patch", "free_server_disk", "apply_host"],
"next_change": "Add a test that the helper refuses a fourth attempt.",
"check_cmd": "python -m pytest tests/test_retry.py -q --timeout=30"
}
Run the review on the machine you administer. A blocked ticket means you are not ready to copy files. A clean ticket permits fixtures, not a deploy.
python3 review_path.py contract.json
If the script exits with code two, fix the contract. Do not bargain the blocker away in a side channel. The side channel is not your architecture record.
Copy only the allowed files to the free server. Run only the check command printed on the ticket. Pull the logs home, then delete the scratch tree.
scp -r src tests user@free-server:~/scratch/retry-check/
ssh user@free-server 'cd ~/scratch/retry-check && python -m pytest tests/test_retry.py -q --timeout=30'
ssh user@free-server 'rm -rf ~/scratch/retry-check'
Those shell lines are a sketch, not a promise. You replace the host with the name your plan gives. If the plan has no shell, you do not invent one.
What you change next
The next change is a sentence in the contract. In the sample, that sentence is a fourth-attempt test. You write it before the model is allowed to speak.
After the logs return, you edit that sentence or you keep it. You do not let the model replace it in silence. Your change note is the memory of the architecture.
You would change the script next by hashing allowed files. The ticket should name the bytes you meant to send. A later run should fail if those bytes moved.
You would also stamp an end time on the ticket. A free server session should expire in that stamp. If you cannot state an end, scratch has become home.
You would not add an auto-apply step to this ticket. The moment the ticket can merge, four domains collapse. That collapse is the bug this review exists to prevent.
Who should leave this path
This script catches shape, not the author's intent. A secret pasted without a keyword can still leave. A harmful check can look boring and still be wrong.
It does not measure the free option you might rent. It does not prove isolation, uptime, or data deletion. You must read the current vendor terms yourself.
Do not use this path for a production apply. Do not use it on repos that hold live secrets. Do not use it if you cannot reject a fluent patch.
Skip the path when the check needs private customer data. Skip it when the failure domain includes safety hardware. A free bench is the wrong room for that weight.
Skip it when your team needs an audited record you do not control. This note is a local habit you can show a reviewer. It is not a compliance product and should not pretend.
Close the review
File the change note on your own machine first. Run the local review until the ticket is clean. Then spend a free model call on the question you already wrote.
If a free server is still the right bench, use the ticket only. Read the current MonkeyCode plan once before you copy files. Decide with your constraints in view, not with a slogan.
Top comments (0)