Reconcile Claude behavior with current native execution fixes

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-15 14:12:20 -05:00
commit f006b3112b
154 files changed
+8949 -1197

No files matched your search

+139
View File
@@ -0,0 +1,139 @@
name: CI work benchmark
on:
pull_request:
types: [opened, synchronize, reopened, labeled]
paths:
- .github/actions/setup-ci-dependencies/**
- .github/workflows/ci-work-benchmark.yml
- scripts/ci-dependency-cache.mjs
- scripts/benchmark-ci-work.mjs
- scripts/run-vitest-stable.mjs
- server/src/__tests__/setup-supertest.ts
- server/src/__tests__/workspace-runtime.test.ts
- server/src/services/workspace-git-snapshot-streaming.test.ts
permissions:
contents: read
concurrency:
group: ci-work-benchmark-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
paired:
if: >-
contains(github.event.pull_request.labels.*.name, 'profile-ci') &&
(github.event.action != 'labeled' || github.event.label.name == 'profile-ci')
runs-on: ubuntu-latest
timeout-minutes: 25
defaults:
run:
working-directory: candidate
steps:
- name: Checkout candidate
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
ref: ${{ github.sha }}
path: candidate
fetch-depth: 2
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
with:
node-version: 24
package-manager-cache: false
- name: Setup pnpm
uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86
with:
version: 9.15.4
run_install: false
- name: Start cold setup measurement
run: echo "CI_COLD_STARTED=$(date +%s)" >> "$GITHUB_ENV"
- name: Qualify candidate dependency setup
uses: ./candidate/.github/actions/setup-ci-dependencies
with:
working-directory: candidate
restore-cache: 'false'
- name: Record cold setup and compute qualification keys
id: qualification
run: |
echo "CI_COLD_SECONDS=$(($(date +%s) - CI_COLD_STARTED))" >> "$GITHUB_ENV"
node scripts/ci-dependency-cache.mjs
- name: Save PR-scoped qualification dependencies
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
key: ${{ steps.qualification.outputs.dependency-key }}
path: ${{ steps.qualification.outputs.dependency-paths }}
- name: Save PR-scoped qualification builds
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
key: ${{ steps.qualification.outputs.build-key }}
path: ${{ steps.qualification.outputs.build-paths }}
- name: Remove materialized outputs before restore
run: |
node --input-type=module <<'NODE'
import { execFileSync } from 'node:child_process';
import { rmSync } from 'node:fs';
const plan = JSON.parse(execFileSync(process.execPath, ['scripts/ci-dependency-cache.mjs'], {
env: { ...process.env, GITHUB_OUTPUT: '' }, encoding: 'utf8',
}));
for (const directory of [...plan.dependencyPaths, 'packages/shared/dist', 'packages/plugins/sdk/dist']) {
rmSync(directory, { recursive: true, force: true });
}
NODE
echo "CI_WARM_STARTED=$(date +%s)" >> "$GITHUB_ENV"
- name: Qualify a real warm restore
id: warm
uses: ./candidate/.github/actions/setup-ci-dependencies
with:
working-directory: candidate
- name: Verify exact cache hits and record setup comparison
env:
DEPS_RESTORED: ${{ steps.warm.outputs.dependencies-restored }}
BUILDS_RESTORED: ${{ steps.warm.outputs.builds-restored }}
OUTPUT: ${{ runner.temp }}/ci-work-benchmark
run: |
test "$DEPS_RESTORED" = true
test "$BUILDS_RESTORED" = true
mkdir -p "$OUTPUT"
warm_seconds=$(($(date +%s) - CI_WARM_STARTED))
printf '{"coldSeconds":%s,"warmSeconds":%s}\n' "$CI_COLD_SECONDS" "$warm_seconds" > "$OUTPUT/dependency-setup.json"
echo "Dependency setup: ${CI_COLD_SECONDS}s cold, ${warm_seconds}s with exact materialized restores." >> "$GITHUB_STEP_SUMMARY"
- name: Prepare unchanged baseline
run: |
base_sha=$(git rev-parse HEAD^1)
git worktree add --detach ../baseline "$base_sha"
cd ../baseline
if ! pnpm install --frozen-lockfile; then
pnpm install --resolution-only --ignore-scripts --no-frozen-lockfile
pnpm install --frozen-lockfile
fi
pnpm run preflight:workspace-links
pnpm --filter @paperclipai/plugin-sdk ensure-build-deps
- name: Compare complete commands and executed case inventories
env:
BENCHMARK_OUTPUT: ${{ runner.temp }}/ci-work-benchmark
run: |
node scripts/benchmark-ci-work.mjs ../baseline "$BENCHMARK_OUTPUT"
cat "$BENCHMARK_OUTPUT/summary.md" >> "$GITHUB_STEP_SUMMARY"
- name: Retain timings, inventories and failure logs
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: ci-work-benchmark
path: ${{ runner.temp }}/ci-work-benchmark
retention-days: 14
+60 -20
View File
@@ -186,13 +186,19 @@ jobs:
# Share the checked-in lockfile key with master. PR merge refs must not
# save full copies of the store or evict the post-merge build caches.
- name: Restore materialized dependencies and shared builds
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') != ''
uses: ./.github/actions/setup-ci-dependencies
- name: Locate pnpm store
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
id: pnpm_store
run: |
echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
echo "arch=$(node -p 'process.arch')" >> "$GITHUB_OUTPUT"
- name: Restore pnpm store (read only)
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.pnpm_store.outputs.path }}
@@ -200,6 +206,7 @@ jobs:
restore-keys: node-cache-${{ runner.os }}-${{ steps.pnpm_store.outputs.arch }}-pnpm-
- name: Install dependencies
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
# Manifest-changing and stacked PRs can hold a pnpm-lock.yaml that is
# stale for the merge tree. Resolve it inline instead of waiting on a
# policy-job artifact: that dependency put the policy job's queue and
@@ -347,26 +354,9 @@ jobs:
fail-fast: false
matrix:
include:
# The server suite is pinned to maxWorkers=1 (server/vitest.config.ts),
# so it can only be parallelized across runners. Shard it to keep this
# lane off the PR critical path. The suite has grown to ~3184s of
# serial vitest wall time (mean of runs 35036001734 and 35024948947,
# 2026-09-15): at five plain general-server shards with stale
# recorded durations the worst shard ran 806s of tests while the
# best ran 417s. This now uses the same shape as release-verify.yml:
# the ~429s chat integration suite splits by collected test location
# across three dedicated runners (~143s each), and the remaining
# ~2755s levels across twelve duration-balanced shards at ~230s
# each, in line with the other ~200-290s lanes.
#
# The balance only holds while the manifest is fresh. By 2026-10-10
# the without-chat group had grown to 871 suites and ~5031s of serial
# vitest time (mean of runs 38076844891 and 38076972444), 230 of
# them unrecorded and weighted at the median, so the twelve shards
# ran 313-554s of tests (server 2/12 at 618s was the slowest check
# in the run). Re-recorded durations level them to ~415s each; the
# shard count stays at twelve because Build and workspaces-b sit
# above that already.
# Keep twelve duration-balanced server shards. Each shard overlaps
# at most two isolated fork workers; cases within a file stay serial.
# The chat fixture keeps three independent database-backed shards.
- group: general-server-without-chat
group_label: server (1/12)
shard_index: 0
@@ -484,13 +474,19 @@ jobs:
# Share the checked-in lockfile key with master. PR merge refs must not
# save full copies of the store or evict the post-merge build caches.
- name: Restore materialized dependencies and shared builds
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') != ''
uses: ./.github/actions/setup-ci-dependencies
- name: Locate pnpm store
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
id: pnpm_store
run: |
echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
echo "arch=$(node -p 'process.arch')" >> "$GITHUB_OUTPUT"
- name: Restore pnpm store (read only)
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.pnpm_store.outputs.path }}
@@ -498,6 +494,7 @@ jobs:
restore-keys: node-cache-${{ runner.os }}-${{ steps.pnpm_store.outputs.arch }}-pnpm-
- name: Install dependencies
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
# Manifest-changing and stacked PRs can hold a pnpm-lock.yaml that is
# stale for the merge tree. Resolve it inline instead of waiting on a
# policy-job artifact: that dependency put the policy job's queue and
@@ -558,6 +555,14 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4
- name: Set up Docker Compose
uses: docker/setup-compose-action@54042514f505b273907334ae2b9cdbb9a0213c1a # v2
with:
version: v5.5.1
- name: Verify Compose signing secret forwarding
run: node --test scripts/docker-compose-secrets.test.mjs
# Same .dockerignore semantics as the real image builds: a
# context-slimming change that strips a committed build input must
# fail here, on the pull request, instead of failing every
@@ -684,13 +689,19 @@ jobs:
# Share the checked-in lockfile key with master. PR merge refs must not
# save full copies of the store or evict the post-merge build caches.
- name: Restore materialized dependencies and shared builds
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') != ''
uses: ./.github/actions/setup-ci-dependencies
- name: Locate pnpm store
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
id: pnpm_store
run: |
echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
echo "arch=$(node -p 'process.arch')" >> "$GITHUB_OUTPUT"
- name: Restore pnpm store (read only)
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.pnpm_store.outputs.path }}
@@ -698,6 +709,7 @@ jobs:
restore-keys: node-cache-${{ runner.os }}-${{ steps.pnpm_store.outputs.arch }}-pnpm-
- name: Install dependencies
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
# Manifest-changing and stacked PRs can hold a pnpm-lock.yaml that is
# stale for the merge tree. Resolve it inline instead of waiting on a
# policy-job artifact: that dependency put the policy job's queue and
@@ -885,13 +897,19 @@ jobs:
# Share the checked-in lockfile key with master. PR merge refs must not
# save full copies of the store or evict the post-merge build caches.
- name: Restore materialized dependencies and shared builds
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') != ''
uses: ./.github/actions/setup-ci-dependencies
- name: Locate pnpm store
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
id: pnpm_store
run: |
echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
echo "arch=$(node -p 'process.arch')" >> "$GITHUB_OUTPUT"
- name: Restore pnpm store (read only)
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.pnpm_store.outputs.path }}
@@ -899,6 +917,7 @@ jobs:
restore-keys: node-cache-${{ runner.os }}-${{ steps.pnpm_store.outputs.arch }}-pnpm-
- name: Install dependencies
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
# Manifest-changing and stacked PRs can hold a pnpm-lock.yaml that is
# stale for the merge tree. Resolve it inline instead of waiting on a
# policy-job artifact: that dependency put the policy job's queue and
@@ -1160,13 +1179,19 @@ jobs:
# Share the checked-in lockfile key with master. PR merge refs must not
# save full copies of the store or evict the post-merge build caches.
- name: Restore materialized dependencies and shared builds
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') != ''
uses: ./.github/actions/setup-ci-dependencies
- name: Locate pnpm store
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
id: pnpm_store
run: |
echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
echo "arch=$(node -p 'process.arch')" >> "$GITHUB_OUTPUT"
- name: Restore pnpm store (read only)
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.pnpm_store.outputs.path }}
@@ -1174,6 +1199,7 @@ jobs:
restore-keys: node-cache-${{ runner.os }}-${{ steps.pnpm_store.outputs.arch }}-pnpm-
- name: Install dependencies
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
# Manifest-changing and stacked PRs can hold a pnpm-lock.yaml that is
# stale for the merge tree. Resolve it inline instead of waiting on a
# policy-job artifact: that dependency put the policy job's queue and
@@ -1239,13 +1265,19 @@ jobs:
# Share the checked-in lockfile key with master. PR merge refs must not
# save full copies of the store or evict the post-merge build caches.
- name: Restore materialized dependencies and shared builds
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') != ''
uses: ./.github/actions/setup-ci-dependencies
- name: Locate pnpm store
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
id: pnpm_store
run: |
echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
echo "arch=$(node -p 'process.arch')" >> "$GITHUB_OUTPUT"
- name: Restore pnpm store (read only)
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.pnpm_store.outputs.path }}
@@ -1253,6 +1285,7 @@ jobs:
restore-keys: node-cache-${{ runner.os }}-${{ steps.pnpm_store.outputs.arch }}-pnpm-
- name: Install dependencies
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
# Manifest-changing and stacked PRs can hold a pnpm-lock.yaml that is
# stale for the merge tree. Resolve it inline instead of waiting on a
# policy-job artifact: that dependency put the policy job's queue and
@@ -1486,13 +1519,19 @@ jobs:
# Share the checked-in lockfile key with master. PR merge refs must not
# save full copies of the store or evict the post-merge build caches.
- name: Restore materialized dependencies and shared builds
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') != ''
uses: ./.github/actions/setup-ci-dependencies
- name: Locate pnpm store
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
id: pnpm_store
run: |
echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
echo "arch=$(node -p 'process.arch')" >> "$GITHUB_OUTPUT"
- name: Restore pnpm store (read only)
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.pnpm_store.outputs.path }}
@@ -1500,6 +1539,7 @@ jobs:
restore-keys: node-cache-${{ runner.os }}-${{ steps.pnpm_store.outputs.arch }}-pnpm-
- name: Install dependencies
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
# Manifest-changing and stacked PRs can hold a pnpm-lock.yaml that is
# stale for the merge tree. Resolve it inline instead of waiting on a
# policy-job artifact: that dependency put the policy job's queue and
+8 -1
View File
@@ -52,7 +52,7 @@ jobs:
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: 24
cache: pnpm
package-manager-cache: false
# rust-cache hashes its absolute cache paths into the entry's version,
# and GitHub only serves an entry whose key and version both match. The
@@ -102,7 +102,14 @@ jobs:
- name: Validate release package manifest
run: node ./scripts/release-package-map.mjs check
- name: Restore materialized dependencies and shared builds
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') != ''
uses: ./.github/actions/setup-ci-dependencies
with:
save-cache: ${{ github.repository == 'paperclipai/paperclip' && github.event_name == 'push' && github.ref == 'refs/heads/master' && inputs.ref == github.sha }}
- name: Install dependencies
if: hashFiles('.github/actions/setup-ci-dependencies/action.yml') == ''
run: pnpm install --no-frozen-lockfile
- name: Typecheck