← Back ← Back

Bidirectional Checkers (zero LLM cost)

Direction 1: Action -> Reality

Checks that a recent action actually had the effect it claimed.

write_file-verifier (after every write_file, automatically fired by the bridge):
- Read the file back
- Hash the content
- Compare to the "expected hash" the caller passed
- If mismatch: write was silently lost, escalate

build-verifier (after every npm run build):
- Check the dist/assets/ directory
- Check that the latest .js file has a different hash from the previous
- If same hash: build produced nothing, escalate

deploy-verifier (after every SFTP upload):
- Check that the asset exists on the VPS
- Check that the new bundle is in the index.html
- Check that deploy_info returns the new hash
- If any of these fail: deploy didn't take, escalate

command-verifier (after every run_command):
- Check exit code
- If exit != 0, capture stderr and escalate
- If exit = 0, run a follow-up read to confirm side effects

Direction 2: Reality -> Plan

Checks that the world still matches what we expect.

plan-executor (during plan execution):
- Before each step: verify the preconditions (file exists, dir writable)
- After each step: verify the postconditions (file has new content, build succeeded)
- If precondition fails: skip step or escalate (don't try to write to a missing file)
- If postcondition fails: retry, rollback previous step, or escalate

config-consistency (every 5 min):
- bridge /api/agent/services returns 27 services running
- If < 27: which one died? Toast the operator
- Pure curl, 0 LLM

bundle-monotonicity (every 5 min):
- For each deploy in the last hour, verify the bundle hash in deploy_info matches the hash of the file uploaded
- If a hash in deploy_info doesn't have a matching file: drift, escalate

Direction 3: Checker -> Action

Each finding has a deterministic, automated response.

Finding Auto-response
2+ bridge endpoints fail Restart bridge process
deploy_info != disk Touch index.html to bust cache
css-purity > 5 Queue chat task to fix
chat-eval fails Toast operator, don't auto-restart chat
Build produces no new hash Roll back to previous deploy
Write file but hash doesn't match Re-attempt write with smaller chunks

Why this is "clever" without LLM

The cleverness is in the RULES, not the LLM:
- "If X then Y" is reliable, fast, free
- LLM is only called for: generating the plan, generating the file content for write_file, generating the report
- That's 2-3 LLM calls per task, not 8+

Avoiding 429s

Three rules:
1. Checkers are 100% rule-based, 0 LLM (current state)
2. No checker ever calls an LLM directly
3. LLM calls happen only when operator types something or a plan executes
4. If we need interpretation, write a more specific rule instead of asking an LLM

This way, running 20 checkers in parallel costs nothing in the LLM budget.

Concrete next steps

Build these without LLMs:
1. write_file-verifier (in bridge: hash after write, return mismatch if any)
2. build-verifier (shell script in deploy.sh)
3. deploy-verifier (in deploy.sh: verify hash matches before saying "done")
4. config-consistency (cron, every 5 min, 0 LLM)
5. plan-executor (new component, deterministic state machine)

Each one is a small file. No LLM cost. The chat's intelligence comes from planning, not from monitoring.

Bidirectional loop without 429s

operator: "add dark mode"
   |
   v
[LLM call 1: plan]
   |
   v
[operator approves]
   |
   v
[deterministic executor] <----+
   |                          |
   v                          |
[LLM call 2-N: write content] |
   |                          |
   v                          |
[build-verifier] --if fail----+
   |                          |
   v                          |
[deploy-verifier] --if fail--+
   |                          |
   v                          |
[LLM call final: report]
   |
   v
operator sees Report

Total LLM calls: ~3-5. Checkers are pure rules. 429s are avoided because checkers don't burn the LLM budget.