docs(agents): forbid ending a subagent turn narrating an intention to wait - #5019
Open
bobmatnyc wants to merge 1 commit into
Open
docs(agents): forbid ending a subagent turn narrating an intention to wait#5019bobmatnyc wants to merge 1 commit into
bobmatnyc wants to merge 1 commit into
Conversation
… wait A subagent's turn ends the moment it stops emitting tool calls, and that stop is its result to the parent. Nothing re-invokes it afterward: the main loop is re-invoked on background-shell completion, but there is no subagent equivalent, and `CLAUDE_SUBAGENT_BG_SHELL_MAX_MS` explicitly lets a subagent-owned background shell outlive the turn that started it. Parent-driven `SendMessage` is the only resume path. Agents nonetheless end turns with "I'll wait for the pull to finish" or "will resume when the monitor reports completion" and strand the task — observed five times in one session. Adds a `Never Narrate a Wait` section to `BASE-AGENT.md`, placed before `Git Workflow` so an agent reads it before starting work rather than at the bottom under `Finishing Work`, which it reaches only when it already believes it is done. The section names the working shape (start the operation with `run_in_background`, poll a backgrounded until-loop), calls out that foreground `sleep` is blocked in this harness — the trap a bare "poll" instruction walks agents into — and states that reporting unfinished state and stopping is a correct outcome. The redundant "never spawn a background monitor as a wake mechanism" bullet under `Your own gates DO block` collapses to a pointer at the new section. Both copies stay byte-identical per `scripts/check_agent_assets.sh`. 🤖🤖🤖 Generated with trusty-mpm — https://github.com/bobmatnyc/trusty-tools
bobmatnyc
force-pushed
the
fix/base-agent-no-narrated-wait
branch
from
August 6, 2026 17:57
0707d4c to
6d14749
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Defect
A subagent handed a long-running operation ends its turn narrating an intention to wait — "I'll wait for the pull to complete", "will resume automatically when the monitor reports completion", "monitoring in the background" — with its task unfinished. Nothing resumes it. Observed five times in one session; the parent had to notice and re-engage each one by hand.
This is a harness gap, not misuse. A subagent's turn ends the moment it stops emitting tool calls, and that stop is its result to the parent.
CLAUDE_SUBAGENT_BG_SHELL_MAX_MSexplicitly lets a subagent-owned background shell outlive the subagent's turn, but nothing reconnects the two when it finishes: the main loop is re-invoked on background completion, and there is no subagent equivalent. Parent-drivenSendMessageis the only resume mechanism.Resolution
One new section in
BASE-AGENT.md,Never Narrate a Wait, carrying five rules: never end a turn narrating a wait; stay in the turn viarun_in_backgroundplus an until-loop; foregroundsleepis blocked in this harness so the waiter must be backgrounded too; reporting unfinished state and stopping is a correct outcome; never re-issue a long-running command because a foreground shell returned early at the ~120s cap.Rule 3 is called out explicitly because a prior session recorded that plain "poll" advice was itself producing the parking it meant to prevent —
sleep 60 && checkis the shape agents reach for, and it does not run here.The now-redundant "never spawn a background monitor as a wake mechanism" bullet under
Your own gates DO block, in the foregroundcollapses to a pointer at the new section.Where it sits, and why
Immediately before
## Git Workflow, in the operating-rules band afterPM Authority & Escalation— roughly a quarter of the way into the file.The existing turn-ending guidance (
Finishing Work — Push, Report, Stop,Report, don't promise) lives at ~line 250 and is framed around CI. An agent reads that band only once it believes it is finishing. The stranding happens mid-task, on a build, a clone, a VM run — so the rule has to be in front of the agent before it picks its first long command, not appended at the bottom.Register matches the file: numbered imperatives, one 🔴 marker on the blocked-
sleeptrap, one code block. No harness-internals essay.Byte-parity mirror
BASE-AGENT.mdexists in two crates and is held at byte parity byscripts/check_agent_assets.sh:crates/trusty-mpm/src/assets/agents/BASE-AGENT.mdcrates/trusty-code/src/assets/agents/BASE-AGENT.mdBoth are in the gate's PARITY set (5
BASE-*+ 24 roster agents), not the 4-file pinned-deviation set, so no re-pinning was needed andscripts/agent-asset-pins.tsvis untouched. Both files hash0ee276e2a1d5ab5a7e9aa2de72f6a52924017ec4after the change.Ownership and how a user picks this up
Framework-owned, overwritten on install.
crates/trusty-mpm/src/core/bundle_all.rs:107registers it asoverwrite("agents/BASE-AGENT.md", BASE_AGENT)—InstallPolicy::Overwrite, notSeedOnce. A user-modified copy is still respected by the deployer's ownership rule (a file whose on-disk content no longer matches what tm wrote is left alone), but the shipped default tracks upgrades.A rebuild alone does not deploy it. The asset is
include_str!-embedded, so it reaches an agent only through an install plus an asset deploy:Session launch deploys agents exactly once, at launch (DOC-34/#2002);
tm sessions sync-assetsis the offline redeploy for a live session.Gates
cargo fmt --checkcargo check -p trusty-mpmFinished dev profile ... in 41.53s, EXIT=0cargo test -p trusty-mpm4724 passed; 1 failed; 7 ignored— see belowbash scripts/check_agent_assets.shscanned 30 byte-parity file(s) (floor 20), all match; 4 pinned deviation(s) match upstream — OK.bash scripts/check_sld.shscanned 56 spec doc(s) + 3115 code file(s); 0 error(s), 0 warning(s)bash scripts/check_line_cap.shmeasured 3742 tracked .rs file(s) (floor 500); 7 allowlisted, 0 violations — OK.bash scripts/check_test_pointers.shresolved 22070 Test: citation(s) (floor 200) — 0 dangling pointers — OK.bash scripts/check_changelog_fragment.shscanned 4 changed path(s); all 2 crate(s) with source changes are recorded.The one failure is pre-existing
client::executor::tests::execute_doctor_against_test_daemon— a documented baseline flake (docs/reference/test-ladder-baseline.md). Proven, not assumed: with bothBASE-AGENT.mdfiles reverted toorigin/mainviagit checkout origin/main -- <paths>, the fullcargo test -p trusty-mpmfailed on the same single test:Two other flakes seen and traced, not silenced
An earlier run also failed
compose_session_instructions_display_matches_live_promptand..._with_override. Cause found, and it is not this diff: the assertion diff is the agent roster embedded in the PM prompt, differing by five user-tier entries (copyeditor,pangram-editor,proofreader,writer,writing-critic) between the test's two prompt builds. Both builds scan the live$CLAUDE_CONFIG_DIR/agentsdirectory, and that directory was being rewritten by a concurrent deploy on this machine at the time (drwxr-xr-x ... Aug 6 13:31 ., mid-run). Same machine, load average 35/51/64.cargo test -p trusty-mpm --bin tmon pristineorigin/mainassets passed 3/3 at1518 passed; the same suite with this change passed 1/3 and failed with a different test (guided_fallback_non_git_dir_with_managed_env_settles_quickly_returns_promptly, a timing test) on one of the reds. Nothing was ignored, cfg-gated, or excluded.check_test_pointers.shdid not return within 9 minutes on a second invocation under that load; its result above is from the earlier chain, on identical content — this change touches zero.rsfiles.Changelog
crates/trusty-mpm/changelog.d/5019-base-agent-no-narrated-wait.mdandcrates/trusty-code/changelog.d/5019-base-agent-no-narrated-wait.md, oneChangedcategory each.No issue filed — instruction fixes go straight into the assets.
🤖🤖🤖 Generated with trusty-mpm — https://github.com/bobmatnyc/trusty-tools