mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-04 11:01:16 +01:00
adf258ede2f05b29f1ea0dbd7b105a310d28626f
5099
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
adf258ede2 |
Merge latest Codex qualification and master fixes
Co-Authored-By: Paperclip <noreply@paperclip.ing> * codex/claude-runner-default: (25 commits) fix: pin ARM qualification helper to workflow source perf(ci): cache the Runner's release crate artifacts keyed by their inputs (#15932) perf(build): reuse a current Runner build in the server's prepare:runner-vendor step (#15926) fix(test): make the vitest home teardown remove read-only runtime-context bundles (#15931) fix(test): stop the Sentry timeout assertion matching a random event id (#15929) test: qualify Linux ARM with stock sandbox prerequisites docs(release): align 2026.1006.0-beta.0 stable notes header with v2026.1012.0 (#16000) fix: use Hermes adapter API URL env in prompt (#9425) fix(docker): skip the full-tree ownership walk on routine boots (#15992) refactor(chat): isolate Telegram, Slack, GitHub and Discord workflows (#15976) Preserve repository dependencies when importing GitHub skills (#15731) refactor(heartbeat): extract instruction working-copy lifecycle (#15984) test: retire redundant suites and consolidate owner coverage (#15978) refactor(heartbeat): extract runtime service coordination (#15980) refactor(heartbeat): extract execution configuration (#15973) refactor(heartbeat): extract run output recording (#15969) refactor(chat): extract failed-run retry coordination (#15845) refactor(chat): extract publication replacement decisions (#15844) refactor(chat): extract identity linking (#15836) refactor(heartbeat): extract session preparation (#15966) ... # Conflicts: # packages/paperclip-runner/package.json |
||
|
|
ed31211f0e |
Merge latest Codex qualification and master fixes
Co-Authored-By: Paperclip <noreply@paperclip.ing> * codex/claude-runner-protocol: (25 commits) fix: pin ARM qualification helper to workflow source perf(ci): cache the Runner's release crate artifacts keyed by their inputs (#15932) perf(build): reuse a current Runner build in the server's prepare:runner-vendor step (#15926) fix(test): make the vitest home teardown remove read-only runtime-context bundles (#15931) fix(test): stop the Sentry timeout assertion matching a random event id (#15929) test: qualify Linux ARM with stock sandbox prerequisites docs(release): align 2026.1006.0-beta.0 stable notes header with v2026.1012.0 (#16000) fix: use Hermes adapter API URL env in prompt (#9425) fix(docker): skip the full-tree ownership walk on routine boots (#15992) refactor(chat): isolate Telegram, Slack, GitHub and Discord workflows (#15976) Preserve repository dependencies when importing GitHub skills (#15731) refactor(heartbeat): extract instruction working-copy lifecycle (#15984) test: retire redundant suites and consolidate owner coverage (#15978) refactor(heartbeat): extract runtime service coordination (#15980) refactor(heartbeat): extract execution configuration (#15973) refactor(heartbeat): extract run output recording (#15969) refactor(chat): extract failed-run retry coordination (#15845) refactor(chat): extract publication replacement decisions (#15844) refactor(chat): extract identity linking (#15836) refactor(heartbeat): extract session preparation (#15966) ... # Conflicts: # tests/runner-e2e/README.md |
||
|
|
12f7b62115 |
Merge latest Codex qualification prerequisites and master fixes
Co-Authored-By: Paperclip <noreply@paperclip.ing> * origin/codex/codex-runner-default: (25 commits) fix: pin ARM qualification helper to workflow source perf(ci): cache the Runner's release crate artifacts keyed by their inputs (#15932) perf(build): reuse a current Runner build in the server's prepare:runner-vendor step (#15926) fix(test): make the vitest home teardown remove read-only runtime-context bundles (#15931) fix(test): stop the Sentry timeout assertion matching a random event id (#15929) test: qualify Linux ARM with stock sandbox prerequisites docs(release): align 2026.1006.0-beta.0 stable notes header with v2026.1012.0 (#16000) fix: use Hermes adapter API URL env in prompt (#9425) fix(docker): skip the full-tree ownership walk on routine boots (#15992) refactor(chat): isolate Telegram, Slack, GitHub and Discord workflows (#15976) Preserve repository dependencies when importing GitHub skills (#15731) refactor(heartbeat): extract instruction working-copy lifecycle (#15984) test: retire redundant suites and consolidate owner coverage (#15978) refactor(heartbeat): extract runtime service coordination (#15980) refactor(heartbeat): extract execution configuration (#15973) refactor(heartbeat): extract run output recording (#15969) refactor(chat): extract failed-run retry coordination (#15845) refactor(chat): extract publication replacement decisions (#15844) refactor(chat): extract identity linking (#15836) refactor(heartbeat): extract session preparation (#15966) ... # Conflicts: # tests/runner-e2e/pi-controls-evidence.test.ts |
||
|
|
665c155472 |
Merge master and preserve qualified runner paths
Retain both hosted cache scopes. Use shared test-home teardown and restore owned directory permissions for the observed Mac ENOTEMPTY failure while keeping unrelated errors visible. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
a5b16834c8 |
fix: pin ARM qualification helper to workflow source
Keep frozen product and reusable workflow tooling identities separate. Preserve clean-consumer and package integrity checks. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
8227485372 |
perf(ci): cache the Runner's release crate artifacts keyed by their inputs (#15932)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Its trusted PR workflow builds the Runner's Rust binary in five
jobs: Typecheck + Release Registry, Build, Canary Dry Run, and the
`rust` and `vitest 2/2` lanes of Verify Paperclip Runner. The `Build`
job is the slowest check in almost every green run (461s, 489s and 515s
in runs 38180574768, 38182717052 and 38183149920 on 2026-10-11).
> - Each of those jobs restores master's `release-runner-v2` dependency
cache. That cache holds only third-party crates. `rust-cache` removes
workspace crates when it saves, and a fresh checkout invalidates cargo's
mtime fingerprints for workspace crates in any case. So cargo compiles
`paperclip-runner-core` in release mode from scratch on every run. The
job logs show one `Compiling` line and 28s to 49s for it.
> - 18 of the 239 commits on `master` in the seven days before this
change touched the crate's inputs. The other 221 compiled the same
sources to the same binary again.
> - This pull request adds a second cache that holds only that crate's
release artifacts (about 70 MB). The key is made from the compiler, the
checkout root and a hash of every input the build reads. The master Rust
lane writes it. A pull request whose merge tree has byte-identical
inputs restores it and marks the artifacts newer than the checkout, so
cargo keeps them. Every other pull request misses and compiles as
before.
> - The benefit is about 28s to 49s less on `Build`, which is the run's
critical path, and the same on Typecheck, Canary Dry Run and two Runner
lanes, for about nine of ten pull requests.
## Linked Issues or Issue Description
No GitHub issue exists for this. The description below follows the
enhancement template.
**What existing behavior does this improve?**
The time the trusted PR workflow spends to compile the Runner's own
crate on every run.
**Subsystem affected**
CI / build
**Current behavior**
Every PR job that builds the Runner binary compiles
`paperclip-runner-core` in release mode from scratch. The compile takes
28s to 49s on the `runs-on` fleet (one `Compiling paperclip-runner-core`
line, then `Finished release profile` in runs 38169436532 to 38183149920
on 2026-10-11). The shared Rust cache cannot help: it holds only
third-party crates, and a fresh checkout gives every source a new mtime,
which makes cargo discard the crate's fingerprints.
**Proposed behavior**
The master Rust lane in `release-verify.yml` saves the crate's release
artifacts under a key made from the compiler, the checkout root and a
hash of every input the release build reads. The PR jobs that build the
binary restore that entry read-only. On a hit, a script sets the mtime
of every restored artifact to now, so cargo sees every source as older
than the build and keeps the artifacts. `pnpm build` then prints
`Finished release profile` in under a second for that crate. On a miss,
cargo compiles the crate exactly as before.
**Reason and benefit**
About 28s to 49s off `Build`, the slowest check in almost every green
run, and the same off the Typecheck, Canary Dry Run and two Verify
Paperclip Runner lanes. The saving applies to every pull request whose
merge tree does not change the crate's inputs, which was 221 of 239
`master` commits in the week before this change.
**Breaking changes**
None. The checks are unchanged. A miss or an eviction costs the compile
time it costs today and nothing else.
**Additional context**
This is a workflow change. `pr.yml` calls `pr-trusted.yml@master`, so
this pull request's own run uses the current reader steps, and the
writer runs only on a master push. The saving becomes visible on the
first PR runs after the merge and after the next master push has written
the entry.
## What Changed
- `scripts/runner-release-crate-cache.mjs` (new): the one place that
defines the cached path list (`CACHED_PATHS`), the hashed inputs
(`HASHED_INPUTS`) and the files a restore must contain (`REQUIRED`). The
`scope` subcommand prints the platform, the `rustc --version --verbose`
release, commit and host, and a hash of the checkout root. The
`mark-current` subcommand sets the mtime of every restored artifact to
now and prints a `paperclip.runner-release-crate.v1` JSON line with the
file count and bytes. If the restored set lacks any of the seven files
cargo's freshness check reads or checks for (the fingerprint hash and
dep-info of each unit, the lib's rlib and rmeta, the binary under
`deps`), it removes the restored files, prints `action: discarded`
naming the missing file, and exits 0, so cargo compiles as on a miss.
- `.github/workflows/pr-trusted.yml`: after the `release-runner-v2`
restore in `typecheck_release_registry`, `build` and `canary_dry_run`,
and in the `rust` and `vitest 2/2` lanes of `verify_paperclip_runner`
(new matrix key `release_crate: true`), three steps: compute the key
scope, `actions/cache/restore` the crate under
`runner-release-crate-v1-<scope>-<hashFiles(...)>` with no
`restore-keys`, and run `mark-current` when `cache-hit == 'true'`. The
`hashFiles` list covers the toolchain pin, the manifests and lockfile,
the crate sources, the protocol tree and the three fixture trees the
test modules include (two under the Runner package and
`tests/runner-e2e/fixtures` at the repository root).
- `.github/workflows/release-verify.yml`: in the Rust lane of an
own-repository master push, after the debug warm-up: compute the key
scope, look the key up (`lookup-only: true`), and on a miss run `cargo
clean --release -p paperclip-runner-core` and `pnpm build:binary` (the
exact command the readers run, so the entry carries no test-profile
variants), then `actions/cache/save` the same path list under the same
key.
- `scripts/__tests__/runner-release-crate-cache.test.mjs` (new, 10
tests, in `test:release-registry`): the path list and hashed inputs are
the expected ones and exist; every `include_str!` and `include_bytes!`
in the crate sources resolves under a hashed input, whether its argument
is a literal or a `concat!` of literals, `env!("CARGO_MANIFEST_DIR")`
and macro metavariables, and any other form fails the test by name (this
guard found the `test/fixtures` tree during development and the
`tests/runner-e2e/fixtures` tree in review); the parser itself is tested
on a synthetic crate for each supported form and six rejected ones;
every PR reader restores after the dependency cache and marks before its
build command with the script's exact path list and key and no
`restore-keys`; the Verify lanes are gated by `release_crate`; the
writer runs after the checks with the lookup, the clean and build, and
the save under the readers' exact path list and key; the scope changes
with the compiler and the checkout root and survives a missing `rustc`;
`mark-current` makes every artifact newer than the checkout, leaves a
dependency's artifacts alone, discards a restore missing any one of the
seven required files (one case each, checking the named reason), and
still marks a restore missing any one of the seven files cargo does not
need.
## Review fixes
Greptile's two findings on the first commit were both valid and are
fixed in the second commit:
- **Incomplete caches looked usable.** `REQUIRED` checked four files,
but cargo's freshness check needs seven. Measured with cargo 1.97.1 on
the real crate (restore, touch the artifacts, delete one file, build):
without the lib's fingerprint hash, dep-info, rlib or rmeta it
recompiles the crate (24s to 27s); without the bin's fingerprint hash,
dep-info or the binary under `deps` it relinks (1.5s); without either
`.json` fingerprint record, either rustc `.d` file, the uplifted binary
or its `.d` it reports the crate fresh in 0.15s and recreates the
uplifted binary from `deps`, and the staging step then copies it.
`REQUIRED` now lists exactly the seven files, the glob for the binary
under `deps` excludes the `.d` beside it, and the test removes each of
the seven in turn (discarded, naming it) and each of the other seven in
turn (still marked).
- **Composed include paths escaped the guard.** The regex matched only
`include_str!("literal")` and skipped `include_str!(concat!(...))`,
which the crate uses four times (30 of 34 includes were checked). The
guard now parses every include argument and resolves the `concat!`
forms; one of them, in `provider_events.rs`, reads
`tests/runner-e2e/fixtures/native-completion/terminal-tool-carrier.json`
at the repository root, outside every hashed input. It is test-only, so
today's release binary does not read it, but the key is meant to cover
every include whatever its build, so `tests/runner-e2e/fixtures/**` (9
files, 80 KB) joins `HASHED_INPUTS` and the six key embeddings in the
two workflows. With the first commit's input list, the new guard fails
on exactly that include.
- `doc/RELEASE-AUTOMATION-SETUP.md`: a "Runner release crate cache"
section under the Runner verification dependency cache, with the key,
the writer, the readers and the trust boundary.
- `package.json`: the new test file in `test:release-registry`.
## Verification
- `node --test scripts/__tests__/runner-release-crate-cache.test.mjs`:
10 tests pass, three consecutive runs.
- The second commit, with the real toolchain on the real crate (`rustc
1.97.1`, cold build 2m20s, the crate's artifacts 74 MB): every source
touched to a fresh-checkout mtime and the archived artifacts restored,
cargo compiles (`Compiling paperclip-runner-core`, 24.8s and 25.1s, the
two controls); restored and marked by `mark-current`, `Finished release
profile in 0.16s` with no `Compiling`, and the same on a second build.
Then, for each of the fourteen files cargo wrote for the two units, one
at a time: restored, marked and that file deleted, cargo recompiles
without any of the seven `REQUIRED` files and reports fresh without any
of the other seven; restored with that file deleted and run through
`mark-current`, the seven required ones print `action: discarded` naming
the file and the others print `marked`. A restore holding only the seven
required files builds fresh in 0.15s, cargo recreates the uplifted
binary, and `stage-runner-binary.mjs` copies it into `dist/bin`.
- `node --test '.github/scripts/tests/*.test.mjs'`: 378 of 381 pass. The
3 failures are in `docker-canary-promotion.test.mjs` and fail the same
way on an unmodified `master` checkout in this sandbox (the stand-in
docker writes no `calls.jsonl`).
- `node --test scripts/__tests__/release-verify-workflow.test.mjs
scripts/__tests__/e2e-shard.test.mjs
scripts/__tests__/run-vitest-stable-shard.test.mjs`: 99 of 101 pass; the
2 failures spawn `pnpm`, which is not on this sandbox's PATH, and fail
the same way on `master`.
- Both workflows parse as YAML. No job has a duplicate step name or step
id.
- The mechanism, with the real toolchain (`rustc 1.97.1`, the package's
pin) on a copy of the crate: a cold `cargo build --release -p
paperclip-runner-core --bin paperclip-runnerd` (2m23s here). Then the
artifact set was archived with `tar`, removed, every source re-copied so
each had a new mtime, and the set restored:
- restored, not marked: `Compiling paperclip-runner-core`, 24.6s (the
control; this is what CI does today);
- restored and marked by `mark-current`: `Finished release profile in
0.15s`, no `Compiling`; a second build is the same;
- one Rust source edited after a marked restore: `Compiling`, 24.0s;
- one protocol schema edited after a marked restore: `Compiling`, 23.9s
(the protocol files enter cargo's dep-info as absolute paths and are
hashed into the key);
- the rlib removed from a restored set: `mark-current` prints `action:
discarded, reason: incomplete: the lib rlib is missing` and removes the
rest, and cargo compiles.
- Not run here: the workflow steps themselves. `pr.yml` pins
`pr-trusted.yml@master`, so this pull request's own `Build` job runs the
current reader steps, and the writer runs only on a master push. The
first PR runs after the merge and after the next master push show the
`Restore the Runner release crate` step's result and the
`paperclip.runner-release-crate.v1` line in their `Build` logs.
## Risks
- Correctness: a reader can only restore artifacts that master built
from inputs byte-identical to its own merge tree, because every input
the build reads is in the key, and the key has no prefix match. A pull
request cannot write. The trust boundary is unchanged: master writes, a
pull request restores master's entry.
- An input the build reads that is outside the hashed patterns would let
a stale artifact pass. The release dep-info lists the crate sources and
the protocol schemas and fixtures; all are hashed. The guard test
resolves every `include_str!` and `include_bytes!` in the crate, literal
or `concat!`, and fails if one lands outside the hashed inputs or uses a
form it cannot resolve, so a new include form cannot slip past it by not
matching a regex.
- GitHub-hosted runners check out under `/home/runner/work`, the
`runs-on` fleets under `/home/runner/_work`. Cargo records the included
protocol files as absolute paths, so an entry from one root is useless
under the other. The checkout root is in the key, so the other root
misses instead of restoring something cargo then discards.
- A cache that does not keep mtimes on restore changes nothing: the
artifacts are then already newer than the checkout, and `mark-current`
sets them to now in any case.
- Cost: one new entry of about 70 MB per distinct input set, written
only by the master Rust lane on a miss, plus one `cargo clean` and
`build:binary` (about 40s to 50s) on that lane when the inputs changed.
The readers pay one restore of about 70 MB (two to three seconds at the
fleet's observed restore speed) and a sub-second `mark-current`.
- An incomplete entry (a writer that saved a partial set) is discarded
by `mark-current` and costs one compile, the same as a miss.
## Model Used
- Claude (Anthropic), model id `claude-fable-5-1` (Claude Fable 5.1),
extended thinking, with tool use (shell, file editing, GitHub CLI, a
local Rust toolchain for the experiment) in a Paperclip agent 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
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
|
||
|
|
7df517d18f |
perf(build): reuse a current Runner build in the server's prepare:runner-vendor step (#15926)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Its CI runs a `Build` job on every pull request. That job runs `pnpm build` and then verifies the public npm install. Since the server test shards got faster, `Build` is the slowest check in most runs (419-497s on the six fully green `master` runs created 2026-10-11 19:46Z to 20:17Z). > - Inside `pnpm build`, the server package is the last package to build. Its first step, `prepare:runner-vendor`, runs the full build of `@paperclipai/paperclip-runner` so the server can vendor `packages/paperclip-runner/dist`. In `pnpm -r build` that package was built seconds earlier by the same command. The second build took 12-16s on those six runs and sits on the critical path of the job. > - The step cannot just be removed. A standalone `pnpm --filter @paperclipai/server build` (the Dockerfile's path) must produce a current vendored Runner on its own. > - This pull request keeps that guarantee and skips only the build that is provably redundant. The Runner's `build` records a digest of its inputs, captured before its first step and confirmed after its last, together with a manifest of every file it left under `dist`. The server's `prepare:runner-vendor` reuses the build when the digest matches, the stamp is for this platform, and every recorded output is still there at its recorded size. Any other state runs the same full Runner build as before. > - The benefit is 12-16s off the `Build` job and off every other `pnpm build` (the Canary Dry Run's `release.sh` build, local builds), with no change to what a standalone server build produces. The PR's own first run measured it: the server step reused the build in 56ms where `master` runs rebuilt for 11-15s. ## Linked Issues or Issue Description No GitHub issue exists for this. The description below follows the enhancement template. **What existing behavior does this improve?** The server build's `prepare:runner-vendor` step, which builds `@paperclipai/paperclip-runner` so the server can vendor its `dist`. **Subsystem affected** Build and CI (`server/package.json`, `packages/paperclip-runner/package.json`, the `Build` job). **Current behavior** `prepare:runner-vendor` runs the Runner's full `build` every time. Inside `pnpm -r build`, the Runner was already built by the same command 20 to 25 seconds earlier, with every check passing. On six fully green `master` runs (2026-10-11, 19:46Z to 20:17Z) the repeated build took 11.8s to 15.9s, measured from the `server build$ pnpm run prepare:runner-vendor` log line to the Runner's `Finished release profile` line. The server package builds last, so that time is on the critical path of `Build`, which is the slowest check in most pull request runs. **Proposed behavior** - The Runner's `build` starts with `node scripts/record-build-inputs.mjs --begin` and ends with `node scripts/record-build-inputs.mjs --finish`. `--begin` removes the previous stamp and records a digest of every build input before the first step reads anything. `--finish`, after every step and check has passed, recomputes the digest and writes `packages/paperclip-runner/node_modules/.cache/paperclip-runner-build-inputs.json` only if the inputs are still the ones the build began with, together with the path and size of every file under `dist`. A stamp therefore exists only for a build that completed every step on inputs that did not move while it ran. - The server's `prepare:runner-vendor` becomes `node scripts/prepare-runner-vendor.mjs`. It reuses the build if the stamp is for this platform and architecture, every recorded output is still there at its recorded size, and the recomputed digest matches. In every other case it removes the stamp and runs `pnpm --filter @paperclipai/paperclip-runner build`, the exact command the step ran before. - `PAPERCLIP_RUNNER_VENDOR_REBUILD=1` forces the rebuild. **Reason and benefit** 12-16s off the `Build` job and off every other `pnpm build` (the Canary Dry Run's `release.sh` build, local builds), with no change to what a standalone `pnpm --filter @paperclipai/server build` produces. **Breaking changes** None. The rebuild path runs the same command as before. A fresh checkout, a changed input, a missing or truncated output, an edit that landed during the build, or a stamp from another platform always rebuilds. ## What Changed - `packages/paperclip-runner/scripts/build-inputs.mjs` (new): defines the input set, the digest, the output manifest and the reuse decision. Inputs are every file under `packages/paperclip-runner` except `dist`, `dist-browser`, `runner/target`, `node_modules` and dot-directories; every file under `packages/paperclip-eval-kernel` except `dist` and `node_modules` (the Runner's `build:typescript` builds it first); every file under the root `patches` directory (`check:acpx-profiles` hashes `acpx@0.13.1.patch`, and `build-verified-provider-entrypoints.mjs` copies the `pi-acp` and `brace-expansion` patches into `dist/cli/pi-provision-inputs`); and the root `package.json`, `pnpm-lock.yaml`, `pnpm-workspace.yaml` and `tsconfig.base.json`. The toolchain pins are inside the package (`rust-toolchain.toml`, `runner/Cargo.lock`) and the TypeScript version is in the lockfile, so both are covered. A symlink is hashed as its target path and is not followed. Outputs are every file under `dist`, the tree the server copies wholesale, recorded with their sizes. Exports `beginRunnerBuild`, `recordRunnerBuild` and `assessRunnerBuild` (returns `current` plus a stable reason code: `no_stamp`, `schema_mismatch`, `platform_mismatch`, `missing_output`, `outputs_changed`, `inputs_changed`, `inputs_unchanged`). - `packages/paperclip-runner/scripts/record-build-inputs.mjs` (new): the two phases, `--begin` and `--finish`, added as the first and last step of the Runner's `build` in `packages/paperclip-runner/package.json`. Each build chain has its own pending record under `node_modules/.cache/paperclip-runner-build-inputs.pending/`, named after the shell pnpm runs the chain in (the parent of both phases; `--finish` also accepts a record named after its own pid, for a shell that execs the last command of the chain), so two Runner builds running at once in one checkout do not consume each other's record. `--finish` without a pending record for its chain is an error, so the chain cannot silently lose its first step; `--finish` after an edit that landed mid-build prints `not recorded: inputs changed while the build ran` and leaves no stamp. Records of builds that never finished are pruned by the next `--begin` after a day. - `server/scripts/prepare-runner-vendor.mjs` (new): the reuse-or-rebuild step. It resolves the pnpm that is running it through `npm_execpath` with the same rule as the CLI's `resolvePnpmInstallInvocation` (a JavaScript entry runs through this Node, a native executable runs directly, otherwise `pnpm` on PATH). It prints one `paperclip.runner-vendor.timing.v1` line with `action`, `reason`, `check_ms` and `build_ms`, so the saving is measured on this PR's own `Build` job. - `server/package.json`: `prepare:runner-vendor` now runs that script. The `build` and `typecheck` scripts are unchanged. - `server/src/__tests__/server-package-build-script.test.ts`: pins the new indirection and the command behind it (imported from the script, so the Dockerfile's standalone path stays pinned), and a new test asserts the Runner's `build` starts with `--begin`, ends with `--finish`, and has exactly those two record steps. - Tests: `packages/paperclip-runner/scripts/build-inputs.test.mjs` (node:test, added to `test:typescript:prep`) and `server/scripts/prepare-runner-vendor.test.mjs` (vitest, in the server lane). - `doc/DEVELOPING.md`: a "Reused Runner build in the server build" section under Test Commands. ## Review findings on the first head, all fixed in [ |
||
|
|
0ea8ebd040 |
fix(test): make the vitest home teardown remove read-only runtime-context bundles (#15931)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Its CI runs the server test suite as twelve `General tests (server
(n/12))` shards on every pull request. Each shard worker gets its own
throwaway `PAPERCLIP_HOME` from
`server/src/__tests__/setup-supertest.ts`, which removes it with a
recursive `rmSync` at worker exit.
> - That removal has been failing now and then with `EACCES, Permission
denied: /tmp/.../paperclip-vitest-home-...` after every test file in the
shard passed (four shard jobs on 2026-10-11 between 14:10Z and 22:10Z,
on four different branches, each attributed to
`native-session-resumption.test.ts` because that file was running in the
worker at exit). Vitest reports it as an unhandled error and fails the
shard, so the job has to be re-run, which costs a full shard (four to
six minutes) on the run's critical path.
> - The directory it cannot remove is one a native session leaves
behind: runtime-context bundles are published under the instance root
(`$PAPERCLIP_HOME/instances/<id>/runtime-context-assets/bundles/<digest>`)
and every directory in them is made read-only by design
(`makeDirectoriesReadOnly` in
`services/native-runtime/runtime-context.ts`). A file inside a read-only
directory cannot be unlinked, so the recursive removal stops with
`EACCES`. Whether such a bundle is under the worker's home at exit
depends on timing: suites set and restore `PAPERCLIP_HOME` for their own
fixtures, and a heartbeat that is still finishing when the worker exits
can publish its bundle under whichever home is current.
> - The teardown is the right place to fix this: the bundle is read-only
on purpose, and the test home is throwaway. On a permission error the
teardown now makes every directory in the tree writable and removes it
again.
## Linked Issues or Issue Description
No GitHub issue exists for this. The description below follows the bug
report template.
**What happened?**
A `General tests (server (n/12))` shard fails after all its test files
passed:
```
Vitest caught 1 unhandled error during the test run.
Error: EACCES, Permission denied: /tmp/pv-k2snZS/t/paperclip-vitest-home-qANo1F
❯ Object.rmSync node:fs:1282:18
❯ process.<anonymous> server/src/__tests__/setup-supertest.ts:32:31
This error originated in "server/src/__tests__/native-session-resumption.test.ts" test file.
Test Files 74 passed (74)
Tests 3226 passed | 1 skipped (3227)
Errors 1 error
```
Seen on 2026-10-11 in the first attempt of run 38146108750 (server
(11/12)), run 38150787810 (server (11/12)), run 38178832013 (server
(12/12), branch `fix/windows-opencode-utf8`) and run 38179110043 (server
(11/12), branch `fix/sentry-timeout-assertion-event-id`). The re-run of
the same job passes every time.
**Expected behavior**
A shard whose tests all passed is green. The per-worker test home is
removed at exit whatever a finishing run left in it.
**Steps to reproduce**
1. Create a directory tree with a read-only directory inside it, the way
`makeDirectoriesReadOnly` publishes a runtime-context bundle: `mkdir -p
home/bundle && touch home/bundle/SKILL.md && chmod 555 home/bundle`.
2. Remove it the way the setup file did: `node -e
"require('fs').rmSync('home', { recursive: true, force: true })"`.
3. The removal throws `EACCES` and leaves the tree behind. The new
`removeTestHome` removes it.
**Paperclip version or commit**
`master` at
|
||
|
|
a96329dfa2 |
fix(test): stop the Sentry timeout assertion matching a random event id (#15929)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Every pull request runs the `Sentry SDK contract` workflow, whose one job installs the real `@sentry/node` outside the workspace and runs `server/src/__tests__/run-failure-sentry-real-sdk.test.ts` to prove that run-failure reports never carry provider output or credentials. > - One of its assertions checks that the captured events do not contain the provider's stderr canary `<html>504 Gateway Time-out private-timeout-credential-canary</html>`, by matching the serialized events against `/private-timeout-|<html>|504|Timed out after/`. > - The bare `504` alternative also matches a Sentry event id. On pull request #15926 (a build-script change that does not touch this code) the job failed because that run's event id was `f353d184e5504ee39db611f2e60f49ff`; the re-run passed. About 0.7% of random 32-character hex ids contain `504`, and the test serializes two events, so roughly one job in seventy fails for no reason. > - This pull request narrows that alternative to `504 Gateway`, which still catches the canary with or without its HTML wrapper and cannot match a hex id. ## Linked Issues or Issue Description No GitHub issue exists for this. The description below follows the bug report template. **Pre-submission checklist** - [x] I have searched existing open and closed issues and this is not a duplicate. - [x] I am on the latest released version of Paperclip (or can reproduce on `master`). - [x] I have confirmed the error originates in Paperclip itself — not in my agent adapter, API provider, or local configuration. **What happened?** The `Sentry SDK contract` job (`Real Sentry SDK isolation`) failed on pull request #15926 at head |
||
|
|
0690801f13 |
test: qualify Linux ARM with stock sandbox prerequisites
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
3fc2af5511 |
Merge Claude Auto effort and implicit harness fixes
Co-Authored-By: Paperclip <noreply@paperclip.ing> * codex/claude-runner-default: fix(claude): honor Auto effort and implicit native harness settings |
||
|
|
4dc13aa32c |
fix(runner): match image and native provider pack contents
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
23d834fc0a |
fix(claude): honor Auto effort and implicit native harness settings
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
f8798aac1e |
docs(release): align 2026.1006.0-beta.0 stable notes header with v2026.1012.0 (#16000)
<!-- Write all pull request text in Simplified Technical English (ASD-STE100). --> ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The release pipeline promotes a soaked beta to stable. The stable job publishes `releases/beta/v<beta-version>.md` from `master` as the GitHub Release body, pinned at dispatch time. > - Beta `2026.1006.0-beta.0` (source `22a3ea3414e9039a538fbb0374b3cfa7fc4371eb`, 130 commits after v2026.1005.0) has soaked for more than three days. The stable version for 2026-10-12 is `v2026.1012.0`. > - The curated notes from #15388 were written at beta time. They guess `v2026.1009.0` and `2026-10-09`, which did not ship. > - A pre-dispatch audit confirmed the commit count, the PR cross-check, the migration range, the environment defaults, and the Contributors handles. Only the header, the date, the intro version, and the contributor count are stale. > - This pull request corrects those four lines before the stable dispatch, so the public release page shows the version that ships. > - The benefit is that the GitHub Release body and the canonical notes file agree with the npm version and the git tag. ## Linked Issues or Issue Description **Issue type** Docs: release notes. **Where is the issue?** `releases/beta/v2026.1006.0-beta.0.md` on `master`. **What's wrong?** The notes carry a guessed stable version and date from beta time: - The H1 reads `# Paperclip v2026.1009.0` and the next line reads `> Released: 2026-10-09`. No `v2026.1009.0` stable shipped. The stable that promotes this beta on 2026-10-12 resolves to `v2026.1012.0`. - The intro paragraph names `v2026.1009.0` for the same reason. - The Contributors line says 8 contributors. `git shortlog -sn v2026.1005.0..22a3ea3414e9039a538fbb0374b3cfa7fc4371eb` lists 10 authors. Excluding `github-actions[bot]` gives 9 (this count includes `dependabot[bot]`, as the v2026.916.0 notes did). Paperclip Cloud changes in the range (#15314, #15340) stay out of these notes. The notes do not cite them today, and this change does not add them. **Suggested fix** Change the version in the H1 and the intro paragraph to `v2026.1012.0`, change the Released line to `2026-10-12`, and change the contributor count to 9. Change nothing else. ## What Changed - Line 1: `# Paperclip v2026.1009.0` → `# Paperclip v2026.1012.0`. - Line 3: `> Released: 2026-10-09` → `> Released: 2026-10-12`. - Line 5: the intro paragraph now starts `Paperclip v2026.1012.0 carries 130 commits`. - Contributors: `from 8 contributors` → `from 9 contributors`. - No other lines changed. The 130-commit count, the cited PR numbers, the `0294`–`0305` migration range, the environment defaults, and the external handles were already correct. ## Verification - Docs only. `scripts/release.sh stable --print-version --date 2026-10-12` on `master` prints `2026.1012.0`, which matches the new header. - `git rev-list --count v2026.1005.0..22a3ea3414e9039a538fbb0374b3cfa7fc4371eb` is 130, which matches the notes. - All 89 PR numbers cited in the notes are in that range. The 40 uncited in-range PRs are 23 Dependabot bumps, one lockfile refresh, six test-only changes, five release-notes and contributor-docs changes, one CODEOWNERS change, two evals changes, one release-smoke test change, and two Paperclip Cloud changes (#15314, #15340). - Migrations `0294`–`0305` match `packages/db/src/migrations` in the range. `0298` is the only migration that updates existing rows. - Defaults were read at the beta source: `--listen-port` defaults to 43127 in `paperclip-runnerd.rs`; silent-run thresholds are 5 and 15 minutes in the sandbox runtime; remote Codex accepts `0.149.0` up to but excluding `0.161.0` in `codex-runtime-compatibility.ts`; pins are Codex `0.160.0`, Claude Agent SDK `0.3.286`, OpenCode `1.18.34`; Sonnet 5.5 needs Claude Code `2.1.284` or later. - `git shortlog -sn` over the range gives 9 contributors excluding `github-actions[bot]`. The external handles are `@baozdemir`, `@valentinpalkovic`, and `@abderbejaoui`, which the notes already list. - `git diff --stat` shows one file, 4 insertions, 4 deletions. ## Risks Low. Documentation only. This must merge before the stable dispatch, because the stable job pins the `master` revision of this file at dispatch time. ## Model Used Anthropic Claude Fable 5.1 (`claude-fable-5-1`) via Claude Code, with tool use and code execution. ## 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 (docs only; no tests apply) - [x] I have added or updated tests where applicable (none apply) - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green (running) - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups (running) - [x] I will address all Greptile and reviewer comments before requesting merge 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>canary/v2026.1012.0-canary.10 |
||
|
|
39fec166b9 |
Merge the exact Pi v23 install-probe digest
Co-Authored-By: Paperclip <noreply@paperclip.ing> * codex/claude-runner-default: fix(runner): pin the Pi v23 digest in its install probe |
||
|
|
cbc0d6e946 |
Merge the exact Pi v23 install-probe digest
Co-Authored-By: Paperclip <noreply@paperclip.ing> * codex/claude-runner-protocol: fix(runner): pin the Pi v23 digest in its install probe |
||
|
|
33c9216614 |
fix(runner): pin the Pi v23 digest in its install probe
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
a1ac0a7324 |
Merge the current Pi clean-install assertion
Co-Authored-By: Paperclip <noreply@paperclip.ing> * codex/claude-runner-default: fix(runner): verify the current Pi profile in clean installs |
||
|
|
d0cc4332ab |
Merge the current Pi clean-install assertion
Co-Authored-By: Paperclip <noreply@paperclip.ing> * codex/claude-runner-protocol: fix(runner): verify the current Pi profile in clean installs |
||
|
|
ca52d2998c |
fix(runner): verify the current Pi profile in clean installs
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
4c7e0538c3 |
Merge the reviewed compact question envelope fix
Co-Authored-By: Paperclip <noreply@paperclip.ing> * codex/claude-runner-default: fix(runner): point v7 question answers to the compact envelope |
||
|
|
8cd1212d08 |
Merge reviewed v7 question-answer correction
Co-Authored-By: Paperclip <noreply@paperclip.ing> * codex/claude-runner-protocol: fix(runner): point v7 question answers to the compact envelope |
||
|
|
bd966ff9cd |
fix(runner): point v7 question answers to the compact envelope
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
2145925f71 |
fix: use Hermes adapter API URL env in prompt (#9425)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The Hermes adapter builds the command environment and renders the prompt that tells Hermes how to call back into Paperclip. > - Adapter configuration can provide `PAPERCLIP_API_URL` through `config.env`, which is often the most precise API base for the spawned worker. > - The current prompt rendering path does not read that adapter env value when deciding which Paperclip API base to show. > - This can leave Hermes with prompt instructions that point at a less appropriate process-level or public URL, even though the adapter env contains the intended API base. > - This pull request makes prompt rendering honor the adapter env value before falling back to broader process defaults. > - The benefit is a more consistent Hermes prompt without changing command execution behavior. ## Linked Issues or Issue Description Adapter: Hermes Agent or provider Hermes local adapter. Why this adapter is useful The Hermes adapter lets Paperclip run Hermes-backed agents while preserving Paperclip run context and callback instructions. How the agent is invoked Paperclip spawns the configured Hermes command and passes a rendered prompt plus adapter-provided environment variables. What happened? When `PAPERCLIP_API_URL` is supplied through adapter env, the Hermes subprocess receives it, but the prompt can still render its API base from a process-level fallback instead of that configured adapter env value. Expected behavior If an explicit `paperclipApiUrl` option is not configured, the prompt should prefer `config.env.PAPERCLIP_API_URL` when present, then fall back to the existing defaults. Related context: supersedes NousResearch/hermes-paperclip-adapter#118 for Paperclip's bundled Hermes adapter. ## What Changed - Added a small env-value resolver for raw string values and `{ value: string }` wrappers. - Builds a prompt-specific config that uses `config.env.PAPERCLIP_API_URL` when `paperclipApiUrl` is not explicitly set. - Added a focused command-resolution test that verifies the rendered prompt API base uses the adapter env URL instead of the process fallback. ## Verification - `pnpm --filter @paperclipai/hermes-paperclip-adapter test:command-resolution` - `pnpm --filter @paperclipai/hermes-paperclip-adapter typecheck` - `pnpm --filter @paperclipai/hermes-paperclip-adapter build` ## Risks Low risk. This only affects prompt rendering for Hermes adapter runs where `paperclipApiUrl` is unset and `config.env.PAPERCLIP_API_URL` is present. Explicit `paperclipApiUrl` values keep precedence, and existing fallback behavior remains in place when the env value is absent. ## Model Used OpenAI Codex, GPT-5.5, tool-enabled coding session with local shell, Git, and GitHub CLI validation. ## 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: zocomputer <help@zocomputer.com> Co-authored-by: commitperclip[bot] <284812584+commitperclip[bot]@users.noreply.github.com> |
||
|
|
d0da37c221 |
feat(runner): assemble target-owned Claude Linux provider packs
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
18626f677f |
Merge reviewed Claude behavior into platform qualification
Co-Authored-By: Paperclip <noreply@paperclip.ing> * codex/claude-runner-default: docs: link the approved protocol review boundary fix(runner): retain versioned profiles in Docker context docs: record Claude review fixes and protocol prerequisite fix(claude): preserve permissions and connection claims at creation feat(runner): admit Claude effort before native prompts and resume fix: preserve TOML table semantics during Codex startup trust |
||
|
|
8d07b40907 |
Merge protocol Docker context correction
Co-Authored-By: Paperclip <noreply@paperclip.ing> * codex/claude-runner-protocol: fix(runner): retain versioned profiles in Docker context |
||
|
|
a950d9b163 |
docs: link the approved protocol review boundary
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
269e802fe6 |
fix(runner): retain versioned profiles in Docker context
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
342a9f4b18 |
docs: record Claude review fixes and protocol prerequisite
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
12f30702d7 |
Merge branch 'codex/claude-runner-protocol' into codex/claude-runner-default
* codex/claude-runner-protocol: feat(runner): admit Claude effort before native prompts and resume fix: preserve TOML table semantics during Codex startup trust Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
6263a47185 |
fix(claude): preserve permissions and connection claims at creation
Retain native import settings, explicitly select Legacy in qualification, pin updated CLI fixtures, and version shared source attestations. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
2e8d5e906e |
feat(runner): admit Claude effort before native prompts and resume
Version the shared Pi and pending Copilot source attestations without changing their executable closures or platform qualification. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
4f399cec9f |
fix(docker): skip the full-tree ownership walk on routine boots (#15992)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - The Docker image keeps all instance state under `PAPERCLIP_HOME`,
and deployments mount a volume there
> - Before it drops privileges, the entrypoint makes sure that the
`node` user owns the home (#10530)
> - The ownership probe is a first-mismatch `find` over the whole tree.
When ownership is correct, `-quit` never fires, so every boot stats
every file on the volume
> - On homes with many agent worktrees and `node_modules` trees, this
walk takes minutes before Node starts. That is close to common 300s
healthcheck windows
> - This pull request keeps a cheap shallow probe on every boot. It runs
the full-tree probe only once per volume and node UID/GID, and records
the result in a marker file
> - The benefit is that routine boots no longer scale with the file
count, and the original root-owned-volume fix stays in place
## Linked Issues or Issue Description
Refs #10431 (the open follow-up about the remaining cost of the
ownership walk). Related: #10530 (the change that added the full-tree
probe).
**What happened?**
On a hosted multi-instance deployment, we measured the time from
container start to the first app log line. Instances with many files on
the volume (agent worktrees with `node_modules`) took about 190-235s.
Small instances took 5-22s. One 30 GB volume with few files took 24s, so
the cost follows the file count, not the volume size. Almost all of this
time is the `find "$home_dir" \( ! -user node -o ! -group node \) -print
-quit` walk in `scripts/docker-entrypoint.sh`. When ownership is already
correct, `-quit` never fires, so the walk stats every inode on every
boot.
**Expected behavior**
When ownership is already correct, the entrypoint pre-start phase is
short and does not depend on the number of files in `PAPERCLIP_HOME`. A
fresh root-owned volume, a UID/GID remap, and an upgrade from an older
image are still repaired before the privilege drop.
**Steps to reproduce**
1. Run the image with a volume on `/paperclip` that holds a few hundred
thousand files, all owned by `node:node`.
2. Restart the container.
3. Compare the container start time with the first server log line. The
gap grows with the file count, even though no `chown` runs.
**Paperclip version or commit**
`master` at
|
||
|
|
a200495cc7 |
fix: preserve TOML table semantics during Codex startup trust
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
c860863295 |
feat(runner): select verified Claude Linux ARM64 artifacts
Automatic defaults remain gated until installed execution qualification passes. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
a2ac5c2715 |
refactor(chat): isolate Telegram, Slack, GitHub and Discord workflows (#15976)
## Thinking Path > - Paperclip manages AI agents and their work. > - Chat channels connect that work to external conversations. > - The shared chat service still contains provider-specific workflows. > - Those workflows are hard to inspect in a 34,000-line file. > - This stack extracts Telegram, Slack, GitHub and Discord workflows into their channel folders. > - Shared authorization and service lifetime remain explicit. ## Linked Issues or Issue Description Refs #15823, #15834, #15836, #15844 and #15845. Root of the second behavior-preserving channel-folder refactor stack. The dependent PRs #15979, #15981, #15985 and #15987 have merged into this branch; this PR lands all five extractions on master. ## What Changed - Move Telegram maintenance and subscription repair into `chat-channels/telegram/maintenance.ts`. - Move Slack session stopping and task starts into `chat-channels/slack/session-stop.ts` and `task-start.ts`. - Move GitHub webhook intake and recovery into `chat-channels/github/webhook-ingress.ts`. - Move Discord command registration and handling into `chat-channels/discord/commands.ts`. - Share type-only runtime records while preserving shared authorization, transactions, live lease checks and worker ownership. - Reduce the original service from 34,603 to 29,897 lines, removing 4,706 lines (13.6%). ## Verification - All 205 selected integration cases passed before and after their respective extractions: Telegram 41, Slack session stop 2 multi-step scenarios, GitHub 84, Slack task start 25 and Discord 53. Each dependent PR records its focused reproduction command. - Server typecheck, module boundaries and whitespace checks passed. - Per-slice syntax comparisons passed for moved declarations and remaining service statements, allowing only the documented live callback substitutions. - Tests exercise the public service with disposable databases and fixture provider transports. They do not claim live third-party execution. - Cumulative workspace typecheck and build passed on the final stack. - Current-head CI passed on the combined stack commit `d5b37dbe512e3e199932b6608cdc17639eda555a`; Greptile is 5/5 with no unresolved threads. - The [original serialized shard](https://github.com/paperclipai/paperclip/actions/runs/38266518817/job/114870022249) timed out in unchanged `adapter-auth-signal-routes.test.ts`. The exact case passed locally without changes, and the [single job retry](https://github.com/paperclipai/paperclip/actions/runs/38266518817/job/114874019933) passed. The original timeout remains recorded. Reproduce the original Telegram slice’s focused suite: ```sh pnpm exec vitest run server/src/__tests__/chat-channels.integration.test.ts -t 'Telegram durable private draft Stop|Telegram maintenance|Telegram webhook|Telegram.*(pause|remove)|Telegram.*commands' ``` - Cumulative local `pnpm test:run` exited 1: the first server group had **18,770 passed, 105 skipped, and one timeout** in unchanged `server/src/services/workspace-git-snapshot-streaming.test.ts:56` (300,000 ms on macOS). The fail-fast runner did not reach its later workspace and serialized groups. An unchanged isolated rerun passed using the existing timeout; this does not turn the original full run green. The test and its Git utility code are outside this refactor; all current-head CI jobs passed. - Reproduce that diagnostic alone: `pnpm exec vitest run server/src/services/workspace-git-snapshot-streaming.test.ts`. ## Risks - Credential lease ownership and provider-confirmation ordering must remain unchanged. Existing rotation, lease-loss, recovery and durable Stop cases pass. - The channel factories create no workers or timers and preserve live runtime, shutdown and gateway-ownership reads. ## Model Used OpenAI Codex, GPT-6 family, with reasoning and repository tools. The exact runtime model ID and context-window size are not exposed in this session. No separate agent was used. ## 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 - [ ] 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> |
||
|
|
ee315082e4 |
Merge remote-tracking branch 'origin/codex/codex-runner-default' into codex/claude-runner-default
* origin/codex/codex-runner-default: test: bind installed native payloads and await saved state Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
7c0f3d75a6 |
fix(ui): hide legacy commands for native Claude
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
7ede05c1c5 |
docs: record successful Claude API resume acceptance
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
966b3d5bc2 |
Merge latest Codex platform qualification into Claude default
Preserve Codex GNU libc eligibility and Linux ARM64 behavior; keep Claude automatic selection limited to Apple Silicon. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
598e190cb3 |
test: bind installed native payloads and await saved state
Isolate actual Codex resolver fixtures from global bridge lookup and preserve host qualification blockers with literal evidence. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
9788c05d0a |
test(runner): retain bounded Claude qualification evidence
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
5a60820588 |
fix(runner): acknowledge Claude cold session resume
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
a9830414c7 |
Preserve repository dependencies when importing GitHub skills (#15731)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Its Skills library imports reusable instructions from GitHub. > - Some skills depend on shared files and sibling skills outside their folders. > - Directory-only imports lose those dependencies. > - This pull request keeps repository files together and lets users select which skills appear in the library. > - Agents receive the original files and paths through the existing skill delivery system. ## Linked Issues or Issue Description Refs #14713. Related: #13656. **Current behavior** GitHub imports copy independent skill directories. Shared scripts, policies, helper skills, and credit files can be omitted. One shared-file error can block every skill. **Proposed behavior** New imports keep repository files together at the scanned commit. Show all skills with their folders and select every skill by default. Collapse individual package files. Omit unsupported or oversized files with a warning. Import available content without repair choices or an extra confirmation. Keep warnings on the saved source. **Reason and benefit** Skills can read their shared repository files after Paperclip delivers them to an agent. Original instructions stay unchanged. Users can inspect included files and understand omissions before and after import. ## What Changed - Store immutable company-scoped repository snapshots and associate them with skill versions. Regenerate the migration after merging master. - Preserve original bytes, binary encoding, and executable modes. Shared-file changes version each usable selected skill. Pinned versions retain their original files. - Deliver a discovery wrapper with the original tree under `.paperclip-repository/`. Preserve invocation policy when present. Fork and create-from-existing retain repository files. - Keep repository files together for new UI imports. Show every skill, select all by default, and collapse package files. Remove the packaging-mode menu. Keep the mobile import footer visible. - Warn about symlinks, submodules, oversized files, missing references, and invalid optional manifests. A malformed skill remains selected with a Needs setup warning. Usable skills still publish, and its original file remains repository support content. Source warnings persist through refresh. Unsafe execution and secret-disclosure findings omit the affected files before snapshot publication. - Expose saved repository files in the installed skill viewer, including binary encoding and executable flags. Reads use the immutable company-scoped snapshot; relative instruction links resolve from their original repository directory. - Audit delivered inventories and derive trust from all repository files. Accept evaluation prose while retaining dynamic-execution findings. Read blobs in one bounded Git batch and check budgets before reading support files. Imports never execute setup commands. - Add scanner, database, delivery, UI, and browser regressions. Update Storybooks, screenshots, and documentation. ## Verification - 69 focused scanner, Git snapshot, delivery, and PostgreSQL lifecycle tests passed. They cover partial imports, warning persistence, missing references, binary files, executable modes, copies, pinned versions, cancellation, company isolation, and batched Git reads. - 110 import, skill-detail, selection-tree, saved-file link, and Markdown renderer tests passed. A file-switch regression failed before the resolver fix and passed afterward. Browser walkthroughs cover the all-selected open tree, repository preview, non-blocking warnings, missing references, setup problems, warning persistence, and mobile layout. - Full workspace typecheck and build passed. Runner E2E TypeScript checks and design-token gates passed. The full serial local suite was attempted and stopped after over an hour. The existing 40,000-file Git streaming stress test failed after 303 seconds on macOS; the broad local suite is not counted as passed. All 55 applicable PR checks passed on the final commit, including the full sharded CI suite. Two optional Storybook workflows were skipped; the five local Storybook walkthroughs passed. - On October 12, live campaigns imported the private Poteto repository through the production GitHub Sources UI, selected architect and bro, and invoked them with native Codex on local and Daytona. The source connection was disabled before invocation. Independent filesystem inspections matched every supported Git blob, size, and executable mode. Both tasks completed and cleanup passed. Campaigns: `local-2026-10-12T15-07-39-504Z` (both environments), `local-2026-10-12T16-08-39-682Z` (local), and `local-2026-10-12T16-03-33-938Z` (Daytona). Each of the two selected skills received all 234 supported repository files. Later changes only affect the installed-file viewer and documentation. This qualifies skill delivery and instruction reads, not every Poteto workflow or adapter. - A manual source-checkout test drive imported a synthetic private GitHub repository with a symlink, an oversized file, a missing reference, and malformed skill metadata. Available skills published with their shared checklist. The walkthrough found duplicate warning text after import; the final UI fix removes that duplicate. The file viewer exposes saved repository dependencies and resolves authored relative links without changing the instructions. A follow-up live refresh omitted unsafe helper files with warnings, preserved every safe file byte, and survived a server restart. Screenshots below use the production UI with Storybook fixtures. They do not replace the live GitHub and runtime checks. <details> <summary>All skills visible and selected by default</summary>  </details> <details> <summary>Import stays available with warnings</summary>  </details> <details> <summary>Repository file inspector</summary>  </details> <details> <summary>Mobile import</summary>  </details> ## Risks - Each selected skill carries a repository copy in the runtime. The database stores each snapshot once. Runtime transfer and storage increase with the number of assigned skills. - Runtime budgets remain: 9,990 repository entries, 1 MiB per file, and 61 MiB total. File omissions are recorded as warnings. Source-access or download failures retain installed versions. - Import success does not prove that every skill can run. Environment dependencies, credentials, delegation tools, and schedules still need configuration. Imported setup scripts are not executed. - Live runtime coverage is native Codex on local and Daytona. Other adapters use the shared delivery path but were not exercised in these campaigns. The roadmap marks Skills Manager as shipped. This extends the existing importer. Related pull requests were checked. ## Model Used OpenAI Codex, based on GPT-6, with repository inspection, code execution, automated tests, and browser tools. The exact deployment identifier and context-window size were 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 - [ ] 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 mergecanary/v2026.1012.0-canary.8 |
||
|
|
123a188374 |
fix: separate Codex login and ARM host qualification
Keep daemon ABI admission separate from CLI login and preserve restricted Docker installation checks before native host startup. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
695506ad39 |
perf: cache native builds and verify Linux runtime targets
Preserve actual target selection, record the GNU libc baseline, and retain primary installed-startup failures for ARM qualification. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
ce08872dfb |
refactor(heartbeat): extract instruction working-copy lifecycle (#15984)
## Thinking Path > - Paperclip runs agent tasks and preserves their managed agent files. > - Heartbeat must prepare a private copy, collect stopped-provider edits, and retain ownership during warm-session handoff. > - That lifecycle is spread across preparation, adapter callbacks, and cleanup. > - A per-run controller can own the copy and receipt while the executor retains teardown ordering. > - This PR moves that coordination into a dedicated module. > - Live getters preserve updated state and partially acquired resources. ## Linked Issues or Issue Description **What existing behavior does this improve?** Maintenance of heartbeat instruction preparation. This is the second and final PR in this batch, originally stacked on #15980. That dependency is now merged; this PR is rebased onto its squash merge with an identical patch and identical touched-file contents. Related-PR search found no duplicate extraction. **Current behavior** After #15980, `heartbeat.ts` has 4,215 lines and 173,657 bytes. It coordinates instruction-copy preparation, save receipts, warm handoffs, and deferred cleanup inline. **Proposed behavior** `heartbeat/instruction-working-copy.ts` owns the per-run lifecycle in 233 lines. `heartbeat.ts` becomes 4,055 lines and 162,520 bytes. The executor retains the outer release order, unavailable-copy reporting, and environment/service cleanup policy. **Reason and benefit** The copy, save receipt, and warm ownership are readable together. The remaining executor names preparation and dispatch phases without obscuring teardown decisions. **Breaking changes** None intended. All 140 named public heartbeat exports remain unchanged. ## What Changed - Extract copy preparation, save/checkpoint callbacks, warm reservation/adoption, prompt guidance, and the deferred-release closure. - Read the executor's current run row through a callback; expose current copies, receipts, and acquired cleanup handles through live getters. - Keep cleanup handles available after preparation failure, and preserve release-before-retry on invalidated warm reuse. - Add four public-path characterization tests with real disposable PostgreSQL and files, plus four direct boundary tests. - Add isolated browser acceptance with a real process that edits instructions, completes its task, and reads the saved bytes on its next task. - Document the boundary and opt-in acceptance command. ## Verification - **Before extraction:** four new public-path tests pass on the original implementation, as do 108 existing instruction-copy/directory/native-cleanup tests. The two-task browser journey also passes on the baseline server. - **After extraction:** all 112 baseline tests pass; all four new boundary tests pass; 12 selected native-session ownership/retirement cases pass (the other 670 cases were outside this focused selection). - **Browser acceptance:** the fresh extracted-code server passes the full two-task journey (25.9 seconds): real child-process edits, saved/unchanged receipts, canonical bytes through the agent-file API, next-task restore, completed task UI, and copy cleanup. - `pnpm -r typecheck`, final server typecheck, and `pnpm build` pass. Module-boundary and public-export checks pass. - Normalized syntax comparison confirms all moved bodies and the reconstructed executor match the base, accounting explicitly for live run getters and delegation. - Final rebased head: `a08872c97e587a21ffc0fc6b78f34b81e484e7b0`. Combined entry-point and boundary regressions pass again (12/12); fresh Greptile review is 5/5 with no findings. All 55 current-head checks pass (two configured skips), including the hosted full-suite tests, build, typecheck, and all eight browser shards. There are no open review threads. ## Risks - Acquisition can succeed before preparation throws. Boundary tests verify that both the reservation and a transferred copy remain visible to the cleanup owner. - Callbacks can replace copy/save state during execution. Public tests verify saved receipts; direct tests verify the current run row, warm checkpoint receipt, and permission-root preservation. - Missing edit authorization and cleanup failure must remain nonfatal. Characterization tests revoke actual membership after dispatch admission and inject a cleanup error while preserving the saved result. - The browser uses a test-launcher-only instruction-capable wrapper around the real process adapter. Production adapter capabilities are unchanged. No live provider calls are made; native warm ownership is covered by focused module and native-session tests rather than a live provider browser run. ## Model Used OpenAI Codex, based on GPT-6, assisted with reasoning, code edits, tool execution, and verification. The exact deployment model ID and context-window size 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> |
||
|
|
5f0b898e9e |
merge: reconcile latest Codex runner target qualification
Preserve the user-approved Codex Linux ARM64 default and keep Claude automatic selection limited to Apple Silicon. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
6fd56c445d |
feat: default Claude to the native runner on Apple Silicon
Carry Claude effort through versioned native admission and recovery. Preserve existing connections and saved runner choices, and price Opus 5.5 API receipts. Co-Authored-By: Paperclip <noreply@paperclip.ing> |