Expose the credential-entry response separately from human-only secret generation and verify the typed contract through OpenAPI and real agent authentication.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Record actual agent-key and JWT handoff evidence, human rotation compatibility, and retained CI failures.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Return a saved setup handoff for delegated agents and reject plaintext signing-secret generation at the service boundary. Verify key/JWT handoffs preserve credential refs and human sessions can still rotate.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
## Thinking Path
> - Paperclip helps people manage AI agents and their work.
> - Each task page shows the instruction and saved conversation.
> - Cold opens show recent content before older history.
> - The page used any linked run as evidence of older messages.
> - A task's first run therefore showed an empty More messages control.
> - This PR shows the control only when the preview omits comments or
runs.
> - Fresh tasks stay clear, and older task history remains available.
## Linked Issues or Issue Description
Refs: #17593.
**What happened?**
A fresh task with only its first run displayed More messages, even
though there was no earlier history to load.
**Expected behavior**
Show More messages only when older comments or runs are omitted. Runs
observed while the page stays open must not create a false disclosure.
The output control also uses actual skipped bytes, so a growing run does
not gain an empty output control.
**Steps to reproduce**
1. Create a task and let its first run start or finish.
2. Open that task with a fresh application cache.
3. Observe the empty More messages control below its instruction.
## What Changed
- Keep omitted-run evidence with the cached recent run window.
- Use omitted comments or runs to decide whether to show More messages.
- Preserve run retention, reconnect reconciliation, and expansion of
real history.
- Offer More run output when a single legacy log exceeds the compact
byte window.
- Keep first-run native diagnostics accessible through More task actions
→ Show task activity.
- Add regression coverage and update the task feature map.
## Verification
- Passed the existing 9,168-test UI suite across 794 files, then all 504
focused task-detail, history-window, real thread, and log-transport
tests after adding the activity-menu regression.
- Passed workspace build, workspace typechecks, token gates, and map
checks.
- Reproduced the bug in the earlier UI using a disposable local task.
The corrected UI hides the control with zero runs or only the first run.
- In the local browser, expanded a long task to all 80 comments. The
latest answer appeared once and the disclosure disappeared. No console
warnings or errors occurred in that journey.
- Expanded a saved 111 KB legacy log through More run output and opened
its earlier activity in the local browser.
- On a single saved native run, verified no More messages control. Used
Show task activity to reveal its earlier tool output; the latest answer
remained visible exactly once, with no console warnings or errors.
- The first broad local run stopped because the fresh dependency install
lacked PostgreSQL library symlinks. The normal package setup repaired
that environment issue.
- The next broad run hit one workspace-runtime timeout. Its focused
rerun passed with unchanged server source; the original failure remains
recorded. Stopped the already-failed broad runner after the previous
revision passed full PR CI. All final-head build, typecheck, test, and
policy CI jobs passed. Both automated reviewers scored the final head
5/5, with no unresolved threads. The separate Entire Gates check is
pending because the PR has no active assessed Change for its current
comparison. The installed Entire CLI reports no linked project trail and
exposes no Change-assessment command; no gate or repository settings
were altered. Browser verification used this branch's UI with the
existing disposable test-drive API. No agent execution was started.
## Risks
Low risk. This changes the recent run cache shape and the disclosure
condition. The full run cache remains an array. Tests cover first-run
states, observed new runs, omitted older runs, expansion, and reconnect
reconciliation. No schema or API changes. A separate run-output control
preserves access to a single truncated legacy log. The task menu
preserves first-run native activity access without implying older
messages exist.
## Model Used
OpenAI GPT-6 through Codex, with code execution and browser tools. A
more specific model ID and context-window size are not exposed in this
session.
## 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
- [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>
Project profiles can affect any company agent running work in that project. Check the existing configuration authority for all affected agents on bind, unbind, and retained profile edits, alongside project visibility.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
## Thinking Path
> - Paperclip lets people manage AI agents and their work.
> - The HTTP server also owns durable Runner state.
> - Each committed event rewrites and flushes that state on the HTTP
thread.
> - Large journals and slow writes delay unrelated navigation and saves.
> - Event acknowledgements must still wait for durable storage.
> - This PR stages output writes asynchronously and joins them before
writer replacement.
> - The board can serve requests while Runner output waits for storage.
## Linked Issues or Issue Description
Refs: #17507. Related: #17514 reduces writes per event burst. This PR
moves individual output writes and file flushes outside the HTTP thread.
**What happened?**
A live CPU profile spent about three seconds of a 13-second sample
serializing and synchronously writing Runner state. Representative
journals were about 9 MB. Unrelated task requests had multi-second
delays.
**Expected behavior**
A slow output-journal write must leave unrelated HTTP requests
responsive. An event must not be acknowledged before it is durable.
**Steps to reproduce**
Hold an authenticated output event's file flush in the durable protocol
test. Send an unrelated HTTP request during that flush. Also save a
command, reconnect, or retire the controller during the write.
## What Changed
- Stage `item.delta` snapshots with asynchronous file writes and file
flushes. Keep lifecycle, control, authentication, and tool events
synchronous so transport readers observe durable boundaries.
- Fence publication by saved revision. An older snapshot cannot replace
newer commands or connection state. A failed write fences the writer.
- Write compact JSON and share private-file checks. Existing journals
remain readable.
- Stop external ingress before joining admitted writes. Checkpoint only
after retirement succeeds. Close reports a failed detach consistently
and releases notification consumers.
- Add real HTTP and Rust transport cases for held writes, reconnects,
commands, failure, restart, close, and timeout.
- Add immutable Copilot source identity v61 for the changed shared
transport. Preserve v60, historical decoding, exact-current launch
checks, and qualification flags. No new live Copilot qualification is
claimed.
## Verification
- Head `6f5c92e778`: workspace `pnpm -r typecheck` and `pnpm build`
passed. All CI gates passed in [run
40356159484](https://github.com/paperclipai/paperclip/actions/runs/40356159484),
including both full Runner shards. Fresh Greptile review is 5/5; all
findings are resolved.
- Current-base focused verification passed 300 cases across protocol,
real Rust restart/continuation, permission, backend, and
immutable-profile suites. The complete transport suite also passed 286
cases before the base refresh.
- Earlier iterations exposed lifecycle visibility, late writer
publication, and close-order failures. Controlled regressions reproduced
each before repair. CI also found missing test-peer drain methods and a
stale source fingerprint; both are corrected. An older broad local test
run was stopped after its source was superseded. No full local-suite
pass is claimed; full coverage passed in isolated CI.
- A synthetic 9 MB journal comparison used 20 writes per sample and
concurrent HTTP probes, with alternating baseline/treatment order. HTTP
median changed from 31 ms to 2–3 ms; p95 changed from 51–85 ms to 12–21
ms. Parsed output was equal. The asynchronous loop served 125–153 probes
versus 19–20, and took longer overall (992–1069 ms versus 675–678 ms).
This proves local I/O responsiveness, not deployed application latency.
- Deployment and live save/archive acceptance remain pending.
## Risks
Persistence interleavings affect restart authority. The tests cover
concurrent commands, replacement, failed storage, and reopening the
journal. JSON serialization, atomic rename, directory flush, and
control-event writes remain synchronous. This change still rewrites
whole journals. Incomplete retirement retains recovery evidence and
fails the close. A new exact-current Copilot source identity can reject
an older launch identity; historical decoding remains available. No
migration is required.
## Model Used
OpenAI GPT-6 (Codex), with reasoning, tool use, SSH and browser
diagnostics, code editing, and test execution. The exact serving model
suffix and context-window size are not exposed in this session.
## 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>
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native agents use assigned connection tools through a governed
gateway.
> - OpenCode received the gateway catalog directly, outside the bounded
server tool projection.
> - A large catalog can exceed a provider grammar compiler's capacity
even when it fits the transport limits.
> - Synthetic requests reproduced the Fireworks grammar timeout on the
configured DeepSeek model.
> - This pull request gives OpenCode two assigned-tool discovery and
call schemas through the existing server relay.
> - The gateway keeps the same grants, validation, approvals,
revocation, and audit rules.
## Linked Issues or Issue Description
**What happened?**
A native OpenCode run could fail during provider grammar compilation
before its first assigned-tool call. OpenCode advertised the full
assigned gateway catalog. A synthetic catalog of 741 tool schemas
reproduced `Grammar processing took too much time` on Fireworks through
OpenRouter with `deepseek/deepseek-v4.1-flash-1017`. The same model and
backend accepted a compact two-tool discovery/call catalog. This
reproduces the mechanism; it does not replay a historical private
request.
**Expected behavior**
Assigned-tool discovery must keep provider grammar size bounded. Every
call must retain the run's original gateway binding and permissions.
**Steps to reproduce**
1. Give a native OpenCode run a large assigned connection catalog.
2. Use a provider that compiles tool schemas into a constrained output
grammar.
3. Observe the full catalog in the provider tool surface before this
change.
4. After this change, observe only `paperclip_search_assigned_tools` and
`paperclip_call_assigned_tool` for assigned tools. Discover and call a
permitted tool through its pinned alias.
**Paperclip version or commit**
Source checkout based on current `master`.
**Deployment mode**
Native local or sandbox execution with OpenCode 1.18.34.
Related work: Refs #14258 (discovery paging), #16678 (local adapter MCP
launch), and #17688 (gateway capability advertisement). This change
covers native OpenCode catalog projection.
## What Changed
- Route native OpenCode assigned tools through the existing server-owned
authenticated relay.
- Use bounded discovery/call schemas for OpenCode, including small
catalogs. Preserve transport capacity checks.
- Keep assigned gateway credentials on the controller. Ignore gateway
and credential values in tool arguments.
- Preserve exact declared MCP operation names through admission and
driver dispatch. Resolve transport prefixes only against the closed
catalog. Reject unknown or shortened names.
- Refresh former OpenCode direct-catalog and shortened-name checkpoints.
Keep the existing fingerprints for other providers.
- Add local and remote wiring, catalog capacity, alias, scope,
work-mode, approval, and revocation tests.
- Allow the native test files to use a validated dedicated external test
database when embedded PostgreSQL is unavailable.
- Document the assigned-tool execution contract.
- Bound OpenCode discovery pages to 32 KiB and large-schema chunks to
16K characters. Keep other harness budgets unchanged.
- Test medium pages and escaped large schemas through the actual HTTP
MCP bridge on the explicit Runner testing surface.
## Verification
- Red before the catalog fix: OpenCode did not create the server relay,
and forced compact delivery advertised 1 or 741 direct schemas.
- Red before the alias repair: HTTP MCP changed declared operation
names, and the driver sent `search_assigned_tools` instead of the
authorized `paperclip_search_assigned_tools`.
- Current repair tests: 112 OpenCode/proxy tests pass, plus one actual
Rust/proxy/HTTP MCP regression. Two checkpoint regressions fail with the
former scoped revision and pass with the new revision. Other providers
keep their prior fingerprints.
- The combined QA candidate with this exact PR head passes all 916
native tests and all 113 transport tests on supported Node 24.22. An
earlier Node 26.4/macOS run passed the 113 assertions but had an
uncaught networking error. That non-clean run remains recorded; its
stack matches [the upstream Undici
defect](https://github.com/nodejs/undici/issues/5544). No production
workaround or error suppression was added.
- `pnpm -r typecheck`, `pnpm build`, and `git diff --check` pass on
`bc41ba72be2195eabeb0d7727227ee0cd02e8532`. The maps structural check
passes.
- The local `pnpm test:run` attempt stopped after host embedded
PostgreSQL initialization failures. The relevant database suites pass
with isolated PostgreSQL 18. All repository CI gates, including
aggregate `ci / verify`, pass on the current head.
- Synthetic live provider comparison: 741 invented schemas produced the
exact Fireworks grammar timeout in 20.9 seconds. Two compact invented
schemas produced a discovery call in 585 ms on the same model and
backend.
- The first hosted QA attempt exposed the alias failure described above.
On the patched source, a real local Rust runner → proxy → OpenCode
1.18.34 → exact DeepSeek smoke completed discovery, one synthetic
gateway read, and `paperclip_finish`, then emitted `turn/completed`. It
used the production compact projection and unchanged Rust allowlist.
- Two earlier local smoke attempts exposed missing terminal authority
and completion-contract fields in the smoke harness. Those failures
remain recorded. The corrected ordinary bindings produced the clean
result.
- Fresh Greptile: 5/5 on `bc41ba72be2195eabeb0d7727227ee0cd02e8532`,
with no new actionable findings or unresolved threads.
- Hosted QA publication and lifecycle acceptance remain pending. The
separate deployed-agent `Paperclip Review` check is also pending; it
follows a task that failed on the earlier deployed runtime.
- Local OpenCode/OpenRouter acceptance at `bc41ba72`: 530 synthetic
tools were authorized and installed. A simple model-ID reply completed
in 17.3 seconds with no app calls. A discovery task completed in 37.6
seconds, used the search/call relay, made one upstream call, and
returned the exact synthetic value. This is local source acceptance, not
a staging sandbox timing comparison.
- The large-result review finding has a failing-before/passing-after
HTTP MCP regression. Five medium schemas now page without invalid JSON.
A large schema with escaped text reconstructs exactly through bounded
chunks. All 35 assigned-tool tests and the server typecheck pass after
this follow-up.
- Final head `d84ce4856a6e65a35ad5fb8b561492598b525f4e`: all CI gates
pass. Greptile and Paperclip Review both rate the change 5/5. No review
threads remain open. The final full build, server typecheck, and 35
assigned-tool tests pass locally.
## Risks
- OpenCode uses discovery before it calls an assigned tool, including
for small catalogs. This can add a model turn.
- An existing OpenCode provider checkpoint rotates once because it
retains the former tool declarations. Paperclip task history remains
available.
- The historical filtered catalog was not captured. The synthetic
comparison proves the failure mechanism, not the exact cardinality of an
earlier private request.
- No model, provider route, permission, or automatic retry policy
changes.
## Model Used
The bounded-result follow-up also used OpenAI Codex (GPT-6 family). The
exact backend model ID and context-window size were not exposed for that
session. It used reasoning, code execution, and tool use.
OpenAI `gpt-6.1-sol` in Codex, with reasoning, tool use, code execution,
and source inspection. 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>
## Thinking Path
> - Paperclip keeps human-agent conversations attached to tasks.
> - People need to read and reply comfortably from a phone.
> - The mobile task page scrolled the document and positioned its
composer with a sticky navigation offset.
> - Safari's keyboard resize and later focus pan could move that
document again, causing overlap, gaps, and jumps while editing.
> - This change gives mobile and desktop the same message scroller and a
normal flex footer.
> - CSS owns the layout. A small VisualViewport adapter handles the
visible height and Safari's stale document focus scroll.
> - Streaming no longer measures every historical row while following
the bottom.
## Linked Issues or Issue Description
Fixes https://github.com/paperclipai/paperclip/issues/16497
Related: https://github.com/paperclipai/paperclip/pull/15245 also
addresses keyboard positioning. This change additionally removes mobile
document auto-follow and reduces historical-row measurement work.
## What Changed
### One scroll owner and a natural-flow composer
Before:
```text
Document scroll + mobile auto-follow
└─ Conversation + sticky composer + animated navigation offset
```
After:
```text
Height-constrained conversation shell
├─ Header
├─ Message scroller — owns follow/reading position
└─ Composer — normal flex footer
Navigation stays at the layout viewport bottom, behind the keyboard
```
- Reuse TaskMessageScroller on mobile. Delete the separate 136-line
useWindowAutoFollow implementation and its superseded tests.
- Keep the composer in normal flex flow. Remove its sticky bottom
positioning and navigation-offset animation.
- Constrain the mobile conversation with CSS. Classic tasks and other
pages retain their existing layout.
- Add a 47-line useMobileVisualViewport hook. It changes shell height on
resize, not on typing or incoming messages. It never translates the
shell or hides navigation.
- Reject Safari's stale document focus pan only for an unzoomed,
keyboard-open conversation. Inner message and editor scrolling stay
native.
- Keep a saved reading anchor when reading older messages. Skip
historical-row measurements while following the bottom.
- Update tests and the existing mobile streaming fixture. Keep only two
layout-contract sentences in DESIGN.md.
**Scope:** 19 files, +367 / -482 lines: 115 fewer lines overall.
Production UI/CSS alone is +158 / -190 lines. No API, database, or
dependency changes.
## Verification
Bottom-follow is also saved explicitly for Back navigation. A new
regression covers returning after rotation changes message wrapping,
without restoring historical-row scans.
### Physical iPhone acceptance
Tested on an iPhone 15 Pro running iOS 26.7.1. The reporter confirmed:
- Opening the keyboard positions the composer correctly immediately,
before any typing.
- The installed web app works.
- Long drafts, insertion, deletion, and sending are acceptable. The
reporter described long drafts as not perfect but good enough.
- Reading older messages during incoming output preserves position;
returning to the bottom resumes following.
- Rotation, keyboard close/reopen, and attachment/picker transitions
work.
Remote inspection corroborated the corrected open-keyboard state:
visible height 358px, composer bottom 358px, document scrollY 0.
Navigation remained display:block at y=631px, behind the keyboard.
Earlier candidates failed device testing. The decisive trace showed a
correct viewport resize followed about one frame later by a stale 337px
native document focus pan. Typing caused Safari to correct it. Tests now
cover that event ordering, the reverse ordering, and zoom panning.
### Performance evidence
The existing TaskChatPerfHarness supplied 200 historical responses,
4,000 collapsed tools, and 30 updates at 100ms intervals.
| Measurement | Before | After |
| --- | ---: | ---: |
| Historical row geometry reads | 6,000 | 0 |
| Renderer main-thread work | 331.2ms | 273.5ms |
| Largest task | 27.1ms | 12.3ms |
This is one instrumented Chromium development run on the Mac, not a
phone benchmark or a statistical speedup claim. The zero-row-measurement
result also has a regression test that failed with 6,000 reads before
the change.
To reproduce, serve ui/tests/task-chat-perf.html with the UI Vite
server. Record 30 streaming updates at the bottom. Inspect
TaskMessageScroller and row getBoundingClientRect calls. Existing
historical-render tests also confirm that unchanged Markdown does not
reparse on live-tail updates.
### Automated and full-app checks
- [Current-head
CI](https://github.com/paperclipai/paperclip/actions/runs/39862524031)
is green: 54 successful checks and 2 skipped checks. Greptile rates the
current head 5/5, confirms the Back-navigation fix, and has no
unresolved findings.
- **601 focused tests pass** across the task page, layout, composer,
scroller, viewport adapter, and historical-render coverage.
- UI typecheck and production build pass.
- Token gates, Storybook catalog checks, and catalog/map structural
tests pass.
- Independent review of the final source tree passed with no findings.
- The full source app ran on macOS with an isolated database and saved
conversation history. A reply sent through the real UI persisted after
reload. Provider execution was not part of this layout test.
- **Full local repository checks did not pass.** Build/typecheck stop at
missing Rust cargo. The full test run reported 142 failed server tests
and 3 failed suites; missing cargo is confirmed in those three suites.
The other server failures were not diagnosed in this UI task.
Current-head CI now supplies the repository-wide evidence; these local
failures remain disclosed.
## Risks
- Mobile conversations now share the desktop scroll owner. Navigation,
loading, history restoration, and reading-position tests cover that
change.
- The keyboard-state threshold is a 120px viewport reduction.
Accessory-only keyboards retain the normal navigation spacing.
- The document-scroll fallback is scoped to rendered conversations with
an open keyboard at scale 1. It does not handle inner scrolling or
prevent zoom panning.
- Long-draft behavior is accepted, with minor polish still possible.
- The UI change is reversible and requires no data migration.
## Model Used
OpenAI GPT-6 Astra, exact model ID gpt-6-astra, through OpenCode.
Capabilities used: reasoning, code editing, tests, Chromium performance
tracing, and Safari remote inspection. The harness does not expose the
context-window size. An independent general-purpose subagent reviewed
the final tree; its serving model ID was not exposed.
## 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 or instance-derived details
- [x] I have run focused tests locally and they pass; repository-wide
failures are disclosed 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
A saved aiLogin link reaches the existing owner-validated login panel without a catalog source. Add an entry-policy regression that failed before the fix and reject empty identifiers.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Restore existing chat provenance notes and enumerate private voice and phone operations. Record unsupported MCP GET transports and the authenticated device-session regression evidence.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Use the shared connection authority for device-login management while preserving the responsible user as immutable owner. Keep refreshed continuation context available at dispatch. Add bearer-authenticated saved-session reads, cancellation, and owner isolation coverage.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
* codex/agent-connection-api-parity:
test(chat): compare retry action IDs in a stable order
fix(connections): bound resource checks and preserve current delegation
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native Codex agents use the saved agent settings to prepare each
provider launch.
> - Onboarding saves web search as off, but native configuration
conversion removes that setting.
> - Codex 0.160.0 includes a hosted web-search tool by default, even in
an authentication probe that asks it not to use tools.
> - A gateway that permits only priced function tools can reject that
request before budget admission.
> - This change preserves the explicit restriction through native
execution and disables web search for authentication probes.
## Linked Issues or Issue Description
**What happened?**
A native Codex authentication probe can include hosted web search.
Normal task execution also loses a saved `search: false` setting. A
restricted Responses gateway can reject these requests before it makes a
model call. Related repairs: Refs #17445, Refs #17529. The roadmap and
related PRs were checked; no duplicate repair was found.
**Expected behavior**
Authentication probes check the selected account and model without
hosted web search. A saved search-off setting remains effective in
native task launches, prepared launches, and session recovery. Existing
behavior for an absent setting remains unchanged.
**Steps to reproduce**
1. Create a Codex agent with search off and choose Paperclip Runner.
2. Use a Responses gateway that rejects hosted tools.
3. Inspect the request from the native authentication probe or task
launch. Before this fix, the pinned Codex SDK includes `web_search`
despite the saved setting.
## What Changed
- Preserve an explicit search-off setting when native agent
configuration is built and converted.
- Carry the restriction in the durable native input and provider launch
requirements.
- Apply the restriction to authentication probes and normal launch
paths, including custom arguments and recovery.
- Reject prepared launches that discard the required restriction. Keep
gateway billing rules unchanged.
- Admit only the restrictive literal value in the strict plugin task
API. Exercise the real plugin setup path.
- Add regression coverage and document the policy.
- Add the immutable Copilot v60 source identity required by the changed
shared files. Preserve v59 and all original live evidence. Copilot
authentication probes keep their prior launch requirements.
## Verification
- Regression cases were run against the unfixed source and failed at the
configuration and launch boundaries.
- An isolated capture using the real Codex 0.160.0 app-server reproduced
hosted-tool rejection. Disabling web search reached a mocked budget
reservation. The helper and child processes permitted only loopback
network access and used synthetic credentials. It made zero upstream
calls.
- Focused checks passed: 284 server cases, 61 native form cases, 198
backend/security/launch/parser cases, and 36 authentication/launch
cases. A separate complete transport/launch/parser run passed 393 cases.
These groups overlap.
- Head `617b98f` passed workspace typecheck/build and 28/28 plugin
contract and actual Runner probe tests with no skips. Final rebased head
`20ff0c1` passed all current-head CI checks, including full isolated
test lanes, and fresh Greptile and Paperclip reviews at 5/5.
- The additive Copilot identity update passed 134
compatibility/policy/protocol checks and nine authentication probe
checks. The real pinned Codex SDK capture was repeated after the final
policy change: all five cases passed with zero upstream calls.
- Two local full-suite attempts stopped after native PostgreSQL loader
failures. Seven local dependency aliases were restored, and an isolated
cluster initialized successfully. A third run later encountered host
PostgreSQL semaphore exhaustion and was interrupted before
source-profile regeneration. Its zero exit code after SIGINT is
explicitly not a full-suite pass. Final full-suite verification runs in
isolated CI; the local attempts remain recorded.
- The first CI run exposed a missing strict plugin API field. Its five
failures were reproduced locally, then passed after repair. The next run
passed every underlying job except the source-identity guard. That guard
now binds an additive identity with v59 retained. Final-head CI and both
fresh reviews passed; addressed review threads are resolved.
- The offline capture runs on Darwin ARM64. It does not prove the
contents of a prior unretained Linux request or complete Cloud
onboarding acceptance.
## Risks
- The restriction must survive prepared launches and resumed sessions.
Regression tests cover those boundaries.
- Existing absent settings retain their prior behavior. This change does
not add native search-on support or loosen gateway admission.
- Older durable inputs without the optional restriction must remain
valid.
- Copilot now uses profile v60 for exact launch admission. Historical
v59 inputs remain readable. The new declaration adds no live Copilot
qualification and does not change its executable or admission flags.
- A deployed Cloud acceptance run is still required after this source
repair.
## Model Used
- OpenAI GPT-6 through Codex, with reasoning, code execution, and
delegated review. The exact backend model identifier and context-window
size are not exposed in this session.
## 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>
The retry authorization test checks that the same action rows remain. Sort both database reads so a PostgreSQL scan-order change does not report a mutation.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Limit and deduplicate management selectors before lookups, hide foreign resources, and reuse captured run identity only for request-local capability reads. Re-resolve resources at commit-time checks and enforce proposed provider scope. Preserve rate-limit admission during the final test dispatch check.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent settings select an authorized AI account independently of the
harness and model.
> - Multiple accounts can have the same provider name.
> - The account picker and legacy adoption dialog showed only that name.
> - Operators could not distinguish a personal API key from a shared
subscription during credential repair.
> - This pull request shows the existing sign-in method, sharing scope,
and available account identity before selection and adoption.
> - Operators can select the intended account while the existing access
and validation checks remain effective.
## Linked Issues or Issue Description
Refs #14970 for the shared account selection control. No duplicate
account-identity repair was found.
**What happened?**
Two authorized OpenAI accounts appeared as identical `OpenAI` choices.
The adoption dialog repeated that ambiguous name. The list response
already contained the account method, scope, and identity, but the UI
omitted them.
**Expected behavior**
An operator can distinguish a personal API key from a company-shared
subscription and confirm the selected account before saving.
**Steps to reproduce**
1. Make a personal OpenAI API-key account and a shared OpenAI
subscription available to an agent. Give both the name `OpenAI`.
2. Open Harness / Runtime and choose a managed connection for a legacy
agent.
3. Inspect the two choices and the adoption confirmation.
**Paperclip version or commit**
Reproduced on master `a1f77821b9cd5c9c846fdf7a0fa5cc620ad2b6bb`.
**Deployment mode**
Hosted staging and the source UI regression.
## What Changed
- Show the sign-in method, personal/shared scope, and available account
or owner identity in connection labels.
- Use the same label in the selected value and legacy adoption
confirmation. Match the confirmation to both the connection and grant.
Wrap dropdown choices so narrow screens retain the account identity, and
expose the full selected label in the trigger title.
- Add a behavioral regression with duplicate provider names, exact grant
selection, and disabled unavailable accounts.
- Update affected Storybook interaction selectors, the account guide,
and the agent verification recipe.
## Verification
- Before the fix, the new regression fails because duplicate accounts
have no distinguishing metadata. The other 13 field tests pass.
- After the fix, all 67 tests in `ui/src/components/ai-connections`
pass. The regression selects the exact personal grant and keeps the
unavailable option disabled.
- `pnpm -r typecheck` and `pnpm build` pass locally. The full `pnpm
test:run` command was stopped after embedded PostgreSQL failed to
initialize after five attempts in an unrelated native-runtime suite. Its
log is retained. Current-head CI partitions must establish full test
coverage.
- Token gates, map checks, Storybook catalog checks, and all 30
map/catalog contract tests pass.
- In local Chrome, the existing production-component Storybook dropdown
shows method and scope. Its nine interaction steps pass, as do all 19
steps in the new-agent connection-modes story. At a 320-pixel preview
width, two shared OpenAI subscriptions show their distinct account
identities in full, including during keyboard selection. These fixtures
do not establish provider authentication.
- Separately, the staging credential-repair workflow validated an
existing authorized shared OpenAI connection, persisted the agent
binding across reload, and resumed the original task into real
provider/tool execution. This configuration recovery does not deploy
this UI patch or establish task completion.
- All CI completes on final head
`a283bda2ad2f026f4f3c0fee03bf2962b0ad6e02`: 55 successful checks, the
neutral Paperclip review, and two intentionally skipped Storybook
checks; no pending or failed checks. This includes the partitioned
tests, typecheck, build, runner suites, canary, and eight browser
shards. Greptile and Paperclip review both rate this exact head 5/5 with
no unresolved findings. [CI
run](https://github.com/paperclipai/paperclip/actions/runs/40338613167).
- The review's selected-trigger truncation finding is fixed in the final
head. Its title assertion failed before the fix, and all 67
account-selection tests, UI typecheck, and token gates pass afterward.
## Risks
- Labels are longer and can truncate in narrow selected-value controls;
the trigger title exposes the complete label. Dropdown choices wrap, and
the adoption dialog uses the complete label.
- The UI uses existing authorized account metadata. It adds no
credential reads, access grants, provider fallback, or account selection
policy.
## Model Used
OpenAI Codex (GPT-6). The exact serving model identifier and context
window are not exposed in this session. The agent used code editing,
terminal tests, and browser tools.
## 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>
## Thinking Path
> - Paperclip lets people manage AI agents and their saved work.
> - A stopped run can owe workspace preservation before saved input can
continue.
> - Retry saved a recovery request but did not wake the worker that owns
preservation.
> - Older recovery records could also take the bounded scan slots before
a due request.
> - A second Retry could change the revision while the physical owner
was still saving files.
> - This pull request wakes a separate worker after commit, selects due
work first, and keeps the active owner's revision.
> - Saved work can progress without replaying the stopped provider turn
or blocking other finalization.
## Linked Issues or Issue Description
**What happened?**
An operator approved a saved design and selected Retry after native
workspace finalization failed. The API accepted one canonical request.
The source remained scheduled at zero preservation attempts for more
than 30 minutes. No new provider turn started. A local regression also
found that repeated Retry during export invalidated the physical owner's
completion revision.
**Expected behavior**
Committed Retry must wake bounded source preservation. Due recovery must
progress ahead of passive cleanup obligations and unrelated history.
Duplicate requests must keep one physical attempt. Saved input must
still pass normal admission after verified recovery.
**Steps to reproduce**
1. Retain a terminal run with an exhausted workspace recovery and saved
authorized input.
2. Let the delivery coordinator become quiet, then request Retry.
3. Observe the recovery state and physical preservation receipt. Repeat
Retry while the export is held.
**Paperclip version or commit**
Observed on served commit `4b89eec644d6e1a99d58926e77ae58927c3fa87b`.
Local baseline: `a1f77821b9cd5c9c846fdf7a0fa5cc620ad2b6bb`.
Related work: Refs #17053, #17267, #17094. This change repairs explicit
Retry delivery. It is separate from the run instruction projection in
#17724 and historical unsafe-export discovery in #17687.
## What Changed
- Notify a dedicated workspace recovery duty from the transaction that
saves Retry, recovery admission, adoption, or recovery progress.
- Reconstruct work and saved retry deadlines at startup. Fill each free
export slot independently, track physical work for idle drain, and join
the dedicated worker's exports on shutdown.
- Drain one bounded pass through completed cleanup and saved-input
obligations. Restart that pass after committed changes without
repeatedly rechecking paused input.
- Share source eligibility between deadline selection and candidate
consumption. Keep resolved files-only obligations and ignore unrelated
resolved or cancelled history.
- Select due unfinished preservation before passive historical records.
Rotate past source locks held by other workers and retain the indexed
source lookup.
- Bind the canonical Retry intent without changing an active physical
attempt's generation or revision. Preserve that binding across later
progress writes.
- Add real producer, physical preservation, startup, deadline, idle, and
independent finalization regressions. Document the delivery contract.
## Verification
- Red controls: Retry without a notification stayed scheduled; duplicate
Retry invalidated the active export; whole-batch waiting stranded a
third Retry; a scan without cursor rotation starved a source behind two
actual advisory locks. Removing unfinished-first selection left HTTP
Retry scheduled behind five real recovered sources still owing cleanup.
The fixture explicitly verifies their eligibility with the worker's
actual query filter.
- Further red controls: the previous worker visits only two of three
eligible completed sources. Disabling the committed-change cursor reset
misses a new earlier source arriving while two callbacks are held. Both
pass with the final worker.
- Green: the public Retry HTTP route, registered production worker, real
file copyback, duplicate canonical receipts, and public recovery receipt
reload passed on an owned local fixture. Its agent is paused to keep
this files-only check from starting a provider turn.
- Full workspace recovery suite passed 56 tests, including the
foreign-lock regression.
- Execution-control lifecycle suite passed 24 tests. It covers idle SQL,
stored deadlines, cancelled and resolved history, independent
finalization, and shutdown. One, three, and seven paused completed
sources are each visited in a bounded pass, then stay deferred without a
successor or SQL during 90 seconds of fake-clock idle time. A committed
earlier source is evaluated when it arrives during two held callbacks.
- Both GitHub and Telegram `automatic_running` continuation regressions
passed with the new canonical intent binding.
- `pnpm -r typecheck` passed.
- `pnpm build` passed.
- `node scripts/check-maps.mjs` and `node
scripts/check-module-boundaries.mjs` passed.
- Local `pnpm test:run` could not complete: embedded PostgreSQL
repeatedly failed to start. The owned run was stopped after this setup
failure repeated. Latest-head CI supplies broad coverage.
- Earlier setup failures included a localhost sandbox denial and loss of
the owned disposable Docker database. These were separate from the
product red controls above.
- Local database tests use an explicitly named disposable PostgreSQL
`_test` database. That opt-in database is reset before the suite.
Default embedded test behavior is unchanged.
- Exact-head CI is green at `ef7dcf1ba1060864c9d216c33b51f4d9f8f57fbd`;
Greptile and Ponytail both rate it 5/5, with no unresolved review
threads. Earlier CI caught the indexed discovery assertion and two exact
chat intent-binding regressions; all three were fixed and pass locally
and in CI. A separate chat shard lost contact with its self-hosted
runner without a product assertion result. A later shared runner
shutdown interrupted several jobs; one infrastructure rerun passed
before the final test-and-worker follow-up triggered a fresh green run.
- No staging deployment is part of this PR. The original approval
remains saved; deployed recovery still needs acceptance after rollout.
## Risks
- More recovery writes now wake a bounded maintenance duty. Completed
history must not keep it active. Idle and deadline tests cover this
boundary.
- Resolved files-only obligations must remain eligible without granting
replay. The startup regression checks that path.
- Provider stop proof, copyback ownership, source binding, retry
budgets, and normal execution admission remain required. There is no
schema or public API change.
## Model Used
- OpenAI Codex based on GPT-6, with code execution and browser tools.
The exact serving model ID and context window are not exposed in this
session.
## 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>