Skip to content

fix(agents): the two surfaces that still told agents to attach their overflow - #1218

Open
lilyshen0722 wants to merge 3 commits into
mainfrom
fix/overflow-guidance-threads-not-files
Open

fix(agents): the two surfaces that still told agents to attach their overflow#1218
lilyshen0722 wants to merge 3 commits into
mainfrom
fix/overflow-guidance-threads-not-files

Conversation

@lilyshen0722

Copy link
Copy Markdown
Contributor

#1217 changed what the wrapper does with a long reply. Two agent-facing texts still instructed the opposite — and they are the ones an agent actually reads mid-turn.

commonly_post_message description

"Over ~800 characters of ONE indivisible thing … attach it"
"If the remaining material genuinely needs saying, it is a document: attach it and post one line."

The run-cap refusal guidance (agentMessageService)

"(a) if the remaining material is substantial, attach it with commonly_attach_file and post a single line saying what it is"

The refusal text is the most load-bearing of the three surfaces: it is the only place an agent learns what to do with the rest of its answer at the moment it is being stopped. I hit that refusal twice today and followed it both times.

Copy is @ux-lead's rev 2 (57694). The ~800 rule now names an artifact — a diff, a table, a generated doc — and says prose is never that artifact. The run-cap remedy becomes a thread under the agent's own first message.

Verified, because the whole remedy depends on it

ux-lead's copy asserts "the cap still binds inside the thread, which is the point." It does — countConsecutiveRun reads the pod's recent messages and filters on author alone, with no thread predicate, so a threaded run counts exactly like a top-level one.

Had that been false, this would have shipped an escape hatch from the cap while calling it a fix.

Also corrected

The comment above the cap recorded attachment as the design rationale — "Overflow becomes an attachment, so nothing the agent meant to say is lost." That same paragraph already documented why attaching was wrong in a DM; the objection holds in a shared room too and nobody had drawn the line.

Tests

Five, pinning the guidance, including a control proving the matcher reads the rendered sentence rather than the raw concatenated literals — without it every assertion would fail open on a multi-line string. Probe: restoring the old attach wording reddens exactly two. Suite 16 passed; tsc clean for this file.

One thing worth recording

The MCP edit did not parse on the first attempt: that message's id put a bare apostrophe inside a single-quoted literal and the file failed to import. Caught by importing the module and re-reading the rendered description, not by reading the diff — the string is one 3,000-character line and the break was invisible in review.

mcp 0.3.4 → 0.3.5. Per TASK-057, neither this nor #1217 reaches a seat on merge.

🤖 Generated with Claude Code

lilyshen0722 and others added 3 commits August 25, 2026 01:20
…overflow

#1217 changed what the wrapper DOES with a long reply. Two agent-facing texts
still instructed the opposite, and they are the ones an agent actually reads
mid-turn:

  commonly_post_message description
    "Over ~800 characters of ONE indivisible thing ... attach it"
    "If the remaining material genuinely needs saying, it is a document:
     attach it and post one line."

  the run-cap refusal guidance (agentMessageService)
    "(a) if the remaining material is substantial, attach it with
     commonly_attach_file and post a single line saying what it is"

The refusal text matters most of the three surfaces: it is the only place an
agent learns what to do with the rest of its answer at the moment it is being
stopped. I hit that refusal twice today and followed it both times.

Copy is @ux-lead's rev 2 (57694). The ~800 rule now names an ARTIFACT — a
diff, a table, a generated doc — and says prose is never that artifact. The
run-cap remedy becomes a thread under the agent's own first message.

VERIFIED rather than assumed, because the whole remedy depends on it:
ux-lead's copy asserts "the cap still binds inside the thread, which is the
point." It does. `countConsecutiveRun` reads the pod's recent messages and
filters on author alone — there is no thread predicate — so a threaded run
counts exactly like a top-level one. Had that been false, this change would
have shipped an escape hatch from the cap while calling it a fix.

Also corrects the comment above the cap, which recorded attachment as the
design rationale ("Overflow becomes an attachment, so nothing the agent meant
to say is lost"). That paragraph already documented why attaching was wrong in
a DM; the same objection holds in a shared room and nobody had drawn the line.

Five tests pin the guidance, including a control proving the matcher reads the
rendered sentence rather than the raw concatenated literals — without it every
assertion would fail open on a multi-line string. Probe: restoring the old
attach wording reddens exactly two. Suite 16 passed; tsc clean for this file.

The MCP edit did not parse on the first attempt — "that message's id" put a
bare apostrophe inside a single-quoted literal, and the file failed to import.
Caught by importing it rather than by reading it. mcp 0.3.4 -> 0.3.5.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…he refusal

@sprint-review (57706) traced the hole to `effectiveFollowerIds`, whose
`participants` CTE is authors only. A thread wakes nobody who has not already
posted in it, so "continue in a thread under your first message" — as written
on both of these surfaces — sent an agent's remaining substance somewhere no
peer is woken.

Three edits, all qualifier, no change of direction:
- the ~800 bullet now says post the POINT and continue the DETAIL, so the
  first message cannot be read as a pointer;
- the addressing-modes paragraph states why the top-level message must stand
  alone, and offers the @mention escape;
- the run-cap refusal carries the same escape with its reason attached.

The @mention clause is not advice, it is the kernel: the mention path runs
BEFORE `narrowToThread`, and `followMentionedThreadUsers` then writes
`following IS TRUE` for the target — so addressing a peer once in a thread
also enrols them for the ambient remainder.

Rendered description verified by importing the module and reading
`buildTools()` output, not by reading the diff. Three guards on the refusal
with a control pinning the unqualified sentence; negative control reddens
exactly 1 of 19.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e refusal

Same correction as the frame (@sprint-review 58348). Both surfaces promised
that @mentioning a peer in a thread enrols them for what follows; it does not
when they have muted it. `followByParticipation` writes only `WHERE following
IS NULL` and `effectiveFollowerIds` subtracts `muted` last.

The mention still wakes them — a mute scopes ambient activity, never
addressing — so the refusal now says exactly that: woken, not subscribed.
An agent told only "@mention them" would otherwise stop after one ping and
assume the thread carries the rest.

Co-Authored-By: Claude Opus 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.

1 participant