Skip to content

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’s dialog-open to 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 flagged fresh: false on the controller, and the box held two cards to close. The box now sends one dialog-open per 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 · trial11 is main · trial11, not main - 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 through restrictLabel, so it reads main _ trial11, as documented. The box’s dialog-seen and dialog-unrouted log lines carry that label as owner (dialog-seen also has package, the raw owner such as rpiv, which they carried before).
  • A close only ends its own team’s card. The controller ignores a dialog-close that 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.

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=off in the environment, or "integration": "off" in <agent folder>/straw-boss/config.json (the agent folder is PI_CODING_AGENT_DIR, else ~/.pi/agent). The environment wins when it is set and not empty, then config.json, then the default: off under the desk (STRAW_BOSS_DESK=1), on elsewhere. on, true, 1, yes are on; off, false, 0, no are off. It fails closed: any other value, and a config.json that 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 starts herdr server, or in config.json, which every session reads.
  • For the desk. Nothing to set: STRAW_BOSS_DESK=1 makes the default off. An explicit STRAW_BOSS_INTEGRATION=on or "integration": "on" still turns it on. "integration": "off" in the desk’s config.json is 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-on skill 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 shared request that carries a car: block with “integration is off on this computer”, opening nothing; integrator.md is never loaded, because the folder the prompts point to ({{dir}}) becomes a copy, prompts-off/ in the state folder, that holds apps-config.md and planning.md without their integration text and no integrator.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, and deploy in any apps.json are ignored; apps.json still 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), and src/trainswitch.ts applies 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 in tests/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.