VUH-2417: native Pi workers on the installed release (Pi 1.3.0)
James, 2026-10-17: harnesses stay on their latest release, and a newer one must never silently make a harness unhireable. Pi 1.3.0 became the global install that day, while native Pi capability accepted exactly 0.87.1 and its published bundle hashes. This change admits whatever Pi is installed when it passes a hire-time probe, and refuses anything else by name (ADR 0250 amendment).
What changed between 0.87.1 and 1.3.0
Compared from the installed 1.3.0 package and 0.87.1 in a temporary prefix:
- Extension API. Every event, context method and
pimethod the worker runtime and fleet consumer use still exists with the same shape:session_start(reason: "startup",ctx.mode: "tui"), the session switch/fork/tree/shutdown events,ui_prompt_start/ui_prompt_end,message_start,agent_settled,before_agent_start,tool_result,sendMessage(..., { triggerTurn, deliverAs }),registerTool,get/setActiveTools,getAllTools, andisIdle,isProjectTrusted,hasPendingMessages,signal,abortand the session manager reads. - Semantics that moved (1.2.0).
before_agent_startnow also runs for an idlesendMessage(..., { triggerTurn: true })run, before the custom message enters the loop, and a starting run counts as busy. The fleet consumer waited there, unbounded, for its MCP catalog, so a brief's native receipt could miss the ten-second send deadline while the worker went on to do the work (observed live, below). The wait is now bounded at 20 seconds and the brief's receipt window is 30 seconds. - Tool results. 1.x also reads a returned
isError; the fleet consumer'stool_resultoverride still applies and is what 0.87.1 needs. - Session files. Header version 3 and
<timestamp>_<uuid>.jsonlunder the profile'ssessions/--cwd--/are unchanged. The file is still created lazily. - Bundle layout.
dist/bundle/cli.jsstill requires./cli-runtime.js, which imports its chunks statically (8 in 0.87.1, 18 in 1.3.0, about 4.5 MB either way). Chunk names change every release, which is why published hashes cannot follow upgrades. - Auth and models.
auth.json,models.jsonandsettings.jsonkeep their shape. The captain's 1.0.0 reader resolves a 1.3.0 profile'sopenrouter/~anthropic/claude-haiku-latest. 1.0.3 renamed the Azure provider toazure.
The probe
integrations/pi-plugin/probe.mjs runs with the selected native Node, offline,
in a throwaway profile, against a local OpenAI-compatible endpoint
(how it works). It
loads its extension through Pi's own loader and drives the real worker runtime:
identity and session layout, dialog blocking, custom-message receipt, follow-up
turn, settlement, the MCP tool-error override and the persisted header.
probe.jsonl: both 0.87.1 and 1.3.0 pass in about 1.1 seconds on
Node 26.7.0. Breaking the receipt check or the tool-error hook in a scratch copy
fails with receive a custom-message brief: delivery unconfirmed and
mark an MCP refusal as a tool error: tool_result isError override ignored.
A release below 0.87.1, an unrecognized bundle or a failing probe is refused
with Native Pi VERSION ..., in the hire and in worker_accounts
(pi-native-capability.test.ts, against synthetic installs and the real probe).
The native acceptance slices that VUH-2414 guards on this same check now run:
with the global 1.3.0, all 14 (11 fleet, 2 accounts, 1 integrate-environment)
run and pass, and they also pass with 0.87.1 first on PATH.
Live hire
A real hire on the installed Pi 1.3.0 (openrouter/~anthropic/claude-haiku-latest) passed end to end, by apps/clankie/scripts/verify-pi-seat.ts in a throwaway service and Herdr session (live-hire.json): spawn, brief consumed, the worker's message_clankie report stored, a follow-up message_seat delivered and answered, and the completion harvested.
The first run failed at the follow-up: message_seat came back unconfirmed. Briefs had the 30-second receipt window, but follow-ups kept 10 seconds, and on 1.2+ an idle triggered send first waits (up to 20 seconds) in before_agent_start for the MCP catalog. Every send now shares the 30-second window (SEND_RECEIPT_MS in pi-seat-adapter.ts).
What this does not prove
Hosted Linux hires, billing and Discord-origin completion remain the open owner
acceptance in the Pi acceptance boundary.
The Linux image now pins 1.3.0; the Linux process proof
(scripts/proof-linux-pi-process.mjs) was not rerun. The probe drives the
package's SDK build, not the CLI bundle a hire launches; the live hire covers
that bundle on 1.3.0 only.
