diff --git a/doc/plans/2026-10-03-cursor-production-readiness.md b/doc/plans/2026-10-03-cursor-production-readiness.md index 2009f936a61..1d8fd194b25 100644 --- a/doc/plans/2026-10-03-cursor-production-readiness.md +++ b/doc/plans/2026-10-03-cursor-production-readiness.md @@ -162,10 +162,19 @@ Runner contract/replay checks, 164 focused Runner tests, executor/profile/runtim tests, 56 plan-wait tests, fixture typecheck and 9 UI option tests. The new plan-wait case preserves valid v11 waits saved with pre-promotion admission metadata; incompatible profile identities remain fenced. Original failed test attempts are -retained separately from their affected successful repeats. The full default local -test command and final GitHub checks are required before handoff; the PR's live -checks show the final-head CI state. Historical verification below retains its -original source and outcomes. +retained separately from their affected successful repeats. The latest default +local command passed all general groups and 107 serialized route suites, then +failed on a socket hang up in `issue-thread-interaction-routes.test.ts`. The +isolated affected repeat and all remaining 43 suites passed with unchanged source, +completing all 150 serialized suites. The failed command remains failed. No +unrelated route repair was made. Final recursive typecheck passed again. Repeated +assembly exposed a read-only manifest overwrite failure; assembly now replaces +that manifest atomically, and the server copy can replace an existing read-only +inode. Two isolated assemblies preserved all three packaged daemon hashes and the +exact Linux manifest SHA-256/mode. The affected full build and its unchanged +repeat passed. The PR's live +checks show final-head CI; green checks are required before handoff. Historical +verification below retains its original source and outcomes. The user reconfirmed all remaining work on 2026-10-04 within the original $100 total ceiling. Prior committed upper bounds total $47.080380624; the remaining envelope diff --git a/packages/paperclip-runner/scripts/stage-release-runner-binaries.mjs b/packages/paperclip-runner/scripts/stage-release-runner-binaries.mjs index 5a43989db60..6bf1e8a396a 100644 --- a/packages/paperclip-runner/scripts/stage-release-runner-binaries.mjs +++ b/packages/paperclip-runner/scripts/stage-release-runner-binaries.mjs @@ -3,7 +3,7 @@ // Manifest: {sourceRevision, platforms: {"darwin-arm64": {path, sha256}, ...}}. import { createHash } from "node:crypto"; import { execFileSync } from "node:child_process"; -import { chmodSync, copyFileSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; +import { chmodSync, copyFileSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs"; import { dirname, isAbsolute, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { runnerBinaryTarget } from "../src/live/runner-binary.ts"; @@ -44,7 +44,14 @@ for (const artifact of verified) { if (remoteProviderPack) { const destination = join(root, "dist", "remote-provider-packs", "linux-x64", "provider-pack.json"); mkdirSync(dirname(destination), { recursive: true }); - writeFileSync(destination, remoteProviderPack.bytes, { mode: 0o444 }); + // Replace the inode so repeat assembly can preserve a read-only manifest. + const staged = `${destination}.staging-${process.pid}`; + try { + writeFileSync(staged, remoteProviderPack.bytes, { mode: 0o444, flag: "wx" }); + renameSync(staged, destination); + } finally { + rmSync(staged, { force: true }); + } } writeFileSync(join(root, "dist", "bin", "release-manifest.json"), JSON.stringify({schema:"paperclip.runner.release-binaries.v1",sourceRevision:manifest.sourceRevision,platforms, ...(remoteProviderPack ? { remoteProviderPack: { target: "linux-x64", digest: remoteProviderPack.identity.digest, sourceRevision: remoteProviderPack.identity.payload.runnerSourceRevision } } : {})},null,2)+"\n"); diff --git a/server/package.json b/server/package.json index d9e6badbf23..405df9ccb62 100644 --- a/server/package.json +++ b/server/package.json @@ -35,7 +35,7 @@ "dev": "tsx src/index.ts", "dev:watch": "cross-env PAPERCLIP_MIGRATION_PROMPT=never PAPERCLIP_MIGRATION_AUTO_APPLY=true tsx ./scripts/dev-watch.ts", "prepare:ui-dist": "bash ../scripts/prepare-server-ui-dist.sh", - "build": "pnpm run prepare:runner-vendor && node scripts/verify-runner-vendor-dependencies.mjs && tsc && mkdir -p dist/onboarding-assets dist/built-ins dist/services/scripts dist/vendor/paperclip-runner && cp -R src/onboarding-assets/. dist/onboarding-assets/ && cp -R src/built-ins/. dist/built-ins/ && cp -R src/services/scripts/. dist/services/scripts/ && cp -R ../packages/paperclip-runner/dist/. dist/vendor/paperclip-runner/ && node scripts/write-build-stamp.mjs", + "build": "pnpm run prepare:runner-vendor && node scripts/verify-runner-vendor-dependencies.mjs && tsc && mkdir -p dist/onboarding-assets dist/built-ins dist/services/scripts dist/vendor/paperclip-runner && cp -R src/onboarding-assets/. dist/onboarding-assets/ && cp -R src/built-ins/. dist/built-ins/ && cp -R src/services/scripts/. dist/services/scripts/ && cp -Rf ../packages/paperclip-runner/dist/. dist/vendor/paperclip-runner/ && node scripts/write-build-stamp.mjs", "prepack": "pnpm run prepare:ui-dist && pnpm run build", "postpack": "rm -rf ui-dist", "clean": "rm -rf dist",