Merge master into native backup expiration

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-30 16:26:42 -05:00
commit 882ece69cd
126 files changed
+5887 -1286

No files matched your search

+82 -21
View File
@@ -146,19 +146,19 @@ New workflow versions merged into master then receive runner access without a
separate SHA allowlist update. Dependabot leaves this first-party reference on
master.
Runner selection calls `ci-routing.yml@master` on the dedicated
`paperclip-ci-routing-x64` AWS Fleet. The `paperclip-ci-routing` runner group
admits only `paperclipai/paperclip/.github/workflows/ci-routing.yml@refs/heads/master`
and repository ID `1170821064`. GitHub evaluates the canonical repository, author, and sender checks before
allocating reserved capacity. The validated admission snapshot (`AWS_CI_ROUTING_USER_IDS_SOURCE` and
`AWS_CI_ROUTING_USER_IDS`) must match `AWS_CI_TRUSTED_USER_IDS`. Refresh it through
the runner-group configuration helper when the roster changes. Missing, stale,
or malformed settings keep hosted routing available without evaluating JSON
in the job's placement expression. Unapproved PRs use hosted metadata routing;
approved manual canaries on master can use the reserved pool. The routing
workflow reads GitHub metadata without checking out or executing PR code. Its author, sender, rerun actor,
repository, head, and merge validation still decide whether tests can use AWS.
Unapproved test workloads continue to use GitHub-hosted runners.
Runner selection calls `ci-routing.yml@master` on a GitHub-hosted runner. It
verifies authorization before allocating any AWS capacity and never checks out
or executes PR code. The author, event sender and rerun actor must each be both
in `AWS_CI_TRUSTED_USER_IDS` and a current owner of `.github/**` in CODEOWNERS.
The resolver and CODEOWNERS are read from the same protected master revision;
PR edits cannot change the trusted owner list. Documentation-only owners,
unsupported owner rules and failed identity lookups do not authorize AWS.
Repository, head and merge validation also apply. Missing or malformed settings
and unverifiable authorization use GitHub-hosted runners. A maintainer rerunning
an outside contributor's PR does not grant it AWS access.
Authorized test jobs and the final `verify` and `e2e` aggregates use the selected
AWS fleet. The metadata authorization job remains hosted even for maintainers,
so stale admission snapshots cannot allocate an AWS runner before verification.
The routing workflow also selects the CI scope. Middle PRs in a stack and PRs
whose diff changes only release notes (`releases/v*.md` or
@@ -213,7 +213,11 @@ coverage without paying for another graph traversal. Filesystem, subprocess, net
dynamic-loader, unresolved, and unapproved external-package consumers are
retained conservatively, including indirect consumers through local helpers.
The selector explicitly tracks setup/configuration dependencies as well as test
imports. The small pure-dependency allowlist lives in
imports. Ordinary source names such as `session-config-metadata.test.ts` or
`setup-state.ts` remain eligible; the words `config` and `setup` alone do not
force full CI. Conventional Vite/Vitest config and setup files remain broad
inputs. Other resolved setup/config dependencies invalidate their entire project.
The small pure-dependency allowlist lives in
`scripts/ci/vitest-selection-graph.mjs`; new external packages remain opaque
until reviewed. This is deliberately broader than `vitest related` alone.
For conservative retention, explicit complete local mock factories cut the
@@ -236,6 +240,9 @@ existing selection/execution rules. The job summary reports files and jobs
selected per lane, and the `vitest-selection` artifact records the manifest and
dependency audit. Selected jobs execute exact Vitest test specifications, so
similarly named `.test.ts` and `.test.tsx` files cannot overlap between shards.
The wrapper consumes and validates the selection before launching Vitest, then
removes selection environment variables from the test process. Nested runner
fixtures therefore use their own checkout and test inventory.
Missing/deleted/renamed source files, non-exempt non-source inputs, unrecognized graph inputs,
setup/config changes, failed dependency installs, graph errors and timeouts use
@@ -288,13 +295,10 @@ explicit. When changing shard layout, update `.github/ci-task-matrix.json` and
the full fallback matrices in `pr-trusted.yml`; the contract tests require them
to agree. Add new cache-affecting environment settings to `globalEnv`.
The routing Fleet has two warm On-Demand runners and a four-runner ceiling.
Test fleets cannot consume its runner slots. Hosted test queues therefore do
not block AWS runner selection. A manual dispatch of `ci-routing.yml` on master
checks placement without launching the test matrix; its non-PR event returns
the hosted test-runner output. Configure and verify the group and Fleet before
merging this caller. To roll back, restore the hosted gate and retain the routing
workflow authorization until assigned jobs finish.
The former reserved routing Fleet is no longer selected by this workflow.
Keep its existing authorization until older assigned jobs finish. A manual
dispatch of `ci-routing.yml` on master exercises the hosted metadata job without
launching the test matrix; its non-PR event returns the hosted test-runner output.
Keep the `.github/**` rule in `.github/CODEOWNERS` and the active master ruleset's
code-owner review requirement enabled. This covers the caller, the trusted
@@ -1507,6 +1511,45 @@ Configure storage provider/settings:
pnpm paperclipai configure --section storage
```
### Managed cloud prerequisites
A nonblank Cloud tenant token or the presence of `PAPERCLIP_MANAGED_CONFIG`
selects the managed-cloud profile. A supplied blank or invalid managed feature
document refuses startup. Without either signal, the instance remains self-hosted.
The managed profile also requires:
- `PAPERCLIP_STORAGE_PROVIDER=s3` or `storage.provider: "s3"` in the canonical
database snapshot. An invalid explicit environment value refuses startup even
if the snapshot selects S3.
- An explicit nonblank `PAPERCLIP_STORAGE_S3_BUCKET` or `storage.s3.bucket`.
The self-hosted `paperclip` bucket default does not qualify. The region defaults
to `us-east-1`; an explicit blank region refuses startup. An optional endpoint
must be an HTTP(S) URL without embedded credentials.
- An external PostgreSQL URL from the environment `DATABASE_URL`.
The managed profile never falls back to embedded PostgreSQL.
- A stable `PAPERCLIP_SECRETS_MASTER_KEY` supplied by the deployment secret store.
Use the same value across replacements. The existing provider accepts 32-byte
base64, 64-character hex, or a raw 32-byte UTF-8 string. A key file alone does
not qualify because a replacement web server may not have that file.
Bootstrap validates the environment database URL and encryption master key before
opening the database or creating local state. Effective storage validation follows
canonical snapshot resolution, before signing keys, first-party Telemetry or app
construction. Raw canonical rows and legacy S3 imports cannot obtain a missing
bucket from schema defaults. Already-stored nonblank bucket values remain
canonical, including the deliberate name `paperclip`; prior normalization cannot
reliably establish their original provenance.
It does not contact S3 or verify credentials, bucket access, database connectivity,
or that a key matches existing encrypted data. Operators must qualify ordinary
S3 put/read/delete with deployment credentials and preserve the existing key.
AWS credentials continue to use the provider's normal SDK credential chain.
Local and self-hosted storage and key-file defaults remain unchanged.
These are prerequisites for shared storage and secrets. They do not establish
that the whole web server is disposable or that all execution and recovery paths
survive web-server replacement. Run-log/trace storage and producer retention are
separate changes.
## Agent Artifact Uploads
When an agent generates a file that a board user or reviewer should inspect as
@@ -2694,6 +2737,24 @@ and hard restarts with live and dead runners, the result-finalization race,
incomplete bootstrap, repeated crashes with steering, and fail-closed process
identity mismatches.
## Version-based skill authoring and delivery
Managed content uses `managed-skill-content.ts`: prepare and verify outside the
publication transaction, then compare the captured head and publish version,
projections, audit and applicable receipt together. `skill-execution-content.ts`
owns disposable filesystem bindings. Do not write managed installed directories
or infer missing content from an absent cache. Keep linked-local behavior explicit.
The [conversion and qualification guide](skill-ephemeral-web-servers.md) documents
bounded eligibility/verification commands and the one-time writer maintenance
boundary. `managed-skill-content.test.ts` covers the focused domain behavior;
`ephemeral-skills-process.test.ts` requires independent disposable Postgres and
S3 fixtures and starts separate Node processes. The optional
`PAPERCLIP_TEST_POSTGRES_ADMIN_URL` creates a random test database per suite.
On hosts with unavailable Tailscale, set `PAPERCLIP_TAILNET_BIND_HOST=127.0.0.1`
for local fixtures to avoid repeated CLI discovery. Do not use fixture timings
collected during builds as hosted performance evidence.
## App-Shipped Skills Catalog
Skill-library reads still reconcile bundled releases, folders, and direct local
+10
View File
@@ -184,6 +184,16 @@ Source feeds and project task lists retain their existing access rules.
Company skills are shared operating capabilities, not privileged objects by default. Every authenticated agent in a company can create, import, install, edit, update, test, reset, and remove that company's skills unless the company has configured an explicit restriction.
Paperclip-managed skills are immutable saved versions. Studio and API authoring
publish complete content before acknowledging a save; stale edits return a version
conflict and Studio retains the draft. Installed repository skills use the same
version-based reads and execution selection. Web-server files are disposable caches
and staging, so compatible replacement servers can read, edit and deliver protected
versions from the same database and remote object storage. Explicit linked-local
sources retain local behavior. Active or recovering run pins prevent deletion even
after an agent detaches the skill. See [ephemeral-server skills](skill-ephemeral-web-servers.md)
for conversion, compatibility and qualification boundaries.
The governing rule is: **skill permissions are opt-in restrictions, not opt-in capabilities**. Missing skill grants never create a denial in an otherwise unconfigured company, and ordinary skill work does not require board confirmation, a draft-only workflow, or an activation approval.
Core Paperclip owns the skill runtime, company-boundary enforcement, policy evaluation contract, API denials, validation, path containment, secret redaction, and activity logging. Those safety invariants cannot be disabled by policy. Open-by-default skill work never authorizes arbitrary host-path reads, unsafe executable content, or policy edits: local imports and scans must stay within Paperclip-known workspace or managed-skill roots, remote sources must resolve to validated immutable content, and platform safety denials must stay distinct from optional administrative restrictions. Paperclip EE may provide detailed administration for per-agent, per-role, per-action, per-source, and protected-skill rules, but EE is not required to use skills and is not an enforcement boundary. Without EE, companies remain open by default and any already-configured restrictions continue to be enforced by core.
+10 -1
View File
@@ -2375,6 +2375,15 @@ unavailable. Preserve current ownership and newer-work fences. See
is automatic and bounded. Unused Git caches can expire and reacquire the recorded
commit after current authorization and hash checks; authored/unproven legacy bytes
remain durable. See [skill package storage](skill-package-storage.md).
- Paperclip ownership is `managed`, with a null source locator and an immutable
current version. Content mutations prepare durable bytes before a short,
authorization-checked compare-and-swap publication. Acknowledged changes do not
depend on an installed web-server directory. Repository installations use the
same committed-version read and execution boundary; linked-local sources are
explicitly outside the empty-disk guarantee. Execution selections, including
empty selections, persist before delivery; recovery reconstructs exact admitted
digests and active/recovering pins prevent deletion. See
[conversion and compatible upgrades](skill-ephemeral-web-servers.md).
- Refresh is serialized per source, checks saved selection revisions, and publishes
valid skills plus per-entry outcomes with required activity records in one transaction.
Failed packages retain prior versions; access/scan/download failures retain all content.
@@ -2382,7 +2391,7 @@ unavailable. Preserve current ownership and newer-work fences. See
- Match by repository identity and exact path. Preserve IDs, keys, assignments, folders,
and history. New key collisions cannot overwrite unrelated skills. Only changed package
bytes or executable modes create versions. Library reads, tests, and subsequent unpinned
runs use local installed snapshots; pinned/active runs retain their versions.
runs use immutable installed snapshots; pinned/active runs retain their versions.
- Runtime version directories are disposable caches. An hourly, bounded sweep may
evict non-current copies unused for one hour, preserving active and unresolved
execution pins. Selection, materialization, and pin persistence serialize with
+4 -3
View File
@@ -24,10 +24,11 @@ Ordinary PRs do not write timing artifacts or export traces. The exporter job is
skipped for ordinary run names. Adding another label does not run the CI matrix.
Profiling preserves the existing trusted AWS runner routing. Eligible PR jobs
use `paperclip-public-pr-x64`; the routing gate uses `paperclip-ci-routing-x64`.
use `paperclip-public-pr-x64`; the routing gate uses `ubuntu-latest` to verify
current CI CODEOWNERS before allocating any AWS capacity.
The existing fail-closed GitHub-hosted fallback still applies if AWS routing
cannot be authorized. Only the separate post-run Honeycomb exporter uses
`ubuntu-latest` directly; it is outside the measured PR suite.
cannot be authorized. The separate post-run Honeycomb exporter also uses
`ubuntu-latest`; it is outside the measured PR suite.
## Read the waterfall
+26 -3
View File
@@ -18,7 +18,8 @@ existing validation at application startup.
to embedded PostgreSQL. Credentials, trust keys, provider configuration and
deployment wiring needed before the database connection remain supplied by
the environment or the existing secret system. This phase parses only the
database connection record. Runtime mode, host binding and authentication
database connection record and requires the stable environment encryption
master key. Runtime mode, host binding and authentication
checks wait until the saved snapshot has loaded.
2. After schema migration and database connection, startup reads the private
runtime configuration row. An existing invalid row or a database error stops
@@ -38,6 +39,27 @@ existing validation at application startup.
authentication and application services. A saved telemetry opt-out therefore
takes effect before a telemetry client can be created.
Managed Cloud always requires a stable environment master key, including when
an external default secrets provider is selected. Internal local-encrypted
credential paths still need that key.
Managed Cloud validates effective S3 storage after publishing the canonical
snapshot, before signing-key initialization, telemetry, authentication or app
construction. Cloud requires S3 and a nonblank bucket; an authoritative absent
configuration needs explicit environment storage settings. Raw saved snapshots
cannot obtain a bucket from a schema default. Every legacy Cloud file must name its
bucket before its one-time import, even if its saved provider is local disk and
an environment bucket is present. Omission or blank values fail before seeding;
The effective storage candidate is validated before seeding, so a rejected
legacy file leaves no canonical row and can be corrected before retry.
Environment overlays are not saved as operator choices. Correct that file before
import, or use the existing absent-file/null-snapshot environment-only setup.
Ordinary self-hosted file defaults remain unchanged.
Already-canonical nonblank values, including `paperclip`, remain authoritative.
Prior normalization cannot reliably distinguish an operator's deliberate name
from a historical default, so this release does not invent retrospective
provenance or replace those saved values.
Existing operator environment overlays keep precedence over saved values.
Reading an overlaid value does not save it back to the database. Credentials and
connection URLs are never copied into this JSONB row.
@@ -78,8 +100,9 @@ bytes. Restart tests prove configuration restoration under a different home;
they do not prove durable file, secret, or backup storage.
The decision signing service still uses `PAPERCLIP_DECISION_SIGNING_SECRET` when
supplied and otherwise reads or creates its instance key file before the database
connection. The local encrypted secret provider still uses its environment key
supplied and otherwise reads or creates its instance key file. Managed Cloud
performs that step after effective storage validation; self-hosted startup keeps
its pre-connection ordering. The local encrypted secret provider still uses its environment key
or existing key-file mechanism. Those byte-storage fallbacks are outside this
configuration migration. Qualification must account for them separately; this
PR does not establish file-free secret storage on Cloud.
+10 -1
View File
@@ -61,6 +61,15 @@ self-hosted/Cloud targets and separately selected local/Daytona agents. Account
and credential bindings stay in the private eval repo; registration and oracle
tests do not establish a completed live pass or unattended CI qualification.
The deployment-targeted `question-answer-resume` journey reuses the classic
two-question scenario and native continuation oracle on an attached target.
It checks the actual board answers, one to three bound work runs, an agent-authored
task document and browser readback after reload. It accepts provider questions and
durable questions proven by an applied semantic receipt or an immutable completed
native API mutation receipt. It does not qualify named-tool selection. Its provider owns target setup,
usage and cleanup. Registration and local calibration do not establish a fresh
Cloud pass or inclusion in a recurring selection.
The explicit-only [necessary free-text question journey](../tests/runner-e2e/README.md#necessary-free-text-question)
checks one essential input, the rendered prompt and context, the real answer,
one bound continuation, and an exact saved confirmation. Its four development
@@ -547,7 +556,7 @@ any qualification claim; catalog presence alone is not a pass.
The explicit-only [native question/resume qualification](../tests/runner-e2e/README.md#task-continuation)
separates a completed two-answer user journey from semantic-tool documentation
qualification. It verifies the exact provider-pause or semantic-response-wake
qualification. It verifies the exact provider-pause or native response-wake
binding for each answer and preserves prior grades when the definition changes.
## Lifecycle behavior baseline
@@ -0,0 +1,462 @@
# Skills on ephemeral web servers
## Qualification status
Implementation is in [PR #18334](https://github.com/paperclipai/paperclip/pull/18334).
Hosted qualification uses the owned disposable
[test tenant](https://ephemeral-skills-qa-oct-30.test.paperclip.app), external
Postgres, S3, and a real remote Paperclip Computer. Cloud policy reserves the
staging domain for master; the rejected staging branch request below made no
deployment.
- **Passed:** independent-process PostgreSQL/S3 failure matrix; hosted A → B → C
replacement with predecessor homes absent; C reads and executes B's acknowledged
save; historical repository pin delivery while a newer revision is installed.
- **Passed:** full CI and code review at `7ec495de77`, confidence 5/5, no
unresolved findings. Workspace typecheck/build, focused regressions and the
separate-process replacement matrix passed. Local timeout attempts remain
recorded below; their results are not counted as passes.
- **Passed:** compatible image rollback to `6518b323` retained the newer managed
revisions and delivered their bytes plus the historical repository pin remotely.
- **Passed:** deployed unassigned-skill Studio retry: the exact fork v3 was
delivered and executed, Studio reached `succeeded`, and its output snapshot
persisted. Independent package verification found zero blockers.
- The maintenance CLI configuration bootstrap regression and server typecheck
passed. The PR records final CI/review status for the commit containing this
evidence update.
Runtime candidate `9200e3fcb4` contains the native Studio selection/completion and
legacy completeness fixes. It is deployed and qualified. Later changes integrate
master, protect drafts during a delayed UI reload, and load persisted Cloud
configuration in the maintenance CLI; their verification is recorded separately.
The chronological record below
retains earlier failures and intermediate pending states; this section describes
the current qualification status.
## Accepted contract
Given the same database, object storage, secrets, and supported application
artifacts, a replacement server must discover, read, edit, and deliver protected
installed skill versions without its predecessor's files or process memory.
Disk is permitted for disposable scratch, verified caches, and execution delivery.
Managed authoring and library operations address immutable content, not a mutable
installed directory. Git remains the authoring source for repository skills;
installed revisions and run pins govern delivery. Linked local sources remain an
explicit self-hosted compatibility boundary.
Current, pinned, active/recovering, and authored versions retain durable bytes.
Unused historical Git versions keep the existing expiry/exact-commit policy.
Legacy conversion may use one maintenance window. Compatible later upgrades and
rollback use the same remote state. Other web-server persistence, Railway traffic
handoff, and production volume removal are outside this slice.
## Delivery and acceptance
1. Introduce managed ownership and content publication without installed paths;
preserve access, atomic metadata/version publication, idempotency, conflicts,
and active-run retention. Update Studio and API consumers.
2. Separate selection/pinning from materialization; restore exact runtime digests.
Add bounded legacy conversion and disk-independent eligibility diagnostics.
3. Prove cold A → B → C replacements, concurrent writers, uncertain commits,
offline upstream, corrupt/missing objects, access, retention and idle behavior.
Run required checks and qualify one disposable staging tenant with a real
remote agent. Finish with a reviewable PR and exact revision/evidence links.
## Canonical work and progress
- Worktree: `/Users/dotta/.codex/worktrees/d084/paperclip`
- Branch: `codex/skills-ephemeral-web`
- Draft PR: https://github.com/paperclipai/paperclip/pull/18334
- Approved plan: this chat, “Skills on ephemeral web servers,” nine sections.
- Implemented managed create/read/edit/delete-file/fork/rename/restore publication,
immutable catalog installation/reset, Studio version conflict recovery, durable
pre-materialization selection and exact pinned-runtime rehydration. Source
disconnect retains immutable content and access provenance.
- Added bounded installation conversion, eligibility and independent version
verification to existing migration tooling; conversion requires retired writers.
- Independent OS-process A → B → C qualification passed using owned Docker
PostgreSQL and RustFS S3 fixtures. Real HTTP routes covered saves, supporting
executable content, uncertain commit receipts, stale concurrent saves and upload
crashes. This is not hosted Runner qualification.
- Studio tests: 14 passed, including draft preservation and confirmed reload.
- Workspace typecheck and build passed. Map checks and UI token gates passed.
Broader compatibility coverage passed 362 cases; follow-up runs passed migration,
policy, package, project access and retained-run cases after updating old model
expectations. Final focused checks and the full repository suite are running.
- One-connection tests now exercise package acquisition before the publication
transaction. Fork reassignment also uses the transaction's database handle.
- Host embedded Postgres cannot initialize: exhausted kernel semaphore pool.
Owned Docker fixtures are `paperclip-skills-ephemeral-pg` (port 61006) and
`paperclip-skills-ephemeral-s3` (port 61007). No unrelated databases changed.
- Disposable staging tenant created through normal onboarding:
https://ephemeral-skills-qa-oct-30.staging.paperclip.app
Agent `dfd238b5-5e5d-43ef-b34a-cb5bff2267f3` (Skills Qualification), paused.
OpenAI API-key setup uses the explicitly authorized local credential. Candidate
`6518b323528b2b595c5949c3ed2c57a8d2438cb6` is building under release run
https://github.com/paperclipai/paperclip/actions/runs/41085949238.
Single-tenant deploy request: `c65f3677-4b4e-4687-957a-28e2bfb89451`.
Stack `stack-pool-50f5009d5644` is user-managed during qualification so unrelated
fleet rollouts cannot replace the test candidate. No live run claimed yet.
- Greptile's first review found root-package path truncation, linked-local fork
and restore regressions, and a concurrent receipt replay race. Fixed all four;
focused review checks passed 76 server and 16 Studio tests. CI also exposed
obsolete host-path fixtures and a company-deletion/publication race. Updated
those fixtures and publication locking; 20 targeted integration tests passed.
Skill detail now resolves existing metadata without seeding the entire library.
- Remaining: finish repository checks and PR review, candidate deployment and
fresh-home remote Runner qualification including compatible rollback. The PR
stays draft until hosted qualification and the final checks are complete.
- Greptile reached 5/5 with all six comments resolved at `8c0fae76a6`.
CI at that revision passed typecheck, build, all unit/integration shards and
Runner checks; two browser shards still require investigation. The shared-chat
question fixture's five-second assertion raced a successful asynchronous run;
its readiness wait now follows the existing run-settlement helper.
- A cold metadata assertion exposed three manifest downloads during history
listing. New versions now persist a complete metadata index and migration
backfills legacy indexes without changing content/version identity. Process
qualification confirmed zero metadata/warm downloads; its tiny fixture measured
a 176 ms cold read (two objects, 899 bytes), 37 ms warm execution preparation,
899 MB process RSS and 820 bytes of temporary files. These local fixture numbers
are not hosted latency or incremental memory claims. A follow-up compatibility
run caught changed file ordering; preserving the existing order fixes that drift.
- Metadata/package compatibility passed all 44 tests after preserving file order.
Both affected browser cases passed independently. Stop/reset now allows a bounded
30-second cold startup; its failure trace showed cancellation during preparation
when the old five-second assertion expired, before the fixture began streaming.
- The baseline image published successfully, but the deployment check rejected the
branch with `fleet_campaign_staging_requires_master` (Cloud run `41092962684`).
Current Cloud policy uses `test.paperclip.app` for branch experiments. The local
Cloud checkout's older runbook missed this boundary. Qualification is moving to
an owned disposable test tenant; the rejected request made no tenant deployment.
- All 53 applicable CI checks passed at `0dc9a42a6f` (two skipped checks).
The next review found that complete metadata indexes bypassed the unchanged
linked-local manifest shortcut. Whole-package identity mappings now retain that
shortcut; subsets and remapped paths still use their projected inventory.
- A new concurrency regression reproduced a content save overwriting an already
acknowledged metadata edit. Publication now checks the metadata fields it will
replace as well as the version head, and returns 409 when they changed during
preparation. The managed-content and catalog suites passed after this fix.
- Local package/project checks hit timing limits while an older full-suite worker
remained active for over 80 minutes. That task-owned run was stopped; it is not
recorded as a full-suite pass. All four isolated package cases then passed,
including the two previous timeout failures and the linked-local regression.
Final project-access/process qualification is running sequentially. Server
typecheck passed with both final fixes.
- Correct disposable branch-test tenant:
https://ephemeral-skills-qa-oct-30.test.paperclip.app
Stack `stack-ephemeral-skills-qa-oct-30` is pinned user-managed. Baseline A
`6518b323528b2b595c5949c3ed2c57a8d2438cb6` is confirmed serving from image
`ghcr.io/paperclipai/paperclip:sha-6518b323528b2b595c5949c3ed2c57a8d2438cb6-cloud`.
Deploy request `19c33461-d232-453a-bdd1-ba357459be48`, campaign
`fleet-campaign-1793366873548`, Cloud run `41094804453`: one target succeeded.
The user approved saving the same OpenAI key to this test tenant; its remote
Codex environment verification succeeded on a Paperclip Computer.
- Studio created unassigned managed skill `3ade7878-8aaf-47c7-aebd-7da23a8afb5d`
(Ephemeral Skills Proof), with instructions, `references/value.txt`, and
`scripts/prove.sh`. Remote agent `300911d4-590d-4a26-b1c0-c80db14fa072` is
preparing the executable flag through the ordinary API. Fresh-home replacement,
delivered-byte verification and compatible rollback remain pending.
- Final sequential project-access/process qualification passed all 31 cases;
the complete-map package checks passed all four isolated cases. The metadata
and linked-local fixes were pushed as `ceab192b1774fcb5be17db57de5579d81007b9c1`.
- Remote preparation task EPH-1 saved revision 6, version
`1abec28d-dd4a-4763-acd4-5a67af874911`, with the script executable. All three
reported file digests match hashes independently computed from the Studio
inputs. Company: `16cfa89e-f159-5040-927e-aca46ee87c2f`.
- Baseline Studio test `81951c91-ec59-4eae-b5c5-c0083119f6ae` failed before
execution (`b326a961-c1b8-43ad-b38b-7f6424939ee3`): its route constructed
heartbeat without the existing plugin worker manager. This is a route wiring
failure, not missing skill content or missing image dependencies. The fix passes
the app's existing manager through the Studio route to execution, matching other
task routes. No Cloud composition/admission policy changes are required.
The first route-suite attempt hit its 30-second module-load setup timeout before
any test ran; a bounded 120-second setup-budget retry is running.
- The Studio route regression suite passed all 64 cases on retry, and server
typecheck passed. The managed sandbox manager is reused from app construction;
no provider behavior, permissions or lifecycle ownership changed.
- Baseline remote task EPH-3 passed on run
`07a711a9-a7d7-45e3-8c00-f64f71d2a9cc`: the delivered v6 script ran directly
with mode `555`, printed `skill-script-A: durable-skill-payload-A-20261030`,
and all three file digests matched independently calculated input digests.
Its saved task document records the execution-local installation path.
- Imported repository skill `581b718a-3681-48c4-96d5-87d12b694550` from
`paperclipai/paperclip` commit `dff63551fe07934a82a0942e502adba3fcbb08ca`.
The existing import filter admitted 12 files and excluded the API reference.
A later explicit source refresh hit the repository size limit and retained
the installed revision. That refresh is not counted as a successful update.
- Test-only env campaign `fleet-campaign-1793366873581` succeeded at
`2026-10-30T17:38:00.006Z`, changing only `PAPERCLIP_HOME` to
`/tmp/ephemeral-skills-a` on `stack-ephemeral-skills-qa-oct-30`.
Audit evidence reports one target, one key, zero removed keys, and unchanged
Computer images. Studio reopened v6 with its supporting files afterward.
Unassigned fork `6381a0a0-582b-4d26-b858-4e56b606e07c` was created through
Studio and saved as v2 with `unassigned-payload-A-20261030` in its reference.
- Review of `35b6a12fe4` identified a forced catalog reinstall conflicting with
its own audit metadata write. A real Postgres regression reproduced the 409.
Candidate auditing is now read-only; successful publication commits the new
audit metadata, while unchanged/rejected operations retain audit reporting.
Regression checks cover forced reinstall, a new slug, and a competing metadata
writer. The combined catalog/managed run passed 29 cases and hit one unrelated
15-second asset-test timeout; all four focused catalog cases passed on an
isolated rerun. Server typecheck passed.
- Latest browser CI exposed another five-second startup assertion in the
feature-disable journey. Its trace showed an active adapter invocation before
the fixture's first message. The assertion now uses the existing 30-second
cold-start budget; the exact browser journey passed locally in 12.5 seconds.
No feature-disable behavior or fixture completion assertions changed.
- Latest code review of `07fffa749511a39b05b2dbc43adcce842195398a` is 5/5,
with zero unresolved review threads. Hosted candidate build is run
`41101360597`; baseline A remains deployed until it completes.
- Provider console independently confirmed external Neon Postgres and S3 on A,
with `PAPERCLIP_HOME=/tmp/ephemeral-skills-a`, deployment
`5fc05d1a-2451-465c-8a15-16b18d1e0d3d`, replica
`f7393d02-49b6-40b9-ae94-db9181300bf4`. A temporary marker was written to
that home so a later container can prove the predecessor's local state is absent.
- Imported the smaller `vercel-labs/agent-skills` repository at exact commit
`93f5a2dee1a270015473e19d24a758a012fa058b`: skill
`3e9f2b84-2d15-49f9-a5c0-8596f4c6e313`, source
`0c03e633-d22e-4a63-b5a5-843823f2eb7b`, 75 admitted files.
Early pin attempts were rejected by the existing Beta skills gate. The late
error toast was confirmed; read-only DB inspection showed no saved pin.
- Beta skills is a tenant preference, so fleet feature override correctly
rejected it as non-managed. Test-only env campaign
`fleet-campaign-1793366873607` exposed only this preference, preserving the
complete existing hidden-settings list and temporary A home. It succeeded at
`2026-10-30T18:04:20.150Z`: one target, two keys, zero removed keys, unchanged
Computer images. The tenant's normal Experimental UI then saved Beta skills
enabled. No fleet default, identity, permission, or volume policy changed.
- The preference campaign replaced A's container: deployment
`9ba9202e-7f47-4edd-b501-aa807760b132`, replica
`d2131533-f4d2-4173-b984-ca46beaef61c`. Provider console observed the
predecessor marker absent, then wrote a new A2 marker for the next replacement.
- Repository assignment saved through the library UI as historical version
`918e2066-b241-4cdc-934a-db896138240b` (revision 1, `GitHub 93f5a2de`).
Explicit source refresh to main published current revision 2
`fa3bb9ac-fcd9-443b-970c-f62590f881dc` (`GitHub 1a2c79d4`); automatic
updates remain paused for this fixture.
- Remote task EPH-4 (`e561a058-3e2d-4f90-9899-a69c6539ed42`), run
`9917cfa3-caed-400a-b1a0-58183e2e2614`, passed after A's temporary state
was replaced. Managed v6 hashes/output/mode matched EPH-3. The repository
wrapper delivered revision 1 while revision 2 was current. Independently read
exact-commit upstream contents matched the delivered instruction digest
`50b55178a2da8ee931850193596601fa0517cd800e171366a903769f25bf4dda`
and `rules/async-parallel.md` digest
`6d2f841896279e976dfcdc1ac89e70771ac188baadfd43c096b5706cb838b961`.
The agent used the rule to recommend parallel independent fetches and saved
paths, command results and API history in task document `immutable-pin-proof`.
- Required CI gates `ci / verify` and `ci / e2e` passed on `07fffa749`.
Latest check rollup: 52 success, two skipped, one cancelled advisory review
job; Greptile separately completed at 5/5 with no unresolved threads.
- Candidate `07fffa749` deployed successfully through core-only test request
`d4e172e8-a861-48cc-ae9c-e2f26c8ee636`, Cloud run `41106109829`.
B is deployment `ed70e789-22c3-4b93-93de-da61d7f30ca4`, replica
`16fbb2e8-a7b3-4f32-a483-bc2f5c77a8ee`, with
`PAPERCLIP_HOME=/tmp/ephemeral-skills-b`. Local health confirmed the code SHA;
provider console confirmed A's home and marker absent. The unassigned fork
opened as v2 with zero agents. Studio acknowledged a supporting-file edit to
the primary managed skill as v7 (`durable-skill-payload-B-20261030`).
- Independent verification on B read 23 saved versions: 21 `remote_storage`
results and two `database_release_snapshot` results. No corrupt, missing,
local-storage or provider-mismatch results. The next cursor returned zero.
- Live Studio test EPH-5, test `9c4f3775-2793-46c6-b09d-e3343e0e4c65`,
heartbeat `7fe45977-a061-408b-b7c5-5721a7e9f08b`, passed the repaired plugin
wiring but failed native admission: `skill_test` was excluded by Runner's
task-mode allowlist and execution-input parser. This failure is retained;
the Studio acceptance requirement remains pending a deployed retry.
- Follow-up admits and preserves `skill_test` through the existing native
selection, execution contract and tool bindings. It does not relabel tests
as standard work. Task-bound JWT restrictions remain with their authorization
owners; the native surface is restricted as detailed below. No executor refactor or
Rust protocol change is needed. Older images that reject this mode cannot
continue a new Studio test; rollback qualification settles tests first.
- Follow-up local checks: 78 admission/input tests, 109 Runner contract tests,
40 assigned-MCP tests, and three real-HTTP skill-test scope regressions passed.
Initial scope/MCP attempts encountered sandbox socket restrictions; permitted
retries passed. Runner TypeScript/Rust checks and server TypeScript check
passed. Maps remain aligned (35 areas, 192 capabilities).
- B's v7 is `e1f96114-6be5-4878-b9ae-269bac0da215`; independent hash of
its supporting file is `c2d9b967aa8ddfad7896804ea1a7ae613b8ff631ff6a084cee7553125bc7fd27`.
EPH-6 (`c5377e90-c80c-4f97-8ada-c4eaf205af0a`), run
`96537d81-b224-442a-9ec1-993fbd89ff56`, completed successfully and saved
`server-b-skill-proof`. Direct script output contained the B payload; executable
mode remained 555, other managed hashes were unchanged, and repository v1
instruction/rule hashes matched the independent exact-commit reference.
- C home campaign `fleet-campaign-1793366873685` (target
`fleet-campaign-target-1793366873686`) succeeded at
`2026-10-30T18:36:03.930Z`, preserving both managed env keys and Computer images.
Deployment `462e3327-e49b-4096-b5e2-73f5db058a9f`, replica
`01c696c4-89b9-4358-9c2b-108faa4c9d50`, served `07fffa749` with home
`/tmp/ephemeral-skills-c`. Console verified A and B directories and B's marker
absent. Studio cold-read v7 and the exact acknowledged B payload.
- Unassigned fork v2 identity was independently confirmed as
`8b008393-f909-424a-9f68-1995231455a7`. It remained at zero assignments on C;
its supporting file was then edited through Studio to a C-specific payload.
Execution on the candidate with native Studio admission remains pending.
- C's remote EPH-7 (`d57f6f66-7072-4fb9-abde-199edf5192ef`), run
`c7f89682-ab9b-4f00-940f-88967c6c0264`, completed successfully. The saved
`server-c-skill-proof` document (revision `8129375b-f56c-4b80-99b0-637481a31f72`)
was independently opened and read. All five hashes matched the B run and
independent references. Its new session `7f164893cdc73464e112e2572baed3ddc166bb29485d770c37fbf7449793cdc0`
executed the unchanged script with exit 0, mode 0555 and the exact B payload.
The managed selected/current version remained v7, and repository selection
remained v1 while its current head remained v2.
- Review of `8821b040` found that native task creation omitted the admitted
skill-test scope. Image build `41108317938` was cancelled before deployment.
Native authorization now carries the saved scope, denies company/peer tools,
task creation and external tools, and checks the scope before mutation receipt
replay. Task context contains only the harness task. Real database regressions
exercise both fresh tests and persisted tests after their task mode changes.
- Native scope checks passed: three new real-database cases plus four REST
scope/image-access cases. The existing native tool-authority suite passed all
37 tests. Server typecheck and map checks passed. The initial new-test attempts
corrected a fixture tool name and matched the existing privacy-preserving 404
for unrelated tasks; own-task reads returned 200.
- `350f1b377c459420a1c1474723501a4bccc6d7fc` received Greptile 5/5.
The native-scope review thread is resolved. Test deployment request
`d2480188-1fc9-4a22-a32b-16af7f439ca4` prepared in Cloud run `41110650568`;
candidate image build is `41110729544`.
- The fork's C save is version `ef34d9e5-2533-497e-8411-a797117afb4a`.
C's durable `tool.execution.completed` event at sequence 322 was inspected
independently of the report: the real shell command completed with exit 0,
mode 555, all five expected hashes, and `skill-script-A: durable-skill-payload-B-20261030`.
A disposable `qualification-marker-c` was written in C's temporary home for
the next container replacement check.
- Full CI at `350f1b377c` passed 50 checks but found two old `mode_denied`
message expectations in case/reassignment tests. Both operations are rejected
earlier by the native scope guard with 403. Updated the assertions and checked
that denial never stops another task. The case-gate regression and all 26
reassignment tests passed locally. Reassignment now uses the existing optional
external-Postgres helper; initial attempts hit exhausted embedded-Postgres
resources and a startup timeout, retained as failures rather than passes.
These follow-ups change only tests and evidence, not candidate runtime code.
- Image `350f1b377c` deployed successfully in Cloud run `41115408877`, confirmed
by local health on deployment `d70457ab-a812-45d5-8a38-657f6bfc02de`, replica
`9f58192d-9207-4065-86e4-48887c6a8b3e`. A/B homes and C's marker were absent.
- Studio test `ef0aa327-f719-44a3-bea2-1d051f2a793a`, task EPH-8
(`860476c5-d4bf-4619-9206-8aa18884f545`), executed successfully but delivered
the agent's normally assigned primary skill instead of the requested unassigned
fork. Its report explicitly records the mismatch. This is a failed qualification,
regardless of the task's Done status. The fix passes the durable Studio pin into
execution preparation, replacing ordinary assignments while preserving recovery
pins and current access checks. Hosted retry remains required.
- The same EPH-8 heartbeat (`94eeb6ff-7d9e-49b7-bee2-0ef5f41ff8a4`) succeeded
and marked its task Done, but the Studio row remained queued with an empty
output snapshot. Native completion bypassed the REST-only success hook. Native
status publication now calls the existing skills owner within its transaction;
status, output and activity commit together. Four real-Postgres regressions pass
for completion/cancellation, replay from another client, transaction rollback,
blocked work and superseded tests. Completion uses a conditional terminal update.
- The two selection regressions pass, including assembled dispatch of an unassigned
historical executable file. Server typecheck and map checks pass. A broad local
execution suite attempt hit timeout cascades (20 passed, 9 failed); this is not
counted as success. Isolated new tests passed; the full affected suite is rerunning.
- Compatible rollback request `2363f01e-2e6b-4b72-9234-3fd0c5f22e88` deployed
`6518b323528b2b595c5949c3ed2c57a8d2438cb6` through Cloud run `41116892516`.
Deployment `5034b027-d9e2-4bd6-8efe-526d3d065d7d`, replica
`9ff45218-e553-4122-b411-e7052c521917`, was confirmed through local health.
The predecessor's `qualification-marker-d` was absent. Studio reopened the
unassigned fork's v3 supporting file as `unassigned-payload-C-20261030`.
- Rollback task EPH-9 (`d5d03621-9616-4713-88ad-0ea54e4c3d53`), run
`7ae0b61d-0e9f-4761-914c-9dc399c0ebc8`, completed on a real remote Computer.
Its `rollback-skill-proof` document matches all six independently known hashes,
managed v7 and repository v1 IDs. It executed the unchanged script with exit 0,
mode 0555 and the acknowledged B payload. Durable command event sequence 293
was independently inspected through the tenant console and confirms those
bytes, hashes and actual execution. The repository rule also produced the useful
independent-requests `Promise.all()` recommendation.
- The complete affected suites passed all 33 tests in 65.65 seconds. The Studio
fix is `417270ab18`; current master `3b84c89885` merged without conflicts as
`5afd8c3b056f6c0fceeb121c0f398beb72317e2b`. Post-merge server typecheck,
all 33 affected tests, map checks and UI token gates passed again.
- The independent OS-process replacement matrix passed again on `5afd8c3b05`
(two scenarios, 54.24 seconds). A/B/C version IDs were
`56c4b315-082f-4caa-8788-02e10b45d3a4`,
`ed03e467-3a81-4256-849e-53ece688e5aa`, and
`9ff5d4ce-43e7-4b2e-883d-8b010fc5c42b`. Cold read was 522.16 ms,
two downloads/899 bytes; warm preparation was 143.72 ms with zero downloads.
Reported RSS was 881,639,424 bytes and disposable home content 820 bytes.
These are local fixture measurements, not hosted latency claims.
- Candidate request `9a03542e-ea41-4ea1-94c8-7dd1ae38c621` prepares in Cloud
run `41118819981` and builds in Core run `41118878753`. The tenant remains on
the verified rollback image until this candidate is deployed.
- Review at `5afd8c3b05` found that existing partial repository versions could
bypass conversion and be reported as eligible. Installation conversion,
eligibility and independent verification now compare the current saved inventory
with the installed inventory. Missing files block readiness; conversion can use
only complete saved/local content or the exact pinned remote source. Both JSONB
and packaged legacy regressions pass, including upstream failure with an unchanged
head, exact-commit repair and unchanged complete installations. The entire managed
content suite passed 16 tests. Build `41118878753` was cancelled before deployment
so hosted acceptance will use a candidate containing this correction.
- Full workspace typecheck passed after allowing the migration launcher's local IPC
socket. The initial sandbox attempt failed with `listen EPERM` before that check
could run. The workspace build is running separately.
- The workspace build passed on `9200e3fcb4` after correcting a missing-version
null check caught by its first attempt. Greptile re-reviewed that commit at
5/5 with zero unresolved findings. Image request
`0b5a10c1-dccf-4c01-9db7-548ea07897a0` prepares in Cloud run `41120340127`
and builds in Core run `41120440752`.
- Earlier failed Studio fixture `ef0aa327-f719-44a3-bea2-1d051f2a793a` was
cancelled through Studio to settle its stale queued pin. Its mismatch report and
draft output remain visible. It is still recorded as a failed qualification.
- CI run `41120305357` found the same obsolete restart-scope fixture in Runner
static checks and general server shard 5. The helper always returned no saved
skill; preparation now correctly rejects that state. It now reads a real durable
test/version row, asserts missing-version rejection first, and still verifies
restricted REST scope after task-mode edits. Both focused HTTP cases and server
typecheck pass. The complete 52-case HTTP suite passed in 63.78 seconds. This follow-up
changes only the test fixture and evidence, leaving image runtime code unchanged.
- Master advanced to `76fde891cc` during image publication. Merge `61f5664337`
preserves both the skill-recovery and native-usage imports; no skills behavior
changed in the merge. Full workspace typecheck and build passed. A combined
local run passed 42 cases, failed three execution timeouts plus a tracer setup
assertion, and skipped 52 HTTP cases after a setup timeout. Isolated retries
are recorded below rather than treating the combined run as passing.
- Review found a delayed conflict-reload response could overwrite text typed after
discard confirmation. The response now applies only while the same skill, file
and draft remain current. All 17 Studio component cases passed, including a
delayed response while the user continues typing. This client-only follow-up
is separate from the `9200e3fcb4` server image used for remote delivery proof.
- Full CI run `41124309799` passed at `7ec495de77`; Greptile review 14 is 5/5
with zero unresolved findings. The isolated local execution retry stopped
producing progress and was interrupted; no success is claimed for that attempt.
The full CI suites cover the integrated execution and HTTP cases.
- Candidate `9200e3fcb45082ad73fbb75863d56eb2e6ce526c` deployed successfully
through Cloud run `41124147876`, ready at `2026-10-30T20:36:46Z`.
Deployment `3daed721-eefe-4947-afe3-d8fd1db6aa2c`, replica
`29375d2e-50ea-467e-9492-a2d4bc7e628e`, retained the temporary C home setting.
Console inspection confirmed A/B homes and the rollback marker absent.
- The Studio retry created test `7c55d51d-c2c9-426e-a2fa-3606c486d41a`, task
`e8405564-1d2e-4013-8aeb-145de0a76fbd`, and remote run
`c6ebc90d-1411-404b-ad6d-789d960a7a48`. It delivered only the selected
unassigned fork `ef34d9e5-2533-497e-8411-a797117afb4a` (v3), with
`unassigned-payload-C-20261030\n`, stdout
`skill-script-A: unassigned-payload-C-20261030\n`, exit 0 and mode 0555.
Studio visibly reached `succeeded` and displayed the durable output snapshot.
The fork still has zero assignments. SHA-256 values match the expected fixture:
`SKILL.md` = `a97ee4d33cac28f9affcc53e48b3de00f72a9a8b70a0b3a53bb81569b1111ae6`,
reference = `0d5a7396baaf395ef24e9136b2f9892e9878d863b42ff3195d376f61248d1f5f`,
script = `8830c87e4e56e76dbe70bfac5fa4260d1e33d62eaa3289d1f8887a3fa9521da0`.
- Independent database inspection confirmed task EPH-10 is done, its native run
succeeded, and its exact durable selection contains only the unassigned fork v3.
The Studio row is `succeeded` with a 1,915-character output snapshot. Runner
command event sequence 204 independently confirms all three hashes, actual
script stdout, exit 0 and mode 0555; these are tool results, not only the agent's
report. The Studio success screenshot is retained with the handoff.
- Final eligibility inspected 14 installations, all `version_backed`.
Independent verification inspected 25 versions: 23 `remote_storage`, two
`database_release_snapshot`, zero blockers, and zero rows at the next cursor.
The first standalone command incorrectly reported packages unavailable because
it had not loaded Cloud's persisted runtime configuration. The same services
passed after loading that snapshot. The CLI now loads it read-only and fails
explicitly if absent, without seeding configuration. A real child-process test
covers missing configuration, no write on inspection, eligibility, and object
verification; it passed. An initial diagnostic wrapper also used a nonexistent
compiled DB entry point; correcting it to the image's source entry point allowed
the bounded verification to run. Neither diagnostic failure changed skill data.
- The CLI child-process regression passed in 46.52 seconds, and server typecheck
passed after the bootstrap correction. The CLI reads existing configuration
without creating or changing it; no new maintenance process or listener exists.
+173
View File
@@ -0,0 +1,173 @@
# Skills on ephemeral web servers
The skills guarantee is replacement of A by B, and then C, with empty web-server
homes and the same database, object storage, secrets and supported application
artifacts. Disk remains useful for scratch archives, verified caches and transport
staging. It does not own acknowledged managed edits or installed version selection.
This guarantee does not qualify instructions, workspaces, controller state, run
logs, traffic switching or readiness/draining for volume removal.
## Ownership and publication
`managed` is Paperclip ownership. Its locator is null; editability does not depend
on a directory's position beneath a managed root. Existing policies normalize it
to `workspace`, the policy category previously used by managed local skills.
Repository provenance and tracking remain separate from installed content. Forks
and disconnected editable copies retain source access and cannot publish restricted
content through a public source category.
`managed-skill-content.ts` reads immutable version inventories, prepares candidates,
and publishes them against a captured head. Package upload and verification happen
before the final database transaction. That transaction rechecks identity/access,
locks names in sorted order, locks the skill, verifies the base, and publishes the
version, head, projections and applicable mutation audit/receipt. Publication races
return `409`; clients must reconcile instead of automatically rebasing. Complete
inline versions remain the compatibility fallback when external writes are disabled;
they never depend on an installed directory. Normal cloud qualification uses remote
object storage.
The initial create response, including its original version, can be replayed after
a lost response and subsequent edits. Its durable API receipt retains the response
projection without Markdown; the immutable version supplies the body. Receipts
remain scoped to company, actor and operation context. A deleted skill's receipt
fails explicitly rather than creating another identity.
`skill-execution-content.ts` owns temporary materialization. Heartbeat preparation
selects authorized immutable versions, saves the selection (including an empty
selection), and only then materializes admitted entries while retaining the existing
retention lock. A renamed skill is recovered through the version's stable skill ID.
Native recovery resolves the version, reconstructs its v1 projection and requires
the admitted digest, manifest digest, file count and byte count to match. Adjacent
compatible releases must preserve that projection contract.
Studio tests deliver the selected saved version through the same native Runner
path, even without a permanent agent assignment. Their `skill_test` mode remains
explicit in the execution input. The durable test row replaces ordinary agent
assignments with its exact version, independently of the Beta skills preference;
required environment skills remain subject to their existing policy. A shadowed
or inaccessible test skill fails preparation. Preconfigured Runner homes cannot
receive this managed delivery, so Studio requires an isolated home. Task-bound
credentials and native authorization
retain the admitted scope through restart and task-mode edits. Native tools expose
only the harness task and admitted skills; company browsing, task creation,
connectors and assigned MCP tools are unavailable. A rollback image must understand
that mode to continue an active Studio test. Settle tests before rolling back to an
earlier image that rejects it.
Native task completion publishes the Studio result and output snapshot in the
same transaction as its status decision. Replaying a committed decision cannot
recapture later document edits or duplicate completion activity. A successful
provider turn alone does not complete a test whose task remains unfinished.
Bundled release snapshots remain immutable. Reconciliation preserves an installed
head; an older process must never promote its shipped bytes over another installed
version. The shipped release history remains independently selectable. Linked-local
skills retain mutable source behavior and are explicitly excluded from cloud readiness.
## One-time conversion
First deploy compatible readers and shared/API types. Preserve the old volume and
keep legacy writers until the final supported contents can be captured. Automatic
JSONB package migration is separate from installation conversion; passing one does
not prove the other is finished.
Run the existing bounded CLI with the target's explicit database and storage config:
```sh
pnpm --filter @paperclipai/server exec tsx scripts/migrate-skill-packages.ts --phase=eligibility --company=<uuid> --limit=10
pnpm --filter @paperclipai/server exec tsx scripts/migrate-skill-packages.ts --phase=installations --company=<uuid> --limit=10
```
These commands return a cursor. Continue each phase with `--after=<uuid>` until an
empty batch. Eligibility is a metadata-only report, not a storage verification claim.
Installation preview inspects candidate legacy contents without publishing them.
For remote legacy imports it can acquire their exact pinned source; it must never
use the latest branch as a replacement for missing installed content.
1. Inventory all companies and source kinds. Identify missing versions, incomplete
inventory, local storage receipts, catalog reset snapshots and unresolved runs.
2. Backfill legacy package/version bodies with the existing `snapshots` and
`versions` phases. The latter also fills missing version metadata indexes so
subsequent library/history reads need no object downloads. Keep original bytes
until independent verification succeeds.
3. Stop admission and skill/source writers; retire every filesystem-authoritative
process. The `--writers-stopped` flag attests this operator action; it does not
stop the application itself.
4. Apply final installation conversion on the host with the legacy files:
```sh
pnpm --filter @paperclipai/server exec tsx scripts/migrate-skill-packages.ts --phase=installations --company=<uuid> --limit=10 --apply --writers-stopped
```
5. Sweep `eligibility` and `verification`, including all historical versions. The
latter verifies object bytes independently of caches. Follow all cursors; a
successful first batch is not a complete readiness report.
6. Start a compatible server with a fresh home and test list, file read, authoring,
history and exact selected execution before reopening normal admission.
Managed conversion preserves skill IDs, keys, history, assignments, pins and access
provenance. Identical complete snapshots reuse their version IDs. Catalog conversion
preserves the original reset version as well as installed content. A missing legacy
directory can use a complete verified saved version. A partial Markdown-only rescue,
unknown revision, unsafe source tree or active legacy selection without exact version
identity is a blocker. Settle or snapshot such runs while A is still available; do
not cancel them simply to pass preflight.
Report statuses distinguish linked-local sources, legacy managed/catalog records,
missing current versions, unknown active-run selections, missing/corrupt packages,
local storage and provider mismatch. Expired unused Git history keeps its existing
30-day/exact-commit policy. Current, pinned, authored and recovering versions need
independent durable content. `local_storage` is supported self-hosted durability;
it does not satisfy remote empty-disk recovery.
## Storage and rollback
Cloud readiness requires external Postgres and remote object storage. Migrate and
verify existing local-disk objects before changing provider/bucket configuration;
changing configuration alone does not copy receipts or objects. Keep the old provider
available until a provider migration has copied and independently verified every
referenced object and atomically updated its storage receipt. This command does not
perform provider migration: `local_storage` and `provider_mismatch` are blocking
results for cloud qualification, not instructions to switch configuration and retry.
A directory of extracted caches is never a durable object backend.
Conversion establishes the rollback floor. Afterward only compatible version-reading
binaries may overlap or be rolled back against the same remote state. Reattaching an
old volume does not roll back committed content. Filesystem-authoritative binaries
require an explicit reverse migration and are unsupported rollback targets.
A routine compatible A → B upgrade needs no skills conversion or filesystem copy.
A current version ID alone does not establish conversion completeness. Eligibility
and independent verification compare its file inventory with the installed record
and report `incomplete_current_version` when supporting files are missing. Installation
conversion can reacquire a complete exact pinned source; unavailable or unpinned
sources remain blockers. Historical versions are not compared with newer installed
inventories, since later revisions may legitimately add files.
## Qualification
The focused service suite covers publication rollback/conflict, supporting and binary
files, executable modes, restore/fork/rename, active-run deletion protection and legacy
conversion. The opt-in process suite starts independent Node servers with one database
connection each, exercises real HTTP routes and object storage, removes predecessor
homes and executes a delivered harmless script. It also injects a lost response, failed
upload and process death during upload. It is a skills-router qualification, not a
full hosted Runner or whole-application deployment claim.
Use owned disposable Postgres and S3-compatible fixtures. The optional admin URL
creates a random database per test suite and never migrates the database named in
that URL. The S3 test creates and removes its own random bucket. Supply test-only AWS
credentials through the environment:
```sh
PAPERCLIP_TEST_POSTGRES_ADMIN_URL=<disposable-postgres-url> \
PAPERCLIP_TEST_S3_ENDPOINT=<disposable-s3-endpoint> \
pnpm exec vitest run server/src/__tests__/ephemeral-skills-process.test.ts
```
Record revision, fixture image digests, version IDs, cache/object reads, cold/warm
timings and useful output. These local timings do not establish hosted latency.
Separately qualify one disposable staging tenant and a real remote Runner, including
an explicit repository import, historical pin, fresh-home replacements, compatible
rollback and recovery without predecessor paths. Publish the observed evidence with
the PR; a passing local suite is not that staging evidence.
+45 -13
View File
@@ -7,7 +7,26 @@ The original repository tree, wrappers, binary bytes and executable flags retain
their existing behavior. New Git packages also retain an immutable restore recipe;
locally authored/edited packages and unproven legacy packages keep a durable copy.
## Automatic upgrade
## Installed content authority
Paperclip-owned skills use `sourceType: managed`, `sourceLocator: null`, and an
immutable `currentVersionId`. Creation, edits, deletion of files, forks and restores
prepare verified packages before a short transaction publishes the version, head,
metadata and audit. A competing head returns `409`; it never overwrites another
writer's files. Acknowledged saves survive cache loss. Studio submits the version it
read and preserves unsaved text on a conflict.
Repository and catalog installations also read committed versions. Runtime selection
persists version pins before delivery materializes files. Recovery uses the pinned
version and checks its reconstructed v1 asset digest; a previous server's `rootPath`
is not proof of availability. Active or recovering run pins block whole-skill deletion,
even after the agent assignment is detached. Explicit linked-local sources retain
their local filesystem behavior and are outside this replacement guarantee.
See [ephemeral web-server operation](skill-ephemeral-web-servers.md) for the one-time
installation conversion, rollback boundary and qualification procedure.
## Automatic package upgrade
No data-migration command is required. The normal schema upgrade applies migration
0415 (`0415_zippy_zemo.sql`). External writes and automatic conversion are enabled by default. Startup
@@ -31,20 +50,30 @@ reader is the rollback floor; an older binary needs rehydrated database contents
Use durable, backed-up local storage or S3-compatible storage for authored packages.
The extracted cache is not that storage backend.
Deleting an editable file or folder keeps a temporary copy outside the skill until
the transaction commits. Upload or database failures restore the original subtree,
including binary files, permissions, empty folders and files omitted from inventory.
Successful deletions remove the temporary copy; historical versions retain their
existing package bytes. If the commit reply is lost, recovery checks the saved
version under the mutation lock before restoring. A committed deletion stays
deleted. If the database is unavailable or the skill has since changed, recovery
preserves the backup and logs its location instead of overwriting newer work.
Managed file and folder deletion publishes a new inventory. It requires no local
rollback copy. Unused uploads follow the existing orphan/deletion machinery; a
post-commit cache or notification failure cannot undo a committed save. Only the
explicit linked-local compatibility adapter retains filesystem rollback handling.
Create idempotency receipts retain the original response projection and immutable
version identity in `company_skill_mutation_receipts`; file-save receipts keep their
existing activity receipt shape. Retries reauthorize access. Deleted identities do
not transfer their receipts to a skill recreated with the same name. Skill bodies
remain in packages/versions rather than activity logs.
The optional `server/scripts/migrate-skill-packages.ts` command remains available for
diagnostics and controlled batches. It defaults to dry run, supports
`--phase=snapshots|versions|orphans|deletions`, `--company=<uuid>`, `--limit=1..50`,
`--phase=snapshots|versions|orphans|deletions|installations|eligibility|verification`, `--company=<uuid>`, `--limit=1..50`,
`--after=<uuid>`, `--apply` and `--clear-legacy`. It is not part of normal installation
or upgrade. Never point it at another instance's database/storage configuration.
or compatible routine upgrade. The installations phase is the one-time legacy
conversion boundary described in the linked runbook. Never point it at another instance's database/storage configuration.
New package-backed versions retain their complete path/kind/encoding index in
`package_file_map`, including identity mappings. Library and version listing read
this metadata without downloading manifests or archives. The bounded `versions`
phase also backfills older null indexes from verified manifests without changing
version IDs or content; include that phase in legacy conversion. Old null indexes
remain readable during conversion, with a cold manifest read when needed.
## Acquisition and retention
@@ -83,8 +112,11 @@ Package/version publication and deletion use transaction-aware work notification
local asset use signals its filesystem worker. Both reuse the delivery coordinator,
restore deadlines on startup, pause in drain/standby, and stop on shutdown. With no
pending conversion, retry, or eligible cache deadline they perform no recurring work.
The supported live writer is the owning server; independent SQL writers/other servers
need restart reconstruction or an explicit wake. No permanent DB listener is added.
Compatible servers resolve the durable head on each content operation and use
transactional publication checks. Content correctness needs no process-local
invalidation. Maintenance wake delivery across instances remains owned by the
delivery coordinator; startup reconstructs pending deadlines. No permanent
skills-specific DB listener is added.
Conversion retains authoritative legacy bytes until verification succeeds. Conversion
retries and cache/deletion dates are optional maintenance eligibility; they may wait
until the next ingress wake, including with package storage disabled. They do not