0.59.4
0.59.2 and 0.59.3 were tagged but never published. 0.59.2’s publish run failed tests/phone-targets.test.ts, which looks up the phone block’s 44 px rule by its selector, and the ally card’s question button had joined that selector (the button had its 44 px; the test now names it). The v0.59.3 tag holds only a rename of this note, and its publish run stops at the tag-matches-version check. 0.59.4 is 0.59.2 with that test fixed.
A forwarded question can be answered where the boss is
Section titled “A forwarded question can be answered where the boss is”The 2026-11-05 box trial (trial11, box and controller both 0.59.1) forwarded both questions, and the controller’s link.log had dialog-in for each. The boss still could not answer from the Mac: a Zen page that was open showed only the circle for three minutes, and Standard had nowhere to answer.
- A question lands on a Zen page that is already open. A hidden page kept the 3-second pause after a card for a boss who was not there to breathe, so a question that arrived in that pause stayed off the screen until the page was shown. A hidden page that has an item waiting now ends the pause: the card is drawn and the page reminds, as it does for any item that takes a hidden page. With nothing waiting the pause is kept until the page is shown, as before (
docs/specs/2026-11-01-zen-view.md, pause and reminders). This is the one cause that could be reproduced for a page that stays on the circle; the trial’s page was not inspected, so the next item says which cause holds if it happens again. Two tests pin the live path: the server pushes a box’sdialog-opento a GUI stream that was already open (tests/server-link-dialogs.test.ts), and a layer on the circle draws the card at the next snapshot with no reload (tests/zen-layer.test.ts). - A question that waits off the Zen page says why.
[sb] a question from <box> waits and is not on the Zen page: <reason>goes to the page’s console once per reason (another card is on the screen and was waiting first, the pause is on, it was put aside, the boss is typing, the layer is not shown). - Standard answers it on the box’s base. The base the box draws on the map (
<box> · <short id>, the teammate’s card) had the row “waiting on a question” with nothing behind it. It now has a button,1 question waits for you: answer it here, and a click on a row that waits opens the same button’s panel: the shared forwarded-question panel (gui/linkdialogs.ts) in place, answered through the same action as Zen and the Link row (gui/asks.ts). The Link button’s row opens it too. A card the box closes (or another controller answers) closes on every surface. - One card per device and question. A device that is in two teams of the box got two
dialog-opens for one question, the second one flaggedfresh: falseon the controller, and the box held two cards to close. The box now sends onedialog-openper controller device (the team it was told on stays while that team lists the device, else one where it is online), and its answer and its close go the same way; the controller keeps one card per device and dialog id. - The label. The unit’s name is not told twice:
main · trial11ismain · trial11, notmain - main · trial11(a name that begins with its role word is told as it is). The card and the row show the label whole; the notice still runs it throughrestrictLabel, so it readsmain _ trial11, as documented. The box’sdialog-seenanddialog-unroutedlog lines carry that label asowner(dialog-seenalso haspackage, the raw owner such asrpiv, which they carried before). - A close only ends its own team’s card. The controller ignores a
dialog-closethat comes on a team other than the card’s, so a withdrawal on one team cannot strike out a question the box re-sent on another.
The merge train can be turned off
Section titled “The merge train can be turned off”A computer where a merge and a deploy are the boss’s word each time (a desk, say) took the integrator rules anyway: a main sent a car slip, the tower opened an integrator, and prompts/integrator.md deployed auto targets with no ask. This release adds a switch that takes the whole machinery out. The default is unchanged (on).
- The switch.
STRAW_BOSS_INTEGRATION=offin the environment, or"integration": "off"in<agent folder>/straw-boss/config.json(the agent folder isPI_CODING_AGENT_DIR, else~/.pi/agent). The environment wins when it is set and not empty, thenconfig.json, then the default: off under the desk (STRAW_BOSS_DESK=1), on elsewhere.on,true,1,yesare on;off,false,0,noare off. It fails closed: any other value, and aconfig.jsonthat exists but cannot be read or parsed (a trailing comma, a folder; a BOM is fine), turn the train off and say so once per process, naming the file and the value. Every session’s pi extension reads it. Mains and tower runs both get their environment from Herdr’s pane (herdr agent start), not from the sb server, so set it in the environment that startsherdr server, or inconfig.json, which every session reads. - For the desk. Nothing to set:
STRAW_BOSS_DESK=1makes the default off. An explicitSTRAW_BOSS_INTEGRATION=onor"integration": "on"still turns it on."integration": "off"in the desk’sconfig.jsonis an optional belt. - Not covered. The switch is per computer, and it reaches sb’s own prompts only. A project’s own skills are the desk’s to handle: moldplan-center’s
work-onskill tells a coordinator “with no integrator, you play it from the same skill”, which an off main still follows if it loads that skill. Work a desk sends over Straw Link to a device where the train is on runs that device’s train. A running integrator keeps its loaded prompt until it restarts, and a tower’s memory entry about car slips stays; clear them by hand on a machine that ran trains. - What off does. No main or tower takes the integrator role. The main prompt loses the car-slip route and says to ask the boss before merging to a shared branch or deploying; the tower and tower-run prompts lose the forward-to-integrator rule and answer a
sharedrequest that carries acar:block with “integration is off on this computer”, opening nothing;integrator.mdis never loaded, because the folder the prompts point to ({{dir}}) becomes a copy,prompts-off/in the state folder, that holdsapps-config.mdandplanning.mdwithout their integration text and nointegrator.md. The copy follows the sources at each load, is removed when the switch is on again, and a copy that cannot be written is told rather than leaving the turn without its Straw Boss section.integration,stages,targets, anddeployin anyapps.jsonare ignored;apps.jsonstill gives the owning app and its paths. - One set of prompt files. The integration text is marked in place,
<!-- integration -->…<!-- /integration -->(dropped when off) and<!-- no-integration -->…<!-- /no-integration -->(kept only when off), andsrc/trainswitch.tsapplies it when a session loads its prompts. With the switch on, a session gets today’s text minus the markers; a stray, nested, crossed, or mis-spelled marker fails the session start. Tests:tests/trainswitch.test.ts,tests/prompts.test.ts, and a tower run intests/run-session.test.ts.
The train’s ledger follows the agent folder
Section titled “The train’s ledger follows the agent folder”The integrator’s ledger folder was written as ~/.pi/agent/straw-boss/trains/ in its prompt, whatever PI_CODING_AGENT_DIR said. The main prompt now names the resolved state folder ({{state}}/trains, <agent folder>/straw-boss/trains), and integrator.md points to the folder the role prompt names. This holds with the switch on or off.