Skip to content

fix(mod): report blank worker turns only, not refusals - #69

Merged
omartelo merged 1 commit into
mainfrom
fix/refusal-not-reported
Oct 10, 2026
Merged

omartelo merged 1 commit into
mainfrom
fix/refusal-not-reported

Conversation

@omartelo

Copy link
Copy Markdown
Collaborator

Measured on Claude Code 2.1.296: a real API refusal ends the turn through StopFailure (error invalid_request), then turn.complete with reason refusal, and fires no classic.Stop. hooks/worker-answer.js posts only after reading the main-loop Stop, so its refusal branch never ran: zero POSTs to /mod/answer.

API errors behave the same, and neither carries background_tasks, so the mod cannot tell a failed turn with nothing running from one whose background work resumes it later. Posting would answer the errand twice.

  • hooks/worker-answer.js: drop the refusal branch; only a blank Stop posts {unanswered: "blank"}. The comment states the measured behaviour for refusal and error.
  • Tests: the ones that pinned "refusal posts unanswered refusal" asserted a contract the provider never delivers. Replaced by a test that a refusal turn (no Stop) posts nothing, in both the node suite and the engine suite. Blank tests kept.
  • docs/mod-answer.md and CHANGELOG.md [Unreleased]: the plugin reports blank turns only; refusal and API errors are not reported. Fixtures untouched; the lich contract still accepts refusal.

Checked: node --test tests/*.test.mjs (392 pass), claude plugin test . (33 pass), claude plugin validate .claude-plugin/plugin.json (passed).

Measured on Claude Code 2.1.296, a real API refusal ends the turn through
StopFailure (error invalid_request), then turn.complete with reason refusal,
and fires no classic.Stop. The worker-answer mod only posts after reading the
main-loop Stop, so its refusal branch never ran. API errors behave the same,
and neither carries background_tasks, so the mod cannot tell a failed turn
with nothing running from one whose background work resumes it later; posting
would answer the errand twice.

The tests that pinned "a refusal posts unanswered refusal" asserted a contract
the provider never delivers: they fed a Stop before a refusal completion,
which Claude Code 2.1.296 does not produce. They are replaced by a test that a
refusal turn (turn.complete reason refusal, no Stop) posts nothing.
@omartelo
omartelo merged commit e065b2c into main Oct 10, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant