You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A board card's detail is cut at exactly 300 chars mid-word with no ellipsis — 13 of 15 irreversible acts vanish, and the full text is already on the same card #568
A board card's detail is cut at exactly 300 chars mid-word with no ellipsis — 13 of 15 irreversible acts vanish, and the full text is already on the same card
What the owner sees
instance_board for instance bd43f4de-ef35-4051-bdec-43f8571414a1, card deleg-ae7fa3f2-53a1-43ba-b3ad-921dd8dba7b1, Failed column:
outcome: failed — run error: Too many API requests by single Worker invocation. To configure this limit, refer to https://developers.cloudflare.com/workers/wrangler/configuration/#limits | Acts: pushed directly to the trunk origin main; pushed directly to the trunk origin main; pushed directly to th
Measured: exactly 300 characters, ending …pushed directly to th. No ellipsis, no marker. It reads as a finished sentence that names two pushes.
The same card, in instance_task_events, carries the full text under a different key:
reasoning (691 chars): Overseer delegated on your behalf → apps/chess-academy: … — outcome: failed — run error: … | Acts: pushed directly to the trunk origin main; ×4; **and 11 more.**
4 named + 11 more = 15 acts. Corroborated independently by agent_trace(level:"warn"), which has 15 act.consequential events on that run's session, all irreversible: true — 14 push.trunk to origin main and one recursive file.delete.
The board shows 2 of 15 irreversible acts, and gives the reader no reason to think anything is missing. The delegated objective was "commit directly to main, push. Do NOT create feature branches."
Mechanism — the cut and the marker are in two different functions
against reasoning two lines up (:30), capped at 8000. The comment at :36-41 explains why both exist:
ALSO as description, because that is the field every generic reader takes a card's one-line detail from (board.ts, and instance-work.ts for a supervisor) — reasoning is in neither chain, so the outcome text reached the console and nothing else.
So description is the field every generic reader (the console board, MCP instance_board, a supervising agent) uses, and it is the one carrying the 300-char cut. reasoning — complete, with its honest and 11 more. — is on the same row and is read by nothing on that chain.
lib/coding-board.ts:65 has the identical slice(0, 300), and lib/repo-policies.ts:257 (MAX_DESCRIPTION = 300) is the third — but repo-policies.ts:367 is the one that gets it right:
it budgets for the attribution it must keep. Nothing does the equivalent for the acts list.
Verified precedent for the marker.lib/tool-result-cap.ts:95-99 already made exactly this decision for the tool log, and states the principle:
A success is cut EXACTLY as before, with no ellipsis … A failure marks its cut, because the sentence it is cutting is an instruction and a silently truncated instruction is how this started.
A truncated list of irreversible pushes is the same class of sentence and gets no marker.
Why the ordering of the text makes it worse
The 300 chars are spent, in order, on: the outcome, a raw Cloudflare error, a Wrangler docs URL (81 chars of it), and then the acts. So the least useful content — a link to a configuration page for a Worker the owner does not own (#523) — displaces the record of 13 pushes to main. The acts are the part a human reads a Failed card for.
What to do — cheapest first
1. Add the ellipsis. One character, and it converts a false complete sentence into a visibly-cut one. The lowest-value fix, and worth shipping alone if nothing else is.
2. Build description as a budgeted summary rather than a prefix of reasoning. The count is already known at the call site — and 11 more. is computed there. Put the count FIRST: outcome: failed — 15 irreversible acts (14 pushes to origin main, 1 recursive delete) — run error: …. 300 chars is plenty for the facts; it is not plenty for a prefix of a 691-char sentence.
3. Let the generic readers reach the full text.instance_board returns a truncated detail and no field saying more exists. Either return reasoning alongside, or return detailTruncated: true — a reader that cannot tell it was cut cannot go and look.
Show only the acts, drop the error. The error is why the card is in Failed. Both belong; the ordering and the budget are the fix.
Fix it in instance_board's renderer. The truncation happens at write time (delegation.ts:41), so the full text never reaches the reader — nothing downstream can restore it.
Acceptance criteria
A delegation card whose run performed N acts states N; a reader can tell 15 from 2.
Any truncated description is visibly marked as truncated.
The full text remains reachable from the board response (reasoning or an explicit flag).
Test: build a card from a run with 15 acts and a 200-char error; assert the rendered detail names 15 and is ≤ the cap.
Regression risk
description is read by board.ts and instance-work.ts (per the comment at delegation.ts:36), and a supervising agent parses it. Changing the shape from "prefix of reasoning" to "budgeted summary" changes what a Lead reads back from a subordinate — check subordinate-payload.ts, which already trims this text a second time (:111) and could double-trim a newly-front-loaded count. Assert the count survives both passes.
Related: #523 (same run and same card — that issue is about classifying the failure, this one is about the acts being invisible), #503 (a payload silently dropping half its content), #517 (tool-result-cap's marked-cut precedent).
A board card's detail is cut at exactly 300 chars mid-word with no ellipsis — 13 of 15 irreversible acts vanish, and the full text is already on the same card
What the owner sees
instance_boardfor instancebd43f4de-ef35-4051-bdec-43f8571414a1, carddeleg-ae7fa3f2-53a1-43ba-b3ad-921dd8dba7b1, Failed column:Measured: exactly 300 characters, ending
…pushed directly to th. No ellipsis, no marker. It reads as a finished sentence that names two pushes.The same card, in
instance_task_events, carries the full text under a different key:4 named + 11 more = 15 acts. Corroborated independently by
agent_trace(level:"warn"), which has 15act.consequentialevents on that run's session, allirreversible: true— 14push.trunktoorigin mainand one recursivefile.delete.The board shows 2 of 15 irreversible acts, and gives the reader no reason to think anything is missing. The delegated objective was "commit directly to main, push. Do NOT create feature branches."
Mechanism — the cut and the marker are in two different functions
Verified.
workers/api/src/lib/delegation.ts:41:against
reasoningtwo lines up (:30), capped at 8000. The comment at:36-41explains why both exist:So
descriptionis the field every generic reader (the console board, MCPinstance_board, a supervising agent) uses, and it is the one carrying the 300-char cut.reasoning— complete, with its honestand 11 more.— is on the same row and is read by nothing on that chain.lib/coding-board.ts:65has the identicalslice(0, 300), andlib/repo-policies.ts:257(MAX_DESCRIPTION = 300) is the third — butrepo-policies.ts:367is the one that gets it right:it budgets for the attribution it must keep. Nothing does the equivalent for the acts list.
Verified precedent for the marker.
lib/tool-result-cap.ts:95-99already made exactly this decision for the tool log, and states the principle:A truncated list of irreversible pushes is the same class of sentence and gets no marker.
Why the ordering of the text makes it worse
The 300 chars are spent, in order, on: the outcome, a raw Cloudflare error, a Wrangler docs URL (81 chars of it), and then the acts. So the least useful content — a link to a configuration page for a Worker the owner does not own (#523) — displaces the record of 13 pushes to
main. The acts are the part a human reads a Failed card for.What to do — cheapest first
1. Add the ellipsis. One character, and it converts a false complete sentence into a visibly-cut one. The lowest-value fix, and worth shipping alone if nothing else is.
2. Build
descriptionas a budgeted summary rather than a prefix ofreasoning. The count is already known at the call site —and 11 more.is computed there. Put the count FIRST:outcome: failed — 15 irreversible acts (14 pushes to origin main, 1 recursive delete) — run error: …. 300 chars is plenty for the facts; it is not plenty for a prefix of a 691-char sentence.3. Let the generic readers reach the full text.
instance_boardreturns a truncateddetailand no field saying more exists. Either returnreasoningalongside, or returndetailTruncated: true— a reader that cannot tell it was cut cannot go and look.Alternatives considered and rejected
description.descriptionexists because the generic chain reads it; widening it pushes 691-char blobs into every board card and every supervisor payload. [bug] The Coder Lead can only ever see 3 of 6 agents — subordinate_status returns 60,239 chars into a 24,000 cap, so half the roster is silently dropped #503 is the same repo's counter-example — 60,239 chars into a 24,000 cap silently dropped half a roster. The cap is right; the selection is wrong.instance_board's renderer. The truncation happens at write time (delegation.ts:41), so the full text never reaches the reader — nothing downstream can restore it.Acceptance criteria
descriptionis visibly marked as truncated.reasoningor an explicit flag).Regression risk
descriptionis read byboard.tsandinstance-work.ts(per the comment atdelegation.ts:36), and a supervising agent parses it. Changing the shape from "prefix of reasoning" to "budgeted summary" changes what a Lead reads back from a subordinate — checksubordinate-payload.ts, which already trims this text a second time (:111) and could double-trim a newly-front-loaded count. Assert the count survives both passes.Related: #523 (same run and same card — that issue is about classifying the failure, this one is about the acts being invisible), #503 (a payload silently dropping half its content), #517 (
tool-result-cap's marked-cut precedent).