Skip to content

feat(agent): catch the Pi crates up to Pi 1.4.0 - #1389

Merged
AnthonyRonning merged 11 commits into
masterfrom
agent/pi-1-4-catch-up
Oct 31, 2026
Merged

AnthonyRonning merged 11 commits into
masterfrom
agent/pi-1-4-catch-up

Conversation

@AnthonyRonning

@AnthonyRonning AnthonyRonning commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

The first full "catch up to upstream Pi" review of the pi-* crates, done as crates/UPSTREAM.md describes. It adopts 22 upstream commits, including the three that mid-task model switching needs. It does not switch models or touch Maple's per-task model lock; that is the next PR.

Range

The three must-adopt changes

  1. Another model's thinking is dropped (#11000, 911309429). In pi-ai/src/openai.rs convert_messages, a reply from another provider, API or model keeps its text and tool calls. Its reasoning is no longer sent as visible text. The same model still gets its own reasoning back in the field it came in.
  2. Summaries leave thinking out (15e7bdc14). serialize_conversation no longer writes [Assistant thinking]. This applies to compaction, split-turn and branch summaries.
  3. No fixed output limit on summary requests (#11036, 6fcb48670). Before, compaction was capped at 0.8 × reserve, the turn prefix at 0.5 × reserve and branch summaries at 4096 tokens. Summary requests now send max_tokens: None, so the provider fits the model's own limit to the request, as it does for turns. reserve_tokens only decides when to compact.

Commits

Each commit names its upstream commits and says whether it adopts an upstream fix or a feature. Each one builds and passes the pi crates' tests on its own.

  1. pi-ai: drop another model's thinking (#11000)
  2. pi-ai: repair \u without hex digits (4b994d5e5), and report malformed final tool-call arguments (#10944). This adds ToolCall::arguments_error and parse_tool_call_arguments; struct literals in maple-agent tests and store-bench gain the field.
  3. pi-ai: whitespace-only tool output counts as none (4dd2b149d)
  4. pi-ai: retry and overflow texts of 1.4.0, and any HTTP 413 as overflow (9 commits)
  5. pi-coding-agent: summaries leave thinking out (15e7bdc14)
  6. pi-coding-agent: no fixed summary output limit (#11036), and /compact instructions reach the split-turn summary (adfc14461)
  7. pi-coding-agent: recovery omits a cut-off call's tool results with it (02726086d)
  8. pi-coding-agent: before_agent_start for custom-message runs, and an abort while a run starts (#10739)
  9. pi-coding-agent: keep empty quoted template arguments (9fe3f3716), and load a worktree's symlinked context file (f1b2e77f5)
  10. pi-coding-agent: Windows shell lookup of 1.4.0 (61060ddf8, 28bea006b)
  11. docs: the UPSTREAM.md reference revision and review log

Behavioural changes to review

These are the riskiest, roughly in order:

  • Custom-message runs (send_custom_message, an extension's triggered send_message) now start as prompts do:
    • compaction first when needed, then before_agent_start, the run's prompt options, the next-turn messages and the handlers' messages;
    • Maple's MCP, computer-use and read_image handlers now run for them, so their prompt sections no longer drop out mid-run (Pi #10267: a prompt change and a cache break);
    • BeforeAgentStart now carries trigger: RunTrigger::{User { prompt, images }, Custom(CustomMessage)} in place of prompt/images. Maple's handlers read only options;
    • an abort requested while the run starts now aborts it at agent_start. Before, run_prompt cleared the flag and the run went ahead;
    • messages added meanwhile are flushed before the run's own messages, as they would be while idle.
  • Summary requests are bigger. Without the fixed cap they can use the model's whole output limit, fitted to its window, and reasoning no longer starves the summary. A summary request is still one request, so history larger than the summarizing model's window still fails (see follow-ups).
  • Malformed tool-call arguments are no longer cut back to a parsed prefix. The call fails validation with Invalid arguments for tool "…": <error>\n\nReceived arguments:\n<text>, and the model sees what it sent.
  • Recovery after a cut-off reply now writes a context edit for each tool result of the omitted call, not only for the reply. Maple's timeline already hides omitted entries generically.

New differences from Pi

No new adaptation or Maple policy is added to the crates.

  • Tool-call end events. A call closes when the next block starts, a difference Agent core in Rust after Pi: pi-ai, pi-agent-core, pi-coding-agent #1104 recorded. So the strict parse runs when the response finishes, as Pi's stream end does. A ToolCallEnd sent earlier, for a call that can still receive fragments, carries the arguments as they stream.
  • Error text. arguments_error carries serde_json's message, where Pi's carries JSON.parse's.
  • Status-code boundary. Rust's regex has no lookaround, so the status-code pattern spells Pi's boundary as (?:^|[^a-z0-9])…(?:[^a-z0-9]|$). Agent core in Rust after Pi: pi-ai, pi-agent-core, pi-coding-agent #1104 had recorded that ours matched whole numbers and Pi did not; that difference is now gone.
  • Windows paths. The WSL launcher check normalizes separators, repeated separators and case, not every win32.normalize rule.
  • Shared on purpose. Agent core in Rust after Pi: pi-ai, pi-agent-core, pi-coding-agent #1104 had kept "a custom message that starts a turn skips before_agent_start" because Pi did the same. Pi changed it, and so does this PR.

Storage adaptations revisited

Upstream's session manager and tool output did not change between these tags, so all three adaptations stay. bd3c9b823 is the one change they block. It activates extension tools registered after a branch recorded its tools, and needs every tool the branch ever named; a partially loaded SessionBase carries only the current snapshot. Maple sets its tools itself and never moves in the tree, so it is skipped and noted in UPSTREAM.md.

Validation

All runs were in apps/maple-agent's pinned Nix shell, with a private build directory. The build log shows Compiling pi-ai … (/Users/admin/workspaces/pi14/…).

  • just ci — passes.
    • fmt, all four clippy runs (-D warnings) and the dependency checks pass. ci-extra passes: the -D warnings build of every target, and 352 headless app tests.
    • ci-test: 2,464 tests in 27 test binaries pass, 8 ignored. (A macOS-only failure in a fix(agent): bound shell execution and show quiet command progress #1378 shell test, from /tmp being a symlink, is fixed on master by PR #1398; this branch no longer carries its own fix.)
  • Pre-commit hook — just ci-lint and just ci-test passed on every commit.
  • Each commit on its own — tests for pi-ai, pi-agent-core and pi-coding-agent pass, and cargo check --all-targets -p maple-agent -p store-bench is clean with -D warnings.
  • New tests — the pi crates go from 424 to 442 tests, all against the scripted provider or a scripted transport. They follow upstream's own tests where it has them:
    • cross-model and alternating-model thinking;
    • \u repair, strict final arguments, a cut-off final call, and validation through the agent loop;
    • whitespace-only output;
    • the new retry and 413 texts, and digits inside ids;
    • summaries without thinking or an output cap, and the split-turn focus with and without history;
    • recovery of a resumed cut-off call (Pi #11227);
    • custom-message runs keeping one system prompt, a custom message that joins the starting run, a message added during before_agent_start, and an abort while the run starts (Pi #10739);
    • empty quoted arguments, a symlinked worktree context file, and the WSL launcher in %SystemRoot%.

Real app, local stack

Maple Work was built from this branch (just build) and run against mde smoke pi14, signed in as the local Pro fixture. The task used Kimi K3, with Web off, in a scratch project under /tmp.

  1. A reply with thinking, expanded:

    Kimi K3 reply with its thinking block expanded

  2. A turn with a tool call, which read notes.txt and answered with its first line:

    A completed read tool call and its answer

  3. Manual /compact. At the default 20,000-token keep window a two-turn task reports "Nothing to compact yet", so the task first read two ~50 KB files. Compaction then succeeded on the real model. The app shows a notice, not the summary text:

    The compaction notice after /compact

  4. After compaction, a tool-free question about the summarized turns gets a correct answer, so the summary reached the model:

    The model recalls the summarized turns

Upgrade check: tasks from master reopened on this branch

The same store was used by a master build and then by this branch's build. Seven tasks were created on master: thinking (Kimi K3), read/shell/write/edit tools, /compact with a follow-up, a stopped reply, an image on a vision model, an image on GLM 5.3 through read_image, and eight turns. All seven reopened on this branch with their transcripts intact, and a follow-up in each that depended on earlier context answered correctly. A new task on this branch also passed, and so did a Claude Code background result delivered back into its task (the custom-message run path this PR changes). Neither build logged errors or warnings.

Follow-ups (not in this PR)

  • Compaction on a smaller-window model (next project). A summary request is one request, here and in Pi.
    • History larger than the summarizing model's window still fails as an overflow of the summary request.
    • Without the fixed cap, output is the model's limit fitted to what is left of its window, which can be small on a tight window.
    • The model-switch work should decide where it summarizes, for example on the outgoing model before switching.
  • Model switching. Another model's thinking is now dropped, and a model gets its own back when the conversation returns to it, matched by provider, API and model id.
    • check_compaction's overflow and cut-off-reply checks still apply only to the current model's own last reply, as in Pi. After a switch, the threshold check is what compacts before the next prompt.
    • Maple's per-task model lock is untouched.
  • Noted on upstream main after 1.4.0, for the next review:
  • Skipped here, worth revisiting.
    • 6f2f164ab/bd3c9b823 (restoring tools on resume and tree moves) would need defaultTools and the full branch's tool history in SessionBase.
    • Windows shell lookup is covered only by unit tests on macOS and by Windows CI.

Adopt/skip table

All 84 upstream commits in the reviewed paths, v1.0.4..v1.4.0.

Adopted (22)

Upstream Area Decision Reason
911309429 (#11000) pi-ai provider Adopt (must) Another model's thinking is dropped instead of sent as text; its text and tool calls stay.
4b994d5e5 pi-ai JSON repair Adopt \u without four hex digits (\usepackage) stays literal instead of dropping the field and everything after it.
87f9a3641 (#10944) pi-ai tool calls Adopt A finished call's arguments are parsed strictly; malformed text leaves arguments empty with arguments_error, which validation reports to the model.
4dd2b149d pi-ai provider Adopt Whitespace-only tool output is sent as (no tool output).
6e491cfa9 pi-ai retry Adopt Status codes match only as standalone numbers; ours used \b, now Pi's boundary.
7bd01fb92 pi-ai retry Adopt Retry text: "The upstream provider returned an error".
7efebff18 pi-ai retry Adopt Retry text: "Unable to forward upstream stream".
550f1f3ec pi-ai retry Adopt Retry text: "The service is temporarily unavailable".
0fbdbd3f8 pi-ai retry Adopt Retry text: request to … failed, reason:.
698a2d23b pi-ai retry Adopt Retry texts for more gateway upstream failures.
29057ece3 pi-ai retry Adopt Retry text: "stream disconnected before completion".
cedefc532 pi-ai retry Adopt ChatGPT Business workspace usage limit is never retried (shared account-limit list).
73f8de80b pi-ai overflow Adopt Any HTTP 413 counts as context overflow, so the session compacts and retries.
15e7bdc14 compaction Adopt (must) Summaries and branch summaries leave thinking out of the serialized conversation.
6fcb48670 (#11036) compaction Adopt (must) Summary requests set no output limit; the provider fits the model's own. reserve_tokens only decides when to compact.
adfc14461 compaction Adopt /compact instructions also reach the split-turn prefix summary.
02726086d session Adopt Omitting a failed or cut-off attempt also omits the tool results that answer its calls.
a447ba11f (#10739) session, extensions Adopt Custom-message runs go through compaction, before_agent_start (now with a RunTrigger), next-turn messages and run prompt options; an abort while a run starts stops it.
9fe3f3716 prompt templates Adopt Empty quoted arguments keep their place.
f1b2e77f5 resources Adopt A worktree's AGENTS.md that links to the main checkout's file loads.
61060ddf8 tools (Windows shell) Adopt PowerShell found in its install folders; the WSL launcher check follows %SystemRoot%.
28bea006b tools (Windows shell) Adopt Microsoft Store shell aliases count as existing shells.
Already matched (7)
Upstream Area Decision Reason
8c4e87389 tools (grep) Already holds Native search reads no ripgrep config.
63035734f pi-ai provider Already matches Ours already applies reasoning before content in one chunk.
503c60552 session events Already matches / skip agent_settled.aborted ported in #1104; OSC 7501 is terminal UI.
27c7b6ff4 user bash Already matches Split colour codes already held back (#1104).
ce8972a0e classifiers Already matches / skip Classifier images ported in #1104; the OpenAI Decisions classifier is not ported (#1104).
27075fe07 pi-ai estimate Already matches Ported in #1104 (3.5 characters per token).
8b5708dbb pi-ai retry Already matches server_busy texts already retried (#1104).
Skipped (55)
Upstream Area Decision Reason
4a080252f release Skip Release commit.
7f225f25d classifiers Skip Per-service image wire forms (TypeSafe, Cloudflare, OpenRouter); our System One follows Maple's server, which takes data URLs (#1104).
bd3c9b823 session tools Skip Needs every tool a branch ever named, which a partially loaded SessionBase does not carry; its resume half follows defaultTools (not ported). Maple sets tools itself and does not move in the tree.
04a93bad8 client identity Skip User-Agent and provider attribution headers; the host transport sets headers.
adc5fa9f8 client identity Skip As above.
e5fe9777b catalog Skip Catalog not ported.
22dc6c26f extension loader Skip TypeScript extension loading.
26293e74f (#11168) HTML export Skip Not ported.
530015d93 catalog Skip Catalog not ported.
caa6967b6 (#11142) Responses tools Skip Responses/Kimi in-place tool declarations are not ported; Chat Completions sends the current tools.
2ec55d808 telemetry Skip Telemetry spans and metrics are not ported.
8efd314fa (#11038) docs Skip Generated models.json reference.
95364a54e (#10910) defaults Skip Pi's default model per provider is not ported (#1104).
90d863f7c defaults Skip As above.
5ab7fe74c Anthropic Skip Provider not ported.
a3f265b1c Kimi Code Skip Provider catalog/config.
6a1f799b6 Kimi Code Skip Revert of the above.
dc939913f Anthropic Skip Provider not ported.
b06c1f2cf Kimi Code Skip Provider catalog/config.
910149912 (#10938) rendering Skip TUI/HTML read labels.
b39979799 pi-ai frames Skip Removes an API we never ported.
1692bba63 Google Skip Provider not ported.
d7f7e0dfe (#10913) model resolver Skip CLI model references; models come from the host registry (#1104).
60ac3bcc3 (#10930) Responses Skip GPT-6 mid-conversation effort on the Responses API, not ported.
195120a91 OpenCode Skip Provider catalog/config.
6f2f164ab (#10887) session tools Skip Resume restores tools only when they come from defaultTools/--tools, not ported; hosts choose tools at start (#1104).
34a8bb38b Anthropic Skip Provider not ported.
cea257439 share Skip /share and HTML export are not ported.
d4d53612b Anthropic Skip Provider not ported.
e6fb2581d auth storage Skip auth.json locking; credentials come from the host.
014873d7d codemode Skip Codemode not ported (#1104).
6a51a39d4 package settings Skip !/+/- resource entries are not ported (#1104).
ee409a85f (#10672) OpenRouter catalog Skip Catalog not ported.
24382bedd codemode/MCP Skip Pi's MCP and codemode are not ported (#1104).
0f4b1465a Codex Skip Provider not ported.
6b07b4e57 Mistral Skip Provider not ported.
7f9e1198f (#9880) settings schema Skip Publishes JSON schemas and moves types; defaults unchanged.
f76c1db66 catalog Skip Model catalog not ported.
7fb59f995 Mistral Skip Mistral's own finish-reason text; our Chat Completions reports its own.
8d8ae2fc2 Anthropic OAuth Skip OAuth not ported.
6b5854454 classifiers Skip OpenAI classifier catalog typing; not ported.
fe11328b0 faux provider Skip Pi's faux cache-usage estimate; usage numbers unchanged and ours estimates its own way (#1104).
f284a2460 durations Skip Timing internals and streamProxy, not ported.
3ba22ce17 pi-ai types Skip TypeScript stream typing.
43d376399 Radius Skip Catalog not ported.
36a686ee8 durations Skip Response and tool durations are not ported (#1104).
2989eb581 (#10142) Bedrock Skip Provider not ported.
18336987a (#10557) rendering Skip TUI outputPad.
ddaa0a034 CLI tools Skip --tools +name/-name is CLI and defaultTools (not ported).
0cf65d2bf (#10429) Codex Skip Provider not ported.
9ad083102 (#10433) OpenAI login Skip OAuth not ported.
3e477eab5 clipboard Skip Terminal UI.
592fb57b7 clipboard Skip Terminal UI.
b30a6dd77 image resize Skip Node worker channel; ours resizes with the image crate.
f8ab362cc clipboard Skip Terminal UI.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

AnthonyRonning added a commit that referenced this pull request Oct 30, 2026
The crates now follow Pi v1.4.0 (4a080252f). The next review starts
there. The review log records this full review of v1.0.4..v1.4.0, its
scope and validation, and why bd3c9b823 was skipped. Maple #1389 holds
the full adopt/skip table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AnthonyRonning added a commit that referenced this pull request Oct 30, 2026
The crates now follow Pi v1.4.0 (4a080252f). The next review starts
there. The review log records this full review of v1.0.4..v1.4.0, its
scope and validation, and why bd3c9b823 was skipped. Maple #1389 holds
the full adopt/skip table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AnthonyRonning and others added 11 commits October 31, 2026 19:59
Adopts Pi 911309429 (earendil-works/pi#11000), an upstream fix in Pi 1.3.0.
Our port matched Pi 1.0.4, which sent thinking from an earlier reply of
another provider, API or model as plain text. The new model then read
that reasoning as part of its own replies and could start writing its
reasoning into the visible answer.

`convert_messages` now drops another model's thinking and keeps the
reply's text and tool calls. A reply that was only thinking leaves
nothing to send, as before for empty replies. The same model still gets
its own reasoning back in the field it came in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adopts two upstream fixes in Pi 1.3.0's JSON parsing:

- 4b994d5e5 (#10868 upstream): string repair treated any `\u` as a
  valid escape. Arguments with text like `\usepackage` failed to parse,
  and the truncation repair dropped that field and every field after
  it. A `\u` without four hex digits is now kept as literal text, as
  other invalid escapes are.
- 87f9a3641 (earendil-works/pi#10944): when a finished call's argument
  text was not valid JSON, the streaming parser kept the fields before
  the error and the tool ran with them. `parse_tool_call_arguments`
  parses a finished call strictly, with the string repair. On failure
  `arguments` is empty, and the new `ToolCall::arguments_error` holds
  the reason and the text the model sent. `validate_tool_arguments`
  fails with it, so the model sees what it sent. The error is
  serde_json's, where Pi's is `JSON.parse`'s.

A call closes when the next block starts (recorded in #1104), so the
strict parse runs when the response finishes, as Pi's does at the end
of its stream. A call's earlier end event still shows its arguments as
they stream, since fragments can follow it.

Struct literals in maple-agent tests and store-bench gain the field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adopts Pi 4dd2b149d, an upstream fix in Pi 1.4.0 (#8720 upstream).
Output that is only whitespace, such as a bare line break from bash, was
sent as is, and some servers reject it with a 400. It now gets the
empty-output placeholder, or the image placeholder when images came with
it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adopts the retry and overflow texts Pi added from 1.0.4 to 1.4.0. These
are upstream fixes; the classifier lists follow Pi's.

- 6e491cfa9: status codes count only as standalone numbers, not digits
  inside a request id or a byte count. Ours used `\b`; this is Pi's
  boundary, spelled without lookaround. It closes the difference #1104
  recorded.
- 550f1f3ec, 7bd01fb92, 7efebff18, 698a2d23b, 0fbdbd3f8, 29057ece3:
  retry "service is temporarily unavailable", "the upstream provider
  returned an error", gateway upstream failures, node-fetch "request to
  ... failed, reason:" and "stream disconnected before completion".
- cedefc532: a ChatGPT Business workspace usage limit is never retried.
- 73f8de80b: any HTTP 413 is context overflow, whatever the body says,
  so the session compacts and retries. A bodyless 400 is still overflow
  only from Cerebras.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adopts Pi 15e7bdc14, an upstream fix in Pi 1.2.0.
`serialize_conversation` wrote every thinking block as `[Assistant
thinking]`. Replayed thinking is often not in the live context (another
model's is now dropped), so a summary request could grow larger than the
context it summarizes. Text, tool calls and tool results record what
happened. This applies to compaction, split-turn and branch summaries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adopts two upstream fixes in Pi 1.4.0:

- 6fcb48670 (earendil-works/pi#11036): compaction summaries were capped
  at 0.8 x the reserve, the split-turn summary at half of it, and branch
  summaries at 4096 tokens. Reasoning could use up that cap, so
  compaction failed with "generation hit the token cap". Summary
  requests now set no `max_tokens`, so the provider fits the model's own
  limit to the request, as for turns. `reserve_tokens` only decides when
  to compact.
- adfc14461: `/compact` instructions also reach the split-turn summary.
  When the split turn was the only new content, they were ignored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adopts Pi 02726086d, an upstream fix in Pi 1.4.0 (#11227 upstream). This
also fixes drift: Pi 1.0.4 already omitted the results at the end of a
run, and ours did not. Recovering from a reply cut off at the output
limit omitted the reply but kept the tool results that answered its
calls. Our provider's transcript repair drops such orphans before
sending, but they stayed in the context and its estimates.

The omission now also writes a context edit for each result of the
omitted reply's calls, as Pi's `_omitRecoveryAttempt` does. This holds
before a prompt and at the end of a run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adopts Pi a447ba11f (earendil-works/pi#10739), an upstream fix in Pi
1.2.0. #1104 had kept the old behaviour on purpose because Pi shared it.
A run that a custom message started (`send_custom_message`, or an
extension's triggered `send_message`) skipped `before_agent_start`. Its
prompt fell back to the base options, so sections the handlers had added
were patched away mid-run and the prompt cache broke (Pi #10267).

Prompts and custom messages now share `start_run`/`prepare_run`. Both
compact first when needed, ask `before_agent_start`, apply the run's
prompt options and tools, and send the starting message with the
next-turn and handler messages. `BeforeAgentStart` carries a
`RunTrigger` (`User { prompt, images }` or `Custom(CustomMessage)`) in
place of `prompt` and `images`, after Pi's union on `messageType`.

The session stays busy from the start of setup. An abort requested
meanwhile now stops the run at `agent_start`; before, it was cleared.
Messages added meanwhile go before the run's messages, as when idle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
….3.0

Adopts two upstream resource fixes:

- 9fe3f3716 (Pi 1.3.0, #10867 upstream): `""` and `''` were dropped
  from a template's arguments. That shifted the later positional
  arguments and kept positional defaults from applying. They now keep
  their place.
- f1b2e77f5 (Pi 1.2.0, #10681 upstream): in a worktree nested inside
  its main checkout, a context file that links to the main checkout's
  file resolved to the shadowed path. So it was skipped together with
  the main checkout's file, and no project context loaded. The check now
  compares the folder's real path joined with the file's name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adopts two upstream fixes in Pi 1.4.0's shell lookup:

- 61060ddf8: PowerShell is also found in its installation folders
  (`%ProgramFiles%\PowerShell\7`, then
  `%SystemRoot%\System32\WindowsPowerShell\v1.0`), and the legacy WSL
  launcher is recognized in `%SystemRoot%` wherever Windows is
  installed. `taskkill` ignores an empty `SystemRoot`.
- 28bea006b: a Microsoft Store shell alias, which cannot be opened
  through, counts as an existing shell.

Unix lookup is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The crates now follow Pi v1.4.0 (4a080252f). The next review starts
there. The review log records this full review of v1.0.4..v1.4.0, its
scope and validation, and why bd3c9b823 was skipped. Maple #1389 holds
the full adopt/skip table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@AnthonyRonning
AnthonyRonning marked this pull request as ready for review October 31, 2026 20:13
@AnthonyRonning
AnthonyRonning merged commit 86d900d into master Oct 31, 2026
22 checks passed
@AnthonyRonning
AnthonyRonning deleted the agent/pi-1-4-catch-up branch October 31, 2026 22:39
@AnthonyRonning

Copy link
Copy Markdown
Contributor Author

Review note, recorded here and deliberately not fixed:

P3: a broken shell link can be mistaken for a Microsoft Store alias on Windows. is_store_alias accepts any path where following the link fails but reading the link itself succeeds. An ordinary dangling symlink passes that too. A stale bash.exe or pwsh.exe link early on PATH could then be picked over a working shell later on PATH. This needs an uncommon setup and hasn't been reproduced on Windows.

We're ignoring it on purpose. Pi 1.4.0 behaves the same way: it checks a shell with accessSync(F_OK), which on Windows reads the link's own attributes, and it takes only the first where result. The Pi crates stay with upstream unless something is a blocker, and this one isn't. It can go if upstream changes it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant