Commit Graph

4299 Commits

Author SHA1 Message Date
Zannis Kalampoukis 5db8ce3c44
fix(docker): make tini PID 1 in the server image so adopted orphans are reaped (#12137)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent runs execute inside the server container, and they spawn many
short-lived descendants: git, the adapter CLI, esbuild, sh
> - The server image sets `ENTRYPOINT ["docker-entrypoint.sh"]`, and
that entrypoint ends in `exec`, so node becomes PID 1
> - Node reaps only the children it spawned itself. It installs no
`SIGCHLD`/`waitpid` handler for orphans that the kernel re-parents onto
PID 1, so those orphans stay as zombies forever
> - Zombies accumulate monotonically. When the cgroup pid limit is
reached, every `fork()` in the container fails and the instance is dead
> - This pull request installs `tini` and makes it PID 1 in front of the
existing entrypoint, adds a behavioural test that proves reaping, and
adds a `pids_limit` backstop to both compose files
> - The benefit is that a long-running container no longer degrades into
total fork failure, and a future regression is caught by CI instead of
by an outage

Depends-on: none — this change is self-contained in the image build and
its tests, and it touches no other in-flight branch

## Linked Issues or Issue Description

No public GitHub issue exists for this defect. It was found on a live
long-running instance. Description follows the bug report template.

**What happened?**

The server container ran for 22 hours and reached 2039 of 2048 pids in
its cgroup. Of 1760 processes, 1731 were zombies, and all 1731 had PID 1
as their parent. PID 1 was `node --import
./server/node_modules/tsx/dist/loader.mjs server/dist/index.js`. Zombies
accrued at about 79 per hour and were never reaped. The oldest zombie
was 20.8 hours old against a container uptime of 22.0 hours, so nothing
had been reaped since boot. Once the pid limit was reached, `git` and
`gh` failed with `pthread_create failed: Resource temporarily
unavailable`.

**Expected behavior**

PID 1 reaps orphaned processes that the kernel re-parents onto it. The
pid count of a long-running container stays flat instead of growing
without bound.

**Steps to reproduce**

1. Start the server image without `docker run --init` and without `init:
true`.
2. Run agent work that spawns descendants which outlive their immediate
parent.
3. Read `/sys/fs/cgroup/pids.current` and count processes in `Z` state
over several hours.
4. The zombie count grows monotonically and every zombie has PPID 1.

**Relevant logs or output**

```
cgroup pids.current / pids.max : 2039 / 2048
total processes                : 1760
  zombies                      : 1731  (98.4%)
  parent of every zombie       : PID 1  (1731/1731)
PID 1 cmdline                  : node --import .../tsx/dist/loader.mjs server/dist/index.js
container uptime               : 22.0 h
oldest zombie                  : 20.8 h    median: 14.4 h
zombie names                   : git 717, claude 280, MainThread 167, sleep 141,
                                 esbuild 138, postgres 76, sh 65, sccache 50
```

**Additional context**

The fix pattern is already in this repository.
`docker/agent-runtime/Dockerfile.base` installs `tini` and sets
`ENTRYPOINT ["/usr/bin/tini", "--"]`. It was never applied to the server
image.

## What Changed

- `Dockerfile`: install `tini` in the `base` stage and set `ENTRYPOINT
["/usr/bin/tini", "--", "docker-entrypoint.sh"]`. The entrypoint stays
in the exec chain, so UID/GID remapping, `gosu`, and graceful shutdown
are unchanged.
- `scripts/assert-orphan-reaping.sh` (new): a behavioural probe. It
spawns a leader that forks a grandchild, exits the leader, and asserts
that the orphaned grandchild leaves `Z` state instead of persisting. It
fails closed if the grandchild is not re-parented onto PID 1, so a pass
cannot mean the check ran too early.
- `.github/workflows/docker.yml`: run that probe against the pushed
image after the publish step. The publish step is multi-arch with `push:
true`, so nothing is loaded into the runner daemon and the pushed tag is
the only thing to test. The cloud variant is `FROM production` and
inherits the same `ENTRYPOINT`.
- `scripts/docker-build-test.sh`: run the same probe against a local
build.
- `docker/docker-compose.yml` and
`docker/docker-compose.quickstart.yml`: add `pids_limit: 2048` as a
backstop, so a future leak dies visibly at its own ceiling instead of
starving the host of pids.
- `server/src/__tests__/container-init-reaping.test.ts` (new): 13
assertions that guard the configuration the probe depends on.

No per-orchestrator init lever was added. The image owning PID 1 covers
compose, plain `docker run`, the quadlet units, and the ECS task
definition in one place. Adding `init: true` in compose or
`initProcessEnabled` on the ECS task would nest a second init around
`tini`, and `tini` then warns on every boot that it is not PID 1. The
new test asserts the absence of both levers across all three manifests,
so the decision survives the next edit.

## Verification

| Check | Result |
|---|---|
| `scripts/assert-orphan-reaping.sh` against a real init | Grandchild
re-parented to PPID 1, then reaped. Exit 0. |
| Same probe forced against a genuine zombie | Reports `Z` and fails.
The failure branch is not vacuous. |
| Config guard against the pre-fix files | Exactly the 3 relevant
assertions turn red. |
| Config guard with `tini` removed from `apt-get` but the comments kept
| Red. It checks the install, not a mention of the name. |
| `cd server && npx vitest run
src/__tests__/container-init-reaping.test.ts` | 13 passed |
| `npx tsc --noEmit -p server` | Clean |
| `node scripts/check-docker-deps-stage.mjs` | PASS |
| `node --test scripts/release-verify-workflow.test.mjs` | 8 passed |

Not verified locally: no container runtime is available in the authoring
environment, so the probe has not run against a build of this image. The
new `docker.yml` step runs it against the pushed image on this PR.

## Risks

Low risk, but it is an image and entrypoint change, so it affects
deployments.

- `tini` adds one small package to the `base` stage.
`docker/agent-runtime/Dockerfile.base` already installs it from the same
Debian archive.
- Signal handling changes shape: `tini` receives `SIGTERM` and forwards
it to the entrypoint, which `exec`s node. `tini` forwards signals to its
direct child by default, and the exec chain keeps node as that child, so
graceful shutdown is preserved. A reviewer should confirm this on a real
stop.
- `pids_limit: 2048` is new for compose users. A deployment that
legitimately needs more than 2048 processes would now hit the ceiling.
The measured steady state on a busy instance was under 400.
- If a deployment already passes `--init` or `init: true`, `tini` runs
under another init and prints a warning that it is not PID 1. Reaping
still works because the outer init handles it. The compose files in this
repository do not set `init: true`.

## Model Used

Claude Opus 5 (`claude-opus-5`), extended thinking, with tool use and
code execution in an agent harness.

## 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 issues or links
- [x] My branch name describes the change and contains no internal
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 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: zannis <1011451+zannis@users.noreply.github.com>
2026-08-25 09:52:39 -07:00
dependabot[bot] 3a841e15d0
build(deps-dev): bump @types/supertest from 6.0.3 to 7.2.1 (#11878)
Bumps
[@types/supertest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/supertest)
from 6.0.3 to 7.2.1.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/supertest">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>
2026-08-25 09:46:49 -07:00
dependabot[bot] 3c328a7726
build(deps): bump @mdxeditor/editor from 3.55.0 to 4.2.1 (#11870)
Bumps [@mdxeditor/editor](https://github.com/mdx-editor/editor) from
3.55.0 to 4.2.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/mdx-editor/editor/releases">@​mdxeditor/editor's
releases</a>.</em></p>
<blockquote>
<h2>v4.2.1</h2>
<h2><a
href="https://github.com/mdx-editor/editor/compare/v4.2.0...v4.2.1">4.2.1</a>
(2026-08-21)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>upgrade js-yaml to 4.3.1 to resolve GHSA-5p4m-2wfm-xmqj (<a
href="3ff7296ffd">3ff7296</a>)</li>
</ul>
<h2>v4.2.0</h2>
<h1><a
href="https://github.com/mdx-editor/editor/compare/v4.1.1...v4.2.0">4.2.0</a>
(2026-08-02)</h1>
<h3>Bug Fixes</h3>
<ul>
<li>declare the frontmatter node as a block-level decorator (<a
href="ebc4755212">ebc4755</a>),
closes <a
href="https://redirect.github.com/mdx-editor/editor/issues/957">#957</a></li>
<li>support links on selected images (<a
href="d8c442b69f">d8c442b</a>),
closes <a
href="https://redirect.github.com/mdx-editor/editor/issues/753">#753</a></li>
</ul>
<h3>Features</h3>
<ul>
<li>mdxeditor-full-height opt-in class for editors that fill their
parent (<a
href="cdeda5847e">cdeda58</a>),
closes <a
href="https://redirect.github.com/mdx-editor/editor/issues/953">#953</a></li>
</ul>
<h2>v4.1.1</h2>
<h2><a
href="https://github.com/mdx-editor/editor/compare/v4.1.0...v4.1.1">4.1.1</a>
(2026-07-29)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>clear resolvable security audit findings in the dev dependency tree
(<a
href="117dd84987">117dd84</a>)</li>
<li>respect configured heading shortcuts (<a
href="beacb4c3c2">beacb4c</a>)</li>
</ul>
<h2>v4.1.0</h2>
<h1><a
href="https://github.com/mdx-editor/editor/compare/v4.0.4...v4.1.0">4.1.0</a>
(2026-07-19)</h1>
<h3>Bug Fixes</h3>
<ul>
<li>harden Lexical adoption lifecycle edges (<a
href="859bf459af">859bf45</a>)</li>
<li>pass Playwright install flags through npm (<a
href="0b2d19b3bf">0b2d19b</a>)</li>
<li>remove stray Realm provider token (<a
href="c432da3a83">c432da3</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>adopt Lexical 0.48 with compatibility gates (<a
href="90a1466d5e">90a1466</a>)</li>
<li>export Markdown from the active selection (<a
href="a7c3baee1c">a7c3bae</a>)</li>
<li>make search replacement state-backed (<a
href="b108652c55">b108652</a>)</li>
</ul>
<h2>v4.0.4</h2>
<h2><a
href="https://github.com/mdx-editor/editor/compare/v4.0.3...v4.0.4">4.0.4</a>
(2026-06-18)</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="3ff7296ffd"><code>3ff7296</code></a>
fix: upgrade js-yaml to 4.3.1 to resolve GHSA-5p4m-2wfm-xmqj</li>
<li><a
href="b5bc01b2c9"><code>b5bc01b</code></a>
Merge pull request <a
href="https://redirect.github.com/mdx-editor/editor/issues/959">#959</a>
from alexander-neuschl-tu-dresden-de/patch-1</li>
<li><a
href="b607c8ce2d"><code>b607c8c</code></a>
Update package-lock.json for js-yaml 4.3.1</li>
<li><a
href="dda0c61c0b"><code>dda0c61</code></a>
Upgrade js-yaml to 4.3.1 to resolve high vulnerability</li>
<li><a
href="d8c442b69f"><code>d8c442b</code></a>
fix: support links on selected images</li>
<li><a
href="cdeda5847e"><code>cdeda58</code></a>
feat: mdxeditor-full-height opt-in class for editors that fill their
parent</li>
<li><a
href="ebc4755212"><code>ebc4755</code></a>
fix: declare the frontmatter node as a block-level decorator</li>
<li><a
href="117dd84987"><code>117dd84</code></a>
fix: clear resolvable security audit findings in the dev dependency
tree</li>
<li><a
href="88b7545e5d"><code>88b7545</code></a>
Merge branch 'pr-954'</li>
<li><a
href="2b1af77dff"><code>2b1af77</code></a>
Merge pull request <a
href="https://redirect.github.com/mdx-editor/editor/issues/952">#952</a>
from 11suixing11/fix/allowed-heading-shortcuts</li>
<li>Additional commits viewable in <a
href="https://github.com/mdx-editor/editor/compare/v3.55.0...v4.2.1">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>
2026-08-25 09:46:10 -07:00
dependabot[bot] 1d3195bfcd
build(deps-dev): bump esbuild from 0.28.1 to 0.28.2 (#11882)
Bumps [esbuild](https://github.com/evanw/esbuild) from 0.28.1 to 0.28.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/evanw/esbuild/releases">esbuild's
releases</a>.</em></p>
<blockquote>
<h2>v0.28.2</h2>
<ul>
<li>
<p>Fix tree shaking bug due to TypeScript import alias (<a
href="https://redirect.github.com/evanw/esbuild/issues/4507">#4507</a>)</p>
<p>This release fixes a bug that could cause esbuild to incorrectly
tree-shake imports that are used in a TypeScript type alias under
certain circumstances. Affected code uses a TypeScript-specific
<code>import</code> assignment and looks something like this:</p>
<pre lang="ts"><code>import Base from './dep.js';
import Alias = Base.SomeType;
</code></pre>
</li>
<li>
<p>Fix CSS minification bug involving <code>&amp;</code> (<a
href="https://redirect.github.com/evanw/esbuild/issues/4497">#4497</a>)</p>
<p>This release fixes a bug where esbuild's CSS minifier incorrectly
removed a <code>&amp;</code> when it was unsafe to do so. Here is an
example:</p>
<pre lang="css"><code>/* Original code */
.a .b {
  &amp; .b:not(&amp; .c) {
    color: red;
  }
}
<p>/* Old output (with --minify) */<br />
.a .b{.b:not(&amp; .c){color:red}}</p>
<p>/* New output (with --minify) */<br />
.a .b{&amp; .b:not(&amp; .c){color:red}}<br />
</code></pre></p>
<p>This should match <code>&lt;span class=&quot;a&quot;&gt;&lt;span
class=&quot;b&quot;&gt;&lt;span
class=&quot;b&quot;&gt;yes&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;</code>
but not <code>&lt;span class=&quot;a&quot;&gt;&lt;span
class=&quot;b&quot;&gt;no&lt;/span&gt;&lt;/span&gt;</code>. The old
output incorrectly matched both.</p>
</li>
<li>
<p>Avoid overwriting input files without <code>--allow-overwrite</code>
(<a
href="https://redirect.github.com/evanw/esbuild/issues/4484">#4484</a>)</p>
<p>For example: <code>esbuild input.js --outfile=input.js</code> tells
esbuild to overwrite <code>input.js</code> with the output of running
esbuild on it. This was supposed to already be prevented by default, but
it accidentally regressed in version 0.17.0 and apparently didn't have
any test coverage. The error message was being printed but the input
file was still being overwritten. Oops.</p>
<p>This release puts the original behavior back. With this release,
esbuild should now actually avoid overwriting input files unless
<code>--allow-overwrite</code> is explicitly present. This is done by
not writing out any files when a build error is encountered.</p>
</li>
<li>
<p>Fix incorrect code generated when using top-level await (<a
href="https://redirect.github.com/evanw/esbuild/issues/4498">#4498</a>)</p>
<p>Previously esbuild could generate code containing a syntax error in
complex scenarios involving top-level await used in a dependency cycle.
The problem was a missing <code>async</code> on one or more module
wrapper closures. With this release, esbuild now uses a fixed-point
iteration algorithm to correctly annotate all dependencies in the cycle
as needing an <code>async</code> module wrapper.</p>
</li>
<li>
<p>Fix a minification bug with lowered logical assignment operators (<a
href="https://redirect.github.com/evanw/esbuild/issues/4508">#4508</a>)</p>
<p>This release fixes a bug that could cause esbuild to generate
incorrect code for logical assignment operators when lowering them to an
older target environment. Specifically the lowering process requires
duplicating the left-hand side, but esbuild incorrectly failed to count
the duplicate as a new usage when the left-hand side is an identifier.
That then caused the minifier to believe that the left-hand side was
only used once and could attempt to incorrectly inline an initializer
into the first usage. This bug has now been fixed:</p>
<pre lang="js"><code>// Original code
function foo() {
  let x
  bar(x ||= {})
</code></pre>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/evanw/esbuild/blob/main/CHANGELOG.md">esbuild's
changelog</a>.</em></p>
<blockquote>
<h2>0.28.2</h2>
<ul>
<li>
<p>Fix tree shaking bug due to TypeScript import alias (<a
href="https://redirect.github.com/evanw/esbuild/issues/4507">#4507</a>)</p>
<p>This release fixes a bug that could cause esbuild to incorrectly
tree-shake imports that are used in a TypeScript type alias under
certain circumstances. Affected code uses a TypeScript-specific
<code>import</code> assignment and looks something like this:</p>
<pre lang="ts"><code>import Base from './dep.js';
import Alias = Base.SomeType;
</code></pre>
</li>
<li>
<p>Fix CSS minification bug involving <code>&amp;</code> (<a
href="https://redirect.github.com/evanw/esbuild/issues/4497">#4497</a>)</p>
<p>This release fixes a bug where esbuild's CSS minifier incorrectly
removed a <code>&amp;</code> when it was unsafe to do so. Here is an
example:</p>
<pre lang="css"><code>/* Original code */
.a .b {
  &amp; .b:not(&amp; .c) {
    color: red;
  }
}
<p>/* Old output (with --minify) */<br />
.a .b{.b:not(&amp; .c){color:red}}</p>
<p>/* New output (with --minify) */<br />
.a .b{&amp; .b:not(&amp; .c){color:red}}<br />
</code></pre></p>
<p>This should match <code>&lt;span class=&quot;a&quot;&gt;&lt;span
class=&quot;b&quot;&gt;&lt;span
class=&quot;b&quot;&gt;yes&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;</code>
but not <code>&lt;span class=&quot;a&quot;&gt;&lt;span
class=&quot;b&quot;&gt;no&lt;/span&gt;&lt;/span&gt;</code>. The old
output incorrectly matched both.</p>
</li>
<li>
<p>Avoid overwriting input files without <code>--allow-overwrite</code>
(<a
href="https://redirect.github.com/evanw/esbuild/issues/4484">#4484</a>)</p>
<p>For example: <code>esbuild input.js --outfile=input.js</code> tells
esbuild to overwrite <code>input.js</code> with the output of running
esbuild on it. This was supposed to already be prevented by default, but
it accidentally regressed in version 0.17.0 and apparently didn't have
any test coverage. The error message was being printed but the input
file was still being overwritten. Oops.</p>
<p>This release puts the original behavior back. With this release,
esbuild should now actually avoid overwriting input files unless
<code>--allow-overwrite</code> is explicitly present. This is done by
not writing out any files when a build error is encountered.</p>
</li>
<li>
<p>Fix incorrect code generated when using top-level await (<a
href="https://redirect.github.com/evanw/esbuild/issues/4498">#4498</a>)</p>
<p>Previously esbuild could generate code containing a syntax error in
complex scenarios involving top-level await used in a dependency cycle.
The problem was a missing <code>async</code> on one or more module
wrapper closures. With this release, esbuild now uses a fixed-point
iteration algorithm to correctly annotate all dependencies in the cycle
as needing an <code>async</code> module wrapper.</p>
</li>
<li>
<p>Fix a minification bug with lowered logical assignment operators (<a
href="https://redirect.github.com/evanw/esbuild/issues/4508">#4508</a>)</p>
<p>This release fixes a bug that could cause esbuild to generate
incorrect code for logical assignment operators when lowering them to an
older target environment. Specifically the lowering process requires
duplicating the left-hand side, but esbuild incorrectly failed to count
the duplicate as a new usage when the left-hand side is an identifier.
That then caused the minifier to believe that the left-hand side was
only used once and could attempt to incorrectly inline an initializer
into the first usage. This bug has now been fixed:</p>
<pre lang="js"><code>// Original code
function foo() {
  let x
</code></pre>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="609683d892"><code>609683d</code></a>
publish 0.28.2 to npm</li>
<li><a
href="11b1fe48df"><code>11b1fe4</code></a>
add to release notes</li>
<li><a
href="ab50d91559"><code>ab50d91</code></a>
css: fix green/blue channel swap in oklch gamut mapping (<a
href="https://redirect.github.com/evanw/esbuild/issues/4488">#4488</a>)</li>
<li><a
href="04627b6cf9"><code>04627b6</code></a>
fix <a
href="https://redirect.github.com/evanw/esbuild/issues/4498">#4498</a>:
<code>async</code> TLA checks need a worklist</li>
<li><a
href="5c15177a30"><code>5c15177</code></a>
disable <code>gopls</code> in the <code>go</code> folder</li>
<li><a
href="fc2ee9babc"><code>fc2ee9b</code></a>
css: adjust parser to allow <code>--foo: {...}</code></li>
<li><a
href="209db54371"><code>209db54</code></a>
release notes for css nesting bugfix</li>
<li><a
href="c625d31bf0"><code>c625d31</code></a>
fix <a
href="https://redirect.github.com/evanw/esbuild/issues/4497">#4497</a>:
preserve nested ampersands during minification (<a
href="https://redirect.github.com/evanw/esbuild/issues/4500">#4500</a>)</li>
<li><a
href="34474e2785"><code>34474e2</code></a>
better isolation of current part in js parser</li>
<li><a
href="07f6e8c506"><code>07f6e8c</code></a>
fix <a
href="https://redirect.github.com/evanw/esbuild/issues/4507">#4507</a>:
<code>import</code> assignment tree-shaking bug</li>
<li>Additional commits viewable in <a
href="https://github.com/evanw/esbuild/compare/v0.28.1...v0.28.2">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>
2026-08-25 09:42:26 -07:00
dependabot[bot] ab4c4941f2
build(deps): bump @aws-sdk/client-s3 from 3.1111.0 to 3.1115.0 (#11876)
Bumps
[@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3)
from 3.1111.0 to 3.1115.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/aws/aws-sdk-js-v3/releases">@​aws-sdk/client-s3's
releases</a>.</em></p>
<blockquote>
<h2>v3.1115.0</h2>
<h4>3.1115.0(2026-08-20)</h4>
<h5>Documentation Changes</h5>
<ul>
<li><strong>client-pricing-plan-manager:</strong> Documentation update
for the CreateSubscription API to correct the default value of the
approval mode parameter. The default value for paid subscriptions is
MANUAL, not IMMEDIATE as previously documented. The default value
remains IMMEDIATE for FREE tier subscriptions. (<a
href="50d16ae3f2">50d16ae3</a>)</li>
</ul>
<h5>New Features</h5>
<ul>
<li><strong>client-sesv2:</strong> Amazon SES now supports per-message
tracking overrides. You can use the new ConfigurationOverrides parameter
in SendEmail and SendBulkEmail to enable or disable open and click
tracking for individual messages without changing your account-level or
configuration set settings. (<a
href="da56caa551">da56caa5</a>)</li>
<li><strong>client-arc-region-switch:</strong> Adds support for Rds
switchover read replica for Oracle databases in Region switch plans (<a
href="85ffb20a78">85ffb20a</a>)</li>
<li><strong>client-ec2:</strong> EC2 marks UEFI instance metadata field
as sensitive. (<a
href="c232746ad7">c232746a</a>)</li>
<li><strong>client-direct-connect:</strong> This release adds custom
route prefix pool allocations for Direct Connect. You can set IPv4 and
IPv6 route prefix counts on private and transit virtual interfaces, and
view pool size and unallocated counts on connections and LAGs, plus
direct connect gateway attachment prefix allocation totals. (<a
href="a94fb9783b">a94fb978</a>)</li>
<li><strong>client-amplify:</strong> Increased the maximum allowed
length from 255 to 4,096 characters to support longer access tokens. (<a
href="f7f8ecd1b8">f7f8ecd1</a>)</li>
<li><strong>client-batch:</strong> AWS Batch now supports a new compute
environment type that provides fully managed EC2 capacity with broader
compute flexibility than Fargate, including GPU instances, bare metal,
and specific instance type selection, without infrastructure management
overhead. (<a
href="9c559a7366">9c559a73</a>)</li>
<li><strong>client-sagemaker:</strong> Added IAM Identity Center (IdC)
support to CreatePartnerApp and UpdatePartnerApp APIs. Added Customer
Managed Key (CMK) support to CreateMlflowApp and DescribeMlflowApp. (<a
href="5548588739">55485887</a>)</li>
<li><strong>client-lambda:</strong> Adds support for full JSON
resource-based policies, enabling customers to create, retrieve, update,
and delete function resource policies as complete JSON documents. (<a
href="72573a2ad8">72573a2a</a>)</li>
<li><strong>client-cloudfront:</strong> Added SigV4a as a supported
signing protocol for Origin Access Control (OAC), enabling CloudFront to
sign requests to Amazon S3 Multi-Region Access Point (S3-MRAP) origins.
(<a
href="95476293d5">95476293</a>)</li>
</ul>
<hr />
<p>For list of updated packages, view
<strong>updated-packages.md</strong> in
<strong>assets-3.1115.0.zip</strong></p>
<h2>v3.1114.0</h2>
<h4>3.1114.0(2026-08-19)</h4>
<h5>New Features</h5>
<ul>
<li><strong>client-eks:</strong> Adds support for EKS cluster
certificate authorities (CA) (<a
href="a1316eaec0">a1316eae</a>)</li>
<li><strong>client-bedrock-agentcore-control:</strong> AgentCore Memory
now supports Flexible Namespaces (<a
href="65c89d6d82">65c89d6d</a>)</li>
<li><strong>client-batch:</strong> AWS Batch now supports managing
CloudWatch Container Insights on compute environments via
CreateComputeEnvironment and UpdateComputeEnvironment. (<a
href="f77fc37f10">f77fc37f</a>)</li>
<li><strong>client-redshift:</strong> Amazon Redshift enhanced System
Table retention that allows customers to store their system table data
directly in S3 Tables in customer's account instead of Redshift Managed
Storage (<a
href="a46d1f9634">a46d1f96</a>)</li>
<li><strong>client-bedrock-agentcore:</strong> AgentCore Memory now
supports Flexible Namespaces and Non-Conversational Payloads in
CreateEvent API (<a
href="a0d8fb6df9">a0d8fb6d</a>)</li>
<li><strong>client-medialive:</strong> AWS Elemental MediaLive now
supports video cropping and output positioning. Use cropRectangle and
outputPositionRectangle to position the encoded video within the output
frame, with the surrounding area filled with black. (<a
href="2bf1331a81">2bf1331a</a>)</li>
<li><strong>client-account-access:</strong> Adds throttling exceptions
to operation outputs that were previously inconsistent with other
operations. (<a
href="1e39b38544">1e39b385</a>)</li>
<li><strong>client-vpc-lattice:</strong> Amazon VPC Lattice now supports
modification of private DNS options on Service Network VPC Associations
(<a
href="92c89b2723">92c89b27</a>)</li>
<li><strong>client-redshift-serverless:</strong> Amazon Redshift
Enhanced System Table Retention that allows customers to store their
system table data directly in S3 Tables in customer's account instead of
Redshift Managed Storage (<a
href="73ad53c311">73ad53c3</a>)</li>
<li><strong>lib-transfer-manager:</strong> add file based download api
and worker thread based download. (<a
href="https://redirect.github.com/aws/aws-sdk-js-v3/pull/8259">#8259</a>)
(<a
href="b2d60357c8">b2d60357</a>)</li>
</ul>
<hr />
<p>For list of updated packages, view
<strong>updated-packages.md</strong> in
<strong>assets-3.1114.0.zip</strong></p>
<h2>v3.1113.0</h2>
<h4>3.1113.0(2026-08-18)</h4>
<h5>Chores</h5>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/CHANGELOG.md">@​aws-sdk/client-s3's
changelog</a>.</em></p>
<blockquote>
<h1><a
href="https://github.com/aws/aws-sdk-js-v3/compare/v3.1114.0...v3.1115.0">3.1115.0</a>
(2026-08-20)</h1>
<p><strong>Note:</strong> Version bump only for package
<code>@​aws-sdk/client-s3</code></p>
<h1><a
href="https://github.com/aws/aws-sdk-js-v3/compare/v3.1113.0...v3.1114.0">3.1114.0</a>
(2026-08-19)</h1>
<p><strong>Note:</strong> Version bump only for package
<code>@​aws-sdk/client-s3</code></p>
<h1><a
href="https://github.com/aws/aws-sdk-js-v3/compare/v3.1112.0...v3.1113.0">3.1113.0</a>
(2026-08-18)</h1>
<p><strong>Note:</strong> Version bump only for package
<code>@​aws-sdk/client-s3</code></p>
<h1><a
href="https://github.com/aws/aws-sdk-js-v3/compare/v3.1111.0...v3.1112.0">3.1112.0</a>
(2026-08-17)</h1>
<p><strong>Note:</strong> Version bump only for package
<code>@​aws-sdk/client-s3</code></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="efc86fc9c3"><code>efc86fc</code></a>
Publish v3.1115.0</li>
<li><a
href="5318b44c47"><code>5318b44</code></a>
Publish v3.1114.0</li>
<li><a
href="73a06d2aeb"><code>73a06d2</code></a>
Publish v3.1113.0</li>
<li><a
href="cb4ae7624b"><code>cb4ae76</code></a>
Publish v3.1112.0</li>
<li>See full diff in <a
href="https://github.com/aws/aws-sdk-js-v3/commits/v3.1115.0/clients/client-s3">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>
2026-08-25 09:41:28 -07:00
dependabot[bot] a68af9ed9c
build(deps-dev): bump @storybook/addon-a11y from 10.5.8 to 10.5.10 (#11874)
Bumps
[@storybook/addon-a11y](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/a11y)
from 10.5.8 to 10.5.10.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/releases">@​storybook/addon-a11y's
releases</a>.</em></p>
<blockquote>
<h2>v10.5.10</h2>
<h2>10.5.10</h2>
<ul>
<li>Core: Fetch static open-service snapshots relative to the document -
<a
href="https://redirect.github.com/storybookjs/storybook/pull/35945">#35945</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Core: Pin oxc-resolver to 11.21.2 to keep tsconfig path aliases on
solution-style tsconfigs - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35929">#35929</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Dependencies: Bump Vitest to 4.1.6 (CVE-2026-47428) - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35530">#35530</a>,
thanks <a
href="https://github.com/anupamme"><code>@​anupamme</code></a>!</li>
<li>Docs: Declare the font on overlay surfaces so docs tooltips are not
left to inherit - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35966">#35966</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>ESLint Plugin: Bundle CSF helpers so the plugin loads without
storybook - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35950">#35950</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>React: Preserve discriminated union prop values in metadata
extraction - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35844">#35844</a>,
thanks <a
href="https://github.com/s-robertson"><code>@​s-robertson</code></a>!</li>
</ul>
<h2>v10.5.9</h2>
<h2>10.5.9</h2>
<ul>
<li>Addon-Pseudo-States: Fix pseudo-states rewriting for nested
functional selectors - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34318">#34318</a>,
thanks <a
href="https://github.com/filipw01"><code>@​filipw01</code></a>!</li>
<li>Core: Skip module-graph reverse-index mirror when a patch is a no-op
- <a
href="https://redirect.github.com/storybookjs/storybook/pull/35825">#35825</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Core: Split module-graph into hot revisions and cold index services
- <a
href="https://redirect.github.com/storybookjs/storybook/pull/35831">#35831</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Preview: Fix crash when initialising UrlStore on a docs path - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35521">#35521</a>,
thanks <a
href="https://github.com/TheSeydiCharyyev"><code>@​TheSeydiCharyyev</code></a>!</li>
<li>Pseudo-States: Make stylesheet rewrites WebKit-safe - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35629">#35629</a>,
thanks <a
href="https://github.com/ethriel3695"><code>@​ethriel3695</code></a>!</li>
<li>TanStack: Keep the layout id when cloning a standalone index file
route - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35660">#35660</a>,
thanks <a
href="https://github.com/Insik-Han"><code>@​Insik-Han</code></a>!</li>
<li>TanStack: Render real link hrefs in the Link mock - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35505">#35505</a>,
thanks <a
href="https://github.com/unpunnyfuns"><code>@​unpunnyfuns</code></a>!</li>
<li>Webpack: Prevent long preview output filenames - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35533">#35533</a>,
thanks <a
href="https://github.com/zhangli091011"><code>@​zhangli091011</code></a>!</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md">@​storybook/addon-a11y's
changelog</a>.</em></p>
<blockquote>
<h2>10.5.10</h2>
<ul>
<li>Core: Fetch static open-service snapshots relative to the document -
<a
href="https://redirect.github.com/storybookjs/storybook/pull/35945">#35945</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Core: Pin oxc-resolver to 11.21.2 to keep tsconfig path aliases on
solution-style tsconfigs - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35929">#35929</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Dependencies: Bump Vitest to 4.1.6 (CVE-2026-47428) - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35530">#35530</a>,
thanks <a
href="https://github.com/anupamme"><code>@​anupamme</code></a>!</li>
<li>Docs: Declare the font on overlay surfaces so docs tooltips are not
left to inherit - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35966">#35966</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>ESLint Plugin: Bundle CSF helpers so the plugin loads without
storybook - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35950">#35950</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>React: Preserve discriminated union prop values in metadata
extraction - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35844">#35844</a>,
thanks <a
href="https://github.com/s-robertson"><code>@​s-robertson</code></a>!</li>
</ul>
<h2>10.5.9</h2>
<ul>
<li>Addon-Pseudo-States: Fix pseudo-states rewriting for nested
functional selectors - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34318">#34318</a>,
thanks <a
href="https://github.com/filipw01"><code>@​filipw01</code></a>!</li>
<li>Core: Skip module-graph reverse-index mirror when a patch is a no-op
- <a
href="https://redirect.github.com/storybookjs/storybook/pull/35825">#35825</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Core: Split module-graph into hot revisions and cold index services
- <a
href="https://redirect.github.com/storybookjs/storybook/pull/35831">#35831</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Preview: Fix crash when initialising UrlStore on a docs path - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35521">#35521</a>,
thanks <a
href="https://github.com/TheSeydiCharyyev"><code>@​TheSeydiCharyyev</code></a>!</li>
<li>Pseudo-States: Make stylesheet rewrites WebKit-safe - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35629">#35629</a>,
thanks <a
href="https://github.com/ethriel3695"><code>@​ethriel3695</code></a>!</li>
<li>TanStack: Keep the layout id when cloning a standalone index file
route - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35660">#35660</a>,
thanks <a
href="https://github.com/Insik-Han"><code>@​Insik-Han</code></a>!</li>
<li>TanStack: Render real link hrefs in the Link mock - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35505">#35505</a>,
thanks <a
href="https://github.com/unpunnyfuns"><code>@​unpunnyfuns</code></a>!</li>
<li>Webpack: Prevent long preview output filenames - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35533">#35533</a>,
thanks <a
href="https://github.com/zhangli091011"><code>@​zhangli091011</code></a>!</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="a2db7526e1"><code>a2db752</code></a>
Bump version from &quot;10.5.9&quot; to &quot;10.5.10&quot; [skip
ci]</li>
<li><a
href="8f56104894"><code>8f56104</code></a>
Bump version from &quot;10.5.8&quot; to &quot;10.5.9&quot; [skip
ci]</li>
<li>See full diff in <a
href="https://github.com/storybookjs/storybook/commits/v10.5.10/code/addons/a11y">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>
2026-08-25 09:39:41 -07:00
dependabot[bot] 41726ae279
build(deps): bump react-resizable-panels from 4.12.2 to 4.12.3 (#11872)
Bumps
[react-resizable-panels](https://github.com/bvaughn/react-resizable-panels)
from 4.12.2 to 4.12.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/bvaughn/react-resizable-panels/releases">react-resizable-panels's
releases</a>.</em></p>
<blockquote>
<h2>4.12.3</h2>
<ul>
<li><a
href="https://redirect.github.com/bvaughn/react-resizable-panels/pull/730">730</a>:
Guard <code>CSSStyleSheet</code> construction to avoid throwing in
unsupported environments (<a
href="https://github.com/leo-yang-qiong"><code>@​leo-yang-qiong</code></a>)</li>
<li><a
href="https://redirect.github.com/bvaughn/react-resizable-panels/pull/736">736</a>:
Bugfix: Derived Panel constraints equality check</li>
<li><a
href="https://redirect.github.com/bvaughn/react-resizable-panels/pull/732">732</a>:
Bugfix: Prevent orphaned groups in &quot;pointerup&quot; edge case (<a
href="https://github.com/waterWang"><code>@​waterWang</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/bvaughn/react-resizable-panels/blob/main/CHANGELOG.md">react-resizable-panels's
changelog</a>.</em></p>
<blockquote>
<h2>4.12.3</h2>
<ul>
<li><a
href="https://redirect.github.com/bvaughn/react-resizable-panels/pull/730">730</a>:
Guard <code>CSSStyleSheet</code> construction to avoid throwing in
unsupported environments (<a
href="https://github.com/leo-yang-qiong"><code>@​leo-yang-qiong</code></a>)</li>
<li><a
href="https://redirect.github.com/bvaughn/react-resizable-panels/pull/736">736</a>:
Bugfix: Derived Panel constraints equality check</li>
<li><a
href="https://redirect.github.com/bvaughn/react-resizable-panels/pull/732">732</a>:
Bugfix: Prevent orphaned groups in &quot;pointerup&quot; edge case (<a
href="https://github.com/waterWang"><code>@​waterWang</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="f9c422714a"><code>f9c4227</code></a>
4.12.2 -&gt; 4.12.3</li>
<li><a
href="30503d1dad"><code>30503d1</code></a>
Fix derived Panel constraints equality check (<a
href="https://redirect.github.com/bvaughn/react-resizable-panels/issues/736">#736</a>)</li>
<li><a
href="30aef6a448"><code>30aef6a</code></a>
Pending CHANGELOG</li>
<li><a
href="b1d574e504"><code>b1d574e</code></a>
fix: guard CSSStyleSheet construction with adoptedStyleSheets check (<a
href="https://redirect.github.com/bvaughn/react-resizable-panels/issues/730">#730</a>)</li>
<li><a
href="6649f42e56"><code>6649f42</code></a>
fix: don't resurrect stale group entries on pointer-up commit (Fixes <a
href="https://redirect.github.com/bvaughn/react-resizable-panels/issues/729">#729</a>)
(#...</li>
<li>See full diff in <a
href="https://github.com/bvaughn/react-resizable-panels/compare/4.12.2...4.12.3">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>
2026-08-25 09:24:39 -07:00
dependabot[bot] 50e324638c
build(deps): bump @assistant-ui/react from 0.15.14 to 0.15.16 (#11888)
Bumps
[@assistant-ui/react](https://github.com/assistant-ui/assistant-ui/tree/HEAD/packages/react)
from 0.15.14 to 0.15.16.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/assistant-ui/assistant-ui/releases">@​assistant-ui/react's
releases</a>.</em></p>
<blockquote>
<h2><code>@​assistant-ui/react</code><a
href="https://github.com/0"><code>@​0</code></a>.15.16</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6136">#6136</a>
<a
href="f7bd2d9392"><code>f7bd2d9</code></a>
- fix: keep DevTools updates flowing when a subscriber throws (<a
href="https://github.com/Kinfe123"><code>@​Kinfe123</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6055">#6055</a>
<a
href="1f3eaa7789"><code>1f3eaa7</code></a>
- fix: contain SandboxHost render failures after teardown (<a
href="https://github.com/Kinfe123"><code>@​Kinfe123</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6110">#6110</a>
<a
href="48f95b1442"><code>48f95b1</code></a>
- chore: delete the dead <code>ensureBinding</code> and
<code>useRuntimeState</code> utilities (<a
href="https://github.com/samdickson22"><code>@​samdickson22</code></a>)</p>
<p><code>src/context/react/utils/ensureBinding.ts</code> and
<code>src/context/react/utils/useRuntimeState.ts</code> imported only
each other. Nothing
else in the repo referenced them, neither appears in the package barrel
or the
api-surface snapshot, and the <code>&quot;.&quot;</code>-only exports
map made them unreachable to
consumers. <code>ensureBinding</code> was an external caller of
<code>__internal_bindMethods</code>
that no longer had a caller of its own; the runtime classes bind
themselves in
their constructors, so nothing changes at runtime. The public API
surface is
unchanged and every other emitted file is byte-identical.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6156">#6156</a>
<a
href="9c65b511bc"><code>9c65b51</code></a>
- deprecate leftover Primitive.If and Empty wrappers on react-native and
react-ink, and point them at AuiIf (<a
href="https://github.com/okisdev"><code>@​okisdev</code></a>)</p>
<p>ThreadIf now reads <code>thread.isEmpty</code> instead of
<code>messages.length === 0</code>, matching the loading-aware field
already used by ThreadEmpty and AuiIf. First-party examples and docs
samples that still called the leftover wrappers now use
<code>AuiIf</code> directly.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6084">#6084</a>
<a
href="ca9e72ce85"><code>ca9e72c</code></a>
- fix: resync trigger popover cursor after selection (<a
href="https://github.com/apps/rupic-app"><code>@​rupic-app</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6054">#6054</a>
<a
href="59e9a0881c"><code>59e9a08</code></a>
- fix: handle rejected asynchronous Markdown exports (<a
href="https://github.com/Kinfe123"><code>@​Kinfe123</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6098">#6098</a>
<a
href="b9b9dad28a"><code>b9b9dad</code></a>
- fix: drain unrevealed smooth text when a message completes before any
frame (<a
href="https://github.com/apps/rupic-app"><code>@​rupic-app</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6061">#6061</a>
<a
href="75dfbe3a2b"><code>75dfbe3</code></a>
- docs: document Escape-to-stop-speaking on ThreadPrimitive.Root (<a
href="https://github.com/samdickson22"><code>@​samdickson22</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6124">#6124</a>
<a
href="06b04a7976"><code>06b04a7</code></a>
- chore: update dependencies (<a
href="https://github.com/okisdev"><code>@​okisdev</code></a>)</p>
</li>
<li>
<p>Updated dependencies [<a
href="fa309156e0"><code>fa30915</code></a>,
<a
href="b355aefbe2"><code>b355aef</code></a>,
<a
href="f7bd2d9392"><code>f7bd2d9</code></a>,
<a
href="4947ef4f9b"><code>4947ef4</code></a>,
<a
href="332f736e64"><code>332f736</code></a>,
<a
href="ef9254d5b2"><code>ef9254d</code></a>,
<a
href="9c65b511bc"><code>9c65b51</code></a>,
<a
href="5845ba7c56"><code>5845ba7</code></a>,
<a
href="1b30bfdaba"><code>1b30bfd</code></a>,
<a
href="365e763928"><code>365e763</code></a>,
<a
href="d19921d373"><code>d19921d</code></a>,
<a
href="996aa5723c"><code>996aa57</code></a>,
<a
href="21d6e87dc2"><code>21d6e87</code></a>,
<a
href="cd247e557b"><code>cd247e5</code></a>,
<a
href="f2b3ef8b63"><code>f2b3ef8</code></a>,
<a
href="1bf263ba20"><code>1bf263b</code></a>,
<a
href="19e52c4012"><code>19e52c4</code></a>,
<a
href="06b04a7976"><code>06b04a7</code></a>,
<a
href="a614b5e44d"><code>a614b5e</code></a>,
<a
href="07b51dbbc7"><code>07b51db</code></a>,
<a
href="92e52bd2c9"><code>92e52bd</code></a>]:</p>
<ul>
<li><code>@​assistant-ui/core</code><a
href="https://github.com/0"><code>@​0</code></a>.3.15</li>
<li><code>@​assistant-ui/tap</code><a
href="https://github.com/0"><code>@​0</code></a>.9.14</li>
<li>assistant-stream@0.3.39</li>
</ul>
</li>
</ul>
<h2><code>@​assistant-ui/react</code><a
href="https://github.com/0"><code>@​0</code></a>.15.15</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6071">#6071</a>
<a
href="c3fd447f23"><code>c3fd447</code></a>
- feat: host assistant-cloud thread lists on AISDKThreads via
RemoteThreadList (<a
href="https://github.com/okisdev"><code>@​okisdev</code></a>)</p>
<p>AISDKThreads({ cloud }) uses RemoteThreadList and remounts each
thread like useChatRuntime. Cloud history withFormat resolves
persistence per call so one adapter can serve many threads.
useExternalHistory waits for threadListItem.remoteId instead of latching
on the first empty paint.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/5872">#5872</a>
<a
href="f9529bfdea"><code>f9529bf</code></a>
- feat: move useAssistantTransportRuntime into core/react (<a
href="https://github.com/okisdev"><code>@​okisdev</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/5872">#5872</a>
<a
href="f9529bfdea"><code>f9529bf</code></a>
- fix: persist data message parts in aui/v0 cloud history (<a
href="https://github.com/okisdev"><code>@​okisdev</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/5839">#5839</a>
<a
href="24a1af7607"><code>24a1af7</code></a>
- fix: validate MCP App resource responses (<a
href="https://github.com/Kinfe123"><code>@​Kinfe123</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/5817">#5817</a>
<a
href="dab7b7af71"><code>dab7b7a</code></a>
- fix: dispose sandbox frames when bridge setup fails (<a
href="https://github.com/Kinfe123"><code>@​Kinfe123</code></a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/assistant-ui/assistant-ui/blob/main/packages/react/CHANGELOG.md">@​assistant-ui/react's
changelog</a>.</em></p>
<blockquote>
<h2>0.15.16</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6136">#6136</a>
<a
href="f7bd2d9392"><code>f7bd2d9</code></a>
- fix: keep DevTools updates flowing when a subscriber throws (<a
href="https://github.com/Kinfe123"><code>@​Kinfe123</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6055">#6055</a>
<a
href="1f3eaa7789"><code>1f3eaa7</code></a>
- fix: contain SandboxHost render failures after teardown (<a
href="https://github.com/Kinfe123"><code>@​Kinfe123</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6110">#6110</a>
<a
href="48f95b1442"><code>48f95b1</code></a>
- chore: delete the dead <code>ensureBinding</code> and
<code>useRuntimeState</code> utilities (<a
href="https://github.com/samdickson22"><code>@​samdickson22</code></a>)</p>
<p><code>src/context/react/utils/ensureBinding.ts</code> and
<code>src/context/react/utils/useRuntimeState.ts</code> imported only
each other. Nothing
else in the repo referenced them, neither appears in the package barrel
or the
api-surface snapshot, and the <code>&quot;.&quot;</code>-only exports
map made them unreachable to
consumers. <code>ensureBinding</code> was an external caller of
<code>__internal_bindMethods</code>
that no longer had a caller of its own; the runtime classes bind
themselves in
their constructors, so nothing changes at runtime. The public API
surface is
unchanged and every other emitted file is byte-identical.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6156">#6156</a>
<a
href="9c65b511bc"><code>9c65b51</code></a>
- deprecate leftover Primitive.If and Empty wrappers on react-native and
react-ink, and point them at AuiIf (<a
href="https://github.com/okisdev"><code>@​okisdev</code></a>)</p>
<p>ThreadIf now reads <code>thread.isEmpty</code> instead of
<code>messages.length === 0</code>, matching the loading-aware field
already used by ThreadEmpty and AuiIf. First-party examples and docs
samples that still called the leftover wrappers now use
<code>AuiIf</code> directly.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6084">#6084</a>
<a
href="ca9e72ce85"><code>ca9e72c</code></a>
- fix: resync trigger popover cursor after selection (<a
href="https://github.com/apps/rupic-app"><code>@​rupic-app</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6054">#6054</a>
<a
href="59e9a0881c"><code>59e9a08</code></a>
- fix: handle rejected asynchronous Markdown exports (<a
href="https://github.com/Kinfe123"><code>@​Kinfe123</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6098">#6098</a>
<a
href="b9b9dad28a"><code>b9b9dad</code></a>
- fix: drain unrevealed smooth text when a message completes before any
frame (<a
href="https://github.com/apps/rupic-app"><code>@​rupic-app</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6061">#6061</a>
<a
href="75dfbe3a2b"><code>75dfbe3</code></a>
- docs: document Escape-to-stop-speaking on ThreadPrimitive.Root (<a
href="https://github.com/samdickson22"><code>@​samdickson22</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6124">#6124</a>
<a
href="06b04a7976"><code>06b04a7</code></a>
- chore: update dependencies (<a
href="https://github.com/okisdev"><code>@​okisdev</code></a>)</p>
</li>
<li>
<p>Updated dependencies [<a
href="fa309156e0"><code>fa30915</code></a>,
<a
href="b355aefbe2"><code>b355aef</code></a>,
<a
href="f7bd2d9392"><code>f7bd2d9</code></a>,
<a
href="4947ef4f9b"><code>4947ef4</code></a>,
<a
href="332f736e64"><code>332f736</code></a>,
<a
href="ef9254d5b2"><code>ef9254d</code></a>,
<a
href="9c65b511bc"><code>9c65b51</code></a>,
<a
href="5845ba7c56"><code>5845ba7</code></a>,
<a
href="1b30bfdaba"><code>1b30bfd</code></a>,
<a
href="365e763928"><code>365e763</code></a>,
<a
href="d19921d373"><code>d19921d</code></a>,
<a
href="996aa5723c"><code>996aa57</code></a>,
<a
href="21d6e87dc2"><code>21d6e87</code></a>,
<a
href="cd247e557b"><code>cd247e5</code></a>,
<a
href="f2b3ef8b63"><code>f2b3ef8</code></a>,
<a
href="1bf263ba20"><code>1bf263b</code></a>,
<a
href="19e52c4012"><code>19e52c4</code></a>,
<a
href="06b04a7976"><code>06b04a7</code></a>,
<a
href="a614b5e44d"><code>a614b5e</code></a>,
<a
href="07b51dbbc7"><code>07b51db</code></a>,
<a
href="92e52bd2c9"><code>92e52bd</code></a>]:</p>
<ul>
<li><code>@​assistant-ui/core</code><a
href="https://github.com/0"><code>@​0</code></a>.3.15</li>
<li><code>@​assistant-ui/tap</code><a
href="https://github.com/0"><code>@​0</code></a>.9.14</li>
<li>assistant-stream@0.3.39</li>
</ul>
</li>
</ul>
<h2>0.15.15</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/6071">#6071</a>
<a
href="c3fd447f23"><code>c3fd447</code></a>
- feat: host assistant-cloud thread lists on AISDKThreads via
RemoteThreadList (<a
href="https://github.com/okisdev"><code>@​okisdev</code></a>)</p>
<p>AISDKThreads({ cloud }) uses RemoteThreadList and remounts each
thread like useChatRuntime. Cloud history withFormat resolves
persistence per call so one adapter can serve many threads.
useExternalHistory waits for threadListItem.remoteId instead of latching
on the first empty paint.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/5872">#5872</a>
<a
href="f9529bfdea"><code>f9529bf</code></a>
- feat: move useAssistantTransportRuntime into core/react (<a
href="https://github.com/okisdev"><code>@​okisdev</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/5872">#5872</a>
<a
href="f9529bfdea"><code>f9529bf</code></a>
- fix: persist data message parts in aui/v0 cloud history (<a
href="https://github.com/okisdev"><code>@​okisdev</code></a>)</p>
</li>
<li>
<p><a
href="https://redirect.github.com/assistant-ui/assistant-ui/pull/5839">#5839</a>
<a
href="24a1af7607"><code>24a1af7</code></a>
- fix: validate MCP App resource responses (<a
href="https://github.com/Kinfe123"><code>@​Kinfe123</code></a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="75e3ef71be"><code>75e3ef7</code></a>
chore: update versions (<a
href="https://github.com/assistant-ui/assistant-ui/tree/HEAD/packages/react/issues/6086">#6086</a>)</li>
<li><a
href="f7bd2d9392"><code>f7bd2d9</code></a>
fix(react): isolate devtools subscribers (<a
href="https://github.com/assistant-ui/assistant-ui/tree/HEAD/packages/react/issues/6136">#6136</a>)</li>
<li><a
href="9c65b511bc"><code>9c65b51</code></a>
fix(react-native,react-ink): honor thread.isEmpty in leftover ThreadIf
(<a
href="https://github.com/assistant-ui/assistant-ui/tree/HEAD/packages/react/issues/6156">#6156</a>)</li>
<li><a
href="48f95b1442"><code>48f95b1</code></a>
chore(react): delete the dead ensureBinding and useRuntimeState
utilities (<a
href="https://github.com/assistant-ui/assistant-ui/tree/HEAD/packages/react/issues/6">#6</a>...</li>
<li><a
href="06b04a7976"><code>06b04a7</code></a>
chore: update dependencies (<a
href="https://github.com/assistant-ui/assistant-ui/tree/HEAD/packages/react/issues/6124">#6124</a>)</li>
<li><a
href="b9b9dad28a"><code>b9b9dad</code></a>
fix: drain smooth text when a message completes before an animation
frame (<a
href="https://github.com/assistant-ui/assistant-ui/tree/HEAD/packages/react/issues/6">#6</a>...</li>
<li><a
href="10a0f3ade8"><code>10a0f3a</code></a>
test(react): vary live-completion fetcher and cacheKey independently (<a
href="https://github.com/assistant-ui/assistant-ui/tree/HEAD/packages/react/issues/6062">#6062</a>)</li>
<li><a
href="b355aefbe2"><code>b355aef</code></a>
fix(core): prevent assistant frame origin downgrades (<a
href="https://github.com/assistant-ui/assistant-ui/tree/HEAD/packages/react/issues/5823">#5823</a>)</li>
<li><a
href="75dfbe3a2b"><code>75dfbe3</code></a>
docs(react): document Escape-to-stop-speaking on ThreadPrimitive.Root
(<a
href="https://github.com/assistant-ui/assistant-ui/tree/HEAD/packages/react/issues/6061">#6061</a>)</li>
<li><a
href="ca9e72ce85"><code>ca9e72c</code></a>
fix(react): resync trigger cursor after selection (<a
href="https://github.com/assistant-ui/assistant-ui/tree/HEAD/packages/react/issues/6082">#6082</a>)
(<a
href="https://github.com/assistant-ui/assistant-ui/tree/HEAD/packages/react/issues/6084">#6084</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/assistant-ui/assistant-ui/commits/@assistant-ui/react@0.15.16/packages/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>
2026-08-25 09:24:15 -07:00
dependabot[bot] 4fb0978578
build(deps): bump googleapis from 174.0.1 to 176.0.0 (#11889)
Bumps
[googleapis](https://github.com/googleapis/google-api-nodejs-client)
from 174.0.1 to 176.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/googleapis/google-api-nodejs-client/releases">googleapis's
releases</a>.</em></p>
<blockquote>
<h2>googleapis: v176.0.0</h2>
<h2><a
href="https://github.com/googleapis/google-api-nodejs-client/compare/googleapis-v175.0.0...googleapis-v176.0.0">176.0.0</a>
(2026-08-18)</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li><strong>securityposture:</strong> This release has breaking
changes.</li>
<li><strong>compute:</strong> This release has breaking changes.</li>
<li><strong>assuredworkloads:</strong> This release has breaking
changes.</li>
</ul>
<h3>Features</h3>
<ul>
<li><strong>assuredworkloads:</strong> update the API (<a
href="4f787ecb10">4f787ec</a>)</li>
<li><strong>bigqueryconnection:</strong> update the API (<a
href="19d67d7998">19d67d7</a>)</li>
<li><strong>bigquery:</strong> update the API (<a
href="5047629259">5047629</a>)</li>
<li><strong>ces:</strong> update the API (<a
href="4d674e7e4e">4d674e7</a>)</li>
<li><strong>compute:</strong> update the API (<a
href="88ee28ba7c">88ee28b</a>)</li>
<li><strong>contactcenterinsights:</strong> update the API (<a
href="8987bcff71">8987bcf</a>)</li>
<li><strong>dialogflow:</strong> update the API (<a
href="cb090b72b2">cb090b7</a>)</li>
<li><strong>discoveryengine:</strong> update the API (<a
href="c9a9b98cfc">c9a9b98</a>)</li>
<li><strong>gkehub:</strong> update the API (<a
href="e7356ce9c0">e7356ce</a>)</li>
<li><strong>looker:</strong> update the API (<a
href="ce6eba9927">ce6eba9</a>)</li>
<li><strong>metastore:</strong> update the API (<a
href="266b861fd1">266b861</a>)</li>
<li><strong>networkservices:</strong> update the API (<a
href="71b26e6c37">71b26e6</a>)</li>
<li><strong>playdeveloperreporting:</strong> update the API (<a
href="b0d0c26491">b0d0c26</a>)</li>
<li>regenerate index files (<a
href="0eb3a957cc">0eb3a95</a>)</li>
<li><strong>secretmanager:</strong> update the API (<a
href="333f48fa3a">333f48f</a>)</li>
<li><strong>securityposture:</strong> update the API (<a
href="868105393d">8681053</a>)</li>
<li><strong>storage:</strong> update the API (<a
href="9974109dd4">9974109</a>)</li>
<li><strong>webcontentpublisher:</strong> update the API (<a
href="7dc05fc5f2">7dc05fc</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li><strong>datafusion:</strong> update the API (<a
href="2c691d571a">2c691d5</a>)</li>
<li><strong>docs:</strong> run JSDoc once per documentation build (<a
href="https://redirect.github.com/googleapis/google-api-nodejs-client/issues/3958">#3958</a>)
(<a
href="5aaf111af8">5aaf111</a>)</li>
<li><strong>redis:</strong> update the API (<a
href="c639065e6a">c639065</a>)</li>
<li><strong>trafficdirector:</strong> update the API (<a
href="3331b0cd34">3331b0c</a>)</li>
<li><strong>workstations:</strong> update the API (<a
href="ee9521ce5c">ee9521c</a>)</li>
</ul>
<h2>googleapis: v175.0.0</h2>
<h2><a
href="https://github.com/googleapis/google-api-nodejs-client/compare/googleapis-v174.0.1...googleapis-v175.0.0">175.0.0</a>
(2026-08-14)</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li><strong>merchantapi:</strong> This release has breaking
changes.</li>
<li><strong>discoveryengine:</strong> This release has breaking
changes.</li>
</ul>
<h3>Features</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="a454f9bda0"><code>a454f9b</code></a>
chore: release main (<a
href="https://redirect.github.com/googleapis/google-api-nodejs-client/issues/3976">#3976</a>)</li>
<li><a
href="0eb3a957cc"><code>0eb3a95</code></a>
feat: regenerate index files</li>
<li><a
href="ee9521ce5c"><code>ee9521c</code></a>
fix(workstations): update the API</li>
<li><a
href="7dc05fc5f2"><code>7dc05fc</code></a>
feat(webcontentpublisher): update the API</li>
<li><a
href="3331b0cd34"><code>3331b0c</code></a>
fix(trafficdirector): update the API</li>
<li><a
href="9974109dd4"><code>9974109</code></a>
feat(storage): update the API</li>
<li><a
href="868105393d"><code>8681053</code></a>
feat(securityposture)!: update the API</li>
<li><a
href="333f48fa3a"><code>333f48f</code></a>
feat(secretmanager): update the API</li>
<li><a
href="c639065e6a"><code>c639065</code></a>
fix(redis): update the API</li>
<li><a
href="b0d0c26491"><code>b0d0c26</code></a>
feat(playdeveloperreporting): update the API</li>
<li>Additional commits viewable in <a
href="https://github.com/googleapis/google-api-nodejs-client/compare/googleapis-v174.0.1...googleapis-v176.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>
2026-08-25 09:23:50 -07:00
dependabot[bot] b67dced1bf
build(deps): bump @agentclientprotocol/codex-acp from 1.2.0 to 1.6.2 (#11883)
Bumps
[@agentclientprotocol/codex-acp](https://github.com/agentclientprotocol/codex-acp)
from 1.2.0 to 1.6.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/agentclientprotocol/codex-acp/releases">@​agentclientprotocol/codex-acp's
releases</a>.</em></p>
<blockquote>
<h2>v1.6.2</h2>
<h2><a
href="https://github.com/agentclientprotocol/codex-acp/compare/v1.6.1...v1.6.2">1.6.2</a>
(2026-08-19)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>right-size the apt timeouts so a slow mirror still finishes (<a
href="86e0772204">86e0772</a>)</li>
</ul>
<h2>v1.6.1</h2>
<h2><a
href="https://github.com/agentclientprotocol/codex-acp/compare/v1.6.0...v1.6.1">1.6.1</a>
(2026-08-19)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>kill stalled apt from outside and serialize the unit suite (<a
href="51e011fef2">51e011f</a>)</li>
</ul>
<h2>v1.6.0</h2>
<h2><a
href="https://github.com/agentclientprotocol/codex-acp/compare/v1.5.1...v1.6.0">1.6.0</a>
(2026-08-19)</h2>
<h3>Features</h3>
<ul>
<li>harden release pipeline against hangs and e2e flakes (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/413">#413</a>)
(<a
href="39af81c29b">39af81c</a>)</li>
</ul>
<h2>v1.5.1</h2>
<h2><a
href="https://github.com/agentclientprotocol/codex-acp/compare/v1.5.0...v1.5.1">1.5.1</a>
(2026-08-19)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>update codex to 0.148.0 (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/410">#410</a>)
(<a
href="3616954dc0">3616954</a>)</li>
</ul>
<h2>v1.5.0</h2>
<h2><a
href="https://github.com/agentclientprotocol/codex-acp/compare/v1.4.0...v1.5.0">1.5.0</a>
(2026-08-17)</h2>
<h3>Features</h3>
<ul>
<li>switch providers for loaded Codex sessions (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/404">#404</a>)
(<a
href="47b57da564">47b57da</a>)</li>
</ul>
<h2>v1.4.0</h2>
<h2><a
href="https://github.com/agentclientprotocol/codex-acp/compare/v1.3.0...v1.4.0">1.4.0</a>
(2026-08-16)</h2>
<h3>Features</h3>
<ul>
<li>report changed files to AIR (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/403">#403</a>)
(<a
href="e305394d3f">e305394</a>)</li>
</ul>
<h2>v1.3.0</h2>
<h2><a
href="https://github.com/agentclientprotocol/codex-acp/compare/v1.2.0...v1.3.0">1.3.0</a>
(2026-08-14)</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/agentclientprotocol/codex-acp/blob/main/CHANGELOG.md">@​agentclientprotocol/codex-acp's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/agentclientprotocol/codex-acp/compare/v1.6.1...v1.6.2">1.6.2</a>
(2026-08-19)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>right-size the apt timeouts so a slow mirror still finishes (<a
href="86e0772204">86e0772</a>)</li>
</ul>
<h2><a
href="https://github.com/agentclientprotocol/codex-acp/compare/v1.6.0...v1.6.1">1.6.1</a>
(2026-08-19)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>kill stalled apt from outside and serialize the unit suite (<a
href="51e011fef2">51e011f</a>)</li>
</ul>
<h2><a
href="https://github.com/agentclientprotocol/codex-acp/compare/v1.5.1...v1.6.0">1.6.0</a>
(2026-08-19)</h2>
<h3>Features</h3>
<ul>
<li>harden release pipeline against hangs and e2e flakes (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/413">#413</a>)
(<a
href="39af81c29b">39af81c</a>)</li>
</ul>
<h2><a
href="https://github.com/agentclientprotocol/codex-acp/compare/v1.5.0...v1.5.1">1.5.1</a>
(2026-08-19)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>update codex to 0.148.0 (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/410">#410</a>)
(<a
href="3616954dc0">3616954</a>)</li>
</ul>
<h2><a
href="https://github.com/agentclientprotocol/codex-acp/compare/v1.4.0...v1.5.0">1.5.0</a>
(2026-08-17)</h2>
<h3>Features</h3>
<ul>
<li>switch providers for loaded Codex sessions (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/404">#404</a>)
(<a
href="47b57da564">47b57da</a>)</li>
</ul>
<h2><a
href="https://github.com/agentclientprotocol/codex-acp/compare/v1.3.0...v1.4.0">1.4.0</a>
(2026-08-16)</h2>
<h3>Features</h3>
<ul>
<li>report changed files to AIR (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/403">#403</a>)
(<a
href="e305394d3f">e305394</a>)</li>
</ul>
<h2><a
href="https://github.com/agentclientprotocol/codex-acp/compare/v1.2.0...v1.3.0">1.3.0</a>
(2026-08-14)</h2>
<h3>Features</h3>
<ul>
<li>add versioned context compaction metadata (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/396">#396</a>)
(<a
href="c4a9311f60">c4a9311</a>)</li>
<li>align typed session failures with AIR protocol (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/393">#393</a>)
(<a
href="e4fb92fffd">e4fb92f</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9780d314d3"><code>9780d31</code></a>
chore(main): release 1.6.2 (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/417">#417</a>)</li>
<li><a
href="86e0772204"><code>86e0772</code></a>
fix: right-size the apt timeouts so a slow mirror still finishes</li>
<li><a
href="096f5a8850"><code>096f5a8</code></a>
chore(main): release 1.6.1 (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/416">#416</a>)</li>
<li><a
href="51e011fef2"><code>51e011f</code></a>
fix: kill stalled apt from outside and serialize the unit suite</li>
<li><a
href="50bd611451"><code>50bd611</code></a>
chore(main): release 1.6.0 (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/414">#414</a>)</li>
<li><a
href="39af81c29b"><code>39af81c</code></a>
feat: harden release pipeline against hangs and e2e flakes (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/413">#413</a>)</li>
<li><a
href="ad658e6ec6"><code>ad658e6</code></a>
chore(main): release 1.5.1 (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/412">#412</a>)</li>
<li><a
href="3616954dc0"><code>3616954</code></a>
fix: update codex to 0.148.0 (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/410">#410</a>)</li>
<li><a
href="3d56827225"><code>3d56827</code></a>
chore(main): release 1.5.0 (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/409">#409</a>)</li>
<li><a
href="47b57da564"><code>47b57da</code></a>
feat: switch providers for loaded Codex sessions (<a
href="https://redirect.github.com/agentclientprotocol/codex-acp/issues/404">#404</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/agentclientprotocol/codex-acp/compare/v1.2.0...v1.6.2">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>
2026-08-25 09:23:47 -07:00
dependabot[bot] b858fc7248
build(deps): bump @codemirror/view from 6.43.8 to 6.43.9 (#11879)
Bumps [@codemirror/view](https://github.com/codemirror/view) from 6.43.8
to 6.43.9.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/codemirror/view/commits">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>
2026-08-25 09:23:31 -07:00
dependabot[bot] 30f9888d3f
build(deps-dev): bump storybook from 10.5.5 to 10.5.10 (#11884)
Bumps
[storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/core)
from 10.5.5 to 10.5.10.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/releases">storybook's
releases</a>.</em></p>
<blockquote>
<h2>v10.5.10</h2>
<h2>10.5.10</h2>
<ul>
<li>Core: Fetch static open-service snapshots relative to the document -
<a
href="https://redirect.github.com/storybookjs/storybook/pull/35945">#35945</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Core: Pin oxc-resolver to 11.21.2 to keep tsconfig path aliases on
solution-style tsconfigs - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35929">#35929</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Dependencies: Bump Vitest to 4.1.6 (CVE-2026-47428) - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35530">#35530</a>,
thanks <a
href="https://github.com/anupamme"><code>@​anupamme</code></a>!</li>
<li>Docs: Declare the font on overlay surfaces so docs tooltips are not
left to inherit - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35966">#35966</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>ESLint Plugin: Bundle CSF helpers so the plugin loads without
storybook - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35950">#35950</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>React: Preserve discriminated union prop values in metadata
extraction - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35844">#35844</a>,
thanks <a
href="https://github.com/s-robertson"><code>@​s-robertson</code></a>!</li>
</ul>
<h2>v10.5.9</h2>
<h2>10.5.9</h2>
<ul>
<li>Addon-Pseudo-States: Fix pseudo-states rewriting for nested
functional selectors - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34318">#34318</a>,
thanks <a
href="https://github.com/filipw01"><code>@​filipw01</code></a>!</li>
<li>Core: Skip module-graph reverse-index mirror when a patch is a no-op
- <a
href="https://redirect.github.com/storybookjs/storybook/pull/35825">#35825</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Core: Split module-graph into hot revisions and cold index services
- <a
href="https://redirect.github.com/storybookjs/storybook/pull/35831">#35831</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Preview: Fix crash when initialising UrlStore on a docs path - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35521">#35521</a>,
thanks <a
href="https://github.com/TheSeydiCharyyev"><code>@​TheSeydiCharyyev</code></a>!</li>
<li>Pseudo-States: Make stylesheet rewrites WebKit-safe - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35629">#35629</a>,
thanks <a
href="https://github.com/ethriel3695"><code>@​ethriel3695</code></a>!</li>
<li>TanStack: Keep the layout id when cloning a standalone index file
route - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35660">#35660</a>,
thanks <a
href="https://github.com/Insik-Han"><code>@​Insik-Han</code></a>!</li>
<li>TanStack: Render real link hrefs in the Link mock - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35505">#35505</a>,
thanks <a
href="https://github.com/unpunnyfuns"><code>@​unpunnyfuns</code></a>!</li>
<li>Webpack: Prevent long preview output filenames - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35533">#35533</a>,
thanks <a
href="https://github.com/zhangli091011"><code>@​zhangli091011</code></a>!</li>
</ul>
<h2>v10.5.8</h2>
<h2>10.5.8</h2>
<ul>
<li>React: Fix RDT tsconfig selection for Vite project references - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35743">#35743</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Tanstack React: Remove <code>@​cloudflare/vite-plugin</code> from
the inherited Vite config - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35706">#35706</a>,
thanks <a
href="https://github.com/FrancoKaddour"><code>@​FrancoKaddour</code></a>!</li>
<li>Tanstack: Wait for router to load before rendering - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35784">#35784</a>,
thanks <a
href="https://github.com/huang-julien"><code>@​huang-julien</code></a>!</li>
<li>Test: Fix Illegal invocation when reading prototype.focus - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35528">#35528</a>,
thanks <a
href="https://github.com/FrancoKaddour"><code>@​FrancoKaddour</code></a>!</li>
</ul>
<h2>v10.5.7</h2>
<h2>10.5.7</h2>
<ul>
<li>Angular: Serve ancestor node_modules for addon-vitest in browser
mode - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35600">#35600</a>,
thanks <a
href="https://github.com/brandonroberts"><code>@​brandonroberts</code></a>!</li>
<li>Refactor: Update getVersionedPackages method to handle non-Storybook
packages correctly - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35769">#35769</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
</ul>
<h2>v10.5.6</h2>
<h2>10.5.6</h2>
<ul>
<li>Dependencies: Pin `@testing-library/jest-dom` to `6.9.1` - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35614">#35614</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>ESLint Plugin: Add plugin meta and document oxlint usage - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35655">#35655</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Vue: Skip docgen for module ids carrying a query - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35598">#35598</a>,
thanks <a
href="https://github.com/seanogdev"><code>@​seanogdev</code></a>!</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md">storybook's
changelog</a>.</em></p>
<blockquote>
<h2>10.5.10</h2>
<ul>
<li>Core: Fetch static open-service snapshots relative to the document -
<a
href="https://redirect.github.com/storybookjs/storybook/pull/35945">#35945</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Core: Pin oxc-resolver to 11.21.2 to keep tsconfig path aliases on
solution-style tsconfigs - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35929">#35929</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Dependencies: Bump Vitest to 4.1.6 (CVE-2026-47428) - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35530">#35530</a>,
thanks <a
href="https://github.com/anupamme"><code>@​anupamme</code></a>!</li>
<li>Docs: Declare the font on overlay surfaces so docs tooltips are not
left to inherit - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35966">#35966</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>ESLint Plugin: Bundle CSF helpers so the plugin loads without
storybook - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35950">#35950</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>React: Preserve discriminated union prop values in metadata
extraction - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35844">#35844</a>,
thanks <a
href="https://github.com/s-robertson"><code>@​s-robertson</code></a>!</li>
</ul>
<h2>10.5.9</h2>
<ul>
<li>Addon-Pseudo-States: Fix pseudo-states rewriting for nested
functional selectors - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34318">#34318</a>,
thanks <a
href="https://github.com/filipw01"><code>@​filipw01</code></a>!</li>
<li>Core: Skip module-graph reverse-index mirror when a patch is a no-op
- <a
href="https://redirect.github.com/storybookjs/storybook/pull/35825">#35825</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Core: Split module-graph into hot revisions and cold index services
- <a
href="https://redirect.github.com/storybookjs/storybook/pull/35831">#35831</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Preview: Fix crash when initialising UrlStore on a docs path - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35521">#35521</a>,
thanks <a
href="https://github.com/TheSeydiCharyyev"><code>@​TheSeydiCharyyev</code></a>!</li>
<li>Pseudo-States: Make stylesheet rewrites WebKit-safe - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35629">#35629</a>,
thanks <a
href="https://github.com/ethriel3695"><code>@​ethriel3695</code></a>!</li>
<li>TanStack: Keep the layout id when cloning a standalone index file
route - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35660">#35660</a>,
thanks <a
href="https://github.com/Insik-Han"><code>@​Insik-Han</code></a>!</li>
<li>TanStack: Render real link hrefs in the Link mock - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35505">#35505</a>,
thanks <a
href="https://github.com/unpunnyfuns"><code>@​unpunnyfuns</code></a>!</li>
<li>Webpack: Prevent long preview output filenames - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35533">#35533</a>,
thanks <a
href="https://github.com/zhangli091011"><code>@​zhangli091011</code></a>!</li>
</ul>
<h2>10.5.8</h2>
<ul>
<li>React: Fix RDT tsconfig selection for Vite project references - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35743">#35743</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Tanstack React: Remove <code>@​cloudflare/vite-plugin</code> from
the inherited Vite config - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35706">#35706</a>,
thanks <a
href="https://github.com/FrancoKaddour"><code>@​FrancoKaddour</code></a>!</li>
<li>Tanstack: Wait for router to load before rendering - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35784">#35784</a>,
thanks <a
href="https://github.com/huang-julien"><code>@​huang-julien</code></a>!</li>
<li>Test: Fix Illegal invocation when reading prototype.focus - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35528">#35528</a>,
thanks <a
href="https://github.com/FrancoKaddour"><code>@​FrancoKaddour</code></a>!</li>
</ul>
<h2>10.5.7</h2>
<ul>
<li>Angular: Serve ancestor node_modules for addon-vitest in browser
mode - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35600">#35600</a>,
thanks <a
href="https://github.com/brandonroberts"><code>@​brandonroberts</code></a>!</li>
<li>Refactor: Update getVersionedPackages method to handle non-Storybook
packages correctly - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35769">#35769</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
</ul>
<h2>10.5.6</h2>
<ul>
<li>Dependencies: Pin <code>@testing-library/jest-dom</code> to
<code>6.9.1</code> - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35614">#35614</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>ESLint Plugin: Add plugin meta and document oxlint usage - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35655">#35655</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Vue: Skip docgen for module ids carrying a query - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35598">#35598</a>,
thanks <a
href="https://github.com/seanogdev"><code>@​seanogdev</code></a>!</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="a2db7526e1"><code>a2db752</code></a>
Bump version from &quot;10.5.9&quot; to &quot;10.5.10&quot; [skip
ci]</li>
<li><a
href="de77b08382"><code>de77b08</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/35929">#35929</a>
from storybookjs/valentin/sb-1821-pin-oxc-resolver</li>
<li><a
href="374b8b3451"><code>374b8b3</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/35966">#35966</a>
from storybookjs/valentin/docs-overlay-typography</li>
<li><a
href="2148cdd5af"><code>2148cdd</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/35950">#35950</a>
from storybookjs/fix/eslint-plugin-bundle-csf</li>
<li><a
href="b336e8f5c1"><code>b336e8f</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/35945">#35945</a>
from storybookjs/valentin/static-services-subpath-f...</li>
<li><a
href="8f56104894"><code>8f56104</code></a>
Bump version from &quot;10.5.8&quot; to &quot;10.5.9&quot; [skip
ci]</li>
<li><a
href="f31554b81e"><code>f31554b</code></a>
Backport the module-graph hot/cold split and no-op index skip to
10.5.9.</li>
<li><a
href="c1db83aae8"><code>c1db83a</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/35521">#35521</a>
from TheSeydiCharyyev/fix/35436-urlstore-docs-path</li>
<li><a
href="6ef7d1ae81"><code>6ef7d1a</code></a>
Bump version from &quot;10.5.7&quot; to &quot;10.5.8&quot; [skip
ci]</li>
<li><a
href="647e982151"><code>647e982</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/35743">#35743</a>
from storybookjs/norbert/revive-34415-file-aware-ts...</li>
<li>Additional commits viewable in <a
href="https://github.com/storybookjs/storybook/commits/v10.5.10/code/core">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>
2026-08-25 09:23:29 -07:00
Nicky Leach 2862e18484
refactor(adapter-utils): remove the retired duplex_v1 sandbox bridge transport (#12171)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The adapter utilities provide sandbox transport paths for agent
execution
> - The retired `duplex_v1` path remains in host, gateway, and test code
after `http2_v1` replaced it
> - Retired transport code adds maintenance cost and leaves an unsafe
fallback for unknown gateway modes
> - This pull request removes the retired path, moves shared `http2_v1`
contracts to a leaf module, and closes mode dispatch to a fixed
allowlist
> - The benefit is a smaller transport surface and explicit failure for
unsupported modes

## Linked Issues or Issue Description

Refs #12120

The `http2_v1` transport replaced `duplex_v1`, but the retired broker,
gateway, constants, and tests remain in the adapter utilities. An
unknown bridge mode can also fall through to the queue gateway when a
queue directory exists. This change removes the retired code and rejects
unsupported modes before gateway selection.

## What Changed

- Delete the host `duplex_v1` broker and its transport-only tests.
- Delete the in-sandbox duplex gateway and retired mode constants.
- Move shared `http2_v1` symbols into `bridge-transport-contract.ts`.
- Update the remaining importers and repair their focused tests.
- Validate bridge modes against `http2_v1` and `queue_v1` before queue
lookup.
- Keep `queue_v1`, `duplex-frame-codec.ts`, and duplex telemetry
dimensions unchanged.

## Verification

- [x] `npx tsc --noEmit -p packages/adapter-utils` passes.
- [x] `npx vitest run packages/adapter-utils/src` passes: 48 files and
968 tests pass, with 4 pre-existing platform skips.
- [x] Full CI is green on this pull request.
- [x] Greptile review is complete and every finding is resolved.

## Risks

The change removes an internal transport that no host path selects. The
main risk is an overlooked import or test dependency. Targeted typecheck
and tests cover the adapter utility package. Full CI must confirm
workspace-wide compatibility.

## Model Used

Anthropic Claude Sonnet 5 assisted with the implementation, as recorded
in the commit. The commit does not record a context-window size or
reasoning mode.

## 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>
2026-08-25 08:47:43 -07:00
Nicky Leach 02a984068c
refactor(adapter-utils): clean up the HTTP/2 bridge request-body bounds (#12166)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent adapters use the HTTP/2 bridge to carry requests and responses
> - The bridge has an idle bound and a total-lifetime ceiling for
request bodies
> - The old renewable lifetime bound re-armed with each DATA chunk and
could not act before the idle bound
> - The code also repeated the same bounds and rationale in several
places
> - This pull request removes the unreachable renewable bound, keeps the
one-shot ceiling, and simplifies the shared bounds object
> - The benefit is clearer protection logic with the same default
request-body behavior

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The HTTP/2 bridge request-body reader uses several repeated bound
parameters and comments. One renewable lifetime bound cannot act before
the idle bound under the shipped defaults.

**Subsystem affected**

`packages/adapter-utils/` — HTTP/2 bridge adapter utilities.

**Current behavior**

The idle bound and renewable lifetime bound both re-arm after each DATA
chunk. The renewable bound therefore does not act on its own. The
total-lifetime ceiling also shares timer setup with the renewable bound.

**Proposed behavior**

Remove the renewable lifetime bound. Keep the total-lifetime ceiling as
an independent one-shot timer. Pass one bounds object to the bridge call
sites and keep tests for the idle bound and total-lifetime ceiling.

**Reason and benefit**

The change removes unreachable logic and repeated rationale. It keeps
the independent total-lifetime protection and makes the bound behavior
easier to review.

**Breaking changes**

The change removes two public constant and option names that
repository-wide search found unused outside this implementation. The
shipped default behavior does not change.

## What Changed

- Remove the renewable request-body lifetime bound and its public names.
- Keep the total-lifetime ceiling as a one-shot timer that starts when
the body read starts.
- Replace repeated bound parameters with one `Http2BridgeBodyBounds`
object.
- De-duplicate bound rationale comments.
- Add shared test helpers and update tests for the idle bound and
total-lifetime ceiling.

## Verification

- Run `npx tsc --noEmit -p packages/adapter-utils`.
- Run `npx vitest run
packages/adapter-utils/src/http2-bridge-server.test.ts`.
- Wait for the pull request CI checks.
- Request the Greptile review and confirm a 5/5 verdict with no open
findings.

## Risks

The main risk is an incorrect timer lifetime after the renewable timer
removal. The one-shot ceiling remains independent, and the updated tests
cover its expiry and cleanup paths. The change does not alter the
shipped default bounds.

## Model Used

OpenAI Codex based on GPT-5. Exact runtime model version is GPT-5. The
work used tool calls and code execution for repository inspection and
GitHub operations.

## 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>
2026-08-25 08:09:52 -07:00
Nicky Leach 445547c989
feat(duplex): run the Daytona sandbox callback bridge over Node HTTP/2 (#12120)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Sandbox providers carry agent work through controlled execution
channels
> - The Daytona callback bridge uses a bespoke line-framed protocol over
its duplex channel
> - The bespoke protocol adds framing work and does not use the Node
transport that already supports multiplexed streams
> - This pull request carries raw bytes across the channel, adds a Node
HTTP/2 bridge, and selects it for Daytona
> - The benefit is one authenticated, multiplexed callback session with
queue_v1 as the bounded fallback

## Linked Issues or Issue Description

**Subsystem affected**

The packages/plugins Daytona provider and the shared duplex execution
path.

**Problem or motivation**

The Daytona callback bridge uses a bespoke line-framed protocol over the
provider duplex channel. This adds protocol work and limits stream
handling.

**Proposed solution**

Carry raw bytes through the cross-layer channel. Add an authenticated
Node HTTP/2 host server and sandbox client gateway. Select http2_v1 for
Daytona and retain queue_v1 as the fallback.

**Alternatives considered**

Keep the current duplex_v1 protocol. This keeps the bespoke framing path
and does not provide one HTTP/2 session for callback streams.

**Roadmap alignment**

ROADMAP.md lists Daytona under cloud and sandbox agents. This change
improves the shipped Daytona provider path.

**Additional context**

The branch adds no dependency. Node 24 provides the http2 module. The
host token check and canonical path parser remain the single dispatch
path.

## What Changed

- Carry raw Uint8Array chunks through the adapter, plugin, worker,
runtime, and Daytona layers.
- Encode bytes as base64 only across the JSON-RPC hop, because JSON has
no binary type.
- Add the bounded host HTTP/2 server and the in-sandbox HTTP/2 client
gateway.
- Authenticate every stream with the per-run bridge token before route
work.
- Parse the path once and reuse the canonical result for route and
forwarding work.
- Select http2_v1 for Daytona and fall back once to queue_v1 when the
client preface is absent.
- Add transport, session, stream, and fallback telemetry.
- Mark HTTP/2 as the preferred transport and queue_v1 as the
soft-deprecated fallback.

## Verification

- `npx vitest run packages/adapter-utils/src` — 990 passed and 4
skipped.
- `npx vitest run
server/src/__tests__/plugin-worker-manager-duplex.test.ts` — 32 passed.
- `npx vitest run --config
packages/plugins/sandbox-providers/daytona/vitest.config.ts` — 220
passed and 6 skipped.
- `npx tsc --noEmit` in `packages/adapter-utils`, `packages/shared`,
`packages/plugins/sdk`, and `server` — clean.
- No `package.json` or `pnpm-lock.yaml` file changed.
- The live Daytona test skips when `DAYTONA_API_KEY` is absent.
- The root `npx tsc --noEmit` command has a pre-existing missing
`packages/adapters/droid-local` reference on this branch and on
`master`.

## Risks

- The transport change affects several duplex layers and could expose
byte-boundary errors.
- A missing HTTP/2 client preface falls back once to queue_v1 and
records `preface_missing`.
- The host token check and canonical path parser must remain on the
shared dispatch path.
- The live Daytona test needs `DAYTONA_API_KEY` and does not run in this
agent sandbox.

## Model Used

OpenAI GPT-5, tool-enabled coding agent with repository inspection,
GitHub CLI, and shell 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>
2026-08-25 07:35:39 -07:00
Dotta 0f0e544317
fix(cli): open dashboard after onboarding service starts (#12164)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The CLI can install and start Paperclip as a managed user service
during onboarding.
> - Recent fixes now install the service shim and remove the redundant
foreground start prompt.
> - The service path still ends without a dashboard URL or an open
browser.
> - The server can also move to a free port when the configured port is
busy.
> - This pull request adds a health-aware handoff to the managed
service's actual endpoint.
> - The benefit is that new users can reach Paperclip without starting a
second process.

## Linked Issues or Issue Description

**What happened?**

After interactive onboarding installs and starts the managed service,
the command ends without printing the dashboard URL or opening the
browser. If the configured port is busy, the service can use a fallback
port that the onboarding process does not know.

**Expected behavior**

Onboarding must print the dashboard URL that belongs to the managed
service. An interactive terminal should open the URL after the local
health check succeeds. A non-interactive terminal should only print the
URL.

**Steps to reproduce**

1. Start from a host without an installed Paperclip service.
2. Run another process on the configured Paperclip port.
3. Run `npx paperclipai@<version> onboard` in an interactive terminal.
4. Accept the managed service installation.
5. Observe that the service starts on a fallback port, but onboarding
does not provide or open that dashboard URL.

**Paperclip version or commit**

`b6854e61c` on `master`, after #12148, #12151, and #12153.

**Deployment mode**

Local managed user service on macOS or Linux.

**Installation method**

`npx paperclipai@<version> onboard`. The same onboarding path can also
run after `install.sh`.

Related public pull requests: #12148, #12151, and #12153.

## What Changed

- Record each running CLI server's PID, selected port, and dashboard URL
in atomic per-instance runtime metadata.
- Accept runtime metadata only when its PID matches the active managed
service.
- Wait for the selected runtime endpoint to report healthy before
printing its URL.
- Open the URL in interactive terminals and keep headless runs
browser-free.
- Keep the printed configured URL as a fallback when runtime discovery
fails.
- Use browser-launch wording that only claims the URL was sent to the
opener.
- Add runtime metadata, fallback-port, health handoff, headless, and
failure-path tests.
- Document the managed service dashboard handoff.

## Verification

- `pnpm exec vitest run cli/src/__tests__/onboard-service.test.ts
cli/src/__tests__/runtime-info.test.ts cli/src/__tests__/onboard.test.ts
cli/src/__tests__/open-url.test.ts
cli/src/__tests__/service-health-check.test.ts` — 44 tests passed.
- `node --test scripts/service-onboard-smoke.test.mjs` — 4 tests passed.
- `pnpm -r typecheck` — passed on head `82920596a`.
- `pnpm build` — passed on head `82920596a`.
- `pnpm test:run` — 4,685 tests passed. The command also reported 31
failures in nine server test files outside this change. This machine
generated invalid test ports above 65,535, and some project-skill
fixtures resolved outside the worktree.

## Risks

- Risk is low because the new handoff runs only after a successful
service installation.
- Onboarding can wait up to 60 seconds when runtime metadata or the
health check does not become ready.
- Runtime metadata is matched to the supervisor PID, so stale or
foreground-process metadata is ignored.
- A non-interactive terminal does not open a browser.
- A failed health check or browser launch does not fail onboarding. The
CLI keeps a manual URL visible.

> 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, GPT-5 family. The runtime did not expose the exact model
ID or context window. The model used reasoning, repository tools, GitHub
access, 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>
2026-08-25 09:33:09 -05:00
Dotta ffff1fe6e3
feat(runner): define package API and verification boundary (#12129)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The runner package now has protocol, transport, provider, catalog,
and authorization foundations.
> - Its first upstream package boundary should expose only the
implemented runtime and test-helper surfaces.
> - Rust correctness belongs in the repository existing build
verification, without introducing a parallel release process.
> - Direct package creation must build the files declared by the package
manifest.
> - This pull request defines the minimal package API and verifies the
optimized runner binaries in the existing PR and release Build jobs.
> - The benefit is a production-ready runner package boundary with
minimal build-process change.

## Linked Issues or Issue Description

Refs #11962

This pull request replaces one bounded part of the archived large runner
change. It follows the package-local authorization change in #12126.

## What Changed

- Export only `@paperclipai/paperclip-runner` and
`@paperclipai/paperclip-runner/testing`.
- Keep Node-only fixture loading and semantic conformance helpers out of
the runtime root.
- Add a provider-neutral semantic conformance kit with stable JSON
comparison and fail-closed input checks.
- Keep deferred SDK, eval, browser, React, lab, and command surfaces
private.
- Pin the runner Rust toolchain to 1.97.1 with the minimal profile and
`rustfmt`.
- Run the Rust workspace tests in release mode.
- Launch the optimized `paperclip-runnerd` and fake-harness binaries in
process-level integration coverage.
- Add one `pnpm --filter @paperclipai/paperclip-runner check:all` step
to each existing PR and release Build job.
- Make the existing server `prepack` lifecycle run its existing build
after it prepares UI assets.
- Document that no production adapter starts runnerd yet.

This revision adds no standalone GitHub Actions job. It adds no server
runner dependency or runner vendoring. It adds no Docker bootstrap or
clean-consumer harness. It does not change `pnpm-lock.yaml`.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner check:all`
  - 66 TypeScript tests
  - 8 protocol contract tests
  - 56 Rust unit and integration tests
- Release-mode integration coverage launches the optimized runnerd and
fake-harness binaries.
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/server-package-build-script.test.ts` (2 tests)
- Clean `pnpm pack` from `server/` rebuilt the server and produced both
`package/dist/index.js` and `package/dist/index.d.ts`.
- `node --test scripts/__tests__/release-verify-workflow.test.mjs` (8
tests)
- `pnpm -r typecheck`
- `pnpm build`
- `pnpm check:token-gates`
- `git diff --check`
- No `pnpm-lock.yaml` diff.
- The diff changes 12 files.

## Risks

The runner adds Rust work to the existing Build jobs. These jobs can
take longer on a cold cache. The pinned toolchain makes contributor and
CI behavior reproducible. Cargo tests use `--release` to verify
optimized executables. The server prepack lifecycle now performs the
build that its published entry points require. This can make direct
server packing slower. This pull request does not wire runnerd into the
server. It does not select runnerd for any adapter. Existing application
execution and finalization paths remain unchanged.

## Model Used

OpenAI Codex with GPT-5. Agentic coding mode used repository tools, code
execution, and automated tests.

## 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>
2026-08-25 09:31:48 -05:00
Nicky Leach b6854e61c7
refactor(adapter-utils): rename EffectiveSandboxCapabilities to EffectiveExecutionCapabilities (#12119)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The adapter utilities package defines shared types for agent
execution targets
> - The type name EffectiveSandboxCapabilities describes only one
transport
> - All execution target drivers return the same resolved capability
snapshot
> - This pull request gives the snapshot a general name and keeps the
old type as a deprecated alias
> - The benefit is clearer public vocabulary with source compatibility
for current consumers

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The exported capability snapshot type uses the name
`EffectiveSandboxCapabilities`, although local, SSH, sandbox, and plugin
drivers return it.

**Subsystem affected**

The change affects `packages/adapter-utils` and its server consumers.

**Current behavior**

The public type name points to the sandbox transport. The private parser
also uses the sandbox-only name.

**Proposed behavior**

Use `EffectiveExecutionCapabilities` for the public type and
`parseEffectiveExecutionCapabilities` for the private parser. Keep a
deprecated alias for the old public type.

**Reason and benefit**

The new name matches the established execution-target vocabulary. The
alias keeps existing type imports working during the migration.

**Breaking changes**

None. The runtime field, capability flags, parsed shape, and package
versions do not change.

**Additional context**

GitHub search found no duplicate or related open issue or pull request.

## What Changed

- Rename the exported interface to `EffectiveExecutionCapabilities`.
- Keep `EffectiveSandboxCapabilities` as a deprecated type alias.
- Rename the private parser and update its call site and references.
- Add a type-level test for the deprecated alias.

## Verification

- `npx tsc --noEmit -p packages/adapter-utils`
- `npx vitest run
packages/adapter-utils/src/execution-target-sandbox.test.ts`
- `npx vitest run
server/src/__tests__/environment-execution-target-capabilities.test.ts
server/src/__tests__/environment-execution-target-duplex.test.ts`
- The local checks passed with 133 adapter-utils tests and 31 server
tests.
- Reviewers can confirm that the runtime field and capability flags stay
unchanged.

## Risks

Low risk. The alias protects existing type imports. The change does not
alter runtime behavior or serialized data.

## Model Used

OpenAI Codex, GPT-5, tool use and code execution. The runtime does not
expose the 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>
2026-08-25 07:13:55 -07:00
Devin Foley 8d714c2d84
fix(cli): skip the foreground-start prompt after the service starts (#12153)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The CLI onboarding wizard can install Paperclip as a background
service, and it offers a foreground start when nothing else will serve
> - After #12148, an interactive onboard installs and starts the
service, then still asks "Start Paperclip now?"
> - Answering yes runs the foreground start into the already-running
instance guard, so a fully successful onboard ends with an error message
> - This pull request excludes the just-installed-service case from the
foreground-start prompt
> - The benefit is that an interactive onboard that installs the service
ends cleanly instead of steering the user into a guard refusal

## Linked Issues or Issue Description

Refs #12148 — found while verifying that fix interactively. The
`shouldRunNow` flag already accounts for `serviceInstalled`, but the
interactive TTY fallback prompt did not, so only real interactive runs
hit it: `--yes` runs, CI, and container smokes all skip the prompt
branch.

**What happened?**

Interactive `onboard`, accept the background-service prompt. Output ends
with: service installed and started, then "Start Paperclip now?" → yes →
"Paperclip instance 'default' is already running as
ing.paperclip.paperclipai. Use 'paperclipai service status --instance
default' or pass --force to bypass this safety check."

**What did you expect to happen?**

Onboarding ends cleanly after "Installed and started …" — there is
nothing left to start, so no prompt.

**Steps to reproduce**

Run `npx paperclipai@2026.825.0-nightly.1 onboard --data-dir "$(mktemp
-d)"` in a terminal, accept the service prompt, then accept "Start
Paperclip now?".

## What Changed

- New `shouldOfferForegroundStart` predicate in
`cli/src/onboard-service.ts`: the foreground-start prompt is offered
only when the start was not already decided by flags, the service was
not just installed, onboarding was not invoked by `run`, and the
terminal is interactive.
- Both onboarding call sites in `cli/src/commands/onboard.ts` use the
predicate instead of the inline condition that ignored
`serviceInstalled`.
- Unit tests cover the predicate matrix in
`cli/src/__tests__/onboard-service.test.ts`.

## Verification

- `npx vitest run src/__tests__/onboard-service.test.ts` in `cli/`: 12
passed (5 new).
- `tsc --noEmit` reports no errors in the changed files (remaining
errors are pre-existing in `server/`).
- Manual reproduction of the defect on macOS with `2026.825.0-nightly.1`
before the fix: service installed, started, and healthy, then the prompt
steered into the guard refusal.

## Risks

- Low risk. The prompt still appears in every case it did before except
when the service was just installed and is already serving.
- No behavior change for `--yes`, `--run`, `--install-service` in
non-interactive runs: those paths never reached the prompt.

## Model Used

- Claude Fable 5 (Anthropic, model ID `claude-fable-5`), extended
thinking, agentic 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
2026-08-25 01:06:20 -07:00
Devin Foley 0a01444514
test(release-smoke): cover the background-service leg of onboarding (#12151)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The release pipeline gates each nightly and beta on a smoke suite
that onboards the published npm artifact and drives the golden path
> - That smoke runs onboarding inside a Docker container, and containers
have no service manager, so the background-service leg of onboarding has
zero automated coverage
> - v2026.824.0 shipped a service install that crash-looped on a missing
shim, and every smoke check stayed green (#12148 fixed the defect
itself)
> - This pull request adds a `smoke_service` job that runs the same
published artifact directly on the runner VM's systemd and requires the
installed service to end up serving
> - The benefit is that a release with a broken service install can no
longer pass the release smoke suite

## Linked Issues or Issue Description

Refs #12148 — the fix for the defect this coverage gap let through. The
gap: the release smoke runs `onboard` with `--yes` inside Docker, which
both skips the service prompt and lacks systemd, so no CI job ever
executed `manager.install()` against a real service manager.

## What Changed

- New `scripts/service-onboard-smoke.sh`: onboards the published
artifact with `--yes --install-service` on a systemd host, then fails
unless the managed shim exists and is executable, `paperclipai.service`
is active, and `/api/health` answers. A health response while the unit
is not active also fails, because that is the signature of something
other than the service serving. The script refuses to run over an
existing managed install unless `SMOKE_FORCE=true`, and cleans up after
itself by default so it is safe to run locally.
- New `smoke_service` job in `.github/workflows/release-smoke.yml`:
starts a user systemd session on the hosted runner (`loginctl
enable-linger` + exported `XDG_RUNTIME_DIR`/`DBUS_SESSION_BUS_ADDRESS`),
runs the script against `inputs.paperclip_version`, and uploads
`systemctl status` + journal output as diagnostics.
- No `release.yml` changes needed: `smoke_nightly` and `smoke_beta` call
this reusable workflow, and a `workflow_call` result aggregates all
jobs, so the new job gates nightly promotion automatically.

## Verification

- `bash -n scripts/service-onboard-smoke.sh` passes and the workflow
YAML parses.
- End-to-end: dispatched this branch's Release Smoke workflow against
the published canary that contains #12148; the `smoke_service` job
onboards, installs the service, and verifies the service serves health.
(Run link in PR comments.)
- Negative case: the same assertions fail against v2026.824.0 —
reproduced in a systemd container during the #12148 investigation: shim
missing, unit in a 203/EXEC restart loop.

## Risks

- Low risk to the product: no application code changes.
- Pipeline risk: a flaky user-session setup on the hosted runner would
block nightly promotion. Mitigated by validating the job end-to-end from
this branch before merge, a 30-minute job timeout, and diagnostics
uploaded on every run.
- The service leg only covers systemd. launchd (macOS) still has no CI
coverage; a macOS runner job is a possible follow-up.

## Model Used

- Claude Fable 5 (Anthropic, model ID `claude-fable-5`), extended
thinking, agentic 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
2026-08-25 01:05:27 -07:00
Devin Foley faad235aa2
fix(cli): materialize the managed install before the onboarding service install (#12148)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Interactive onboarding offers to install Paperclip as a background
service, defaulting to yes
> - The service definition targets the managed command shim, but an
ephemeral npx run never installs it, and the service step never checks
> - The result is a crash-looping service, a doctor hint about a
nonexistent port conflict, and a first run that ends with nothing
serving
> - This pull request materializes the managed install before
registering the service, or declines with the repair path
> - The benefit is that saying yes to the service prompt yields a
working service — or an honest explanation

## Linked Issues or Issue Description

**What happened?**

On a machine with no managed install, `npx paperclipai@2026.824.0
onboard` (interactive), accepting the background-service prompt,
produced: a LaunchAgent pointing at `~/.local/bin/paperclipai` (which
does not exist), launchd exit code 78 in a KeepAlive crash loop, doctor
reporting "inactive but the configured port is serving another Paperclip
process — stop the conflicting foreground process" (no such process
existed), and "Service health: fetch failed". Reproduced twice on a
clean field. `latest` has carried this path since v2026.817.0 shipped;
CI never sees it because `--yes` onboarding skips the service prompt.

**Expected behavior**

Accepting the service prompt installs a working service (materializing
the managed payload and shim first when needed), and doctor diagnoses a
missing service binary as exactly that.

**Steps to reproduce**

On macOS with no `~/.local/bin/paperclipai`: `npx paperclipai@latest
onboard`, accept the service prompt, then `launchctl print
gui/$UID/ing.paperclip.paperclipai` (exit code 78, spawn scheduled) and
`paperclipai doctor`.

**Paperclip version or commit**

`2026.824.0` (path present since #10045).

## What Changed

- `cli/src/onboard-service.ts`: after the user opts in, an
`ensureServiceShim` step checks the service shim path. Missing +
managed-store location → run `installCommand` pinned to the onboarding
version (payload, shim, PATH block), then proceed. Missing + custom
`PAPERCLIP_SHIM_PATH`, or install failure → decline with `paperclipai
install` / `paperclipai service install` guidance and install nothing.
- `cli/src/checks/service-health-check.ts`: the runtime check diagnoses
a missing service binary with the install repair hint (instead of the
port-conflict hint); an inactive service with a healthy responder gets a
`warn` attributing the foreign process instead of a plain "Healthy"
pass.
- Tests: new cases for shim materialization ordering,
decline-on-failure, missing-binary diagnosis, and foreign-responder
attribution; existing fixtures updated to inject the new dependencies.

## Verification

- `vitest run` on both touched suites: 15 pass.
- `tsc --noEmit` error count identical to the master baseline (16
pre-existing, all in `server/`, none in changed files).
- The live failure was reproduced on macOS before the fix (twice, clean
field) and the mechanism confirmed in source: `install()` writes the
definition and bootstraps launchd only; `install-store` was previously
reachable solely from the `install`/`update` commands.

## Risks

- Low: the new path runs only when the user opts into the service and
the shim is absent. The managed install resolves the pinned onboarding
version from the public registry; on failure the flow declines exactly
as it does on unsupported platforms. `--yes` quickstarts, Docker, and
managed installs are untouched.

## Model Used

Claude Fable 5 (Claude Code)

## Pre-submission 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
2026-08-24 23:30:54 -07:00
Devin Foley fa40a1b8d5
docs(release): canonicalize stable notes for v2026.824.0 (#12139)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Stable notes are drafted beta-keyed during the soak and published
verbatim as the GitHub Release
> - After the stable ships, the canonicalize job moves the file to its
durable home, releases/vYYYY.MDD.P.md
> - v2026.824.0 just shipped from the master-side beta notes, and the
job pushed this rename branch
> - This pull request lands that rename, keeping the stable-notes record
complete at the canonical path
> - The benefit is one canonical notes location per stable, with the
pinned shipped content

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The `releases/` record on master after the v2026.824.0 promotion.

**Current behavior**

The shipped notes live at `releases/beta/v2026.818.0-beta.1.md`;
`releases/v2026.824.0.md` does not exist.

**Proposed behavior**

The file moves to `releases/v2026.824.0.md`, content pinned to the
revision the release read (machine-generated by the
`canonicalize_stable_notes` job).

**Reason and benefit**

The durable stable-notes invariant holds: every shipped stable has its
notes at `releases/vYYYY.MDD.P.md`.

## What Changed

- `git mv`-equivalent rename of the beta-keyed notes to
`releases/v2026.824.0.md`, exactly as the release published them.

## Verification

- Branch pushed by the release run's `canonicalize_stable_notes` job
(run 32806191945) from the preflight-pinned notes revision; the GitHub
Release v2026.824.0 body matches this content.

## Risks

- None; docs-only rename.

## Model Used

Claude Fable 5 (Claude Code) — PR opened for the machine-pushed branch;
a GITHUB_TOKEN-created PR would not run required checks.

## Pre-submission 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

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-24 21:37:17 -07:00
Devin Foley 14867bd186
test(release-smoke): follow the mission-less onboarding reorder (#12135)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The nightly release lane publishes only after the release smoke
suite passes against the newest canary
> - Onboarding was reordered: step 1 now creates the company and routes
straight to the agent step, and the mission step is gone (collected
later in the tenant app, deliberately writing no goal)
> - The smoke spec still walked the removed mission step, so the
scheduled nightly has been red since the reorder shipped
> - This pull request updates the spec to the current flow and asserts
the deliberate empty goal list
> - The benefit is a green nightly lane and an unblocked beta promotion
from current master

## Linked Issues or Issue Description

**What happened?**

The scheduled `Release` nightly run fails in `smoke_nightly / smoke`
since 2026-08-23 (runs 32630184811, 32710905212):
`docker-auth-onboarding.spec.ts` waits for the `Define your mission`
heading after step 1, but the wizard now routes 1 → 3 with no mission
step (the step buttons literally skip from 1 to 3). The retry then fails
on step 1 because the first attempt's company persists.

**Expected behavior**

The smoke passes against canaries carrying the reordered wizard, and the
nightly lane publishes again.

**Steps to reproduce**

Run `scripts/docker-onboard-smoke.sh` with
`PAPERCLIPAI_VERSION=2026.824.0-canary.7` and `pnpm run
test:release-smoke` against it.

**Paperclip version or commit**

`2026.824.0-canary.7`

Related (not duplicates): #11565 updated this same spec for the
chat-first rewrite; this is the follow-up for the mission-less reorder.

## What Changed

- Remove the mission-step interaction; step 1's "Next" now creates the
company and the spec goes straight to the agent step.
- Replace the mission-goal API assertion with the truthful one:
onboarding deliberately writes no goal, so a fresh company's goal list
is empty.
- Update step comments to match the shipped flow.

## Verification

- Local run of the exact CI harness against
`paperclipai@2026.824.0-canary.7`: 1 passed (6.8s), exit 0.
- The suite's remaining API assertions (company, CEO agent, seeded task
assignment, landed issue URL, assignment-sourced heartbeat run) pass
unchanged.

## Risks

- Low risk: test-only. The spec remains copy-coupled to the wizard —
this is the third drift in two weeks; stable `data-testid` hooks in the
wizard remain the durable fix and can follow separately.

## Model Used

Claude Fable 5 (Claude Code)

## Pre-submission 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
2026-08-24 21:08:22 -07:00
Devin Foley 890ab9acfe
feat(release): thorough notes skeletons — nest each PR's summary at creation (#12124)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The release workflow drafts the upcoming stable's notes skeleton the
moment a beta publishes
> - That skeleton was a bare list of commit subjects, so the notes only
reached the shipped stable's depth after a later authoring pass during
the soak
> - Stable release notes are consistently verbose and thorough; the
initial draft should start that way too
> - This pull request nests each referenced PR's own summary under its
subject line at creation time, and states the density bar in the
authoring skill
> - The benefit is a thorough raw document from day one of the soak,
with no LLM tokens in Actions

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The `draft_stable_notes` skeleton generated at beta publish
(`scripts/draft-stable-notes.sh`).

**Current behavior**

The skeleton groups bare commit subjects by conventional-commit type.
All substance arrives later, when a maintainer or agent rewrites it —
reviewed maintainer feedback: stable notes are a lot more verbose, and
the initial beta notes should be consistent with that.

**Proposed behavior**

Each subject that references a PR carries that PR's own summary nested
beneath it — the PR template's "What Changed" bullets, else the first
prose lines — fetched best-effort via `gh` and skipped silently when
unavailable. The release-changelog skill now states the density bar
explicitly: the beta-keyed draft ships verbatim as the stable's notes
and is written at the previous stable's depth from the first pass.

**Reason and benefit**

The notes author starts from a thorough raw document instead of a commit
list, and beta-time notes match the verbosity the stable will ship with.

## What Changed

- `scripts/draft-stable-notes.sh`: `enrich_pr` nests PR summaries under
subjects; best-effort (`gh` failure or
`DRAFT_NOTES_SKIP_PR_ENRICHMENT=1` degrades to today's output);
pipefail-safe when a "What Changed" section has no bullets.
- `.github/workflows/release.yml`: the `draft_stable_notes` step gets
`GH_TOKEN` so `gh` can read PR bodies.
- `.agents/skills/release-changelog/SKILL.md`: "write at full stable
depth from the first pass" guideline.
- `scripts/draft-stable-notes.test.mjs`: three new tests — enrichment
rendering via a fake `gh`, silent degradation without one, and the
sparse-body case that previously killed the script under `set -o
pipefail`.

## Verification

- `node --test scripts/draft-stable-notes.test.mjs` — 11 pass.
- Live run against the real repository for the current beta
(`2026.818.0-beta.1`, 172 commits): exit 0, 439 nested summary lines;
spot-checked entries carry the correct PRs' What Changed bullets.
- `bash -n` on the script; `release.yml` re-parsed as YAML.

## Risks

- Low: the publish path is untouched; enrichment is read-only `gh` calls
in the post-publish draft job and degrades to the current skeleton on
any failure. Roughly one API call per commit in the range (~170 today) —
well inside the token's rate budget, adds a couple of minutes to a job
with a 10-minute timeout.

## Model Used

Claude Fable 5 (Claude Code)

## Pre-submission 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
2026-08-24 20:51:33 -07:00
Devin Foley ae9711da48
docs(release): re-date the 2026.818.0-beta.1 stable notes to v2026.824.0 (#12113)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Stable versions date the promotion, and the promotion reads its
notes from master
> - The merged notes for beta 2026.818.0-beta.1 assumed an Aug 21
promotion; the beta soaked longer
> - This pull request re-dates the header to today's resolved version,
v2026.824.0
> - The benefit is a GitHub Release whose title, date, and body agree

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The stable notes header for the promotion happening today.

**Current behavior**

`releases/beta/v2026.818.0-beta.1.md` is titled `# Paperclip
v2026.821.0`, `> Released: 2026-08-21`.

**Proposed behavior**

`# Paperclip v2026.824.0`, `> Released: 2026-08-24` — matching
`./scripts/release.sh stable --date 2026-08-24 --print-version`.

**Reason and benefit**

The file publishes verbatim as the GitHub Release body; the header
should match the version actually minted.

## What Changed

- Three header/intro lines re-dated. Nothing else.

## Verification

- `./scripts/release.sh stable --date 2026-08-24 --print-version` →
`2026.824.0`.

## Risks

- None; docs-only.

## Model Used

Claude Fable 5 (Claude Code)

## Pre-submission 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
2026-08-24 20:42:25 -07:00
Nicky Leach d1573244b5
refactor: disambiguate the Telemetry and Observability data paths (#12128)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Paperclip records first-party events, OpenTelemetry data, and local
run-log events
> - The code and documents used one term for these three data paths
> - This naming made the required review level unclear
> - This pull request names each data path in the module names,
documents, and code comments
> - The benefit is a clear review rule without a runtime change

## Linked Issues or Issue Description

**Issue type**

Unclear or confusing.

**Where is the issue?**

`packages/shared/src/telemetry/README.md`, `doc/observability.md`,
`doc/run-log-events.md`, and the duplex instrumentation modules.

**What's wrong?**

The repository used Telemetry for first-party events, OpenTelemetry
data, and local run-log events. This usage made the data path and review
level unclear.

**Suggested fix**

Use Telemetry only for Paperclip first-party events. Use Observability
for OpenTelemetry data. Use the run log for rows in
`heartbeat_run_events`.

Related public pull requests: #8476 and #9672.

## What Changed

- Rename the duplex instrumentation modules and identifiers from
`Telemetry` to `Observability`.
- Move the Observability and run-log contracts out of the Telemetry
README.
- Add `doc/observability.md` and `doc/run-log-events.md` as the
canonical documents.
- Add a file-path review rule to `AGENTS.md`.
- Correct the remaining code comments that name the wrong data path.
- Keep all event names, payloads, database records, spans, configuration
keys, environment variables, and runtime paths unchanged.

## Verification

- `npx vitest run packages/shared/src/telemetry/readme-contract.test.ts`
passes.
- `npx vitest run packages/adapter-utils/src/published-exports.test.ts`
passes.
- `npx vitest run
packages/adapter-utils/src/acpx-engine/startup-timing.test.ts` passes
with 42 tests.
- `pnpm --filter @paperclipai/adapter-utils typecheck` passes.
- `pnpm --filter server typecheck` passes.
- The old module name does not remain in TypeScript or JSON files,
except for the intentional publication guard.
- CI and Greptile checks remain pending after PR creation.

## Risks

- The old duplex module subpath no longer has a compatibility shim. The
board accepted this intentional hard break.
- The new duplex module subpath stays blocked from package publication.
- The change has no runtime effect. The main risk is an incorrect
document or module reference.

## Model Used

OpenAI GPT-5 Codex, exact model ID `gpt-5`, with tool use 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 described the issue in-PR with the documentation issue
fields
- [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 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>
2026-08-24 16:42:33 -07:00
Dotta 42b8f7ab2f
feat(runner): authorize semantic tool dispatch (#12126)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The runner package defines a provider-neutral protocol and semantic
action catalog.
> - Catalog membership alone must not grant access to an action.
> - Each run needs current company, actor, task, claim, mode, and
application-binding authority.
> - Mutating actions also need safe retry behavior and durable receipts.
> - This pull request adds a package-local authority and dispatch layer.
> - The benefit is a small and testable trust boundary before server
integration lands.

## Linked Issues or Issue Description

Refs #11962

This pull request replaces one bounded part of the archived large runner
change.

## What Changed

- Add run-scoped tool projection and optional tool discovery.
- Require an explicit application binding before an action is visible.
- Intersect actor claims with claims delegated to the run.
- Recheck company, actor, task, mode, state, role, claim, and policy
authority before each call.
- Validate action input and output with the canonical catalog schemas.
- Redact protected values and keep raw tool content out of semantic
receipts.
- Require atomic idempotency claims for mutating actions.
- Replay exact completed retries and reject changed or concurrent
retries.
- Recover a durable completed receipt if the primary receipt commit
fails, without re-executing the mutation.
- Add bounded authorization records and PRP semantic input and result
receipts.
- Document that this change adds no server binding or production tool
installation.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner check:all`
- `pnpm -r typecheck`
- `pnpm check:token-gates`
- `pnpm build`
- 60 package TypeScript tests pass.
- 56 Rust unit and integration tests pass.
- Protocol, replay, and cross-language conformance checks pass.
- `pnpm test:run` completed with 4,684 passing and 19 skipped tests. It
reproduced 32 local baseline failures across 9 unchanged server files;
all corresponding hosted test shards pass.
- Every applicable GitHub Actions gate passes. The Storybook job skipped
because this PR has no UI changes.
- Socket and Snyk pass with no findings. Superagent completed neutral
with zero annotations because its external sandbox did not start within
120 seconds.
- Greptile is 5/5 with no unresolved actionable comments.
- The diff changes 11 files.

## Risks

The main risk is an authorization or idempotency error at the tool
boundary. The dispatcher fails closed for malformed authority,
unavailable receipt storage, stale authority, unauthorized actions,
protected input, invalid binding output, and unrecoverable receipt
completion. The receipt store must recover a completed mutation outcome
idempotently if its primary commit fails; otherwise the claim remains
reserved for operator recovery rather than allowing automated
re-execution. Unbound actions are absent. No server or provider installs
these tools in this change. Existing adapters and application behavior
do not change.

## Model Used

OpenAI Codex with GPT-5. Agentic coding mode used repository tools, code
execution, and automated tests.

## 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 the affected tests locally and they pass; full-suite
baseline exceptions are documented above
- [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>
2026-08-24 17:28:54 -05:00
Dotta 23048f1219
Add canonical semantic action catalog to Paperclip Runner (#12121)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip Runner now has a durable PRP transport and a Codex
provider bridge.
> - Codex must use stable, provider-neutral action contracts before
Paperclip can grant run-scoped tool access.
> - A catalog must describe actions without granting permission to
discover or invoke them.
> - Generated inventory must stay synchronized with its TypeScript
source.
> - This pull request adds the canonical Codex-spine semantic action
catalog inside the runner package.
> - The benefit is a small review unit for schemas and inventory before
authorization and dispatch land.

## Linked Issues or Issue Description

**Subsystem affected**

Cross-cutting. This pull request extends private runner infrastructure
in `packages/paperclip-runner`.

**Problem or motivation**

The Codex provider bridge has no canonical description of the Paperclip
actions that a later authorization layer can project into a run.
Independent operation lists can drift in names, claims, task modes,
effects, and input bounds.

**Proposed solution**

Add one immutable v1 catalog for the first 27 Codex-spine actions. Give
each action a stable identifier, placement, effect, required claims,
supported task modes, and JSON Schema input and output contracts.
Generate a deterministic JSON inventory from that source and fail
package checks on drift.

**Alternatives considered**

The combined runner branch contains larger live and scenario catalogs
with authorization, bindings, labs, and other providers. That change is
too large for this review unit. A generic API escape hatch would also
bypass the operation-level boundary, so this catalog excludes it.

**Roadmap alignment**

This work supports the governed tool access direction in `ROADMAP.md`.
It does not add a tool gateway, application binding, server endpoint, or
production authorization decision.

**Additional context**

Refs #12111 and #11962. Pull request #12111 was squash-merged first.
This branch starts at the resulting `master` commit. Its delta is 10
files.

## What Changed

- Added 27 versioned, provider-neutral semantic action declarations for
the Codex spine.
- Added bounded JSON Schema input contracts and normalized operation
receipt output contracts.
- Added placement, effect, claim, mode, and role metadata.
- Added a deeply frozen public catalog and an operation lookup helper.
- Added a deterministic checked-in JSON inventory and generation
commands.
- Added a byte-for-byte drift gate to the package build.
- Added AJV schema compilation, mutation-bound, forged-field,
immutability, inventory, and non-executable-boundary tests.
- Exported only the catalog types and declarations from the existing
package root.
- Documented that catalog membership does not grant discovery,
authorization, dispatch, or application binding.
- Kept server code, UI code, other providers, scenario-only actions,
labs, generic API access, authorization, dispatch, and receipts
processing out of this pull request.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner check:all` passes.
- TypeScript protocol tests pass: 8 Node tests and 49 Vitest tests.
- All package Rust tests and conformance and replay parity checks pass.
- `pnpm --filter @paperclipai/paperclip-runner
check:semantic-action-catalog` passes.
- `pnpm -r typecheck` passes.
- `pnpm build` passes.
- `pnpm check:token-gates` passes.
- Prettier and `git diff --check` pass for the changed source and
documentation files.
- The generated catalog matches its source byte for byte.
- The secret scan is clean.
- The delta against `master` is 10 files. `pnpm-lock.yaml` is unchanged.
- `pnpm test:run` completed locally with 4,692 passing tests, 19 skipped
tests, and 24 failures in 8 unchanged server test files. The failures
reproduce the established local macOS path-alias, listener, and
workspace-runtime baseline. No changed-file test failed. Linux CI
remains the repository handoff authority.
- The full Linux PR workflow passes, including the aggregate `verify`
gate.
- Snyk, Socket, Superagent security, and supply-chain checks pass.
- Greptile is 5/5 with no actionable comments, recommendations, or
follow-ups.
- Storybook visual regression skipped by design because this pull
request changes no UI file.
- Browser and migration tests are not applicable because this pull
request changes no server, UI, database, or migration file.

## Risks

Production behavior is unchanged because no consumer projects this
catalog into a provider run. The main risks are contract drift,
unbounded mutation input, forged scope fields, accidental executable
authority, and generated inventory drift. Closed input schemas, explicit
bounds, a frozen catalog, tests, and the byte drift gate cover these
risks. The later authorization layer must still bind every action to the
active run and company before discovery or invocation.

I checked `ROADMAP.md`. This change is private contract infrastructure
for the governed tool access direction. It does not duplicate a shipped
or public product surface.

## Model Used

OpenAI Codex with GPT-5 was used. The exact serving model ID and context
size were not exposed. The model used high reasoning, repository tools,
GitHub tools, and local 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
- [ ] 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>
2026-08-24 16:26:21 -05:00
Dotta 4ffa8de4e2
Add Codex provider bridge to Paperclip Runner (#12111)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The package-local runner now has a durable PRP transport, but it
cannot execute a real provider.
> - The first provider must preserve PRP identities while using Codex
native thread and turn identities.
> - Recovery must resume the same Codex thread without starting a
duplicate turn.
> - Provider output must become bounded and provider-neutral before it
crosses PRP.
> - Semantic tools must remain unavailable until the catalog and
authorization layers exist.
> - This pull request adds the Codex provider bridge inside the runner
package only.
> - The benefit is a reviewable provider slice with no server or
user-facing behavior change.

## Linked Issues or Issue Description

**Subsystem affected**

Cross-cutting. This pull request extends private provider infrastructure
in `packages/paperclip-runner`.

**Problem or motivation**

The durable runner from #12100 has no production provider. It cannot
start Codex app-server, map its events, cancel or steer a turn, deliver
a structured question, or recover a native thread after process restart.

**Proposed solution**

Add a supervised Codex app-server transport and a normalized runner
backend. Persist the Codex thread and active turn identities. Resume and
inspect the exact thread after restart. Convert supported notifications
into bounded PRP events. Keep the dynamic tool inventory empty.

**Alternatives considered**

The combined runner branch implements several providers, semantic tools,
server coordination, and UI integration together. That change is too
large for one review unit. Reusing the direct `codex_local` adapter
would also couple this package layer to the existing server execution
path.

**Roadmap alignment**

This work supports the governed tools and self-healing run direction in
`ROADMAP.md`. It does not add a server endpoint, runtime adapter,
rollout flag, or user-facing behavior.

**Additional context**

Refs #12100 and #11962. Pull request #12100 was squash-merged first.
This branch starts at the resulting `master` commit. Its current delta
is 16 files.

## What Changed

- Added a Codex-only app-server process transport with bounded JSONL
frames and buffered notifications.
- Added strict provider descriptor validation for the Codex driver,
working directory, launch arguments, model, instructions, and
non-interactive approval policy.
- Started new Codex threads with an empty dynamic tool inventory and the
named workspace-only permission profile.
- Added native turn start, steering, interruption, cancellation, thread
reads, and structured question responses.
- Added thread and active-turn binding checks for provider requests and
notifications.
- Added provider-neutral normalization for session, turn, item, plan,
usage, tool execution, notice, and structured input events.
- Bounded and redacted provider text and process output before durable
persistence.
- Added private atomic provider state for the descriptor, thread ID,
account session ID, active turn ID, and unacknowledged normalized
events.
- Added exact-thread recovery through `thread/resume` and `thread/read`.
Recovery does not issue another `turn/start` for an active turn.
- Preserved active native turn identity across unexpected provider exit
and reconciled it before later start, interrupt, or snapshot commands.
- Added stable provider-event identities, per-event durable commit and
acknowledgement, and a bounded fingerprint receipt journal that prevents
duplicate delivery across outbox and provider-ack crash windows.
- Extended the durable command executor with provider event polling and
explicit process shutdown on stop, suspend, revocation, lease expiry,
and runtime expiry.
- Preserved completed shutdown behavior when the command result is
replayed after a disconnect.
- Added a fake Codex app-server and integration tests for response
buffering, structured questions, interruption, provider exit,
unacknowledged-event recovery, durable resume, and duplicate-turn
prevention.
- Added a focused `test:codex` package command for the provider
integration suite.
- Kept server code, UI code, other providers, semantic catalogs, tool
authorization, and production runtime selection out of this pull
request.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner check:all` passes.
- TypeScript contract tests pass: 8 Node tests and 44 Vitest tests.
- Rust tests pass: 43 unit tests, 5 Codex integration tests, 3 public
durable-recovery tests, 2 local-runner tests, and 3 process-supervisor
tests.
- Rust conformance and replay parity checks pass against the shared PRP
fixtures.
- `cargo clippy --workspace --all-targets -- -A
clippy::filter-map-bool-then -D warnings` passes. The narrow allow
covers an unchanged replay implementation from the preceding contract
pull request.
- `pnpm -r typecheck` passes.
- `pnpm build` passes.
- `pnpm check:token-gates` passes.
- `git diff --check` passes.
- The delta against `master` is 16 files. The package lockfile is
unchanged. The PR workflow generates its temporary lockfile artifact
from the changed package manifest.
- `pnpm test:run` completed locally with 4,690 passing tests, 19 skipped
tests, and 26 failures in 8 unchanged server test files. The failures
reproduce the established local macOS path-alias, listener, port-range,
and workspace-runtime baseline. No changed-file test failed. Linux CI
remains the repository handoff authority.
- Browser and migration tests are not applicable because this pull
request changes no server, UI, database, or migration file.
- The full Linux PR workflow passes. One unchanged heartbeat recovery
test timed out on the first pass and passed on the failed-only rerun;
the aggregate `verify` gate is green.
- Greptile is 5/5 on the final commit. All four review threads are
resolved.

## Risks

Production behavior is unchanged because no server code starts this
provider. The main risks are a provider process escape, cross-thread
event confusion, secret leakage, duplicated turns, duplicated or lost
provider events, lost questions, and unsafe recovery. Process-group
supervision, identity binding, private bounded state, redaction, durable
command replay, retained event acknowledgements, bounded durable
receipts, exact-thread reconciliation, and integration tests cover these
risks. Semantic tools remain undiscoverable in this layer.

I checked `ROADMAP.md`. This change is private provider infrastructure
for planned control-plane work. It does not duplicate a shipped or
public product surface.

## Model Used

OpenAI Codex with GPT-5 was used. The exact serving model ID and context
size were not exposed. The model used high reasoning, repository tools,
GitHub tools, and local 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
- [ ] 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>

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-24 15:19:14 -05:00
github-actions[bot] dc621184a1
chore(lockfile): refresh pnpm-lock.yaml (#12094)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - CI owns pnpm-lock.yaml: manifest-changing PRs merge without it, and
this automation lands the regenerated lockfile right after
> - The runner-supervision and PRP-transport merges (#12095, #12100)
added devDependencies to packages/paperclip-runner, desyncing the
lockfile
> - Every frozen-lockfile install on master has failed since, taking CI
down repo-wide
> - This pull request lands the regenerated entries for the
paperclip-runner importer
> - The benefit is CI works again on every branch

## Linked Issues or Issue Description

**What happened?**

Since #12095 merged, every CI job fails in ~15 seconds at `pnpm install
--frozen-lockfile`: the lockfile's `packages/paperclip-runner` importer
does not match its `package.json`.

**Expected behavior**

`pnpm install --frozen-lockfile` succeeds on master.

**Steps to reproduce**

`npx pnpm@9.15.4 install --frozen-lockfile` on master before this
change.

**Paperclip version or commit**

master at `b76e36d6c`.

## What Changed

- `pnpm-lock.yaml` regenerated by the refresh automation (pnpm 9.15.4,
`--lockfile-only`); the diff covers only the `packages/paperclip-runner`
importer's new devDependencies. A human empty commit triggered the
required checks (the automation's `GITHUB_TOKEN` push cannot — fix
proposed in #12115).

## Verification

- `npx pnpm@9.15.4 install --frozen-lockfile` verified locally against
this exact lockfile content (fails on master without it).
- Full required suite green on this PR (30 checks).

## Risks

- None beyond lockfile content; the diff touches no version outside the
paperclip-runner importer.

## Model Used

Claude Fable 5 (Claude Code) — body authored on behalf of the lockfile
automation.

## Pre-submission 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

---------

Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com>
Co-authored-by: Devin Foley <devin@paperclip.ing>
2026-08-24 12:36:34 -07:00
Dotta b76e36d6cf
Add durable PRP transport and recovery (#12100)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The package-local runner can supervise a local process, but it
cannot yet survive a broken controller connection.
> - A production transport must authenticate both peers without putting
the bootstrap secret on the wire.
> - Commands and events must remain bounded, ordered, and recoverable
across reconnects and crashes.
> - Retrying an uncertain side effect is unsafe, so indeterminate
outcomes must fail closed instead of running twice.
> - This pull request adds those transport and recovery guarantees
inside the runner package only.
> - The benefit is a durable PRP boundary that can be reviewed before
any provider or server integration exists.

## Linked Issues or Issue Description

**Subsystem affected**

Cross-cutting. This pull request extends private transport
infrastructure in `packages/paperclip-runner`.

**Problem or motivation**

The local runner introduced by #12095 has no authenticated network
handshake, durable outbox, reconnect lease, cumulative acknowledgement,
or crash-safe command journal. A dropped connection could otherwise lose
an event or tempt a controller to repeat a side effect whose outcome is
unknown.

**Proposed solution**

Add an authenticated PRP v1 WebSocket transport, encrypted frames,
lease-based reconnects, a bounded durable event outbox, cumulative
acknowledgements, and an idempotent command journal. Preserve pending
commands before execution and classify the crash window as indeterminate
so an uncertain side effect is never repeated automatically.

**Alternatives considered**

The combined runner branch implements transport together with Codex,
semantic tools, and server coordination. That change is too large for
one review unit. Keeping transport in memory would make reconnect and
crash recovery unverifiable. Re-running a pending command after restart
would weaken the at-most-once side-effect boundary.

**Roadmap alignment**

This work supports the governed tools and self-healing run direction in
`ROADMAP.md`. It does not add a production provider, server endpoint,
adapter, feature flag, or user-facing behavior.

**Additional context**

Refs #12095 and #11962. Pull request #12095 was squash-merged first.
This branch has been rebased onto the resulting `master` commit, and its
current delta is 13 files.

## What Changed

- Added a loopback-only WebSocket connection policy with one-time DNS
resolution and pinned reconnect addresses.
- Added an HMAC mutual-authentication handshake that never sends the
bootstrap ticket over the socket.
- Added AES-256-GCM secure frames with per-direction keys, monotonic
counters, and session-bound authenticated data.
- Added one-use bootstrap-ticket handling and lease-based reconnect
validation with expiry, revocation, and epoch checks.
- Added a private, symlink-resistant state directory with atomic,
synchronized state replacement.
- Added a bounded durable event outbox, priority-zero reserve,
cumulative acknowledgements, and reconnect replay of only the
unacknowledged suffix.
- Added a bounded command journal with contiguous sequence enforcement,
persistent results, and deterministic duplicate responses. Duplicate
replay requires a SHA-256 match over the complete canonical command.
- Persisted commands before their effects. A crash after persistence but
before result storage returns an indeterminate terminal result and does
not execute the command again.
- Migrated pre-fingerprint command journals by compacting through their
persisted controller cursor. Legacy redelivery fails closed instead of
reconstructing an incomplete identity or repeating an uncertain effect.
- Added strict limits and validation for frames, state, results, outbox
entries, command history, and redacted diagnostics.
- Added a transport-only `paperclip-runnerd --connect-url` mode. It
handles lifecycle commands and rejects provider commands because no
provider is present in this pull request.
- Added a full disconnect-before-ack fault test that reconnects with the
lease, replays identical command and event state, and proves the effect
ran once.
- Kept provider transports, semantic tools, server integration, and
production runtime selection out of this pull request.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner check:all` passes.
- TypeScript contract tests pass: 8 Node tests and 44 Vitest tests.
- Rust tests pass: 33 unit tests, 3 public durable-recovery integration
tests, plus the existing 2 local-runner and 3 process-supervisor tests.
- The disconnect-before-ack, lease reconnect, duplicate command,
malformed state, unknown command, bounds, and crash-window tests pass.
- Rust conformance and replay parity checks pass against the shared PRP
fixtures.
- `cargo clippy --workspace --all-targets -- -A
clippy::filter-map-bool-then -D warnings` passes. The narrow allow
covers an unchanged replay implementation from the preceding contract
pull request.
- `pnpm -r typecheck` passes.
- `pnpm build` passes.
- `pnpm check:token-gates` passes.
- `git diff --check` passes.
- The delta against `master` is 13 files. The package lockfile is
unchanged.
- `pnpm test:run` completed locally with 4,686 passing tests, 19 skipped
tests, and 30 failures in 8 unchanged server test files. The failures
reproduce the established local macOS path-alias, listener, port-range,
and workspace-runtime baseline. No changed-file test failed; Linux CI
remains the repository handoff authority.
- Storybook visual regression is not applicable because this pull
request changes no UI or story files.

## Risks

Production behavior is unchanged because no server code starts or
connects to this transport. The main risks are secret disclosure, forged
or replayed frames, state corruption, unbounded disk growth, duplicated
side effects, and incorrect recovery. Mutual authentication, encrypted
counter-bound frames, private atomic state, explicit bounds, cumulative
acknowledgements, a durable command journal, fail-closed indeterminate
recovery, and fault-injection tests cover these risks.

I checked `ROADMAP.md`. This change is private transport infrastructure
for planned control-plane work. It does not duplicate a shipped or
public product surface.

## Model Used

OpenAI Codex with GPT-5 was used. The exact serving model ID and context
size were not exposed. The model used high reasoning, repository tools,
GitHub tools, and local 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
- [ ] 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>

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-24 12:55:08 -05:00
Dotta 6b20cc97cc
Add local fake runner supervision (#12095)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip Runner needs a small local process model before it can
connect to a production provider or server.
> - The TypeScript PRP contracts now define the expected replay
behavior.
> - A second language implementation must produce the same result from
the same fixtures.
> - Local child processes also need bounded input, bounded output, and
complete descendant cleanup.
> - This pull request adds a package-local Rust runner, a scripted fake
harness, and deterministic parity checks.
> - The benefit is a testable process boundary with no production
Paperclip behavior change.

## Linked Issues or Issue Description

**Subsystem affected**

Cross-cutting. This pull request adds private test infrastructure to
`packages/paperclip-runner`.

**Problem or motivation**

The PRP contracts have no second implementation on `master`. There is
also no small harness that can prove process cleanup, command
idempotency, terminal reconciliation, or bounded JSONL handling without
a production provider.

**Proposed solution**

Add a minimal Rust workspace. Add a local runner process, a scripted
fake harness, a bounded process supervisor, and Rust conformance and
replay checks. Keep all binaries package-local. Do not connect them to
the Paperclip server.

**Alternatives considered**

The combined runner branch includes provider transports, durable
networking, SDKs, labs, and server behavior. That change is too large
for this review unit. A TypeScript-only harness would not test
cross-language contract parity.

**Roadmap alignment**

This work supports the governed tools and self-healing run direction in
`ROADMAP.md`. It does not add a user-facing runtime, adapter, endpoint,
or rollout flag.

**Additional context**

Refs #12091 and #11962. Pull request #12091 was merged before this
branch opened. This branch is based on the current `master`. Its delta
is 25 files.

## What Changed

- Added a minimal locked Rust workspace with only `serde` and
`serde_json` dependencies.
- Added a package-local `paperclip-runnerd` local mode and a scripted
fake harness.
- Added bounded controller input, harness input, subprocess output
queues, line sizes, log retention, script sizes, script steps, and
command history.
- Added contiguous controller and harness sequence checks and
equivalent-command replay handling.
- Added process-group supervision that cleans up child processes and
remaining descendants after forced or natural harness exit.
- Added runner-owned terminal reconciliation for success, failure,
interruption, cancellation, controller closure, and protocol failure.
- Added Rust conformance output and deterministic replay summaries for
the shared PRP fixtures.
- Added fake scripts for success, failure, interruption, interaction,
duplicate terminal output, process cleanup, and oversized output.
- Added package scripts and documentation for the Rust and
cross-language checks.
- Kept provider transport, server integration, semantic tools, and
production runtime selection out of this pull request.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner check:all` passes.
- TypeScript contract tests pass: 8 Node tests and 44 Vitest tests.
- Rust tests pass: 20 unit tests, 2 local-runner tests, and 3
process-supervisor tests.
- The Rust conformance and replay parity checks pass against the shared
fixtures.
- The natural-exit and forced-exit tests confirm that the harness and
its worker process are stopped.
- The oversized-frame test confirms that a harness frame above the
configured limit is rejected.
- `pnpm -r typecheck` passes after the final rebase to `master`.
- `pnpm build` passes after the final rebase to `master`.
- `pnpm check:token-gates` passes.
- `git diff --check` passes.
- The delta against `master` is 25 files. The package lockfile is
unchanged.
- `pnpm test:run` completed locally with 4,686 passing tests, 19 skipped
tests, and 30 failures in 8 unchanged server test files. The failures
are local macOS path-alias, listener, port-range, and workspace-runtime
baseline failures. No changed-file test failed, and every applicable
Linux CI shard passes.
- Storybook visual regression skipped intentionally because this pull
request changes no UI or story files.

## Risks

Low production risk. No server code invokes the new binaries. The
package remains private. The main risks are process leaks, unbounded
local input, and cross-language drift. Bounded queues and sizes,
process-group cleanup tests, fixture manifests, and parity checks cover
these risks.

I checked `ROADMAP.md`. This change is private test infrastructure for
planned control-plane work. It does not duplicate a shipped or public
product surface.

## Model Used

OpenAI Codex with GPT-5 was used. The exact serving model ID and context
size were not exposed. The model used high reasoning, repository tools,
GitHub tools, and local 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
- [ ] 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>

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-24 12:16:48 -05:00
Devin Foley 83fefaadd1
fix(grok_local): do not warn when the default model sentinel is unavailable (#12062)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Each agent runs under an adapter. The `grok_local` adapter runs the
Grok Build CLI.
> - The adapter has an environment test. It probes the CLI and reports
checks to the operator.
> - `DEFAULT_GROK_LOCAL_MODEL` is `"grok-build"`. This value is a
sentinel. It means "use the Grok CLI's own default model".
> - `execute.ts` only passes `--model` when the configured model differs
from the sentinel. So the sentinel is never sent to grok.
> - The environment test still compared the sentinel to the models that
`grok models` lists. Real grok never lists `grok-build`.
> - So every probe emitted a false "Configured model not found" warning,
even on a correctly configured agent.
> - This pull request stops the false warning and keeps the real check
for user-set models.
> - The benefit is an accurate environment test: operators see a warning
only when it is real.

## Linked Issues or Issue Description

No public issue exists. The problem, in bug-report form:

**What happened?**
The `grok_local` environment test always warns `Configured model
"grok-build" not found in available models`, even when the agent works.
`grok-build` is the default sentinel, not a real model id, and it is
never sent to the CLI.

**Expected behavior**
When the model is left at the default, the test reports the CLI's own
default model as info and does not warn. It warns only when a user sets
a real model that `grok models` does not list.

**Steps to reproduce**
1. Create a `grok_local` agent and leave the model at its default.
2. Run the adapter environment test.
3. See the `grok_model_not_found` warning, although `grok models` and
the hello probe succeed.

**Agent adapter(s) involved**
grok_local (Grok Build CLI).

## What Changed

- `packages/adapters/grok-local/src/server/test.ts`: the model check now
treats the default sentinel as valid and reports it as info (`Using the
Grok CLI's default model (<default>)`). It still warns when an
explicitly configured, non-sentinel model is absent from the discovered
list. This matches `execute.ts`, which never sends the sentinel to grok.
- `packages/adapters/grok-local/src/server/test.test.ts`: adds a test
that the default sentinel does not warn when it is absent from the real
model list, and a test that a real, unavailable model still warns.

## Verification

- `pnpm exec vitest run
packages/adapters/grok-local/src/server/test.test.ts` — 5 passed.

## Risks

Low risk. The change only affects one adapter's environment-test
reporting. It does not change how runs pass `--model`. No schema, no
runtime behavior change.

## Model Used

Claude Fable 5 (`claude-fable-5`), extended thinking, 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 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 (n/a —
no doc change)
- [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
- [ ] I will address all Greptile and reviewer comments before
requesting merge
2026-08-24 09:38:34 -07:00
Devin Foley 0dfa0fb988
ci: refresh general-server shard duration manifest (#12075)
<!-- Write all pull request text in Simplified Technical English
(ASD-STE100). -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The PR verify workflow gates every pull request; its slowest check
sets the feedback time for all contributors
> - The general-server test lane splits its vitest suites across five
runners with a duration-weighted partition
(`scripts/general-server-shard.mjs`)
> - The partition reads a duration manifest that was sampled on
2026-08-04, when the lane had 279 suites and 946s of serial time
> - The lane has since grown to 405 suites and 1274s; 126 suites had no
recorded duration and one suite grew from 37s to 123s
> - The stale weights made the partition uneven: in the fully green
actions run 32708351172, "General tests (server (2/5))" ran 364s and was
the slowest check in the whole run, while sibling shards ran 292-330s
> - This pull request refreshes the manifest with per-suite durations
measured from that same run
> - The benefit is a level five-shard split (255s ±1s of predicted suite
time per shard), which removes ~50s from the slowest PR check

## Linked Issues or Issue Description

**Describe the current behavior**

In the fully green PR actions run
[32708351172](https://github.com/paperclipai/paperclip/actions/runs/32708351172)
(2026-08-24), the check "General tests (server (2/5))" completed in
364s. Its test step ran 315s while sibling shards ran 241-276s. It was
the slowest check in the run.

**Describe the improvement**

The duration manifest `scripts/general-server-shard-durations.json` is
stale. It holds 279 suites sampled on 2026-08-04, but the lane now has
405 suites. The 126 unknown suites fall back to the median weight
(~1.3s), and `server/src/__tests__/workspace-runtime.test.ts` grew from
37.4s to 123.3s. The partition therefore predicts a level split but
produces an uneven one. Refreshing the manifest restores the level split
without any code change.

**Expected impact**

All five server shards level at ~255s of predicted suite time (~310s job
time). The slowest PR check drops from 364s to about 317s, so the PR
critical path improves by roughly 50s.

## What Changed

- Regenerated `scripts/general-server-shard-durations.json` from actions
run 32708351172 (2026-08-24): 405 suites, 1274s total serial time (was
279 suites, 946s from 2026-08-04)
- Updated the `$comment` field to name the new sample run and date
- No code changes; the partition logic in
`scripts/general-server-shard.mjs` is untouched

## Verification

- Parsed all five "General tests (server (n/5))" job logs from run
32708351172 with the consecutive-completion-timestamp method described
in the manifest `$comment`; asserted that the parsed suite set equals
the exact file list that `run-vitest-stable.mjs` collects (405/405, no
misses, no extras)
- Ran `node scripts/run-vitest-stable.mjs --mode general --group
general-server --shard-index N --shard-count 5 --dry-run` for N=0..4
with the new manifest: each shard predicts 255s (±1s) of suite time, and
the five shards form a complete, non-overlapping cover of all 405 suites
- Ran `node --test
./scripts/__tests__/run-vitest-stable-shard.test.mjs`: 13/13 pass

## Risks

- Low risk. The change is data-only. Wrong weights cannot break
correctness: the partition always covers every suite exactly once, so
the worst case of a bad weight is an uneven shard, which is the current
state.

## Model Used

- Claude (Anthropic), model ID `claude-fable-5`, agentic coding session
with tool use (Claude Code / Claude Agent SDK)

## 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 (no code change;
existing partition tests pass)
- [x] I have updated relevant documentation to reflect my changes
(manifest `$comment` updated)
- [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

Related prior work: #11528 (balanced the serialized server shards by
recorded duration), #10923 (split serialized tests into five shards),
#11156 (split workspaces-a into two shards).

Co-authored-by: Claude <noreply@paperclip.ing>
2026-08-24 08:54:52 -07:00
Devin Foley 87d68f476b
fix: harden the sandbox bridge gateway against crashes and queue wedge (#12060)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents on remote sandbox targets reach the Paperclip API through the
sandbox callback bridge: a loopback HTTP gateway inside the sandbox
queues request files for a host-side worker
> - The gateway process has no supervisor: nothing inside the sandbox
respawns it, so a crash leaves a dead loopback port for the rest of the
run
> - The gateway also never cleaned up request files whose responses
never arrived, so a stalled host wedged the queue at its depth cap and
every later request got an immediate 503
> - #12052 made the host-side worker survive transient faults; this pull
request hardens the other half of the relay
> - The benefit is that a gateway fault degrades one request instead of
severing the agent from the control plane until run end

## Linked Issues or Issue Description

Refs #12052 (host-side worker half of the same relay). Refs #9904 and
#8977 (adjacent bridge behavior).

No public issue exists for this defect. The description below follows
the bug report template.

**What happened?**

During a staging run, an agent's API calls to the bridge's loopback port
began failing at the connection level (curl reported HTTP 000) partway
through the run. A dead gateway process is the only mechanism that
produces connection-level failures on that port, and nothing restarts
it. Separately, request files for timed-out requests stayed in the
queue; after 64 accumulated, the gateway answered every request with
`503 Bridge request queue is full.` until the run ended.

**Expected behavior**

An uncaught fault in the gateway must not kill the loopback listener. A
request that times out must not leave its file counting toward the
queue-depth cap. A queue full of orphaned files must recover instead of
rejecting until run end.

**Steps to reproduce**

1. Start a remote-sandbox run and stop the host-side bridge worker.
2. Send requests to the gateway until they time out; the request files
stay in `requests/`.
3. After 64 such files, every request gets an immediate 503, even after
the host recovers.
4. Independently, raise any uncaught exception in the gateway process;
the loopback port dies for the rest of the run.

## What Changed

- The generated gateway source installs global `uncaughtException` /
`unhandledRejection` handlers that log to stderr (already redirected to
`logs/bridge.log`) and keep serving. The relay holds no state a fault
can corrupt beyond the one request it interrupted.
- Survival is gated on readiness: before the gateway has written its
readiness file (file mode) or sent its READY frame (duplex mode), the
same handlers exit(1) instead. A startup fault (failed bind, failed
readiness write) means the process can never serve, and surviving there
would only leave an un-ready zombie while the host waits out its
readiness poll.
- The file gateway attaches an explicit `error` listener to its server
and pins the event loop with a keepalive until the bind settles. Newer
Node runtimes do not reliably surface a failed bind through
`uncaughtException` in this shape: the process can drain and exit 0
before the error event is delivered (reproduced on Node 24/25; Node 22
delivered it). The duplex gateway already had an explicit listener.
- A request that times out waiting for the host now deletes its own
request file. The host's response write is guarded on that file, so the
removal also signals that no caller waits anymore.
- At the queue-depth cap, the gateway sweeps request files older than
the response deadline (orphans from killed callers or a previous gateway
process) before rejecting with 503.
- Host-side, `processRequestFile` treats a request file that vanished
before the read as the benign caller-gave-up race and skips it quietly
instead of escalating into the recovery pass.

## Verification

- `npx vitest run
packages/adapter-utils/src/sandbox-callback-bridge.test.ts` — 43 passed,
verified on both Node 22 and Node 25.
- New end-to-end test: with no worker running, a request times out
(502), its file is cleaned, and the same gateway then serves a 200 once
a worker starts — no wedge, no dead port.
- New end-to-end test: with `maxQueueDepth: 1` and a backdated orphan
file at the cap, the gateway sweeps the orphan and admits the request
instead of answering 503.
- New worker test: a request file that vanishes before the read is
skipped without a handler call, a response write, or a run-level error.
- New generated-source test: spawned directly against an
already-occupied port, the gateway exits 1 promptly with the
`EADDRINUSE` fault on stderr instead of lingering un-ready (or exiting 0
silently, the pre-existing behavior on Node 24/25).
- A pin keeps the crash handlers, the readiness gate, and the sweep in
the generated source.
- `pnpm --filter @paperclipai/adapter-utils typecheck`.

## Risks

- Keeping a Node process alive after `uncaughtException` is normally
suspect; here the alternative is a dead loopback port for the rest of
the run, and the gateway is a stateless per-request relay. The fault is
logged with its stack to `bridge.log`, and survival applies only after
readiness — startup faults still fail fast.
- Deleting a timed-out request file could race a host that is
mid-processing. The host's response write is already guarded on
request-file existence, and the new host-side skip treats the vanished
file as a no-op, so no duplicate mutation path is introduced.
- The stale sweep runs only at the depth cap and only removes files
older than the response deadline plus a 2 s grace, so a live caller's
file is never swept.
- Orphaned response files (host responded after the caller gave up)
still linger; that pre-existing minor leak is unchanged here.

## Model Used

- Claude Fable 5 (Anthropic), model id `claude-fable-5`, extended
thinking enabled, agentic tool use via Claude Code (CLI harness), 200k
context window.

## 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
2026-08-24 08:52:05 -07:00
Dotta b2d1673b9e
Add TypeScript PRP replay contracts (#12091)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip Runner needs one typed interpretation of the
language-neutral PRP contract.
> - The JSON Schemas and fixtures now exist, but TypeScript consumers
cannot validate or replay them yet.
> - A deterministic reducer must define how duplicate delivery and
source gaps affect the projected session.
> - Result and question contracts must also validate untrusted provider
and user input before later runtime code uses it.
> - This pull request adds those TypeScript contracts and replay oracles
without adding a process, provider, endpoint, or production behavior.
> - The benefit is a reviewable and testable TypeScript foundation for
the local runner and transport pull requests.

## Linked Issues or Issue Description

**Subsystem affected**

This change affects the private `@paperclipai/paperclip-runner` package.
It does not change an existing server or adapter execution path.

**Problem or motivation**

The PRP v1 schemas do not yet provide TypeScript types, runtime
validators, normalized result handling, or a deterministic session
projection. Later Rust, transport, provider, and server work needs one
tested TypeScript oracle instead of separate interpretations.

**Proposed solution**

Generate a checked-in TypeScript schema bundle from the PRP v1 sources.
Add derived types, AJV validation, result and question validation,
deterministic replay, a reducer, and generated golden snapshots. Export
only these implemented root-package surfaces.

**Alternatives considered**

The combined runner branch adds the TypeScript contracts together with
Rust, providers, semantic authorization, SDKs, labs, and server
behavior. That delta is too large for normal review. Handwritten
duplicate protocol types would also create a drift risk.

**Roadmap alignment**

This work supports the governed tool and control-plane direction in
`ROADMAP.md`. It does not enable a new production adapter or endpoint.

**Additional context**

Refs #12087 and #11962. This pull request was prepared on #12087, then
rebased onto its squash merge before opening. The current delta against
`master` is 37 files.

## What Changed

- Added JSON-Schema-derived PRP v1 types and AJV runtime validation.
- Added fail-closed required-version checks and cross-envelope binding
checks.
- Added provider-neutral completion-result and structured-question
contracts.
- Added normalization for accepted legacy provider result aliases before
strict validation.
- Added a deterministic session reducer for replay, duplicate delivery,
source gaps, requests, items, results, and terminal state.
- Added generated replay snapshots and compact parity summaries for six
accepted fixtures.
- Added schema-bundle, manifest, and replay-golden drift gates.
- Added only the root package export. Deferred testing, SDK, evaluation,
lab, provider, and browser entry points remain unavailable.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner test` passed with 8
protocol tests and 44 TypeScript tests.
- `pnpm --filter @paperclipai/paperclip-runner typecheck` passed.
- `pnpm --filter @paperclipai/paperclip-runner check:replay-goldens`
passed.
- `pnpm -r typecheck` passed.
- `pnpm build` passed.
- `pnpm check:token-gates` passed.
- `git diff --check` passed.
- The delta against its declared base is 37 files.
- `pnpm test:run` was executed locally. The package tests pass, while
the macOS repository run retains the unchanged local-environment
failures documented on #12087. The complete Linux CI matrix must pass on
this commit.
- A scoped scan found no secret-like values, internal references, or
deferred-provider file names.
- Greptile found an unbounded sequence-gap allocation. Commit `4a405c17`
caps detailed missing IDs at 256, records the full missing count and
truncation state, and rejects sequence values above the exact JavaScript
integer range. The focused tests, workspace typecheck, build, and token
gates pass after this fix.

## Risks

Low production risk. The package remains private. This change adds no
process, network endpoint, provider bridge, server integration, database
change, or execution selection. The main risk is protocol interpretation
drift. Generated schema and replay gates detect that drift. Browser and
CSP-specific validator packaging remains deferred to its later package
boundary.

I checked `ROADMAP.md`. This change defines contracts for planned
control-plane work and does not add overlapping product behavior.

## Model Used

OpenAI Codex with GPT-5 was used. The exact serving model ID and context
size were not exposed. The model used high reasoning, repository tools,
GitHub tools, and local 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
- [ ] 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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-24 10:43:53 -05:00
github-actions[bot] 3708779501
chore(lockfile): refresh pnpm-lock.yaml (#12090)
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>
2026-08-24 10:02:56 -05:00
Dotta fdbc69172d
feat(runner): add PRP v1 schemas and fixtures (#12087)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip Runner needs a language-neutral contract between the
server and the runner process.
> - A shared contract must exist before TypeScript, Rust, transport, or
provider implementations can depend on it.
> - Required protocol versions must fail closed, while safe optional
fields must remain compatible.
> - The contract also needs deterministic fixtures and a drift gate for
later cross-language work.
> - This pull request adds that contract without adding runtime
behavior.
> - The benefit is a small, reviewable source of truth for the next
implementation pull requests.

## Linked Issues or Issue Description

**Subsystem affected**

Cross-cutting. This pull request adds a private package contract for
later server, TypeScript, and Rust work.

**Problem or motivation**

Paperclip Runner does not have a small language-neutral protocol
boundary on `master`. A runtime implementation without this boundary can
drift between languages, accept unsupported required versions, or
silently change canonical fixtures.

**Proposed solution**

Add PRP v1 JSON Schemas, accepted and rejected fixtures, a Codex
structured-question fixture, and a generated SHA-256 manifest. Run
compatibility and manifest checks during the package build. Keep the
package private and export nothing in this pull request.

**Alternatives considered**

The combined runner branch contains schemas together with providers,
SDKs, labs, and server behavior. That change is too large for normal
review. Generating TypeScript validators in this pull request would also
cross into the next review unit.

**Roadmap alignment**

This contract supports the governed tool and control-plane direction in
`ROADMAP.md`. It does not enable a new production adapter or endpoint.

**Additional context**

Refs #12084 and #11962. This pull request was reviewed as a stack on
#12084, then rebased and retargeted to `master` after #12084 merged. The
current delta is 38 files.

## What Changed

- Added 20 PRP v1 JSON Schemas with stable identifiers and resolved
references, including explicit cross-language conformance input and
output schemas.
- Added canonical replay, cross-language, and Codex question fixtures.
- Added accepted cases for additive optional fields and a rejected case
for an unsupported required protocol version.
- Added a deterministic manifest with SHA-256 digests for every schema
and fixture.
- Added package-local schema-instance, schema-reference, compatibility,
question-ID, conformance-pair, and drift checks.
- Added a private workspace package with no public exports and no
production runtime behavior.
- Added the package manifest to the Docker dependency-stage inventory
required for every workspace package. This does not copy or build runner
runtime code into the production image.
- Kept the provider descriptor and question fixture Codex-only. No
deferred provider package or dependency is present.

## Verification

- `pnpm install --frozen-lockfile` passed with Node 24.19.0 and pnpm
9.15.4. No lockfile change is committed.
- `pnpm --filter @paperclipai/paperclip-runner check:protocol` passed
with 8 tests.
- The committed AJV 2020-12 gate accepted every canonical v1 replay,
question, and cross-language conformance fixture. It rejected the
required v2 fixture, a replay fixture with a missing required command
ID, and conformance output with a missing session ID.
- `pnpm -r typecheck` passed.
- `pnpm build` passed and ran the protocol manifest drift check.
- `pnpm check:token-gates` passed.
- `node ./scripts/check-docker-deps-stage.mjs` passed.
- `git diff --check` passed.
- The delta against its declared base is 38 files.
- `pnpm test:run` completed with 4,687 passing tests, 19 skipped tests,
and 29 failures across 9 unchanged server files. The failures reproduce
macOS path aliases, local listener probes, workspace-runtime
assumptions, and one connection-retry timeout. No changed-file test
failed. Linux CI must pass before this pull request is ready.
- `pnpm check:tokens` reports existing personal-name references outside
this pull request. A scoped scan of `packages/paperclip-runner` found no
secret-like values, internal references, or deferred-provider names.
- PR #12084 was squash-merged, and this branch was rebased onto that
merge and retargeted to `master`. The first master-base policy run
correctly caught the missing Docker dependency-stage manifest copy;
commit `4fa1ea7c` fixes that gate, and the complete Linux matrix is
green.
- Serialized server shard 1 initially hit an unchanged heartbeat
test-harness timeout and a later assertion in the same file. Its
isolated rerun passed in 3m57s. All other shards passed on their first
attempt.
- Greptile reviewed the final commit at 5/5 with no blocking failure.
Both earlier actionable validation threads are resolved, and no review
thread remains open.

## Risks

Low production risk. The package is private and has no exports, server
adapter, endpoint, or process. AJV is a package-only development
dependency that the server workspace already uses. The main risk is
contract churn before the TypeScript and Rust consumers land. The
generated manifest and compatibility fixtures make that churn explicit.

I checked `ROADMAP.md`. This change defines a contract for planned
control-plane work and does not add overlapping product behavior.

## Model Used

OpenAI Codex with GPT-5 was used. The exact serving model ID and context
size were not exposed. The model used high reasoning, repository tools,
GitHub tools, and local 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
- [ ] 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>
2026-08-24 09:59:03 -05:00
Dotta 41bf5cafa1
docs(runner): define architecture and compatibility (#12084)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent execution currently uses direct adapters inside the server
process.
> - The proposed Paperclip Runner adds a separate process and a new
protocol boundary.
> - This boundary needs clear trust, recovery, rollout, and
compatibility rules before code lands.
> - Large runner changes are difficult to review as one pull request.
> - This pull request defines the first small boundary for the runner
series.
> - The benefit is a stable design contract for later implementation
pull requests.

## Linked Issues or Issue Description

**Issue type**

Missing documentation.

**Where is the issue?**

The repository does not have a concise architecture decision or
compatibility contract for Paperclip Runner.

**What's wrong?**

The available runner design material is too large for normal review. It
mixes architecture, implementation history, test evidence, and deferred
work. Reviewers need a short statement of the process boundary, trust
model, rollout behavior, and direct-adapter compatibility rules.

**Suggested fix**

Add one architecture decision record and one compatibility document.
Keep implementation details and campaign evidence out of this pull
request.

Related public work: Refs #11041, #11297, #11634, #11639, #11640, and
#11962. This pull request is the first small replacement in the new
review series for #11962.

## What Changed

- Added an architecture decision for the runner process, PRP v1
transport, semantic tools, durable recovery, and additive server
integration.
- Added a compatibility and rollout contract for the default-off
adapter, existing direct adapters, persisted native runs, and the task
page.
- Defined the initial package and provider limits. The first production
provider is Codex only.
- Defined acceptance checks for later implementation pull requests.

## Verification

- `pnpm install --frozen-lockfile` passed with Node 24.19.0 and pnpm
9.15.4.
- `pnpm check:node-version` passed.
- `pnpm -r typecheck` passed.
- `pnpm build` passed.
- `git diff --check origin/master...HEAD` passed.
- The pull request changes 2 files.
- `pnpm test:run` completed with 4,686 passing tests and 30 failures in
unchanged master paths. The failures reproduce macOS path aliases,
invalid generated port values, and local listener behavior. This
documentation-only change does not touch those paths. Linux CI must pass
before this pull request is ready.
- All applicable GitHub Actions and security scans passed. The Storybook
visual job skipped because this documentation-only change does not match
its paths.
- Greptile completed at 5/5 with no actionable comments.

## Risks

Low implementation risk. This pull request changes documentation only. A
later implementation can still diverge from the contract. Each later
pull request must prove its behavior against these compatibility rules.

I checked `ROADMAP.md`. This design supports the governed tool and
control-plane direction. It does not add an overlapping user feature.

## Model Used

OpenAI Codex with GPT-5 was used. The exact serving model ID and context
size were not exposed. The model used high reasoning, repository tools,
GitHub tools, and local 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
- [ ] I have run tests locally and they pass
- [ ] 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
2026-08-24 09:30:47 -05:00
Tonio 88a0f885e8
Brand lockup, no idle env-check card, no Mission row (#12074)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - New customers meet the product through an onboarding arc that ends
in the tenant wizard
> - A staging walk of that arc found three rough edges: an ad-hoc icon
standing in for the brand, an environment-check card that narrates a
probe the flow already runs on its own, and a review checklist that
still lists a Mission the arc stopped asking for
> - Each one makes the product look less finished than it is at the
exact moment a customer decides what it is
> - This pull request renders the brand lockup, hides the idle
environment-check card while keeping the probe and its failure surface,
and drops the Mission row
> - The benefit is a first-session arc that reads as one product, with
no controls for questions nobody was asked

## Linked Issues or Issue Description

No public issue exists. The changes come from walking the sign-up arc on
a staging fleet.

**What happened:**
The model step shows an "Adapter environment check" card with a "Test
now" button even though pressing Connect runs the same probe and blocks
a failing hire. The review step lists "Mission" in its checklist
although onboarding no longer asks for one. The auth page renders a
sparkles icon beside the word "Paperclip" instead of the brand lockup.

**Expected behavior:**
The model step shows the check only when a probe has found something to
fix. The review checklist lists only what onboarding set up. The brand
renders as the lockup asset used across surfaces.

**Actual behavior:**
An idle card narrates a probe that runs regardless. A permanent
unchecked row marks a question nobody was asked. The brand is a generic
icon plus text.

**Steps to reproduce:**
1. Sign up on a staging fleet and enter the tenant wizard.
2. On "Create your first agent", choose a role and press Next: the model
step shows the "Adapter environment check" card before anything has been
probed.
3. Continue to Review: the checklist lists "Mission" as a permanently
unchecked row.

**Additional context:**
The Mission row outlived the removal of the mission step (#11935). The
environment probe itself still runs on Connect and blocks a failing
hire; only its idle card is at issue. The brand lockup lands across all
three surfaces in the same round — paperclip-cloud#270 and
paperclip-id#58 carry the other halves.

## What Changed

- `PaperclipLockup` renders the brand asset (mark + wordmark, one
geometry, `fill="currentColor"`); the auth page uses it in place of the
sparkles icon.
- The adapter environment check's idle card (explainer + "Test now") no
longer renders. The probe still runs on Connect and still blocks a
failing hire.
- The check's failure content still renders when a probe has found
something — the blocking error points the customer at "the reported
checks", so they stay visible.
- Connect retries a cached failed probe instead of reusing it. With
"Test now" gone, Connect is the only retry, and a stale fail would lock
out a machine the customer has since fixed.
- The review checklist drops its "Mission" row.

## Verification

Run the tenant suite:

```
cd ui && npx vitest run
```

- 4365 tests pass across 471 files; `npx tsc --noEmit` is clean.
- New test drives the wizard to the model step and asserts the
environment-check card is absent, anchored on "Connect a model" so an
unrendered step cannot pass as an absence.
- The review assertions anchor on the remaining rows ("Organization
name", "Agent created", "Model connected").

## Risks

- **Behavioral change:** a cached *failed* probe is re-run on Connect
instead of reused. Pass and warn results are still cached. This only
affects the retry path that "Test now" used to serve.
- **Hidden, not removed:** the environment check machinery is intact;
only the idle card is gone. A failing probe still blocks the hire and
still shows its checks.
- **Brand:** the wordmark now ships inside an SVG; its accessible name
carries the text. Screen readers announce "Paperclip" as before.

## Model Used

Claude Fable 5 (`claude-fable-5`) via Claude Code, with tool use and
code execution; earlier rounds on this branch's predecessor used Claude
Opus 5 (`claude-opus-5`).

## 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>
2026-08-24 01:35:15 -07:00
Nicky Leach a14e51d592
refactor(environment): classify environment capabilities from static driver definitions (#12045)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Environment runtime drivers provide workspace, lease, and custom
image behavior
> - Runtime code used driver identity checks and several
capability-specific members
> - These checks spread capability rules across the runtime and made new
drivers harder to verify
> - This pull request adds one general capability classifier and one
static driver support table
> - The benefit is one fail-closed capability model that keeps current
behavior and supports future drivers

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Environment runtime capability checks for workspace realization, custom
images, lease capabilities, and duplex authorization.

**Subsystem affected**

Cross-cutting (multiple of the above)

**Current behavior**

The runtime selects several capability paths from driver identity and
separate capability members. Custom image gates also trust provider
declarations without checking every matching live worker method.

**Proposed behavior**

The runtime uses one general capability classifier and one static
support table. Custom image gates require both the provider declaration
and every matching live worker method. The public capability names
remain unchanged.

**Reason and benefit**

The change keeps capability rules in one place. It removes identity
conditions from runtime consumers and makes unsupported drivers fail
closed.

**Breaking changes**

None. The public names sandboxCapabilities, sandboxProviders, and
EffectiveSandboxCapabilities remain available.

## What Changed

- Add classifyEnvironmentCapabilities and static support definitions for
all four driver families.
- Add resolveCapabilities to every environment runtime driver.
- Move driver traits into environment-driver-traits.ts and migrate
runtime consumers.
- Require provider declarations and matching live worker methods for all
custom image gates.
- Migrate duplex authorization to the general resolver and remove the
dead sandbox-only member.
- Delete the unused resolveEffectiveSandboxCapabilities wrapper and
update its test.

## Verification

- pnpm --filter @paperclipai/server typecheck
- pnpm exec vitest run
server/src/__tests__/environment-capability-contract.test.ts
server/src/__tests__/environment-runtime.test.ts — 92 tests pass
- pnpm exec vitest run
server/src/__tests__/environment-driver-traits.test.ts
server/src/__tests__/general-capability-classifier.test.ts — 12 tests
pass
- pnpm exec vitest run
server/src/__tests__/environment-custom-images-service.test.ts
server/src/__tests__/environment-execution-target-capabilities.test.ts
server/src/__tests__/environment-execution-target-duplex.test.ts
server/src/__tests__/environment-execution-target-duplex-kill-switch.test.ts
— 66 tests pass

## Risks

The main risk is a capability gate that denies a valid driver or permits
an invalid driver. The static support matrix, live worker method checks,
and regression tests reduce this risk. No database, public API, or
published type name changes.

## Model Used

OpenAI Codex, GPT-5, with tool use and code execution. The deployment
does not provide 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 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 (for example, docs/... or
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>
2026-08-23 21:24:59 -07:00
Devin Foley fc9e9b704f
fix: stop teaching agents to curl literal {id} route templates (#12061)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Adapters inject prompt text that teaches agents how to call the
Paperclip API, including copy-pasteable curl examples
> - Some of those URLs contained brace placeholders like
`/api/issues/{id}/checkout`
> - Agents paste such lines verbatim; the placeholder reaches the server
as `/api/issues/%7Bid%7D` and 404s, and request logs show agents doing
exactly that
> - The acpx engine's API note already avoids this by using
`$PAPERCLIP_TASK_ID`, and its test pins `/api/issues/{id}` out of the
prompt
> - This pull request applies the same standard to the gemini adapter,
the shared prompt template, and the openclaw gateway workflow
> - The benefit is that agents stop burning turns on placeholder 404s
and doc examples stay safe to execute as written

## Linked Issues or Issue Description

No public issue exists for this defect. The description below follows
the bug report template.

**What happened?**

Server request logs show agents issuing `GET /api/issues/%7Bid%7D` — the
literal, percent-encoded text `{id}` — which 404s. The source is adapter
prompt text: the gemini adapter's API note embeds a curl example with
`/api/issues/{id}/checkout` in the URL, the shared agent prompt template
mentions `/api/issues/{issueId}` endpoints, and the harness checkout
notice names `/api/issues/{id}/checkout`. Models copy these strings into
real requests.

**Expected behavior**

URL paths in prompt text must carry environment variables or real ids,
never brace placeholders, in every string an agent might execute
verbatim. Where a placeholder is unavoidable, the prompt must state
explicitly that the literal text must never be sent.

**Steps to reproduce**

1. Give an agent the gemini adapter's API access note.
2. Watch it call `curl ...
"$PAPERCLIP_API_URL/api/issues/{id}/checkout"` as written.
3. The server logs `POST /api/issues/%7Bid%7D/checkout 404`.

## What Changed

- gemini-local's API note curl example now uses `$PAPERCLIP_TASK_ID` and
tells the agent to substitute a real issue id when that variable is
absent — the same convention as the acpx engine's API note.
- The shared agent prompt template (`server-utils.ts`) uses
`$PAPERCLIP_TASK_ID` in its interaction-creation and resume-endpoint
mentions, and the harness checkout notice names `POST
/api/issues/$PAPERCLIP_TASK_ID/checkout`.
- openclaw-gateway's endpoint workflow keeps its `{issueId}`
placeholders — they are defined by its "determine issueId" step — but
now states explicitly that the literal text must never be sent in a URL.
- `server-utils.test.ts` pins the new form and adds negative pins that
keep `/api/issues/{id}` and `/api/issues/{issueId}` out of the shared
prompt template, mirroring the existing acpx-engine negative pin.
- The `confirmation:{issueId}:plan:{revisionId}` idempotency-key
template is untouched: it is a value-construction pattern, not a URL.

## Verification

- `npx vitest run packages/adapter-utils/src/server-utils.test.ts
packages/adapters/gemini-local packages/adapters/openclaw-gateway` — 152
passed. The single failure (`pre-selects gemini-api-key auth in the
managed HOME for sandbox execution`) is a pre-existing
environment-specific failure on the development machine, unrelated to
prompt text; CI is authoritative for it.
- `pnpm --filter @paperclipai/adapter-utils --filter
@paperclipai/adapter-gemini-local --filter
@paperclipai/adapter-openclaw-gateway typecheck`.

## Risks

- Low risk: prompt-text and test changes only; no runtime logic changes.
- Agents that memorized the old example strings keep working — the
routes are unchanged, only the placeholder text in prompts is.

## Model Used

- Claude Fable 5 (Anthropic), model id `claude-fable-5`, extended
thinking enabled, agentic tool use via Claude Code (CLI harness), 200k
context window.

## 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
2026-08-23 17:16:30 -07:00
Devin Foley 633e102971
fix: verify issue-update writes instead of inferring success (#12051)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents report task state to the control plane with `PATCH
/api/issues/{id}` at the end of each heartbeat
> - On remote sandbox targets those writes cross a relay that can fail
at the connection level
> - An agent that pipes its status curl through `head` cannot see that
failure; the write is lost but the run reports success
> - The issue then stays `in_progress` with no disposition, and the
missing-disposition recovery must repair it
> - This pull request makes the issue-update helper verify every write,
and it teaches the shared skill to require verified writes
> - The benefit is that a lost status write becomes a visible, retried
failure instead of a silent success

## Linked Issues or Issue Description

No public issue exists for this defect. The description below follows
the bug report template.

**What happened?**

A sandboxed heartbeat run answered its issue in a comment. It then sent
`PATCH /api/issues/{id}` with `status: done` through `curl -sf ... |
head -c 400`. The relay dropped the connection. The `-f` flag suppressed
the error output, and the pipe replaced curl's exit code with the exit
code of `head`. The agent saw empty output and exit 0. It reported the
write as an "empty 2xx" success and exited. The issue stayed
`in_progress`, and the successful-run recovery had to close it in a
corrective run.

**Expected behavior**

A status write that does not reach the server must surface as a failure.
The helper script must retry transient failures. It must exit non-zero
when the write is unconfirmed. Skill guidance must forbid write patterns
that hide failures.

**Steps to reproduce**

1. Point `PAPERCLIP_API_URL` at an endpoint that drops connections
intermittently.
2. Finalize an issue with `curl -sf -X PATCH
"$PAPERCLIP_API_URL/api/issues/$ID" -d '{"status":"done"}' | head -c
400`.
3. Observe exit code 0 with empty output while the server never received
the PATCH.

## What Changed

- `scripts/paperclip-issue-update.sh` now captures `%{http_code}`,
retries a retryable failure (connection-level, 429, 5xx) once — two
attempts total, which matches the shared bounded-write-retry rule —
rejects an empty 2xx body, and confirms the response echoes the
requested status before it exits 0.
- Failure output states plainly that the write was NOT saved, so the
calling agent reports it accurately.
- `skills/paperclip/SKILL.md` Step 8 adds a required "Verify writes —
never infer them" rule: a successful PATCH always returns the updated
issue JSON, disposition writes must never run through `head`/`tail`
pipelines, and an unconfirmed write must be reported as FAILED.
- `server/src/__tests__/paperclip-skill-utils.test.ts` pins the new
skill rule; a new `paperclip-issue-update-helper.test.ts` exercises the
helper's behavior end-to-end.

## Verification

- `bash -n scripts/paperclip-issue-update.sh`
- `server/src/__tests__/paperclip-issue-update-helper.test.ts` runs the
helper end-to-end against a local HTTP server: confirmed-echo success
(exit 0), empty 2xx (exit 1), wrong echoed status (exit 1), 422 reject
(exit 1, exactly one request), 503 then success (two requests),
connection refused (two attempts, then exit 1 with a "NOT saved"
report).
- `npx vitest run
server/src/__tests__/paperclip-issue-update-helper.test.ts
server/src/__tests__/paperclip-skill-utils.test.ts
server/src/__tests__/cli-invocation-safety.test.ts` — 50 passed.

## Risks

- Low risk. The success-path output is unchanged (the updated issue
JSON).
- The helper now exits non-zero on unconfirmed writes. Callers that
previously missed silent failures now see explicit errors. That is the
intended behavior change.
- The single retry re-sends the PATCH after a retryable failure. If the
first request committed and only its response was lost, an attached
comment can post twice. The duplicate is visible and benign; the prior
behavior lost the write silently.

## Model Used

- Claude Fable 5 (Anthropic), model id `claude-fable-5`, extended
thinking enabled, agentic tool use via Claude Code (CLI harness), 200k
context window.

## 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
2026-08-23 16:56:51 -07:00
Devin Foley c7f4bc1300
fix: survive transient sandbox exec failures in the callback bridge worker (#12052)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents on remote sandbox targets reach the Paperclip API through the
sandbox callback bridge: a loopback gateway inside the sandbox writes
request files, and a host-side worker polls them over the provider's
exec channel and forwards them to the server
> - The worker's poll loop had one terminal catch: a single reset or
slow exec ended the relay for the rest of the run
> - The in-sandbox gateway kept queueing requests against the dead
worker, so every later API call from the agent stranded, including its
final status write
> - A relay that dies on one transient fault turns a routine provider
hiccup into a lost issue disposition
> - This pull request restructures the loop so transient faults back off
and retry, while the watchdog remains the escalation path for sustained
outages
> - The benefit is that one flaky exec no longer severs an agent from
the control plane mid-run

## Linked Issues or Issue Description

Refs #9904. Refs #8977. Both touch adjacent bridge behavior (curl shim,
header forwarding); neither addresses worker-loop lifetime.

No public issue exists for this defect. The description below follows
the bug report template.

**What happened?**

During a staging run, the host-side bridge worker hit one failed sandbox
exec while relaying requests. The poll loop's only catch is terminal: it
failed the pending requests and set the worker to settled, with no
restart. The agent's later API calls saw connection-level failures or
bridge errors until the run ended. Its final `PATCH status: done` was
lost, and the missing-disposition recovery had to repair the issue in a
corrective run.

**Expected behavior**

One transient exec failure must not end the relay for the rest of the
run. The worker must back off and retry. A sustained outage must still
fail queued requests fast through the watchdog. In-flight request
semantics (abort plus 504 backstop, retry-safe 503) must not change.

**Steps to reproduce**

1. Start a remote-sandbox run and let the provider exec channel reject
or stall one call while the bridge worker polls.
2. The worker hits one `listJsonFiles` failure or one request-attempt
timeout, and the loop exits through its terminal catch.
3. Every later bridge request strands. The loopback gateway keeps
accepting requests that never complete, and after 64 queued files it
answers every request with 503 until run end.

## What Changed

- `startSandboxCallbackBridgeWorker`'s poll loop now separates three
failure domains:
- A failed poll backs off exponentially (capped at 5 s) and retries
instead of dying. The first failure of a streak still lands on the run
trace through the workerFailed span; later repeats only warn.
- A failed or hung request attempt runs the same recovery pass the loop
previously died on — abort the in-flight handler (its 504 backstop keeps
the caller from stranding) and 503 the unclaimed queued requests — and
the loop then continues and serves the caller's retry.
- A listing where every file already has an in-flight attempt sleeps one
poll interval, like an empty listing. The previous immediate re-list was
a hot spin: an exec storm against a real channel, and a pure-microtask
loop that starved every timer in the process when the queue client
resolves synchronously.
- The watchdog, the claim/finalize fences, and the stop/drain semantics
are unchanged.

## Verification

- `npx vitest run
packages/adapter-utils/src/sandbox-callback-bridge.test.ts` — 38 passed.
- New regression test: a request queued behind three consecutive poll
failures is still delivered.
- Updated tests: the stalled-poll test now expects recovery (the
handler's real 200) instead of a terminal 503; the sustained-outage 503
path remains proven by the dedicated watchdog test; the
recovery-503-write-retry test triggers the recovery pass through a hung
request read, because a hung poll no longer runs that pass.
- `pnpm --filter @paperclipai/adapter-utils typecheck`.

## Risks

- Behavior change: a transiently failing poll no longer mass-fails
queued requests on the first error. Callers wait through the backoff
window, bounded by the existing in-sandbox 30 s response deadline, or
the watchdog fails them after 20 s of no successful iteration. This
trades fast-but-terminal degradation for recovery.
- A hard-down channel now retries every ≤5 s for the rest of the run
instead of stopping. Each retry is one exec attempt against a channel
that already fails.
- In-flight mutation safety is unchanged: the guard map and the claim
protocol still prevent a double-applied host mutation, and a guarded
file is always finalized by its own attempt or by its 504 backstop.

## Model Used

- Claude Fable 5 (Anthropic), model id `claude-fable-5`, extended
thinking enabled, agentic tool use via Claude Code (CLI harness), 200k
context window.

## 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
2026-08-23 16:55:23 -07:00
Devin Foley c62bb4b16b
feat: environment delete with agent reassignment and consented sandbox destroy (#12053)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Environments define where agent runs execute: local, SSH, or
provider sandboxes
> - Operators can create and edit environments, but the UI has no way to
delete one
> - The server already exposes `DELETE /environments/:id` and a
delete-blast-radius preflight, but no UI consumes them, and a delete
blocked by reusable sandbox leases gives the operator no path forward
> - This pull request adds the delete flow to the environment
configuration page: a preflight-driven modal that reassigns dependent
agents, names the workspaces that hold blocking sandbox leases, and can
destroy those sandboxes with explicit consent
> - The benefit is that operators can retire stale environments from the
UI without database surgery, and dependent agents move to a chosen
replacement instead of silently falling back

## Linked Issues or Issue Description

Refs #8554
Refs #11124

**Subsystem affected**

Environments (server routes, environment runtime service, and the
environment settings UI).

**Problem or motivation**

The environment configuration page has no delete control. The server
delete endpoint exists, but nothing in the UI calls it. When reusable
sandbox leases block a delete, the 409 error names no owner, so the
operator cannot find the blocking workspace. Agents that use the
environment as their default lose it silently through the FK `on delete
set null`.

**Proposed solution**

Add a delete button with a confirmation modal on the environment edit
page. The modal reads the delete-blast-radius preflight. It offers a
dropdown to reassign dependent agents to another environment before the
delete. It lists each workspace that holds a blocking reusable sandbox
lease, with a link. When those leases are the only blocker, the confirm
button destroys the sandboxes inline
(`?destroyReusableSandboxLeases=true`) and then deletes. A failed
teardown falls back to `pending_cleanup` for the sweep, so no sandbox is
orphaned.

## What Changed

- `ui/src/pages/CompanyEnvironments.tsx`: delete button on the edit page
header, confirmation modal with agent reassignment select, lease-holder
list, impact notes, and a consent-labeled destroy-and-delete action
- `ui/src/api/environments.ts`: `deleteBlastRadius` and `remove` client
methods; `remove` takes an optional `destroyReusableSandboxLeases` flag
- `server/src/routes/environments.ts`: `DELETE /environments/:id`
accepts `?destroyReusableSandboxLeases=true`; it destroys the
environment's reusable sandbox leases first, but only when those leases
are the sole delete blocker, then re-checks the blast radius before it
deletes
- `server/src/services/environment-runtime.ts`: new
`destroyReusableSandboxLeasesForEnvironment` — destroys every reusable
sandbox lease an environment still owns while the environment config
(provider credentials) is still available
- `server/src/services/environments.ts`: the delete blast radius now
returns `reusableSandboxLeaseHolders` (lease id, workspace, issue) so
clients can name what blocks a delete
- `packages/shared/src/types/environment.ts`:
`EnvironmentDeleteReusableLeaseHolder` type on the blast radius
- Tests: route gating for the consent flag (destroy runs, mixed-blocker
rejection, surviving-lease rejection), runtime destroy scoped to an
environment, blast-radius holder join, and UI tests for the reassignment
flow, holder links, and the consent button

## Verification

- `npx vitest run server/src/__tests__/environment-routes.test.ts
server/src/__tests__/environment-service.test.ts
server/src/__tests__/environment-runtime.test.ts
ui/src/pages/CompanyEnvironments.test.tsx`
- Manual: open Settings → Environments → edit an environment. The trash
icon opens the modal. With agents on the environment, pick a
reassignment target and confirm; agents move and the environment
deletes. With reusable sandbox leases, the modal names the holding
workspaces and the confirm button reads "Destroy N sandboxes and
delete".

## Risks

- The consented path destroys provider sandboxes. It runs only when
reusable leases are the sole blocker, so a delete that would still be
rejected never destroys anything. A failed teardown routes to
`pending_cleanup` and the delete stays blocked until the sweep resolves
it.
- Agent reassignment issues one PATCH per agent from the client. A
mid-sequence failure leaves some agents reassigned; the reassignments
are valid on their own and the UI refreshes to the actual state.
- Hard blockers (managed local, instance default, pending cleanup) keep
the existing 409 behavior and disable the confirm button.

## Model Used

- Claude (Anthropic) — Fable 5, model id `claude-fable-5`, extended
thinking, agentic tool use via Claude Code CLI.

## 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
- [ ] 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
2026-08-23 16:53:17 -07:00
Devin Foley 627eef7cbd
fix(plugins): retry errored plugins at boot instead of leaving them dead (#12054)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Plugins extend the server with sandbox providers, tools, and jobs; a
loader activates them at boot
> - When activation fails, the loader marks the plugin `error` and skips
it on every later boot
> - Activation failures are often environmental — missing package
dependencies, a stale build output, a module that moved under a pull —
and the fix lands on disk without any write to the plugin row
> - The plugin therefore stays dead forever, and every feature behind it
(sandbox destroys, cleanup sweeps, probes) silently stops working until
an operator flips the row by hand
> - This pull request makes `loadAll` retry errored plugins once per
boot: flip to `ready`, attempt activation, and re-record the error if
the attempt fails
> - The benefit is that a plugin recovers on the next boot after its
environment is fixed, with no manual database or lifecycle intervention

## Linked Issues or Issue Description

**What happened?**

Several sandbox-provider plugins sat in `error` status for weeks after a
transient activation failure (a module resolution error from an older
checkout state). The boot loader only loads plugins in `ready` status,
so it never retried them. Environments backed by those providers lost
sandbox destroys, cleanup sweeps, and probes with no visible signal
other than the stale `last_error`.

**Expected behavior**

A plugin whose activation failure has been fixed on disk recovers on the
next server boot. A plugin that still fails stays in `error` with a
fresh error message.

**Steps to reproduce**

1. Install a plugin whose worker cannot start (for example, delete one
of its dependencies), then boot the server. The plugin lands in `error`
status.
2. Restore the dependency.
3. Restart the server. Before this change, the plugin stays in `error`
forever. After this change, the boot retries it and the plugin
activates.

## What Changed

- `server/src/services/plugin-loader.ts`: `loadAll` also fetches plugins
in `error` status, flips each to `ready`, and activates it with the
normal batch. The flip runs before activation because the `error` status
only legally transitions to `ready` or `uninstalled`; a retry that
failed while still in `error` could not re-mark itself. A failed flip
logs a warning and never aborts the boot load. The stale comment at the
`markError` site now describes the retry.
- `server/src/__tests__/plugin-loader-error-retry.test.ts`: covers the
flip-then-retry flow, the failed-flip isolation, and the empty case.

## Verification

- `npx vitest run server/src/__tests__/plugin-loader-error-retry.test.ts
server/src/__tests__/bundled-plugins.test.ts
server/src/__tests__/plugin-lifecycle-restart.test.ts
server/src/__tests__/cloud-image-bundled-plugins.test.ts`
- Manual: mark an installed plugin's status to `error`, restart the
server, and observe the loader log line `retrying plugins that failed
activation on a previous boot` followed by a successful activation (or a
fresh `last_error` if the plugin is genuinely broken).

## Risks

- A genuinely broken plugin now costs one bounded activation attempt per
boot (the attempts run in parallel with the ready batch under
`Promise.allSettled`). It cannot crash-loop within a running process,
and it returns to `error` with a fresh message.
- The flip clears `last_error` before the attempt. If the process dies
between the flip and the activation, the row is `ready` with no error
text; the next boot simply loads it as a ready plugin.
- Operators who relied on `error` as a manual "keep this off" latch
should use the `disabled` status, which this change does not touch.

## Model Used

- Claude (Anthropic) — Fable 5, model id `claude-fable-5`, extended
thinking, agentic tool use via Claude Code CLI.

## 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
- [ ] 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
2026-08-23 16:52:42 -07:00
Dotta ae6761e2b0
fix(server): authorize agent resume through direct grants (#12047)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Paperclip keeps agent lifecycle changes behind control-plane
authorization
> - Plugins can create agents in a paused state until an operator
activates them
> - An agent with a direct configuration grant could not resume these
agents
> - A paused plugin-managed agent also had no stable provenance in its
pause reason
> - This pull request adds one protected resume path and preserves every
other lifecycle gate
> - The benefit is safe recovery from plugin provisioning without a
broad permission change

## Linked Issues or Issue Description

Refs #8168. That pull request uses a role capability and also opens
clear-error. This change uses the current grant system and keeps
clear-error closed.

**What happened?**

A plugin can create a paused managed agent. An agent actor cannot resume
that agent, even when the actor has a direct `agents:configure` grant.
The paused agent can also have a null pause reason.

**Expected behavior**

An agent with a direct `agents:configure` grant can resume an accessible
paused agent. An agent without that grant cannot resume it.
Plugin-managed paused agents show stable plugin provenance. A completed
resume stays in effect after reconcile.

**Steps to reproduce**

1. Install a plugin that declares a managed agent with `status: paused`.
2. Give a same-company agent a direct `agents:configure` grant.
3. Call `POST /api/agents/{id}/resume` with the granted agent key.
4. On the base revision, observe a board-only authorization error.

**Paperclip version or commit**

`master` at `63df7ad2b3`.

**Deployment mode**

All deployment modes. This is a server authorization and reconcile
behavior.

## What Changed

- The resume route now uses the protected `agent_config:update` decision
with `requiresChangeGrant: true` for agent actors.
- The route keeps board access, tenant non-disclosure, and invalid
organization-chain protection.
- Resume activity now records the real user or agent actor, run, and API
key.
- Plugin-managed paused agents now receive a stable provenance reason
and pause time at creation.
- Reconcile backfills only a null reason on an agent that is still
declared and stored as paused.
- Reconcile preserves manual, budget, system, and other pause reasons.
It does not pause a resumed agent again.
- The implementation specification now records the narrow resume
exception.

## Verification

- `pnpm exec vitest run
server/src/__tests__/agent-cross-tenant-authz-routes.test.ts
server/src/__tests__/plugin-managed-agents.test.ts` passed: 2 files and
26 tests.
- `pnpm --filter @paperclipai/server typecheck` passed.
- `pnpm -r typecheck` passed.
- `pnpm build` passed.
- GitHub CI passed all policy, typecheck, build, test, e2e, canary, and
security gates on commit `306edf469c`.
- Greptile reviewed all 5 changed files. Its check passed with 0
comments and 0 unresolved threads.
- The host uses Node 22.22.2. The repository requests Node 24.11 or
newer, so pnpm printed engine warnings.
- A broad `pnpm test:run` attempt did not complete its general-server
group. Runtime port fixtures failed because host port `52000` was
already bound. The isolated failing fixture reproduced the same port
conflict. The focused feature tests passed before and after the final
commit.

## Risks

The main risk is an unintended lifecycle permission increase. The change
limits agent access to resume only. It requires a protected
direct-change decision. It does not open pause, clear-error, terminate,
approval, or key-management routes. Tests cover denial, self-denial,
tenant isolation, organization-chain checks, and activity attribution.
There is no database migration.

> This change fixes a narrow gap in the completed plugin, approval, and
activity-log roadmap areas. It does not add a new roadmap feature.

## Model Used

OpenAI Codex `gpt-5.6-sol`, with xhigh reasoning, tool use, 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>
2026-08-23 16:15:32 -05:00
Nicky Leach 63df7ad2b3
feat(login): use the login pseudo-terminal for Codex device login and de-Claude the shared channel (#12020)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent adapters use provider-specific login flows
> - Codex device login needs a live pseudo-terminal (PTY), while the
shared channel still uses Claude-specific names
> - The old streamed-exec path does not provide the prompt transport
that Codex needs
> - This pull request moves Codex device login to the shared login PTY
and removes the dead streamed-exec path
> - The benefit is one controlled login transport with fail-closed
capability checks and safer credential reads

## Linked Issues or Issue Description

**Problem or motivation**

Codex device login used a streamed-exec path that did not provide the
required prompt transport. The shared login channel also exposed
Claude-specific names outside Claude code.

**Expected behavior**

The host selects a fixed login command from trusted adapter data. Codex
login uses the provider login PTY. Providers without that capability
fail closed.

**Proposed solution**

Use a server-controlled session home, create and validate it as a fresh
0700 directory, read credentials from one validated descriptor, and
rename shared channel names to the neutral login PTY family.

**Alternatives considered**

Keep the shared login PTY as the single transport. Do not keep the
removed streamed-exec path because it cannot provide the required prompt
transport.

**Roadmap alignment**

This change supports the planned login transport work. It does not add a
separate roadmap item.

## What Changed

- Route Codex device login through the shared login PTY transport.
- Select the login command from a closed internal command key.
- Carry a server-controlled session home through the launch contract.
- Create and validate the session home as a fresh 0700 directory owned
by the login user.
- Read the credential file with descriptor-relative, no-follow path
walking and final descriptor checks.
- Gate the login route and run lease on the provider login PTY
capability.
- Rename shared channel names to the neutral login PTY family.
- Remove the streamed-exec transport value, selector field, driver
branch, and related tests.
- Hide Codex login in the user interface when the provider lacks the
login PTY capability.

## Verification

- Server unit suites pass: 89/89.
- Adapter-utils suites pass: 262/262.
- Codex-local suites pass: 326/326.
- Credential-read reader suite passes: 20/20.
- Daytona login PTY suite passes: 30/30.
- Device-login suites pass: 56/56.
- TypeScript checks pass for server, adapter-utils, and UI.
- GitHub Actions must pass after pull request creation.
- Greptile review must reach 5/5 with no open P2 findings,
recommendations, or follow-ups.

## Risks

- Providers without a login PTY capability lose Codex login support by
design.
- The credential read rejects invalid ownership, mode, type, path, and
size.
- The launch-time sandbox directory race remains outside the threat
model because the login runs inside the sandbox and a hostile sandbox
already controls its credential.

## Model Used

OpenAI Codex, GPT-5, tool use and code review assistance. The exact
context window and reasoning mode are not exposed 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>
2026-08-23 09:44:59 -07:00
Nicky Leach 16b59c9315
feat(adapter-utils): stream duplex bridge bodies as sequenced chunks with receive-side spill (#12006)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent adapters use a duplex bridge to send requests and responses
across an isolated boundary
> - The bridge held each request body and response body in memory on
both ends
> - Large bodies can exhaust memory and reduce the safe size of adapter
traffic
> - This pull request sends receive-side bodies as sequenced chunks and
spills large bodies to disk
> - The benefit is bounded memory use with strict size, order, and
cleanup checks

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The adapter-utils duplex bridge transports request and response bodies
across the sandbox boundary.

**Current behavior**

The bridge stores each complete body in memory on both ends of the
duplex channel.

**Proposed behavior**

The bridge sends body chunks with sequence checks. The receive side
keeps bodies up to 1 MiB in memory and spills larger bodies to a
temporary file.

**Reason and benefit**

This change reduces memory pressure and keeps malformed or oversized
input on a terminal error path.

**Breaking changes**

The duplex frame version changes to version 2. The request and response
envelopes now carry bodyByteCount, and body_chunk frames carry the body
data.

## What Changed

- Add version 2 body_chunk frames with 256 KiB raw slices encoded as
canonical base64 text.
- Add receive-side memory and spill reassembly with per-channel disk and
file limits.
- Reject malformed, reordered, oversized, truncated, and non-canonical
body chunks.
- Stream reassembled request bodies to the host forward handler with a
web stream and half-duplex request.
- Remove spill files on success, failure, channel death, and startup
cleanup.

## Verification

- Run the adapter-utils type-check.
- Run the adapter-utils duplex test suite.
- Run all pull request checks.
- Run the Greptile review and confirm a 5/5 score with no open findings.

## Risks

The wire format changes from version 1 to version 2. Older bridge peers
cannot use this protocol. The receive path adds temporary file
operations and cleanup paths. The implementation fails closed when a
body violates size or sequence rules.

## Model Used

OpenAI GPT-5 Codex, tool-enabled coding agent. The exact context-window
size and reasoning mode are not exposed 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>
2026-08-23 08:52:31 -07:00
zach-hermes 8db826d18a
fix(issues): cycle-aware issue_blockers_resolved after terminal reset (#11979)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents resume blocked work through the `issue_blockers_resolved`
wake when every durable blocker is `done`
> - That wake is level-triggered: one ready state produces one wake,
shared by the issue update route, workspace-finalize backstop, and
periodic liveness backstop
> - The ready-state key hashed only the dependent id and blocker set, so
it ignored a later reset from a terminal status back into `blocked`
> - After that reset, completing the same blockers found the previous
cycle's completed wake and suppressed the new continuation
> - This pull request folds the dependent's `blockedTransitionAt` into
the ready-state key, with compatibility for old no-cycle keys
> - The benefit is that a reset blocked issue receives exactly one new
wake without watchdog status repair or a change to blocker edges

## Linked Issues or Issue Description

Refs: https://github.com/paperclipai/paperclip/issues/5985
Refs: https://github.com/paperclipai/paperclip/issues/6555
Related: https://github.com/paperclipai/paperclip/pull/8009
Related: https://github.com/paperclipai/paperclip/pull/11570

This change does not auto-flip `blocked` to `todo`. The wake is the
continuation. It also does not treat cancelled blockers as resolved.

**What happened?**
A blocked assigned issue that was previously `done` or `cancelled`, then
reset to `blocked` on the same blocker set, did not receive
`issue_blockers_resolved` when those blockers later returned to `done`.
A completed wake from the previous cycle reused the same level-triggered
state key and suppressed the new wake. Route-time emit,
workspace-finalize backstop, and periodic liveness backstop all used
that helper.

**Expected behavior**
When every durable blocker is `done`, a currently `blocked` assigned
issue must receive exactly one valid `issue_blockers_resolved`
continuation for the current blocked cycle. A completed wake from an
earlier cycle must not suppress it. Watchdog `blocked` → `todo` repair
must not be required.

**Steps to reproduce**
1. Assign issue B, block it on issue A, mark A `done`, and let B receive
`issue_blockers_resolved`.
2. Mark B `done`.
3. Reset A to `todo` and reset B from `done` to `blocked` on the same A
id. This refreshes `blockedTransitionAt`.
4. Mark A `done` again.
5. Observe that B stays `blocked` with no new `issue_blockers_resolved`
wake.

**Paperclip version or commit**
`master` at `cc42a67e7e9e8eb183097afc8ff4ebfa694fb3e0`

**Deployment mode**
Self-hosted server

## What Changed

- Extend `buildIssueBlockersResolvedWakeStateKey` so the digest includes
the dependent's `blockedTransitionAt` as UTC ISO-8601, or `none`
- Thread `blockedTransitionAt` through `listWakeableBlockedDependents`,
both route emit sites, and both backstop candidate selects
- Keep compatibility: new cycle-aware keys suppress in idempotent
statuses; old no-cycle state keys suppress when in-flight, or when
completed and `requestedAt >= blockedTransitionAt` (or the cycle is
null); legacy per-edge keys stay in-flight-only
- Do not rewrite `blockedByIssueIds`, auto-flip `blocked` → `todo`, or
delete historical wake rows
- Add helper, route, restore, chained dependent, and backstop tests for
the reset cycle

## Verification

```
pnpm --filter @paperclipai/server exec vitest run \
  src/__tests__/issue-dependency-wakeups-routes.test.ts \
  src/__tests__/heartbeat-issue-liveness-escalation.test.ts \
  src/services/issue-dependency-wakeups.ts \
  src/services/issue-dependency-wakeups.test.ts
```

Local result: all named tests passed (helper 9, routes 8, liveness 26).

## Risks

- Deploy overlap: in-flight and same-cycle completed wakes still exist
under the old no-cycle key. The lookup keeps those as suppressors so
this change does not enqueue a duplicate in the current cycle.
- A completed old-key wake from before the current `blockedTransitionAt`
no longer suppresses. That is the intended fix.
- No schema migration. Rollback is revert of this PR.
- This does not change cancelled-blocker semantics or watchdog `blocked`
→ `todo` repair.

> 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

- Provider: xAI
- Model: Grok 4.6
- Tool use and code execution: yes
- Human-authored: no

## 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>
2026-08-23 08:50:38 -07:00