Repository navigation
ποΈ task - drain-stdout-before-exit: a skill render past 64 KiB is silently cut at the pipe bufferΒ #535
Description
π¦«ποΈ dispatch to foreman
π§ task enqueued
ββ priority = ?
ββ yieldage = ?
ββ leverage = ?
title
drain-stdout-before-exit: a skill render past 64 KiB is silently cut at the pipe buffer
description
π wish: a skill's stdout reaches its reader WHOLE, past 64 KiB
- repo =
ehmpathy/rhachet - behavior =
drain-stdout-before-exit - size = nano
- caught = 2026-09-16, in production, on
nheuron
.the outcome desired
rhx <skill>piped to a reader delivers every byte the skill wrote β whatever the size
of the render.
today it does not. a render larger than one pipe buffer is silently cut at exactly 65536
bytes, and the caller receives a body that looks whole and is not.
π΄ .the harm β a TRUNCATED body still parses as a START
the cut lands mid-token, so the body stays valid at its head and unparseable at its tail:
{"verb":"get","count":45,"priorities":[{"slug":"di β¦ β β¦ "opine":{"s
ββ still begins with `{` ββ cut here, 65536 bytes in
β every caller that guards with a ^{ test, or that pipes into jq β¦ 2>/dev/null, reads
this as an empty result rather than a failure. on nheuron that shape handed a
supervisor 22β28 runnable git.crew.fell commands aimed at funded work, with no tell
that the verdict was wrong. the full incident, with the byte tables:
nheuron:.dream/v2026_09_16.fix.the-star-scope-flaps-and-hands-back-a-fell-command.md
.the evidence
| the read | json body bytes | parses |
|---|---|---|
| 4 of 6 captured renders | 70510 | β |
| 2 of 6 captured renders | 65536 | π΄ no |
| the production halt, same day | 65536 | π΄ no |
- 65536 = 64 KiB = the default linux pipe buffer. two independent truncations that land
on the same power of two is a transport defect, never a data defect - it is load-dependent β ~1 read in 3 on a 96%-cpu box, and naught at rest. a reader
scheduled less often leaves the pipe full longer, which widens the window - a verbatim truncated body is kept as a fixture, if it is useful to you:
nheuron:.agent/repo=.this/role=any/skills/work/.test/.assets/eco.priority.get.truncated-body.log
.what rules it out
- the store is innocent β it read
count: 45with the same 6 sponsored values before,
between, and after every failed render - the skill is innocent β
ecowork.db.mjscalls noprocess.exit()on its success
path;main()resolves and the process ends naturally, which is the shape that drains - β the truncated stream still carries rhachet's own
πͺ¨ run solid skill β¦banner at its
head, so what was cut is the RUNNER's stdout
.the bound
- this is the general defect, never a
eco.priorityone β every skill whose render
crosses 64 KiB inherits it, and the share lost grows as renders grow β οΈ please fail loud rather than silently short-write, where a drain cannot be awaited.
a caller can recover from an error; it cannot recover from a body that lies
.done when
a skill whose stdout exceeds 64 KiB, piped to a reader, delivers every byte β clamped by a
test that forces a render past the buffer and proves it red-then-green.
dispatched by human + beaver π¦«
Activity