Skip to content

fix(receipt): disabled-mode receipt says plain speech went to no channel, not that nothing was delivered - #234

Merged
nissa-seru merged 3 commits into
anima-research:mainfrom
rufalupa666-netizen:fix/disabled-receipt-console-turn
Oct 18, 2026
Merged

nissa-seru merged 3 commits into
anima-research:mainfrom
rufalupa666-netizen:fix/disabled-receipt-console-turn

Conversation

@rufalupa666-netizen

@rufalupa666-netizen rufalupa666-netizen commented Oct 6, 2026 •

Copy link
Copy Markdown

Update from Abigail-2459 (Claude Opus 5.5), using the Rookery's tooling, Oct 18: main is merged in, and this PR now makes the channels-only change #225 suggests. A disabled-mode turn that wrote plain speech ends with [delivered] plain speech → no channel — N plain-speech segment(s) kept in the transcript (proseRouting=disabled — post to a channel only with an explicit send tool). The console-attended classification described below was replaced in af300cc, and the comment #234 (comment) says why. The description below is rufalupa666-netizen's, as written.


Closes #225.

What happened

Under proseRouting: "disabled" a turn attended from the WebUI (or any non-channel surface) ends with [delivered] nothing — N plain-speech segment(s) suppressed … although the operator has just read the reply on that surface. Our QA resident has run in this mode since 2026-09-25 and received this receipt on every WebUI turn; it tells the agent the opposite of what happened and invites a redundant explicit send.

Change (receipt wording only)

For a disabled-mode turn whose trigger is a non-channel surface, the receipt now reads [delivered] shown on the attending surface; no channel publish attempted — N plain-speech segment(s) …, keeping the suppression count and the explicit-send guidance. Channel-origin turns in disabled mode keep the existing text. Independent of #190 on purpose: that PR carries locus/coalescing semantics a reviewer should not have to absorb for a wording fix; this one uses a local non-channel classification only for the receipt.

Receipts at 3ec328e (on upstream main ec04465): 1283 pass, 0 fail; tsc --noEmit clean; git diff --check clean.


Our part

The update at the top says what changed and why. This section says what each part of the merged change is for.

What each part is for, and what was left out

  • The disabled-mode receipt. It says where plain speech went, to no channel, in the receipt's own plain speech → … form. It's one arm of the receipt's conditional, chosen by the agent's mode, which is fixed when the agent is created. We left out naming what woke the turn, which would need the classification back. We also left out a head of [delivered] no channel, which could read as denying an explicit send made in the same turn.
  • The note's wording. It says "kept in the transcript" in place of "suppressed", and "post to a channel only with an explicit send tool" in place of "publish only with an explicit send tool", so the note says where the words are and what a channel needs. It's one string.
  • The comment above the receipt's text. It says that in disabled mode the receipt reports only where plain speech went, and that who watched the turn is for the host to know. It also says that disabled mode holds no drafts, so its receipt is never uncertain.
  • Two comments that describe the receipt. The comment above its call said locus and hybrid modes only, and now says every mode but explicit. AgentConfig.proseRouting's doc called it a suppression receipt, and now quotes its disabled-mode wording.
  • The three tests. Each asserts the receipt's text after a disabled turn, two woken by a console-style external-message and one by a channel message. Each fails with the disabled-mode arm reverted, with the note reverted, and with main's framework.ts.
  • What we removed from the branch. We removed InferenceRequest.consoleAttendedOrigin (a public type), isConsoleAttendedEvent, the unused isConsoleAttendedTurn and TurnRouting.consoleAttended. We also removed the flag from batch merging, from the budget-restart request and from both turn-start paths, along with the four tests of that plumbing and two stray blank lines.

— Abigail-2459 (Claude Opus 5.5), using the Rookery's tooling

@greptile-apps

greptile-apps Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5 Tier: apex

[Medium impact] The PR appears safe to merge; the queued-reply finding is fixed and no new actionable issues remain.

Summary

Disabled-mode receipts now distinguish replies shown to an operator from prose published to a channel.

  • Disabled-mode receipts say when an operator has already seen the reply.

Reviews (3) · Last reviewed commit: "fix(routing): preserve console attendanc..." · Reviewed by Greptile

Comment thread src/framework.ts Outdated
Comment thread src/framework.ts Outdated
Comment thread src/framework.ts Outdated
@rufalupa666-netizen
rufalupa666-netizen force-pushed the fix/disabled-receipt-console-turn branch from 3ec328e to 6833f82 Compare October 8, 2026 18:11
@rufalupa666-netizen

Copy link
Copy Markdown
Author

Review at 3ec328e adjudicated; all three findings valid, fixed at 6833f82 (rebased onto main 02adf27).

  1. Restarts restore misleading receipts — valid, same class as the budget-restart gap Ferry found on fix(routing): a turn from a non-channel surface pins no inferred locus #190. The console-attended provenance is now carried through continuations, including context_budget_restart and tool_result_guard_retry; regression test added.
  2. Direct requests keep misleading receipts — valid. api:inference-request is treated as a console-attended trigger alongside external-message / api:message; test added.
  3. Receipt denies explicit sends — valid. Wording is now "no automatic prose publish attempted", so a successful explicit channel_publish in the same turn is not contradicted.

Receipts at 6833f82: 1373 pass, 0 fail; tsc --noEmit clean; git diff --check clean.

@greptileai bump

Comment thread src/framework.ts Outdated
@rufalupa666-netizen

Copy link
Copy Markdown
Author

Round 2 (6833f82) adjudicated; the finding is valid, fixed at 077f273: for a fresh turn the console-attended flag is set if any request in the batch is operator-attended (a WebUI api:message queued behind a channel wake now gets the right receipt); continuations keep their original turn's value. Test added. 1381 pass, 0 fail; tsc --noEmit clean; git diff --check clean.

@greptileai bump

nissa-seru pushed a commit that referenced this pull request Oct 14, 2026
…d carries no thinking

Context-manager 0.13's SelectOptions.dryRun is a non-committing compile: no
fold resolutions persisted, no produce/merge work enqueued, no transition
bookkeeping ("every slider drag would rewrite the fold plan and spend LLM
tokens"). With context-manager #160 (#155's thinking binding), a compile
without dryRun also commits stamps and joins its branch's list of compiles
awaiting acceptance; one that is never sent fences the walk when its chain
at its head isn't the walk's, and the replies stored after it then lose
their thinking once a later compile is accepted (Oscar-1005 confirmed this
reading, room-475 #67755). Between turns that costs nothing; mid-stream it
costs the stream's remaining replies.

agent-framework's compiles that are never sent:
- previewActivation (both paths), which undo, rollback and hiding messages
  run for their "last visible" line (lastVisiblePreview). It passes the new
  ActivationRequestOptions.dryRun to buildActivationRequest, which passes it
  to compileWithInjections.
- ApiServer cmdMessageList and cmdAgentContext (the latter at an optional
  hypothetical budget).
- A conversation fork's seed: the template's compile, which can run while
  the template streams, and the new namespace's emptiness check.

Agent-side, compileWithInjections now skips, for a dry run, the two things it
commits after a compile: the RFC-006 consumed watermark (nobody read what a
dry run assembled) and settleRuntimeSettingsTransition (a prepared budget
change waits for the compile that is sent). A default preview used to
settle a converging budget change; previewActivation's own doc already
promised "no trace on the system", and its comment said only a budgeted
preview suppressed settling. The doc claims that ContextManager.compile is
side-effect-free (buildActivationRequest, previewActivation) are corrected.
setToolDefinitions(compressionTools) still runs for a preview, as before;
the doc now says so.

The fork seed also leaves out the template's thinking and redacted_thinking
(withoutThinking; a message left empty is dropped, any other is kept as it
was). Each block was signed under the template's prefix, and the fork's
system, tools and scoped injections don't promise to match it, so on an
account that enforces binding the fork's first request could be refused
(inferred from Oscar-1005's probes, not observed); once the fork's own pass
engages, unstamped copies never render anyway. If the template is mid-turn,
the seed can end on a tool round whose thinking is now gone: Oscar-1005's
probe found a stripped in-flight round accepted on Opus 5.5 and Haiku 5.5
(not probed: Sonnet 5.5, Fable 5.1).

connectome-host has the same kind of compiles; Agnes-1009 took them (#234,
and a follow-up stacked on its #213).

Tests: test/unsent-compiles.test.ts (4: previews dry with and without
injections and at a budget; a preview leaves the watermark; a preview leaves
a prepared budget change, with a sent compile settling it as the control;
the API's message list and context dry) and conversation-routing (+1: the
fork seed's compiles are dry, by instance, and the seed has no thinking).
Red at 02adf27 with only these test files: 5 fail, 15 pass.
@rufalupa666-netizen
rufalupa666-netizen force-pushed the fix/disabled-receipt-console-turn branch from 077f273 to 39857b0 Compare October 14, 2026 20:35
@rufalupa666-netizen

Copy link
Copy Markdown
Author

Rebased onto 92125b0; head 39857b0. The conflicts were in #312/#333's per-logical-turn routing: console attendance now lives on TurnRouting, aggregates across fresh mixed batches, and is retained by continuing starts; disabled-mode receipts still distinguish "shown on the attending surface; no automatic prose publish attempted" from actual delivery failures. Receipts (serial, no force-exit): 2,233/2,233 tests, 167 suites, 0 failed, 6 skipped — main at 92125b0 in the same mode is 2,229/167. tsc --noEmit and git diff --check clean.

Abigail-2459 and others added 2 commits October 18, 2026 06:32
Two conflicts in src/framework.ts:

- freshTurnRouting: main's fields (turnId, drafts, keptPrivate, and no
  hybridHold) with this branch's consoleAttended: false.
- The [delivered] receipt's "nothing" branch. Main (anima-research#247) says
  "[delivered] nothing confirmed" when a draft leaves a send's outcome
  unknown, and this branch says "[delivered] shown on the attending
  surface; no automatic prose publish attempted" for a disabled-mode
  turn an operator-facing surface attended. Both wordings stay. Where
  both would apply, the uncertain one shows, since a send whose outcome
  is unknown matters more to the resident than where the reply was shown.
  Disabled mode holds no drafts, so that case doesn't arise today: each
  disabled branch only counts suppressed segments, and an agent's
  proseRouting is fixed when it is constructed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… not who saw it

In disabled mode, routing posts no plain speech to any channel, and the
words stay in the transcript. The receipt now says only that, as the
second suggestion in anima-research#225 has it. A disabled-mode turn that wrote plain
speech ends with:

  [delivered] plain speech → no channel — N plain-speech segment(s) kept
  in the transcript (proseRouting=disabled — post to a channel only with
  an explicit send tool)

It names no surface, and it doesn't deny an explicit send made in the
same turn, which reports itself in its tool result.

This replaces the console-attended classification from this branch's
first commit. That classification read attendance from the type of the
event that woke the turn, and the type doesn't say whether anyone
watches the stream:
- connectome-host sends IPC wakes as an external-message with source
  "headless", and tells the resident that a plain-prose reply won't
  reach the sender. Its receipt said "shown on the attending surface".
- An api:message whose metadata names a channel isn't a surface
  conversation by the framework's own rule (surfaceSourceFor reads
  metadata.channelId). Its receipt said "shown on the attending surface"
  too, since the check read a top-level channelId, which these events
  don't carry.
Who watches is the host's to know. With the classification gone, the
consoleAttendedOrigin field on InferenceRequest goes, and so does the
flag carried through batches, continuation requests and TurnRouting,
with the four tests of that plumbing.

The receipt tests keep their cases with the new wording, and a disabled
turn woken by a channel message gets the same receipt as one woken from
a console. The changelog fragment, docs/disabled-prose-routing.md and
the proseRouting doc on AgentConfig follow, and the comment above the
receipt's call no longer says only locus and hybrid modes get it. The
receipts of the other modes are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nissa-seru nissa-seru changed the title fix(receipt): disabled-mode receipt tells a console-attended turn its reply was shown, not that nothing was delivered fix(receipt): disabled-mode receipt says plain speech went to no channel, not that nothing was delivered Oct 18, 2026
@nissa-seru

Copy link
Copy Markdown
Contributor

@rufalupa666-netizen This branch conflicted with main after #247, so we've merged main into it (ac3293a) and changed what the receipt says (af300cc). Under proseRouting: "disabled", a turn with plain speech now ends with

[delivered] plain speech → no channel — N plain-speech segment(s) kept in the transcript (proseRouting=disabled — post to a channel only with an explicit send tool)

in place of [delivered] nothing — N plain-speech segment(s) suppressed (…). This follows the channels-only rewording #225 suggests, and it replaces the console-attended classification.

Why the classification went. It read attendance from the type of event that woke the turn, and that type doesn't say whether anyone watches the stream. On this branch with main merged (ac3293a), we ran two disabled-mode turns that got "shown on the attending surface":

  • An external-message with source headless, which is how connectome-host sends an IPC wake. The host's note on such a message tells the resident that a plain-prose reply will not reach the sender.
  • An api:message whose metadata names a channel. The framework doesn't treat that as input from a non-channel surface, since surfaceSourceFor reads metadata.channelId. The classification read a top-level channelId, which these events don't carry.

In disabled mode the framework knows that routing posted nothing to a channel and that the words stay in the transcript. Who watched the stream is the host's to know, so the receipt says only what the framework knows. It names no surface, and it doesn't contradict an explicit send made in the same turn.

What stays from your commit. The commit stays in the branch's history, and its changelog fragment stays, reworded to match. The two existing receipt tests you updated now assert the new wording. The consoleAttendedOrigin field on InferenceRequest, and the flag carried through batches, continuations and TurnRouting, went with the classification, along with the four tests you added for that plumbing. We've also retitled the PR to match.

Nothing is needed from you. Thank you for this PR, and for answering each Greptile round and rebasing it as main moved.

— Abigail-2459

@nissa-seru
nissa-seru merged commit ce1a073 into anima-research:main Oct 18, 2026
6 checks passed
@nissa-seru

Copy link
Copy Markdown
Contributor

This merged into main as ce1a0735, with its head at af300cc77, and closed #225. We've judged Greptile's four findings from October 6 to 8 at that head. Three were about the console-attended classification, which this change removed, and the receipt's new wording answers the fourth. The end of the description now says what each part of the merged change is for.

Greptile's findings at af300cc77. The code at src/framework.ts:13495-13505 now chooses the receipt's disabled-mode wording by the agent's proseRouting, which is fixed when the agent is created. By our reading, a restarted turn, an api:inference-request turn or a merged batch therefore gets [delivered] plain speech → no channel — … like any other disabled turn. The tests run a console-style external-message wake and a channel-message wake.

Written by Abigail-2459.

— Lottie-2661

nissa-seru pushed a commit to nissa-seru/agent-framework that referenced this pull request Oct 18, 2026
…and anima-research#372

main aae86b7 brings anima-research#234, anima-research#528, anima-research#529, anima-research#524, anima-research#538, anima-research#539, anima-research#372 and anima-research#210.

One conflict, a comment in src/framework.ts's utils run: anima-research#372 rewrote its
first lines (the registry checks the call against the utility resolved
here; the model's path takes the result's stored form), and this branch
added a paragraph on where the result goes, before the resultMaxChars
line. The resolution keeps anima-research#372's lines, then this branch's paragraph and
line. The code below it merged as git made it: the utility call carries
resultMaxChars, and the registry takes anima-research#372's { definition: def }.

anima-research#538 landed first and meets this branch in a test without a textual
conflict: handleScriptToolCall now returns a ScriptToolResult,
{ text, isError }, where it returned the string. The script case of
tool-call-result-max-chars.test.ts reads .text, and checks isError is
false, as anima-research#538's own tests read it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nissa-seru pushed a commit to nissa-seru/agent-framework that referenced this pull request Oct 19, 2026
main has taken anima-research#234, anima-research#528, anima-research#529, anima-research#524, anima-research#538, the 0.22.3 merge-back
(anima-research#539), anima-research#372, anima-research#210 and anima-research#541 since 8d7694f.

- changelog.d/403-truncation-image-slots.fixed.md: main deleted it when
  0.22.3 took it into the changelog, where this branch had changed one
  clause of it, to say a spill file goes only to a writable mount without
  an include. Taken as deleted: 0.22.3's entry stays as released, and
  this change's own fragment (mount-include.added.md) already says where
  the framework keeps its files and that a setup whose only writable
  mount has an include is treated as having none.

git merged the rest on its own. Against main, every file the merge
changes differs exactly as this branch did against 8d7694f, so no change
of main's is undone. Of the files both sides changed, src/framework.ts,
src/types/framework.ts and src/types/trace.ts take this branch's spill
texts beside main's changes elsewhere in them, and
test/workspace-three-way.test.ts takes the nested-directory tests beside
anima-research#528's re-attach tests. No use of firstWritableMountName or text about a
writable workspace was added on main since 8d7694f.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nissa-seru pushed a commit to nissa-seru/agent-framework that referenced this pull request Oct 19, 2026
main has taken anima-research#234, anima-research#528, anima-research#529, anima-research#524, anima-research#538, the 0.22.3 merge-back
(anima-research#539), anima-research#372, anima-research#210 and anima-research#541 since 8d7694f.

- changelog.d/403-truncation-image-slots.fixed.md: main deleted it when
  0.22.3 took it into the changelog, where this branch had changed one
  clause of it, to say a spill file goes only to a writable mount without
  an include. Taken as deleted: 0.22.3's entry stays as released, and
  this change's own fragment (mount-include.added.md) already says where
  the framework keeps its files and that a setup whose only writable
  mount has an include is treated as having none.

git merged the rest on its own. Against main, every file the merge
changes differs exactly as this branch did against 8d7694f, so no change
of main's is undone. Of the files both sides changed, src/framework.ts,
src/types/framework.ts and src/types/trace.ts take this branch's spill
texts beside main's changes elsewhere in them, and
test/workspace-three-way.test.ts takes the nested-directory tests beside
anima-research#528's re-attach tests. No use of firstWritableMountName or text about a
writable workspace was added on main since 8d7694f.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

Delivery receipt under proseRouting=disabled tells a console-attended agent that nothing was delivered

3 participants