You sit down on Saturday with two free hours.
You want a tiny digest of failed CI logs.
A chat window is already open beside your editor.
You paste the idea and wait for a plan.
The reply looks complete and very confident.
Then you notice Redis and a worker pool.
You asked for a script, not a platform.
The model assumed scale you do not have.
Your Saturday is already half gone.
The problem you are actually solving
AI plans invent architecture you will not run.
They add queues, caches, and extra databases.
They treat a weekend toy like a funded product.
You do not need a bigger model for this.
You need a gate that fails before you code.
The gate should live in your repo as files.
This recipe is a proposed weekend workflow you can copy.
Run the examples on your machine before you trust them.
Do not treat the sample plans as production advice.
What you will ship by Sunday
You will write one JSON constraint card.
You will write a small Python checker script.
You will keep two fixture plans next to it.
The checker prints PASS or FAIL with reasons.
You run it before any implementation starts.
That is the whole working demo for this weekend.
What you will cut on purpose
Skip the web UI. Skip the Slack bot.
Skip GitHub comments and auto-opened issues.
Skip agents that rewrite the plan in a loop.
Skip Kubernetes. Skip a second database.
Skip paid search and paid embedding APIs.
If a step needs a credit card, cut it.
1. Write the constraint card first
Create a folder named plan-gate.
Put a file named card.json inside it.
Keep every rule short enough to read aloud.
{
"project": "ci-log-digest",
"goal": "Summarize one failed CI log into five bullets",
"max_services": 1,
"allowed_storage": ["sqlite", "local files"],
"paid_apis": false,
"forbidden": [
"redis",
"kafka",
"rabbitmq",
"kubernetes",
"elasticsearch",
"microservices",
"second database",
"worker pool"
],
"required_phrases": ["single process", "local files"]
}
Read that card out loud once.
If a line feels like theater, delete it.
A useful card is boring and short.
2. Save one bad plan and one good plan
Save this as fixtures/bad_plan.txt.
It should look like a typical chat dump.
Build a CI digest platform with three microservices.
Use Redis for job state and Kafka for log streams.
Add a worker pool and a second database for archives.
Deploy on Kubernetes with an autoscaling API gateway.
Save this as fixtures/good_plan.txt.
It should match the weekend goal only.
Build a single process CLI named cidigest.
Read one log file from local files.
Write five bullets to stdout.
Store an optional sqlite cache of prior runs.
No extra services and no paid APIs.
The bad plan is inflated on purpose.
The good plan names one process and files.
Your checker should split them without mercy.
3. Write the checker in plain Python
Save this as check_plan.py.
It uses only the Python standard library.
Label it as an example until you run it.
#!/usr/bin/env python3
"""Fail AI plans that invent extra architecture."""
from __future__ import annotations
import argparse
import json
import re
import sys
from pathlib import Path
def load_card(path: Path) -> dict:
data = json.loads(path.read_text(encoding="utf-8"))
required = {
"project",
"goal",
"max_services",
"allowed_storage",
"paid_apis",
"forbidden",
"required_phrases",
}
missing = required - set(data)
if missing:
raise ValueError(f"card missing keys: {sorted(missing)}")
return data
def tokenize(text: str) -> str:
return " " + re.sub(r"\s+", " ", text.lower()) + " "
def count_service_mentions(text: str) -> int:
labels = [
"service",
"microservice",
"worker",
"queue",
"cluster",
"gateway",
]
blob = tokenize(text)
return sum(blob.count(" " + word) for word in labels)
def check_plan(card: dict, plan: str) -> list[str]:
blob = tokenize(plan)
violations: list[str] = []
for token in card["forbidden"]:
needle = " " + token.lower() + " "
if needle in blob:
violations.append(f"forbidden architecture: {token}")
for phrase in card["required_phrases"]:
needle = " " + phrase.lower() + " "
if needle not in blob:
violations.append(f"missing required phrase: {phrase}")
if card["paid_apis"] is False:
paid_hints = ["stripe key", "paid api", "credit card", "prod account"]
for hint in paid_hints:
if " " + hint + " " in blob:
violations.append(f"paid API hint: {hint}")
service_hits = count_service_mentions(plan)
if service_hits > card["max_services"]:
violations.append(
f"service mentions {service_hits} exceed max_services {card['max_services']}"
)
storage_hits = [
name
for name in card["allowed_storage"]
if " " + name.lower() + " " in blob
]
if not storage_hits:
allowed = ", ".join(card["allowed_storage"])
violations.append(f"no allowed storage named ({allowed})")
return violations
def main() -> int:
parser = argparse.ArgumentParser(description="Reject inflated AI plans")
parser.add_argument("--card", required=True, type=Path)
parser.add_argument("--plan", required=True, type=Path)
args = parser.parse_args()
card = load_card(args.card)
plan = args.plan.read_text(encoding="utf-8")
violations = check_plan(card, plan)
print(f"project: {card['project']}")
print(f"goal: {card['goal']}")
print(f"plan: {args.plan}")
if violations:
print("result: FAIL")
for item in violations:
print(f"- {item}")
return 1
print("result: PASS")
print("plan stays inside the weekend card")
return 0
if __name__ == "__main__":
sys.exit(main())
4. Run the demo until the fixtures split
Use these commands from plan-gate.
Do not skip the exit codes.
python3 check_plan.py --card card.json --plan fixtures/bad_plan.txt
echo $?
python3 check_plan.py --card card.json --plan fixtures/good_plan.txt
echo $?
The first command should exit with status 1.
You should see forbidden architecture lines.
The second command should exit with status 0.
If both pass, your fixtures are too soft.
Tighten the forbidden list and run again.
The card is the product, not the model.
5. Use this table when a plan feels almost fine
Print the table beside your editor window.
If you argue with a FAIL, the card is winning.
That argument is the whole point.
| Signal in the plan | Weekend action | Why you cut it |
|---|---|---|
| Extra cache or broker | FAIL | You will not operate it |
| Second database | FAIL | One sqlite file is enough |
| Kubernetes or a cluster | FAIL | Saturday has no ops budget |
| Paid API or usage keys | FAIL | Free-tier surprises add up |
| Single process plus files | PASS | You can finish and demo |
| "We can add Redis later" | FAIL | Later becomes this weekend |
Treat "later" as a FAIL this weekend.
Later is how a script becomes a platform.
Write the cut in the card, not in chat.
Where a free model still helps
The checker does not write the plan.
A model can draft the first version.
You then force a rewrite against the card.
Paste the FAIL list back into the chat.
Ask for a plan that clears every line.
Run the checker until it prints PASS.
You can do that loop on your laptop.
You can also park the checker on a free server.
Keep the card in git either way.
You may want a hosted model for rewrites.
MonkeyCode offers free model access and a free server.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
Use them only to run the same script.
Do not let the host invent a wider stack.
Stay inside the card when the model replies.
If it adds a queue, fail the plan again.
Free hosting still does not change the rules.
6. Follow this numbered weekend schedule
- Write
card.jsonbefore you open a chat. - Save one bad plan and one good plan.
- Run
check_plan.pyuntil the fixtures split. - Draft your real idea with a free model.
- Paste the draft through the checker.
- Rewrite until you get PASS.
- Freeze the PASS plan in the repo.
- Stop. Do not code the app yet.
Do not add a dashboard in step eight.
The working demo is PASS versus FAIL.
Ship the cut, not the imaginary platform.
Honest limits
This checker is a keyword gate.
It will miss clever synonyms.
It will also flag quoted refusals.
"We will not use Redis" can still FAIL.
Add tests for your own phrasing later.
Do not pretend this is formal architecture review.
It will not measure token cost.
It will not review security.
It will not deploy anything.
False confidence is the remaining risk.
A PASS plan can still be technically wrong.
Read the plan after the script smiles.
Who should not use this
Skip this if you already have an architecture board.
Skip this for medical, payroll, or identity systems.
Skip this if several teams share on-call.
Skip this if you need streaming pipelines today.
A weekend digest is not that job.
Use a real design review instead.
What you skipped, written down
You skipped agents that keep calling tools.
You skipped MCP servers and browser drivers.
You skipped a pretty report in HTML.
You skipped auto-commits to a public repo.
You skipped "just one more microservice."
Write those skips into the project README.
The skip list protects Monday-you.
Monday-you will want to add Redis.
Show Monday-you the FAIL output from Saturday.
Close
You started with two hours and a chat window.
You end with a card, a checker, and a PASS plan.
The extra database never makes it into git.
Keep the card next to the code.
Run the checker before every generation.
That is the weekend, and it is enough.
Need a hosted box for that same loop?
Try the free model and free server path.
Leave the constraint card in version control.
Top comments (0)