diff --git a/src/servers/api/bots/brief.ts b/src/servers/api/bots/brief.ts index 8ff7f4eb..8df0fa29 100644 --- a/src/servers/api/bots/brief.ts +++ b/src/servers/api/bots/brief.ts @@ -59,17 +59,47 @@ to. "tell me", "let me know", "ping me", "message the todo guy" all mean the sam - **The first run establishes the baseline** and does not fire. A bot that announces the current headline the moment it is armed has told the owner something they did not ask about. -## Arming is a background job, and nothing else +## Arming — the whole mechanism, so you do not go looking for it -Use the background job you already know, with the **hand-back-then-re-arm** behaviour. Its own instructions -tell you the rest; the parts that matter here: +**Do not read the commander skill.** It is about spawning agents in a loop and none of it applies here. +This is everything a bot needs: -- The watch is a **cheap shell check that exits when the condition is true.** Polling costs nothing that - way, and you are woken only when something happened. Do not build a loop that wakes you on a timer to - look for yourself — that costs a turn every tick, forever, for a site that has been up all week. -- **Exit is the signal.** Print what changed on the way out, so the turn you are handed has the answer in - it and does not have to go and look again. -- **Re-arm before you end the turn**, exactly as you armed it the first time. Same condition, same command. +1. **Write the check as a shell script in THIS directory**, named after the bot — \`newweb-uptime.sh\`, not + somewhere under \`/tmp\`. It has to survive a reboot, and \`/tmp\` does not. +2. **Run it with the Bash tool, \`run_in_background: true\`.** That is the arming. You will be handed back + when it exits. +3. **The script waits in the shell and exits when the condition is true**, printing one line saying what + happened. The exit IS the signal — nothing else tells anyone it fired. + +The shape, which almost every bot is a variation of: + +\`\`\`bash +#!/bin/bash +# state lives beside this script, so a restart resumes rather than re-baselines +STATE="$(dirname "$0")/newweb-uptime.state" +fails=0 +while true; do + code=$(curl -s -o /dev/null -w '%{http_code}' -L --max-time 10 "https://example.com/" || echo 000) + if [ "$code" = "000" ] || [ "$code" -ge 500 ]; then + fails=$((fails + 1)) + # twice in a row, never once — a single failed request is a blip + if [ "$fails" -ge 2 ]; then echo "DOWN http=$code"; exit 0; fi + else + fails=0 + fi + sleep 60 +done +\`\`\` + +For a "has it changed" watch, the same shape with the comparison against \`$STATE\` instead of a counter: +fetch, extract the smallest stable piece, compare, and \`exit 0\` printing the new value when it differs. +Write the new value to \`$STATE\` **before** exiting, or the next arming fires on the same change again. + +4. **When you are handed back**, do what the owner asked, then **re-arm the same script the same way, + before you end the turn**. Act, then re-arm, in the one turn. Never build a second loop on top of this. + +Do not go hunting for how any of this works — it is above, and looking costs the owner a minute of tool +calls before anything is armed. ## What to do when it fires