An agent that says an item is impossible is asking for a person, not failing - #175
Merged
Merged
Conversation
…, not failing
A session-mode agent that read the repository, concluded the item cannot be
done as written, and said so was recorded as:
refused / no_target — "the agent made no changes"
which costs an attempt, reads as an ordinary failure, and is deliberately
excluded from the set a human is asked to look at. The rule in its own prompt
said "stop and say so plainly" — into a terminal nobody reads.
The harness already had the right word for this. `ESCALATED` is documented as
"a person has to resolve something before this can be attempted again; not a
failure of the item and not a transient condition", and it is the sole member
of `NEEDS_A_PERSON`. The code contradicted a comment eleven lines above it,
which already said a clean tree from a refusing agent "is a real answer, not a
failure to paper over".
So: the agent is told to write its reasoning to `.harness-refusal.md` and
change nothing else. The harness reads that note, deletes it, and ends the item
`escalated / item_impossible`, `blocked`, **without consuming an attempt** —
because what is wrong is the brief, and no number of retries rewrites a brief.
Deliberate, and tested:
- the note is read and removed *before* the tree is inspected, so it cannot
reach a commit, a diff, or a reviewer;
- a note left alongside real changes is not a refusal. The tree decides;
- a clean tree with no note escalates too, as `no_target`, naming the session
that holds the explanation. "It was impossible" and "it did nothing" are
indistinguishable from a clean tree, both want a human, and the reason text
is what tells them apart.
Not in scope: publishing the finding to the item's issue. `GitHub.comment()`
exists and that is a reasonable follow-up, but it is a projection of the
outcome rather than the outcome, and an item can run with no repository
configured at all.
Closes #174.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
thedancingdeveloper
added a commit
that referenced
this pull request
Aug 5, 2026
#176) Both found by running rdpapp R7 through the path added in #175. The agent refused an impossible item correctly, with citations, and the harness then mishandled the answer twice. **The state never reached the queue.** `Stop(state=BLOCKED)` was honoured only on the checks path, which copied `stop.state` across by hand; every other path left the item in `failed`. So R7 was recorded `escalated / item_impossible` with `attempts=0` — all correct — and sat in `failed`, where nothing looking for work that needs a person would ever find it. The state is now applied centrally, at the release call, beside `consumes_attempt` which was already read there. An empty `state` still means the caller chose, which is every path older than this taxonomy. **The run announced it as `FAIL R7`.** `ok` and `FAIL` were the whole vocabulary, so an outcome where nothing went wrong and no attempt was spent was reported as a failure — and set exit 1, which makes a queue of well-formed questions read to CI as a broken run. There is now a `YOU` marker, a closing `waiting on you, not on a retry` line, and `_is_failure` excludes `NEEDS_A_PERSON` from the exit status. The summary is extracted as `run_summary()` returning lines rather than printing them, because a formatting decision that only exists inside a print loop cannot be tested, and this one is a decision. One older test asserted `FAILED` for a clean tree while its own docstring said "that is a real answer, not a failure to paper over". It asserts `BLOCKED` now. Co-authored-by: sprooty <sprooty@sprooty.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Closes #174.
A session agent that concluded an item could not be done as written was recorded
refused / no_target — "the agent made no changes": an attempt spent, an ordinary failure, and outsideNEEDS_A_PERSON. Its prompt told it to "stop and say so plainly", which meant explaining itself to a terminal nothing reads.It now writes to
.harness-refusal.mdand the harness ends the itemescalated / item_impossible,blocked, not consuming an attempt — the brief is what is wrong, and retrying does not rewrite a brief.The note is read and deleted before the tree is inspected, so it reaches no commit, diff or reviewer. A note left alongside real changes is not a refusal — the tree decides. A clean tree with no note escalates as
no_targetand names the session, because "impossible" and "did nothing" look identical from an empty tree, both want a human, and the reason is what separates them.Nine tests; all four gates green locally.
🤖 Generated with Claude Code