mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-06 10:48:12 +02:00
1de105c475bcfc31e00a6ad464ca42466140474b
3902
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1de105c475 |
fix(observability): pin the Sentry browser SDK and gate the optional Sentry server peer on the exact version (#12270)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip uses separate server and browser packages for runtime
services and the board.
> - Sentry integrations need an exact SDK version and safe optional
loading.
> - A version range can select an SDK that the privacy tests did not
audit.
> - Missing peer metadata does not describe the optional server SDK
contract.
> - This pull request pins the browser SDK and gates the optional server
SDK on its exact version.
> - The benefit is a clear SDK contract with fail-open startup behavior.
## Linked Issues or Issue Description
**What happened?**
The browser package used the range ^10.71.0, so a lockfile refresh could
select a newer SDK. The server loaded @sentry/node dynamically but did
not declare its optional peer contract.
**Expected behavior**
The browser package must use the audited 10.71.0 version. The server
must load @sentry/node only when the installed peer matches 10.71.0. The
server must start when the optional peer is absent.
**Steps to reproduce**
1. Install the project dependencies.
2. Inspect the browser Sentry version and the server package metadata.
3. Start the server without installing @sentry/node.
4. Confirm that the server starts and that the dynamic Sentry bootstrap
does not load an unsupported peer version.
**Paperclip version or commit**
|
||
|
|
4d82f5eaea | copy: unify user-facing "company" wording to "organization" (#12243) | ||
|
|
d785b19213 |
test(server): fix the pre-bind race in the byte-ledger ceiling test (#12280)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - The server manages duplex channels that carry data between workers
and hosts.
> - The aggregate byte-ledger ceiling test can race the channel bind.
> - The race can make channel open fail before the test checks the
ceiling rejection.
> - This pull request writes one byte after the open call binds the
channel.
> - The test now checks the post-bind rejection and the retained-byte
count.
> - The benefit is a stable test that checks the intended byte-ledger
behavior.
## Linked Issues or Issue Description
**What happened?**
The duplex aggregate byte-ledger ceiling test scripted data during
channel open. Under load, the host could process the data notification
before the open continuation bound the route. The test then saw
`DUPLEX_CHANNEL_OPEN_FAILED` instead of the intended post-bind
rejection.
**Expected behavior**
The test must open the channel first. It must then write one byte and
confirm that the serialized host-to-worker frame exceeds the four-byte
ceiling. The route must reject the write and retain no bytes.
**Steps to reproduce**
1. Run the focused server test file.
2. Repeat the test several times under load.
3. Observe that the old test can fail during channel open.
4. Run the updated test and confirm the post-bind rejection.
**Paperclip version or commit**
canary/v2026.827.0-canary.0
|
||
|
|
eb86fcd498 |
The agent, drawn as itself (#12274)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - A new customer's first session ends in the tenant's agent arc: create an agent, connect a model, review > - Walking it turned up questions the arc had no business asking — a role picker using a vocabulary the customer has not been given, a model picker asking them to judge models they have not met — and chrome restating what they had just watched happen > - Each one costs a first-session customer attention at the exact moment they are deciding what this product is > - This pull request cuts the arc to what it must ask, and draws the agent as itself so the arc has a visible subject > - The benefit is three steps that each ask one thing, ending on an agent that is visibly ready ## Linked Issues or Issue Description No public issue exists. The changes come from walking the sign-up arc end to end. **What happened:** The agent step asks for a role from a fixed enum before asking for a name. The model step shows two "Recommended" badges (on both options), an "Adapter type" eyebrow, and a model picker. The review step lists a three-row checklist of work the customer just performed. The progress strip is a full-width segmented bar. **Expected behavior:** The agent step asks for a name. The model step offers the two harnesses and hides the rest behind advanced settings. The review step says the agent is ready. The strip counts three discrete steps. **Steps to reproduce:** 1. Sign up and enter the tenant wizard on the agent arc. 2. Observe the role select above the optional name field. 3. Continue to the model step: both options carry a "Recommended" badge, and a model picker sits below. 4. Continue to review: a checklist restates the organization name, agent, and model. **Additional context:** The brand pill assets (`pill-1-dormant.svg`, `pill-1-alive.svg`) are transcribed verbatim into a component rather than approximated. The role removal exposed a latent silent-failure path — see Risks. ## What Changed - `PillGuy` renders the brand pill in two states; the arc holds one instance, dormant through create and connect, alive on review. - The agent step asks for a name only. The name is required; the role picker is gone. - `DEFAULT_AGENT_ROLE` (`general`) backs every onboarding hire, and `agentRole` now defaults to it rather than empty. - The model step drops both "Recommended" badges, the "Adapter type" eyebrow, and the model picker; "More Agent Adapter Types" becomes "Advanced settings"; the sub-line becomes "Paperclip works with your existing subscription or API keys." - The review step drops its checklist; the heading becomes "Let's get started..." with "[name] is ready to work!". - The progress strip renders three left-aligned dots at the previous gap. - Five e2e specs and both wizard unit suites migrate off `#onboarding-agent-role`. ## Verification Run the tenant suite: ``` cd ui && npx vitest run ``` - 4398 tests pass across 474 files; `npx tsc --noEmit` clean. - Walked live in a local instance: agent step (dots, dormant pill, name placeholder), model step (no badges/eyebrow/picker, "Advanced settings"), review (pill alive, new copy, no checklist). - The retargeted role test asserts the hire payload carries `role: "general"` and the typed name — it is the test that catches the silent failure below. ## Risks - **A latent silent failure, now closed.** `handleGiveHeartbeat` returns early when `agentRole` is empty. With the picker removed and no default, Connect would have hired nobody and shown no error. The default closes it; the guard stays for any future path that clears the role. - **Behavioral change:** every onboarding hire is filed as `general` rather than a chosen role. The role remains editable in the app. - **Behavioral change:** the model is no longer chosen during onboarding. Every adapter offered here resolves its own default in `buildAdapterConfig`, and the model is changeable later. - **Assets:** the pill carries its own gradient fills and does not follow the theme. That is deliberate — the agent looks like itself on either ground. ## Model Used Claude Opus 5 (`claude-opus-5`) via Claude Code, with tool use and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal Paperclip ticket id - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
24d639abad |
feat(daytona): add transparent zstd-3 compression to the file-mapping upload path (#12271)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Sandbox providers transfer files between the host and an agent sandbox > - The Daytona file-mapping upload path sends staged tar files without compression > - Large raw uploads use more transfer bandwidth and storage > - This pull request adds transparent zstd-3 compression for eligible inbound file mappings > - The benefit is lower transfer size without changes for callers or post-upload commands ## Linked Issues or Issue Description **Subsystem affected** The change affects `packages/plugins`, in the Daytona sandbox provider. **Problem or motivation** The Daytona file-mapping upload path sends eligible staged tar files without compression. This increases transfer size and storage use. **Proposed solution** Compress eligible files on the host with zstd level 3. Upload the compressed bytes to a confined remote scratch path. Decompress them during the existing promote command, then promote the raw file. Use the raw upload path when compression cannot run or does not reduce size enough. **Alternatives considered** Keep the raw path for all uploads. This avoids compression work but does not reduce transfer size. Add a new sandbox round trip for decompression. This adds latency, so the change uses the existing promote round trip. **Roadmap alignment** `ROADMAP.md` lists Daytona under cloud and sandbox agents. This focused plugin change does not duplicate a planned core feature. **Additional context** The directory-mapping flow stays on the raw path. Callers and post-upload commands keep the same behavior. ## What Changed - Add transparent zstd-3 compression to `syncInFileMappings`. - Upload compressed artifacts to confined remote scratch paths and decompress them during promotion. - Keep the raw upload fallback when zstd is absent, compression fails, or the compressed result does not reduce size enough. - Create the raw scratch file once with atomic exclusive no-clobber open and write through the retained descriptor. - Stage compressed host artifacts in private `0700` directories with `0600` files. - Remove temporary directories on success and failure. - Add regression tests for compressed uploads, fallbacks, decompression failures, and cleanup. ## Verification - `pnpm --dir packages/plugins/sandbox-providers/daytona test` passes with 20 tests. - The compressed success path produces a byte-identical remote file. - A target without zstd uses the raw upload path. - A decompression failure does not promote a partial raw file. - Temporary files and directories do not remain after success or failure. - The newest cleanup regression test fails when the production cleanup fix is reverted and passes with the fix. ## Risks - Compression adds host CPU work for eligible file mappings. - The raw path remains available when compression is unavailable or ineffective. - Decompression runs during the existing promote command and can fail before promotion. - The change does not alter the directory-mapping flow or caller interface. ## Model Used OpenAI Codex, GPT-5, tool use and code execution enabled. The model assisted with repository review and pull request preparation. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes: #` / `Refs: #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
9c57c0f119 |
chore(lockfile): refresh pnpm-lock.yaml (#12252)
Auto-generated lockfile refresh after dependencies changed on master. This PR only updates pnpm-lock.yaml. Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com> |
||
|
|
e628cf35da |
fix(adapter-utils): harden the wrapper birth-time probe with exclusive create and identity-aware cleanup (#12248)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Adapter utilities run process sessions in local and remote environments. > - The remote process-session wrapper uses a probe file to verify directory creation time. > - A peer could pre-create the probe path or replace it before cleanup. > - This pull request uses exclusive create and file-descriptor identity checks to protect the probe. > - The benefit is safer cleanup and fail-closed behavior at the sandbox boundary. ## Linked Issues or Issue Description **What existing behavior does this improve?** The remote process-session wrapper creates and removes a birth-time probe file. The old path-based flow did not prove that the wrapper created the path or that the path still named the same file. **Current behavior** A sandbox peer can race with the probe path. The peer can pre-create a symbolic link or replace the probe before cleanup. The wrapper can then inspect or remove an object that it did not create. **Proposed behavior** The wrapper creates the probe with exclusive create. It reads `(dev, ino, ctimeMs)` from the open file descriptor. It removes the path only when a final identity read matches the created file. **Reason and benefit** This change prevents symlink-following during creation and avoids removal of a peer's replacement object. The wrapper still fails closed when it cannot prove a real creation time. **Breaking changes** None. The wrapper keeps its existing fail-closed capture behavior. ## What Changed - Create the birth-time probe with `fs.open(path, "wx")`. - Read probe identity with `fstat` from the open descriptor. - Remove the probe only after a matching final identity read. - Add focused race tests for ordinary cleanup and file, directory, and symbolic-link replacement. ## Verification - Run `pnpm --filter @paperclipai/adapter-utils exec tsc --noEmit`. - Run the focused suite `packages/adapter-utils/src/execution-target-stdin-race.test.ts`. - Confirm that the focused suite passes all 33 tests. ## Risks The change affects shared wrapper source for local and remote process sessions. An identity read or cleanup failure leaves the probe in place and stops capture. The focused tests cover the new race paths. ## Model Used OpenAI Codex, GPT-5, tool use and code execution. The model reviewed and prepared this pull request from the supplied implementation and test results. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
06cd21ed0f |
fix(observability): declare the optional OpenTelemetry peer dependencies (#12249)
## Thinking Path > - Paperclip manages AI agents for work. > - Paperclip includes an observability path that operators can enable for tracing. > - The server loads several OpenTelemetry packages only when tracing is enabled. > - The documentation calls these packages optional peer dependencies, but the server manifest does not declare them. > - This gap hides supported versions and stops Dependabot from maintaining the packages. > - This pull request aligns package metadata, runtime checks, and documentation with the opt-in tracing design. > - The change gives operators clear installation behavior and keeps the no-op default. ## Linked Issues or Issue Description This pull request fixes a package metadata and installation defect. Related observability work appears in [#8476](https://github.com/paperclipai/paperclip/pull/8476) and [#9672](https://github.com/paperclipai/paperclip/pull/9672). The server documentation described optional OpenTelemetry peer dependencies, but `server/package.json` did not declare them. Package managers and Dependabot could not see the supported version ranges. The UI and Claude local adapter also relied on automatic peer installation for `yjs` and `@anthropic-ai/sdk`. The package manifests now declare the optional runtime packages. A default install does not install optional tracing peers. The server keeps its no-op behavior when tracing is disabled or a peer is absent. ## What Changed - Add seven optional OpenTelemetry packages to `server/package.json` and mark each package as optional. - Keep `@opentelemetry/api` as a normal dependency for the no-op interface. - Disable automatic peer installation in `.npmrc`. - Declare `yjs` for the UI package and `@anthropic-ai/sdk` for the Claude local adapter. - Check declared peer versions before the server loads a dynamic OpenTelemetry import. - Keep the endpoint gate, dynamic imports, and fail-open behavior unchanged. - Update the observability and README documentation. - Tell Dependabot that its npm parser does not read `peerDependencies`. ## Verification - Targeted server tests pass: 34 passed and 2 skipped. - The skipped tests require the real OpenTelemetry SDK and remain pre-existing. - The pull request workflow regenerates the lockfile because manifest files and `.npmrc` changed. - The policy job confirms that the pull request does not include `pnpm-lock.yaml`. - GitHub checks pass except `security/snyk (cryppadotta)`, which remains pending after its authorized wait cap. - Greptile Review reports 5/5 with no open findings. - Server typecheck passes. ## Risks - Optional peers can produce a diagnostic when the installed version does not match the declared range. - A missing optional peer does not stop the server. - Disabling automatic peer installation can expose undeclared package use in other workspaces. - This pull request declares the affected packages and adds tests for the changed behavior. - This pull request makes no database or API changes. ## Model Used OpenAI Codex, GPT-5, with repository inspection and pull request preparation. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with Fixes / Closes / Refs OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal Paperclip ticket id - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
4277ecbb2e |
fix(adapter-utils): terminate the remote process-session wrapper deterministically on bridge stop (#12244)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Adapter utilities run remote process-session wrappers for sandbox work. > - A wrapper can outlive its host run when the host removes its session directory during shutdown. > - A failed directory read can look like an empty queue, so the wrapper can poll forever. > - This pull request adds an explicit shutdown acknowledgement and fail-closed identity checks. > - The benefit is deterministic wrapper cleanup without killing an unrelated session. ## Linked Issues or Issue Description Refs: #11916 **What happened?** Remote process-session wrappers could remain after a host run ended. The host could remove the session directory before the wrapper read the shutdown marker. The wrapper then treated directory errors as an empty queue and continued to poll. **Expected behavior** The host must receive an explicit shutdown acknowledgement before it treats the wrapper as stopped. The wrapper must stop when its session identity becomes invalid or untrusted. **Steps to reproduce** 1. Start a remote process-session wrapper. 2. Stop the bridge while the wrapper polls its session directory. 3. Remove the session directory during the poll. 4. Observe that the wrapper must terminate with its child. **Paperclip version or commit** `7cfbd1ecbe4a40261ba51fed07f624524352ada2` **Deployment mode** Built from source with the adapter-utils test suite. ## What Changed - Add a shutdown control file and wait for a bounded `shutdownAck` before session cleanup. - Require `shutdownAck` as proof of host-side shutdown. - Capture and verify session and stdin directory identity before each poll. - Terminate and latch the wrapper on missing, changed, linked, non-directory, or untrusted paths. - Reject unusable creation times and treat all identity-check `lstat` errors as terminal. - Add focused regression coverage for shutdown races and identity failures. ## Verification - `npx vitest run packages/adapter-utils/src/execution-target-stdin-race.test.ts` passes. - The full execution-target set passes: 175 tests across three files. - The `packages/adapter-utils` typecheck passes with `tsc --noEmit`. - CI will run on this pull request. - Greptile will review the pull request. ## Risks - A platform with unreliable directory creation times can stop a wrapper earlier than before. This fail-closed result prevents an orphan. - A transient identity-check error now stops the wrapper. This favors cleanup over continued polling when the session identity cannot be trusted. - Session cleanup remains unconditional after the bounded acknowledgement wait. ## Model Used OpenAI Codex — GPT-5. Context window size is not exposed in this run. The model used tool calls and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
039a547962 |
fix(adapter-utils): make SSH env-lab fixture teardown deterministic (#12238)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent adapters use SSH environment fixtures to test process behavior
> - The SSH fixture detached its listener process from the test process
> - Teardown removed the fixture directory without stopping and awaiting
that listener
> - This pull request validates fixture state, stops the listener with
bounded escalation, and waits before directory removal
> - The benefit is deterministic test cleanup without orphan listeners
or unsafe signals
## Linked Issues or Issue Description
**What happened?**
The SSH environment fixture detached its listener process. Test teardown
removed the temporary fixture directory without stopping and awaiting
the listener. Repeated test runs left orphan listeners that held
loopback ports.
**Expected behavior**
The fixture teardown stops its listener, waits for exit, and then
removes the fixture directory. A forged state file must not signal an
unrelated process.
**Steps to reproduce**
1. Run the SSH fixture test repeatedly.
2. Inspect listener processes after each run.
3. Observe orphan listeners or ports that remain held.
**Paperclip version or commit**
Commit
canary/v2026.826.0-canary.6
|
||
|
|
75b6d22aac |
fix(recovery): make silent-run detection UI-only (#12242)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The recovery service detects active runs that stop producing output. > - The dashboard already shows suspicious and critical silence to the board. > - The recovery scan also creates delegated evaluation work for the same signal. > - Output silence alone does not prove that the run or source task needs recovery. > - This pull request keeps the signal and removes automatic recovery artifacts. > - The benefit is a visible watchdog signal without assignment changes, wake requests, or issue noise. ## Linked Issues or Issue Description - Refs #6596 - Refs #7036 - Refs #9475 - Refs #11544 - Refs #11839 - Refs #11961 ## What Changed - Keep the one-hour suspicious level and four-hour critical level in active-run API summaries. - Stop output silence from creating or changing issues, recovery actions, comments, relations, assignments, and wake requests. - Store snooze, continue, and false-positive decisions against the run without an evaluation issue. - Preserve terminal-source folding, orphan cleanup, and open legacy evaluation links. - Show informational watchdog copy and board controls without requiring an evaluation-task link. - Document the UI-only watchdog contract. - Add focused server and UI coverage for artifact-free scans and board decisions. ## Verification - `pnpm -r typecheck` - `pnpm exec vitest run server/src/__tests__/heartbeat-active-run-output-watchdog.test.ts ui/src/components/IssueRunLedger.test.tsx` (32 tests passed) - `pnpm build` - `pnpm check:token-gates` - `git diff --check` - `pnpm test:run` completed locally with 4,772 passing tests. It found 30 unrelated macOS test-harness failures in eight workspace, skill, listener, and runtime exposure files. The failures use `/tmp` and `/private/tmp` as different paths, require Linux `/proc` listener data, or derive invalid HMR ports from the macOS ephemeral range. - The full Linux CI matrix passed on the latest commit. It includes build, typecheck, server tests, worker tests, serialization tests, canary, and e2e tests. - Greptile reviewed the latest commit at 5/5 with no actionable findings. ## Risks - The recovery scan keeps its existing result shape, but its created and escalated counts remain zero for output silence. - A false-positive decision now suppresses the signal for the full life of that run. - Open legacy evaluation issues remain visible and manually resolvable. The scan does not refresh or reprioritize them. - There is no database migration and no API schema change. > I checked `ROADMAP.md`. This change corrects existing watchdog behavior and does not duplicate planned core work. ## Model Used - OpenAI Codex, GPT-5, with extended reasoning, tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and the focused tests and non-platform gates pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.826.0-canary.5 |
||
|
|
381b763846 |
chore(lockfile): refresh pnpm-lock.yaml (#12232)
Auto-generated lockfile refresh after dependencies changed on master. This PR only updates pnpm-lock.yaml. Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com> |
||
|
|
8f1e3cfe24 |
feat(observability): add opt-in Sentry error monitoring for the server and the browser (#12190)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The server and the browser need clear error reports when an operator enables external monitoring. > - Paperclip already uses an opt-in OpenTelemetry pattern for server traces. > - Sentry can provide error reports for both runtime paths when the operator sets one data source name. > - This pull request adds one opt-in Sentry gate for the server and the browser. > - The benefit is faster diagnosis while the default setup sends no Sentry data. ## Linked Issues or Issue Description **What is improved?** Paperclip gains optional error monitoring for server and browser failures. **Subsystem affected** Cross-cutting (server, UI, and shared authentication data). **Current behavior** Paperclip has no built-in Sentry error capture for server failures or browser boundary failures. Operators must inspect local logs and browser tools. **Proposed behavior** When the operator sets `SENTRY_DSN`, the server and authenticated browser use the same Sentry project. When the variable is absent, both paths stay inactive. The server loads Sentry dynamically and fails open when the optional package is absent. **Reason and benefit** Operators can inspect runtime errors in one Sentry project. The default setup remains local and sends no monitoring data. **Breaking changes** None when `SENTRY_DSN` remains unset. Authenticated session responses add the optional `sentryDsn` field. **Additional context** The implementation uses built-in Sentry privacy options. It disables default HTTP context and breadcrumb integrations and keeps `sendDefaultPii` false. ## What Changed - Add an opt-in server Sentry gate with dynamic package loading and fail-open behavior. - Add the Sentry data source name to the authenticated session response. - Add an authenticated browser Sentry gate and React error boundary capture. - Add tests for server, browser, route, and application error paths. - Document activation, installation, privacy settings, capture behavior, and operator controls. ## Verification - Run `npx vitest run server/src/__tests__/sentry.test.ts`. - Run `npx vitest run ui/src/lib/sentry.test.ts`. - Run `npx vitest run server/src/__tests__/auth-routes.test.ts server/src/__tests__/shutdown.test.ts`. - Confirm that the full continuous integration suite passes on this pull request. - Leave `SENTRY_DSN` unset and confirm that the server and browser gates stay inactive. - Set `SENTRY_DSN` and install the optional Sentry packages before a manual capture check. ## Risks The operator controls the Sentry project and accepts the data risk when the operator enables the feature. Error objects can contain messages, stacks, or cause chains with private values. The default configuration sends no data because the feature stays off without `SENTRY_DSN`. A missing optional server package does not stop server boot. ## Model Used OpenAI Codex, GPT-5, with tool use, repository inspection, GitHub CLI operations, and code review support. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.826.0-canary.4 |
||
|
|
8ef39febd7 |
refactor(db): drop the vendored postgres teardown patch (reverts #12227) (#12234)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - #12227 vendored a pnpm patch of the `postgres` driver to stop a teardown race (`nextWrite` firing after the socket is nulled) from crashing the process and failing green CI shards > - Maintainer call: carrying a vendored driver patch is not worth it for a CI flake — the patch adds a maintenance obligation on every future driver upgrade > - The race is an upstream bug in `postgres@3.4.9`; the plan is to wait for an upstream release that fixes it and bump the dependency instead > - This pull request reverts #12227 in full: the patch file, its `package.json` registration, and the regression test that exercised the patched behavior > - The benefit is an unmodified dependency graph; the known flake signature returns and is retried when it bites ## Linked Issues or Issue Description Reverts #12227. **What existing behavior does this improve?** Dependency hygiene: `postgres@3.4.9` is consumed unmodified again, with no `pnpm.patchedDependencies` entry to re-evaluate on every driver upgrade. **Current behavior** The repo carries `patches/postgres@3.4.9.patch` (null-socket guard in the driver's deferred write flush, plus an `execute()` refusal on socketless connections) and a regression test for it. **Proposed behavior** Plain upstream `postgres@3.4.9`. The teardown race stays an upstream bug: a green test shard can occasionally fail with `Vitest caught 1 unhandled error` and `TypeError: Cannot read properties of null (reading 'write')` at `Immediate.nextWrite`; the remedy is retrying the shard until an upstream driver release fixes the race and we bump. **Reason and benefit** A vendored driver patch is a standing maintenance cost that outweighs the flake it suppressed. ## What Changed - Reverts #12227 (`6c7c0fd1f`) in full: removes `patches/postgres@3.4.9.patch`, its `pnpm.patchedDependencies` registration in root `package.json`, and `packages/db/src/postgres-driver-teardown.test.ts`. No lockfile involvement — the merged commit never touched `pnpm-lock.yaml` and the refresh bot had not yet recorded the patch. ## Verification - `pnpm install` on the reverted tree is coherent; the full `packages/db` suite passes (26 files / 100 tests). - `git revert` applied cleanly with no conflicts. ## Risks - Low. This restores the exact pre-#12227 state. The known flake signature returns; it fails jobs whose tests all passed and is cleared by retrying the shard. ## Model Used Claude Fable 5 (`claude-fable-5`, Anthropic) via Claude Code — agentic coding session with tool use. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
8ed1f51f75 |
fix(scripts): silence pnpm DEP0169 at provisioning install call sites (#12228)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Worktree provisioning prepares the dependencies and tools that these agents need. > - The pinned pnpm version calls the deprecated `url.parse()` function during each install. > - Node.js 24 reports this call as `DeprecationWarning [DEP0169]`. > - The provisioning scripts run more than one install, so the warning repeats in each run. > - This pull request disables only `DEP0169` at each affected pnpm install call site. > - The benefit is a clear provisioning log while other deprecation warnings remain visible. ## Linked Issues or Issue Description **What happened?** The worktree provisioning scripts printed `DeprecationWarning [DEP0169]` during each pnpm install. The warning came from pnpm 9.15.4 and its `toNerfDart` call to `url.parse()`. **Expected behavior** The provisioning scripts should hide this known warning from the pinned pnpm version. They should keep other deprecation warnings visible. **Steps to reproduce** 1. Use Node.js 24 with pnpm 9.15.4. 2. Run worktree provisioning with a base-workspace repair or dependency install. 3. Observe the repeated `DeprecationWarning [DEP0169]` output. **Paperclip version or commit** Commit `5cd41b1a9996713efdfdc62373da8045664c7f30`. **Deployment mode** Built from source. **Installation method** Built from source with pnpm. **Agent adapter(s) involved** Not adapter-specific (core bug). **Database mode** Not database-related. ## What Changed - Add `--disable-warning=DEP0169` to each affected pnpm install call site. - Append the flag to `NODE_OPTIONS` so the scripts keep existing values. - Add comments that name the source of the warning and the removal condition. - Add a regression test for all affected scripts and warning codes. ## Verification - `bash -n scripts/provision-worktree.sh` passes. - `bash -n scripts/provision-worktree-runtime.sh` passes. - `node --test scripts/__tests__/provision-worktree-self-heal.test.mjs` passes with 15 tests. - GitHub Actions must pass all required checks before merge. ## Risks This change has low risk. It changes warning output only for `DEP0169`. It does not overwrite existing `NODE_OPTIONS` values. Revert commit `5cd41b1a9996713efdfdc62373da8045664c7f30` to restore the prior output. ## Model Used OpenAI Codex, GPT-5. The model used tool calls and code execution. The runtime did not expose a context-window value. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes: #` / `Refs: #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.826.0-canary.3 |
||
|
|
6c7c0fd1f2 |
fix(db): stop the postgres driver from crashing the process on a write/close race (#12227)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - The server and its test suites talk to PostgreSQL through the
`postgres` (postgres.js) driver, and tests routinely tear their
databases down while connections still carry traffic
> - The driver flushes small buffered frames from a `setImmediate`, and
that deferred flush calls `socket.write()` without checking that the
socket still exists; a reserved connection whose backend died keeps
accepting queries, so the flush can fire with a null socket
> - The resulting `TypeError` escapes from a timer callback with no
try/catch above it, crashing the process — in CI this fails suites whose
tests all passed ("Vitest caught 1 unhandled error"), and the same crash
is reported against the driver in the wild after ECONNRESET
> - The latest driver release (3.4.9) still has the bug, so this pull
request adds a pnpm patch guarding the flush and normalizing timer state
on close, plus a deterministic regression test
> - The benefit is CI that no longer fails randomly on a teardown race,
and production processes that survive a database connection dying at the
wrong moment
## Linked Issues or Issue Description
No public issue exists; the underlying problem follows the bug-report
template.
**What happened?**
CI jobs fail with all tests passing: vitest reports `Vitest caught 1
unhandled error during the test run` with `TypeError: Cannot read
properties of null (reading 'write')` at `postgres/src/connection.js`
`Immediate.nextWrite`. The attribution points at whichever test file
happened to be running (e.g. `native-codex-runner.integration.test.ts`),
because the throw comes from a process-level timer callback, not from a
test. The identical crash is reported against the upstream driver by
other projects after `ECONNRESET` (e.g. immich-app/immich#25098).
**Expected behavior**
A connection dying between a write being scheduled and its deferred
flush must settle the affected queries through the driver's normal
connection-error path, never throw from a bare timer callback.
**Steps to reproduce**
Run the new `packages/db/src/postgres-driver-teardown.test.ts` with the
patch removed: reserve a connection (`sql.reserve()` — the same surface
`sql.begin()` uses), destroy the backend socket, wait for the client to
process the close, then issue one query on the reserved connection. The
deferred flush fires one tick later with `socket === null` and crashes
the process with exactly the CI signature.
**Paperclip version or commit**
master `198fc8b28`, `postgres@3.4.9` (latest release; bug still present
on the driver's master branch).
## What Changed
- `patches/postgres@3.4.9.patch` (new, wired via
`pnpm.patchedDependencies`): `nextWrite` returns without writing when
`socket === null`, dropping the buffered bytes — the close path has
already settled every in-flight query, so those bytes have nowhere to
go. The `closed()` and `terminate()` handlers additionally reset
`nextWriteTimer`/`chunk` after `clearImmediate`, so a stale cleared
handle cannot silently block a future reconnect's first flush. All three
shipped builds (`src`, `cjs`, `cf`) get the identical change.
- `packages/db/src/postgres-driver-teardown.test.ts` (new):
deterministic reproduction against a minimal in-process fake wire server
(startup auth + an empty result for the `fetch_types` bootstrap).
Asserts the late query settles with `CONNECTION_DESTROYED` through
`sql.end()` instead of crashing the process.
## Verification
- The regression test fails against unpatched `postgres@3.4.9` with the
exact CI signature (verified by running the same scenario against an
unpatched checkout) and passes with the patch.
- Full `packages/db` suite: 27 files / 101 tests pass.
- Spot-checked server suites that exercise the database through the
patched driver.
## Risks
- Low. The behavioral change activates only in a state that previously
crashed the process (write flush with no socket). Dropping the buffered
bytes matches what the connection's close path already promised callers:
every in-flight query has been settled with a connection error.
- The timer/chunk reset in `closed()`/`terminate()` prevents a
theoretical stale-handle hang after reconnect; on the normal path both
were already reset by `nextWrite`.
- The patch pins to `postgres@3.4.9`; a future driver upgrade will
surface the patch for re-evaluation (pnpm fails loudly on version
mismatch), and the guard can be dropped if the fix lands upstream.
## Model Used
Claude Fable 5 (`claude-fable-5`, Anthropic) via Claude Code — agentic
coding session with tool use (driver source analysis, wire-protocol fake
server, local test execution).
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
canary/v2026.826.0-canary.2
|
||
|
|
198fc8b281 |
fix(adapter-utils): harden the referenced-project ignore scan (#12214)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent adapters stage referenced projects into controlled sandboxes
> - The ignore scan must preserve exact Git path bytes and fail closed
on unsafe input
> - Unbounded ignored-path data and raw diagnostics can harm resource
use or expose host details
> - This pull request adds exact path parsing, input bounds, fixed
failure categories, and saturation-only retry
> - The benefit is safer and more predictable referenced-project staging
## Linked Issues or Issue Description
**What happened?**
The referenced-project ignore scan trimmed NUL-delimited Git paths. It
also accepted a large ignored-path set and exposed raw failure details
through staging errors and warnings.
**Expected behavior**
The scan must preserve leading and trailing whitespace in Git paths. It
must reject oversized ignored-path data and expose only fixed failure
categories.
**Steps to reproduce**
1. Run the referenced-project ignore scan with paths that start or end
with whitespace.
2. Provide more than 10,000 ignored entries or more than 2 MiB of path
bytes.
3. Trigger a scan failure and inspect the reported reason.
**Paperclip version or commit**
|
||
|
|
a9d0927fe8 |
fix(adapters): restore Paperclip skill for legacy runners (#12225)
<!-- Write all pull request text in Simplified Technical English (ASD-STE100): short sentences, one instruction per sentence, simple approved vocabulary, and the active voice. --> ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Legacy local adapters run agents that use the Paperclip skill for the control-plane workflow. > - PR #7029 removed the required-skill fallback and made runtime skill selection depend only on stored preferences. > - No migration or runtime fallback replaced that behavior for existing agents or non-CEO agents. > - PR #12138 added core skills to new CEOs, and PR #12147 added Claude skill discovery. These changes did not mount the operational skill for all legacy agents. > - This pull request makes the operational skill a legacy adapter runtime invariant. It keeps all other skills configurable. > - The native runner stays unchanged because its protocol supplies the control-plane contract. > - The benefit is that new and existing legacy agents can always operate through Paperclip. ## Linked Issues or Issue Description Refs #7029 Refs #12138 Refs #12147 **What happened?** A skill-capable legacy local agent could start without `paperclipai/paperclip/paperclip`. This happened when the agent had no stored skill preference. An explicit empty preference also removed the skill. The agent then reported that the Paperclip skill was not available. **Expected behavior** Every skill-capable legacy local adapter must mount the Paperclip operational skill when the runtime inventory contains it. Optional skills must remain configurable. The native runner must keep its current protocol-based behavior. **Steps to reproduce** 1. Create a non-CEO `codex_local` agent without `paperclipSkillSync` preferences. 2. Start a legacy heartbeat. 3. Inspect the managed `CODEX_HOME/skills` directory. 4. Observe that the Paperclip skill is absent before this change. **Paperclip version or commit** The problem reproduces on `master` before this pull request. PR #7029 introduced the configured-only selection behavior. **Deployment mode** Local development and self-hosted legacy local adapters. ## What Changed - Added a shared legacy skill resolver that always selects the canonical Paperclip operational skill when it is available. - Applied the resolver to direct adapter execution, ACPX execution, skill snapshots, and persistent skill sync. - Added Hermes skill materialization at sync and run boundaries. - Aligned Cursor, Gemini, and OpenCode execution-time injection with the configured child `HOME`. - Made Hermes stop execution when another installation blocks the required operational skill. - Kept optional skills controlled by `paperclipSkillSync.desiredSkills`. - Kept `paperclip_runner` on the configurable-only resolver. - Added regression coverage for missing preferences, empty preferences, each skill-capable legacy adapter, ACPX, Hermes, and native runner isolation. - Documented the legacy runtime invariant. ## Verification - `pnpm -r typecheck` passed on the pushed commit. - `pnpm build` passed on the pushed commit. - The adapter utility regression suites passed: 236 tests. - The changed server adapter suites passed: 48 tests across 12 files. - The OpenCode adapter suite passed: 8 tests. - The Hermes adapter suite passed: 7 tests. - `git diff --check` passed. - `pnpm test:run` is not clean on this macOS host. The command reported failures in unchanged workspace and filesystem suites. An isolated rerun of `company-skills.test.ts` and `company-skills-service.test.ts` reproduced 11 failures because macOS resolved `/var/...` paths as `/private/var/...`. The changed adapter suites pass independently. ## Risks - This change deliberately makes the operational skill non-removable for skill-capable legacy local adapters. - Existing agents receive the skill on their next list, sync, or run boundary. No database migration is required. - The resolver does not create a skill when the runtime inventory does not contain the canonical entry. - Hermes aborts a run if another installation occupies the required operational skill target. - Hermes removes only an undesired Paperclip-owned symlink that still points to the known Paperclip source. - The native runner does not receive the legacy default. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex based on GPT-5. The exact serving model ID and context window were not exposed. The agent used reasoning, tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
6524d2b67f |
fix(dev): honor --data-dir isolation (#12193)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The development runner starts the local API, UI, and embedded PostgreSQL services. > - Developers need separate data roots when they run more than one local checkout. > - The runner forwarded `--data-dir` to a child process that did not use it. > - The migration check and server therefore continued to use the default Paperclip home. > - This pull request applies the data root before worktree setup and migration checks. > - The benefit is an isolated database and state root for each requested development run. ## Linked Issues or Issue Description Refs #7466 ## What Changed - Parse and consume `--data-dir`, `--data-dir=<path>`, and `-d` in the development runner. - Set isolated default home, config, and context paths before worktree setup and migration checks. - Keep explicit config and context paths unchanged. - Include the normalized data root in the local service identity. - Let `dev:list` and `dev:stop` select the matching isolated service registry. - Keep explicit option environments independent of ambient process instance values. - Add regression tests and development documentation. ## Verification - `PAPERCLIP_INSTANCE_ID=ambient-test-instance pnpm exec vitest run server/src/__tests__/dev-runner-options.test.ts` passes with 8 tests. - `pnpm --filter @paperclipai/server typecheck` passes. - `pnpm --filter @paperclipai/adapter-utils build` passes. - `pnpm -r typecheck` passes. - `pnpm build` passes. - `pnpm dev:list --data-dir ./tmp/dev-service-review-fixture` selects the isolated registry. - A live run of `pnpm dev --data-dir ./tmp/data-dir-pr-smoke` became healthy on port 3101 while another checkout used port 3100. - The live run used `./tmp/data-dir-pr-smoke/instances/default/db` on a separate PostgreSQL port. - The latest-head Linux CI matrix passes, including build, typecheck, canary, all general and serialized test shards, and all e2e shards. - `pnpm test:run` was attempted on macOS. Current `master` has unrelated workspace path failures because `/tmp` resolves to `/private/tmp`. The focused regression suite passes, and the full Linux matrix is green. ## Risks - Risk is low. The change only affects development runs that pass `--data-dir` and matching service-management commands. - Explicit `PAPERCLIP_CONFIG` and `PAPERCLIP_CONTEXT` values still take priority. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with `gpt-5.6-sol` produced this change. The run used tool-enabled reasoning and code execution. The runtime did not expose its context window size. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.826.0-canary.1 |
||
|
|
821573ede8 |
refactor(adapter-utils): extract the shared workspace-restore teardown factory (#12196)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agent adapters run workspace restore steps when an ACP run ends. > - Claude, Codex, and Gemini each kept a near-identical teardown closure. > - Duplicate closures require the same defect fix in three files. > - This pull request adds one shared workspace-restore teardown factory and keeps each adapter's message strings. > - The benefit is one tested restore-failure path with the same output and outcome for all three adapters. ## Linked Issues or Issue Description **What existing behavior does this improve?** The Claude, Codex, and Gemini ACP adapters restore the workspace during teardown and report restore failures with an allowlisted message. **Subsystem affected** `packages/adapters/` and `packages/adapter-utils/`. **Current behavior** Each adapter keeps a near-identical closure. The closure logs a start line, restores the workspace, classifies errors, and logs a fixed failure line. **Proposed behavior** A shared `createWorkspaceRestoreTeardown` factory owns the common steps. Each adapter passes its staged runtime, log sink, start line, and failure prefix. **Reason and benefit** The shared factory removes duplicate error handling. One tested implementation now preserves the existing output and outcome for all three adapters. **Breaking changes** None. The refactor preserves the emitted lines and returned outcomes. **Additional context** This pull request contains no public issue reference because no related public issue was found. ## What Changed - Add `createWorkspaceRestoreTeardown` to `packages/adapter-utils`. - Move the shared restore, classify, and allowlisted log flow into the factory. - Update the Claude, Codex, and Gemini ACP adapters to call the factory. - Add a table-driven test for all three message pairs. - Keep one end-to-end restore-failure regression test per adapter. ## Verification - `pnpm --filter @paperclipai/adapter-claude-local typecheck` - `pnpm --filter @paperclipai/adapter-codex-local typecheck` - `pnpm --filter @paperclipai/adapter-gemini-local typecheck` - `npx vitest run packages/adapter-utils/src/workspace-restore-teardown.test.ts` - `npx vitest run packages/adapter-utils/src/workspace-restore-merge.test.ts` - `npx vitest run packages/adapters/claude-local/src/server/acp.test.ts` - `npx vitest run packages/adapters/codex-local/src/server/acp.test.ts` - `npx vitest run packages/adapters/gemini-local/src/server/acp.test.ts` - Continuous integration must pass before merge, except for the known pre-existing failures listed in the handoff. ## Risks Low risk. This change moves shared code without changing behavior. The adapter-specific message strings remain unchanged. ## Model Used OpenAI GPT-5, exact model ID `gpt-5`, tool use and code review assistance. The context window size was not provided by the runtime. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
dc30dc4f34 |
fix(setup-token): pin the start guard to the served adapter (#12179)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Sandbox agents use adapter login routes to start authenticated sessions > - The setup-token start route accepted adapter types that later routes and cleanup did not serve > - This mismatch could create sessions that no route or reaper could reach > - The OpenAPI body schema and synchronous login capability defaults also differed from the enforced behavior > - This pull request pins the start guard to the served adapter, shares the adapter constant, aligns the schema, and exposes login capabilities early > - The benefit is consistent session access, cleanup, API documentation, and login UI behavior ## Linked Issues or Issue Description Refs: #11730 Refs: #11286 **Subsystem affected** Cross-cutting server and UI login behavior. **Problem or motivation** The setup-token start route accepted a non-served adapter type. Follow-up routes and the reaper only handled the served adapter. This could create an unreachable session that held its slot. The OpenAPI schema and early capability defaults also did not match the route behavior. **Proposed solution** Pin the start guard, follow-up key, and reaper filter to one exported served-adapter constant. Derive the OpenAPI body from the strict shared schema. Add the login capability projection to synchronous defaults. **Alternatives considered** Keep separate adapter constants and add another guard at each follow-up route. This would preserve duplicate sources of truth and leave future drift possible. **Roadmap alignment** This change supports the Cloud / Sandbox agents milestone in `ROADMAP.md`. ## What Changed - Reject a setup-token start request when its adapter type is not the served adapter. - Reuse one exported adapter constant for the start guard, follow-up key, and reaper filter. - Derive the company adapter login-sessions start body from the strict shared schema. - Add the `login` capability projection to the synchronous Claude and Codex adapter defaults. - Add regression coverage for the rejected non-served adapter request. ## Verification - The setup-token route suite passes, including the non-served adapter regression test. - The setup-token session-service suite passes. - The setup-token reaper suite passes. - The OpenAPI suite passes. - The server TypeScript check passes. - The UI TypeScript check passes. - GitHub Actions must confirm all required checks after pull request creation. ## Risks The start route now rejects adapter types that follow-up routes cannot serve. No database migration exists. Revert the one commit to roll back the change. ## Model Used OpenAI Codex, GPT-5, exact runtime model ID not exposed, large context window, reasoning, tool use, and code execution. The implementing engineer used AI assistance. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes: #` / `Refs: #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.826.0-canary.0 |
||
|
|
ca02d2463a |
fix(ui): keep the installed service worker fresh on parked tabs (#12198)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The web UI registers a service worker (`/sw.js`) that caches the app shell for an offline fallback. > - Browsers only re-fetch a worker script on navigation or a ~24h timer, and Paperclip is a parked-tab SPA: a tab can sit open for weeks without one navigation. > - An installed worker — and the shell it cached — can therefore keep serving an old bundle long after a deploy, and the server let `sw.js` inherit the generic 1h static TTL on top of that. > - This pull request adds explicit update checks (tab-visible + hourly), applies a discovered update with one reload while the tab is hidden, and serves `sw.js` with `Cache-Control: no-cache`. > - The benefit is that a deploy reaches every open tab within about an hour, instead of some tabs silently running stale UI indefinitely. ## Linked Issues or Issue Description Refs #11292 (the network-first `sw.js` fallback fix; this PR closes the delivery gap that can keep clients pinned on a pre-#11292 worker). **What happened?** A browser that had an older cache-first worker installed kept rendering a stale app shell — old feature set, old naming — while the server was verified to be running the current release. Nothing on the client checks for a new worker outside navigations, so a parked tab never picked up the fixed worker, and `sw.js` was served with a 1h cache TTL that further delayed update checks. **Expected behavior** Every open tab converges to the deployed bundle shortly after a release, without users unregistering workers in DevTools or hard-reloading. **Steps to reproduce** Install a build's service worker, deploy a newer build, and leave the tab parked (no navigation): the tab keeps running the old bundle indefinitely; the worker update check only happens if the user navigates, and even then a cached `sw.js` can answer it. ## What Changed - New `ui/src/lib/service-worker-updates.ts`: registers `/sw.js`, runs `registration.update()` when the tab becomes visible and on an hourly timer, and on `controllerchange` of a previously-controlled page applies the update with a single reload — only while the tab is hidden, so an update never yanks the page mid-session; a takeover while visible defers the reload to the next hidden transition. First-ever installs never reload. - `ui/src/main.tsx`: replaces the fire-and-forget `register()` with the new module. - New `server/src/static-ui-cache.ts` (`staticUiCacheControl`): `index.html` and `sw.js` are served `Cache-Control: no-cache`; other non-hashed statics keep the 1h default. `server/src/app.ts` uses it in the static middleware. ## Verification - `npx vitest run ui/src/lib/service-worker-updates.test.ts` — 8 tests: registration, hidden-takeover reload (once), deferred reload on visible takeover, no reload on first install, visibility-triggered and timer-triggered update checks, cleanup, no-container no-op. - `npx vitest run server/src/__tests__/static-ui-cache.test.ts` — 3 tests incl. the `sw.js.map` lookalike keeping the default TTL. - `tsc -b` (ui) and `tsc --noEmit` (server) clean; `pnpm check:tokens` clean. ## Risks - Behavioral shift: tabs now reload once, while hidden, after a deploy lands. Unsaved in-page state in a hidden tab is lost at that moment — the same exposure as a browser discarding a background tab, which SPAs must already tolerate. - Self-hosted behavior is otherwise unchanged: same worker script, same registration URL, one added conditional header. - Low risk on the server side: the header change only widens revalidation. ## Model Used Claude Fable 5 (`claude-fable-5`, Anthropic) via Claude Code — agentic coding session with tool use and extended thinking. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting mergecanary/v2026.825.0-canary.15 |
||
|
|
9c03443c48 |
feat: hideable company settings pages, with import floored on cloud-managed instances (#12199)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - The app can run self-hosted or as a cloud-managed instance, where a
hosting platform provisions the instance with its company already
materialized (the existing `isCloudManagedInstance()` predicate and
`cloud_managed` floors)
> - The company Import/Export surface lets an operator materialize whole
companies from an export bundle; on a cloud-managed instance this
bypasses the existing `cloud_managed` company-creation floor and
conflicts with platform-owned provisioning
> - Importing should be disabled on cloud-managed instances, while
export stays open as the data-portability escape hatch
> - This pull request floors every import route with 403
`code=cloud_managed` on cloud-managed instances and hides the Import UI
there, using the existing predicate and the established floor pattern
> - It also extends the operator-hidden settings registry with keys for
every top-level company settings page, so a hosting operator can hide
any of them with `PAPERCLIP_HIDDEN_SETTINGS` alone next time
> - The benefit is one consistent managed-instance policy: cloud-managed
instances cannot import companies, self-hosted installs keep the full
import surface unchanged
## Linked Issues or Issue Description
No public issue exists; the underlying problem follows the enhancement
template.
**What existing behavior does this improve?**
The company import surface (`/api/companies/import*`,
`/api/companies/:companyId/imports/*`) and its UI entry points on
cloud-managed instances.
**Subsystem affected**
Server routes (`server/src/routes/companies.ts`) and UI navigation/pages
(settings sidebar, settings tabs, org chart, `/company/import` route).
**Current behavior**
A cloud-managed instance floors direct company creation (`POST
/api/companies` answers 403 `cloud_managed`), but the import routes
still accept company bundles, so an import can materialize companies the
hosting platform did not provision. The UI offers Import entry points
that lead to a surface that is not available on cloud-managed instances.
**Proposed behavior**
On instances where `isCloudManagedInstance()` is true, every import
route answers 403 `code=cloud_managed` before auth and body work, and
the Import UI (sidebar entry, settings tab, org-chart button,
`/company/import` route) is hidden or redirected. Export remains fully
available. Self-hosted instances are unchanged.
**Reason and benefit**
Cloud-managed instances keep one consistent provisioning authority, and
users do not see an Import surface that dead-ends in a 403.
## What Changed
- `server/src/routes/companies.ts`: a router-level floor mounted at the
`/import` and `/:companyId/imports` prefixes. It covers the single-shot
upload, preview, job polling, chunked transfer
declare/part-upload/status/preview/apply, and the agent-safe per-company
import routes. It throws `forbidden(..., { code: "cloud_managed" })` on
cloud-managed instances, or `403 settings_operator_managed` when the
operator hides `company.import` — both before auth and body validation,
mirroring the company-creation floor.
- `packages/shared/src/settings-visibility.ts`: new
`HIDEABLE_COMPANY_PAGES` registry group — `company.members`,
`company.invites`, `company.secrets`, `company.export`, `company.import`
— with a `hidesCompanyPage` helper. The company General page stays
non-hideable (settings root). `company.import` floors its API; the other
keys are UI-visibility only, as documented in the registry, so
membership/invite/secret/export APIs stay live for agents.
- `ui/src/components/CloudManagedPageGate.tsx` (new): route gate that
redirects cloud-managed instances to `/company/settings`, modeled on
`HiddenSettingsPageGate`.
- `ui/src/App.tsx`: wraps the `company/import` route in
`CloudManagedPageGate`.
- `ui/src/components/CompanySettingsSidebar.tsx`,
`ui/src/components/access/CompanySettingsNav.tsx`,
`ui/src/pages/OrgChart.tsx`: hide the Import entry points when
`useCloudInstance()` reports a managed instance, and honor the new
`company.*` hidden-settings keys for every company page entry (sidebar
item, tab, org-chart buttons).
- `ui/src/App.tsx`: `HiddenSettingsPageGate` route gates for the members
(incl. the legacy access route), invites, secrets, export, and import
pages under their `company.*` keys.
- `docs/deploy/environment-variables.md`: documents the new keys and
their semantics; the CLI and board-operator guides note that import is
unavailable on cloud-managed instances.
- Tests: new `server/src/__tests__/company-import-cloud-floor.test.ts`
and `ui/src/components/CloudManagedPageGate.test.tsx`, registry cases in
`packages/shared/src/settings-visibility.test.ts`, plus cloud and
hidden-key cases in the sidebar, settings-nav, and org-chart suites.
## Verification
- TypeScript typechecks pass for every workspace package (`tsc` in
shared, server, ui; the runner's Rust leg needs a local cargo toolchain
and is covered by CI).
- `pnpm test` on this branch fails only in 9 files that also fail on a
clean `origin/master` checkout on the same machine
(environment-dependent suites: live-listener probes,
workspace/native-runtime spawns, skill materialization). Zero
branch-only failures against that baseline; every suite touched by this
change passes.
- `server/src/__tests__/company-import-cloud-floor.test.ts` asserts:
every import route answers 403 `cloud_managed` under the server-token
signal; the managed-config signal alone also floors; every import route
answers 403 `settings_operator_managed` when `company.import` is hidden;
hiding other company pages leaves import open; the floor applies before
auth and body validation; export stays open on cloud-managed instances;
self-hosted import preview and job polling still work.
- `packages/shared/src/settings-visibility.test.ts` covers the new
`company.*` keys and `hidesCompanyPage`.
- UI suites assert the Import tab, sidebar entry, and org-chart button
disappear on a cloud-managed instance while Export stays, that
`/company/import` redirects through the gate, and that the `company.*`
keys hide their sidebar entries and tabs.
## Risks
- Low risk for self-hosted installs: the floor is inert unless a cloud
signal (`PAPERCLIP_CLOUD_TENANT_SERVER_TOKEN` or
`PAPERCLIP_MANAGED_CONFIG`) is present, and the self-hosted paths are
regression-tested.
- On cloud-managed instances this is a deliberate behavioral removal:
import (including agent-driven safe imports and resumable transfers)
stops working the moment an instance runs this build. In-flight chunked
transfers on such instances cannot be applied afterward; they answer
403.
- CLI import commands against a cloud-managed instance now fail with the
`cloud_managed` error; the message names the reason.
- The new `company.*` keys change nothing unless an operator sets them:
`PAPERCLIP_HIDDEN_SETTINGS` unset keeps behavior identical, and older
images ignore unknown keys by design. The four non-import company keys
hide UI only; their APIs stay live, which the registry documents
explicitly.
## Model Used
Claude Fable 5 (`claude-fable-5`, Anthropic) via Claude Code — agentic
coding session with tool use (code search, editing, local test
execution).
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
|
||
|
|
a5c2add7be |
fix(adapter-utils): repair referenced-source ignore resolution type break and symlink descendant check (#12201)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Referenced projects are staged into run sandboxes, and a recent
change made each staging site resolve the project's Git-ignored paths
explicitly (`ignoreResolution` on `SandboxAdditionalSource`)
> - One test call site was left without the now-required property, so
`tsc` fails in adapter-utils and every Build/Typecheck CI job on master
is red (surfaced when the TypeScript 7 bump landed in the same window)
> - Separately, the new descendant check compares a logical caller path
against the physical toplevel git prints, so any symlinked path fails
ignore resolution spuriously — three of the suite's own tests fail on
macOS because temp dirs live under the `/var` → `/private/var` symlink
> - This pull request supplies the missing property at the test call
site and makes the descendant comparison symlink-safe via realpath on
both sides
> - The benefit is a green master again, plus referenced-project staging
that works from symlinked checkouts and temp directories
## Linked Issues or Issue Description
No public issue exists; the underlying problem follows the bug-report
template.
**What happened?**
`packages/adapter-utils` fails `tsc` on master:
`src/sandbox-managed-runtime.test.ts(2284,29): error TS2741: Property
'ignoreResolution' is missing in type '{ localPath: string; projectId:
string; }' but required in type 'SandboxAdditionalSource'.` Every
Build/Typecheck CI job is red. Independently,
`resolveReferencedSourceIgnore` returns `{ kind: "failed", reason:
"referenced project path is not a descendant of its own Git top level:
/var/... under /private/var/..." }` for any symlinked project path, and
three tests in the suite fail on macOS.
**Expected behavior**
Master typechecks. A referenced project whose path reaches git through a
symlink (macOS temp dirs, symlinked checkouts) resolves its ignore set
normally, and the descendant check still fails closed for genuinely
foreign paths.
**Steps to reproduce**
1. `pnpm --filter @paperclipai/adapter-utils exec tsc --noEmit` on
master — TS2741 at `sandbox-managed-runtime.test.ts:2284`.
2. On macOS: `pnpm vitest run
packages/adapter-utils/src/sandbox-managed-runtime.test.ts` — three
`resolveReferencedSourceIgnore` tests fail with the "not a descendant"
reason above.
**Paperclip version or commit**
master `29d12045f`.
## What Changed
- `sandbox-managed-runtime.test.ts:2284`: the one call site missing
`ignoreResolution` now passes `{ kind: "other" }`, matching every
sibling call site from the same change.
- `sandbox-managed-runtime.ts`: `resolveReferencedSourceIgnore` resolves
both the git toplevel and the caller's `localPath` through a new
`physicalPath` helper (realpath with a resolve fallback) before the
descendant comparison. Git prints physical toplevels, so both sides must
be physical; the fallback keeps the check failing closed when a path
vanishes mid-run.
## Verification
- `pnpm vitest run
packages/adapter-utils/src/sandbox-managed-runtime.test.ts` — 61/61 pass
on macOS (previously 58 passing, 3 failing, plus the typecheck break).
- `tsc --noEmit` in `packages/adapter-utils` is clean.
## Risks
- Low. The behavioral change is confined to path normalization before an
existing comparison; a realpath failure falls back to the prior string
comparison, so the fail-closed property is preserved.
## Model Used
Claude Fable 5 (`claude-fable-5`, Anthropic) via Claude Code — agentic
coding session with tool use (code search, editing, local test
execution).
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
|
||
|
|
29d12045f4 |
perf(gateway): remove the whole-body string round trip on the HTTP/2 send path (#12189)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Sandbox agents send callback requests through a generated gateway. > - The HTTP/2 callback path converts each full request body to a UTF-8 string. > - The same path converts that string back to a buffer before it sends the request. > - This pull request sends the body buffer directly to the HTTP/2 forwarder. > - The benefit is less copying and unchanged queue payload behavior. ## Linked Issues or Issue Description **What existing behavior does this improve?** The sandbox callback gateway HTTP/2 send path copies the full request body through a UTF-8 string before it sends the body. **Subsystem affected** The affected subsystem is `packages/adapter-utils`, which contains sandbox gateway and HTTP/2 adapter utilities. **Current behavior** The gateway reads the body into a buffer, converts the complete body to a UTF-8 string, and converts that string back to a buffer for the HTTP/2 path. The queue path stores the string payload. **Proposed behavior** The gateway keeps a byte reader for the HTTP/2 path. A thin text wrapper keeps the queue path behavior. The HTTP/2 path sends the original body buffer. **Reason and benefit** The extra conversions add work and memory use without changing the HTTP/2 body bytes. Direct buffer forwarding removes that work and preserves the size limit and reject behavior. **Breaking changes** None. The queue payload remains a string. The body size limit, content type check, and reject point remain unchanged. **Additional context** This change has no public issue link. The repository roadmap search found no duplicate planned work. The implementation also adds tests for non-ASCII JSON, malformed UTF-8, size limits, and queue payload shape. ## What Changed - Add `readBodyBytes(req)` for byte-preserving body reads. - Keep `readBody(req)` as a string wrapper for the queue path. - Send the byte buffer directly on the HTTP/2 path. - Add tests for byte identity, malformed UTF-8, size limits, and queue payload shape. ## Verification - `pnpm --filter @paperclip/adapter-utils test src/sandbox-callback-bridge.test.ts` passed with 51 tests. - `pnpm --filter @paperclip/adapter-utils exec tsc --noEmit` passed. - The tests spawn the generated gateway and the real host HTTP/2 bridge. - The tests verify byte identity, malformed UTF-8, pre-forward size rejection, queue file protection, and string queue payloads. - Full repository CI must pass before merge. ## Risks Low risk. The HTTP/2 path changes its internal body conversion only. The queue path keeps the prior string payload. The size limit and reject point stay unchanged. ## Model Used OpenAI Codex, GPT-5, tool use and code review assistance. The exact runtime context window is managed by the Codex service. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes: #` / `Refs: #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
0cedb45df3 |
build(deps-dev): bump typescript from 5.9.3 to 7.0.2 (#11880)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.9.3 to 7.0.2. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/microsoft/TypeScript/releases">typescript's releases</a>.</em></p> <blockquote> <h2>TypeScript 7.0.2</h2> <p><a href="https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/">https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/</a></p> <p>This tag was originally released at: <a href="https://github.com/microsoft/typescript-go/releases/tag/typescript%2Fv7.0.2">https://github.com/microsoft/typescript-go/releases/tag/typescript%2Fv7.0.2</a></p> <h2>TypeScript 6.0.3</h2> <p>For release notes, check out the <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-6-0/">release announcement blog post</a>.</p> <ul> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+6.0.0%22">fixed issues query for TypeScript 6.0.0 (Beta)</a>.</li> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+6.0.1%22">fixed issues query for TypeScript 6.0.1 (RC)</a>.</li> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+6.0.2%22">fixed issues query for TypeScript 6.0.2 (Stable)</a>.</li> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+6.0.3%22">fixed issues query for TypeScript 6.0.3 (Stable)</a>.</li> </ul> <p>Downloads are available on:</p> <ul> <li><a href="https://www.npmjs.com/package/typescript">npm</a></li> </ul> <h2>TypeScript 6.0</h2> <p>For release notes, check out the <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-6-0/">release announcement blog post</a>.</p> <ul> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+6.0.0%22">fixed issues query for TypeScript 6.0.0 (Beta)</a>.</li> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+6.0.1%22">fixed issues query for TypeScript 6.0.1 (RC)</a>.</li> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+6.0.2%22">fixed issues query for TypeScript 6.0.2 (Stable)</a>.</li> </ul> <p>Downloads are available on:</p> <ul> <li><a href="https://www.npmjs.com/package/typescript">npm</a></li> </ul> <h2>TypeScript 6.0.1 RC</h2> <p>For release notes, check out the <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-6-0-rc/">release announcement blog post</a>.</p> <ul> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+6.0.0%22">fixed issues query for TypeScript 6.0.0 (Beta)</a>.</li> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+6.0.1%22">fixed issues query for TypeScript 6.0.1 (RC)</a>.</li> </ul> <p>Downloads are available on:</p> <ul> <li><a href="https://www.npmjs.com/package/typescript">npm</a></li> </ul> <h2>TypeScript 6.0 Beta</h2> <p>For release notes, check out the <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-6-0-beta/">release announcement</a>.</p> <ul> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+6.0.0%22+is%3Aclosed+">fixed issues query for Typescript 6.0.0 (Beta)</a>.</li> </ul> <p>Downloads are available on:</p> <ul> <li><a href="https://www.npmjs.com/package/typescript">npm</a></li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/microsoft/TypeScript/commit/1e4744d68260a7cb91b62b12edc3f6a2187faaf1"><code>1e4744d</code></a> Merge branch 'main' into ts7-release</li> <li><a href="https://github.com/microsoft/TypeScript/commit/a5a219c3b5da0db4fa0ecf6c0b1f588c9af9c669"><code>a5a219c</code></a><code>microsoft/typescript-go#4558</code></li> <li><a href="https://github.com/microsoft/TypeScript/commit/ecfe30dce91368d52c9a49b6095bb0b673a238f8"><code>ecfe30d</code></a> Update status localization</li> <li><a href="https://github.com/microsoft/TypeScript/commit/5de25b5f8fec2ca35eadaed041f1f06d2e214895"><code>5de25b5</code></a> Hide executable name in TypeScript status</li> <li><a href="https://github.com/microsoft/TypeScript/commit/d7ce74a75da2b80e8201506a1599c06549432b93"><code>d7ce74a</code></a> Show bundled TypeScript version for packaged servers</li> <li><a href="https://github.com/microsoft/TypeScript/commit/29be66a607707f90d7a53103a4469bb3015a4d54"><code>29be66a</code></a> Correct TS 7 release version to 7.0.2</li> <li><a href="https://github.com/microsoft/TypeScript/commit/ed2bd1bfa4aac5211ce4bc58fcd1313c7eddc8ff"><code>ed2bd1b</code></a> Merge branch 'main' into ts7-release</li> <li><a href="https://github.com/microsoft/TypeScript/commit/887307575c58ea640dbeba3b4e8fdb6347cd3044"><code>8873075</code></a> Bump the github-actions group across 1 directory with 3 updates (microsoft/ty...</li> <li><a href="https://github.com/microsoft/TypeScript/commit/9427131ae2d4e230a90ee8a09daac4e75da3e311"><code>9427131</code></a> Set up stable / nightly extension split, other prep (microsoft/typescript-go#...</li> <li><a href="https://github.com/microsoft/TypeScript/commit/d4eaca5460a1f5f02a829e62706794b0a6fb903e"><code>d4eaca5</code></a><code>microsoft/typescript-go#4549</code></li> <li>Additional commits viewable in <a href="https://github.com/microsoft/TypeScript/compare/v5.9.3...v7.0.2">compare view</a></li> </ul> </details> <details> <summary>Maintainer changes</summary> <p>This version was pushed to npm by <a href="https://www.npmjs.com/~microsoft1es">microsoft1es</a>, a new releaser for typescript since your current version.</p> </details> <br /> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Priya Raman <priya@paperclip.ing> Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
802f2af154 |
refactor(adapter-utils): delete the dead duplex body-chunk protocol code (#12186)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The adapter utilities package provides transport code for sandbox agents > - The retired `duplex_v1` broker no longer produces or consumes body-chunk frames > - Dead protocol code remains in the host codec, gateway copy, bridge options, and tests > - This pull request removes that dead code and keeps the READY handshake unchanged > - The benefit is a smaller transport surface with fewer unused paths to maintain ## Linked Issues or Issue Description **What existing behavior does this improve?** This change improves the adapter utilities code that supports sandbox duplex readiness and frame handling. **Subsystem affected** `packages/adapter-utils/` — sandbox transport codecs, execution targets, and callback bridge tests. **Current behavior** The repository keeps body-chunk frame types, validators, a body spool, decoder limits, and tests after the `duplex_v1` broker removal. No live producer or consumer uses this code. **Proposed behavior** Remove the unused body-chunk protocol code and retain the READY handshake, its strict checks, and its size limits. **Reason and benefit** The removal reduces dead code and keeps the host and embedded gateway paths easier to inspect. It adds no new behavior. **Breaking changes** The removed frame types now decode as `unknown_type`. The live readiness gate already ignores those frames. The READY handshake stays byte-for-byte compatible. **Additional context** This cleanup follows [PR #12171](https://github.com/paperclipai/paperclip/pull/12171), which removed the duplex broker. ## What Changed - Remove `duplex-body-spool.ts` and its test. - Remove unused body-chunk frame types, validators, decoder code, vectors, and limits. - Remove the unused `reassembledBody` option and decoder limit environment entry. - Remove the embedded gateway decoder copy and the unused frame type map. - Keep the READY handshake and its existing boundary tests unchanged in behavior. ## Verification - `pnpm -F @paperclip/adapter-utils typecheck` passes. - The duplex frame codec test passes with 30 tests. - The sandbox execution-target test passes with 136 tests. - The sandbox callback bridge test passes with 46 tests. - CI must confirm all required checks after it starts. ## Risks Low risk. The change removes code only. The READY handshake, HTTP/2 body path, and byte-ledger path remain unchanged. ## Model Used OpenAI Codex, GPT-5, tool use and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
822e0aed93 |
fix(adapter-utils): move the workspace-restore merge lock to an instance-scoped root and surface restore failures on the run (#12187)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agent adapters restore sandbox work into project workspaces after a run > - The restore lock used the target workspace parent, which can reject writes > - The teardown then hid restore errors, so a run could report success with lost work > - This pull request moves the lock into an instance-scoped root and reports safe restore failure codes > - The benefit is reliable restore coordination and visible failure evidence without changing run success semantics ## Linked Issues or Issue Description Refs: #10914 ## What Changed - Move the workspace-restore merge lock into a private, instance-scoped root. - Derive the lock key from the canonical target path with SHA-256. - Resolve the lock root from the caller environment and reject unsafe root types. - Classify restore failures with three allowlisted codes. - Add the failure code to run result JSON without exposing a host path or process identifier. - Keep restore failure fail-open for the run exit code and run status. ## Verification - Run `npx vitest run packages/adapter-utils/src/workspace-restore-merge.test.ts`. - Run `npx vitest run packages/adapter-utils/src/acpx-engine/run-fault-matrix.test.ts`. - Run the four Codex credential suites. - Confirm the branch includes the current `master` commit and no manual lockfile edit. - Confirm all pull request checks and the Greptile review reach a terminal green state. ## Risks - The lock path changes for workspace restore and removes the sibling-directory fallback. - A misconfigured or inaccessible instance home can still stop lock setup. - Restore remains fail-open, so callers must inspect the result evidence when a restore fails. ## Model Used OpenAI GPT-5. The model used tool calls and code execution to validate and route an author-provided change. The implementing engineer authored the code. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes: #` / `Refs: #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
d866ff374e |
fix(adapter-utils): report real transferred bytes for project sync, git-history export, and workspace restore (#12180)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agent adapters move files between the host and sandbox during a run > - The sync transport reports transferred bytes, but some progress lines discard this value > - Discarded byte totals make large transfers display as `0.0 MB` > - This pull request passes the transport total to the affected progress lines > - The benefit is accurate transfer progress without changing file movement or confinement checks ## Linked Issues or Issue Description **What happened?** Three file-sync progress lines displayed `0.0 MB` when the transport moved data. The affected paths cover referenced-project staging, native git-history export, and native workspace restore. **Expected behavior** Each progress line should display the bytes that the sync transport transfers. A provider that reports zero bytes should preserve the known host-side value for inbound workspace sync. **Steps to reproduce** 1. Run a sandbox task that stages a referenced project. 2. Run a task that uses native git-history export or native workspace restore. 3. Inspect the file-sync progress lines during each transfer. **Paperclip version or commit** Commit `8062612baa20036a1defce8bbd683c038ba187d5`. **Deployment mode** Built from source with the adapter-utils Vitest suite. ## What Changed - Add a helper that sums valid `bytesTransferred` values from a `SandboxSyncResult`. - Use the transport total for referenced-project staging, native git-history export, and native workspace restore. - Preserve the caller count when referenced-project staging reports zero bytes. - Add tests for non-zero progress and the zero-byte fallback. ## Verification - Run `npx vitest run packages/adapter-utils/src/sandbox-managed-runtime.test.ts` from the repository root. - Run the TypeScript check for `packages/adapter-utils`. - Confirm that the new tests cover referenced-project staging, native workspace restore, native git-history export, and the zero-byte fallback. ## Risks This change affects progress reporting only. It does not change transferred files, transfer order, provider behavior, or confinement checks. ## Model Used OpenAI Codex, GPT-5, with tool use and code execution. The model reviewed and routed the author-provided change. The implementing engineer authored the code. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes: #` / `Refs: #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I have addressed all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
6880213de5 |
fix(adapter-utils): honor .gitignore for referenced-project staging (#12184)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Sandbox adapters stage project files before an agent starts. > - Referenced projects ignored Git-ignored paths and copied large local directories. > - This behavior increased staging time and disk use, and it differed from anchor workspaces. > - This pull request resolves Git-ignored paths once and shares that result across all referenced-project consumers. > - The benefit is smaller, faster, and consistent project staging. ## Linked Issues or Issue Description No public GitHub issue exists for this bug. **What happened?** Referenced-project staging copied Git-ignored paths, except for a fixed list of heavy directory names. A large repository therefore used much more time and disk space than the same repository in an anchor workspace. **Expected behavior** Referenced-project staging should exclude the same Git-ignored paths that the workspace staging path excludes. **Steps to reproduce** 1. Create a referenced project with a large Git-ignored directory. 2. Start a sandbox or SSH run that stages the referenced project. 3. Observe that the ignored directory enters the staged content. **Paperclip version or commit** Commit `9964b034bbff24e700c8eccf5a8b1fc3daa44bf2`. **Deployment mode** Built from source. ## What Changed - Resolve each referenced project's Git-ignored paths once before staging. - Carry the resolved paths as a required field on `SandboxAdditionalSource`. - Reuse the resolved paths in sandbox staging, SSH staging, and content-signature code. - Harden the read-only Git helper with a bounded process, a reduced environment, and disabled system and global configuration. - Fail closed on Git errors, timeouts, and invalid path relations. - Escape tar glob metacharacters in ignore-derived exclude entries. - Add and update unit tests for the resolver and its three consumers. ## Verification - `pnpm vitest run --config packages/adapter-utils/vitest.config.ts` passes 266 tests locally. - `pnpm exec tsc --noEmit -p packages/adapter-utils/tsconfig.json` passes locally. - CI must pass on this pull request. - Greptile must report 5/5 with no unresolved comments before merge. ## Risks - A Git error or timeout now prevents staging for the affected referenced project. - The resolver uses a bounded read-only Git process and fails closed by design. - The change stays inside `packages/adapter-utils` and does not change the database schema. ## Model Used Claude Sonnet 5 (Anthropic) assisted the implementation with code execution and tool use. The exact context window and reasoning mode are not recorded. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes: #` / `Refs: #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
9fc2f594ae |
feat(ui): dashboard banner for paused imported agents with Resume all (#12142)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Company import parks every imported agent as a safety default
> - The only surface that offered to activate them was the post-import
checklist, which is UI-only and gone after a reload or an expired import
job
> - A company whose agents are all paused looks broken: tasks sit still
and the dashboard gives no explanation or fix
> - This pull request adds a dashboard banner for import-paused agents
with a one-click Resume all, and a generic banner when every agent is
paused
> - The benefit is a durable, reload-proof place to understand and fix
the parked state
## Linked Issues or Issue Description
**What existing behavior does this improve?**
The company dashboard for a company whose agents are paused, in
particular after a company import.
**Subsystem affected**
Web UI — dashboard (`ui/src/pages/Dashboard.tsx`).
**Current behavior**
Imported agents arrive paused. The activation checklist on the import
page is the only activation surface and is lost on reload. The dashboard
shows paused counts in a metric card but no explanation and no action.
Tasks assigned to the paused agents never start.
**Proposed behavior**
When any agent carries the `import` pause reason, the dashboard shows a
warning banner ("N imported agents are paused and will not run") with a
**Resume all** action. It resumes each parked agent sequentially,
tolerates per-agent failures, and refreshes so the banner reflects
whatever remains paused. When no import pauses exist but every agent in
the company is paused, a generic all-paused banner links to the agents
page.
**Breaking changes**
None. Depends on the `import` pause reason introduced in #12140 (this
branch is stacked on it).
## What Changed
- New exported helper `derivePausedAgentBanner(agents)` deciding between
the imported banner, the all-paused banner, or none.
- Dashboard renders the banners via the shared `InlineBanner`, with a
sequential `agentsApi.resume` mutation for Resume all and query
invalidation for the agent list and dashboard stats.
## Verification
- `cd ui && npx vitest run src/pages/Dashboard.test.ts` — 4 tests pass
(no agents, imported preference, all-paused fallback, mixed-state null).
- `cd ui && pnpm run typecheck` — clean.
- Manual: import a company package with paused agents, open its
dashboard, click Resume all, and watch the banner clear as agents go
idle.
## Risks
- Low risk. Resume all reuses `POST /agents/:id/resume` with its
existing guards, sequentially, matching the import page's activation
checklist pattern. At current import sizes (tens of agents) this is
fast; a server-side bulk endpoint is the follow-up if imports grow to
hundreds of agents.
## Model Used
- Claude Fable 5 (`claude-fable-5`, Anthropic) with extended thinking
and tool use, via Claude Code.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
|
||
|
|
397de98193 |
feat(runner): add flagged Codex execution adapter (#12188)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The Paperclip Runner now has protocol, provider, tool, package, persistence, and hidden server boundaries. > - The server still cannot select that path for a real agent heartbeat. > - A new runtime must not change any existing direct adapter. > - An experimental runtime must fail closed when its rollout flag is off. > - This pull request adds one guarded Codex vertical slice through runnerd. > - The benefit is a production-built runner path that users cannot start by default. ## Linked Issues or Issue Description Refs #11962 Refs #12111 Refs #12169 Refs #12176 **Subsystem affected** Cross-cutting. The change affects the runner package, server orchestration, shared settings, and adapter configuration UI. **Problem or motivation** The hidden PRP coordinator cannot execute a real heartbeat. The application also needs an explicit rollout boundary before it can expose the experimental runner. Existing direct adapters must keep their current execution and finalization behavior. **Proposed solution** Add `paperclip_runner` as a Codex-only adapter behind the default-off `enableNativeRunner` instance flag. Select the native runtime only for that adapter. Persist the run binding before runnerd starts. Wait for the durable PRP result and terminal event. Resume the real Codex provider thread on later heartbeats. Keep persisted native runs readable and recoverable after the flag changes. **Alternatives considered** The server could route `codex_local` through runnerd. That option would change an existing adapter and weaken rollback safety. The server could expose all providers now. That option would add unreviewed provider behavior. The build could depend on a prebuilt runner binary. That option would make source builds architecture-dependent and difficult to verify. **Roadmap alignment** This work supports the shipped enforced-outcomes, governed-tool, and self-healing-run milestones. It does not add a new roadmap surface. It is the guarded execution step after the merged hidden runner boundaries. **Additional context** This is the next replacement for the closed large runner pull request. Task-thread presentation remains a separate follow-up so this change can preserve the current direct-adapter UI. ## What Changed - Add `paperclip_runner` as an explicit Codex-only adapter. - Add the default-off `enableNativeRunner` instance flag. - Reject fresh create, hire, import, switch, and execution requests while the flag is off. - Allow edits to persisted runner agents while the flag is off. - Recover an already persisted native run even after the flag is disabled. - Keep every built-in direct adapter on its existing runtime path. - Persist an immutable native run binding and revisioned completion contract before runnerd starts. - Execute server to PRP to runnerd to Codex to server through the hidden coordinator. - Validate the durable result against the terminal event and exact completion criteria before finalization. - Preserve the Codex provider thread ID and use `thread/resume` on the next heartbeat. - Strip unsupported Codex configuration fields from the experimental adapter. - Build a target-native release runner binary from source and vendor it into the server distribution. - Install Rust only in the Docker build stage. Do not add a workflow or lockfile change. - Stop the runner process group on completion, cancellation, and forced shutdown. ## Verification - Run `pnpm --filter @paperclipai/paperclip-runner check:all`. All 69 TypeScript tests and 58 Rust tests pass. Protocol, conformance, replay, formatting, and generated-file checks pass. - Run the 12 focused adapter, settings, runtime-selection, coordinator, direct-isolation, and real Codex integration test files. All 186 tests pass. - The real integration test uses PostgreSQL, HTTP, WebSocket, runnerd, and a fake Codex app server. It proves one `thread/start` followed by one `thread/resume`. - Run `pnpm -r typecheck`. - Run `pnpm build`. - Run `pnpm check:token-gates`. - Build the Docker `build` target from a clean context. Confirm that the server distribution contains an executable `paperclip-runnerd` built with Debian Rust 1.85. - Start the server through the source-mode tsx entry point with the package `dist` directory absent. Confirm the vendor shim resolves source exports and the server boots. - Run `pnpm test:run` twice. On this macOS host, 405 files pass and 1 file skips. Eight untouched workspace and loopback tests fail because macOS resolves `/tmp` and `/var` through `/private` and because PID-derived test ports exceed 65535. Linux CI must pass the full suite. - Confirm that the diff contains 52 files. Confirm that it contains no `.github` or `pnpm-lock.yaml` change. ## Risks - The feature flag is off by default. A fresh native start fails with a stable error while the flag is off. - A persisted native run remains recoverable after the flag changes. This prevents rollout changes from corrupting recorded work. - Only local Codex execution is accepted. Other providers and remote work modes fail closed. - Existing direct adapters do not start runnerd, create native rows, use native status arbitration, or enter native finalization. - The runner receives its one-use bootstrap ticket through the child environment. The server does not put the ticket in command arguments or logs. - The server validates the company, task, agent, run, runner, session, completion contract, result, and terminal binding before it accepts completion. - The build compiles a target-native Rust binary. Cross-platform release packaging remains a later concern. Source builds and Docker builds compile for their current target. - Docker needs enough build memory for the existing server TypeScript compile. The Docker build stage sets a 4 GB V8 heap limit. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with GPT-5. The exact deployment ID and context-window size are not exposed. The model used agentic reasoning, repository tools, code execution, and test execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and applicable tests pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
243430f76e |
feat: agents see the company skill library at runtime (#12147)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - An agent's runtime mounts only its own enabled skills; nothing tells
the model what else the company skill library holds
> - From inside a sandbox, "installed but not enabled for me" and "does
not exist" look identical, so agents tell users freshly installed skills
are not installed
> - This pull request renders the library as a deterministic markdown
section appended to claude-local agent instructions, and adds a
paperclipListSkills MCP tool
> - The benefit is that agents report the true state ("installed, not
enabled for me — ask an operator to enable it") instead of a false
negative
## Linked Issues or Issue Description
**What existing behavior does this improve?**
How agents reason about the company skill library at runtime.
**Subsystem affected**
`packages/adapter-utils` (new pure builder),
`packages/adapters/claude-local` (instructions append),
`packages/mcp-server` (new tool).
**Current behavior**
The runtime hands adapters the full library list, but only the agent's
enabled skills are mounted, and no prompt content or MCP tool describes
the rest. Agents inspect their sandbox, find nothing, and report
installed skills as not installed.
**Proposed behavior**
A "Company skill library" markdown section lists every skill as
`enabled`, `installed, not enabled for you`, or `enabled but
unavailable: <cause>`, with instructions to report the not-enabled state
accurately and ask an operator to enable it. claude-local appends it to
the agent instructions text. A `paperclipListSkills` MCP tool exposes
the same list on demand.
**Breaking changes**
None. Other adapters are untouched (they can adopt the builder later);
the manifest is deterministic, so the claude-local prompt-bundle cache
only busts when the library actually changes.
## What Changed
- New `packages/adapter-utils/src/skill-library-manifest.ts` with
`buildSkillLibraryManifestMarkdown` (pure, key-sorted, deterministic;
renders the missing-cause detail from #12146).
- `packages/adapters/claude-local/src/server/execute.ts` appends the
manifest to `combinedInstructionsContents` (creating it when no
instructions file is configured).
- `packages/mcp-server/src/tools.ts` adds `paperclipListSkills` hitting
`GET /companies/:companyId/skills`.
## Verification
- `npx vitest run
packages/adapter-utils/src/skill-library-manifest.test.ts` (from repo
root) — 3 tests: byte-identical output for shuffled input, state
rendering incl. the unavailable cause, change detection.
- `cd packages/mcp-server && npx vitest run` — new tool routing test
passes (13 passed; 1 pre-existing failure on my machine reproduces
unchanged at the branch base).
- `cd packages/adapters/claude-local && npx vitest run` — 244 passed, 1
skipped.
- `pnpm run typecheck` clean in adapter-utils, mcp-server, claude-local.
## Risks
- Prompt growth is one line per installed skill plus a five-line header
— bounded and only present when the library is non-empty. Stacked on
#12146 so the manifest's "enabled but unavailable" state reflects real
materialization failures.
## Model Used
- Claude Fable 5 (`claude-fable-5`, Anthropic) with extended thinking
and tool use, via Claude Code.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
|
||
|
|
79b464bf9d |
fix(server): surface skill materialization failures instead of dropping the skill (#12146)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Runtime skill listing materializes each company skill's files before
handing them to the agent's adapter
> - A materialization failure was swallowed with catch-to-null, and the
skill silently vanished from the runtime while the library still showed
it installed
> - Operators saw "installed", agents saw nothing, and nobody saw the
cause; on claude-local a missing desired skill could even crash the
prompt-bundle hasher
> - This pull request turns both failure paths into structured "missing"
entries with the real error and makes every adapter skip unmountable
entries explicitly
> - The benefit is that a broken skill shows up as broken, with its
cause, instead of not existing
## Linked Issues or Issue Description
**What happened?**
A company skill whose runtime files fail to materialize (deleted source,
missing stored SKILL.md copy, failed version snapshot) disappears from
`listRuntimeSkillEntries` with no trace. Agent skill snapshots report a
generic "not available" with no cause. On claude-local, a desired skill
whose source path does not exist reaches the prompt-bundle hasher, whose
`fs.lstat` throws and can fail the whole run.
**Expected behavior**
The skill appears with `sourceStatus: "missing"` and a `missingDetail`
carrying the underlying error, snapshots and the UI show it as broken,
and adapters skip it at mount time with a logged warning instead of
crashing or dangling-symlinking.
**Steps to reproduce**
Install a local-path skill referenced by an agent, delete its source
directory contents so the stored SKILL.md copy cannot be recovered, and
start a run: before this change the skill vanishes from the runtime set
silently; on claude-local a pinned-but-unmaterializable version can fail
bundle preparation.
## What Changed
- `server/src/services/company-skills.ts` `resolveRuntimeSkillSource`:
both `.catch(() => null)` sites (version snapshot, runtime
materialization) now return the structured `{status: "missing", source,
detail}` shape the deliberate missing branch already used, with the
underlying error message in `detail`.
- `packages/adapter-utils/src/server-utils.ts`:
`isPaperclipSkillSourceMissing` is exported with a doc comment.
- `packages/adapters/claude-local/src/server/execute.ts`: missing
desired skills are filtered out of the prompt bundle and each one logs a
`[paperclip] Warning` with its detail to the run output.
- `cursor-local`, `gemini-local`, `kimi-local`, `opencode-local`,
`pi-local` `execute.ts`: mount loops (and the cursor/gemini injection
calls) skip missing entries instead of symlinking a nonexistent path.
## Verification
- `cd server && npx vitest run
src/__tests__/company-skills-service.test.ts` — new test pins the
missing-with-cause entry for a failed materialization. Nine pre-existing
project-workspace tests in this file fail on my machine at clean
`master` too (environment-specific); their count is unchanged by this
PR.
- `cd server && npx vitest run
src/__tests__/heartbeat-runtime-skills.test.ts
src/__tests__/claude-local-skill-sync.test.ts
src/__tests__/cursor-local-skill-sync.test.ts
src/__tests__/cursor-local-skill-injection.test.ts
src/__tests__/gemini-local-skill-sync.test.ts` — 12 tests pass.
- `cd packages/adapters/claude-local && npx vitest run` — 244 passed, 1
skipped.
- `pnpm run typecheck` clean in server, adapter-utils, and all six
touched adapters.
## Risks
- Runtime skill entry lists grow by the previously dropped entries (now
flagged missing). All shipped consumers either intersect with desired
sets, already handle `sourceStatus: "missing"`, or now skip missing
entries at mount time. The snapshot layer already understood the missing
shape via the `materializeMissing: false` path, so downstream contracts
are unchanged.
## Model Used
- Claude Fable 5 (`claude-fable-5`, Anthropic) with extended thinking
and tool use, via Claude Code.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
canary/v2026.825.0-canary.14
|
||
|
|
18b6c788d5 |
feat(server): de-duplicate imported company names (#12145)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Importing a company package as a new company takes the company name from the package manifest > - Repeat imports of the same package therefore create several identically named companies, distinguishable only by issue prefix > - Users cannot tell which import they are looking at, which feeds the "my import disappeared" loop of importing again > - This pull request suffixes manifest-derived names with " (2)", " (3)", … on collision, while honoring explicitly typed names verbatim > - The benefit is that every imported company has a recognizable name ## Linked Issues or Issue Description **What existing behavior does this improve?** Naming of companies created by the company package import. **Subsystem affected** Server — company import (`server/src/services/company-portability.ts`). **Current behavior** The new-company branch uses `newCompanyName ?? manifest name ?? "Imported Company"` with no de-duplication. Only the issue prefix is unique. Three imports of the same package yield three companies with the same name. **Proposed behavior** When the name comes from the manifest (no explicit `newCompanyName`), the import checks existing company names case-insensitively and appends the first free " (N)" suffix. Explicit names remain honored verbatim. Name exhaustion (thousands of collisions) falls back to the base name rather than failing the import, since names carry no uniqueness invariant. **Breaking changes** None. Only the default name of newly imported companies changes, and only on collision. ## What Changed - New exported pure helper `dedupeImportedCompanyName(baseName, existingNames)`. - The new-company branch resolves the name through it when no explicit name was provided, reading existing names via `companyService.list()`. ## Verification - `cd server && npx vitest run src/__tests__/company-portability.test.ts` — 87 tests pass (new: pure helper cases and two `importBundle` tests for the suffixed manifest name and the honored explicit name). - `cd server && npx vitest run src/__tests__/company-portability-routes.test.ts src/__tests__/company-portability-import-batching.test.ts` — 44 passed, 1 skipped (pre-existing skip). - `cd server && pnpm run typecheck` — clean. ## Risks - Low risk. The check-then-create has a theoretical race with a concurrent import, but names have no unique constraint — the worst case is today's behavior (a duplicate name). Issue-prefix uniqueness is untouched. ## Model Used - Claude Fable 5 (`claude-fable-5`, Anthropic) with extended thinking and tool use, via Claude Code. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
fcb84d472d |
feat: already-imported transfer error names the landed company (#12144)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Chunked company-import transfers are deduplicated by content: a
byte-identical zip that already finished an apply is rejected
> - The rejection said only "this exact package was already imported by
a completed transfer" without saying where that import went
> - Users who could not find the earlier import read the rejection as
data loss and kept retrying, or exported again and created duplicate
companies
> - This pull request makes the declaration response carry the company
the completed apply created, and both clients name it in the error
> - The benefit is that the dedupe rejection now points at the existing
import instead of implying it vanished
## Linked Issues or Issue Description
**What existing behavior does this improve?**
The `alreadyCompleted` rejection when re-declaring a chunked
company-import transfer.
**Subsystem affected**
Shared transfer contract
(`packages/shared/src/company-import-transfer.ts`), transfer declaration
route (`server/src/routes/companies.ts`), web import page, CLI import
command.
**Current behavior**
`POST /api/companies/import/transfers` returns `alreadyCompleted: true`
with no pointer to the earlier import. Web and CLI raise "This exact
package was already imported by a completed transfer. Re-export the
package to import it again."
**Proposed behavior**
The response includes an optional `company` field (`{id, name,
issuePrefix} | null`) resolved from the completed run's company link.
Web and CLI raise a shared message: `… It created the company
"Paperclip" (PAPA) — open it from the company switcher. Re-export the
package to import it again.` A company that was deleted since (or a link
that was never written) degrades to `null` and the original message.
**Breaking changes**
None. The new response field is optional; old clients ignore it.
## What Changed
- `CompanyImportTransferCreated` gains optional `company`, plus a shared
`buildAlreadyImportedMessage` used by both clients.
- The declaration route's `alreadyCompleted` branch resolves the landed
company null-safely via `companyService.getById`.
- Web (`ui/src/pages/CompanyImport.tsx`) and CLI
(`cli/src/commands/client/company.ts`) raise the shared message.
## Verification
- `cd packages/shared && npx vitest run
src/company-import-transfer.test.ts` — 3 tests (named company, id
fallback, no-company original message).
- `cd server && npx vitest run
src/__tests__/company-import-transfer-routes.test.ts` — 24 tests; the
re-declaration test now asserts the company payload and the
deleted-company null path.
- `cd cli && npx vitest run
src/__tests__/company-import-transfer.test.ts` — 17 tests; new test pins
the named-company message.
- `cd ui && npx vitest run src/pages/CompanyImport.test.tsx` — 23 tests.
- `pnpm run typecheck` clean in shared, server, ui, cli.
## Risks
- Low risk. The lookup runs only on the `alreadyCompleted` branch and is
null-safe; the transfer run is already scoped to the requesting actor
(user + instance context in the actor key), so the response never names
a company the caller did not import.
## Model Used
- Claude Fable 5 (`claude-fable-5`, Anthropic) with extended thinking
and tool use, via Claude Code.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
|
||
|
|
868e210a95 |
feat(ui): post-import landing CTAs on every outcome branch (#12143)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Company import ends on one of two success screens: the full outcome,
or a soft-success panel when the job's in-memory result expired before
it could be read
> - The soft-success panel named no company and offered no way in, and
the full outcome never said that paused agents stay resumable after
leaving the page
> - Users on the soft-success path concluded the import vanished and ran
it again, producing duplicate companies
> - This pull request gives every success branch a named landing with a
direct CTA into the new company and a pointer to the paused-agents
banner
> - The benefit is that a finished import always lands the user
somewhere actionable
## Linked Issues or Issue Description
**What existing behavior does this improve?**
The outcome screens of the company import page.
**Subsystem affected**
Web UI — company import (`ui/src/pages/CompanyImport.tsx`).
**Current behavior**
The expired-job branch renders two sentences ("the company has been
added — open it to view it") with no company name and no link. The
full-outcome screen shows the activation checklist but does not say the
checklist's resume actions remain available on the dashboard, so users
treat the page as their only chance.
**Proposed behavior**
The expired branch keeps the landed company's name and dashboard path
when readable, renders an "Open company dashboard" button, and notes
that imported agents arrive paused and can be resumed from the dashboard
banner. When the company is unreadable it gives explicit switcher
guidance instead. The full-outcome screen states that paused items stay
resumable from the dashboard.
**Breaking changes**
None. Pure UI copy/state additions to an existing page.
## What Changed
- The `expired` import outcome now carries `companyName` and
`dashboardPath`, captured from the already-fetched company in
`onSuccess`.
- The expired panel renders the company name, a dashboard CTA
(`data-testid="import-expired-open-company"`), the paused-agents
pointer, and a switcher fallback.
- The full-outcome screen adds a line noting the dashboard offers the
same resume actions as the activation checklist.
## Verification
- `cd ui && npx vitest run src/pages/CompanyImport.test.tsx` — 24 tests
pass; the soft-success test now asserts the name, pointer, and CTA, and
a new test covers the unreadable-company fallback.
- `cd ui && pnpm run typecheck` — clean.
## Risks
- Low risk. The dashboard pointer references the paused-agents banner
shipping in #12142; until that merges the sentence still points at the
dashboard, where paused agents are already visible in the metric card.
## Model Used
- Claude Fable 5 (`claude-fable-5`, Anthropic) with extended thinking
and tool use, via Claude Code.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
|
||
|
|
11f6c754c9 |
feat: dedicated import pause reason with visible paused-assignee notices (#12140)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Company import parks every imported agent as a safety default, and issue assignment wakes are dropped for paused agents > - The pause was recorded as the generic reason "system" and was almost invisible: the chat-style task thread showed nothing, the legacy notice had no action, and the new-task dialog gave no hint > - Users assigned tasks in an imported company, nothing ran, and there was no explanation — the imported company looked broken > - This pull request records a dedicated "import" pause reason and makes the paused state visible and fixable where the user is looking > - The benefit is that a silent no-op becomes an explained state with a one-click resume ## Linked Issues or Issue Description **What existing behavior does this improve?** Working with a company whose agents arrived paused from a company import. **Subsystem affected** Shared constants (`PAUSE_REASONS`), company import service (`server/src/services/company-portability.ts`), task thread and new-task dialog UI. **Current behavior** Imported agents get `pauseReason: "system"`, the same value plugin-managed and built-in agent pauses use. Assigning an issue to a paused agent silently drops the wake. The chat-style task thread renders no paused notice; the legacy thread's notice says "It was paused by the system." with no action and only renders when the composer is shown. **Proposed behavior** Import writes `pauseReason: "import"`. The paused-assignee notice explains the import pause, offers an inline "Resume agent" button (suppressed for budget pauses, which clear on their own), and renders for read-only viewers. The chat-style task thread shows the same notice above the composer. The new-task dialog warns when the selected assignee is paused. **Breaking changes** None. `PAUSE_REASONS` is widened, not changed; the column already stores free-text values in other paths, and every consumer is an equality check with a manual fallback, so an older client shows the generic fallback copy for the new value. ## What Changed - `packages/shared/src/constants.ts`: `"import"` added to `PAUSE_REASONS`. - `server/src/services/company-portability.ts`: the import pause patch writes `pauseReason: "import"`. - `ui/src/components/IssueChatThread.tsx`: `IssueAssigneePausedNotice` gains import copy, a Resume button, test ids, and is exported; it now renders even when the composer is hidden. New `onResumeAssignee` / `resumeAssigneePending` props. - `ui/src/components/TaskChatThread.tsx`: renders the paused-assignee notice above the composer dock (the chat-style thread previously had no paused surface at all). - `ui/src/pages/IssueDetail.tsx`: wires a resume mutation (`agentsApi.resume`) through both thread variants and invalidates the company agent list. - `ui/src/components/NewIssueDialog.tsx`: inline note when the chosen assignee is paused, with import-specific copy. ## Verification - `cd server && npx vitest run src/__tests__/company-portability.test.ts` — 82 tests pass (pause pin updated to `"import"`). - `cd ui && npx vitest run src/components/IssueChatThread.test.tsx src/components/NewIssueDialog.test.tsx src/components/TaskChatThread.test.tsx` — 120 tests pass (new: notice copy per reason, resume click, budget suppression, active-agent null render, dialog note). - `pnpm run typecheck` in `packages/shared`, `server`, and `ui` — clean. ## Risks - Low risk. The resume action calls the existing `POST /agents/:id/resume` route with its existing guards. Existing rows keep `"system"` and fall back to the current generic copy; only new imports write `"import"`. ## Model Used - Claude Fable 5 (`claude-fable-5`, Anthropic) with extended thinking and tool use, via Claude Code. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
5af49cb477 |
feat(server): CEO agents get the core paperclip skills by default (#12138)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Each agent's runtime only receives skills listed in its own
desired-skill set; the company library alone does nothing for an agent
> - Every CEO creation path (first-run wizard hire, New Agent
first-agent flow, cloud onboarding seed) creates the CEO with an empty
desired-skill set
> - The default CEO instructions tell the agent to use the core
paperclip skills, so a fresh CEO contradicts its own instructions and
reports its toolkit as "not installed"
> - This pull request unions the core skill keys into every
skills-capable CEO hire/create and into the onboarding-seeded CEO's
adapter config
> - The benefit is that a new CEO can actually do what its instructions
describe, and stops telling users that installed skills do not exist
## Linked Issues or Issue Description
**What existing behavior does this improve?**
Creating the first lead agent (role `ceo`) via hire, create, or the
cloud onboarding seed.
**Subsystem affected**
Server — agent hire/create routes (`server/src/routes/agents.ts`),
onboarding seed (`server/src/services/onboarding-seed.ts`), company
skills service constant (`server/src/services/company-skills.ts`).
**Current behavior**
A CEO created by the wizard, the New Agent page, or the onboarding seed
has no `paperclipSkillSync` block. Its runtime mounts zero skills. Its
default instructions (`server/src/onboarding-assets/ceo/AGENTS.md`,
`HEARTBEAT.md`) tell it to use `paperclip-create-agent`,
`para-memory-files`, and the paperclip coordination skill. The agent
then reports these skills as not installed.
**Proposed behavior**
When the new agent's role is `ceo` and its adapter supports skill sync,
the hire and create routes union the five bundled
`paperclipai/paperclip/*` skill keys into the requested desired-skill
set. The onboarding seed writes the same preference into the seeded
CEO's adapter config. Explicit requests win over defaults for the same
key. Non-CEO agents are unchanged. Any default stays removable through
`POST /agents/:id/skills/sync`.
**Breaking changes**
None. The default is additive, applies only to role `ceo` on
skills-capable adapters, and the bundled skills are guaranteed present
in every company library by `ensureSkillInventoryCurrent`.
## What Changed
- New exported constant `PAPERCLIP_CORE_SKILL_KEYS` in
`server/src/services/company-skills.ts` (the five bundled
`paperclipai/paperclip/*` keys).
- `defaultRoleSkillSelections` + `withDefaultRoleSkillSelections`
helpers in `server/src/routes/agents.ts`, applied in both the hire and
create routes before `resolveDesiredSkillAssignment(..., "add")`.
- `server/src/services/onboarding-seed.ts` builds the seeded CEO's
adapter config with `writePaperclipSkillSyncPreference` instead of `{}`
when the seeded adapter supports skills.
## Verification
- `cd server && npx vitest run
src/__tests__/agent-skills-routes.test.ts` — 32 tests pass (three new:
CEO default set, union with a requested skill, non-CEO untouched).
- `cd server && npx vitest run
src/__tests__/onboarding-seed-route.test.ts` — 14 tests pass (seeded CEO
adapter config assertion added).
- `cd server && npx vitest run
src/__tests__/agent-permissions-routes.test.ts` — 54 tests pass.
- `cd server && pnpm run typecheck` — clean.
## Risks
- Existing CEOs are not modified; only newly created ones get the
defaults. An operator who wants a minimal CEO can remove the skills
after creation with the skills sync (mode `remove`), and that removal
sticks. Adapters without skill support are skipped, so the change is
inert there.
## Model Used
- Claude Fable 5 (`claude-fable-5`, Anthropic) with extended thinking
and tool use, via Claude Code.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
|
||
|
|
d2b9765cc8 |
feat(ui): offer enabling a skill for agents at install time (#12136)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The company skill library lets operators install skills, and each agent has its own enabled-skill set > - Installing a skill only writes the library row; no agent receives the skill, and the UI says "Skill installed" with no attach step > - Operators install a skill, ask an agent to use it, and the agent truthfully reports the skill as not available — the install felt broken > - This pull request adds an "Enable for agents" step to the install dialog and enables the skill for the selected agents right after install > - The benefit is that "install" defaults to a state where agents can actually use the skill, and the toast is honest when they cannot ## Linked Issues or Issue Description **What existing behavior does this improve?** Installing a skill from the catalog in the company Skills page. **Subsystem affected** Web UI — company skills catalog install flow (`ui/src/pages/CompanySkills.tsx`). **Current behavior** Install writes a `company_skills` row and shows a "Skill installed" toast. No agent is enabled for the skill. Agents resolve their skills from their own desired-skill set, so they report the skill as not installed. The operator has to find the separate "Add to agent" control to make the install effective. **Proposed behavior** The install dialog shows an "Enable for agents" section for fresh installs. It pre-selects every agent whose adapter supports skills. After install, the page enables the skill for each selected agent (skills sync with mode `add`). The success toast reports how many agents received the skill, and warns when the skill is in the library with no agents enabled. **Breaking changes** None. Updates and replacements of an existing skill do not show the new section and behave as before. ## What Changed - `InstallPreviewDialog` gains an "Enable for agents" section (fresh installs only) built on the existing `AgentMultiSelect`, with agents whose adapter lacks skills support disabled. - New exported helper `defaultInstallAgentSelection` pre-selects every skills-capable, non-required agent. - The install mutation enables the skill for each selected agent via `agentsApi.syncSkills(..., "add")` before invalidating queries, and reports per-agent failures in a warning toast without failing the install. - Toast copy now distinguishes "enabled for N agents" from "in the library but not enabled for any agent yet". ## Verification - `cd ui && npx vitest run src/pages/CompanySkills.test.tsx` — 23 tests pass, including three new ones: default-selection helper, confirm payload carries the pre-selected agents, update/replace path skips the section. - `cd ui && pnpm run typecheck` — clean. - Manual: install a catalog skill with two agents in the company; both are pre-selected; after install the skill page lists both under "Used by agents". ## Risks - Low risk. Enablement uses the existing per-agent skills sync route with mode `add`, so concurrent edits to an agent's desired set are not overwritten. A per-agent sync failure surfaces as a warning toast and never fails the install itself. ## Model Used - Claude Fable 5 (`claude-fable-5`, Anthropic) with extended thinking and tool use, via Claude Code. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
3e28d64a72 |
fix(plugin-worker-manager): queue and replay pre-bind login pseudo-terminal frames (#12173)
## Thinking Path > - Paperclip routes plugin worker messages to agent sessions. > - The login pseudo-terminal route opens after the host receives the open reply. > - `readline` can deliver later frames from the same pipe read before that reply continuation runs. > - The host dropped early output and exit frames. > - The fix queues valid early frames, preserves arrival order, and replays them after the route opens. > - The route uses bounded memory and closes fail-closed when a bound breaks. > - The final tests also pin child issue ordering so the serialized suite remains deterministic. ## Linked Issues or Issue Description Fixes #12122 ## What Changed - Add a bounded queue for login pseudo-terminal output and exit frames during route opening. - Validate session ids, chunk types, and per-chunk limits before queue insertion. - Bound the queue by 10,000 frames and 8 MiB of characters. - Charge retained worker session identifiers against the character bound. - Preserve arrival order and stop replay after the first valid exit. - Drop repeated exits without changing the first exit position or code. - Bound the repeat-exit lookup and clear queued state on all terminal paths. - Add regression tests and fixture support for coalesced frames, ordering, limits, cleanup, and log safety. - Pin issue numbers in the child-wake test so its expected child order remains deterministic. ## Verification - Build the plugin SDK with `pnpm --filter @paperclipai/plugin-sdk build`. - Run `npx vitest run server/src/__tests__/plugin-worker-manager.test.ts` from the repository root. - Run `npx vitest run server/src/__tests__/issues-service.test.ts` from the repository root. - The focused plugin worker suite passes 66 of 66 tests at the prior reviewed head. - The issue service file passes 120 of 120 tests in two isolated runs at the current head. - Confirm that GitHub Actions passes all required checks. - Confirm that Greptile reports 5/5 with no unresolved review threads. - Storybook visual regression remains skipped because the PR has no `storybook-visual` label. ## Risks - The queue adds bounded memory use while the login pseudo-terminal route opens. - A queue limit breach closes the route and prevents unbounded buffering. - A hostile worker can fail only its own login route when it breaches a bound. - The first valid exit closes the route, so later records do not reach the session. - The child-wake test now uses distinct issue numbers to match the service sort contract. ## Model Used OpenAI Codex, GPT-5, extended reasoning, tool use, and code review support. The runtime does not expose a separate context-window value. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used with version and capability details - [x] I have checked ROADMAP.md and confirmed that this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have linked the existing public issue with `Fixes: #12122` - [x] I have not referenced internal Paperclip issues or links - [x] My branch name describes the change and contains no internal ticket id - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation where needed - [x] I have considered and documented risks above - [x] All required Paperclip CI gates are green - [x] Greptile is 5/5 with no unresolved review threads - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
1fc4591327 |
build(deps): bump commander from 13.1.0 to 15.0.0 (#11877)
Bumps [commander](https://github.com/tj/commander.js) from 13.1.0 to 15.0.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/tj/commander.js/releases">commander's releases</a>.</em></p> <blockquote> <h2>v15.0.0</h2> <p>Commander 15 is ESM only. This is expected to be seamless for ESM consumers, but some CommonJS consumers may hit issues with tooling requiring configuration for ESM-only dependencies. See Migration Tips below.</p> <p>The release of Commander 15 moves Commander 14 into maintenance. Commander 14 will get security updates for 12 months (to May 2027). For more info see <a href="https://github.com/tj/commander.js/blob/v15.0.0/docs/release-policy.md">Release Policy</a>.</p> <h3>Added</h3> <ul> <li>show excess command-arguments in error message (<a href="https://redirect.github.com/tj/commander.js/issues/2384">#2384</a>)</li> </ul> <h3>Fixed</h3> <ul> <li><em>Breaking:</em> only lone <code>--no-*</code> option sets default option value to <code>true</code>, default not implicitly set when define both positive and negative option in either order (<a href="https://redirect.github.com/tj/commander.js/issues/2405">#2405</a>)</li> <li>update example to use compatible character for MINGW64 (<a href="https://redirect.github.com/tj/commander.js/issues/2475">#2475</a>)</li> </ul> <h3>Changed</h3> <ul> <li><em>Breaking:</em> migrated Commander implementation from CommonJS to ESM (<a href="https://redirect.github.com/tj/commander.js/issues/2464">#2464</a>)</li> <li><em>Breaking:</em> Commander 15 requires Node.js v22.12.0 or higher (for <code>require(esm)</code>).</li> <li>dev: switch tests from Jest to <code>node:test</code> test runner (<a href="https://redirect.github.com/tj/commander.js/issues/2463">#2463</a>)</li> </ul> <h3>Deleted</h3> <ul> <li><em>Breaking:</em> removed deprecated export of <code>commander/esm.mjs</code> (<a href="https://redirect.github.com/tj/commander.js/issues/2464">#2464</a>)</li> </ul> <h3>Migration Tips</h3> <p>Commander 15 is ESM only, but this does not mean you need to migrate to ESM to use it. Importing ESM from CommonJS is supported by Node.js, and Bun, and Deno. Hopefully it Just Works for you! However, you may be using a different runtime or some other part of your setup that may not yet natively support importing ESM from CommonJS, such as your testing framework or bundler.</p> <p>If you have problems using Commander 15 in your environment, one option is stay on Commander 14 for now. Commander 14 will get security updates until May 2027 and things will hopefully improve for your setup in the meantime.</p> <h2>v15.0.0-0</h2> <p>Commander 15 is ESM only. This is expected to be seamless for ESM consumers, but some CommonJS consumers may hit issues with tooling requiring configuration for ESM-only dependencies. See Migration Tips below.</p> <p>The release of Commander 15 in May 2026 will move Commander 14 into maintenance. Commander 14 will get security updates for 12 months (to May 2027). For more info see <a href="https://github.com/tj/commander.js/blob/master/docs/release-policy.md">Release Policy</a>.</p> <h3>Added</h3> <ul> <li>show excess command-arguments in error message (<a href="https://redirect.github.com/tj/commander.js/issues/2384">#2384</a>)</li> </ul> <h3>Fixed</h3> <ul> <li><em>Breaking:</em> only lone <code>--no-*</code> option sets default option value to <code>true</code>, default not implicitly set when define both positive and negative option in either order (<a href="https://redirect.github.com/tj/commander.js/issues/2405">#2405</a>)</li> <li>update example to use compatible character for MINGW64 (<a href="https://redirect.github.com/tj/commander.js/issues/2475">#2475</a>)</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/tj/commander.js/blob/master/CHANGELOG.md">commander's changelog</a>.</em></p> <blockquote> <h2>[15.0.0] (2026-05-29)</h2> <p>Commander 15 is ESM only. This is expected to be seamless for ESM consumers, but some CommonJS consumers may hit issues with tooling requiring configuration for ESM-only dependencies. See Migration Tips below.</p> <p>The release of Commander 15 moves Commander 14 into maintenance. Commander 14 will get security updates for 12 months (to May 2027). For more info see <a href="https://github.com/tj/commander.js/blob/master/docs/release-policy.md">Release Policy</a>.</p> <h3>Added</h3> <ul> <li>show excess command-arguments in error message (<a href="https://redirect.github.com/tj/commander.js/issues/2384">#2384</a>)</li> </ul> <h3>Fixed</h3> <ul> <li><em>Breaking:</em> only lone <code>--no-*</code> option sets default option value to <code>true</code>, default not implicitly set when define both positive and negative option in either order (<a href="https://redirect.github.com/tj/commander.js/issues/2405">#2405</a>)</li> <li>update example to use compatible character for MINGW64 (<a href="https://redirect.github.com/tj/commander.js/issues/2475">#2475</a>)</li> </ul> <h3>Changed</h3> <ul> <li><em>Breaking:</em> migrated Commander implementation from CommonJS to ESM (<a href="https://redirect.github.com/tj/commander.js/issues/2464">#2464</a>)</li> <li><em>Breaking:</em> Commander 15 requires Node.js v22.12.0 or higher (for <code>require(esm)</code>).</li> <li>dev: switch tests from Jest to <code>node:test</code> test runner (<a href="https://redirect.github.com/tj/commander.js/issues/2463">#2463</a>)</li> </ul> <h3>Deleted</h3> <ul> <li><em>Breaking:</em> removed deprecated export of <code>commander/esm.mjs</code> (<a href="https://redirect.github.com/tj/commander.js/issues/2464">#2464</a>)</li> </ul> <h3>Migration Tips</h3> <p>Commander 15 is ESM only, but this does not mean you need to migrate to ESM to use it. Importing ESM from CommonJS is supported by Node.js, and Bun, and Deno. Hopefully it Just Works for you! However, you may be using a different runtime or some other part of your setup that may not yet natively support importing ESM from CommonJS, such as your testing framework or bundler.</p> <p>If you have problems using Commander 15 in your environment, one option is stay on Commander 14 for now. Commander 14 will get security updates until May 2027 and things will hopefully improve for your setup in the meantime.</p> <h2>[15.0.0-0] (2026-02-22)</h2> <p>(Released as 15.0.0)</p> <h2>[14.0.3] (2026-01-31)</h2> <h3>Added</h3> <ul> <li>Release Policy document (<a href="https://redirect.github.com/tj/commander.js/issues/2462">#2462</a>)</li> </ul> <h3>Changes</h3> <ul> <li>old major versions now supported for 12 months instead of just previous major version, to give predictable end-of-life date (<a href="https://redirect.github.com/tj/commander.js/issues/2462">#2462</a>)</li> <li>clarify typing for deprecated callback parameter to <code>.outputHelp()</code> (<a href="https://redirect.github.com/tj/commander.js/issues/2427">#2427</a>)</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/tj/commander.js/commit/ba6d13ddb4243e5913367734f8c159089ffe7834"><code>ba6d13d</code></a> Fix release dates in changelog (<a href="https://redirect.github.com/tj/commander.js/issues/2523">#2523</a>)</li> <li><a href="https://github.com/tj/commander.js/commit/a752ed909f179e3a5dcae31a890a89fb748473c4"><code>a752ed9</code></a> Pin GitHub actions with hash (<a href="https://redirect.github.com/tj/commander.js/issues/2521">#2521</a>)</li> <li><a href="https://github.com/tj/commander.js/commit/74d5dfe9b7e199d98e2269ecf88dcf771c260983"><code>74d5dfe</code></a> Drop EOL node 20 from test matrix, and add node 26 (<a href="https://redirect.github.com/tj/commander.js/issues/2520">#2520</a>)</li> <li><a href="https://github.com/tj/commander.js/commit/6df9b68b75ad8df1532ad3572e1d5a1c53bde6cd"><code>6df9b68</code></a> Update details for 15.0.0 release (<a href="https://redirect.github.com/tj/commander.js/issues/2519">#2519</a>)</li> <li><a href="https://github.com/tj/commander.js/commit/01ce5d0cd7e845d6ed749ab57616ec9c173cf91f"><code>01ce5d0</code></a> Remove jest esm examples (<a href="https://redirect.github.com/tj/commander.js/issues/2517">#2517</a>)</li> <li><a href="https://github.com/tj/commander.js/commit/d785d8b3b9448952ef023a8cd26a0a3923a90458"><code>d785d8b</code></a> Update dependencies (<a href="https://redirect.github.com/tj/commander.js/issues/2518">#2518</a>)</li> <li><a href="https://github.com/tj/commander.js/commit/9098b4863ef7678b9d138ae0f04afd949287510c"><code>9098b48</code></a> Update dependencies (<a href="https://redirect.github.com/tj/commander.js/issues/2506">#2506</a>)</li> <li><a href="https://github.com/tj/commander.js/commit/373f660f6febb720b82635220eea72dd9b7e0cba"><code>373f660</code></a> Use node:util stripVTControlCharacters instead of own code (<a href="https://redirect.github.com/tj/commander.js/issues/2486">#2486</a>)</li> <li><a href="https://github.com/tj/commander.js/commit/987f28966c71baecb0ef4a36780e727bcd575b31"><code>987f289</code></a> Use simple match in test (to avoid warning about expensive regex) (<a href="https://redirect.github.com/tj/commander.js/issues/2485">#2485</a>)</li> <li><a href="https://github.com/tj/commander.js/commit/0ea3bb3e883eaa909f1056d0d13a06cc31ec2c3c"><code>0ea3bb3</code></a> Update dependecies and lint (<a href="https://redirect.github.com/tj/commander.js/issues/2489">#2489</a>)</li> <li>Additional commits viewable in <a href="https://github.com/tj/commander.js/compare/v13.1.0...v15.0.0">compare view</a></li> </ul> </details> <br /> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
d9f759b7bc |
chore(lockfile): refresh pnpm-lock.yaml (#12178)
Add the missing server importer for @paperclipai/paperclip-runner. |
||
|
|
9964b034bb |
feat(runner): add hidden server PRP coordinator (#12176)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The Paperclip Runner needs a narrow server trust boundary before an adapter can start it. > - The package has durable runner transport, but the server does not host or authorize that transport. > - Native persistence exists, but no writer connects PRP events to those records. > - A direct adapter must not enter this path by accident. > - This pull request adds a hidden, run-bound PRP server coordinator. > - The benefit is a recoverable server boundary that remains unavailable to normal execution. ## Linked Issues or Issue Description Refs #11962 Refs #12129 Refs #12169 **Subsystem affected** Cross-cutting. The change affects the runner package and server orchestration. **Problem or motivation** The server cannot authenticate runnerd, commit PRP events before ACK, authorize semantic tools, or enter native finalization from a durable runner result. The application must have this hidden boundary before a guarded adapter can use the runner. **Proposed solution** Add an authenticated PRP WebSocket authority and register it only for one exact persisted native Codex run. Bind each connection and event to the company, issue, agent, run, runner, session, turn, item, and verified runner identity. Commit each event before its cumulative ACK. Project only authorized same-task read tools. Rebuild the accepted result and finalization record from durable result and terminal events. **Alternatives considered** The server could expose a broad runner API key or route semantic calls through existing adapter endpoints. Those options grant too much authority and weaken replay recovery. The server could also add the user-facing adapter in this pull request. That option would mix rollout selection with the transport trust boundary and make legacy compatibility harder to review. **Roadmap alignment** This work supports the shipped enforced-outcomes, governed-tool, and self-healing-run milestones. It does not add a new roadmap surface. ## What Changed - Add the durable PRP server authority with one-use bootstrap tickets, reconnect leases, encrypted frames, bounded state, cumulative ACKs, and idempotent commands. - Add `/api/runner/v1/connect/:runId`. Derive its `ws://` or `wss://` URL from the configured Paperclip API URL. - Register one authority only after the coordinator verifies the complete native Codex run binding. - Commit validated PRP events to `heartbeat_run_events` before ACK. Reject source gaps and conflicting replays. - Rebuild accepted results and finalization records from durable result and terminal events. Enforce finalization owner leases and retry times. - Project five same-task read operations. Recheck run, agent, task, and company authority for each call. - Keep the route hidden. No adapter selects this coordinator, and no code starts runnerd. - Vendor the compiled runner TypeScript runtime into the server package while keeping the workspace package development-only for the server. - Document the package, database writer, run-log payload, and credential exclusions. ## Verification - Run `pnpm --filter @paperclipai/paperclip-runner check:all`. All TypeScript protocol checks and 69 Vitest tests pass, including commit-before-ACK crash recovery. All 43 Rust unit tests and 13 Rust integration tests pass. Conformance and replay parity pass. - Run the focused server WebSocket, coordinator, package-build, and startup-wiring suites. All 26 tests pass, including a clean-checkout reproduction with the runner `dist` directory absent. - Run `pnpm -r typecheck`. - Run `pnpm test:run`. - Run `pnpm build`. - Confirm that the diff contains 19 files. Confirm that it contains no workflow or `pnpm-lock.yaml` change. ## Risks - The server installs the WebSocket route at startup. An unregistered or malformed run path fails closed and creates no native record. - Bootstrap tickets are one use. The private state directory uses mode `0700`, and the state file uses mode `0600`. The file stores derived authentication verifiers and never stores raw tickets or lease tokens. - The journal has explicit frame, command, event-window, and file-size bounds. A bound violation closes the runner connection or rejects the command. - A runner event reaches the database before its ACK. A crash between event commit and ACK causes a byte-equivalent replay, not a second logical effect. - The coordinator accepts only an existing queued or running native Codex row with exact company, task, agent, runner, session, and completion-contract ownership. - Existing direct adapters do not call this service. They keep their current execution, transcript, result, and finalization paths. - The server has no production dependency on the private runner package. Its build copies the compiled runtime into `server/dist`; the workspace link is development-only. This adds no external package and does not change the lockfile. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with GPT-5. The exact deployment ID and context-window size are not exposed. The model used agentic reasoning, repository tools, code execution, and test execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting mergecanary/v2026.825.0-canary.13 |
||
|
|
86fe9339e1 |
chore(lockfile): refresh pnpm-lock.yaml (#12174)
Auto-generated lockfile refresh after dependencies changed on master. This PR only updates pnpm-lock.yaml. Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com> |
||
|
|
69e8585146 |
build(deps): bump better-auth from 1.6.28 to 1.7.0 (#11886)
Bumps [better-auth](https://github.com/better-auth/better-auth/tree/HEAD/packages/better-auth) from 1.6.28 to 1.7.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/better-auth/better-auth/releases">better-auth's releases</a>.</em></p> <blockquote> <h2>v1.7.0</h2> <p><strong>Blog post:</strong> <a href="https://better-auth.com/blog/1-7">Better Auth 1.7</a></p> <h2><code>better-auth</code></h2> <h3>❗ Breaking Changes</h3> <ul> <li>Moved database joins out of <code>experimental</code> into the stable <code>advanced.database.joins</code> option (<a href="https://redirect.github.com/better-auth/better-auth/pull/10359">#10359</a>) <blockquote> <p><strong>Migration:</strong> Replace <code>experimental: { joins: true }</code> with <code>advanced: { database: { joins: true } }</code>. Drizzle and Prisma users should regenerate their schema (<code>npx auth@latest generate</code>) so it includes the required relations.</p> </blockquote> </li> <li>Scoped account identity by trusted issuer, keying accounts on <code>(issuer, accountId)</code> (<a href="https://redirect.github.com/better-auth/better-auth/pull/10403">#10403</a>) <blockquote> <p><strong>Migration:</strong> Accounts now require <code>Account.issuer</code>. Read provider identity from <code>accountInfo.account.accountId</code>, drop <code>mapping.id</code> from SSO configs, and give the <code>microsoftEntraId</code> helper a concrete tenant GUID. Apply the account-identity backfill in the 1.7 upgrade guide before deploying.</p> </blockquote> </li> <li>Required captcha endpoint entries to match full auth paths, with wildcard support (<a href="https://redirect.github.com/better-auth/better-auth/pull/10004">#10004</a>) <blockquote> <p><strong>Migration:</strong> Replace partial paths such as <code>/sign-in</code> with explicit wildcards like <code>/sign-in/*</code> or <code>/sign-in/**</code>.</p> </blockquote> </li> <li>Moved the MCP plugin into its own <code>@better-auth/mcp</code> package built on the OAuth provider (<a href="https://redirect.github.com/better-auth/better-auth/pull/9992">#9992</a>) <blockquote> <p><strong>Migration:</strong> Install <code>@better-auth/mcp</code> and <code>@better-auth/cimd</code>, add the now-required <code>jwt()</code> plugin, and move options nested under <code>oidcConfig</code> to flat <code>mcp({ ... })</code> options. Rename <code>withMcpAuth</code> to <code>requireMcpAuth</code> and <code>mcpHandler</code> to <code>createMcpProtectedRequestHandler</code>. Regenerate the schema (<code>npx auth migrate</code>): <code>oauthApplication</code> becomes <code>oauthClient</code>, plus new <code>oauthRefreshToken</code> and <code>oauthClientAssertion</code> tables.</p> </blockquote> </li> <li>Added OIDC back-channel logout so ending a session cuts off every connected app's API access (<a href="https://redirect.github.com/better-auth/better-auth/pull/9304">#9304</a>) <blockquote> <p><strong>Migration:</strong> Introspecting an access token whose session has ended now returns <code>{ active: false }</code>, and <code>/oauth2/userinfo</code> rejects it. Clients opt into notifications by registering <code>backchannel_logout_uri</code>. Run the schema migration for the new <code>oauthClient</code> and <code>oauthAccessToken</code> columns.</p> </blockquote> </li> <li>Modeled OAuth protected resources explicitly, with per-resource TTLs, scopes, claims, and signing pins (<a href="https://redirect.github.com/better-auth/better-auth/pull/9648">#9648</a>) <blockquote> <p><strong>Migration:</strong> <code>validAudiences</code> is removed: move each resource identifier into <code>resources</code> and link restricted clients through <code>oauthClientResource</code>. <code>@better-auth/mcp</code> now requires an explicit <code>resource</code>. Run <code>npx @better-auth/cli generate</code> and apply the migration before deploying.</p> </blockquote> </li> <li>Decoupled SCIM provisioning from the organization plugin (<a href="https://redirect.github.com/better-auth/better-auth/pull/10390">#10390</a>) <blockquote> <p><strong>Migration:</strong> SCIM configuration, client APIs, database schema, and the Group model are all replaced, and provisioning state cannot migrate in place. Follow the SCIM cutover in the 1.7 upgrade guide, including a full directory reprovision, before resuming traffic.</p> </blockquote> </li> <li>Added OTP-only two-factor enablement with a discriminated <code>enableTwoFactor</code> response (<a href="https://redirect.github.com/better-auth/better-auth/pull/9057">#9057</a>) <blockquote> <p><strong>Migration:</strong> <code>enableTwoFactor</code> now returns a <code>method</code> field (<code>"otp"</code> or <code>"totp"</code>); narrow on it before reading <code>totpURI</code> and <code>backupCodes</code>. Pass <code>method: "otp"</code> for OTP enrollment, which requires <code>otpOptions.sendOTP</code>.</p> </blockquote> </li> <li>Resolved the auth origin from <code>Host</code> by default when using a dynamic <code>baseURL</code> (<a href="https://redirect.github.com/better-auth/better-auth/pull/9134">#9134</a>) <blockquote> <p><strong>Migration:</strong> If your proxy exposes the public hostname only through <code>x-forwarded-host</code>, set <code>advanced.trustedProxyHeaders: true</code>. Deployments where the proxy rewrites <code>Host</code> (nginx default, Vercel, Cloudflare, Netlify) are unaffected.</p> </blockquote> </li> <li>Added unique lookup indexes for the device authorization <code>deviceCode</code> and <code>userCode</code> columns (<a href="https://redirect.github.com/better-auth/better-auth/pull/10059">#10059</a>) <blockquote> <p><strong>Migration:</strong> Resolve duplicate code values before applying the migration. MySQL and SQL Server installations must also convert both columns to bounded strings and clean up values longer than 191 characters.</p> </blockquote> </li> <li>Enforced S256 PKCE in the Electron sign-in flow and hardened custom-scheme origin checks (<a href="https://redirect.github.com/better-auth/better-auth/pull/9645">#9645</a>) <blockquote> <p><strong>Migration:</strong> Upgrade the <code>@better-auth/electron</code> client and server together and add your app's scheme to <code>trustedOrigins</code>. The <code>code_challenge_method</code> parameter and <code>disableOriginOverride</code> option are removed, and host-bearing custom-scheme entries now match that host exactly.</p> </blockquote> </li> <li>Identified Microsoft Entra accounts by the stable <code>oid</code> claim (<a href="https://redirect.github.com/better-auth/better-auth/pull/10204">#10204</a>) <blockquote> <p><strong>Migration:</strong> Migrate existing Microsoft account rows created from <code>sub</code> before upgrading. Tokens without a valid <code>oid</code> are rejected.</p> </blockquote> </li> <li>Required a Google client ID before Google One Tap verifies ID tokens (<a href="https://redirect.github.com/better-auth/better-auth/pull/10036">#10036</a>) <blockquote> <p><strong>Migration:</strong> Configure <code>oneTap({ clientId })</code> or <code>socialProviders.google.clientId</code>.</p> </blockquote> </li> <li>Removed the deprecated <code>oidcProvider</code> plugin (<a href="https://redirect.github.com/better-auth/better-auth/pull/10031">#10031</a>) <blockquote> <p><strong>Migration:</strong> Move OIDC authorization-server integrations to <code>@better-auth/oauth-provider</code>.</p> </blockquote> </li> <li>Rewrote the generic OAuth plugin as a first-class social provider with OAuth 2.1 defaults (<a href="https://redirect.github.com/better-auth/better-auth/pull/9069">#9069</a>) <blockquote> <p><strong>Migration:</strong> Replace <code>signIn.oauth2({ providerId })</code> with <code>signIn.social({ provider })</code>, <code>oauth2.link()</code> with <code>linkSocial()</code>, and drop <code>genericOAuthClient()</code>. Callbacks move to <code>/api/auth/callback/:id</code>, <code>pkce</code> now defaults to <code>true</code>, and <code>issuer</code> and <code>requireIssuerValidation</code> are removed in favor of OIDC discovery.</p> </blockquote> </li> <li>Separated OAuth device grant ownership into <code>oauthDeviceAuthorization()</code> (<a href="https://redirect.github.com/better-auth/better-auth/pull/10746">#10746</a>) <blockquote> <p><strong>Migration:</strong> The OAuth integration replaces the optional <code>resource</code> column with <code>oauthClientId</code> and <code>resources</code>, so regenerate and apply the schema. Let pending device codes expire before upgrading from an earlier 1.7 prerelease.</p> </blockquote> </li> <li>Verified provider <code>id_tokens</code> with a single shared verifier (<a href="https://redirect.github.com/better-auth/better-auth/pull/9828">#9828</a>) <blockquote> <p><strong>Migration:</strong> Custom <code>UpstreamProvider</code> implementations replace the removed <code>verifyIdToken</code> method with an <code>idToken</code> config carrying a JWKS source, issuer, and audience. PayPal client <code>id_token</code> sign-in now returns <code>ID_TOKEN_NOT_SUPPORTED</code>; its redirect flow is unchanged.</p> </blockquote> </li> </ul> <h3>Features</h3> <ul> <li>Added <code>clientAssertion</code> support to the Microsoft Entra ID social provider (<a href="https://redirect.github.com/better-auth/better-auth/pull/9898">#9898</a>)</li> <li>Made the <code>Auth</code> instance directly fetchable (<a href="https://redirect.github.com/better-auth/better-auth/pull/9431">#9431</a>)</li> <li>Added per-provider <code>requireEmailVerification</code> for social sign-in (<a href="https://redirect.github.com/better-auth/better-auth/pull/9929">#9929</a>)</li> <li>Added a <code>user.validateUserInfo</code> gate for rejecting an identity before a user is created or linked (<a href="https://redirect.github.com/better-auth/better-auth/pull/9864">#9864</a>)</li> <li>Added <code>hydrateSession</code> so <code>useSession</code> returns server-fetched data on the first render (<a href="https://redirect.github.com/better-auth/better-auth/pull/8733">#8733</a>)</li> <li>Added compound table indexes to plugin database schemas (<a href="https://redirect.github.com/better-auth/better-auth/pull/10402">#10402</a>)</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/better-auth/better-auth/blob/main/packages/better-auth/CHANGELOG.md">better-auth's changelog</a>.</em></p> <blockquote> <h2>1.7.0</h2> <h3>Minor Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/better-auth/better-auth/pull/8733">#8733</a> <a href="https://github.com/better-auth/better-auth/commit/4e8e4c7fc5fb2723144cbf41c4a1bfa28de8d671"><code>4e8e4c7</code></a> Thanks <a href="https://github.com/bytaesu"><code>@bytaesu</code></a>! - Add <code>hydrateSession</code> to seed the client with a server-fetched session so <code>useSession</code> returns data on the first render.</p> </li> <li> <p><a href="https://redirect.github.com/better-auth/better-auth/pull/9930">#9930</a> <a href="https://github.com/better-auth/better-auth/commit/0cbaf81bed9dec4c56880ee78a532262386e1ec5"><code>0cbaf81</code></a> Thanks <a href="https://github.com/gustavovalverde"><code>@gustavovalverde</code></a>! - Anonymous account linking now works after social and generic OAuth sign-in in Expo and other in-app browsers, where the OAuth callback returns without the session cookie. <code>onLinkAccount</code> fires and the anonymous user is migrated; before, it was silently skipped.</p> <p>Plugins can now carry server-trusted data across an OAuth redirect with the new <code>addOAuthServerContext</code> API, read back on the callback via <code>getOAuthState().serverContext</code>. Unlike <code>additionalData</code>, it cannot be set from the request body, so it is the right place for values the server must trust.</p> <p>For <code>@better-auth/oauth-provider</code>, the post-login authorization query now travels through that server-only channel, so it can no longer be injected through <code>additionalData</code>.</p> </li> <li> <p><a href="https://redirect.github.com/better-auth/better-auth/pull/10004">#10004</a> <a href="https://github.com/better-auth/better-auth/commit/b36c38f9842d3416689340552989449a32007819"><code>b36c38f</code></a> Thanks <a href="https://github.com/bytaesu"><code>@bytaesu</code></a>! - The captcha plugin now requires endpoint entries to match full auth paths unless they use wildcard patterns. This prevents requests like <code>/sign-in//email</code> from bypassing captcha while preserving trailing-slash matches like <code>/sign-in/email/</code>. To protect multiple routes, replace partial paths like <code>/sign-in</code> with explicit wildcards such as <code>/sign-in/*</code> or <code>/sign-in/**</code>.</p> </li> <li> <p><a href="https://redirect.github.com/better-auth/better-auth/pull/10746">#10746</a> <a href="https://github.com/better-auth/better-auth/commit/6782647d7c2d248246f9ef3980e656725c29ce64"><code>6782647</code></a> Thanks <a href="https://github.com/gustavovalverde"><code>@gustavovalverde</code></a>! - OAuth device grants now use <code>oauthDeviceAuthorization()</code> alongside <code>oauthProvider()</code> or <code>mcp()</code>. This single integration replaces both the standalone <code>deviceCodeGrant()</code> plugin and the shared-grant configuration. Standalone Device Authorization no longer accepts or stores RFC 8707 resources, and <code>onDeviceAuthRequest</code> receives only <code>clientId</code> and <code>scope</code>. The OAuth integration rejects resource indicators that are not absolute, fragment-free URIs.</p> <p>The OAuth integration replaces the optional <code>resource</code> column with <code>oauthClientId</code> and <code>resources</code>. Regenerate and apply the schema when using it. Before upgrading from an earlier 1.7 prerelease, let pending OAuth device codes expire or delete them because they cannot be exchanged through the new integration.</p> </li> <li> <p><a href="https://redirect.github.com/better-auth/better-auth/pull/10402">#10402</a> <a href="https://github.com/better-auth/better-auth/commit/763a2671c5372d88c291881977c8a1c2e29034b1"><code>763a267</code></a> Thanks <a href="https://github.com/gustavovalverde"><code>@gustavovalverde</code></a>! - Plugin database schemas can now define named or generated table-level indexes across multiple fields. SQL migrations and generated Drizzle or Prisma schemas resolve configured table and column names consistently, while the MongoDB adapter creates the same indexes before the first index-enforcing write.</p> </li> <li> <p><a href="https://redirect.github.com/better-auth/better-auth/pull/9766">#9766</a> <a href="https://github.com/better-auth/better-auth/commit/bf39cbf13f3b934f728cde72b1e7ebdc4c85f641"><code>bf39cbf</code></a> Thanks <a href="https://github.com/GautamBytes"><code>@GautamBytes</code></a>! - Add a server-only <code>auth.api.consumePhoneNumberOTP</code> API for custom phone OTP flows that need to verify and consume a code without creating or updating users or sessions.</p> </li> <li> <p><a href="https://redirect.github.com/better-auth/better-auth/pull/10330">#10330</a> <a href="https://github.com/better-auth/better-auth/commit/081d3c379c720926295067d878c421b5e8684c78"><code>081d3c3</code></a> Thanks <a href="https://github.com/ping-maxwell"><code>@ping-maxwell</code></a>! - Allow the username plugin's separate <code>displayUsername</code> field to be omitted by setting <code>displayUsername: false</code> on both the server and client plugins.</p> </li> <li> <p><a href="https://redirect.github.com/better-auth/better-auth/pull/10059">#10059</a> <a href="https://github.com/better-auth/better-auth/commit/49b5cf650e1264ecc4c917ca193ea05c3b58a3b9"><code>49b5cf6</code></a> Thanks <a href="https://github.com/GautamBytes"><code>@GautamBytes</code></a>! - Device Authorization now creates unique database indexes for <code>deviceCode</code> and <code>userCode</code>, so each generated code must be unique in its column. Existing installations on every adapter must resolve duplicate values before applying the migration. MySQL and SQL Server installations must also convert both columns to bounded strings and clean up values longer than 191 characters before running it.</p> <p>Generated codes are limited to 191 characters. Issuance makes up to 3 attempts to overcome unique-key collisions, then returns <code>server_error</code> if it cannot create a unique <code>deviceCode</code> and <code>userCode</code>. Default-generated user codes accept case changes and readability separators during verification, approval, and denial; custom codes outside the default alphabet are matched exactly. The <code>/device</code> limiter allows 5 requests over a window equal to the configured code lifetime, while <code>/device/token</code> polling keeps its separate interval behavior.</p> </li> <li> <p><a href="https://redirect.github.com/better-auth/better-auth/pull/9645">#9645</a> <a href="https://github.com/better-auth/better-auth/commit/e0140297a59ddb59cccbcb4ba46c513de8cb86a7"><code>e014029</code></a> Thanks <a href="https://github.com/ping-maxwell"><code>@ping-maxwell</code></a>! - Harden the Electron OAuth flow and tighten custom-scheme trusted-origin matching.</p> <p>The Electron sign-in flow now mandates PKCE S256. Plain PKCE is rejected: the <code>code_challenge_method</code> parameter is gone and every authorization code is verified by hashing the verifier with SHA-256. The server no longer trusts an <code>electron-origin</code> header to set the request Origin. The Electron client now sends a real <code>Origin</code> (for example <code>myapp:/</code>), so upgrade the <code>@better-auth/electron</code> client and server together and make sure your app's scheme is in <code>trustedOrigins</code>. The unused <code>disableOriginOverride</code> option is removed.</p> <p>Custom-scheme entries in <code>trustedOrigins</code> now match by scheme and authority instead of string prefix. A host-less entry such as <code>myapp://</code> or <code>exp://</code> still trusts every host of that scheme, but a host-bearing entry such as <code>myapp://callback</code> matches that host exactly, so it is no longer satisfied by <code>myapp://callback.attacker.tld</code>.</p> </li> <li> <p><a href="https://redirect.github.com/better-auth/better-auth/pull/9948">#9948</a> <a href="https://github.com/better-auth/better-auth/commit/3d04fababbf3efd4c46a4012f46ed9397715c2e3"><code>3d04fab</code></a> Thanks <a href="https://github.com/yordis"><code>@yordis</code></a>! - feat(generic-oauth): add <code>refreshTokenParams</code> config to forward extra params on token refresh</p> <p>Multi-tenant OIDC providers (Zitadel multi-org, Auth0 with <code>audience</code>) need to send extra body params on the refresh call to rescope tokens without a full authorization redirect. The generic-oauth plugin now accepts a <code>refreshTokenParams</code> option (object or sync/async function) that is merged into the refresh request body, with <code>grant_type</code> and <code>refresh_token</code> protected from override. The function form receives request metadata for the request that triggered the refresh, so request-scoped data (headers, cookies) is available without out-of-band state like AsyncLocalStorage.</p> <p><code>UpstreamProvider.refreshAccessToken</code> now accepts an optional second <code>ctx</code> argument; the change is backwards compatible because existing implementations that take only <code>refreshToken</code> remain valid. See <a href="https://redirect.github.com/better-auth/better-auth/issues/7554">#7554</a>.</p> </li> <li> <p><a href="https://redirect.github.com/better-auth/better-auth/pull/9069">#9069</a> <a href="https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097"><code>c7d2253</code></a> Thanks <a href="https://github.com/gustavovalverde"><code>@gustavovalverde</code></a>! - Rewrite the generic OAuth plugin as a first-class social provider with OAuth 2.1 security defaults. Providers now use <code>signIn.social</code> + <code>callback/:id</code> instead of dedicated plugin endpoints, with PKCE required by default (OAuth 2.1), RFC 9207 issuer validation, OIDC auto-discovery with <code>openid</code> scope injection, and typed provider IDs.</p> <p><strong>Breaking changes:</strong></p> <ul> <li><code>signIn.oauth2({ providerId })</code> replaced by <code>signIn.social({ provider })</code></li> <li><code>oauth2.link()</code> replaced by <code>linkSocial()</code></li> <li>Callback URL changed from <code>/api/auth/oauth2/callback/:id</code> to <code>/api/auth/callback/:id</code></li> <li><code>genericOAuthClient()</code> removed; generic OAuth providers now use the standard social client APIs</li> <li><code>pkce</code> defaults to <code>true</code> (was <code>false</code>); set <code>pkce: false</code> for providers that reject PKCE</li> <li><code>authorizationUrlParams</code> and <code>tokenUrlParams</code> only accept <code>Record<string, string></code></li> </ul> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/better-auth/better-auth/commit/ccd57c2dcb145a40a30c75ab3f6c89b94af08701"><code>ccd57c2</code></a> docs(changelog): align v1.7 release notes with final behavior (<a href="https://github.com/better-auth/better-auth/tree/HEAD/packages/better-auth/issues/10846">#10846</a>)</li> <li><a href="https://github.com/better-auth/better-auth/commit/f577ec5c766c4ccd0a677ad18ca5f4f17b245289"><code>f577ec5</code></a> chore: exit pre-release mode for v1.7.0</li> <li><a href="https://github.com/better-auth/better-auth/commit/69258d16709b977e519aa00a323ae54aea2b6164"><code>69258d1</code></a> chore: sync main to next</li> <li><a href="https://github.com/better-auth/better-auth/commit/e84ec5e76d30e10fd692e8084177360484d538c1"><code>e84ec5e</code></a> chore: release v1.6.30 (<a href="https://github.com/better-auth/better-auth/tree/HEAD/packages/better-auth/issues/10840">#10840</a>)</li> <li><a href="https://github.com/better-auth/better-auth/commit/bc93b27542cbdf74f6455e6f66a0b4292c247a12"><code>bc93b27</code></a> chore: release v1.7.0-rc.6 (<a href="https://github.com/better-auth/better-auth/tree/HEAD/packages/better-auth/issues/10772">#10772</a>)</li> <li><a href="https://github.com/better-auth/better-auth/commit/58c49eb97f04ff18aa823318a3856a013353fdc2"><code>58c49eb</code></a> chore: release v1.6.29 (<a href="https://github.com/better-auth/better-auth/tree/HEAD/packages/better-auth/issues/10809">#10809</a>)</li> <li><a href="https://github.com/better-auth/better-auth/commit/e6e1b4e8146a84d2a2c5fe2c497c81d03dfc2ad3"><code>e6e1b4e</code></a> perf(db): replace sequential get-then-delete loop with parallel deletes in de...</li> <li><a href="https://github.com/better-auth/better-auth/commit/80799e69314d4d13c875457d932545d54fbc7ada"><code>80799e6</code></a> chore: sync main to next</li> <li><a href="https://github.com/better-auth/better-auth/commit/3e485bf730c62b4ef3df2e55198179c3d15b5a9f"><code>3e485bf</code></a> docs(username): fix displayUsername release notes (<a href="https://github.com/better-auth/better-auth/tree/HEAD/packages/better-auth/issues/10776">#10776</a>)</li> <li><a href="https://github.com/better-auth/better-auth/commit/65fc17c755c3e2c8c77d5b401d612737764c219d"><code>65fc17c</code></a> fix(deps): align <code>drizzle-orm</code> peer range with drizzle-adapter (<a href="https://github.com/better-auth/better-auth/tree/HEAD/packages/better-auth/issues/10501">#10501</a>)</li> <li>Additional commits viewable in <a href="https://github.com/better-auth/better-auth/commits/v1.7.0/packages/better-auth">compare view</a></li> </ul> </details> <br /> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
c5382b36ba |
build(deps-dev): bump vite from 6.4.3 to 8.2.2 (#11887)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.4.3 to 8.2.2. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/vitejs/vite/releases">vite's releases</a>.</em></p> <blockquote> <h2>plugin-legacy@8.2.2</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/plugin-legacy@8.2.2/packages/plugin-legacy/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.2.2</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.2.2/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>plugin-legacy@8.2.1</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/plugin-legacy@8.2.1/packages/plugin-legacy/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.2.1</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.2.1/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>create-vite@8.2.0</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/create-vite@8.2.0/packages/create-vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>plugin-legacy@8.2.0</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/plugin-legacy@8.2.0/packages/plugin-legacy/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.2.0</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.2.0/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.2.0-beta.0</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.2.0-beta.0/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.1.5</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.1.5/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.1.4</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.1.4/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.1.3</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.1.3/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.1.2</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.1.2/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.1.1</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.1.1/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>create-vite@8.1.0</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/create-vite@8.1.0/packages/create-vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>plugin-legacy@8.1.0</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/plugin-legacy@8.1.0/packages/plugin-legacy/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>v8.1.0</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v8.1.0/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <h2>plugin-legacy@8.1.0-beta.0</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/plugin-legacy@8.1.0-beta.0/packages/plugin-legacy/CHANGELOG.md">CHANGELOG.md</a> for details.</p> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md">vite's changelog</a>.</em></p> <blockquote> <h2><!-- raw HTML omitted --><a href="https://github.com/vitejs/vite/compare/v8.2.1...v8.2.2">8.2.2</a> (2026-08-20)<!-- raw HTML omitted --></h2> <h3>Features</h3> <ul> <li><strong>deps:</strong> widen <code>@vitejs/devtools</code> peer range to v0.5.0 (<a href="https://redirect.github.com/vitejs/vite/issues/23302">#23302</a>) (<a href="https://github.com/vitejs/vite/commit/495d9ff5a7d843ca876a9e49799947a5deb704c7">495d9ff</a>)</li> </ul> <h3>Bug Fixes</h3> <ul> <li><strong>bundled-dev:</strong> handle lazy request error (<a href="https://redirect.github.com/vitejs/vite/issues/23291">#23291</a>) (<a href="https://github.com/vitejs/vite/commit/3ba026dade4af56df08815310d3458fa110f5c5c">3ba026d</a>)</li> <li><strong>bundled-dev:</strong> hot update through circular imports instead of reloading (<a href="https://redirect.github.com/vitejs/vite/issues/23259">#23259</a>) (<a href="https://github.com/vitejs/vite/commit/3dbddefaafc091a879b06f9279296f776691e455">3dbddef</a>)</li> <li><strong>config:</strong> resolve sourcemap paths against sourcemap location (<a href="https://redirect.github.com/vitejs/vite/issues/23239">#23239</a>) (<a href="https://github.com/vitejs/vite/commit/05a003e6a17a84d75f907ea0f1598bc39b8dce6c">05a003e</a>)</li> <li><strong>css:</strong> don't pass empty targets to lightningcss (<a href="https://redirect.github.com/vitejs/vite/issues/23295">#23295</a>) (<a href="https://github.com/vitejs/vite/commit/2804636ff608d105928009d274ffba7cfbe55340">2804636</a>)</li> <li><strong>define:</strong> fix match escaped dots to support $-prefixed define keys (<a href="https://redirect.github.com/vitejs/vite/issues/23249">#23249</a>) (<a href="https://github.com/vitejs/vite/commit/dcf88bd2ad2b1a8845f9029587cc8c825e382d42">dcf88bd</a>)</li> <li><strong>deps:</strong> update all non-major dependencies (<a href="https://redirect.github.com/vitejs/vite/issues/23217">#23217</a>) (<a href="https://github.com/vitejs/vite/commit/ba958bddfc9cabe302c6b34269dcf5c9634531e0">ba958bd</a>)</li> <li><strong>deps:</strong> update rolldown-related dependencies (<a href="https://redirect.github.com/vitejs/vite/issues/23218">#23218</a>) (<a href="https://github.com/vitejs/vite/commit/83ecb2c8059e8ce946a7cc835d4c14ef78aef4fd">83ecb2c</a>)</li> <li><strong>module-runner:</strong> exclude completed modules from in-flight cycle detection (fix <a href="https://redirect.github.com/vitejs/vite/issues/22999">#22999</a>) (<a href="https://redirect.github.com/vitejs/vite/issues/23009">#23009</a>) (<a href="https://github.com/vitejs/vite/commit/d9b10a98db1c293ee64300bd75d568b44c8ae931">d9b10a9</a>)</li> <li><strong>optimizer:</strong> close custom extension analysis bundles (<a href="https://redirect.github.com/vitejs/vite/issues/23207">#23207</a>) (<a href="https://github.com/vitejs/vite/commit/8fb76752836f61224d3095b502fa237b478a06b2">8fb7675</a>)</li> <li>reduce Windows 8.3-short-name detection false-positives (<a href="https://redirect.github.com/vitejs/vite/issues/23066">#23066</a>) (<a href="https://github.com/vitejs/vite/commit/02cffa9e2d38d5d8f12e4043ee9d0f7abb1471e2">02cffa9</a>)</li> <li>respect <code>resolve.preserveSymlinks</code> when resolving root (fix <a href="https://redirect.github.com/vitejs/vite/issues/23197">#23197</a>) (<a href="https://redirect.github.com/vitejs/vite/issues/23198">#23198</a>) (<a href="https://github.com/vitejs/vite/commit/8413052731836d4aaf3eb94a0f25788dd35d2888">8413052</a>)</li> <li><strong>ssr:</strong> rewrite computed key of destructing parameter (<a href="https://redirect.github.com/vitejs/vite/issues/23307">#23307</a>) (<a href="https://github.com/vitejs/vite/commit/9db0b61d4c9c7caad7ea1d9670b637faf2bb6c93">9db0b61</a>)</li> <li><strong>vite:</strong> update outdated upstream file links in license comments (<a href="https://redirect.github.com/vitejs/vite/issues/23285">#23285</a>) (<a href="https://github.com/vitejs/vite/commit/c0f2fc607ee97ee4499337b04826420c00654065">c0f2fc6</a>)</li> </ul> <h3>Documentation</h3> <ul> <li><strong>build:</strong> note cssTarget precedence (<a href="https://redirect.github.com/vitejs/vite/issues/23200">#23200</a>) (<a href="https://github.com/vitejs/vite/commit/a20a35ec0685e374519864d0f41dd5f6e9ba0271">a20a35e</a>)</li> </ul> <h3>Miscellaneous Chores</h3> <ul> <li>fix ts errors in build test cases (<a href="https://redirect.github.com/vitejs/vite/issues/23209">#23209</a>) (<a href="https://github.com/vitejs/vite/commit/a0cfcf72f8ef8bf0f2f11d553333b9bb31f1d316">a0cfcf7</a>)</li> </ul> <h3>Code Refactoring</h3> <ul> <li>use JSON import attributes instead of readFileSync in constants (<a href="https://redirect.github.com/vitejs/vite/issues/23258">#23258</a>) (<a href="https://github.com/vitejs/vite/commit/1d9fa392a43229241f80630236f8552ce8f7cd0f">1d9fa39</a>)</li> <li>use named regex constants over inline literals (<a href="https://redirect.github.com/vitejs/vite/issues/22964">#22964</a>) (<a href="https://github.com/vitejs/vite/commit/5c1c6c609718303202832f706884192e1f1e9223">5c1c6c6</a>)</li> </ul> <h3>Tests</h3> <ul> <li><strong>define:</strong> close rolldown bundler after generate (<a href="https://redirect.github.com/vitejs/vite/issues/23231">#23231</a>) (<a href="https://github.com/vitejs/vite/commit/b4d66fee14d970f45b8a6f3d7d6aee73ca9b88ab">b4d66fe</a>)</li> <li><strong>module-runner:</strong> add TLA circular import case (<a href="https://redirect.github.com/vitejs/vite/issues/23299">#23299</a>) (<a href="https://github.com/vitejs/vite/commit/4a261f242831bef92afd2f1aacfb81eab9dec371">4a261f2</a>)</li> <li><strong>module-runner:</strong> simplify server-hmr tests (<a href="https://redirect.github.com/vitejs/vite/issues/23300">#23300</a>) (<a href="https://github.com/vitejs/vite/commit/599b44b6600ec426e10cd556908d53b027b0c4fb">599b44b</a>)</li> <li><strong>ssr:</strong> add destructing assignment case for moduleRunnerTransform (<a href="https://redirect.github.com/vitejs/vite/issues/23308">#23308</a>) (<a href="https://github.com/vitejs/vite/commit/cb77e2a93bad2a8ece00b4aa0ef507c092582c45">cb77e2a</a>)</li> </ul> <h3>Build System</h3> <ul> <li>use JSON import attributes instead of readFIleSync in rolldown configs (<a href="https://redirect.github.com/vitejs/vite/issues/23251">#23251</a>) (<a href="https://github.com/vitejs/vite/commit/d615bcdb23d96c1ca5ce1ee45e21d8d87381106f">d615bcd</a>)</li> </ul> <h2><!-- raw HTML omitted --><a href="https://github.com/vitejs/vite/compare/v8.2.0...v8.2.1">8.2.1</a> (2026-08-06)<!-- raw HTML omitted --></h2> <h3>Bug Fixes</h3> <ul> <li><strong>build:</strong> make client chunkImportMap work with <code>sharedPlugins: true</code> (<a href="https://redirect.github.com/vitejs/vite/issues/23184">#23184</a>) (<a href="https://github.com/vitejs/vite/commit/15f03073c915d6ffb9a1fda447ef66b02bf5cde8">15f0307</a>)</li> <li><strong>bundled-dev:</strong> inject client script tag before chunk scripts (<a href="https://redirect.github.com/vitejs/vite/issues/23161">#23161</a>) (<a href="https://github.com/vitejs/vite/commit/eac0cc84aa2472a85a19ee84561c1ba71e381a55">eac0cc8</a>)</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/vitejs/vite/commit/de1111ab0be00879b404e7ed3b2a80e264edddc1"><code>de1111a</code></a> release: v8.2.2</li> <li><a href="https://github.com/vitejs/vite/commit/cb77e2a93bad2a8ece00b4aa0ef507c092582c45"><code>cb77e2a</code></a> test(ssr): add destructing assignment case for moduleRunnerTransform (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23308">#23308</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/9db0b61d4c9c7caad7ea1d9670b637faf2bb6c93"><code>9db0b61</code></a> fix(ssr): rewrite computed key of destructing parameter (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23307">#23307</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/8413052731836d4aaf3eb94a0f25788dd35d2888"><code>8413052</code></a> fix: respect <code>resolve.preserveSymlinks</code> when resolving root (fix <a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23197">#23197</a>) (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23">#23</a>...</li> <li><a href="https://github.com/vitejs/vite/commit/05a003e6a17a84d75f907ea0f1598bc39b8dce6c"><code>05a003e</code></a> fix(config): resolve sourcemap paths against sourcemap location (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23239">#23239</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/495d9ff5a7d843ca876a9e49799947a5deb704c7"><code>495d9ff</code></a> feat(deps): widen <code>@vitejs/devtools</code> peer range to v0.5.0 (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23302">#23302</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/1d9fa392a43229241f80630236f8552ce8f7cd0f"><code>1d9fa39</code></a> refactor: use JSON import attributes instead of readFileSync in constants (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/2">#2</a>...</li> <li><a href="https://github.com/vitejs/vite/commit/2804636ff608d105928009d274ffba7cfbe55340"><code>2804636</code></a> fix(css): don't pass empty targets to lightningcss (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23295">#23295</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/599b44b6600ec426e10cd556908d53b027b0c4fb"><code>599b44b</code></a> test(module-runner): simplify server-hmr tests (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23300">#23300</a>)</li> <li><a href="https://github.com/vitejs/vite/commit/4a261f242831bef92afd2f1aacfb81eab9dec371"><code>4a261f2</code></a> test(module-runner): add TLA circular import case (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/23299">#23299</a>)</li> <li>Additional commits viewable in <a href="https://github.com/vitejs/vite/commits/v8.2.2/packages/vite">compare view</a></li> </ul> </details> <br /> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Priya Raman <priya@paperclip.ing> Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
4d2af732ae |
feat(runner): add native persistence contracts (#12169)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agent runs need durable records so Paperclip can explain results and final status changes. > - The current heartbeat tables support direct adapters, but they do not model native runner evidence. > - The runner transport and server coordinator must share a strict finalization contract before they write production data. > - This pull request adds that contract and its additive database boundary. > - It does not select the Paperclip Runner or change any existing adapter execution path. > - The benefit is a reviewable persistence layer that preserves all current behavior and supports later guarded integration. ## Linked Issues or Issue Description Refs #11962 Refs #12129 ## What Changed - Add native run result, finalization, completion, assessment, status decision, and status effect tables. - Add inert native metadata to heartbeat runs and events. Keep `legacy` as the default runtime mode. - Bind each evidence relationship to one company, issue, run, contract, result, assessment, and decision with composite constraints. - Add a strict `paperclip.native_finalization.v1` shared type and validator. - Preserve database functions, triggers, and the unique indexes required by foreign keys in JavaScript backups. - Add migration, backup, mixed-owner denial, validator, and direct-adapter compatibility tests. - Document the new records and their ownership rules. ## Verification - Run `pnpm -r typecheck`. - Run `pnpm build`. - Run `pnpm db:generate`. The schema output and migration safety checks remain current. - Run `PAPERCLIP_PSQL_PATH=/Applications/Postgres.app/Contents/Versions/latest/bin/psql pnpm exec vitest run packages/shared/src/validators/native-finalization.test.ts packages/db/src/client.test.ts packages/db/src/backup-lib.test.ts server/src/__tests__/heartbeat-workspace-busy.test.ts server/src/__tests__/heartbeat-comment-wake-batching.test.ts`. All 52 tests pass. - The full local `pnpm test:run` run completed 4,688 tests. It found 30 existing macOS test-environment failures. A serial rerun with the canonical `/private/tmp` path reduced those failures to six existing listener-diagnostics and skill-browser cases. None of those suites use files in this change. - The full Linux GitHub Actions matrix passes. This includes all general-server, serialized-server, workspace, browser, build, typecheck, canary, and aggregate verification jobs. - Greptile passes at 5/5. Contributor trust, Superagent, Socket, and Snyk pass with no finding from this change. - Storybook visual regression skips by path because this pull request has no UI or Storybook change. - Confirm that the diff contains 25 files. Confirm that it contains no workflow or `pnpm-lock.yaml` changes. ## Risks - The migration adds tables, columns, indexes, a function, a trigger, and ownership constraints. It does not remove or rename existing data. - Composite foreign keys reject mixed-company, mixed-issue, and mixed-run evidence even when each ID exists. - The status-version trigger runs only when an issue status changes. Backup tests confirm that restore retains this trigger and its dependencies. - Native source identifiers are unique when present. Legacy event rows remain unchanged. - This change does not add a unique run sequence constraint. The later native writer must allocate its sequence atomically before that invariant can be safe. - Existing adapters keep their current execution and finalization paths. New heartbeat runs default to `legacy` mode. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex with GPT-5. The exact deployment ID and context-window size are not exposed. The model used agentic reasoning, repository tools, code execution, and test execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
0b01593602 |
build(deps): bump lucide-react from 0.577.0 to 1.32.0 (#11885)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.577.0 to 1.32.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/lucide-icons/lucide/releases">lucide-react's releases</a>.</em></p> <blockquote> <h2>Version 1.32.0</h2> <h2>What's Changed</h2> <ul> <li>feat(icons): added <code>car-battery</code> icon by <a href="https://github.com/andreynaz4renko"><code>@andreynaz4renko</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4088">lucide-icons/lucide#4088</a></li> <li>fix(categories): fixes emoji.json by <a href="https://github.com/karsa-mistmere"><code>@karsa-mistmere</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4697">lucide-icons/lucide#4697</a></li> <li>chore(deps): bump vue from 3.5.40 to 3.5.41 in the vue-deps group across 1 directory by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4695">lucide-icons/lucide#4695</a></li> <li>chore(dev): upgrade ESLint to latest compatible stack (v10) by <a href="https://github.com/ericfennis"><code>@ericfennis</code></a> with <a href="https://github.com/Copilot"><code>@Copilot</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4378">lucide-icons/lucide#4378</a></li> <li>feat(icons): add square-text by <a href="https://github.com/samuelalake"><code>@samuelalake</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4609">lucide-icons/lucide#4609</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/andreynaz4renko"><code>@andreynaz4renko</code></a> made their first contribution in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4088">lucide-icons/lucide#4088</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/lucide-icons/lucide/compare/1.31.0...1.32.0">https://github.com/lucide-icons/lucide/compare/1.31.0...1.32.0</a></p> <h2>Version 1.31.0</h2> <h2>What's Changed</h2> <ul> <li>feat(icons): added <code>mail-badge</code> icon by <a href="https://github.com/lazerg"><code>@lazerg</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4638">lucide-icons/lucide#4638</a></li> <li>feat(icons): add angle by <a href="https://github.com/samuelalake"><code>@samuelalake</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4545">lucide-icons/lucide#4545</a></li> <li>feat(icons): added <code>eject</code> icon by <a href="https://github.com/ThibautMarechal"><code>@ThibautMarechal</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4043">lucide-icons/lucide#4043</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/lazerg"><code>@lazerg</code></a> made their first contribution in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4638">lucide-icons/lucide#4638</a></li> <li><a href="https://github.com/ThibautMarechal"><code>@ThibautMarechal</code></a> made their first contribution in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4043">lucide-icons/lucide#4043</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/lucide-icons/lucide/compare/1.30.0...1.31.0">https://github.com/lucide-icons/lucide/compare/1.30.0...1.31.0</a></p> <h2>Version 1.30.0</h2> <h2>What's Changed</h2> <ul> <li>chore(icons): refine & rename various emoji icons by <a href="https://github.com/karsa-mistmere"><code>@karsa-mistmere</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4606">lucide-icons/lucide#4606</a></li> <li>fix(scripts): removed toBeRemovedInVersion from all scripts and tools by <a href="https://github.com/karsa-mistmere"><code>@karsa-mistmere</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4674">lucide-icons/lucide#4674</a></li> <li>feat(icons): added <code>audio-lines-x</code> icon by <a href="https://github.com/karsa-mistmere"><code>@karsa-mistmere</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4590">lucide-icons/lucide#4590</a></li> <li>feat(lab): added <code>chinese-character</code> icon to lab by <a href="https://github.com/congemcd"><code>@congemcd</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4212">lucide-icons/lucide#4212</a></li> <li>test(packages): updates unit test snapshots with face-slightly-smiling by <a href="https://github.com/karsa-mistmere"><code>@karsa-mistmere</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4676">lucide-icons/lucide#4676</a></li> <li>ci(dev): fix post-release job by downloading lucide-font artifact by name by <a href="https://github.com/ericfennis"><code>@ericfennis</code></a> with <a href="https://github.com/Copilot"><code>@Copilot</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4675">lucide-icons/lucide#4675</a></li> <li>feat(icons): add shield-lock icon by <a href="https://github.com/Caisere"><code>@Caisere</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/3508">lucide-icons/lucide#3508</a></li> <li>ci(security): Pin sha actions by <a href="https://github.com/jguddas"><code>@jguddas</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4678">lucide-icons/lucide#4678</a></li> <li>feat(icons): added <code>broom</code> icon by <a href="https://github.com/karsa-mistmere"><code>@karsa-mistmere</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4683">lucide-icons/lucide#4683</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/congemcd"><code>@congemcd</code></a> made their first contribution in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4212">lucide-icons/lucide#4212</a></li> <li><a href="https://github.com/Caisere"><code>@Caisere</code></a> made their first contribution in <a href="https://redirect.github.com/lucide-icons/lucide/pull/3508">lucide-icons/lucide#3508</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/lucide-icons/lucide/compare/1.29.0...1.30.0">https://github.com/lucide-icons/lucide/compare/1.29.0...1.30.0</a></p> <h2>Version 1.29.0</h2> <h2>What's Changed</h2> <ul> <li>fix(<code>@lucide/lab</code>): Fix lab build by <a href="https://github.com/ericfennis"><code>@ericfennis</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4618">lucide-icons/lucide#4618</a></li> <li>feat(copilot): remove incorrect spaces clause from copilot instructions by <a href="https://github.com/karsa-mistmere"><code>@karsa-mistmere</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4623">lucide-icons/lucide#4623</a></li> <li>feat(docs): remove Super and Noodle from showcase by <a href="https://github.com/karsa-mistmere"><code>@karsa-mistmere</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4626">lucide-icons/lucide#4626</a></li> <li>chore(deps-dev): bump <code>@angular/platform-server</code> from 21.2.18 to 21.2.19 by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4629">lucide-icons/lucide#4629</a></li> <li>ci(security): improve security with adding permissions by <a href="https://github.com/ericfennis"><code>@ericfennis</code></a> in <a href="https://redirect.github.com/lucide-icons/lucide/pull/4619">lucide-icons/lucide#4619</a></li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/lucide-icons/lucide/commit/75b55160aa9edd7095dfed1a6e3d88e66fb2b153"><code>75b5516</code></a> chore(dev): upgrade ESLint to latest compatible stack (v10) (<a href="https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react/issues/4378">#4378</a>)</li> <li><a href="https://github.com/lucide-icons/lucide/commit/0f8d48b266e7af1e2bab49ff12ab6ec0795ed204"><code>0f8d48b</code></a> test(packages): updates unit test snapshots with face-slightly-smiling (<a href="https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react/issues/4676">#4676</a>)</li> <li><a href="https://github.com/lucide-icons/lucide/commit/f229f83f0c42f46befeac3cfd8ef7aaa82a71325"><code>f229f83</code></a> chore(depedencies): Update dependencies (<a href="https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react/issues/4553">#4553</a>)</li> <li><a href="https://github.com/lucide-icons/lucide/commit/5ff536e1391335e4f7dc38d244c1bc458b9443e2"><code>5ff536e</code></a> ci(release.yml): Fix workflow and remove <code>version</code> scripts in package scripts...</li> <li><a href="https://github.com/lucide-icons/lucide/commit/07c885e6c1f9952965ba388b7fd2bb7c4d416a67"><code>07c885e</code></a> fix(docs): fix zephyr-cloud URL in readmes</li> <li><a href="https://github.com/lucide-icons/lucide/commit/50d8af5a1012e188f3d71ac8f1fc0fba1aab5357"><code>50d8af5</code></a> docs(readme): Update readme files (<a href="https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react/issues/4320">#4320</a>)</li> <li><a href="https://github.com/lucide-icons/lucide/commit/653e44b83293567ff24dcb90ca1094a9cf0a042a"><code>653e44b</code></a> feat(packages): use .mjs for ESM bundles (<a href="https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react/issues/4285">#4285</a>)</li> <li><a href="https://github.com/lucide-icons/lucide/commit/7623e23f787fe78e5075a613fd22da2cecbb9b1b"><code>7623e23</code></a> feat(docs): add Zephyr Cloud to Hero Backers tier & rework updateSponsors scr...</li> <li><a href="https://github.com/lucide-icons/lucide/commit/dada0a82970d3733d1d716e2089591c538272a39"><code>dada0a8</code></a> fix(lucide-react): Fix dynamic imports (<a href="https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react/issues/4210">#4210</a>)</li> <li><a href="https://github.com/lucide-icons/lucide/commit/a6e648a66ff470c2255d3666765fd73cfcc185ff"><code>a6e648a</code></a> fix(lucide-react): correct client directives in RSC files (<a href="https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react/issues/4189">#4189</a>)</li> <li>Additional commits viewable in <a href="https://github.com/lucide-icons/lucide/commits/1.32.0/packages/lucide-react">compare view</a></li> </ul> </details> <br /> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Priya Raman <priya@paperclip.ing> Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
18ba239d85 |
build(deps): bump @pierre/diffs from 1.2.11 to 1.3.5 (#11875)
Bumps @pierre/diffs from 1.2.11 to 1.3.5. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Priya Raman <priya@paperclip.ing> Co-authored-by: Paperclip <noreply@paperclip.ing> |