Files
PaperClipAI/packages
DottaandPaperclip d2c7edda16 test(runner): own Node executable in ACPX recovery fixtures (#18196)
## Thinking Path

> - Paperclip manages AI agents and controls their work.
> - The runner recovery tests check durable ACPX session ownership.
> - The runner must reject a qualified executable that other users can
write.
> - The recovery fixture passes the shared host Node executable to that
guard.
> - A hosted CI job rejected the fixture before it opened a session.
> - This pull request gives the fixture its own Node copy with safe
permissions.
> - The recovery tests can then check recovery without changing the
production guard.

## Linked Issues or Issue Description

Refs: #18185, #14529.

**What happened?**

The Runner vitest 2/2 job in [run
40928584358](https://github.com/paperclipai/paperclip/actions/runs/40928584358/job/123645695206)
failed five ACPX controller recovery tests. Each test failed at
`session.open` with `qualified ACPX must not be group- or
world-writable`. The assertion did not retain the failing artifact path
or mode. The fixture passes `process.execPath` as its command and digest
source.

**Expected behavior**

A test must supply an owned executable with the permissions that the
production guard requires. It must not change the shared host executable
or weaken the guard.

**Steps to reproduce**

Run `acpx-controller-recovery.test.ts` on a host where the shared Node
executable permits group writes. The remote job above retains the actual
failure. Local validation in this PR does not execute the controller or
compile Rust.

## What Changed

- Extract the existing Node and Homebrew `libnode` copy logic into a
test-support helper.
- Use that helper in the existing native distribution fixture.
- Use an owned Node copy for the recovery descriptor, qualified command
and command digest.
- Add filesystem checks for copied bytes, permissions, library selection
and unchanged source files.
- Ignore only a missing adjacent library directory. Report other read
errors with the directory and original cause.

## Verification

- Three filesystem-only Vitest tests passed. They use synthetic writable
artifacts and copy the actual host Node bytes without executing them.
- TypeScript no-emit passed for the new helper and its pure test.
- The new real-filesystem `ENOTDIR` control fails against the first PR
head and passes after the review fix. The parent returned an incomplete
closure; the successor rejects it during preparation.
- `git diff --check` passed.
- The first-head Build job failed in the public npm consumer check with
`ETARGET` for `@aws-sdk/credential-provider-web-identity@^3.972.85`. A
later single exact-version official registry metadata request returned
HTTP 200 for `3.972.85`. This preserves the original failure and does
not establish its cause. No dependency version or check was changed. The
source review fix will receive normal fresh-head CI.
- The first local test configuration had an import error. The first
typecheck invocations had configuration and type-path errors. Corrected
invocations passed; those setup failures are retained in the source
receipt.
- On the reviewed successor, remote Build passed and all five ACPX
controller recovery tests passed. The other runner shard failed because
the new real-Node Buffer deep-equality assertion exhausted its worker
heap. The one-line follow-up uses native Buffer byte equality and keeps
the same invariant. Its three filesystem controls and scoped typecheck
pass; latest-head normal CI remains required.
- Final head `1939f41a7e9cb4031acdf8e99df431b81f28ba03`: both required
checks (`ci / verify`, `ci / e2e`) pass. Remote tests confirm 5 recovery
tests, 33 native distribution tests and all 3 owned-Node tests pass.
Greptile is 5/5 with no open review threads.
- A server queue test timed out at 15 seconds on this head. Its actual
CI checkout has identical server and dependency sources to the prior
passing checkout. One authorized failed-only replay passed at the same
checkout: all 105 files and 2,270 tests passed. The specific test took
5.23 seconds. Passing Build and runner jobs were carried forward. The
original timeout remains retained; this does not establish its cause.
- The actual recovery and native distribution tests, full typecheck,
build and full suite were not run locally. Those tests can compile or
execute native runtime code. Normal PR CI must verify them before
delivery.

## Risks

- Moving the existing fixture copy logic could affect platform-specific
Node library loading. The helper retains the existing Homebrew library
rule and permission modes. Remote CI remains required.
- This change does not prove which artifact mode caused the retained CI
failure. It removes the fixture's dependence on shared host executable
permissions.
- Production code, dependency versions, timeouts, retries, workflows and
writable-artifact guards are unchanged.

## Model Used

OpenAI GPT-6 through Codex, with source inspection and code tools. The
exact serving model identifier and context window are not exposed in
this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 14:57:08 -05:00
..