fix(reply): a blank never reaches the channel, the message gets a mark instead #1060
No reviewers
Labels
No labels
move-to-repo
coilyco-bridge-deploy
move-to-repo
coilyco-flight-deck-agent-compose
move-to-repo
coilyco-gaming-eco-app
move-to-repo
coilysiren-inbox
move-to-repo
unknown
🔒⚠️📦⚠️🔒 SANDBOXED 🔒⚠️📦⚠️🔒
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
c#
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-gaming/sirens-echo!1060
Loading…
Reference in a new issue
No description provided.
Delete branch "aos/claude/gh1035-no-blank-posts"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Part of #1035, and deliberately not all of it.
Where the four blanks came from, and where they did not
Not the harness. That path is already guarded and has the telemetry to prove it fired:
ParseReplyrunsstrings.TrimSpace, so whitespace-only arrives as emptyreply == ""routes tofinishSilently, which posts nothingrenderPhrasesreturns an error rather than an empty stringfitWithOverflowalways yields at least a noticeturn.reply.deliveredshow no delivery below 54 bytes and none at zeroDowel holds Discord write grants, and
finishSilently's own comment says the agent answers through tools. Acreate_messagecarrying empty content posts a blank the harness never sees. That is the leak, and it is mcp-beaver#87, filed at Kai's direction for an opt-in per-tool control.What this does close
sendReplyis the single funnel every reply crosses and it had no final content check. Its non-Discord branch reachesturn.Replywithout passing throughdeliverWithOverflowat all. A blank arriving there is now refused rather than sent.So this closes the funnel rather than the leak. Worth being explicit, because a PR that looked like it fixed #1035 and did not would be worse than no PR.
The behaviour
Kai chose marking over posting, and the harness already had the shape:
finishByReactingexists because "a mark is the whole answer for a turn that needs no words". This reuses the closed reaction key set rather than inventing a response, marking withacknowledge.A mark that fails to land does not become a message.
finishByReactingfalls back to sending the glyph whenReactfails, which is right when the glyph is the answer. Here the answer is nothing, so that fallback would post the very blank this prevents. A transport with no reaction surface takes the same path and sends nothing.turn.reply.blankrecords it under its own name, besideturn.reply.silent, keeping chosen silence and a defect apart the way #895 asked.Tests
Four, reusing the existing
markableTurnfake rather than adding another: every blank shape refused, the mark applied instead, a non-marking transport still sending nothing, and a real reply untouched including a two-character one.Docs
The existing silence section absorbed this rather than the page growing a new one, since it sat at 7995 of an 8000-character cap. Its #895 retelling is shorter to pay for the space, which matches the decision-archaeology strip running on main tonight.
Not done
The acceptance criterion is not met by this alone. "No zero-content message reaches the channel from either layer" needs mcp-beaver#87 as well. Leave #1035 open.
Refs: #1035, #895, mcp-beaver#87
🤖 Generated with Claude Code