mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-04 19:28:46 +01:00
Reconcile Claude platform packages with merged Codex defaults
Co-Authored-By: Paperclip <noreply@paperclip.ing> * codex/claude-runner-default: (85 commits) feat: default new Codex agents to Paperclip Runner on Linux and macOS (#15683) docs(skills): add slow-query diagnosis and fix skill (#16303) feat(sentry): add opt-in run failure reporting with saved run references (#16300) refactor(server): isolate provider message admission and runtime policies (#16289) refactor(server): isolate provider webhook lifecycle decisions (#16283) fix(workspaces): keep cleanup Git scans fresh and dedupe page reads (#16302) fix(sentry): keep provider-rejected Grok wakes out of run failure reports (#16297) fix(runner): report Runner disconnect age when a Dot bridge exits (#16296) refactor(server): isolate chat conversation and control policies (#16276) perf(recovery): use indexed execution identity lookups (#16291) perf(runs): bound history and reduce repeated context reads (#16286) fix(native-runtime): report which close barrier failed (#16298) feat(skills): select and validate tracked GitHub branches (#16288) fix(observability): sample native runs independently of triggers (#16285) fix(github): retry and recover review publication (#16284) perf(workspaces): wake terminal cleanup from committed changes (#16282) fix(mcp): deduplicate discovered tool descriptors (#16281) perf: remove history scans from task and chat queries (#16278) docs(skills): add maintenance bot setup workflow (#16279) fix(observability): time execution configuration steps (#16236) ... # Conflicts: # scripts/verify-grok-npm-install.mjs
This commit is contained in:
commit
b030683ca2
1176 files changed
+129461
-261897
No files matched your search
@@ -9,6 +9,7 @@ import { fileURLToPath } from 'node:url';
|
||||
import { isWorkspacePackage, parseWorkspaceEntries } from '../build-standalone-public-packages.mjs';
|
||||
import { GROK_PUBLIC_INSTALL_IMAGE, GROK_PUBLIC_INSTALL_LIFECYCLE, assertInstalledCodexPlatformProvenance, assertInstalledNativeConsumerContinuity, assertNoBundledCodexPayloads, grokConsumerDockerArgs, installedClaudeProbeSource, installedCodexProbeSource, installedDaemonProbeSource, macNodeHeadersDirectory, macPublicInstallLifecycleProfile, macInstalledStartupProbeSource, runMacInitialInstallWithDiagnostics } from '../grok-public-install-sandbox.mjs';
|
||||
import { verifyPiPackagedDaemon } from '../pi-public-install-probe.mjs';
|
||||
import { publicInstallClosure } from '../public-install-closure.mjs';
|
||||
import { runnerBinaryTarget } from '../../packages/paperclip-runner/src/live/runner-binary.ts';
|
||||
|
||||
const paths = { assets: '/private/staging/assets', consumer: '/private/staging/consumer', cache: '/private/staging/cache', uid: 1001, gid: 1001 };
|
||||
@@ -243,7 +244,7 @@ test('the image and Grok downloads start before staging and join without weakeni
|
||||
assert.ok(source.includes("const stagedGrok = join(prefetched, 'grok')"));
|
||||
assert.doesNotMatch(source, /provision-grok\.mjs'\), prerequisite\]/);
|
||||
// Both downloads start before any package is staged and before the first sandbox runs.
|
||||
const staging = position("visit('@paperclipai/server')");
|
||||
const staging = position('publicInstallClosure(repo)');
|
||||
const firstSandbox = position("isolated(['npm', 'install', '--ignore-scripts', '--omit=dev'");
|
||||
assert.ok(imagePull < staging && grokProvision < staging);
|
||||
assert.ok(position("await awaited('image', imageReady)") < firstSandbox);
|
||||
@@ -318,17 +319,8 @@ test('the verifier stages only workspace packages, so it skips the standalone bu
|
||||
const retention = readFileSync(new URL('../retain-runner-qualification-packages.mjs', import.meta.url), 'utf8');
|
||||
assert.ok(retention.includes("const pluginRelative = 'packages/plugins/sandbox-providers/daytona';") && retention.includes("cpSync(join(repo, pluginRelative, 'dist'), join(plugin, 'dist'), { recursive: true })"), 'retention still packs the Daytona plugin from its dist, which is why the gated build exists');
|
||||
const repo = new URL('../../', import.meta.url);
|
||||
const listing = spawnSync(process.execPath, [fileURLToPath(new URL('scripts/release-package-map.mjs', repo)), 'list'], { cwd: fileURLToPath(repo), encoding: 'utf8' });
|
||||
assert.equal(listing.status, 0, listing.stderr);
|
||||
const packages = new Map(listing.stdout.trim().split('\n').map(line => line.split('\t')).map(([dir, name]) => [name, { dir, manifest: JSON.parse(readFileSync(new URL(`${dir}/package.json`, repo), 'utf8')) }]));
|
||||
const needed = new Set();
|
||||
const visit = name => {
|
||||
if (needed.has(name)) return;
|
||||
const entry = packages.get(name); assert.ok(entry, `missing public workspace dependency ${name}`); needed.add(name);
|
||||
for (const [dep, spec] of Object.entries({ ...entry.manifest.dependencies, ...entry.manifest.optionalDependencies })) if (spec.startsWith('workspace:')) visit(dep);
|
||||
};
|
||||
assert.ok(source.includes("visit('@paperclipai/server');\n visit('paperclipai');"));
|
||||
visit('@paperclipai/server'); visit('paperclipai');
|
||||
assert.ok(source.includes('const { packages, needed } = publicInstallClosure(repo);'));
|
||||
const { packages, needed } = publicInstallClosure(fileURLToPath(repo));
|
||||
const workspace = parseWorkspaceEntries(readFileSync(new URL('pnpm-workspace.yaml', repo), 'utf8'));
|
||||
const standalone = [...packages.values()].filter(({ dir }) => !isWorkspacePackage(dir, workspace)).map(({ dir }) => dir);
|
||||
assert.ok(standalone.length > 0, 'the public package map must still carry standalone packages for this check to mean anything');
|
||||
@@ -341,7 +333,7 @@ test('the verifier stages only workspace packages, so it skips the standalone bu
|
||||
assert.deepEqual(JSON.parse(readFileSync(new URL('server/package.json', repo), 'utf8')).files, ['dist', 'ui-dist', 'skills']);
|
||||
assert.ok(source.includes("PAPERCLIP_RELEASE_REUSE_UI_DIST: '1'"));
|
||||
const uiDist = position("run('bash', [join(repo, 'scripts/prepare-server-ui-dist.sh')], repo)");
|
||||
assert.ok(position("visit('paperclipai')") < gate && gate < uiDist && uiDist < position('timing.stage_ui_dist_ms =') && uiDist < position('const stageSource = '));
|
||||
assert.ok(position('publicInstallClosure(repo)') < gate && gate < uiDist && uiDist < position('timing.stage_ui_dist_ms =') && uiDist < position('const stageSource = '));
|
||||
});
|
||||
|
||||
test('the installed Codex probe exercises the public export and rejects incomplete or mismatched packages', () => {
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import test from 'node:test';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { PUBLIC_INSTALL_ROOTS, publicInstallClosure, publicRegistryDependencies } from '../public-install-closure.mjs';
|
||||
|
||||
const repo = fileURLToPath(new URL('../../', import.meta.url));
|
||||
|
||||
test('the closure starts at the server and the CLI and follows only workspace specs', () => {
|
||||
assert.deepEqual(PUBLIC_INSTALL_ROOTS, ['@paperclipai/server', 'paperclipai']);
|
||||
const { packages, needed } = publicInstallClosure(repo);
|
||||
const order = [...needed];
|
||||
assert.equal(order[0], '@paperclipai/server');
|
||||
assert.ok(needed.has('paperclipai'));
|
||||
for (const name of needed) {
|
||||
const { manifest } = packages.get(name);
|
||||
for (const [dep, spec] of Object.entries({ ...manifest.dependencies, ...manifest.optionalDependencies })) {
|
||||
assert.equal(needed.has(dep), spec.startsWith('workspace:'), `${name} -> ${dep}@${spec}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('the warm-up graph is the closure\'s registry dependencies, first spec wins', () => {
|
||||
const pkg = (dependencies, optionalDependencies) => ({ dir: 'x', manifest: { dependencies, optionalDependencies } });
|
||||
const packages = new Map([
|
||||
['a', pkg({ b: 'workspace:*', left: '^1.0.0', shared: '^2.0.0', local: 'file:../local', linked: 'link:../linked' }, { native: '1.2.3' })],
|
||||
['b', pkg({ shared: '^3.0.0', right: '~4.0.0' }, { left: '^9.0.0' })],
|
||||
['unvisited', pkg({ never: '1.0.0' })],
|
||||
]);
|
||||
assert.deepEqual(publicRegistryDependencies({ packages, needed: new Set(['a', 'b']) }), {
|
||||
dependencies: { left: '^1.0.0', shared: '^2.0.0', right: '~4.0.0' },
|
||||
optionalDependencies: { native: '1.2.3' },
|
||||
});
|
||||
const real = publicRegistryDependencies(publicInstallClosure(repo));
|
||||
const names = [...Object.keys(real.dependencies), ...Object.keys(real.optionalDependencies)];
|
||||
assert.ok(names.length > 0);
|
||||
for (const spec of [...Object.values(real.dependencies), ...Object.values(real.optionalDependencies)]) {
|
||||
assert.doesNotMatch(spec, /^(workspace|file|link):/);
|
||||
}
|
||||
});
|
||||
|
||||
test('the warm-up refuses to run without the cache the verifier will read', () => {
|
||||
const env = { ...process.env };
|
||||
delete env.PAPERCLIP_PUBLIC_INSTALL_NPM_CACHE;
|
||||
const result = spawnSync(process.execPath, [fileURLToPath(new URL('../warm-public-install-npm-cache.mjs', import.meta.url))], { env, encoding: 'utf8' });
|
||||
assert.notEqual(result.status, 0);
|
||||
assert.match(result.stderr, /PAPERCLIP_PUBLIC_INSTALL_NPM_CACHE/);
|
||||
});
|
||||
|
||||
test('the Build lane warms the cache before pnpm build and hands the same directory to the verifier', () => {
|
||||
const workflow = readFileSync(new URL('../../.github/workflows/pr-trusted.yml', import.meta.url), 'utf8');
|
||||
const build = workflow.slice(workflow.indexOf('\n build:\n'), workflow.indexOf('\n verify_serialized_server:\n'));
|
||||
const position = fragment => { const index = build.indexOf(fragment); assert.notEqual(index, -1, `Build job must contain ${fragment}`); return index; };
|
||||
const warm = position('PAPERCLIP_PUBLIC_INSTALL_NPM_CACHE="$RUNNER_TEMP/public-install-npm-cache" node scripts/warm-public-install-npm-cache.mjs');
|
||||
assert.ok(position('- name: Install dependencies') < warm && warm < position('- name: Build\n'), 'the warm-up overlaps the Rust restore and pnpm build');
|
||||
assert.ok(build.includes('set +e\n'), 'a failed warm-up still records its status, so the verifier never waits it out');
|
||||
const verify = position('export PAPERCLIP_PUBLIC_INSTALL_NPM_CACHE="$RUNNER_TEMP/public-install-npm-cache"');
|
||||
assert.ok(verify < position('node scripts/verify-grok-npm-install.mjs'));
|
||||
const verifier = readFileSync(new URL('../verify-grok-npm-install.mjs', import.meta.url), 'utf8');
|
||||
assert.ok(verifier.includes("const cache = process.env.PAPERCLIP_PUBLIC_INSTALL_NPM_CACHE ? resolve(process.env.PAPERCLIP_PUBLIC_INSTALL_NPM_CACHE) : join(root, 'cache');"));
|
||||
});
|
||||
@@ -7,6 +7,7 @@ import path from "node:path";
|
||||
import { tmpdir } from "node:os";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import test from "node:test";
|
||||
import { runInNewContext } from "node:vm";
|
||||
import { createServer } from "node:http";
|
||||
import { canaryStartup } from "./canary-startup-fixture.mjs";
|
||||
import { canRetryPublishedTarball404, TARBALL_METADATA_TIMEOUT_MS } from "../../tests/canary-onboarding/start-published-canary.mjs";
|
||||
@@ -307,8 +308,20 @@ test("published canaries are gated by the exact-version onboarding browser smoke
|
||||
);
|
||||
assert.match(
|
||||
releaseWorkflow,
|
||||
/smoke_canary_onboarding:\n\s+needs: publish_canary\n\s+if: needs\.publish_canary\.result == 'success'/,
|
||||
/smoke_canary_onboarding:\n\s+needs: publish_canary\n\s+if: \$\{\{ !cancelled\(\) && needs\.publish_canary\.result == 'success' \}\}/,
|
||||
);
|
||||
const smoke = releaseWorkflow.split(" smoke_canary_onboarding:\n")[1].split(/\n [a-z_]+:\n/)[0];
|
||||
const condition = smoke.match(/^ if: \$\{\{ (.+) \}\}$/m)?.[1];
|
||||
assert.match(condition, /^!cancelled\(\) && needs\.publish_canary\.result == 'success'$/);
|
||||
for (const [result, cancelled, expected] of [
|
||||
["success", false, true], ["failure", false, false],
|
||||
["cancelled", false, false], ["skipped", false, false], ["success", true, false],
|
||||
]) {
|
||||
const needs = { publish_canary: { result }, release_runner_source: { result: "success" },
|
||||
select_nightly: { result: "skipped" }, select_beta: { result: "skipped" }, preflight_stable: { result: "skipped" } };
|
||||
assert.equal(runInNewContext(condition, { cancelled: () => cancelled, needs }), expected,
|
||||
`Canary smoke: publisher=${result}, cancelled=${cancelled}`);
|
||||
}
|
||||
assert.match(
|
||||
releaseWorkflow,
|
||||
/PAPERCLIPAI_VERSION: \$\{\{ needs\.publish_canary\.outputs\.canary_version \}\}/,
|
||||
@@ -772,6 +785,31 @@ test("release daemon production uses exact-source native hosts and no publisher
|
||||
assert.ok(workflow.includes(`${job}:\n if: \${{ !inputs.runner_binaries_only }}`));
|
||||
}
|
||||
const release = readWorkflow("release.yml");
|
||||
const source = release.split(" release_runner_source:\n")[1].split(/\n [a-z_]+:\n/)[0];
|
||||
const binaries = release.split(" release_runner_binaries:\n")[1].split(/\n [a-z_]+:\n/)[0];
|
||||
assert.match(source, /needs: \[verify_canary, select_nightly, select_beta, preflight_stable\]/);
|
||||
assert.match(source, /!cancelled\(\)/);
|
||||
assert.match(binaries, /needs: release_runner_source/);
|
||||
assert.match(binaries, /ref: \$\{\{ needs\.release_runner_source\.outputs\.sha \}\}/);
|
||||
assert.match(binaries, /runner_binaries_only: true/);
|
||||
const condition = binaries.match(/^ if: (.+)$/m)?.[1].replace(/^\$\{\{\s*|\s*\}\}$/g, "");
|
||||
assert.match(condition, /^!cancelled\(\) && needs\.release_runner_source\.result == 'success' && needs\.release_runner_source\.outputs\.required == 'true'$/,
|
||||
"Native compilation must bypass deliberately skipped channel ancestors and require successful exact-source selection");
|
||||
const laneJobs = ["verify_canary", "select_nightly", "select_beta", "preflight_stable"];
|
||||
for (const activeLane of laneJobs) {
|
||||
for (const [result, required, cancelled, expected] of [
|
||||
["success", "true", false, true], ["failure", "true", false, false],
|
||||
["cancelled", "true", false, false], ["skipped", "true", false, false],
|
||||
["success", "false", false, false], ["success", undefined, false, false],
|
||||
["success", "true", true, false],
|
||||
]) {
|
||||
const needs = Object.fromEntries(laneJobs.map(job => [job, { result: job === activeLane ? "success" : "skipped" }]));
|
||||
needs.release_runner_source = { result, outputs: { required } };
|
||||
assert.equal(Object.values(needs).filter(job => job.result === "skipped").length, result === "skipped" ? 4 : 3);
|
||||
assert.equal(runInNewContext(condition, { cancelled: () => cancelled, needs }), expected,
|
||||
`${activeLane}: source=${result}, required=${required}, cancelled=${cancelled}`);
|
||||
}
|
||||
}
|
||||
for (const job of ["publish_canary", "publish_nightly", "publish_beta", "preview_stable", "publish_stable"]) {
|
||||
const block = release.split(` ${job}:\n`)[1].split(/\n [a-z_]+:\n/)[0];
|
||||
assert.match(block, /needs: .*release_runner_binaries/);
|
||||
|
||||
Reference in new issue
Block a user