Repository navigation
Sonny goals: keep an agent working until a check command passes - #341
Conversation
The goal tool sets an agent, or a task it made, a goal: what done looks like and a shell command that exits 0 once it is. The lookout runs the check each time the agent's turn completes; while it fails, the agent gets a turn with its exit code and the end of its output, and its lead hears nothing. The goal ends once the check passes, the budget is spent, two turns it started call no tool, or the agent gives up with blocked, and the lead hears that last turn with how it ended. No judge, nothing in the daemon. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
Security findingsAdvisory findings (3)
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2cbd7cdd8e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
🛡️ Codex Security Review · Automatically triggered
Here are some automated security review suggestions for this pull request.
Reviewed commit: 2cbd7cdd8e
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
- A check's output is read as it prints, keeping only its end. - A turn's goal is read fresh as the turn ends, so one a lead set or cleared meanwhile counts. - One check at a time per agent; a turn that ends while one runs is plain news. - A task is the caller's by its creator's id, not its name. - A turn waiting for its check keeps the replay cursor before it, so a restarted lookout runs the check again. - The check runs without the provider keys in ~/.agent/env. - The macOS skip is back on the trigger test, not on note_for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8fd8d02cee
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Main does not build since #344 renamed Places::plist to Places::job while #318's restamp still called the old name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
|
The I've merged main and ported the one-line rename in 31231ed. It becomes a no-op once main carries the same fix. Generated by Claude Code |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 31231ed4d7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- A goal left by an agent deleted while the lookout was away is dropped when another agent with that name ends a turn. - A goal's next turn is not news while it runs, as its end is. - A goal cleared or set again while its check ran is plain news, even when that check passed. - Listing goals shows a lead its tasks' goals, whoever set them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bf1e342bd4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
# Conflicts: # sonny/src/lookout/mod.rs
…e its check ran ends so Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e79ca9916d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 97d3e40d36
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…lay runs again Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6aa2f0ee13
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
🛡️ Codex Security Review · Automatically triggered
Here are some automated security review suggestions for this pull request.
Reviewed commit: 6aa2f0ee13
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
…turn is not counted twice Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
The reason an agent gives up for, and a check it set itself, are its own text; the lead reads them in the turn or with the goal tool. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 025fab9506
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… turn waits on one Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e849c96754
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ves a later turn's news Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
There was a problem hiding this comment.
🛡️ Codex Security Review · Automatically triggered
Here are some automated security review suggestions for this pull request.
Reviewed commit: 09f8d934ee
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 81aa809a16
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…d a lookout that gives way mid-check Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
…-kxnbh9 # Conflicts: # sonny/src/served.rs
…-kxnbh9 # Conflicts: # sonny/src/lookout/mod.rs # sonny/src/lookout/updates.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cb125bcdfc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: acf562c157
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ched or not Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 968a2e527d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let Some(forward) = self.forwarding.remove(&(name.to_owned(), turn)) else { | ||
| return; | ||
| }; |
There was a problem hiding this comment.
Preserve goal settlements when a trigger forwards the turn
When a task with a goal runs through a trigger with --reply-to, a slow check can lose its terminal notification. trigger::reply() forwards the completed turn using from: {bot, turn}; the accepted/queued handler in Updates::event() then unconditionally removes that turn's forwarding entry. When the check subsequently settles, this early return discards the goal outcome, even though the forwarded reply contains only the task's answer, not its check result. Keep goal-held entries when processing forwarded replies, just as read() now preserves them for wait, so the lead still hears whether the goal passed or stopped.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 48a7962. When a trigger passes a turn's answer on and that turn's goal check is still running, the turn now stays held with its reply dropped, so the lead still hears how the goal ended. The goal unit test covers this case.
Generated by Claude Code
… to tell Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 48a7962dde
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "deleted" => { | ||
| self.worked.retain(|(name, _), _| name != bot); | ||
| if let Some(goal) = self.goals.remove(bot) { | ||
| end(&self.store, &goal); | ||
| } |
There was a problem hiding this comment.
Cancel the outstanding pursuit when its bot is deleted
If a bot is deleted during a slow goal check and its name is reused, this branch removes the saved goal but leaves the old pursuit in self.checking. If the replacement bot sets a goal and completes a turn before that check finishes, the checking.contains_key(bot) guard discards its completion. The old pursuit then observes the changed goal and settles without submitting a continuation, leaving the replacement's goal idle indefinitely. Abort and remove the deleted bot's outstanding pursuit so its checking state cannot suppress work for a different bot identity.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 107d22e. Deleting an agent now aborts and forgets its running check, which kills the check's process group, so a new agent under the same name starts clean.
Generated by Claude Code
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 107d22e194
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if self.checking.contains_key(bot) { | ||
| return None; | ||
| } |
There was a problem hiding this comment.
Restart pursuit when a completed turn belongs to a replacement goal
If an agent replaces its goal in a new turn while the previous goal's slow check is running, this bot-only guard discards the new turn's completion despite having just loaded the replacement goal. When the old check finishes, pursue() detects the changed set_ms and returns without submitting a continuation, so the replacement goal remains idle indefinitely unless someone supplies another turn. Associate outstanding checks with their goal generation and cancel or supersede the old pursuit when a completion belongs to a replacement goal.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in e7083fd. A running check now records the goal's set_ms and its turn. When a turn completes under a goal that was set again, the old check is aborted, its turn is let go as plain news, and the new turn is checked against the new goal. A late settle from the old check no longer clears the new one, because settled matches the turn.
Generated by Claude Code
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e7083fd5b1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let goal = Some(outcome.to_owned()).filter(|outcome| !outcome.is_empty()); | ||
| self.tell_ended(name, turn, &status, from, None, origin, goal); |
There was a problem hiding this comment.
Preserve goal outcomes while the lead is still waiting
If the lead waits on multiple task turns with any: false, one task's goal check can settle while another task is still running. This call then reaches tell_ended(), which returns immediately when waiting_on contains the completed turn's handle, discarding the goal outcome after its forwarding entry and goal file have been removed. The eventual wait result contains only the turn result, not the check outcome, so the lead never learns how the goal ended. Unlike the previously fixed read() removal paths, the current tell_ended() waiting-handle guard still suppresses terminal goal outcomes. Exempt goal outcomes from that suppression or retain them until the wait finishes.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in b3c9ede. tell_ended now suppresses a turn the lead is waiting on only when that turn carries no goal outcome, so a check that settles during a multi-turn wait still reaches the lead. The goal unit test covers this case.
Generated by Claude Code
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY
Requested by George · project thread
This is step 2 of the autonomy plan, modeled on Codex's and Claude Code's
/goal. The difference is that "done" comes from a command's exit code, not a model's opinion. No judge is involved, and the daemon doesn't change: the lookout runs all of it.What changes
A new
goaltool for every Sonny agent:set {done_when, check, bot?, budget_tokens?, timeout_s?}sets a goal on the agent itself or on a task it made. A task counts as made by the caller when its creator id matches the caller's.blocked WHYgives the agent's own goal up.clear NAMEremoves a goal.duplicate: true.STORE.lookout/goals/BOT.json.Each time that agent's turn completes, the lookout reads the goal file fresh and runs the check with
sh -cin the folder that turn worked in:ifdoes, but without the provider keys an agent's shell goes without (Sonny'skept_keys).goal) showing the exit code and that tail.triggers, because the check runs outside any sandbox.The goal ends at the first of these:
setreachbudget_tokens;blocked;A turn that fails or is stopped ends nothing.
The lead hears only the end.
- shop.fix: turn:shop.fix/5 completed, asked by goal, and met its goal: its check exits 0.waitthat read the turn.goal-BOT-TURN.Restarts: a turn waiting on its check keeps the replay cursor before it. A restarted or reconnected lookout stops the old check and runs it again.
docs/SONNY.mdgets a Goals section, anddocs/LOOKOUT.mdlists goal-held turns.Left for later, by George's call: #355. It covers sandboxing the check, one crash-replay edge, and keeping an outcome on disk until the lead hears it.
Tests
goals.rs:updates.rs: a goal's turns become news only once the goal ends, and its outcome survives a later turn and awaitread.test_served.py:test_a_goal_keeps_its_agent_working_until_its_check_passestest_a_goal_whose_agent_only_answers_stopstest_a_goal_its_lead_sets_counts_from_the_task_turn_that_ends_nexttest_a_turn_that_ends_while_its_goal_is_checked_starts_no_other_checktest_a_goal_checked_when_its_lookout_gives_way_is_checked_by_the_nextcargo test -p sonnypasses (404), and clippy-D warningsand fmt are clean.tests.test_served,tests.test_lookoutandtests.test_acppass.No screen changes. The visible output is the task-update line above.
Step 1 (helpers that share the daemon's life cycle) comes next as daemon companions, replacing #333.
🤖 Generated with Claude Code
https://claude.ai/code/session_013jkdGHCyGRHdT5WYDPKVFY