Commit Graph

7179 Commits

Author SHA1 Message Date
Peter Steinberger 7bc994aee8 fix(install): avoid success after incomplete lifecycle changes (#125992)
* fix(install): make lifecycle mutations transactional

Standalone installers now apply npm-version-aware lifecycle approval. Updates verify and repair the installation before reporting success and preserve the prior install owner during method switches. Uninstall now exits nonzero when requested cleanup is only partially completed. Plugin update behavior is unchanged.

Closes #125925

* test(uninstall): assert aggregated live-owner failure

* fix(install): satisfy standalone shell checks

* fix(update): scan PATH for prior Git wrapper

* test(hooks): await Gmail watcher descendant exit

* fix(install): verify Windows npm candidate

* fix(ci): normalize package acceptance version

* fix(update): preserve staged local package links

* test(update): fold staged symlink coverage

* fix(update): retire every legacy Git wrapper

* test(docs): align consolidated ownership checks
2026-08-18 20:50:15 -07:00
Peter Steinberger 66cacbae5d test: remove strict-subset assertions (#126142) 2026-08-18 20:15:50 -07:00
Peter Steinberger 0eac4f7a3c test(ai): route parity fixtures to owner (#126131) 2026-08-18 19:33:48 -07:00
Peter Steinberger 0718aedb9d test(cli): remove stale update sidecar fixture (#126126) 2026-08-18 19:13:09 -07:00
Peter Steinberger 8674f0c1e9 test(agents): remove transport contract test facades (#126110) 2026-08-18 18:52:13 -07:00
ClawSweeper a480d0347f feat(sessions): expose sidebar category controls (#126074)
* feat(sessions): expose sidebar category controls

* fix(sessions): make category controls explicit

* test(sessions): update list description fixture

---------

Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
2026-08-18 19:41:35 -06:00
Peter Steinberger f3c076cacb test(release): remove release-check helper barrel (#126105) 2026-08-18 18:14:25 -07:00
Peter Steinberger 54ebb307cd fix(mcp): retire terminal transports and process trees (#126101)
Close terminal SSE and stateful notification streams through the owning lifecycle, and reap stdio/QA process groups before exact authority is discarded.\n\nRefs #126098, #126099, #126100.
2026-08-18 18:10:45 -07:00
Peter Steinberger 4fac990321 fix(test): run the shared Control UI lane on the cross-file cleanup runner (#126071)
* fix(test): run the shared Control UI lane on the cross-file cleanup runner

ui/vitest.config.ts drives CI's checks-ui job (pnpm --dir ui test). Its
unit project sets isolate:false but never wired
runner: nonIsolatedRunnerPath, so the per-file cleanup in
test/non-isolated-runner.ts — module-graph reset, repo-owned custom
element dropping, DOM body reset, timer and spy restoration — never ran
in the lane CI actually uses. Only the repo-root lane behind
scripts/run-vitest.mjs loaded it.

Files sharing a worker therefore kept the previous file's evaluated
modules, so whichever file imported a component first pinned it to the
real dependency and a later file's vi.mock factory never reached
production code, surfacing as "expected 0 to be 1" in whichever sibling
the size sequencer happened to pack alongside it. This is the class
PR #123512 diagnosed and fixed at the runner; the fix never reached this
lane, so the repo kept absorbing it one uiIsolatedTestFiles entry at a
time.

browser stays exempt (the runner imports node:fs and server modules that
cannot load in browser mode) and unit-node stays exempt (it carries the
Playwright-driven layout tests whose browser lives in module scope, which
per-file module resets churn). The config test asserted runner was
undefined for every project, pinning the broken wiring; it now asserts
the invariant and fails on the pre-fix config.

* fix(agents): stop passing an ignored resolver to instance-bound announce dispatch

check-prod-types is red on main: #126062 threaded resolveGatewayContext
into the announce dispatch call, but that call now goes through
dispatchGatewayLifecycleMethod, whose options type does not carry the
field.

The type checker is right that it does not belong there. That dispatcher
hands work to runtime.dispatchAgent, which resolves context from the
Gateway instance it is bound to and forwards a fixed option allowlist, so
a caller-supplied resolver was already being ignored. Dropping it is
behavior-preserving.

The delivery test asserted the resolver was forwarded, but production now
binds to the instance dispatcher while the test injects a mock, so that
assertion only proved the mock. It now asserts the resolver is
deliberately not forwarded.

Left for the owner of #126062: sendSubagentAnnounceDirectly and its
callers still accept and thread resolveGatewayContext, which is now
vestigial on this path. Deleting that chain or teaching the instance
runtime to honor the resolver is a design call on a just-landed change.
2026-08-18 17:42:00 -07:00
Josh Avant 8d6cbee1b5 fix(gateway): avoid Tailscale crash loops after upgrades (#126069)
* fix(gateway): migrate legacy Tailscale routes on upgrade

* fix(gateway): preserve unattributable Tailscale routes
2026-08-18 17:14:49 -07:00
Peter Steinberger fe816d69ef fix(gateway): route detached announce by instance (#125946)
* test(qa): cover worker generation reload

* test(qa): anchor worker generation fixture

* test(qa): strengthen worker generation proof

* test(qa): stabilize terminal reply smoke waits

* test(qa): widen terminal reply CI budget

* test(qa): drop superseded timeout workaround

* fix(gateway): route detached announce by instance
2026-08-18 17:14:43 -07:00
Josh Avant 50720c3b8e fix(codex): preserve native approval scope (#125995) 2026-08-18 16:18:01 -07:00
Peter Steinberger 9924e2d7a7 feat(cli): prepare session-host onboarding (#125879)
* feat(cli): prepare session-host onboarding

* fix(cli): gate session-host installer capability
2026-08-18 16:08:48 -07:00
Peter Steinberger e8312171c1 fix: direct Gateway stops wait for active work (#126024)
* fix(gateway): drain active work on direct stop

* test(ui): isolate widget fetch retry mock
2026-08-18 15:29:52 -07:00
Peter Steinberger f2158a9c36 feat(sessions): keep durable work visible and auto-archive stale sessions (#124925)
* feat(agents): clarify visible session guidance

* feat(sessions): auto-archive inactive dashboard sessions

* fix(sessions): preserve active dashboard sessions during maintenance

* test(sessions): preserve admitted dashboard sessions during archive

* chore: refresh session generated artifacts

* test: align recovery id with transcript redaction

* fix(sessions): report only committed maintenance counts
2026-08-18 14:02:54 -07:00
Peter Steinberger a57d9b5060 fix(ui): never restore a stored draft over typed new-session composer text (#125884)
* fix(ui): never restore a stored draft over typed new-session composer text

After a reload the new-session composer renders before the gateway
recovery scope arrives; selectRoute then zeroes the draft revision, so
text typed in that window lost to the stored draft's higher revision and
the async restore overwrote (or, interleaved with input, appended to)
what the user had typed. Seen on PR #125690 CI (checks-ui-e2e 5/12, run
32122284238) as a doubled composer value.

NewSessionDraftPersistence now records a pristine baseline at each
programmatic content replacement (page reset, navigation handoff,
restore apply) and restores only when no user mutation happened past it;
otherwise the typed text wins and persists above the stored revision,
including minting a revision for text typed before route activation so
that draft still lands. The chat composer sibling is unaffected: its
revision lineage persists synchronously to localStorage.

* test(ui): run draft-persistence regression in the isolated ui lane

The regression test mocks the statically imported
durable-composer-persistence helper (the store runtime is only
dynamically imported, so under the shared isolate:false module graph its
mock alone is packing-dependent). Isolating the file makes the mocks
deterministic and keeps the shared-lane file set unchanged so sibling
packing does not shift.
2026-08-18 13:23:31 -07:00
Peter Steinberger d1a194b52f fix(gateway): refresh edited skills in agent RPC sessions (#125962)
* fix(gateway): watch skills for agent RPC turns

* ci: rebalance hosted agent chat shard
2026-08-18 13:06:48 -07:00
Peter Steinberger d5aff660a2 fix(codex): keep large AGENTS.md instructions visible (#125966)
* fix(codex): raise native project doc budget

Default OpenClaw Codex threads to a bounded 128 KiB aggregate project-document budget so large AGENTS.md chains remain visible. Preserve explicit ordinary-thread overrides and keep restricted or lightweight turns at zero.

* test(codex): refresh project doc config expectations
2026-08-18 12:39:52 -07:00
Peter Steinberger ef22410985 refactor(protocol): remove beta-only expectedRunId from chat.send (#125921)
The Gateway owns start-or-steer at admission (6515f6a255) and no
client produces expectedRunId anymore (d84a910fc8). The field shipped
only in v2026.8.1-beta.2 - never a stable tag - so it is removed rather
than deprecated. Steer sends resolve the selected session's current
operation; the exact-match branch, the operation|run target identity
discriminator, run_mismatch rejection, and the suggestion producers'
active-run-id selection (with its ambiguity failure) are deleted.
Provider-native turn fencing (Codex expectedTurnId) is unchanged:
the backend-captured runId on the injection target remains.
2026-08-18 11:28:36 -07:00
Peter Steinberger fead7fee27 refactor: consolidate small shared helpers (#125805)
* refactor: consolidate small shared helpers

* fix: reject inherited Parallels smoke arguments

* fix: preserve day-prefixed CPU probe times
2026-08-18 10:23:40 -07:00
Peter Steinberger f8ba65636c feat(control-ui): simplified settings experience for non-admin operators (#125492)
* test(control-ui): add --operator-scopes flag to the mock dev server

* feat(control-ui): simplified settings experience for non-admin operators

Non-admin browsers previously saw every settings page, many of which
dead-ended or rendered enabled controls whose RPCs fail with
'missing scope: operator.admin'.

- config.schema drops from operator.admin to operator.read: the schema is a
  static document describing options whose values are already readable via
  read-scoped config.get; admin-only schema only broke read-only settings
  rendering (Automation/Infrastructure/AI Agents/Communications showed
  'Schema unavailable. Use Raw.').
- Settings sidebar and settings search hide admin-only routes (custodian,
  labs, updates, automation, infrastructure, mcp, security, secrets,
  cloud-workers, communications, ai-agents, model-setup) for non-admin
  viewers; legacy gateways without advertised scopes keep the full UI.
- Channels, Devices, Worktrees, Memory Import, Profile gate their mutation
  controls on actual scopes with 'Browsing only…' notices instead of
  enabled-but-failing buttons; Devices no longer fires device.pair.list /
  exec.approvals.get without the scopes to call them (kills the two red
  error callouts on page load).
- Scope-upgrade banner: dismissing it in the guidance phase (no in-app
  upgrade path) now hides it fully instead of leaving a permanent chip.
- Config write coordinator surfaces scope refusals as a visible
  admin-required error instead of silently resolving false.

* test(control-ui): advertise config.schema in the mock dev gateway

ensureSchemaLoaded now checks method advertisement + scope before loading
the schema; the mock harness must advertise config.schema like a real
gateway does or schema-driven settings pages render empty in the mock.

* fix(control-ui): close the worktree create draft on scope downgrade

* perf(doctor): isolate memory health artifact

Doctor lint loaded the broad Memory Core API barrel only to register health checks and read isolated check IDs. That synchronously pulled the full memory public graph into the first lint run, consuming most of the 120-second test budget.

Load a dedicated doctor-health public artifact instead and verify it is packaged. The bisect boundary was 9de3ca5fc9 (#125571); because that commit only adds upgrade-test assets, it exposed a pre-existing runner-sensitive cost rather than introducing the expensive import path.

* test(control-ui): restore device lifecycle test boundary

* perf(control-ui): lazy-load settings sidebar

* fix(ui): recheck access after confirmations

* fix(control-ui): gate presence-driven device reloads on pairing access

The presence connectivity-change path still called device.pair.list without
operator.pairing, the same invariant the pair-event and poller paths already
guard; a limited browser got a doomed RPC on every connectivity change.

* fix(control-ui): fail open on schema loads for legacy scope-less gateways

canCallGatewayMethod hardened to strict advertisement+scope checks (#125478),
which made the new ensureSchemaLoaded gate silently skip config.schema for
legacy hellos without advertised scopes or a method list. Schema loads now
skip only on a definitive denial (method advertised absent, or advertised
scopes without operator.read), reusing the fail-open hasOperatorReadAccess
semantics the rest of the non-admin UI uses; regression test pins the
legacy snapshot path.

* test(control-ui): split schema-access coverage into its own file

runtime-config-capability.test.ts crossed the max-lines cap; the legacy
fail-open regression and its denial counterpart move to a colocated
schema-access test file.

* fix(scripts): keep mapped Vitest lanes at their measured no-output floor

The codex extension shard legitimately works in silence beyond 300s under
the default reporter (measured 61s import + 293s testing at ~95% CPU); the
CI-wide OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS=300000 env override shrank the
lane below that and the watchdog killed healthy runs, flipping with
incidental flake output (#125825). Per-config entries in
VITEST_CONFIG_NO_OUTPUT_TIMEOUT_MS now act as measured silence floors: a
global env value may widen a mapped lane's window but no longer shrinks it;
unmapped configs and the explicit '0' disable keep env verbatim. Adds the
codex extension lane to the map at the extra-long tier (same class as the
discord entry from #123025).
2026-08-18 10:15:10 -07:00
Peter Steinberger b9d0e13b5d fix(agents): share one delegation policy across agent runtimes (#125892)
The `## Delegation` guidance added in #125691 lived only in
buildAgentSystemPrompt, so Codex-runtime agents never received it: the
Codex harness builds its own developer instructions in
extensions/codex/src/app-server/thread-prompt.ts and imports nothing
from the system-prompt builders. Live A/B on gpt-5.6-luna had the native
runtime answer "spawn a visible session" while the Codex runtime
answered "spawn a hidden subagent".

Move the policy into src/agents/delegation-guidance.ts, owning both the
main-session mode resolver and the section text, and export it through
the agent-harness plugin SDK barrel that the Codex harness already uses.
The hidden-delegation vocabulary is injected by each runtime, so core
never names a plugin-owned tool: native passes `sessions_spawn`, Codex
passes native `spawn_agent`. Visible sessions stay `sessions_spawn`
with visible=true on both runtimes because Codex-native children are
never OpenClaw sessions.

Also narrows the Codex line that told the model to use `sessions_spawn`
only for OpenClaw/ACP delegation; it now scopes that to internal
legwork, so user-facing deliverables still route to a visible session.
2026-08-18 09:57:52 -07:00
Peter Steinberger d8c1d90edb perf(test): consolidate shutdown watchdog proof (#125890) 2026-08-18 09:27:35 -07:00
Peter Steinberger 6629ca32df fix(status): surface gateway runtime degradation (#125888) 2026-08-18 09:17:31 -07:00
Peter Steinberger 9e24399e82 fix(ci): stop the codex lane hanging on a cold real-tool graph (#125864)
* fix(ci): stop codex lane cold-graph hangs

The side-question domain-policy test loaded the complete agent-harness tool graph inside a one-second readiness race, making the serial non-isolated Codex shard fail or stay silent under cold imports. Build the test's web_search marker and real web_fetch tool from the narrow implementation, then synchronize on turn startup before issuing the tool call. Cap each Codex test process at 12 files so CI gets bounded time-to-first-output as defense in depth.\n\nRefs #125839

* fix(test): keep codex web fetch fixture on sdk boundary

Load the real web_fetch factory on demand through the existing local-only plugin test runtime. This preserves the narrow cold-graph fix without letting a bundled plugin test reach into core internals.
2026-08-18 09:15:38 -07:00
Peter Steinberger 5f65ef8138 feat: add A2UI widgets to session boards (#125803)
* feat: add A2UI board widgets

* fix: harden A2UI board widget integration

* fix: repair A2UI CI contracts

* fix(canvas): keep native A2UI pushes on v0.8

* fix(canvas): support board-only widgets without file host
2026-08-18 09:08:45 -07:00
Dallin Romney 8de2679a5e test(release): preserve Codex follow-through finality (#125619)
* fix(ci): mark Codex follow-through progress non-final

* test(ci): assert Codex progress finality

* test(ci): align Codex follow-through assertion

* test(codex): accept explicit progress finality

* test(release): preserve frozen Codex finality
2026-08-18 08:53:48 -07:00
Dallin Romney f25f7429df test(release): redact shared failure diagnostics (#125697)
* test(release): use shared channel diagnostics

* fix(release): redact shared E2E failure logs

* test(release): configure redaction timeout fixture
2026-08-18 08:52:17 -07:00
Peter Steinberger 13e3d4535b fix(agents): finalize guided creation safely (#125768)
* fix(agents): finalize guided creation safely

Run channel post-write hooks only after config publication, defer portable auth copying until agent creation succeeds without overwriting newer credentials, and provision existing workspaces before publishing updates.

Keep JSON-only guided creation interactive while routing wizard output to stderr so stdout remains one machine-readable summary.

* fix(terminal): preserve note call signature

* fix(agents): pass committed config to setup hooks

* ci: split heavy codex changed-test shards

Cap non-isolated Codex extension processes at 20 files so 4-vCPU changed-target jobs do not starve real-time watches or hit the no-output watchdog.

* test(ci): align codex shard cap fixture

* docs(cli): clarify agents add JSON mode
2026-08-18 08:50:01 -07:00
Peter Steinberger 005a63f252 test: remove prompt snapshot facades (#124333) 2026-08-18 08:45:44 -07:00
Dallin Romney f6dbcc1ba9 test(e2e): keep recovery proof alive (#125804) 2026-08-18 07:44:38 -07:00
Dallin Romney 5169760bde fix(ci): provide isolated Telegram runtime tmp (#125625)
* fix(ci): provide isolated Telegram runtime tmp

* style(test): format Telegram QA regression
2026-08-18 07:17:37 -07:00
Dallin Romney 902eb1f282 test(e2e): repair release validation harness drift (#125681)
* test(e2e): align usage and Canvas contracts

* test(e2e): restore registry and use built CLI
2026-08-18 07:14:01 -07:00
Dallin Romney 350ac1d050 test(gateway): await hosted plugin registry startup (#125814) 2026-08-18 07:12:34 -07:00
Dallin Romney e1d4eac8f4 fix(qa): use full tool profile for node MCP live proof (#125683)
* fix(gateway): share node tool snapshots across chunks

* docs(gateway): explain node snapshot ownership

* fix(qa): expose node MCP tool in live proof
2026-08-18 07:08:25 -07:00
Peter Steinberger efaa867d93 feat(nodes): publish exact runner slots (#125708)
* feat(nodes): publish exact runner slots

* docs(runners): link slot inventory PR

* fix(ui): keep session menus clickable under previews

* perf(protocol): keep runner slot schema off broad barrel

* test(codex): tolerate elapsed media startup budget

* test(codex): type media client factory mocks

* fix(protocol): reject impossible runner slot counts

* test(ci): stabilize loaded lifecycle checks

* test(ui): allow loaded bulk-delete scheduling

* test(ui): stabilize loaded interaction checks

* test(ui): isolate loaded update notice checks

* test(ui): colocate bulk-delete lifecycle coverage

* test(gateway): publish session config before async setup
2026-08-18 07:08:06 -07:00
Dallin Romney 33a8645dcf fix(ci): resolve performance targets from checkout (#125575) 2026-08-18 07:03:16 -07:00
Peter Steinberger 7f0a87de1d feat(agents): eager delegation default in the main session + coalesced session-state wakes (#125691)
* feat(agents): default to eager delegation in the main session

The delegation prompt section now defaults to "prefer" in each agent's
canonical main session and "suggest" elsewhere; explicit config wins in
both directions. The section is rewritten to be token-leaner and now
covers the hidden-vs-visible spawn distinction (hidden subagents are
invisible and auto-archived; deliverable-bearing work spawns
visible=true and replies with the link) plus the run-end notification
contract. The Messaging spawn-mechanics line is suppressed when the
Delegation section renders, and the stable Tooling visible:true hint is
aligned with the new guidance.

* perf(sessions): coalesce session-state wake bursts

Watched-session change notices woke the watcher's main session with the
generic 250ms heartbeat coalesce, so a burst of changes across several
watched sessions produced one wake per change. Wakes now coalesce for
20s; notices are already queued and deduped, so none are lost.

* test(agents): regenerate prompt snapshots after rebase

* test(sessions,agents): update sibling assertions for coalesced wakes and visible guidance

session-state-events tests advance timers past the new 20s wake
coalesce window; the sessions_spawn schema test tracks the updated
visible description.
2026-08-18 07:03:11 -07:00
Peter Steinberger 1ecd53fe27 fix(qa): handle zombie proc stats in upgrade survivor (#125829) 2026-08-18 06:58:16 -07:00
Peter Steinberger 0c493f6ac8 fix(ui): disable review-only approval actions (#125732)
* fix(ui): disable review-only approval actions

* fix(ui): disable cloud worker save during refresh

* test: drain mock resolution before shared cleanup
2026-08-18 03:32:41 -07:00
Peter Steinberger fd1171f8fb refactor(ui): heal chat-pane max-lines and markdown-tables mock isolation (#125766)
* refactor(ui): extract chat pane rail state

chat-pane-render.ts sits at 702/700 effective max-lines on main, latently
failing the lint lane for any change that pulls it into scope. Extract the
rail/sidebar-slot model building into chat-pane-rails.ts (behavior-neutral)
to heal it without a suppression.

* test(ui): isolate markdown-tables from shared module graph

The shared UI runner reuses its module graph across jsdom registries; when
another worker file evaluates markdown-tables.ts unmocked first, this file's
clipboard vi.mock can bind to a stale instance and the copy spy records zero
calls (checks-ui failures on PR #125668). The test belongs on the canonical
singleton-sensitive list, which exists for exactly this class.
2026-08-18 03:16:44 -07:00
Peter Steinberger f72782d87b refactor(test): restore auth persistence integrity (#125699)
* test: restore auth persistence integrity

Restore the SQLite-backed auth wizard assertions traced to 43ea501f38 and consolidate duplicated message-action and temp-directory fixtures.

* test: support npm 12 pack results
2026-08-18 02:58:30 -07:00
Peter Steinberger 8a0d28d6ba refactor(qa): simplify scenario runner infrastructure (#125738) 2026-08-18 02:03:37 -07:00
Peter Steinberger 56d14af908 test(ui): centralize settle-before-act waits (#125702) 2026-08-18 01:40:28 -07:00
Peter Steinberger da4ad4110b fix(process): treat zombie lock owners as dead (#125658)
Linux signal-zero probes succeed for zombie processes. Reclaim memory promotion and session usage locks only when their exact zombie owner is still current, and route shared test waits through the canonical zombie-aware PID helper.
2026-08-17 23:55:08 -07:00
Peter Steinberger 23bcaef0c1 fix: tools report terminal no-delivery outcomes (#125607)
* fix(tools): report terminal non-delivery outcomes

* fix(agents): prefer authoritative terminal replies

* fix(agents): short-circuit authoritative replies
2026-08-17 22:51:44 -07:00
Peter Steinberger b934625d80 fix(test): name Vitest unhandled errors instead of burying them (#125615)
* fix(test): surface Vitest unhandled errors

* fix(test): keep Vitest error helpers private
2026-08-17 22:49:19 -07:00
Ayaan Zaidi dfcef3a28f fix: Claude CLI subagent thinking and tool calls leak into the parent turn (#125621)
Claude Code forwards Agent-tool subagent records with parent_tool_use_id set; the streaming parser treated them as parent records, so subagent thinking streamed as the assistant's reasoning and subagent tool calls surfaced as unattributed top-level tool events. Gate the thinking/tool dispatchers and assistant-snapshot path on one shared isClaudeSubagentRecord guard.

Also read Claude result errors[] (skipping [ede_diagnostic] telemetry) for every error result instead of reporting only the subtype name.

Fixture: live Claude Code 2.1.234 stream-json capture with a background Explore subagent. Telegram E2E on the claude-cli backend shows the progress draft with only the parent Agent row.
2026-08-18 10:51:18 +05:30
Josh Avant 916aca13f3 feat: record subagent execution lineage (#122015)
* feat(audit): record subagent execution lineage

* fix(audit): type-check spawn lineage validation

* docs: preserve spawned-run lineage invariants

* fix(audit): preserve lineage for worker spawns

* fix(audit): bind worker lineage to live authority

* fix(audit): keep lineage carrier private

* fix(sessions): preserve ACP participant recording

* fix(audit): keep lineage out of runtime bearer

* fix(audit): keep lineage type private

* test(audit): match current worker claim shape

* test(audit): preserve readonly lineage result

* fix(audit): redeem spawn lineage privately

* fix(audit): preserve lineage redemption on copy

* test(audit): prove nested worker spawn lineage

* fix(audit): restore execution identity CI gates
2026-08-17 21:41:30 -07:00
Peter Steinberger 603b0ec7f5 fix(macos): avoid elevation codesign metadata SIGPIPE (#125487)
* fix(macos): avoid elevation codesign metadata SIGPIPE

* fix(macos): preserve codesign metadata failures
2026-08-17 21:40:38 -07:00