Commit Graph
1414 Commits
Author SHA1 Message Date
DottaandPaperclip 83709f75eb fix(ui): hide task row retry status labels (#18017)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task lists and the inbox help people scan their work.
> - Shared task rows show system interruption messages beside task
titles.
> - These messages add detail that the person cannot act on from the
row.
> - This pull request removes the three system interruption labels from
those rows.
> - People can still open the task to inspect progress and use Retry.

## Linked Issues or Issue Description

Refs #16965, which introduced these labels. Related recovery report:
#17386. This change only removes row text and does not resolve that
report's retry behavior.

**What existing behavior does this improve?**

The shared task rows in task lists and the inbox.

**Current behavior**

Rows show “Retry available,” “Thinking,” or “Trying again soon” beside
the title for unresolved system interruptions.

**Proposed behavior**

Omit all three labels from shared task rows. Keep the existing
system-interruption guard so the row does not show a legacy recovery
chip in their place. Keep task status, other badges, and retry controls
inside the task.

**Reason and benefit**

People can scan task titles with less incidental execution text.

**Breaking changes**

The three row labels disappear. APIs, recovery behavior, and task
conversation controls stay the same.

## What Changed

- Remove the system interruption text from every shared task-row
presentation.
- Cover working, scheduled-retry, and failed interruptions in both row
presentations, including a legacy recovery action that must stay hidden.
- Record the expected row behavior and verification states in the task
feature map.

## Verification

- Passed: token gates, feature-map contract and reference checks, and
Git diff whitespace checks.
- Passed: 83 component tests in `IssueRow.test.tsx` and
`Inbox.test.tsx`, including the new regression cases; full `pnpm -r
typecheck`; full `pnpm build`.
- The full local `pnpm test:run` was attempted and stopped after 16
database-dependent failures. An independent disposable `initdb`
reproduced `FATAL: could not create semaphores: No space left on
device`. The host has exhausted its macOS System V semaphore capacity.
All required CI test lanes passed on the final commit and provide full
database-suite coverage. An earlier attempt also found an unbuilt plugin
SDK; building that existing dependency repaired collection before this
database failure.
- Review the working, scheduled-retry, and failed interruption branches.
Each returns no system label. The existing guard still suppresses legacy
recovery chips.
- Independent source review found no actionable code issues. Regression
cases check title navigation, removal of the three labels, and
suppression of replacement recovery chips.
- All required CI gates passed on commit
`dd1d7b08dbba8a10a95c5d24c4aea64479befe95`: typecheck, general and
serialized tests, browser suites, build, canary, and Runner checks.
- Greptile reviewed that commit at 5/5 with no open findings. The
optional Paperclip review also returned 5/5 with no findings; its check
status is neutral.

## Risks

- Low risk. This removes row text only. Task status, recovery records,
other badges, and task-level retry actions keep their current behavior.

## Model Used

OpenAI Codex, GPT-6 family. This session does not expose an exact model
ID or context-window size. The assistant used reasoning, shell tools,
and subagents for source review and validation.

## 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-10-28 08:22:13 -05:00
39279aa34f feat(ui): shared error, connectivity and query foundation for disconnects (#15754)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The board reads API data and keeps the current task on screen.
> - A restart or temporary network failure can interrupt those reads.
> - Separate page error handlers can hide cached data or expose raw
server codes.
> - The app needs one connection state, readable error copy and a
consistent read policy.
> - This change provides that foundation and moves affected read
surfaces onto it.
> - The dependent write layer in #17960 preserves edits and submissions
across the same failures.

## Linked Issues or Issue Description

**What happened?**

Temporary API failures could replace loaded content with errors.
Different surfaces handled the same outage differently. Some showed raw
server codes. A successful query to an unrelated service could also
falsely report that Paperclip had recovered.

**Expected behavior**

Keep cached content visible. Show one connection banner during sustained
trouble. Confirm recovery through the Paperclip health probe or its
WebSocket. Retry transient reads and show readable errors for permanent
failures.

**Steps to reproduce**

1. Open a populated task or workspace page.
2. Interrupt API requests with a 503 or a dropped connection.
3. Keep an unrelated external request in flight.
4. Confirm that cached content remains and that the external result
cannot clear the outage.
5. Restore the API and check that reads refresh.

The write layer first merged into this feature branch in #15769 now has
its own dependent PR, #17960. This PR contains the shared foundation and
read changes. Merge this PR first.

## What Changed

- Classify API errors and provide readable error copy, including
non-JSON proxy responses and Retry-After handling.
- Use one connection store and health probe with bounded backoff.
Confirm recovery from the server health probe or live-updates WebSocket.
- Pause reads while disconnected, retry transient errors, and refresh
active reads after recovery.
- Keep cached data visible through shared query views and affected page,
panel and plugin read surfaces.
- Add one app-level connection banner and support the pending-write
count consumed by the dependent write layer.
- Add a query-error rendering guard. Call it directly from the existing
CI step. Update development documentation.

## Verification

- Historical-chat lookup now follows the same ready/stale roster state
as rendering. Three regressions fail before the fix; the six new cases
pass after it, including working Retry, fresh data, no-cache error,
permanent 403 and company isolation. All six focused query/recovery
suites pass 200 tests. Final-commit CI passes and Apex is 5/5 with no
unresolved findings. Canary Dry Run initially refused a preview version
that was already on npm. It passed after one rerun with fresh registry
metadata; no check was disabled.

- Integrated current master and retained both transcript interest
registration and connectivity reporting on socket open. The seven
focused recovery/query suites pass 288 tests, and UI typecheck and
production build pass. All 9,451 UI tests across 799 files pass on the
merge commit. Final-commit CI passes and Apex is 5/5 with no unresolved
findings.

- Current head `70d9335d732219352ef0f98414439766bbcb33df`: all hosted CI
checks pass. Apex is **5/5** on that head with no unresolved findings.
The branch has no merge conflict. GitHub still requires code-owner
approval.

- The foundation passes 9,430 UI tests in 804 files. After integrating
current master page paths, 190 focused page tests pass.
- Two unrelated-success regressions fail before the latest fix. With the
fix, 62 focused UI tests, all six guard tests and UI TypeScript pass.
- The composed foundation and write layer pass **9,505 UI tests in 808
files**, UI TypeScript, a production UI build, and query-error, token
and map guards.
- A real Chromium journey on the composed source injects a 503 during
title save. The loaded task stays visible; one reconnect banner appears;
the edit saves after recovery; another task stays unchanged; the saved
title survives reload.
- Full recursive local checks were not repeated because Runner
compilation exhausted local disk during another repair. Hosted checks
must pass before merge. No new staging deployment is claimed.

- Latest review follow-up: a cached CaseDetail now survives a failed
HTTP 429 refresh. Its page regression fails before the fix and passes
after it. Eighty focused foundation tests, UI TypeScript, build and
guards pass after that change.
- Earlier CI evidence is retained: several foundation jobs received a
runner shutdown signal together. The write-layer head also failed an
unchanged Runner descriptor close test with `provider_transport_failed`.
The same Runner source passed that suite in the foundation run. New CI
runs cover the updated heads; no check or assertion was weakened.

## Risks

- Shared retry defaults change the time before transient read errors
appear. Permanent errors still fail promptly.
- ApiError.message now contains readable copy. Callers that compare raw
codes must use ApiError.code.
- Cache success can come from another service or local data. It must not
confirm Paperclip recovery.
- Durable writes are reviewed separately in #17960. This PR does not
change database or mutation contracts.

## Model Used

Anthropic Claude Opus 5.5 (`claude-opus-5-5`) produced the original work
with tool use. OpenAI Codex, GPT-6 family, assisted with restoration,
integration, tests and review fixes. The Codex session does not expose
its exact serving model ID or 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: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Amy (Opus) <claude@users.noreply.github.com>
2026-10-27 21:22:07 -07:00
SudheerandClaude Opus 5.5 70c8646337 fix(ui): drop top margin and border on first contextual sidebar section (#17412)
The first section in the contextual sidebar rendered a leading top
margin and divider with nothing above it. Use first: variants so only
sections that follow another section get the spacing and border.

<!-- Write all pull request text in Simplified Technical English
(ASD-STE100): short sentences, one instruction per sentence, simple
approved vocabulary, and the active voice. -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The board UI has contextual sidebars, such as Skills, Apps, and
Agent
> - These sidebars share one set of style constants in
`contextual-sidebar-styles.ts`
> - Each section in the sidebar has a top margin and a top border to
separate it from the section above
> - The first section has no section above it, but it still shows the
margin and the border
> - This pull request adds `first:` variants to the section style
> - The first section now sits flush at the top, and the other sections
keep their divider

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The section style in the contextual sidebar. It adds a top margin and a
top border to every section.

**Subsystem affected**

UI (`ui/src/components/contextual-sidebar-styles.ts`)

**Current behavior**

The first section in the sidebar shows a top margin and a divider line.
Nothing is above it, so the divider looks wrong and wastes space.

**Proposed behavior**

The first section has no top margin and no top border. Each later
section keeps its margin and divider.

**Reason and benefit**

The sidebar looks cleaner at the top. The change is small and uses only
existing design tokens.

**Breaking changes**

None.

## What Changed

- Added `first:mt-0 first:border-t-0` to
`contextualSidebarStyles.section` in
`ui/src/components/contextual-sidebar-styles.ts`.

Before: 
<img width="585" height="410" alt="Screenshot 2026-10-24 at 10 14 36 AM"
src="https://github.com/user-attachments/assets/12c35f5f-7993-4fdb-89b2-df3394859bf8"
/>
After:
<img width="560" height="377" alt="Screenshot 2026-10-24 at 10 14 24 AM"
src="https://github.com/user-attachments/assets/92e1f7ab-f4c0-48ac-832a-a3726770deac"
/>


## Verification

- Run `pnpm check:token-gates`. It passes.
- Open a page that uses a contextual sidebar, such as Skills or Apps.
- Check that the first section has no top gap and no divider.
- Check that the later sections still show their divider.

## Risks

- Low risk. The change affects only the spacing and the top border of
the first sectio
- Several sidebars share this style, so check each one: Apps, Skills,
Agent, and Chat detail.

> 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: Anthropic
- Model: Claude Opus 5.5 (`claude-opus-5-5`) made the commit. Claude
Sonnet 5.5 (`claude-sonnet-5-5`) helped review the change afterward.
- Capabilities: tool use and code execution in Claude Code (CLI).
- The one-line style change is human-authored.

## 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 puub.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
- [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: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 20:42:28 -07:00
Devin FoleyandPaperclip c9213d1be4 fix: send saved queued messages after Stop (#17959)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People can save follow-up messages while an agent runs.
> - Stop preserves those messages and stops the active execution.
> - The queue removed its delivery controls when that execution ended.
> - Native admission also refused an explicit resend of older queued
input.
> - This change adds Send for a stopped queue and records fresh board
intent.
> - The saved message can continue through normal cleanup and admission
checks.

## Linked Issues or Issue Description

**What happened?**

A person queued a message with a screenshot while an agent was starting.
Steering was not yet available. They stopped the run. The message
remained visible, but no control could send it. Native queue delivery
also rejected this transition.

**Expected behavior**

A stopped queue offers Send. The click preserves message IDs, content,
attachments and original authors. It starts at most one eligible
continuation. Stop remains effective until the person gives new
direction.

**Steps to reproduce**

1. Start a native task and queue a second message.
2. Stop the active run before it consumes that message.
3. Open the task after cleanup. Observe the saved message with no send
control.

Refs #16965 for the queue-control change and #15015 for stopped
conversation recovery. No open repair for this exact transition was
found.

## What Changed

- Show Send for a saved deferred queue with no active run.
- Accept the existing board queue action for a stopped native target.
Keep live native interruption restricted.
- Use the server-recorded click time to authorize older native messages.
Reject stale, malformed and wrong-actor intents.
- Reuse normal queue dispatch, revision checks, cleanup proofs and
execution admission, including a failed native predecessor after a
verified Send.
- Ignore a fully committed, successful recovered export when admitting a
fresh message, while retaining the wait for results still committing.
- Honor an applied `/new` conversation boundary while retaining native
execution holds until the existing stop and cleanup checks verify them.
Workspace holds also survive reset. Check the newest failed or cancelled
native execution even when older recovery actions exist.
- Keep native automatic delivery separate from the explicit Send action.
Update execution and access documentation.

## Verification

- Meaningful regressions failed before the fixes: stopped queues lacked
Send, native admission refused fresh intent, cleanup and dispatch
receipts were missing, deferred rows disappeared, live plan Interrupt
rejected its own receipt, and Agent Chat `/new` inherited an old
non-workspace execution hold.
- Six assembled-wakeup cases fail before the reset cleanup fix. All 11
reset/history cases pass after it: live processes, missing identity,
quarantined cleanup, remote leases and live controllers remain held;
verified cleanup proceeds and retires the hold. Two more cases fail
before the fallback fix and pass after it: Send verifies a stopped or
live native predecessor despite a later reset receipt and no recovery
record.
- **525 server tests pass** across seven queue admission, route,
dispatch, envelope, provenance, blocker and conversation files. **343
queue/thread UI tests** also pass. Server/UI TypeScript, token and map
guards pass. The final scoped server typecheck also builds native Runner
successfully.
- The latest regressions prove that completed recovered exports permit
fresh input, and clearing conversation history still requires old native
stop and cleanup verification; an unsafe workspace still blocks after
`/new`; failed native Send reaches actual continuation dispatch with the
original queued comment. A result still being committed remains
deferred. History plus a newer Stop cannot hide a missing
process/controller/lease receipt.
- The real Chromium Stop/Send journey passes on current head
`75fa5e7222c59f43ff7ac326e81093bc9da28330`: queue a follow-up, Stop,
reload, explicitly Send, then verify exactly one useful response and no
live run. Earlier browser journeys cover legacy Interrupt, interruption
during a write and Stop followed by a new direction. These use an
isolated app/database and controlled ACP fixture, not an external AI
account or a staging deployment.
- Negative cases retain actor, company, issue, assignee, queue and
cancellation-receipt bindings; cleanup/process/workspace/controller
holds; approvals; pause and budget gates. Typed responses keep their
original resolver and immutable result.
- Full local recursive typecheck stopped in unchanged Rust Runner
compilation with ENOSPC, so the chained full tests/build did not run.
All hosted CI gates pass on final commit
`75fa5e7222c59f43ff7ac326e81093bc9da28330`, including typecheck, tests,
build and E2E. Apex review on that commit is 5/5, with no unresolved
findings. Earlier unrelated CI failures involved PostgreSQL
fixture-cleanup deadlock and an unchanged decision-expiry deadline
assertion; the latter's 20 cases pass locally without source changes. No
assertions or limits were weakened. Local resource cleanup was limited
to this task's verified completed test processes and rebuildable npm
caches.

## Risks

- Send can authorize a new turn for a saved message after Stop. A Send
click must be newer than the stopped execution; a live plan Interrupt is
bound to the cancellation receipt produced by that same click. It does
not imply that cleanup finished or that an external action is safe to
replay.
- The existing endpoint and intent format are reused. No schema or
credential change is required. Live native steering and legacy
interruption keep their existing paths.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository inspection, tool
use and code execution. The session does not expose the exact serving
model ID or 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-10-27 20:34:14 -07:00
DottaandPaperclip 6cc765bd81 feat(live): deliver recoverable transcripts to interested views (#17456)
## Thinking Path

> - Paperclip should show live agent output without repeating
presentation work for every view.
> - Execution, acknowledgements and durable checkpoints must remain
independent of browser interest.
> - The server already owns authorization and redaction at delivery.
> - A shared browser connection can declare which visible runs need full
transcripts.
> - Catch-up must handle subscription races, disconnects, terminal
output and slow consumers.
> - This PR delivers the backend and UI contract together without a
database migration.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Visible transcript consumers receive recoverable output through one
shared browser connection.

**Current behavior**

Independent views can create duplicate connections, presentation work
and recurring history reads. A subscription race or filtered native
history can lose the saved tail.

**Proposed behavior**

Negotiate run interests, subscribe before catch-up and retain
independent canonical recovery cursors. Keep lightweight lifecycle and
attention events available without full transcript delivery.

PR 4 of #17097 → #17439 → #17455 → #17456. The runtime feature is
independent of hot-upgrade recovery; the stack order is for review
convenience.

## What Changed

- Add additive WebSocket capability negotiation, replacement interests,
revision acknowledgement and resynchronization notices.
- Reference-count visible consumer interests on one company-scoped
browser connection. Preserve older-client/server behavior.
- Reuse canonical structural/current-user/registered-secret redaction
for plugin run notifications through the same bounded delivery queue.
Keep producer and uninterested streams free of recipient lookups.
- Refresh application queries after the matching recovery
acknowledgement, including one follow-up after an older in-flight read.
Ordinary interest acknowledgements add no refresh.
- Keep authorization and redaction at delivery. Browser interest cannot
change harness execution, PRP ACKs, checkpoints, accounting or canonical
logs.
- Deduplicate by sequence and log identity. Catch up terminal output and
saved tails without recurring reads during healthy negotiated streaming.
- Bound delivery to 1,000 items and 1 MiB. Overflow requires
resynchronization; persistent congestion closes the connection.
- Preserve compact-history expansion from current master across
paginated catch-up. Snapshot the original read window before React can
defer its update.

## Verification

On current source `f6710f0b3c`, Linux [job
122604880503](https://github.com/paperclipai/paperclip/actions/runs/40624101891/job/122604880503)
executes all five run-read permission cases successfully (2.574
seconds), including grant and revocation on the same connection. Its
shard passes all 2,430 cases.

Current [server-shard job
122604880416](https://github.com/paperclipai/paperclip/actions/runs/40624101891/job/122604880416)
has 1,513 passes, one failure and three skips: an unchanged nested-clone
expiration/restore test exceeds its 15-second deadline. The preceding
`5efc6c48bf` source has identical non-document bytes; [its corresponding
job
122601359272](https://github.com/paperclipai/paperclip/actions/runs/40623017917/job/122601359272)
passes all 21 nested-clone cases, including that case in 9.505 seconds.
The exact timing cause is unproven. The single diagnostic [retry job
122609332597](https://github.com/paperclipai/paperclip/actions/runs/40624101891/job/122609332597)
passes all 21 nested-clone cases (61.316 seconds), including the
formerly timed-out case in 7.003 seconds, and all 1,514 shard cases
(three skips). The failure remains recorded; no timeout or assertion was
changed.

After the server squash merge and qualification retarget, all 50 focused
server cases and all 91 focused UI cases pass again, with both
typechecks and token gates. Runner vendor preparation rebuilds current
master inputs before those tests. This source needs fresh CI and
reviews; prior CI and browser receipts do not qualify it by inference.

Current candidate `f6710f0b3c` now targets master `6987c2f20b`, after
merged #17097, #17439 and #17455. Its diff contains only transcript
delivery and its documentation. It adds no database migration.
Retargeting changes only the evidence document; all production and test
code is byte-identical to `5efc6c48bf`.

On the eighth integration, all 50 focused server delivery cases and all
91 focused UI cases pass, with both typechecks and token gates. The
following 35-case receipt belongs to the earlier delivery correction.
Four low-queue authorization/decoration stall variants and the
late-rejection case fail before correction. They now verify the
five-second read deadline, old and negotiated clients, revisions that
cannot reset the deadline, unaffected sibling connections, rejected late
results, and timer cleanup. The first combined toast run has four
loopback EPERM failures and 31 passes; its permitted repeat passes all
35. Earlier 28-case evidence excluded the toast file.

The permission correction requires the current HTTP company-scope
transcript permission, plus task access, for both native events and
legacy logs. Prior Linux source `49a8783e9b`, job 122549913643, executes
all five run-read cases, including grant/revocation on the same
connection, successfully. That source placed this file in server shard
11; later shard assignments can differ and must be checked against their
actual inventories. The older `405bedd189` receipt retains a separate
scheduled-retry teardown race and inherited fixture collision; neither
is waived. The new head must pass again in Linux CI.

The seven extracted stream-recovery tests preserve their assertions. All
39 related legacy/native cases, UI typecheck and token gates pass after
restoring the initially missed fixture helper. Earlier full workspace
build/typecheck and Chrome journeys at `445a76563c` cover two views,
company switches, reconnect, terminal catch-up, reload and zero
recurring healthy transcript reads. Those browser receipts are
historical source evidence and do not qualify this new head by
inference. The [qualification
record](https://github.com/paperclipai/paperclip/blob/f6710f0b3c84c6fdb2021df67206261b446dfc97/doc/plans/2026-10-22-hot-upgrade-qualification.md)
retains exact earlier UI/history, source-boundary and cleanup failures
with their fixes and limits.

The workload-cost test preserves bounds and authorization callback
counts for zero interests, one viewer, multiple browsers and a slow
viewer. Its socket congestion is simulated. It measures neither SQL nor
network costs. Current permission checks and the final hosted
active-agent/viewer matrix remain unmeasured; no production savings are
claimed.

Fresh exact-head CI, legacy status, completed Greptile 5/5, resolved
feedback and ordinary merge eligibility remain required.

The earlier recipient corrections pass all 47
registry/plugin/delivery/WebSocket/toast cases and all 174 UI
provider/recovery/interest cases, both typechecks and token gates on
source `b202e59a25`. A real bus/host-service test registers a synthetic
run secret through the production registry and reproduces its raw
notification before the fix; native/legacy/final notifications now
redact it, disposal prevents late worker notification. A later P1 review
reproduces lost final notifications on settings-read and
secret-resolution failure. Both cases fail before correction. Any
delivery failure or subscription timeout now sends one content-free
stream error and removes the plugin subscription. It never changes the
agent execution or run status. Later events start no new redaction
reads. The final integrated six-file server lane passes all 50 cases,
with server typecheck and token gates. Existing browser delivery
behavior is unchanged. Storage and secret-provider seams are scripted.
Two real React Query/provider regressions first miss a run during
resync; both now refresh after the valid replacement ACK, including
pending-read and stale-scope cases. The prerequisite qualification batch
passes all 118 cases and E2E typecheck after master integration. Fresh
CI, security scan and reviews remain pending on this head.

The contribution-rule review correction removes 104 explanatory comments
introduced by this slice and keeps the ordering, deadline and
plugin-delivery explanations in the delivery document. Existing comments
and functional test/lint directives remain. All edited source files have
identical parsed non-comment tokens before and after the change. All 50
server delivery cases and all 91 cases in six affected UI suites pass,
along with token gates. The new head requires fresh CI, security and
review.

## Risks

A slow or disconnected viewer must resynchronize from authorized
canonical history. It may see a display gap until catch-up completes.
Company changes and revoked access must remove delivery interests. This
slice adds no database migration and cannot change execution or recovery
authority. Full transcript delivery evaluates current company-scope
permission per delivery. Active plugin recipients also perform canonical
redaction reads; viewer-load database costs on this final source remain
unmeasured.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools and code
execution. The runtime does not expose a more specific model ID or
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
- [ ] 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-10-27 22:23:30 -05:00
DottaandPaperclip f52da40f08 fix: resume queued turns after maintenance (#17967)
Keep an accepted turn's starting input in task history, show its admission wait, and resume existing queued runs promptly when maintenance ends or expires.

Verified with behavioral red/green regressions, real PostgreSQL and process execution, browser/native Runner acceptance with a deterministic provider, workspace typecheck, production build, and current-head CI/review.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-27 22:20:03 -05:00
DottaandPaperclip 7a8df30953 fix(runner): admit Grok effort through native session metadata (#17942)
## Thinking Path

> - Paperclip lets people manage AI agents for work.
> - Paperclip Runner must preserve each agent's model and thinking
effort.
> - The Grok migration in #17922 passes explicit effort to native
Runner.
> - The pinned Grok 1.0.13 CLI reports native session metadata instead
of standard ACP config options.
> - The standard effort guard rejects that valid session before the
first prompt.
> - This pull request binds model and effort on Grok session open and
verifies the native reply.
> - Restored sessions keep the selected effort instead of reverting to
Grok's default.

## Linked Issues or Issue Description

Related: https://github.com/paperclipai/paperclip/pull/17922

**What happened?**
A migrated Grok 4.7 agent with High effort fails at native session.open
before it can run a tool. Grok 1.0.13 has no standard configOptions
response and rejects session/set_config_option. Its native session
metadata supports the requested model and effort. A cold load also
resets effort to High unless the request supplies it again. The upgrade
banner also calls Grok “Codex”.

**Expected behavior**
The native session must acknowledge the selected model and effort before
a prompt. A cold restore must preserve both values. The upgrade banner
must describe the selected harness accurately.

**Steps to reproduce**
1. Upgrade a Grok agent to Paperclip Runner with explicit High effort.
2. Assign a bounded shell task. The pre-fix native session fails during
admission.
3. For the restore case, create a Low native session, close the process,
and load it without effort metadata. The pinned CLI reports High.

**Paperclip version or commit**
Observed at f60ac29cf1 with Grok 1.0.13.

**Deployment mode**
Cloud, with the board operator interface.

## What Changed

- Project the bound model and effort into native Grok session/new,
session/load, and session/resume metadata before transport writes and
observation.
- Require a correlated native acknowledgement with the exact model,
effort, and session identity. Reject conflicting metadata, selection
drift, stale connections, and prompts before admission.
- Connect lazy restored handles through read-only native session
inspection. Keep the existing process ownership and launch snapshot
checks.
- Replace Grok's unsupported standard config setter. Keep the existing
Claude effort path.
- Add behavioral guard cases and a real ACPX client fixture for fresh
and cold Low/High sessions. The fixture resets effort on restore if
metadata is absent, as the pinned CLI does.
- Publish Copilot profile v69 because its source identity includes the
shared runtime adapter. Preserve published v66/v67/v68 bytes and the
reviewed Grok v67 candidate as history. Keep old profiles closed for
launch.
- Explain the native protocol in the Grok Runner guide and use
provider-independent upgrade banner text.

## Verification

- Three native create/load/resume cases failed before the repair. The
pre-fix guard rejected the native metadata reply.
- Seven affected Runner test files: 234 tests passed after the master
merge. These include native Grok admission, the real ACPX transport
fixture, runtime ownership, Claude effort, and profile history.
- The review follow-up extends the same Low/High fixture through a
complete first turn after cold restore. It checks the repeated native
load, original session id, actual response event, and completed turn.
All 127 tests in the three affected Grok/adapter files passed again;
Runner typecheck and source identity checks also passed.
- All 167 existing agent form tests passed. Token gates and diff checks
passed.
- Workspace typecheck passed. Final Runner typecheck and generated
profile checks passed.
- Production `pnpm build` passed, including after the master conflict
resolution. Runner typecheck, profile history checks, and the 234
affected tests passed on the merged source. All 55 Rust ACPX library
tests also passed on the merged source.
- Real pinned Grok 1.0.13 metadata probes reproduced the unsupported
standard setter and native create/load/resume behavior. No model prompt
was sent. An earlier actual ACPX runtime probe passed fresh and cold
Low/High metadata checks. A repeat with an explicitly isolated HOME
failed authentication before session creation, so it does not count as
final live acceptance. The deterministic transport fixture is green; a
deployed shell task remains required.
- `pnpm test:run` did not complete locally. Embedded Postgres failed
during bootstrap after five attempts. This is the same local fixture
limitation recorded for #17922. Fresh PR CI must pass before merge.
- After deployment, retry the original bounded shell task with the saved
Grok 4.7/High configuration. Verify actual tool output, a successful
run, and Done state after reload.

- Final commit `810d84fd19728e7d798989582f26b05f69166db2`: all CI gates
passed. Greptile and the formal Paperclip review both reached 5/5. No
unresolved review threads remain.

## Risks

- This depends on the pinned Grok 1.0.13 native metadata format. Missing
or conflicting replies stop admission instead of silently changing
effort.
- Cold restores must make one read-only native inspection call before
admission. The existing handshake timeout and process ownership checks
still apply.
- The shared adapter changes Copilot's source identity. The new current
profile includes the final source hashes; the prior profile remains
decodable but cannot launch.
- This does not change the Grok CLI version, account selection, search
policy, dependency patch, or lockfile.

## Model Used

OpenAI Codex, GPT-6. The exact serving model ID and context window are
not exposed in this session. The agent used reasoning, code editing,
shell tools, 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>
2026-10-27 17:53:58 -05:00
Nicky LeachandPaperclip 3f8149066c Fix connection controls for inherited hiring environments (#17944)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/106/changes/paperclip/106
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip lets people hire agents and select execution environments.
> - The name and adapter dialog saves an inactive draft before model
connection.
> - That draft can inherit its environment through a null
defaultEnvironmentId.
> - Managed-only and forced Kubernetes policy resolve that inheritance
to an environment ID.
> - The readiness gate compared the stored null with that ID and treated
the selection as unsaved.
> - This change accepts unchanged inheritance and keeps preparation and
save-failure gates.
> - People can select auth, open Advanced, and test a saved account
before finishing setup.

## Linked Issues or Issue Description

**What happened?**

The Connect a model screen disabled all auth controls for a draft from
the name and adapter dialog under managed-only or forced Kubernetes
policy. Reloading did not recover it. The draft had no explicit
environment, which is a valid inherited selection.

**Expected behavior**

Keep connection controls usable once the draft and environment are
ready. Test the saved agent against its resolved environment before
hiring finishes. Continue to block tests during preparation or an
unsaved environment change.

**Steps to reproduce**

1. Enable managed-only execution with a valid instance default, or force
Kubernetes.
2. Open New agent, enter a name, and choose Claude or Codex.
3. Reach Connect a model with the saved draft's defaultEnvironmentId
still null.
4. Try the saved subscription, API-key tile, or Advanced gateway.

This follows #17761. The roadmap and related PR search found no existing
fix for this readiness regression.

## What Changed

- Accept the inherited selection when neither the draft nor the user
specifies an environment.
- Retain the existing preparation, loading, selection-save, and
connection-test gates.
- Cover Claude and Codex under managed plugin, managed sandbox, and
forced Kubernetes policy.
- Extend preparation coverage to both explicit and inherited
environments.
- Add the inherited-draft journey to the feature map.

## Verification

- Hosted reproduction on Core e71a23c01 from a macOS browser: one owned
draft was created through the real name/adapter UI. Its persisted
environment was null. Auth controls were disabled before and after
reload. The instance required managed execution.
- Cleanup used the normal Terminate action. Readback confirmed
lifecycleState=terminated with no lifecycle error. The roster returned
to its original two active agents. No existing agent, task, account, or
instance setting was changed.
- Before the fix, four inherited-connection cases and the inherited
preparation case failed. The explicit-environment preparation control
passed.
- After the fix, 140 tests passed across NewAgent.test.tsx,
test-agent-setup.test.ts, and qualify-claude-setup.test.ts. Coverage
includes same-agent probes before Finish, preparation waits, account
preservation, failed-save retry, stale reads, and runner qualification.
- npm --prefix ui run typecheck passed, including Storybook catalog
generation and tsc -b. Direct UI TypeScript, token gates, map checks,
and git diff --check also passed.
- The pnpm entry point stalled while resolving its pinned version on
this host; both owned attempts were stopped. Running the same UI
typecheck script through npm passed. Full local workspace
typecheck/build were not repeated because Cargo is absent. The
exact-head CI run supplies the full workspace validation.
- Automated CI on f2a5a2df7 passed all checks. Standard review found
only the explanatory source comment, which contributor policy forbids.
The comment was removed in 8f43a6d80, and its thread was resolved. The
runtime expression and tests are unchanged. Fresh CI passes on
8f43a6d80: 55 successful checks and two intentional skips. The full
workflow includes build, typecheck, all test shards, Rust, and
end-to-end checks:
https://github.com/paperclipai/paperclip/actions/runs/40591187819.
Standard Greptile returned 5/5, then Apex returned 5/5 with zero new
comments on the same head:
https://github.com/paperclipai/paperclip/pull/17944#issuecomment-6454535506.
No review threads remain unresolved; the PR is conflict-free.
- The diff was reviewed for secrets, PII, and run artifacts. Evidence
stays outside git.
- No deployment, live post-fix provider test, or VM provisioning was
performed. Component tests simulate API responses; the hosted check
proves the original failure.

## Risks

This changes only how the wizard recognizes an inherited environment. It
does not change the environment resolver, lifecycle, approval policy, or
lease admission. The existing preparation and failed-save guards remain
active. No migration is required. Hosted acceptance of the fix requires
a later authorized deployment.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, tool use, browser
inspection, and code execution. The exact serving model ID and context
window size are 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 described the issue in-PR following the bug report fields
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
ticket id
- [x] I have run the targeted tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation
- [x] I have considered and documented the risks
- [x] All Paperclip CI gates are green
- [x] Standard Greptile and Apex are 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-10-27 15:24:29 -07:00
DottaandPaperclip f60ac29cf1 fix(runner): migrate Grok Build with native reasoning effort (#17922)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Harness selection maps supported agents to Paperclip Runner.
> - The native Runner already supports Grok Build, but its migration
mapping excludes Grok.
> - Grok agents also have a thinking-effort setting that the native
execution contract does not carry.
> - This pull request adds the migration path and preserves explicit
Grok effort through startup and resume.
> - Operators can upgrade an existing Grok agent without silently losing
its model, account, or effort.

## Linked Issues or Issue Description

**What happened?**

Existing Grok Build agents have no Runner selector or upgrade action.
Adding only the mapping would route conversion through the Codex
fallback and lose Grok execution semantics. Native execution also
ignores the legacy reasoning-effort field.

**Expected behavior**

A qualified Grok agent can explicitly upgrade. The saved model, account,
instructions, history, and supported effort remain intact. Unsupported
legacy settings fail before saving. The provider must acknowledge the
selected effort before inference.

**Steps to reproduce**

1. Open the runtime page of an existing Grok Build agent on a qualified
Linux x64 or macOS ARM64 computer.
2. Observe that the Runner selector and upgrade action are absent.
3. Compare the native execution input with the saved legacy
reasoning-effort setting.

Related work: #13882 introduced native Grok Build. #15422 covers the
earlier default-runner work. This change extends the current shared
selection contract.

## What Changed

- Add the Grok harness mapping, qualified platform limits, upgrade
action, and company-scoped computer qualification.
- Translate Grok settings to ACPX without changing the selected account
or explicit model. Resolve the legacy default model to the native
default. Preserve the effective legacy search policy. Reject
incompatible command, argument, permission, and turn-limit settings.
- Add native execution input v10 for explicit Grok effort and search
policy. Preserve historical schemas. Enforce disabled search through
Grok requirements and bind it across startup and recovery.
- Apply and verify ACP `reasoning_effort` before prompting. Bind the
value to provider descriptors, checkpoints, runtime identity, and resume
checks.
- Use the Grok catalog and effort choices in the task composer. Apply
task model and effort overrides while retaining the agent account and
search policy. Update runtime controls, portability/default handling,
documentation, and capability maps.
- Advance Pi and Copilot source attestations for changed shared
transport and recovery code. Keep historical identities intact and
update all Rust integration fixtures.

## Verification

- Migration and review regressions were reproduced before the fixes.
Coverage includes the Grok mapping, default model, explicit effort,
implicit search policy, task overrides, and incompatible legacy
settings. The broad migration, route, immutable-input, and composer
check passed 478 tests. The final catalog and task-input check passed
135 tests.
- Runner startup, recovery, search policy, and profile checks passed 361
tests, with one platform skip. The final source-identity,
search-admission, and transport event-pump check passed 89 tests.
- All 757 Rust workspace tests passed for the broad implementation.
After the final source attestation update, all 55 ACPX profile/session
tests passed.
- `pnpm -r typecheck` and `pnpm build` passed for the implementation.
Server and Runner typecheck passed after the final production change.
Server `tsc --noEmit` passed after the final test-fixture change. Docker
context integrity, token gates, maps, generated protocol data, and
replay goldens passed.
- The v10 startup fixture initially used an ambient local Grok login and
failed on CI. An explicitly empty credential home reproduced all four
failures. The fixture now supplies a synthetic key and a private empty
home. A separate case checks that missing credentials fail closed. All
seven selected Grok v10 and Claude v9 startup cases pass without host
credentials.
- The full local suite could not complete because embedded PostgreSQL
failed before database-backed fixture setup. The broad executor-suite
attempt hit the same limit and was stopped. Neither attempt is counted
as passing. Current-head CI must verify those paths before merge.
- Earlier CI found missing Rust input fields, stale source attestations
and exact fixture pins, a missing Docker context entry, and an outdated
import expectation. Those failures were fixed and checked locally. The
CI logs retain the original failures.
- Different earlier CI runs also failed unchanged cleanup pagination,
device-login timeout, and chat lost-response recovery cases. Later
attempts passed the cleanup and login cases without changes to those
implementations. Their causes remain unproven. The original evidence
remains in [the first
run](https://github.com/paperclipai/paperclip/actions/runs/40563402840),
[the login
run](https://github.com/paperclipai/paperclip/actions/runs/40571128328),
and [the chat
run](https://github.com/paperclipai/paperclip/actions/runs/40573072163).
A passing retry does not establish a root-cause fix.
- Both reviews rate current head
`16fba9b4cdf12bc7945e6628912e79da42959f35` 5/5. All current-head CI
gates pass in [run
40576580699](https://github.com/paperclipai/paperclip/actions/runs/40576580699).
All 60 check runs completed cleanly, including the four intentional
skips and the neutral 5/5 Paperclip review. The legacy security status
is successful. No review threads remain unresolved.
- Staging migration and a real shell task are pending deployment. This
PR does not claim full Grok provider qualification. Reviewers can verify
the operator path by upgrading a qualified Grok agent, checking its
saved model and effort, and running a shell task through native
execution.

## Risks

- Explicit effort and search policy require the matching Runner and
sidecar build. Older immutable execution inputs keep their existing
schemas.
- Providers that omit or reject the selected effort fail before a
prompt. Unsupported effort does not fall back silently.
- Existing agents retain their saved runner until an explicit change.
New Grok agents use native execution only on qualified platforms.
- Grok token and cost reporting remain unverified, as before.

## Model Used

OpenAI Codex, GPT-6 family. The exact serving model ID and
context-window capacity are not exposed in this session. Used reasoning,
source editing, shell execution, and browser inspection.

## 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 and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run tests locally and the focused suites pass; the full
local suite has the environment limitation recorded 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-10-27 15:28:42 -05:00
DottaandPaperclip eda2a03bfe fix(ui): keep responder avatars visible through comment acknowledgement (#17885)
## Thinking Path

> - Paperclip gives people a shared place to manage and talk with
agents.
> - Task chat and Agent Chat show the responding agent as soon as a
person sends a message.
> - Comment storage and run discovery finish in separate requests.
> - Both chat surfaces removed the startup identity when comment storage
finished.
> - A slow run lookup therefore made the avatar disappear and appear
again.
> - This pull request keeps startup feedback until the run appears or a
newer execution outcome ends admission.
> - The agent stays visible while the response starts.

## Linked Issues or Issue Description

**What happened?**

The responding agent's avatar appeared after Send, disappeared when the
human comment was saved, and appeared again when the run loaded.
Existing conversations made the flash easy to see.

**Expected behavior**

Keep the agent identity visible across comment storage, queued
admission, and runtime startup. Clear temporary startup feedback on
failure, backoff, task completion, or a completed run.

**Steps to reproduce**

1. Open an existing agent conversation.
2. Send another message.
3. Let the comment POST finish before the task and live-run reads
finish.
4. Observe the responder identity disappear during that gap.

**Paperclip version**

Source baseline: `db70c5acd92f50fa37fb4f0dea3da0e7685089a2`.

**Deployment mode**

Local trusted mode with an isolated database. The browser test used the
real app, APIs, and native runner with a deterministic Codex provider.
It held read responses to expose the acknowledgement gap. It did not
call a live model provider.

Related: #4485 addressed human-comment alignment during session loading.
This change addresses agent-response startup.

## What Changed

- Share submission-to-run state between the task and classic chat
surfaces.
- Keep the identity mounted after comment acknowledgement. End startup
on a visible run or a newer admission outcome.
- Keep old execution projections and older loaded history from
acknowledging a new response. Retain slow-start refresh and
uncertain-save handling.
- Extend the startup tests through the missing acknowledgement interval
on desktop and mobile. Add existing-thread, paused-agent,
fast-completion, and clock-skew cases for both surfaces.
- Match completed runs to the saved comment and its server time. Use the
shared status rules and server-reported reporting-chain health for known
agent blockers and confirmed task pauses. Keep submitted feedback
visible through pause-state read errors. No browser/server clock
comparison is used.
- Clarify the identity continuity rule in `DESIGN.md`.

## Verification

- Red: the actual Send tests fail against the original components in
eight cases.
- Green: both chat suites pass, 420 tests total. Extra red/green cases
cover paused or ineligible agents, missing/terminated managers,
reporting cycles, browser clocks five minutes ahead or behind, and
pause-state read failures.
- Chromium on an existing conversation: the original avatar appeared at
58 ms and disappeared at 326 ms. On final commit `f9602e3e48`, the
avatar appeared at 68 ms and stayed visible through the same held-read
interval. Frame sampling found no disappearance after it appeared.
- Native fixture turns succeeded and stored their final provider
replies. Repeated the existing-thread turn and normal navigation/reload
on final commit `f9602e3e48`: both runs succeeded, both replies were
stored, and the conversation returned to its waiting state.
- `pnpm -r typecheck`, `pnpm build`, `pnpm check:token-gates`, and the
final UI typecheck passed.
- `pnpm test:run` was attempted. The host exhausted PostgreSQL
semaphores. The supported external test database let some suites run,
but other suites still attempted embedded clusters and failed or skipped
setup. The run was stopped after repeated setup failures.
- The broader UI run passed 9,251 tests and failed one existing
connection-authentication test. The same test fails on an untouched copy
of the base commit. This PR does not change that component or test.
Full-suite CI remains the complete-suite check.

- Final-head CI attempt 1 lost seven workers to shutdown or lost
communication and hit one timing assertion in an unchanged scheduler
test. Retried only failed jobs once on the same commit; the scheduler
test and interrupted jobs recovered. All retried jobs and both aggregate
gates passed. Final CI is green on
`f9602e3e48c75580935465eb0b4713fc7a4bcc56`.

## Risks

Low scope: this changes client startup feedback only. There are no API,
data, auth, or token changes. If run discovery is slow, the existing
slow-start message remains visible until current execution evidence
arrives. Completed runs are matched to the submitted comment by
consumption identity or server timestamps, so loading old history and
browser clock differences cannot end its feedback incorrectly.

## Model Used

OpenAI Codex, GPT-6 family. This session does not expose the exact
deployment ID or context-window limit. It used reasoning, code editing,
command execution, and Chromium automation.

## 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 (420 relevant chat tests;
the full-suite setup limit is recorded 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-10-27 10:25:56 -05:00
DottaandPaperclip e71a23c01c fix(ui): animate late task sidebar loading (#17880)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/61/changes/paperclip/61
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task pages load the conversation and related sidebar data
separately.
> - The sidebar host did not exist until its content arrived.
> - Its first appearance skipped the width transition and moved the
thread at once.
> - This pull request keeps an empty host at zero width until content is
available.
> - The sidebar and thread now move together, with immediate changes for
reduced motion.

## Linked Issues or Issue Description

**What happened?**
A cold task load showed a wide skeleton. The right sidebar then appeared
at full width and shifted the thread at once.

**Expected behavior**
The sidebar should enter smoothly. The task thread should move with it.
Unknown or hidden sidebars should take no space.

**Steps to reproduce**
1. Open a populated task in a fresh browser context.
2. Delay the task metadata response.
3. Watch the skeleton and thread as the right sidebar becomes available.

Related work: [task cold-open
reads](https://github.com/paperclipai/paperclip/pull/17756).

## What Changed

- Keep the shared sidebar host mounted at zero width while its content
is unknown. Make hidden hosts inert and hide them from assistive
technology.
- Use shared motion tokens for width and opacity. Disable motion for
reduced-motion preferences and keep pointer resizing immediate.
- Clamp late content to the current viewport without overwriting the
saved width. Keep the motion catalog aligned with the reveal tokens.
- Clip the panel body during reveal. Keep the resize handle inside the
viewport during the first frame.
- Clear empty panes immediately when content is removed. Release
maximized geometry on that render. Remove the unused width/opacity
token.
- Add four replayable Storybook scenarios using the production skeleton
and panel components. Add browser checks for both arrival orders, absent
and hidden sidebars, reduced motion, resizing, and maximize/restore.
- Document the shared sidebar loading behavior in DESIGN.md.
- Load the comment-route test modules in suite setup. This prevents a
slow module load from timing out the first test and affecting the next
test. This test-only change fixes a reproducible CI failure; route
behavior and assertions stay the same.

## Verification

- 201 focused task-detail, properties-panel, and motion-catalog tests
passed. New host-continuity regressions failed against the original
component in both task interfaces.
- Eight focused Storybook browser checks passed without retries after
the review fix. They measure intermediate widths and matching thread
widths, check overflow, exercise resize and maximize controls, and
confirm immediate removal of docked and maximized content.
- The first removal checks sampled before replay cleanup committed.
Sampling now starts after the host becomes inert. All three removal
checks fail against the prior commit. Restoring the source during that
comparison left a stale Storybook module in the preview. After a preview
restart, all eight cases passed without retries on the fixed source.
- Verified a real populated local task in a fresh browser context with
delayed real API responses. Recorded a screencast for visual review. The
captured reveal had 20 intermediate widths, no horizontal overflow, and
no browser errors.
- Repository typecheck, full build, Storybook build, token gates, map
checks, and 30 catalog/map tests passed. Full typecheck, full build,
focused UI tests, and UI typecheck were repeated after the upstream
rebase.
- Full `pnpm test:run` was attempted and stopped after repeated embedded
PostgreSQL initialization failures. The host has exhausted its semaphore
pool. The local app test used a disposable container database instead.
- Replay `tasks-sidebar-loading--sidebar-during-skeleton` in Storybook.
Run the focused browser suite with `STORYBOOK_TEST_BASE_URL` set to that
Storybook server.

- CI serialized shard 6/9 failed when the first comment-route test hit
its 15-second timeout. Its work then affected the next test's mock
count. Both failures reproduced locally on Node 24. After moving module
loading to suite setup, all 103 tests and server typecheck passed with
the same test timeout. A first local attempt could not bind the
Supertest listener inside the sandbox; it was repeated with local
network access.

## Risks

- The shared host also serves other properties panels. Hidden
preferences, default widths, pointer resizing, maximize/restore, and
both task interfaces have focused coverage.
- Width animation can reflow text while the panel enters. Reduced motion
removes the transition. Navigation removes empty panes immediately.
- Visual approval is complete. The full CI suite must pass before merge.
No schema or API contracts change.

## Model Used

- OpenAI GPT-6 through Codex, with reasoning, code execution, and
browser tools. The exact deployed 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
- [ ] 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-10-27 10:10:45 -05:00
DottaandPaperclip bd382eee53 fix(recovery): explain retained source verification failures (#17773)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Workspace recovery must prove the identity of retained work before
it uses an allocation.
> - The verifier rejects several different contracts with the same
`source_binding_invalid` code.
> - A saved Retry can therefore stop before file preservation without
enough evidence for a safe repair.
> - Operators need a bounded observation of the selected source without
another attempt or weaker guards.
> - This pull request records closed failure reasons and adds an
explicit read-only inspection on the run page.
> - The benefit is a precise next diagnostic step while the saved work,
intent, and ownership fences remain intact.

## Linked Issues or Issue Description

Refs: #17741, #17053. This is a diagnostic follow-up. It does not change
recovery admission or the retained-source acceptance policy.

**What happened?**

A retained-source recovery exhausted in `verify_execution` with only
`source_binding_invalid`. Run and task diagnostics could not distinguish
an invalid reference, lease policy, source binding, or reopened
allocation. The normal recovery-actions read can also revalidate
recovery state, so it was not a safe substitute for a current read-only
inspection.

**Expected behavior**

Record an allowlisted reason at the rejected guard. Allow a reader to
inspect one exact task/run/action without changing its attempts, saved
input, receipts, or ownership. Clearly separate the recorded failure
from current identity observations.

**Steps to reproduce**

1. Prepare a terminal native run with a retained-source action and a
lease policy of `reuse_by_environment`.
2. Attempt source verification. The guard must still reject that policy.
3. Open the failed run and choose Inspect recovery, then Inspect current
source. The diagnostic should name `lease_policy_not_retained` and the
allowlisted policy.

## What Changed

- Split existing source-binding guards into closed reason codes. Keep
each acceptance predicate and physical recovery action unchanged.
- Persist validated, path-free reason/policy detail with future system
recovery failures. Keep historical generic records compatible.
- Add an explicit query on the existing task recovery-actions GET. Exact
company/task/run/action selection bypasses read revalidation. Run
selection lists at most 20 actions; inspection stops before per-lease
lookup when a record has more than eight sources.
- Add a manual inspection control on native export-failure run pages.
Keep resolved retained actions inspectable. Show recorded failure and
current recorded-source identity separately.
- Update execution semantics and feature/access recipes. The shared type
is the normalized server/UI contract; it contains no provider payload or
secret.

## Verification

- RED: the prior verifier failed both reason assertions for rejected
warm policy and foreign-run lease binding. GREEN: the final focused
source/HTTP, system-state, and UI suites pass 23 tests. The UI follow-up
passes 8 tests after the review fixes.
- HTTP tests prove exact selection, cross-company denial,
resolved-action access, reused-allocation rejection, redaction, and
unchanged actions, runs, leases, tasks, wakeup receipts, workspace
operations, and activity. A nine-source case proves bounded inspection
while the existing worker verifier still accepts all nine valid sources.
- Review follow-up: show allowlisted saved detail beside a changed
current observation, preserve all listed actions, and follow
exact-action selection in verified/limited/error tests. The prior
component fails the saved/current drift regression in an in-memory RED
control; the current component passes. UI typecheck/build pass again.
- `pnpm -r typecheck` and `pnpm build` pass. Token gates, maps, module
boundaries, and `git diff --check` pass.
- Rebased onto master `46de15ff4b` without conflicts. Range-diff proves
both diagnostic commits are unchanged. On new head
`a7e2bc87fcea75e76b6b736304d1287257f71174`, all 23 focused tests, full
typecheck/build, token gates, maps, and module checks pass again. Both
fresh reviews are 5/5 with zero unresolved threads. Final exact-head
GitHub status is CLEAN: 55 success, 2 skipped, 1 neutral, no pending
checks or failures. The [ci / verify
aggregate](https://github.com/paperclipai/paperclip/actions/runs/40387002325/job/121802415824)
passed in eight seconds. All test/build/typecheck/E2E lanes passed.
- Existing full workspace recovery suite: 56/56 pass (103.5 seconds)
before the byte-equivalent rebase. `pnpm test:run` hit repeated embedded
PostgreSQL initialization failure before database-suite assertions and
was stopped. No full local suite pass is claimed. The owned external
`_test` database provided the focused HTTP/source verification. The
prior browser attempt also stalled at Network.enable before its click;
that attempt did not establish browser acceptance.
- Current-head local browser acceptance passes through the actual run
page: Inspect recovery lists the exact action, Inspect current source
shows recorded generic failure separately from the current rejected
policy, and reload resets inspection to the explicit control. Explicit
selection works again after reload. The app used isolated data, an empty
inherited environment, a paused synthetic agent, and no provider
credentials. Final state remains failed/exhausted with zero attempts,
zero wakeup receipts, zero workspace operations, and unchanged original
generic failure. The local app and temporary tab were stopped. This
proves the diagnostic journey, not the deployed source's actual lease
policy or its recovery.
- Final merge verification at
`a7e2bc87fcea75e76b6b736304d1287257f71174`: GitHub reports CLEAN and
mergeable. Both repository-required checks, `ci / verify` and `ci /
e2e`, pass, as does the exact-head Greptile check (5/5, zero unresolved
threads). The separate [Entire
trail](https://entire.com/gh/paperclipai/paperclip/trails/7) has no
recorded reviewer approval; no such approval is claimed. It is not a
configured GitHub merge gate.
- Initial local setup failures were distinct from product assertions:
localhost sandbox EPERM required scoped local access; a browser harness
import path was corrected. A test UUID type inference error and
historical native-export UI selection gap were corrected before the
green run. The live task remains blocked; this diagnostic does not claim
it recovered.

## Risks

- This change improves evidence. It does not prove provider termination,
local descriptor integrity, or successful file preservation, and it does
not repair the original source.
- Current inspection spans multiple database reads. It is an
observation, not a historical cause or execution authority. It performs
no provider/filesystem calls and starts no retry or executor.
- The optional persisted detail is backward compatible. Unknown values
and extra fields are excluded. Oversized source lists remain uninspected
through this explicit diagnostic path; physical recovery rules do not
change.

## Model Used

OpenAI Codex based on GPT-6, with code execution and browser tools. The
exact serving model ID and context window were 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>
2026-10-27 08:21:28 -05:00
TonioandClaude Fable 5.1 3e7c3ee9a9 fix(ui): fall back to the icon face when an Artifacts V1 preview fails to load (#17260)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents produce artifacts: documents, files, pictures, video and
links. The Artifacts V1 presentation (`enableArtifactsV1`, #17228) shows
them as prints, sheets and rows on the Artifacts page, in the panel's
Artifacts tab and in the task thread
> - A picture is printed from its attachment's content path. When that
content cannot be loaded (on staging, image work products whose
attachment returns 404), the browser draws its broken-picture glyph
inside the bordered print and inside the 40px row thumbnail
> - The presentation already has a face for a file with nothing to show:
the icon sheet (the faint glyph and the type label) and the row's
document icon. A picture that cannot be loaded should take that face,
not a browser glyph
> - This pull request listens for the element's own `error` event in the
V1 primitives and falls back to the icon face on all three surfaces: the
stack front and the single tile on the Artifacts page, and the panel and
thread rows
> - The benefit is that a missing or unreadable file reads as a file of
its type everywhere, with no fetch to find out, and nothing changes for
a picture that loads

## Linked Issues or Issue Description

No public issue exists. This section follows the bug report template.

**What happened?**

With Artifacts V1 on, an image work product whose attachment content
returns 404 ("Attachment not found") shows the browser's broken-image
glyph inside the bordered print on the Artifacts page (the stack front
and the single tile) and inside the 40px thumbnail in the panel and
thread rows.

**What did you expect to happen?**

The artifact shows the icon face a file without a preview gets: the icon
sheet with the faint glyph and the type label on the Artifacts page, and
the document icon with the type label in the rows.

**Steps to reproduce**

1. Turn on Settings > Experimental > Artifacts V1.
2. Register an image work product whose attachment content returns 404,
or delete the attachment behind one.
3. Open the Artifacts page, the task's Artifacts tab and the task
thread.

**Relevant subsystem**

The web UI (`ui/src/components/artifacts/v1/`).

## What Changed

- `ArtifactPrint`: a new `usePreviewFailure(source)` hook beside
`useImageAspect`, and an `onMediaError` prop wired to the `error` event
of the print's `<img>` and `<video>`. The hook remembers the source that
failed rather than a flag, so a front that moves on to another picture
(a stack's newest artifact) gets a fresh chance.
- `ArtifactFront`: owns the failure state for its subject and renders
the icon sheet (`IconSheet`, the `icon` treatment) once the print
reports an error; it passes the error on through its own `onMediaError`.
- `ArtifactStack`: on an error it stops fitting a print and stands the
icon sheet where a sheet stands in the media stack (the portrait anchor,
where audio stands), keeping the media backing.
- `ArtifactRow`: the thumbnail listens for `error` on its `<img>` /
`<video>` and gives way to `ArtifactRowIcon`, the document icon with the
type label.
- Until the picture loads the print stays the 4:3 placeholder, and a
picture that loads behaves as before. No fetch is made to detect a
failure.
- A failed video takes the plain icon sheet with no play disc, since the
stream it would promise cannot play; a video with no URL at all keeps
the existing media-fallback treatment with the disc.
- `index.ts` exports `usePreviewFailure`; the plan doc
`doc/plans/2026-10-22-artifacts-mvp-v1.md` records the fallback.
- Tests: `ArtifactTile.test.tsx` covers the single tile (4:3
placeholder, then the icon sheet after `error`), the picture stack (the
sheet stands where the audio stack's sheet stands, on the media backing)
and a video whose stream fails (icon sheet, no play disc).
`ArtifactRow.test.tsx` covers the thumbnail and the video thumbnail
giving way to the document icon, and a new source getting its own
chance.

## Verification

- `cd ui && npx vitest run src/components/artifacts/v1` — 6 files, 33
tests pass (5 new).
- `pnpm run check:token-gates` — exits 0: all four token gates clean,
palette tokens and the ClipLab character in sync. (The bare `pnpm
check:token-gates` form reports "Command not found" under pnpm 9.15.4 in
this worktree; `pnpm run` works.)
- `cd ui && pnpm typecheck` — exits 0 with no errors.
- Browser proof on a throwaway backend-free vite page (not committed)
rendering the primitives with a 404 picture, a 404 video, a picture that
loads and audio: on the Artifacts page the 404 picture's stack front is
the PNG icon sheet at the same position as the audio stack's sheet (left
37.89px, top 13.34px) on the media backing; the single tiles show the
PNG and WEBM icon sheets with no play disc while the loading picture
keeps its fitted 240×160 print; the rows show the PNG and WEBM document
icons with no `<img>`/`<video>` left, while the loading picture's row
keeps its thumbnail. Not run: the browser suites (`pnpm test:e2e`, `pnpm
test:release-smoke`) and a live staging check.

States enumerated: loading (4:3 placeholder print, unchanged), loaded
(fitted print, unchanged), failed picture (icon sheet / document icon),
failed poster-less video (icon sheet without play disc / document icon),
source changed after a failure (print again).

## Risks

- Low risk. The change is behind `enableArtifactsV1` and only acts on
the element's `error` event, which fires for a 404, a network failure,
or content that is not decodable as a picture; nothing is fetched to
find out.
- `ArtifactFront` and `ArtifactStack` each keep the failure state for
their subject (as both already keep the loaded aspect), set from the
same event in one render; a consumer that renders `ArtifactFront` with a
print size but ignores `onMediaError` still gets the icon face, only at
the print's position.
- A picture that fails once and later becomes readable at the same URL
keeps the icon face until the surface remounts or the subject moves on
to another source; the data does not change under a mounted tile in
practice.

> 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

- Claude (Anthropic), model ID `claude-fable-5-1`, extended thinking,
running in Claude Code (desktop app) with tool use: file editing, shell,
Vitest, and the built-in browser for the proof page.

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

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-26 21:08:49 -07:00
DottaandPaperclip f0877a9c7c fix: recover native work and requalify saved computers (#17724)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/32/changes/paperclip/32
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip manages AI agents and preserves their work after an
interruption.
> - Native Stop must confirm termination and save the workspace.
> - Task and run views must show the current recovery receipt.
> - A new external reply can arrive while that cleanup is pending.
> - The reply must return to its original chat owner after cleanup.
> - A successful fresh retry also becomes the task’s bound workspace for
its next ordinary turn.
> - Managed computer updates can invalidate a saved snapshot
qualification.
> - This pull request fixes those instructions, acknowledgements,
handoffs and the existing native-agent Test path.
> - The operator can continue with new input while the stopped turn
remains preserved.

## Linked Issues or Issue Description

**What happened?**

Stopped native runs could keep the initial workspace-repair instruction
after files were recovered. Native Stop could also leave the shared
cancellation state at requested after remote termination was confirmed.
A new GitHub reply saved during cleanup could then remain queued because
cleanup did not ask its original inbound owner to reconsider the
receipt. After a managed snapshot update, an existing native agent could
also need qualification while the generic environment Test required
instance-admin access.

**Expected behavior**

Show the current saved-work state. Acknowledge Stop only after exact
termination proof. Let an authorized operator use the existing
saved-agent Run test to qualify its current computer. After cleanup,
recheck the saved reply's current authority and admit it once as new
input. Preserve the stopped run and uncertain external effects.

**Steps to reproduce**

1. Stop an active native turn before it returns a semantic result.
2. Send a new authorized external reply while cleanup is pending.
3. Let workspace recovery and provider cleanup finish. Inspect the run
instruction, Stop acknowledgement and queued reply.

Related work: #17594 preserves native processes through controller
outages. #17401 addresses a separate bootstrap failure. This pull
request does not replace those fixes.

## What Changed

- Use the exact run's workspace recovery receipt for task and run
guidance, including the Activity ledger.
- Retire an obsolete exact-session notice through the existing bounded
reconciler. Preserve the separate no-replay hold.
- Write the shared native Stop acknowledgement only after the audited
Stop intent and every exact remote lease receipt match.
- Delegate saved external input to the live inbound owner. Recheck its
source, actor, endpoint, principal and conversation generation. Promote
the same receipt in the transaction that creates its new run.
- Use that owner from the cleanup callback and existing stranded-queue
catch-up after a lost callback or restart. A denied source cannot abort
other items.
- Reuse the current private task directory after a successful fresh
retry. Re-read the company/task/workspace binding and validate the
canonical stable or attempt namespace without recreating missing files;
keep a later fresh retry separate.
- Extend the existing agent-scoped qualification owner to native agents.
The clean saved-agent Test qualifies its exact computer before runtime
testing. Reuse a current proof; require a real probe and verified
cleanup for a stale proof. Preserve draft tests and metadata-only
external/pool previews.
- Update execution semantics, capability maps and the recovery
verification recipe. Add a production-page Storybook interaction for the
normal native Test.

## Verification

- **Red:** persisted recovery states returned stale instructions; an
exact terminated native lease left shared Stop requested; the real
GitHub subscribed-message fixture left zero successors after cleanup.
The controlled baseline restored the previous production source,
reproduced the failure, then restored the fixed bytes with matching
SHA-256 hashes.
- **Green:** 382 durable-chat, native-continuation, Stop and recovery
tests pass. The real GitHub/PostgreSQL handoff matrix passes 12/12. It
covers callback, application restart, callback/sweep race, valid input
behind a deleted source, and denial for unknown stop, wrong allocation,
paused endpoint, revoked principal, deleted or changed source, changed
conversation generation and foreign scope. Repeated callbacks preserve
one receipt, its actor, one successor and the unchanged stopped
predecessor.
- **Workspace continuation red/green:** the real PostgreSQL preparation
flow created a fresh attempt and saved a marker, then rejected the next
ordinary turn with the same binding mismatch observed in deployed use.
The repaired preparation and filesystem suites pass 86/86: stable and
attempt-root reuse, saved-marker preservation, a later clean sibling,
changed current bindings, foreign company/task, closed workspace,
traversal, missing path and symlink refusal. No task row reset or
old-turn replay is used.
- **Qualification red/green:** a native saved-agent qualification
returned 422, and its normal Test skipped qualification. The repaired
path passes 224 qualification/immutable-snapshot/environment tests and
176 UI/upgrade tests. It covers revoked authority, foreign or changed
computer, current-proof reuse, failed/missing proof, draft settings,
settings changed during the probe, and external/pool previews. On exact
current source, the real local Harness / Runtime UI also qualified a
newly saved disposable Computer with missing proof through actual
Daytona, then completed the actual OpenCode/OpenRouter hello probe using
`openrouter/deepseek/deepseek-v4.1-flash-1017`. Supported availability
changed from Legacy-only to Paperclip Runner after proof persistence.
Qualification and runtime leases both completed normal release/cleanup.
The five prior task run IDs were unchanged; no task wake was created.
This is macOS source-server/UI with real Linux Daytona and provider
services, not a hosted UI claim. Test probes are archived by the
existing inspection contract; release does not claim physical deletion.
- Full workspace `pnpm -r typecheck`, `pnpm build`, token, map and diff
checks pass at `f6450f4739fc8141815b8b7c35fde22a655c5f90`. The broad
local `pnpm test:run` passed 24,899 tests and reported one existing
nested-clone test timeout at 15 seconds. The complete failing file then
passed 21/21 with the normal timeout; the exact case also passed on the
pinned earlier baseline. The broad runner stopped before its later
groups. No timeout or production workaround was added. Prior head
`f6450f4` has 53 successful checks, two conditional Storybook skips and
Greptile 5/5 with no inline threads. New workspace-reuse head
`fcb13399ec70f92f71bd8250081251dca3f48962` passes workspace typecheck,
full build, 86 scoped tests, maps and diff checks; Current-head CI has
53 successful checks and two conditional Storybook skips; Greptile is
5/5 with no inline findings. Deployed ordinary-turn reuse acceptance
passed as described below.

- **Hosted Stop proof:** the real GitHub issue-mention path used native
OpenCode, `openrouter/deepseek/deepseek-v4.1-flash-1017`, Daytona and an
exact low-trust task boundary. Normal UI Stop interrupted an active Bash
call. Native and shared acknowledgements matched the exact lease.
Automatic recovery saved exactly `STARTED\n` (8 bytes), with no finish
marker. Reload showed Stopped and saved work recovered. Only the
original cancelled run remained. Normal five-minute cleanup completed
its exact provider-destruction transition.
- **Limits:** the provider buffered command output, so the marker was
read after recovery. The approved local provider credential could not
inspect the hosted sandbox; its 404 is not deletion proof. Cleanup
success comes from the exact lease's platform destruction transition. An
earlier hosted stale instruction disappeared after rollout with
unchanged raw run/action data; that historical cause remains
unexplained. Original incident holds and publication receipts were
untouched.
- **Hosted handoff proof:** after QA deployed the combined candidate
containing `46b2e99`, startup admitted the previously saved GitHub
author reply without another comment, Retry or manual action. The new
native run used the exact original wake receipt and saved comment. It
completed once, committed an external-response wait, preserved the
stopped predecessor, emptied the queue and left the task In review. The
answer appeared in the original GitHub conversation. Workspace
finalization and the exact lease's normal destruction transition
succeeded.
- **Hosted workspace proof:** on the combined candidate containing
`fcb13399`, normal Retry preserved the original authenticated GitHub
request and completed a fresh native attempt. One later ordinary
same-head author reply then completed in the exact same workspace ID and
attempt directory, with no Retry/fresh directive. Its input tree digest
matched the Retry's finalized digest; final copyback preserved that
digest. The persisted assessment row and all five prior run records were
unchanged, exactly one new reply run completed, and the task returned to
In review with an empty queue and no live run. Both exact leases
completed normal verified destruction. This used real native OpenCode,
the exact DeepSeek/OpenRouter model and Daytona, without workspace-row
repair or a new remote marker.
- **Publication limit:** the workspace audit compares the persisted
assessment and run history. The ordinary reply exposed a separate
destination-summary fallback that changed the visible GitHub summary
despite the preserved assessment row. The publication track is repairing
that behavior; this proof does not claim the visible summary was
preserved.
- **Deployment boundary:** current-head CI/review and hosted same-source
Retry/ordinary-workspace reuse acceptance passed. The separate
visible-summary publication failure remains owned by the publication
track. Combined hosted UI confirmation of the native-agent Test path is
coordinated separately. Actual missing-proof UI/provider qualification
has passed in the isolated local instance above; prior hosted Stop and
same-input handoff proof remains separate. No merge or deployment is
performed by this pull request.

## Risks

Recovery state and termination receipts must match the exact source run
and allocation. Missing or foreign proof keeps the hold. The chat owner
must retain the original receipt and actor and recheck current
authority. Cleanup cannot grant authority or replay the stopped turn.
Existing native ownership, Stop, budget, permission and uncertain-effect
guards remain in place.

## Model Used

OpenAI GPT-6.1 Sol (`gpt-6.1-sol`) through Codex, with reasoning,
repository tools, source editing and test execution. The context-window
size is 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 (affected suites and
isolated failing file pass; broad timeout retained 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 (current fcb has 53 successful
checks/two conditional Storybook skips)
- [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-10-26 22:21:58 -05:00
Nicky Leach baec3abd67 Authorize background project Git with explicit Connector consent (#17798) 2026-10-26 17:22:49 -07:00
Devin Foleyanddevinfoley cfed739f81 fix(external-objects): stop reporting GitHub rate limits as unreachable (#17792)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/11/changes/paperclip/11
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app that people use to manage AI agents
for work.
> - Paperclip shows the status of external objects, such as GitHub pull
requests and issues.
> - A background sweep refreshes these objects and resolves a GitHub
credential.
> - The sweep read a credential only from a company secret with a
well-known name.
> - An instance without that secret made anonymous GitHub API calls.
Anonymous calls are limited to 60 per hour.
> - When the limit was reached, the sweep showed "unreachable" for
objects that it could not refresh.
> - A server environment token is instance-wide, so it must not expose a
private repository that a company cannot see.
> - This pull request reads a server token for public repositories,
reports a rate limit as its own state, and shows a warning on the pill.
> - The benefit is an accurate status, fewer misleading failures, and no
cross-company private data.

## Linked Issues or Issue Description

No public GitHub issue exists. The sections below describe the bug.

**What happened?**

The board showed "unreachable" for many GitHub links, even after a
related fix was deployed.

**Expected behavior**

The board should show "unreachable" only for real network failures. It
should show a rate limit as its own state and retry later.

**Steps to reproduce**

1. Use an instance with no GitHub token company secret and no server
token.
2. Let the external-object sweep make more than 60 anonymous GitHub
requests in one hour.
3. Open a task with GitHub links.

**Paperclip version or commit**

master (commit a67a18c at report time).

**Deployment mode**

Self-hosted server.

## What Changed

- Add `resolveGitHubApiCredential` in
`server/src/services/git-credentials.ts`. It reads a company secret with
a well-known name, then falls back to the server environment token
(`GITHUB_TOKEN`/`GH_TOKEN`), and it reports the credential `source`.
- Use the source in the GitHub external-object provider and in
`github-commit-details.ts`. A `server_env` token is limited to public
repositories. A private repository resolves only with a company
credential; otherwise the object reports `auth_required` and does not
fetch the private object.
- Add a `rate_limited` liveness state in
`packages/shared/src/constants.ts`.
- Classify a 403 with `x-ratelimit-remaining: 0`, a 429 response, and a
rate-limited repo probe as `rate_limited` instead of `unreachable`.
- Show `rate_limited` in the UI filter, icon, label, tone, overlay, and
badge maps.
- Make `ExternalObjectPill` and `ExternalObjectStatusIcon` prefer a
liveness warning icon and tone, so a rate-limited object shows a warning
even when the last status was healthy.
- Add tests for the credential source, the public-only server token, the
company-scoped private repository, and the rate-limited pill tone.

## Verification

- `vitest run server/src/__tests__/external-objects-service.test.ts
server/src/__tests__/git-credentials.test.ts
server/src/__tests__/github-commit-details.test.ts
server/src/__tests__/work-products.test.ts` — pass, with the new scoping
and credential-source tests.
- `vitest run ui/src/lib/external-objects.test.ts
ui/src/lib/issue-filters.test.ts
ui/src/components/ExternalObjectPill.test.tsx
ui/src/components/MarkdownExternalLink.test.tsx` — pass, with the new
rate-limited pill test.
- `pnpm --filter @paperclipai/shared typecheck` — pass. The full
monorepo `tsc` (server and ui) is killed by the 4GB memory cap of this
sandbox; the authoritative CI Typecheck gate runs it instead.
- One test in `git-credentials.test.ts` fails in this sandbox only. The
test "credential helper execution (real git, no network) ... env-carried
token" reads a global GitHub credential helper in the sandbox. The test
fails the same way on the base without this change.

## Risks

- Low risk. The change adds a liveness state and a credential source. It
does not change existing terminal verdicts.
- A server-environment token cannot resolve a private repository. This
is intentional. An operator who needs private repositories must add a
GitHub token as a company secret. The object then reports
`auth_required` with that instruction.
- `rate_limited` is a new value in `EXTERNAL_OBJECT_LIVENESS_STATES`. An
old client ignores an unknown value.

## Model Used

- Provider: DeepSeek (OpenRouter).
- Exact model ID: `openrouter/deepseek/deepseek-v4.1-flash`.
- Capabilities: tool use and code execution in the Paperclip runner.

## 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 similar open and closed PRs and
confirmed this is not a duplicate
- [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)
- [ ] 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
- [ ] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com>
2026-10-26 16:13:04 -07:00
Nicky LeachandPaperclip 835966dec8 Prepare agent-owned environments during hiring (#17761)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/1/changes/paperclip/1
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip manages agents and their execution environments.
> - New agent setup saves an inactive agent before model connection
tests.
> - Some plugins need that agent to prepare its execution resource.
> - The wizard tested without the agent ID, while the setup hold
prevented preparation.
> - Environment changes also discarded the selected model account.
> - This change prepares the saved draft during setup and keeps normal
execution held.
> - Users can test the prepared resource before they finish hiring.

## Linked Issues or Issue Description

**What happened?**

An agent-owned plugin environment could not acquire a test lease during
hiring. Changing environments also returned the user to Connect and
cleared the selected account.

**Expected behavior**

Keep the selected account, invalidate its test, and prepare the saved
agent resource in the background. Test that same agent before finishing
setup.

**Steps to reproduce**

1. Start a new Claude or Codex agent and select a saved account.
2. Change to an agent-owned plugin environment.
3. Try to finish setup or reconnect the account.

Related: #17750 defers probes until after hire submission. This change
implements preparation during the wizard instead. The related PR search
and ROADMAP review found no other implementation of this setup
preparation path.

## What Changed

- Add the optional `requiresAgent` driver declaration. Require agent
lifecycle participation when it is set.
- Prepare saved drafts on creation or environment changes. Keep the
setup hold and wait in `verifying` without background verification
scans.
- Bind tests to the saved agent. Return a warning without allocating a
lease when the required agent is absent or still preparing.
- Preserve the account and configuration step when the environment
changes. Save the selection and invalidate the old test.
- Show active preparation and support authorized retries. Keep approval,
company, budget, and normal task admission controls.
- Document the contract and cover lifecycle, lease, manifest, and wizard
behavior.

## Verification

- Server and UI TypeScript checks passed.
- 112 wizard and setup helper tests passed. The shared manifest suite
passed.
- 123 lifecycle, policy, lease, and environment-test API cases passed
after the approval-gate fix. The diagnostic and driver suites and all 80
agent adapter route tests also passed.
- Token gates, module boundaries, map validation, and whitespace checks
passed.
- All 66 lifecycle/policy cases passed after the stopping-draft
permission fix. The new real-DB route case verifies creator success,
other-creator denial, and refusal to complete a hire while stopping.
- Full workspace typecheck and build were attempted. Both stop at the
unchanged Rust Runner step because Cargo is not installed on this host.
- CI on 43be3c93d passed all automated checks, including full test
shards, typecheck, build, Rust checks, browser suites, and canary
checks:
https://github.com/paperclipai/paperclip/actions/runs/40368174530.
- The full local repository test command was started. Two unchanged
workspace tests assume Git's initial branch is master; this host
defaults to main. Both fail in isolation under the host default and pass
with process-scoped init.defaultBranch=master. The broad run was stopped
after those confirmed fixture failures; CI supplies the full clean
check.
- Early new-test failures were fixture collisions and an unscoped sweep
assertion; the fixtures and assertion were corrected. One route-suite
load raced with SDK output regeneration; rebuilding first and running
the suite afterward passed.
- Initial CI exposed a route mock missing the new prerequisite lookup.
The fixture was updated and a real HTTP no-lease case was added; all 54
cases in that route suite pass. Security review identified allocation
before required approval; the new approval gate and its tests address
it.
- CI on 50b5a08af reported 32 of 33 expected calls in the unchanged
cleanup-history scheduling test. Its isolated case passed locally
without cleanup-code changes; the original failure remains recorded and
the final CI run passes on the current head.
- Standard Greptile reviewed 43be3c93d at 5/5. A subsequent deeper
review identified runner selection, stale detail reads, error retention,
and test file size issues; 70343387b addresses all four with resolved
threads. Standard review returned 5/5 on that commit and again on
rebased head fda42c5ab. The rebase preserves master's new managed
environment skill declarations alongside requiresAgent. Full CI on
fda42c5ab passes: 55 successful checks, two intentional skips, no
failures. Run:
https://github.com/paperclipai/paperclip/actions/runs/40405121641.
- After those fixes, 133 UI tests and 61 lifecycle/policy cases pass;
all eight focused UI regressions fail against the previous
implementation and pass with the fix. Token, map, and whitespace gates
pass. The stale-read fixture initially omitted the setup URL because
navigation is mocked; following the URL activates the real detail query
and reproduces the race.
- UI TypeScript passes. This host's server dependency links now point to
a separate scratch checkout lacking requiresAgent, so the ordinary
server check reports that missing property. A no-emit check pinned to
this branch's shared declarations passes; it disables declaration
generation and supplies explicit local type roots. The first temporary
configuration lacked those type roots; the corrected configuration
passes. CI remains the full workspace verification.
- After rebasing onto 8373d7867, all 133 UI, 61 lifecycle/policy, and 44
manifest cases pass again, as do UI TypeScript, token, map, and
whitespace checks. The server no-emit check now hits three mismatched
SDK/Runner declarations from the scratch dependency links; these are
outside this change. Full CI builds the complete dependency set.
- Review cycle: the first Apex review scored 3/5 with four findings. All
were fixed together, the branch was rebased to resolve a schema
conflict, full CI and standard Greptile passed, and a second Apex review
returned 5/5 on fda42c5ab with zero new comments. All six review threads
are resolved, and the PR is conflict-free. Review:
https://github.com/paperclipai/paperclip/pull/17761#issuecomment-6422635718.
- No live provider resource was created and no deployment was performed.

## Risks

Plugins must opt in and ship a compatible declaration. Companies
requiring hire approval keep drafts paused and defer allocation and
verification until approval. Other companies prepare drafts during the
wizard under their existing agent-creation authority; the setup hold
still blocks ordinary work. Preparation uses existing lifecycle
ownership, retry, and cleanup paths. The open wizard polls only while
preparation or stopping is active. No database migration is required.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, tool use, and code
execution. The exact serving model ID and context window size are 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 described the issue in-PR using the bug report fields
- [x] I have not referenced internal or instance-local issues or links
- [x] My branch name describes the change and contains no internal
ticket id
- [x] I have run the targeted tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation
- [x] I have considered and documented the risks
- [x] All Paperclip gates are green — 55 successful checks and two
intentional skips on fda42c5ab
- [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-10-26 15:21:47 -07:00
Nicky LeachandPaperclip c7c12dbc79 Support plugin panels in task sidebars (#17796)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task side panels keep live work beside the conversation.
> - Plugins can already provide agent detail tabs.
> - Those tabs have no generic way to appear beside the task that is
using the agent.
> - This pull request adds an optional task-side-panel declaration to
agent detail tabs.
> - The plugin owns the label, component and availability. Core supplies
the task's running agent.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Access to plugin-contributed live views from task chat.

**Subsystem affected**

Plugin manifest validation, slot discovery, and task side-panel
UI/state.

**Current behavior**

Agent detail-tab contributions appear on agent pages. A task cannot
offer the same view through a plugin-owned availability decision.

**Proposed behavior**

An agent detail tab can declare `taskSidePanel: { availabilityPath }`.
Core substitutes the running agent into the plugin-local path. A
declared board GET route scoped to that agent returns `{ available:
boolean }`. Available contributions appear in desktop and mobile task
side panels.

**Reason and benefit**

Keep the task and its live plugin views together. Preserve plugin
ownership of provider protocols and product behavior. Core contains no
concrete plugin identifiers, routes, labels or readiness rules.

**Breaking changes**

None. The field is optional. Existing contributions remain unchanged.
Missing, disabled or unavailable plugins add no panel.

**Additional context**

Related: #17111 established the agent detail-tab and scoped API
extension surfaces. Roadmap and related PR searches found no duplicate
of this extension.

## What Changed

- Extend the manifest with optional task-panel metadata. Validate safe
plugin-local paths and require a declared board GET route with
agent-scoped authorization.
- Discover and load only opted-in agent contributions. Poll their
generic availability responses and mount the existing components with
agent context.
- Add generic panel tabs, launcher entries, dismissal and inactive-view
removal in desktop/mobile task chat.
- Reuse the existing live-run polling guard so idle tasks with a healthy
live connection stop polling.
- Add provider-neutral fixtures, schema/authorization tests, task tests
and SDK/feature documentation.

## Verification

- PASS: 301 focused tests including the full task-detail file, generic
panel discovery, persistence, slot loading and manifest validation.
Regressions cover POST-before-GET route order, mobile drawer dismissal,
recovery without focus and the absence of the hidden desktop task panel
on mobile.
- PASS: UI and shared-package typechecks; production UI build; token
gates, feature-map and module-boundary checks; diff and secrets/PII
review.
- PASS on final head: all 795 UI files / 9,186 tests, and all 95
shared-package files / 1,038 tests. Commands: `node
node_modules/vitest/vitest.mjs run --project @paperclipai/ui
--maxWorkers 3` and the corresponding `--project @paperclipai/shared`
command with local socket access.
- On the final head, server shards 7/12 and 10/12 and workspace shard
a-1/2 were interrupted by runner shutdown/communication loss. GitHub
reported infrastructure failures; no assertion failure was surfaced in
the available diagnostics. The queued summary was cancelled, then `gh
run rerun --failed` successfully requested retries for only those three
jobs. They are currently queued for CI runners; the 50 successful checks
remain passing. Interrupted attempts are not counted as passing.
[Final-head CI and
retry](https://github.com/paperclipai/paperclip/actions/runs/40396870920).
- Earlier verification exposed an empty-panel rerender loop, which was
fixed. The sandboxed combined run also failed five shared port-registry
tests because it could not bind loopback listeners; the full shared
rerun with socket access passed. These earlier failures are retained
here rather than reported as passing runs.
- Full workspace typecheck/build were attempted with pinned pnpm 9 after
resolving the initial local package-manager setup. Both stop at the
unchanged Runner Rust step because `cargo` is not installed. Full local
workspace checks are not reported as passing; final CI must provide
those broader checks.
- No live provider or plugin-specific transport acceptance is claimed by
Core's synthetic fixtures.

## Risks

- Availability is polled every three seconds only while an authorized
running agent exists. Plugins own the side effects and meaning of that
read.
- A view uses the running agent's context. It is not a separate per-task
resource.
- Optional metadata adds no backend endpoint or permission bypass. The
host requires existing board and agent authorization.
- Reverting the optional contract and UI integration removes task panels
without a data migration.

## Model Used

OpenAI Codex (GPT-6), with reasoning, repository tools and code
execution. The exact backend snapshot ID and context window size are not
exposed by 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 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
ticket id
- [x] I have run focused 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>
2026-10-26 14:47:15 -07:00
DottaandPaperclip 507dc70be2 fix(evals): bind hosted controller admission to the first attempt (#17523)
Bind hosted controller admission to the repository, GitHub run, first attempt, workflow revision and selected execution before credential reads or provider launch. Keep offline evidence replay independent of the current worker environment. Preserve the single-project boundary editor and refresh project-access data with agent-detail updates.

Verified head: 1e588f75fe.
Validation: 74 synthetic source/portable controller tests, 98 focused UI tests and token gates passed before the ancestry-only final sync; four hosted/portable regressions pass again with unchanged eval and UI repair trees. Final exact-head full CI passed (40387856225), and Greptile reviewed this head at 5/5 with zero unresolved findings. The optional secondary Paperclip Review is paused and not counted as completed. No paid work or schedule changes.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-26 14:43:58 -05:00
DottaandPaperclip 5061ab7b35 perf(ui): speed up task and inbox cold opens (#17756)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task lists and inboxes are the main entry points to that work.
> - Cold opens fetch overlapping task lists, task descriptions, and run
details before useful rows settle.
> - Independent responses can insert rows above content that a person
has started to read.
> - This pull request loads a small task index first and adds details
only for visible rows.
> - It keeps row order and geometry stable while those details arrive.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Cold opens of Tasks and Inbox, including the shared navigation badge.

**Subsystem affected**

Server list reads, shared response contracts, and the React UI.

**Current behavior**

The badge fetches full task bodies. Mine fetches several overlapping
lists. Historical diagnostics and row metadata add work before the first
useful list. A fast failed-run response can appear before task rows,
then move down when tasks arrive.

**Proposed behavior**

Load the selected inbox source and its required context together. Use an
index without task descriptions or recovery diagnostics. Fetch
diagnostic details for up to 50 visible rows. Keep skeletons, recovery
indicators, external status, and live metadata in fixed space.

**Reason and benefit**

Reduce work on a cold open and prevent loading-induced row movement. On
the same 100 local fixture tasks, the compact response was 262,441
decoded bytes and the index was 110,909 bytes. This comparison excludes
compression and is not a page latency benchmark.

**Breaking changes**

Existing full and compact responses remain available. New index/row
projections are opt-in and marked as partial data. Mine keeps its
existing most-recent-100 display limit, now selected on the server.
Existing filters and group preferences remain in the client. No database
migration.

**Additional context**

Refs: #17593. Related: #13095, #17428, #13803. This change addresses
collection overfetch and layout stability. It does not replace the
blocked-inbox query work or the database activity-index work.

## What Changed

- Add authorized index and row projections, with bounded task and parent
ID batches.
- Replace badge list downloads with unread IDs and aggregate counts.
Preserve actor privacy, dismissals, and local archive behavior.
- Load only the selected inbox source, plus bounded parent and
failed-run context. Return only relevant failures from the bounded run
window.
- Batch hierarchy reads, including at most one authorized child per
collapsed parent in one request. Collapsed markers do not consume the
expanded row budget, and partial descendant counts are not shown as
totals. Enrich visible rows without replacing membership, ordering,
titles, or read state.
- Reserve row geometry on desktop and mobile. Reveal the initial inbox
only after its sources settle. Preserve legacy task-list reads.
- Start collection module downloads during access checks. Keep partial
rows out of the task-detail cache.
- Keep ETags and concurrent request sharing for the new projections, but
skip the short server response TTL so archive undo sees fresh state.

## Verification

- On final head `ef6afb2a56`, the full CI workflow passed, including
build, typecheck, server/workspace/runner suites, and all eight browser
shards. A server shard reported **1,489 passing tests** before runner
shutdown canceled the job; its single infrastructure retry passed. Both
Greptile and Paperclip Review are **5/5**, with zero unresolved review
threads.
- The optional external **Entire Gates** check remains `unassessed`
because it has no active assessed Change for this comparison. Entire is
not set up in this checkout. The repository ruleset requires `ci /
verify` and `ci / e2e`; both passed. No gate configuration was changed.

- Passed workspace typecheck after the final API batching change. The
full production build also passed on the final commit; the exact-retry
E2E run built the shipped UI.
- Passed token gates and map validation. The final batch-preview pass
has 91 passing route/hierarchy/component tests, including privacy,
request bounds, 30 collapsed parents in one read, and a 120-child parent
alongside a sibling.
- Passed the 166-test focused UI/inbox/badge run, 47 additional UI
regression tests, and 34 issue-list route tests. The latest regressions
cover low-trust agent badge IDs, cold company selection, 30
description-only Mine matches with archive actions, retrying optional
row details, and collapsed/expanded siblings.
- The full local `pnpm test:run` spanned the rebase and reported
failures in five suites before it was stopped; it is not claimed as a
complete pass. A fresh serial rerun of all five suites passed
**452/452** tests (tool gateway, native resume, project repositories,
workspace recovery, and runner selection). Full current-commit coverage
is checked by CI.
- Real browser: delayed index and row-detail responses on Tasks and
Mine. The first placeholder and first row had the same origin and
44-pixel height. Twelve rows on each page had zero position, height, or
title-width change after recovery details arrived.
- Real browser: reviewed long titles and recovery status at a 390 by 844
viewport. Task text stays on one line and recovery uses a compact
indicator.
- Three fresh document loads per page on final commit `260893bf92`, with
HTTP cache retained on a warm local development server: Tasks
1.031–1.190 seconds; Mine 0.999–1.193 seconds. Browser-control overhead
is included. These values must not be compared directly with staging
latency or the earlier local samples taken during a full test run.
- The browser archive test exposed stale results after Undo. The new
projections now bypass the server TTL; immediate-mutation regression
tests pass. The final browser retry passed: Archive followed by Undo
restored exactly one row and the badge count.

- CI exposed a hook-order crash when company selection resolved after
the first inbox render. The hook now runs before the empty-company
return. All seven affected exact-retry and legacy-continuation browser
scenarios pass locally after the fix.
- Real browser review regressions: 97 description-only source matches
retained Archive actions; deliberately failed optional row reads
displayed a retry notice while all 12 observed row positions and heights
stayed unchanged. Retry restored the recovery indicator. Network fault
injection was removed.

- The final production build and workspace typecheck passed. Final
focused verification passed 153 UI/helper tests and 26 heartbeat privacy
route tests. Final review regressions cover newer diagnostics arriving
during the index read, reloading diagnostics when the same task ID
changes version, optional source failure/retry without hiding available
rows, and required external-status filter failure. The latest-failures
route test verifies bounded selection, agent filtering, success
suppressing an older failure, and private-run redaction.
- Real browser: deliberately failed the run source, then retried it.
Twelve available task rows kept the same position and 44-pixel height
before, during, and after retry. No loading skeleton replaced them.
Fault injection was removed.
- Hierarchy review decision: the cold-open barrier stays because
inserting ancestors or expanded children after revealing index rows
would cause layout shifts. Existing hierarchy context now survives
subsequent requests, with a regression proving a new ancestor read does
not blank the list. The bounded recursive tree read can still add
latency for unusually deep expanded trees.

- Tasks now handles a failed external-status filter with an explicit
error and Retry, suppressing a false empty state. All 52 Tasks component
tests pass, including failure-to-success retry. One existing large-tree
test timed out while workspace typechecking ran concurrently; the whole
component suite passed when rerun without that competing work. Workspace
typecheck, the full production build, and token gates passed for this
fix.

## Risks

- Saved filters and grouping still operate on the existing bounded
collection. This is not a new global server pagination model.
- Fixed row slots reduce available title width. Long titles remain
accessible through task navigation.
- Recovery and related diagnostics arrive after core rows. Their
responses cannot replace ordering fields, and stale versions are
rejected.
- Index/row requests now revalidate against current data instead of a
short server TTL. They still share concurrent reads and use ETags.
- This has not been deployed by this pull request. Staging latency must
be measured after deployment under comparable conditions.

## Model Used

OpenAI Codex, GPT-6 family. The exact runtime model ID and
context-window size are not exposed in this session. Used code editing,
terminal execution, and real-browser diagnostics.

## 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-10-26 14:29:20 -05:00
DottaandPaperclip a67a18c171 fix(tasks): hide empty message history disclosure (#17751)
## 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>
2026-10-26 11:58:30 -05:00
Clément df5a78cf91 fix(ui): keep iPhone task chat stable while typing and streaming (#17232)
## 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
2026-10-26 08:44:39 -07:00
DottaandPaperclip d64cb7be52 fix(ui): identify accounts in AI connection choices (#17738)
## 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>
2026-10-26 10:28:59 -05:00
DottaandPaperclip a1f77821b9 perf(tasks): show recent conversation before historical activity (#17593)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - A task page must show the instruction and current conversation
quickly.
> - The current page waits for related task data and historical run
transcripts.
> - These reads grow with task history, even when the reader only needs
the latest answer.
> - This pull request gives cold opens a small initial view and loads
older history on demand.
> - Messages and runs observed while the page stays open remain visible.
> - The benefit is a readable task before historical diagnostics finish
loading.

## Linked Issues or Issue Description

Related: #14667 and #16229. The first changes the reveal gate and scroll
anchors. The second adds general history pagination. This PR adds a core
task read and a folded recent-conversation view. It preserves the
default full-read API contracts. The shared files will need coordination
if either related PR lands first.

**What existing behavior does this improve?**

Cold opening an ordinary task with a long conversation or large run
logs.

**Current behavior**

Task enrichment and historical transcripts delay the readable
conversation. A cold open can fetch several megabytes of tool activity
before revealing saved messages.

**Proposed behavior**

Show the task instruction, recent saved replies, latest human input, and
the latest run's conversation data first. Fetch older messages and full
run activity when the reader chooses **More messages**. Retain new
messages while the page stays open.

## What Changed

- Add an authorized core issue view that skips related enrichment. Keep
enrichment on the existing detail read. Share task mutation, rollback
and invalidation updates with the core cache.
- Add a bounded recent-comment read. Preserve the first human
instruction when no description exists, including legacy rows with a
NULL author type. Keep company and task access checks and comment
redaction.
- Add optional recent activity and run-summary views. Fetch original
input receipts for visible comments separately so delivered messages
stay out of the queue. Reconcile watched unfinished runs after a
reconnect beyond the preview window, removing deleted runs after
reconciliation.
- Filter the latest native run's initial events to assistant messages,
request lifecycles and terminal results. Full event reads remain
available on expansion. Legacy fallback reads use a small tail extended
to the first complete record. HTTP cancellation aborts the storage read.
- Retain observed messages across cursor catch-up and new runs. Apply
local cancellation and deletion to both caches and their task aliases.
Refetch locally seeded history pages on expansion. Preserve expansion
across identifier and UUID links. Keep deep links, classic tasks and
Agent Chat on their existing full-history path.
- Update API documentation, design guidance, capability maps and
regression coverage.

## Verification

- Final acceptance on `9ea0b15ae44d9f6d2c9a9f824b4835f299f92979`: all CI
gates passed, including server/UI tests, all eight browser shards,
runner checks, full typecheck and build. [Final CI
run](https://github.com/paperclipai/paperclip/actions/runs/40326990328).
GitHub reports 55 successful checks, two intentionally skipped checks,
and one neutral Paperclip Review check described below. No checks are
pending or failed; Greptile is 5/5 and no review threads remain open.
- October 26 merge update: merged current `master`. The only conflict
was in task-page imports; both the compact-history hook and the new
live-update hooks remain. All CI tests and build jobs passed on
`044fd6733d`. Fresh review found canceled-comment cache drift, legacy
human-comment filtering, send-then-expand truncation, and partial legacy
log records. These defects were fixed in `af3d66a5bd`.
- Review-fix verification: 470 tests pass across ten affected suites,
including all six PostgreSQL cold-open tests without a helper override.
Cancellation/delete and send-then-expand regression tests failed before
the fixes and pass afterward. Coverage includes task identifier/UUID
reopen, stale in-flight reads, legacy NULL author types, local-file and
object-storage tails cut inside UTF-8 text, route forwarding, and
request cancellation. Full workspace typecheck and production build,
token gates, map validation and diff checks pass.
- Follow-up review found that a failed expanded legacy read lost its
record-alignment state on retry. `9ea0b15ae4` commits the expanded
window only after a successful read. The new regression fails before the
fix and passes afterward; all 19 transcript tests, UI typecheck, UI
build and token gates pass. Greptile reviewed this commit at 5/5 with no
actionable findings, and all review threads are resolved.
- The final Paperclip Review check ended neutral because its execution
did not complete; no passing Paperclip assessment is claimed. Its
earlier four concrete findings were fixed and regression-tested.
Greptile and the security scans completed successfully on the final
commit.
- The preceding `af3d66a5bd` CI run was canceled when superseded by the
retry fix. Its server shard 11 check briefly reported failure, but the
job API records cancellation and its test step passed all 1,750 tests.
This superseded run is not used as final CI acceptance.
- 549 focused tests pass on the final implementation across nine task
UI, activity-route, OpenAPI and PostgreSQL suites. These cover pending
history, desktop/mobile visibility, expansion, retained runs, message
bursts, cancellation recovery and queued-comment removal in both views.
- Legacy expansion keeps the latest answer visible while fetching and
deduplicating older output.
- Five PostgreSQL tests pass for core access denial, recent comments,
missing-description instructions, event paging and bounded activity/run
reads. macOS could not start another PostgreSQL cluster because it
exhausted its semaphore limit. These tests used a separate disposable
database on an existing local server through a temporary test setup
override. The helper was restored afterward.
- Full workspace typecheck and build pass with the final state fixes, as
do token gates and capability-map validation.
- Token gates, capability-map validation and `git diff --check` pass.
- Browser proof used a disposable task with 80 comments and six large
run histories. The cold view showed the instruction and recent exchange.
**More messages** revealed older comments. Navigation away and back
preserved expansion.
- Local HTTP sample: core 50 ms, recent comments 24 ms, recent run
summaries 17 ms. The latest native conversation response was 839 JSON
characters / 8 ms; its full event response was 1,099,005 / 86 ms.
Browser content paint was 1.34 seconds with development assets cached.
These are local observations, not staging latency claims.
- The first CI run passed every job except four board-send browser cases
and the review threshold. Those browser fixtures only mocked the old
comments endpoint; they now serve both recent and full reads, retaining
all message and attachment assertions. Both initial review findings were
fixed with regression tests. The next CI run passed every job. The
deeper review identified core-cache mutation, older delivery receipt and
retained run-status gaps; those are now fixed with regression coverage.
Final review is 5/5 with zero unresolved findings. Final-head CI
initially failed one unchanged runner shutdown test
(`runnerd-codex-transport.test.ts`, timeout-attachment case) with
`NativeSessionCloseUnrecoverableError`; all other CI jobs passed. The
same runner code passed on 971a762f80. A targeted local reproduction
also failed during provider drain. The failure is outside the changed
task loading paths; its underlying cause remains unresolved. The single
failed-job retry passed on the same head; this demonstrates recovery,
not a root-cause fix. All CI gates passed on the previous implementation
head `9004f94f28`: [CI run and
retry](https://github.com/paperclipai/paperclip/actions/runs/40192334629).
- `pnpm test:run` was attempted and stopped after repeated embedded
PostgreSQL startup failures. The native session suite recorded 15
database-related failures; other database suites could not start. No
complete local suite pass is claimed.

## Risks

- The compact view intentionally omits older diagnostics until
expansion. Existing open questions and approvals still use the current
interaction and run paths.
- Previously observed comment and activity rows remain cached while
open. The newest preview and incoming cursor pages refresh; this does
not add a general historical-edit synchronization protocol.
- Recent views are optional. Existing full API callers retain their
response shape and behavior. No migration is required.
- A legacy tail can exceed the requested byte limit by the prefix of its
first log record. Backward reads stop at the preceding record boundary
and honor cancellation.
- Staging has not been deployed or qualified with this change. Instance
startup latency is separate from task history loading.
- The related open PRs touch the same task-history files.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, repository editing, shell
tools and browser testing. The exact serving 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 — 549 affected task tests;
the full local suite and unrelated runner failure 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-10-26 08:11:39 -05:00
DottaandPaperclip 5d2515e520 Simplify agent harness configuration choices (#17722)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Users choose a harness in agent setup and configuration.
> - Supported harnesses already determine their native Runner profile.
> - A second ACP agent selector lets users make a conflicting choice.
> - The harness list also shows unavailable options marked Coming soon.
> - This PR removes these extra choices and keeps each harness's
settings.

## Linked Issues or Issue Description

Refs #17142 and #17120. Related runner defaults work: #15422.

**What existing behavior does this improve?**

The Harness dropdown and native agent configuration form.

**Current behavior**

A Pi or Claude agent shows an ACP agent selector below Harness. Users
can select a different agent in that second control. The Harness list
also includes disabled Coming soon entries.

**Proposed behavior**

Use Harness as the only agent choice when it determines the Runner
profile. Hide unavailable entries from its list. Keep the generic
advanced Runner selector available where no parent harness determines
the profile.

**Reason and benefit**

Users choose the harness once. The form no longer offers a conflicting
ACP agent choice or an option they cannot use.

**Breaking changes**

No API or stored configuration changes. Unavailable harnesses are
omitted from the list; existing saved values still display.

## What Changed

- Hide the ACP agent selector when the parent Harness control determines
the Runner profile.
- Remove Coming soon options and their unused disabled-state rendering
from the Harness dropdown.
- Preserve saved Process and HTTP selections during unrelated edits
while omitting them from new choices.
- Document the field visibility contract.
- Cover new and saved Claude, Pi, Codex, and OpenCode forms. Check that
Pi thinking controls remain and an unrelated name edit does not rewrite
Runner configuration.

## Verification

- Passed after rebasing onto master: 199 tests across
AgentConfigForm.render, codex-local/config-fields, and adapter config
sections.
- Passed: UI TypeScript check, UI production build, token gates, and git
diff --check.
- Live browser verification passed for the Pi configuration page before
and after rebase. Harness remains Pi, ACP agent is absent, and the
original model and thinking level remain. The open Harness list contains
no Coming soon, Process, or HTTP entries.
- Dropdown regression cases open Harness, check the supported options,
exclude Coming soon/Process/HTTP options, and preserve saved Process and
HTTP configuration through a name-only save.
- Passed on final commit b60a02387f: all 57 check runs are terminal and
clean (53 success, 2 neutral, 2 skipped). The Snyk status is successful.
Greptile and Paperclip review both give 5/5, with no unresolved review
threads.

## Risks

- Low risk: this change only removes redundant or unavailable UI
choices. Runner routing and saved settings keep their existing
contracts.
- The advanced generic Runner form retains ACP profile selection. It has
no parent harness choice to determine that profile.
- No new agent task or provider call was needed to verify these form
changes.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, code editing, command
execution, and browser use. The exact serving 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
- [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-10-26 08:11:17 -05:00
DottaandPaperclip 5cea9c7c0e fix(ui): show eligible wake targets when resuming tasks (#17521)
## Thinking Path

> - Paperclip manages agents and their assigned tasks.
> - A task pause controls execution without changing task status.
> - Resume can remove that pause and request work from eligible
assignees.
> - The preview counted blocked tasks and former executors as wake
targets.
> - The release route correctly skipped those targets, so the dialog
promised work that did not start.
> - Resume also trusted stale pause snapshots after tasks were reopened.
> - This PR aligns preview with execution eligibility and rechecks
current task state when releasing a pause.

## Linked Issues or Issue Description

**What happened?**

Pause an assigned blocked task, then open Resume. The dialog says that
one task will resume and offers to wake one agent. Applying it only
removes the pause. The route skips blocked and backlog tasks. A former
executor can also inflate the wake count after reassignment.

**Expected behavior**

The dialog must distinguish removing a pause from starting work. Its
wake count must use the current assignees and statuses accepted by the
release route. Blocked work must stay blocked.

**Steps to reproduce**

1. Open an assigned blocked task.
2. Choose Pause work, then Resume task.
3. Inspect the wake count and apply Resume work.

Related runtime recovery work is tracked separately in #17097 and
#17439. This PR does not change remote execution recovery.

## What Changed

- Share the resume status list between preview and release. Count only
current assignees on todo, in-progress, and in-review tasks for resume
wakes.
- Explain that Resume removes the pause. Show the existing preview
warnings, including tasks that remain idle.
- Disable and uncheck the wake option when no agents qualify. Send the
same choice to the server.
- Reevaluate previously skipped pause members after reopening or
releasing another hold. Retain active-pause and unsafe-execution guards.
- Add real PostgreSQL and HTTP-route regressions plus browser coverage
for both task interfaces. Keep draft, ancestor-pause, and
Stop/reconciliation coverage.
- Update the task coordination maps. Add an opt-in dedicated test
database URL for hosts where embedded PostgreSQL cannot start.

## Verification

- Final head `9548eb16736f632cc111a5c13a9a994ec1d95a13`: all 55
completed checks pass, with two optional Storybook checks skipped. [CI
40188094904](https://github.com/paperclipai/paperclip/actions/runs/40188094904)
passes, including typecheck, build, all general/serialized suites, and
all eight E2E shards. Greptile is 5/5 on this commit; the reopened-task
finding is fixed and resolved.
- Red: the real PostgreSQL regression receives three agents instead of
the one eligible current assignee on the original code.
- Green: all 27 tree-control service, route, and unit tests pass. They
cover current assignees, blocked/backlog exclusions, reopened tasks,
company boundaries, remaining pause holds, and execution blockers.
- The reopened-task route regression fails on the previous
implementation: skipped members never reach preflight/wake, and an
unsafe replay releases the hold instead of returning 409. All cases pass
with the fix.
- Browser: all five applicable cases pass together (90 seconds):
blocked-work resume in both interfaces, draft/ancestor-pause cases in
both interfaces, and the process
Stop/pause/reconciliation/restart/cancel lifecycle. The optional
native-runner fixture is skipped locally because its fixture binary is
not configured.
- All 157 task-page component tests pass on the prior commit; subsequent
changes affect the server route and Stop fixture only.
- `pnpm -r typecheck` and `pnpm build` pass before rebase, and CI
typecheck/build passed on the previous PR commit. Server typecheck
passes again after the route fix. The final-head CI run also passes
these full checks.
- `node scripts/check-maps.mjs`, `node scripts/check-token-gates.mjs`,
and `git diff --check` pass.
- Full `pnpm test:run` was attempted but did not complete: this host
cannot initialize embedded PostgreSQL, and unrelated workspace-runtime
tests timed out. The focused database tests and E2E suite use disposable
PostgreSQL 18 instead. All general-test and serialized-test CI shards
passed on the previous PR commit; the final-head CI run also passes
every test shard.
- The first CI run caught the existing Stop test trying to check a
disabled wake option for blocked legacy work. It now asserts zero wake
targets and retains the no-execution-before-reconciliation checks.
- Earlier E2E attempts exposed fixture problems: assignment started the
fixture before it was paused, and the classic interface had two matching
editor nodes. The fixture now enables dispatch after the hold exists and
scopes the final assertion to the task composer. No product assertion
was removed.

## Risks

Resume preview is a snapshot. The release route still checks current
status, assignment, and execution blockers. It does not bypass approval,
budget, or recovery gates. Pause, cancel, and restore keep their
existing affected-agent semantics. The test database override only
accepts a dedicated database name ending in `_test`; it runs migrations
before the suite and closes its clients afterward.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, browser
control, and code execution. The runtime does not expose a more specific
model ID or 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-10-25 21:49:52 -05:00
DottaandPaperclip d0c8f0b090 fix: explain project access denials and add an authorized repair path (#17509)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Low-trust agents may read only the projects in their allowed scope.
> - Workspace setup correctly stops a task outside that scope.
> - The task previously showed a generic failure, and agent settings did
not offer an additive repair.
> - This pull request explains the denial and lets authorized operators
add projects while preserving other restrictions.
> - The saved task then offers an explicit retry. Saving access does not
start work.

## Linked Issues or Issue Description

**What happened?**
A project access denial appeared as an ordinary failed attempt.
Operators could not add a second allowed project from agent settings.

**Expected behavior**
The task should explain the denied access and link to a working
permission editor. The editor should preserve existing scope and
restrictions, enforce operator authority, and retain drafts after a
failed save.

**Steps to reproduce**
1. Assign a low-trust agent to a task whose project is outside its
allowed projects.
2. Let workspace setup deny project access.
3. Open the task, follow Manage project access, add the project, save,
reload, and return to the task.
4. Confirm that the saved message remains and Retry task is a separate
action.

## What Changed

- Record a typed, non-retryable project denial before provider dispatch.
Project denials do not enter automatic continuation or provider comment
policy.
- Project current and historical setup denials into a safe task notice.
Keep unrelated failures, prior assignees, and approval/pause/budget
gates separate. Recheck current project authority, including standard
trust and root-issue grants. Accepted retries keep their working state.
- Add board-only project-access reads and additive saves under the agent
row lock. Enforce company scope, agent-management authority,
pending-approval restrictions, and an audit record for new additions.
- Add the production notice and searchable multi-project editor,
including read-only, saving, cancellation, and failed-save states.
Preserve the return-to-task query through canonical agent redirects.
- Register board-only project-access routes in OpenAPI with a strict
request schema.
- Add production Storybook examples and API/persistence/concurrency
regressions. Retain the approved design snapshot and update the behavior
maps and implementation contract.

## Verification

- Passed: `pnpm -r typecheck`, `pnpm build`, `pnpm build-storybook`,
`pnpm check:token-gates`, `node scripts/check-maps.mjs`, and `node
scripts/storybook-catalog.mjs`.
- Passed: 11 permission/projection tests and 30 run-completion tests
against an isolated PostgreSQL database. These cover historical
failures, concurrent additions, idempotent audit, preserved
restrictions, foreign projects, read-only users, agent self-grants, and
no automatic wakeup.
- Passed: all 27 OpenAPI route tests, including route coverage and the
new board-only request/response contract.
- Browser: the real app displayed a historical denial; Manage project
access opened the editor; saving retained the original project and
survived reload; Return to task showed the ready notice. Saving created
one audit event and zero runs. Explicit Retry returned 202 and reached
the separate sandbox requirement, which remained enforced. No external
provider was used.
- All five production Storybook interaction checks pass: blocked task,
save, cancellation, failed-save recovery, and read-only settings. These
use fixture callbacks; durable authorization is covered separately
above.
- `pnpm test:run` was attempted locally but stopped after repeated
embedded PostgreSQL startup failures caused by macOS semaphore
exhaustion. Full-suite CI is required before merge. The separate UI
suite passed all 9,095 tests. The 41 focused server regressions also
passed after rebasing onto the latest master. A further 26
recovery-classification tests pass, including a red-to-green regression
for automatic continuation after a project denial.

## Risks

- No schema migration. The new endpoint only adds same-company project
IDs and preserves the rest of the stored policy.
- The historical notice recognizes one exact setup denial message. It
does not display arbitrary run errors or disclose a different source
project's identity.
- The retry still passes all current admission and isolation checks. The
notice does not promise that other execution requirements are satisfied.
- Related open work: #13309 covers inherited secret restrictions; #11234
covers the broader repository catalog. This change does not replace
either policy surface.

## Model Used

OpenAI Codex (GPT-6), with code execution and browser tools. The precise
runtime model ID and context-window size were 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
#` 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 (focused server and full UI
suites; full-suite infrastructure limit 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-10-24 16:16:29 -07:00
DottaandPaperclip 0eb2c964a7 fix(agents): allow runner qualification with agent configuration permission (#17448)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent owners configure the harness and computer used for that work.
> - A legacy runner upgrade must first qualify an unverified sandbox.
> - The upgrade called an instance-admin probe, so a company owner with
agent configuration permission received HTTP 403.
> - This pull request qualifies the saved computer through the agent's
existing configuration authorization.
> - Company owners can complete the upgrade while general instance
environment management stays restricted.

## Linked Issues or Issue Description

Refs #17361. Related: #17122.

**What happened?**

Upgrade runner displayed for an existing Claude agent on a Daytona
Paperclip Computer. Clicking it returned “Instance admin access
required” for a cloud company owner. The agent remained on the legacy
runner.

**Expected behavior**

A caller permitted to update the agent can qualify that agent's saved
computer and upgrade. Instance-admin access is not required for this
agent-scoped operation.

**Steps to reproduce**

1. Sign in as a cloud company owner with `agents:configure` and no
instance-admin role.
2. Open an existing legacy Claude agent on an unqualified Daytona
snapshot.
3. Select Upgrade runner.

## What Changed

- Add `POST /api/agents/{id}/qualify-runner` with the existing
`agent_config:update` guard.
- Reuse the server's effective environment resolver. The submitted
environment ID only detects stale state; it cannot select a different
computer.
- Preserve company binding checks, check binding again at lease
acquisition, and record agent-scoped audit activity.
- Return qualification status and the lease receipt without
instance-level provider metadata or raw provider errors.
- Use the new endpoint for the existing-agent upgrade. Keep the generic
environment probe restricted to instance admins.
- Disable Upgrade runner when an unsaved computer change resolves to a
different target, with a save-first explanation. Other draft settings
still accompany an upgrade.
- Add real-database authorization regression tests and update the API
contract and access maps.

## Verification

- Red: the existing UI called the instance-wide probe and failed the new
agent-scoped call assertions in eight upgrade cases.
- Green: 349 related route, provider qualification, runner selection,
and UI tests passed.
- Green: 12 authorization cases passed with real PostgreSQL, real HTTP
routes, real saved role grants, and a simulated provider boot. They
cover the cloud owner, removed grants, foreign agent/computer, inherited
targets, stale target, invalid body, archived/local target, redacted
failure, audit scope, and unchanged agent settings.
- Review regression: two cases first reproduced the enabled upgrade
button after an unsaved computer change; both now pass, along with all
168 related UI tests. Qualified/unqualified computers and restoring the
saved selection are covered.
- All 26 OpenAPI cases passed; the 12 real-database authorization cases
also passed after rebase.
- The host exhausted PostgreSQL semaphores. For the 12 cases, a
temporary local-only setup used disposable PostgreSQL 18 in Docker
instead of the embedded database launcher. The committed tests use the
normal embedded database helper. No authorization decisions were mocked.
- `pnpm -r typecheck`, `pnpm build`, `pnpm check:token-gates`, map
validation, module-boundary validation, and `git diff --check` passed.
- `pnpm test:run` was attempted but did not establish a full local pass:
the host could not start embedded PostgreSQL clusters. All current-head
CI gates passed, including the full suite in CI. The commitperclip
review workflow timed out before reporting any executed steps on its
first attempt and passed on one retry.
- Fresh staging acceptance remains pending deployment. Verify persisted
native configuration and a successful runtime test on the existing
Daytona computer after merge. Earlier live Daytona proof from #17361 is
separate evidence.

## Risks

- Qualification can start a fresh, temporary sandbox. It uses the
existing probe lifecycle and cleanup contract.
- The new path must remain scoped to the saved agent and its company.
Denial and redaction tests cover that boundary. General instance probe
authorization is unchanged.
- No migration, role change, credential change, or automatic agent
upgrade is included.

## Model Used

- OpenAI GPT-6 through Codex, with reasoning, code execution, and
browser tools. The exact deployed model variant and context-window size
were 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>
2026-10-24 10:31:40 -07:00
DottaandPaperclip f66d590899 fix(ui): open the new-task form immediately (#17041)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People use New task to send work to an agent.
> - The board currently downloads the task dialog code after the first
click.
> - This shows a loading window before people can enter their request.
> - The form already loads agent and project choices after it opens.
> - This pull request loads the task dialog code with the board.
> - People can start writing immediately and keep their text as choices
arrive.

## Linked Issues or Issue Description

Related change: #16849. Commit
`fa50cab5685b9cdbb26ad9c610cc5b6c373d3ff4` added the deferred dialog and
its loading window on October 19, 2026.

**What happened?**

The first New task click shows “Loading new task…” while the browser
downloads the dialog code.

**Expected behavior**

The form opens on click. Agent and project choices load in place. Text
entered during those requests stays in the form.

**Steps to reproduce**

1. Open the board in a fresh browser session.
2. Select New task before its code is cached.
3. Observe the loading window before the form appears.

**Paperclip version or commit**

Source baseline: `8b4ab65b1c3d863d282752e83307943720a5c85c`.

**Deployment mode**

The browser code applies to local and hosted boards. Verification used a
source checkout.

## What Changed

- Import NewIssueDialog with the board. Keep the existing mount and
draft lifecycle.
- Add a first-open test that fails if the form waits for an asynchronous
render.
- Cover text entry during delayed agent and project requests and
defaults that arrive later.
- Document the behavior and its verification recipe.

## Verification

- Regression proof: the first-open test failed before the import change
and passed after it.
- All 125 tests in BoardDialogs, DeferredOverlay, NewIssueDialog and
Layout passed.
- The production UI build and UI TypeScript check passed. The typecheck
passed with `NODE_OPTIONS=--max-old-space-size=2400` after the competing
test process was stopped.
- Token gates, map validation and Git diff checks passed.
- The first UI typecheck could not resolve the unbuilt local plugin SDK.
The SDK was then built.
- Full typecheck and build attempts hit the sandbox's 4 GB memory limit
when run with the full test suite. Two later UI typecheck attempts also
hit that limit during other validation. The cgroup recorded four OOM
kills in total. The full repository test attempt and a broader UI test
attempt were stopped. No complete suite result is claimed. Serial
repository typecheck reached the missing Rust `cargo` executable. Full
CI passed on head `9dde4bc`; local limits remain recorded here.
- First CI run at `e5a99b8`: typecheck, build, all unit-test shards and
seven browser shards passed. Browser shard 2 failed at
`chat-adapters-ui-providers.spec.ts:185`, waiting for Slack setup
Success after reload. The saved page showed the working connection and
Continue button. The cause is not confirmed; this failure is retained
for follow-up. [Failed
job](https://github.com/paperclipai/paperclip/actions/runs/39522214527/job/118968542923).
- Removed the added import comment after Greptile review. Head `9dde4bc`
changes only that comment. The review thread is resolved. Fresh CI
passed on head `9dde4bc`. Greptile reviewed that exact head at 5/5 with
no open findings. All eight browser shards passed, including the earlier
Slack failure. The earlier failure remains unexplained; the only
intervening code change removed a source comment. A passing retry
establishes recovery, not its cause.
- Component tests use mocked directory requests. No deployed latency or
browser persistence claim is made.

Latest CI: [run
39523376437](https://github.com/paperclipai/paperclip/actions/runs/39523376437).
Reviewed head: `9dde4bc0caa3556e315a2fc197268b7c9879efa4`.

## Risks

- Task dialog code is part of board startup again. This adds its
dependencies to the initial code graph. No startup latency benchmark is
claimed.
- Other creation dialogs retain their existing lazy imports and loading
behavior.

## Model Used

OpenAI Codex, GPT-6, with reasoning, repository tools and code
execution. The runtime does not expose a more precise model ID or
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-10-24 08:15:35 -07:00
DottaandPaperclip 87bf89756e fix: support Daytona runner upgrades and ignore obsolete Claude options (#17361)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Existing Claude and Codex agents can upgrade to Paperclip Runner.
> - A Daytona computer needs platform qualification before Runner
becomes its default.
> - The upgrade notice required that default, so it hid the action that
could start qualification.
> - Saved Claude turn limits also caused conversion to fail even though
Runner can run without them.
> - This pull request verifies the computer on click and ignores
obsolete Claude options with a warning.
> - Agents retain their model, account, environment, instructions, and
permission policy.

## Linked Issues or Issue Description

Related: #17122.

**What happened?**

A legacy Claude agent on a Daytona snapshot had no upgrade button until
its environment had platform qualification. A saved `maxTurnsPerRun:
1000` then caused conversion to return HTTP 422.

**Expected behavior**

The upgrade action verifies a supported Daytona computer and converts
the agent. Unsupported tuning options produce a visible warning and do
not block execution.

**Steps to reproduce**

1. Create a legacy Claude agent with `maxTurnsPerRun: 1000` on an active
Daytona snapshot.
2. Open Runtime before the environment has platform qualification.
3. Try to upgrade to Paperclip Runner.

**Paperclip version or commit**

After #17122, reproduced against `9c442cf48e`.

## What Changed

- Offer upgrade on probe-capable Daytona snapshots and immutable sandbox
images. Perform the public environment probe only after a click. Save
after fresh adapter discovery confirms support.
- Resolve the actual computer for explicit, instance-default, and hidden
managed environments. Preserve pending edits and reject stale probe
results.
- Ignore Claude `maxTurnsPerRun`, `chrome`, `warmHandleIdleMs`, and
`acpWarmHandleIdleMs`. Return structured warnings from create, hire, and
update. Show warnings in Runtime and after a save.
- Keep validation for commands, credentials, filesystem, network, and
permission settings.
- Retain the legacy turn limit in the existing live conversion fixture.
Update regression tests, upgrade stories, and capability maps.

## Verification

- Red: the old route returns HTTP 422 for the saved turn limit; the old
form hides the Daytona upgrade notice.
- Green: 417 focused server and form tests pass. A further 188 tests
pass after the review fixes. Qualification coverage includes failed
probes, unsupported targets, changed settings, managed defaults, unsaved
environment variables, and forced Kubernetes targets.
- `pnpm -r typecheck` and `pnpm build` pass. Token gates, map checks,
map tests, and Storybook catalog checks pass.
- Real local Claude Opus 5.5 conversion and task pass, with the
downloaded artifact checked against seeded source bytes, SHA-256, and
Git commit.
- Real browser upgrade and full Claude Opus 5.5 task on a disposable
named Daytona snapshot pass at `b81cec7d8c`. The saved agent retains its
model, high effort, credentials, timeout, and grace settings while
dropping the turn limit with a visible warning. Exactly one successful
run completed the task. The downloaded artifact matched independently
seeded source bytes, SHA-256, and Git commit; the source was unchanged,
no interactions remained pending, and the delivery link survived a
browser reload. The snapshot used current runtime assets built from
public source. The supplied Daytona account could not access the
original staging snapshot, so this verifies an equivalent local fixture
rather than that exact snapshot. Disposable test resources were cleaned
up.
- Earlier live attempts remain recorded: an image-based sandbox creation
failed, and the first named-snapshot probe returned failure with
unresolved provisional cleanup identity. Later named-snapshot probing
and the task succeeded; the initial creation failures are not attributed
to this PR or declared resolved. A separate attempt using the Oct 18
cached runtime failed the current provider-pack compatibility check;
rebuilding the runtime from matching public source removed that
mismatch. Owned resources were identified and cleaned up, with
diagnostic databases retained.
- 54 checks passed at `b81cec7d8c`, with no failed checks; Greptile and
Paperclip Review both scored 5/5, with both review threads resolved.
Master advanced during the live proof, so the branch was rebased with
both sides of additive import/test conflicts retained. On the rebased
head `2b74222b94`, 472 focused tests, UI typecheck, and UI build pass.
All required CI gates pass; Greptile and Paperclip Review both score 5/5
on this head, with no unresolved review threads. The PR is mergeable.
The serial local `pnpm test:run` was stopped after the CI test lanes
passed; that local run is not claimed as a pass.

## Risks

- An explicit upgrade can allocate a temporary probe sandbox and take
several minutes. Probe failures leave the agent on its existing runner.
- Ignored options no longer enforce a turn cap, Chrome integration, or
legacy idle-time tuning. The UI warns about each active ignored option.
- Unsafe or ambiguous execution settings still fail validation. This
change does not weaken environment qualification or runtime artifact
checks.

## Model Used

OpenAI Codex, GPT-6, with reasoning, code execution, and browser tools.
The exact deployment 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
- [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-10-24 07:59:18 -07:00
e0d90339bf fix(runner): make task-capable plugin environments Runner-only (#17380)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - An environment plugin can run Paperclip Runner tasks through a
`driver: "plugin"` environment.
> - Core lets only the `paperclip_runner` adapter use a plugin
environment.
> - A Claude agent cannot get onto the Runner there. Runner selection
needs a reported platform for Claude, and a plugin target reports none.
> - The adapter Test route also checks the driver against the requested
harness before it resolves the runner.
> - This pull request makes task-capable plugin environments Runner-only
and checks the Test driver after runner selection.
> - The benefit is that Claude and Codex agents can use a Runner task
environment, and the UI cannot produce a legacy agent there.

## Linked Issues or Issue Description

Refs #17029. Refs #16978.

**What happened?**

A Claude Code agent with a plugin environment that runs Runner tasks
fails the connection test. The error is: `Environment driver "plugin" is
not allowed here. Allowed drivers: local, ssh, sandbox`. The Runner
selector in Advanced shows Paperclip Runner as unavailable, so the user
cannot fix the agent in the form.

**Expected behavior**

A Claude or Codex agent on that environment uses Paperclip Runner. The
connection test passes the driver check. Legacy is not offered, because
a legacy adapter cannot run on a plugin environment.

**Steps to reproduce**

1. Install an environment plugin whose driver declares `supportsTasks:
true`.
2. Create a plugin environment for that driver.
3. Open an agent with the Claude Code harness and select that
environment.
4. Click Test. The test fails with the driver error above.

**Agent adapter(s) involved**

Claude Code, Codex (through Paperclip Runner).

**Additional context**

Two gates caused the failure:

- `agentRunnerAvailability` requires a platform for `claude_local`. A
plugin target is `{ driver: "plugin" }`, so Claude resolves to Legacy.
- The Test route ran `assertAdapterTestEnvironmentForCompany` with the
URL adapter type before `resolveNewAgentRunnerForCompany`. The plugin
driver is allowed only for `paperclip_runner`, so the check failed
before selection could change the adapter.

## What Changed

- Runner target resolution marks a plugin environment as `runnerTasks`
when its plugin manifest declares `supportsTasks` for the driver key and
has the `environment.drivers.register` capability. The check reads the
manifest only. Run admission still verifies a ready plugin and a live
worker.
- `agentRunnerAvailability` returns Paperclip Runner as the only runner
for a `runnerTasks` target. It skips the platform check, because the
plugin provisions the host and launches its own pinned Runner. Harnesses
that the Runner does not support keep the Legacy result.
- The adapter Test route runs the company-binding check first, as
before. It runs the driver check after runner selection, with the
resolved adapter type. The driver check still runs before secret
resolution, leases, and the adapter probe.
- A saved adapter that cannot run on the requested environment no longer
keeps its saved execution in the Test route. It re-resolves its runner.
- `assertAdapterTestEnvironmentBinding` is a new helper that holds the
binding half of the guard. `assertAdapterTestEnvironmentForCompany`
keeps its behavior and calls it.
- The agent form switches a Legacy runner choice to Paperclip Runner
when the selected environment offers no Legacy runner. The test and the
save then send the Runner choice.
- `docs/specs/agent-config-ui.md` records the Runner-only rule and the
Run test order.

## Verification

- `pnpm --filter @paperclipai/server exec tsc --noEmit` passes.
- `pnpm --filter @paperclipai/ui exec tsc -b` passes.
- Server suites pass: `agent-runner-selection.test.ts`,
`agent-test-environment-routes.test.ts`,
`agent-permissions-routes.test.ts`,
`environment-selection-route-guards.test.ts`,
`agent-harness-verification.test.ts`,
`plugin-runner-task.integration.test.ts`, `adapter-routes.test.ts`,
`adapter-auth-signal-routes.test.ts`,
`agent-adapter-validation-routes.test.ts`,
`agent-hire-ai-connections.test.ts`.
- UI suites pass: `AgentConfigForm.render.test.tsx` and
`NewAgent.test.tsx`.
- New tests cover these cases:
- A task-capable plugin target offers only Paperclip Runner for Codex
and Claude.
  - Claude saves as `paperclip_runner` with ACPX on that target.
- A driver without `supportsTasks`, a different driver key, a missing
capability, an unknown plugin, or a malformed config keeps the existing
plugin target.
  - The Test route checks the driver against the resolved adapter.
- The Test route still rejects a plugin environment for a legacy
adapter, before any secret resolution.
- A saved adapter re-resolves only when it cannot run on the requested
environment.
- The form switches a saved or new Legacy choice to Paperclip Runner on
a Runner-only environment.
- I ran the new route and form tests against the old code. They fail
without the change.
- The full server `typecheck` script did not complete locally. Its
Runner vendor step needs `cargo`, which this machine does not have. CI
runs the full script.
- I did not run a live plugin environment end to end.

## Risks

- Behavior change: Codex on a task-capable plugin environment now offers
only Paperclip Runner. Before, the selector also showed Legacy, but Core
rejected a legacy save on that environment. No working setup loses an
option.
- The `runnerTasks` decision reads the plugin manifest. If the plugin is
down, the agent still selects the Runner, and the run fails at admission
with the existing plugin error.
- The adapter auth-signal route still checks the driver with the
requested harness. This PR does not change that route.
- An explicit Legacy save through the API on a Runner-only environment
still fails with the existing driver error. The UI no longer offers that
choice.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`) wrote the change and the tests in
Claude Code, with shell, file editing, and local test runs.
- Claude Fable 5.1 (`claude-fable-5-1`) did the earlier diagnosis in the
same session.
- The session 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
- [ ] 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

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 15:21:09 -07:00
73526559b5 fix(ui): reload once when a lazy chunk or its CSS fails to load (#17349)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The board UI loads each page as a lazy chunk. Vite adds a preload
step that also loads the CSS of the chunk.
> - Staging error monitoring reported `Unable to preload CSS for
…/assets/issue-detail-CIbQo9zW.css`. The same file name comes from the
current build, so the CSS did not change. One request for the file
failed for a short time.
> - Vite rejects only the first import that asks for a failed file.
Later imports skip that file. On a task page, the first import is the
task-page prefetch, which ignores errors. The page then shows without
its CSS. On other pages that share the CSS, such as Agents, the lazy
route rejects and the route error boundary shows the error.
> - Neither case recovers without a manual reload. This is a routine
retry that the app can do safely, so the app must do it.
> - This pull request reloads the page one time when a chunk or its CSS
fails to load. A loop guard limits this to one reload in five minutes.
> - The benefit is that a stale tab after a deploy, or one failed asset
request, recovers without an error page, without missing styles, and
without error-monitoring noise. An asset that stays broken still shows
the error and still sends a report.

## Linked Issues or Issue Description

**What happened?**
A board page showed "This page hit an error" with `Unable to preload CSS
for <origin>/assets/issue-detail-<hash>.css`. On a task page, the same
failure gave no error message, but the page showed without its
stylesheet.

**Steps to reproduce**
1. Build the UI and start the server.
2. Make the first request for `/assets/issue-detail-*.css` fail. The new
Playwright spec does this with `page.route(...).abort("failed")`.
3. Open `/<prefix>/agents`. The route error boundary shows "Unable to
preload CSS".
4. Open `/<prefix>/issues/<id>`. The task shows, but the browser does
not request the task CSS again. The page has no task-page CSS.

**Expected behavior**
The app recovers from a chunk or CSS load failure without user action.
If the failure continues, the app shows the error one time, with no
reload loop.

**Environment**
Hosted staging browser. The local build of current `master` reproduces
it.

I searched open and closed PRs for `preload`, `preloadError`, and `stale
chunk`. I found no related PR.

## What Changed

- `ui/src/lib/chunk-load-recovery.ts` (new): `isChunkLoadError` matches
the Vite CSS preload error and the dynamic import errors from Chromium,
Firefox, and WebKit. `reloadForChunkLoadError` reloads one time. A
`sessionStorage` marker blocks a second reload for five minutes. After
the first reload, later chunk errors in the same document are part of
that reload, so they return "reloading" and do not show an error.
Without `sessionStorage`, the function does not reload, because it
cannot guard against a loop. `startChunkLoadRecovery` listens for
`vite:preloadError`. It does not cancel the event, so the import still
rejects as before.
- `ui/src/main.tsx`: Starts the listener before the first render. The
listener covers every import, including the task-page prefetch that
ignores errors.
- `RouteErrorBoundary` and `AppErrorBoundary`: While a recovery reload
runs, they show a loading state. They do not show the error page and do
not report to Sentry. Other errors work as before.
- Tests: Vitest unit tests for the helper and both boundaries. A new
Playwright spec, `tests/e2e/chunk-load-recovery.spec.ts`, runs against
the real server and the built UI.

## Verification

- `pnpm --filter @paperclipai/ui exec vitest run
src/lib/chunk-load-recovery.test.ts
src/components/RouteErrorBoundary.test.tsx
src/components/AppErrorBoundary.test.tsx`: 21 tests pass.
- Full UI Vitest suite: 793 files, 9,075 tests pass.
- `pnpm --filter @paperclipai/ui typecheck` passes. `node
scripts/check-token-gates.mjs` is clean. `node scripts/check-maps.mjs`
passes.
- `npx playwright test --config tests/e2e/playwright.config.ts
chunk-load-recovery.spec.ts`: 3 tests pass.
- Task page with one failed CSS request: one reload, the CSS loads, and
the task shows.
- Agents page with one failed CSS request: one reload, the CSS loads,
and the page shows with no error page.
- CSS that always fails: one reload, then the error page shows. There is
no second reload.
- Red proof: I ran the same spec with the `ui/src` changes removed
(current `master` UI code). Both recovery tests fail. On Agents, the
route error boundary shows `Unable to preload CSS for
http://127.0.0.1:3199/assets/issue-detail-CIbQo9zW.css`. On the task
page, the CSS is never requested again.
- A failure I found and fixed during the work: my first version changed
only the error boundaries. The task-page e2e case failed with that
version, because the prefetch received the error and the boundary never
saw it. The `vite:preloadError` listener fixes that case. All results
above are from the final commit.
- The spec blocks service workers, because Playwright page routes cannot
see requests that a service worker sends. With a worker, a failed
network request for an asset that is not cached also gives
`Response.error()`. Thus the preload error is the same.

## Risks

- A page can reload while a user is on it. This occurs only after a
chunk or CSS load failure, and at most one time in five minutes per tab
session. Without this change, that page already shows an error or shows
without styles. Composer drafts use browser storage, so a reload keeps
them.
- A failure that recovers no longer sends a Sentry event. A failure that
continues after the reload still sends one, so a broken deploy stays
visible.
- The error patterns match browser and Vite message prefixes. If a
browser changes its message, that browser goes back to the current
behavior: the error page and a report.
- No API, schema, or server changes.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`) by Anthropic, run as a Paperclip
agent through Claude Code with tool use (shell, file edits, Playwright,
and Vitest).

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

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com>
2026-10-23 12:06:38 -07:00
93d26eb84e feat(ui): link routine-created tasks back to their source routine (#16471)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Routines create tasks on a schedule. Each task records its source in
`originKind = "routine_execution"` and `originId = <routine id>`.
> - The issue Properties card shows Relationships such as Parent. It
does not show the routine that created the task.
> - An operator who reads a routine-created task cannot go to the
routine from the task. They must find the routine by hand.
> - This pull request adds a "Routine" row under Relationships, below
Parent. The row links to the source routine.
> - The benefit is a direct path from a routine-created task to the
routine that made it.

## Linked Issues or Issue Description

Refs #9727. That PR adds a general provenance model and an "Origin"
chip. It also links routine executions to the routine. It is much larger
(DB migration, server, plugin SDK). It has merge conflicts and no
updates since August. This PR is a small UI-only change with no schema
or API change. If #9727 merges later, the two rows can be merged into
one.

**Is your feature request related to a problem?**
A task that a routine creates has no visible link back to that routine
in the Properties card.

**Describe the solution you'd like**
Show a "Routine" row under Relationships for routine-created tasks. The
row shows the routine title and links to `/routines/:id`.

**Describe alternatives you've considered**
A generic "Origin" row for all origin kinds (the #9727 approach). That
needs new server data for most kinds. A routine link needs only data
that the issue already has.

## What Changed

- Add `ui/src/components/issue-properties/routine-origin-row.tsx`
(`RoutineOriginRow`). It reads the routine with the same
`queryKeys.routines.detail` query as the routine page, so the cache is
shared.
- Show the row in `IssueProperties.tsx` after Parent, only when
`originKind === "routine_execution"` and `originId` is set (+5 lines).
The new component is in its own file because `IssueProperties.tsx`
already has more than 3,000 lines.
- States:
- Routine found: an outline chip with the repeat icon and the routine
title. The chip links to the routine page.
- Routine still loading, routine deleted (404), or any other lookup
error: no row. The card never shows an empty Routine field.
  - Task not created by a routine: no row. No routine request is sent.
- Add 4 tests in `IssueProperties.test.tsx`: routine found, routine
loading, routine deleted, and task not created by a routine.

## Verification

- `pnpm --filter @paperclipai/ui exec vitest run
src/components/IssueProperties.test.tsx`: 94/94 pass.
- `vitest run src/pages/IssueDetail.test.tsx
src/components/TaskSidePanel.test.tsx` (other surfaces that render the
panel): 195/195 pass.
- `node scripts/check-token-gates.mjs`: all gates clean.
- `tsc --noEmit` in `ui`: no errors in the changed files. Other errors
came from workspace packages that were not built locally
(`@paperclipai/plugin-sdk/ui`, generated storybook catalog JSON). This
change does not touch them.
- Manual check: open a task that a routine created. Find the "Routine"
row under Parent. Click it. The routine page opens.
- Not run locally: full `pnpm -r typecheck`, `pnpm test:run`, `pnpm
build`, and a browser check. CI runs these.

## Risks

- Low risk. The change is UI-only and additive. It has no schema, API,
or contract change.
- Each routine-created task view sends one extra `GET /routines/:id`
request. The routine page uses the same cache key, so the response is
often cached already.
- The row appears only after the routine request finishes. On a cold
cache, it shows up a moment after the rest of the card.
- If the routine is deleted or the user cannot read it, the task shows
no Routine row. The task still records `originKind`/`originId`.

> 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

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`) in Claude Code, with
tool use (shell, file edit, test execution). Standard 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

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Devin Foley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 10:20:58 -07:00
DottaandPaperclip fbaf3c6ed2 feat(onboarding): connect a custom AI gateway (#17253)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - A person must connect an AI account when they set up the first
agent.
> - The existing connection form supports custom Responses and Messages
gateways.
> - First-agent onboarding does not expose that form or its saved model
list.
> - A person who uses a custom gateway cannot complete this setup
through the normal controls.
> - This pull request adds the existing gateway form to onboarding and
requires a model before Connect.
> - The person can save the account first, then choose Connect to test
the environment and hire the agent.

## Linked Issues or Issue Description

Refs #14104. This addresses the missing custom endpoint option during
first-agent onboarding.
Refs #15103. That issue also covers other adapters and the separate New
Agent wizard.

Related source review:

- Refs #15884. That proposal adds a Local LLM source, changes
private-network HTTP validation, and uses OpenCode. This change uses
existing gateway routing and preserves the explicit environment test
before hire.
- Refs #14006. That proposal adds new providers and connection methods.
This change uses the existing OpenAI and Anthropic managed connection
contracts.

**What existing behavior does this improve?**

The API-key step of first-agent onboarding for Codex and Claude.

**Current behavior**

The wizard accepts a direct provider key but does not expose custom
gateway setup or the saved gateway model list.

**Proposed behavior**

Choose Use a custom gateway. Save its URL, key, and models through the
existing connection form. Select a saved model. Choose Connect to run
the normal environment test and hire the agent with the managed
connection binding.

**Reason and benefit**

People can complete onboarding with an existing custom gateway. They can
save the connection before any agent test starts.

**Breaking changes**

No API, database, or routing schema changes. The new path applies to
Codex and Claude API-key setup. Existing direct-key setup remains
available.

## What Changed

- Add a small onboarding dialog that reuses `AiProviderSetup` for
Responses or Messages gateway connections.
- Let the shared setup form use Save connection as its submit label in
this dialog.
- Bind the saved account to the current company and adapter. Clear its
selection when the person changes companies or chooses another API key.
- Load the saved connection's models. Require a model before Connect can
test the environment and hire the agent.
- Show a loading state, a visible error, and Retry loading connection
when the saved connection lookup fails. Reuse the shared lookup cache
and preserve the model hook contract for existing consumers.
- Cover saving, model selection, delegated account use, secret exclusion
from drafts and hire payloads, and Cmd+Enter in the gateway dialog.

## Verification

- Focused UI verification: `pnpm --filter @paperclipai/ui exec vitest
run src/components/OnboardingWizard.test.tsx
src/components/ai-connections/AiProviderSetup.test.tsx` — 187 tests
passed across two files.
- The first focused attempt had one test-only failure because its
fixture lacked `TooltipProvider`. The fixture now supplies that
provider. The complete focused run then passed all 187 tests.
- The new test confirms that saving the connection and pressing
Cmd+Enter in its dialog do not call the adapter test or hire API.
Connect remains disabled until model selection. Connect then uses the
selected model and managed connection for both test and hire.
- Rebased onto `origin/master` at
`042051904d368f5514e287e5ca8e404dc8f78a0d`. The two focused UI files
passed all 187 tests again on the rebased tree.
- UI typecheck passed on the rebased tree. The first attempt found
missing generated Plugin SDK declarations in the fresh worktree. `node
scripts/ensure-plugin-build-deps.mjs` built the local shared and SDK
artifacts. The Storybook catalog check and `tsc -b` then passed.
- Reused installed third-party packages from the unchanged lockfile.
Worktree-local workspace links pointed at the rebased source. No older
workspace source was substituted.
- The full token gate checks and `git diff --check` passed in this
isolated worktree.
- An earlier wider local repository run failed in a chat-channel test.
That failure was not investigated in this isolated UI follow-up and
remains part of the verification history. The complete CI suite for this
PR later passed on the reviewed commit. Deployed gateway acceptance has
not been run.
- Review follow-up: reproduced the failed saved-connection refresh
before the fix. The new test failed because the page did not show the
lookup error. The page now shows the error and Retry loading connection.
Connect stays disabled until lookup and model selection succeed.
- The new failure-and-retry test uses separate response objects so cache
mutation cannot hide a failed refresh. It also proves that save and
retry do not probe or hire an agent.
- The expanded regression initially needed a corrected mock return type.
After that correction, all 199 tests passed across OnboardingWizard,
AiProviderSetup, and useConnectionModels. UI typecheck, all token gate
commands, and `git diff --check` passed.
- The review fix is pushed at
`12b4e9cb8528ba44af377315ba39fe3fbccae7bd`. All 53 active CI and
security checks passed on that exact head. Two Storybook checks were
skipped. Greptile completed with 5/5, and there are no unresolved review
threads. The earlier local chat-channel failure remains recorded above.
- No live Cloud gateway campaign or candidate deployment has been
completed for this product change.

## Risks

- Gateway setup adds a nested dialog inside onboarding. Its key events
must not submit the parent wizard. The Cmd+Enter regression test covers
this boundary.
- A saved connection can offer no model list. That state permits an
explicit model ID and still requires selection before Connect.
- Saving a connection proves that it was stored. The normal Connect
action remains responsible for runtime validation. A successful mocked
UI test does not prove gateway reachability from a deployed runtime.
- `ROADMAP.md` already includes personal and shared AI accounts and
multi-model teams. This is a scoped extension of those capabilities. It
does not add a provider, a protocol, or wider URL access.

## Model Used

OpenAI Codex, GPT-6 family. The exact deployment model ID and context
window are not exposed in this session. The agent used reasoning, tool
use, code editing, and local test execution. No unverified model ID or
context size is claimed.

## 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
- [ ] 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-10-23 06:26:39 -07:00
Devin FoleyandPaperclip c5ca29dbef fix(claude): prepare compatible sandbox runtimes during onboarding (#17259)
## Thinking Path

> - Paperclip connects agent accounts and prepares their execution
environments.
> - A managed sandbox image can outlive the model defaults shipped by
the app.
> - Claude setup skipped installation whenever a CLI was already on
PATH.
> - The selected model then failed its minimum-version check after
sign-in succeeded.
> - This pull request prepares a compatible private CLI before testing
or running it.
> - Cloud onboarding also stops asking customers to run inaccessible
shell commands.

## Linked Issues or Issue Description

**What happened?**

A new managed Cloud stack completed Claude subscription sign-in. Its
environment test then failed because the snapshot contained Claude Code
2.1.263, while the selected `claude-opus-5-5` model requires 2.1.280.
The screen displayed Manual debug commands that a hosted customer cannot
run.

**Expected behavior**

Paperclip prepares its managed runtime before testing the selected
account. A stale image CLI does not require the customer to upgrade a
server package. Failed preparation still blocks hiring. Cloud does not
display manual shell debugging.

**Steps to reproduce**

1. Start a managed sandbox with Claude Code 2.1.263 on PATH.
2. Connect a Claude subscription and select `claude-opus-5-5` on the CLI
lane.
3. Connect the agent. Installation is skipped because the command
exists, then the version gate blocks the hello test.

**Paperclip version or commit**

Source baseline: `6204239cfc8c3be79fc185cf3f468ebaa0ab1e3e`.

**Deployment mode**

Authenticated managed Cloud with a Daytona named snapshot. The
correction also applies to the default CLI in other managed sandbox
transports.

Related work: Refs #14993 sets model/runtime requirements; Refs #15993
changes native defaults on qualified targets. Neither prepares an
outdated default sandbox CLI on this path. Searches found no open
duplicate.

## What Changed

- Check the actual default CLI against the selected model's existing
minimum version.
- When a sandbox's default command is outdated, install the exact
required npm package into a private versioned workspace prefix. Reuse a
compatible private installation. Keep the image's global CLI intact.
- Verify the private executable and use that same command for the
account hello test and normal CLI runs, with matching command metadata.
Probe effort support after preparing that executable so the chosen
effort is retained. Keep the model, account, engine and permissions
unchanged.
- Return safe preparation checks to environment tests and normal run
logs, distinguishing installation failure causes without returning raw
installer output or credential-bearing URLs.
- Exclude provider and Paperclip credentials from the installer
environment. Preserve the existing failing version gate if installation
or verification cannot succeed. Local, SSH and explicit custom commands
remain operator-managed.
- Hide Manual debug and legacy operator check hints on Cloud and while
deployment metadata is unknown; preserve check messages and details.
Retain self-hosted help and the detailed failed checks. Cloud copy asks
for a retry instead of asking the customer to repair the environment.
- Add subprocess-backed runtime controls, an account-probe regression
and mounted Cloud/self-hosted wizard controls. Update development
guidance and the affected capability maps.

## Verification

- Passed all Claude source suites and the server Claude execution suite
on head `c941ae44c22d8dafec0df033a129e39ce4ebd966`: **412 passed**, one
existing opt-in test skipped. These include the new command/effort
ordering, safe installer diagnostics, environment forwarding and run-log
regressions.
- On final head `0ecae0e9304f495a57524158b3700b8e9bc21cb8`, passed **208
tests** across all 174 mounted onboarding wizard tests and 34 Claude
execution tests. The failure fixture includes the real command-bearing
hint, and execution asserts both metadata command fields agree.
- Passed `pnpm -r typecheck`, `pnpm build`, `pnpm check:token-gates`,
`node scripts/check-maps.mjs` and `git diff --check`. Full typecheck and
build were repeated successfully on final head
`0ecae0e9304f495a57524158b3700b8e9bc21cb8`. [Latest-head
CI](https://github.com/paperclipai/paperclip/actions/runs/39879208694)
is green: 54 checks passed and two skipped, including browser E2E and
serialized database suites.
- The new runtime controls execute real subprocesses with a controlled
installer. They cover an old CLI, an already compatible CLI, failed or
ineffective installation, local/custom commands, and an unknown version.
The probe regression asserts that the hello call uses the private
executable.
- A separate non-root local subprocess check installed the real npm
`@anthropic-ai/claude-code@2.1.280` package. Its private command
reported 2.1.280, the simulated image CLI remained 2.1.263, and a second
preparation reused the private copy. This ran on macOS ARM64. It did not
use a provider account, send a model prompt, or prove live Daytona
behavior.
- Attempted `pnpm test:run`. Embedded PostgreSQL initialization failed
after five attempts on this Mac with `Postgres init script exited with
code null`. The unchanged native-session database cases then failed.
Stopped only that full-suite process tree after recording the repeated
startup failure. No full local-suite pass is claimed; Linux CI must
cover those tests.
- The first new subprocess fixture had a quoting syntax error. It was
corrected before the passing focused runs. The one-off real-package
script first required an ESM extension correction, then passed. Logs
retain both attempts. A new execution assertion initially inspected the
final sandbox cleanup shell instead of the launched command; it now
checks execution metadata. A broader directory selection also picked up
generated `dist` tests whose Markdown fixtures are not copied by the
build (two ENOENT failures). The explicit source-suite run above passes;
no generated-test pass is claimed.
- Apex review: **5/5**, reviewed final head
`0ecae0e9304f495a57524158b3700b8e9bc21cb8`, all five earlier findings
addressed and resolved, no new findings.
- Merge, deployment and a fresh live Cloud subscription test are still
required. No customer account or production runtime was changed by this
branch.

## Risks

- An outdated sandbox needs npm registry access and up to 120 seconds
for one bounded installation attempt. A failed or unverified install
continues to block execution.
- The versioned package uses sandbox workspace storage. Compatible
cached copies avoid repeat installation within that workspace. Existing
runtime cleanup and sandbox lifecycle still apply.
- The compatible version comes from the adapter's existing model-version
contract. This does not add a model fallback or change the selected
execution engine.
- No schema, credential, permission, workflow or lockfile change.

## Model Used

OpenAI Codex, based on GPT-6, assisted with implementation and
verification. The exact serving model ID and context-window limit are
not exposed in this session. Capabilities used: code editing, shell
execution, API inspection and test execution.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-22 18:44:53 -07:00
Nicky LeachandPaperclip 6204239cfc Support installed default project workspace providers (#17247)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Storage plugins already own project storage and task checkout
preparation.
> - Core only selected these plugins through an explicit project policy.
> - Installation could therefore leave new and existing projects on
incompatible Core preparation.
> - This pull request adds one generic manifest declaration and one
shared effective-policy resolver.
> - Project configuration shows inheritance while durable workspace
bindings retain their owners.

## Linked Issues or Issue Description

**Subsystem affected**

Plugin contracts, project configuration, and execution workspace
preparation.

**Problem or motivation**

An installed storage provider cannot become the company default.
Projects without an explicit provider keep Core preparation, even when
their execution environment cannot use a Core Git checkout.

**Proposed solution**

A provider declares supported `workspaceProvider.defaultForProjects`
mode and strategy. Company-enabled installations supply inherited
defaults. Explicit plugin selections and explicit Core/local
(`storageProviderPluginId: null`) win. Conflicting defaults require an
operator choice. The declaration and implementation contain no
provider-specific identifiers.

**Alternatives considered**

Rewriting every project would lose the distinction between inheritance
and overrides. Selecting by worker health would silently change storage
on an outage.

**Roadmap alignment**

Extends the existing workspace and sandbox provider contracts. The
roadmap has no duplicate default-provider implementation. Related public
work includes #17243, which covers prepared execution directories rather
than provider selection.

## What Changed

- Add a validated generic default-provider declaration and document it
in the SDK.
- Resolve provider selection and Git defaults consistently in project
responses, source selection, heartbeat source resolution, reservation,
and preparation.
- Keep stored policy separate from effective configuration. Add the
normal project configuration selector for inheritance, explicit plugins,
and Core/local.
- Preserve existing local and plugin workspace ownership. Pin selection
through preparation and keep provider failures visible.
- Add database, API, manifest, heartbeat, and UI regressions. Update the
verification maps.

## Verification

- Targeted Vitest runs cover manifest validation, project defaults and
API access, explicit overrides, existing ownership, new/imported task
inheritance, heartbeat routing, source-free tasks, selection pinning
during setup, and UI configuration.
- Combined policy, provider integration, and heartbeat run: 58 tests
pass; 60 unrelated cases excluded. After the final shared-provider
fallback fix, all 47 policy tests pass, including shared and
operator-mode regressions.
- Server and UI TypeScript checks, SDK build, verification-map
validation, credential-pattern scan, added-comment scan, and `git diff
--check` pass.
- A downstream integration uses this Core resolver and preparation
service with a real storage hook and mocked remote infrastructure. A new
Git project reaches the hook without a stored provider ID.
- Standard Greptile and Apex both scored 5/5 on
5d42998466. All review threads are
resolved.
- Final GitHub CI is fully green on
5d42998466. Browser shard 3 initially hit
a PostgreSQL deadlock during cleanup cancellation, which left an
experiment flag enabled for a later test. A failed-job retry passed all
26 browser tests. The workflow completed successfully on attempt 2. Full
final verification was delegated to CI at the user's request.
- No live provider or hosted tenant run was performed.

## Risks

- Installing one default-claiming provider changes effective selection
for unconfigured projects. Existing explicit settings and workspace
ownership remain intact; incompatible explicit settings fail clearly.
- Each configuration/admission resolution reads installed plugin
metadata and the selected company's enablement. Project list reads share
one catalog query. Selection does not call workers or external
providers.
- Deploy the Core contract before any downstream manifest uses the
declaration. No migration or backfill is required. A downstream
immutable image pin must include this change before packaging its
declaration.
- No merge or deployment is authorized by this PR.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, and code
execution. The exact served 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 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
ticket id
- [x] I have run targeted tests locally and they pass; full gates are
delegated to CI at the user's request
- [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 on
5d42998466ad42400564ba34f48124f40c53fbc5; the branch has no merge
conflicts
- [x] Standard Greptile is 5/5 on 5d4299846 after all fixes, with no
unresolved threads
- [x] Apex is 5/5 on 5d42998466, after
standard Greptile 5/5 on that same head
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-22 17:12:29 -07:00
DottaandPaperclip 9bf7dc0c8f feat(agents): bulk edit connections and default models (#17215)
Add harness-scoped bulk connection and default-model edits to the agent roster, with compatible choices, change previews, per-agent save results, and retries.

Use an icon-based harness filter, keep agent rows readable, remove the status selector and selection hint, and redirect legacy status URLs to the full roster.

Preserve authorization, audit history, unrelated settings, and optimistic concurrency checks through the existing agent update route.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-22 18:47:06 -05:00
Dotta 46760cc588 fix(chat): honor dismissal for all composer requests (#17218)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task conversations show requests in the feed and above the message
composer.
> - Earlier fixes kept dismissed questions in history, but excluded
completion reviews and other request kinds.
> - Closing those forms left a pending badge, and the server could still
demand a response.
> - This pull request saves human dismissal and removes the request from
composer reminders and ordinary completion gates.
> - People can continue the conversation and reopen the request from
history.

## Linked Issues or Issue Description

Related work: #15229 and #15392.

**What happened?**

Dismissing a completion review closed its form but left it counted as
pending. It could return after reload, block a retry, or cause the agent
to demand another response. Raw runtime requests could also lose their
only usable control when dismissed.

**Expected behavior**

Dismissal leaves an accessible request in the feed and clears the
composer form and pending count. It persists after reload. It does not
submit an answer, approve an action, or wake the agent.

**Steps to reproduce**

1. Open a task with a pending completion review or another composer
request.
2. Dismiss the request, then reload the task.
3. Check that the composer stays clear and the feed entry can reopen the
request.

## What Changed

- Add nullable dismissal fields and a human-only dismissal endpoint with
company, private-task access, resolver, and locked review-policy checks.
- Persist saved-request dismissal on the server. Keep browser
persistence for raw runtime requests and existing question dismissals.
- Keep confirmations, choices, item verdicts, suggested tasks, and
runtime requests accessible in the feed.
- Exclude dismissed ordinary requests from completion and retry gates.
Tell agents not to repeat deferred requests.
- Preserve tool, secret, connection, plan, company-policy, and
configured review authorization gates. Expire deferred non-question
requests when their task completes.
- Preserve the selected form when another dismissal finishes saving.
Keep reopened reviews visible through delayed comment refreshes.
- Add a completion-review Storybook test drive and update design, API,
database, and capability documentation.

## Verification

- `pnpm -r typecheck`: passed. The final UI changes also passed the UI
typecheck.
- `pnpm build`: passed. The final UI changes also passed the UI
production build.
- Focused UI and transcript tests: 550 passed across nine files after
merging the current base branch.
- Focused database, completion, and prompt tests: 105 passed across
three files, including two review-policy regressions that failed before
the fix. The tests reject a review requester excluded by current policy,
preserve the pending gate on denial, and permit an independent reviewer
to defer the request.
- Route regression suite: 81 passed, including denial before reading or
mutating a private-task request.
- `pnpm check:token-gates`: passed.
- Map and Storybook structural checks: passed; 30 map/catalog script
tests passed.
- Browser: used the production task-thread components in the
completion-review fixture. Dismissed, reloaded, reopened from the feed,
and dismissed again. No pending badge or composer takeover remained.
Story callbacks simulate API saves; separate server tests cover
persistence and permissions.
- `pnpm test:run`: stopped after the general-server group reported one
failure in `workspace-runtime.test.ts`: "returns a bounded structured
conflict and exposes only same-company workspace references". The same
test passed in isolation (1 passed, 178 skipped). The cause of the
full-suite failure is not established. The full PR CI suite subsequently
passed on e243cbb001; its two authorization review findings are fixed in
9e1b4478b3. Fresh [full
CI](https://github.com/paperclipai/paperclip/actions/runs/39871944846)
passes on 9e1b4478b3, including the previously failing server and
browser shards. All 54 executed checks passed; two optional Storybook
deployment/visual jobs were skipped. The legacy security status also
passed. Fresh Greptile review is 5/5, the security scan passes, and no
review threads remain open. This full CI run settles the merge gate; the
earlier local workspace-suite failure remains recorded above because its
cause was not established.
- Additional verification: the original failing browser journey passed
locally after the delayed-refresh fix. The expanded page-reload case
also passes on 9e1b4478b3 (52.7s): dismiss, reload, reopen, approve, and
receive the actual tool failure in the continuing task. It exposed a
fixture reading an accepted request before tool execution finished; the
fixture now waits for a stored execution result. The first reload
attempt stopped on a still-loading page at the default five-second
assertion; the reload now uses the suite’s navigation allowance. A
controlled server-restart run timed out waiting for server health before
the UI assertions. Local route-suite runs timed out during concurrent
module loading; sequential imports passed all 81 tests, including the
privacy regression.
- Initial verification failures: a missing SDK build and a story fixture
type error were fixed. PostgreSQL bootstrap then failed because the host
had exhausted its semaphore allowance. After explicit operator approval,
64 verified abandoned PostgreSQL semaphore sets were reclaimed; no live
process was stopped. The database regressions then passed. The
raw-runtime regression exposed a missing feed control; the
implementation now preserves that entry and the regression passes.

## Risks

- Apply the additive database migration before the new server code. It
adds two nullable columns and does not change existing decisions.
- A dismissal is shared task attention state. Only a human with task
read access and current resolver/review authority can persist it. Review
policy is checked under the task lock. The operation is idempotent and
records the dismissing user.
- Raw runtime dismissal remains specific to a browser. Saved interaction
dismissal persists across browsers.
- A deferred review is not an approval. Tests retain protected-action
and configured review gates.
- The browser walkthrough uses a fixture. This branch has not been
deployed to a live instance.

## Model Used

OpenAI Codex, GPT-6, with code execution and browser tools. The exact
backend 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
- [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-10-22 18:37:36 -05:00
TonioandClaude Fable 5.1 341b622604 feat(ui): Artifacts V1 behind an experimental setting — Artifacts page, panel tab and task thread (#17228)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents produce artifacts: documents, files, pictures, video and
links. The app shows them on the Artifacts page, in the right panel's
Artifacts tab and in the task thread
> - The artifact directions lab (#17213) settled a presentation for
those surfaces, MVP V1, drawn from the PCLP-Core mocks. It is a
reference, not product code
> - Shipping it means product components on product data, token-only,
behind a switch, one surface at a time, so the current presentation
stays the default until the new one has been used
> - This pull request adds the switch (Settings > Experimental >
Artifacts V1), the `--artifact-*` tokens, the V1 primitives as product
components, and the V1 presentation on all three surfaces behind the
switch: the Artifacts page, the panel's Artifacts tab and the task
thread
> - The benefit is the redesign in the product, reversible by one
setting, with every existing behaviour of those surfaces kept

## Linked Issues or Issue Description

No public issue exists. This section follows the feature request
template; the plan is `doc/plans/2026-10-22-artifacts-mvp-v1.md`.

**Subsystem affected**

The web UI (`ui/`): the Artifacts page, the right panel's Artifacts tab
and the task thread. The experimental settings contract in
`packages/shared` and `server` gains one boolean.

**Problem or motivation**

The three artifact surfaces grew separately and their artifact
presentation is dated and inconsistent. The lab produced a measured
direction; nothing in the product uses it yet.

**Proposed solution**

An experimental setting, `enableArtifactsV1`, default off, with the same
plumbing as the other experimental settings. Product primitives under
`ui/src/components/artifacts/v1` (kind helpers and adapters, the sheet
and print artwork, the stack, the page tiles with the Paper Mono pill,
the row the panel and thread will share), driven by `--artifact-*`
tokens in `index.css` with light and dark values. With the setting on:
the Artifacts page shows one row of views (Tasks, All files, Images,
Videos, Documents, Text, Files) and the V1 tiles, a task with several
artifacts as a stack whose newest artifact is the first page, everything
else as single tiles; the panel's Artifacts tab is one flat list of V1
rows, newest first, with the expandable rows (Markdown review surface,
document annotations, deep links) keeping their behaviour behind the row
as their face; the thread shows a message's files as rows under its
footer and registered deliverables and documents as one row each. The
hover movement respects reduced motion.

**Alternatives considered**

Replacing the current cards outright: no fallback and three surfaces to
land at once. Mounting the lab's components: they are typed on lab
fixtures and keep lab-local tokens, which the token gates reject. The
primitives were ported instead and the lab stays a reference.

**Roadmap alignment**

Supports the "Artifacts & Work Products" theme in `ROADMAP.md`.
Presentation only; no data model change.

**Additional context**

No new API fields: the tiles show title, identifier, count and "Updated
…"; rows take sizes from the work-product and attachment payloads; a
picture's aspect ratio comes from the loaded image, 4:3 until it loads.
The plan records what each surface keeps and what it drops (run sections
in the panel; the "Images · N / Files · N" labels and the four-up grid
in the thread).

## What Changed

- Add the `enableArtifactsV1` experimental setting: shared type,
validator and feature catalog, server defaults and managed keys, the
`useArtifactsV1Enabled` hook, and the Settings > Experimental toggle (in
its alphabetical place).
- Add the `--artifact-*` tokens and the Artifacts V1 component rules to
`ui/src/index.css`: light values on `:root`, dark overrides, and the
hover movement under `prefers-reduced-motion: no-preference`.
- Add `ui/src/components/artifacts/v1/`: `kinds.ts` (kind treatment,
labels, glyphs, the server's media-kind rule, adapters from
`CompanyArtifact`), `geometry.ts` (the measured constants), `when.ts`,
`ArtifactSheet`, `ArtifactPrint`, `ArtifactStack`, `ArtifactFront`,
`ArtifactTile` (stack and single tiles, caption, grid), `ArtifactRow`
(the row and its inline group), `ArtifactsV1Filters`, with the mock's
SVG assets.
- Wire the Artifacts page: with the setting on, the toolbar's filter row
becomes the V1 views and the grid renders V1 tiles; the toolbar takes an
optional `filters` row for this. The old cards and kind filters stay the
default.
- Wire the panel's Artifacts tab (`IssuePropertiesArtifactsTab`): with
the setting on, one flat list of V1 rows, newest first; `DocumentRow`
and `MarkdownWorkProductRow` take a `face` render prop so the V1 row
fronts their unchanged expansion, review and deep-link behaviour;
`PanelFileRow` opens attachments and attachment-backed work products the
way the shipped card does (gallery, text tab, new tab) with open and
download beside the name; other work products are a link row with their
status.
- Wire the task thread: `TaskChatBubble` hangs a message's files under
its footer as V1 rows inline (pictures and video to the gallery, text to
a text tab, files to a new tab) in place of the media grid and file
chips; `TaskChatProtocolCard`'s resource rows render deliverables,
documents and attachments as one V1 row each, opening where the card
did.
- `ArtifactRow` keeps trailing controls beside its own control (no
nested interactive elements) and can be a link, an in-app anchor, a
new-tab anchor or a button; adapters read work products, documents,
attachments and message references.
- Add a catalogued Storybook story, `Components/Artifact V1 primitives`,
under `documents-artifacts`, on fixtures.
- Add tests: the primitives (kinds, dates, print fitting, tiles, rows),
the hook, the Artifacts page, the panel's Artifacts tab, the task-chat
bubble and the protocol card, each with the setting on and off; the
settings page and server tests list the new key.
- Add `doc/plans/2026-10-22-artifacts-mvp-v1.md`.

## Verification

- Run `cd ui && pnpm typecheck`: the Storybook catalog accepts the new
story, and `tsc -b` is clean apart from the five pre-existing
`PluginOrganizationSwitcher` errors.
- Run `pnpm check:token-gates` and `node scripts/check-maps.mjs`: clean.
- Run `cd ui && npx vitest run src/components/artifacts
src/components/issue-properties
src/components/task-chat/TaskChatBubble.test.tsx
src/components/task-chat/TaskChatBubble.artifactsV1.test.tsx
src/components/task-chat/TaskChatProtocolCard.test.tsx
src/components/task-chat/TaskChatProtocolCard.artifactsV1.test.tsx
src/pages/Artifacts.test.tsx src/hooks/useArtifactsV1Enabled.test.ts
src/pages/InstanceExperimentalSettings.test.tsx`: the suites pass (151
tests in the last run).
- Run `cd packages/shared && npx vitest run src/feature-catalog.test.ts`
and `cd server && npx vitest run
src/__tests__/instance-settings-service.test.ts`: pass.
- Manual: open Settings > Experimental, turn on Artifacts V1. On the
Artifacts page the view row reads Tasks, All files, Images, Videos,
Documents, Text, Files; tasks with several artifacts show as stacks,
hovering fans the pages and lifts the artwork (not under reduced
motion); Images shows single tiles with bordered prints. Open a task's
Artifacts tab: one list of rows, newest first; a Markdown work product
still expands into its review surface, a document still opens in its
tab. In the thread, a message's files sit under its footer as rows. Turn
the setting off: everything returns to the current presentation.
- Storybook: `Tasks and conversations / Documents, attachments, and work
products / Components / Artifact V1 primitives`.
- Not run: the full `pnpm test:run` and `pnpm build` (CI runs them), and
a browser pass against a dev instance with real artifacts on the three
surfaces; that pass is the remaining step before this leaves draft.

## Risks

- Off by default; with the setting off, the only changes on a product
path are an optional `filters` prop on the toolbar, an optional `face`
prop on two panel rows, a read of the setting in the bubble and the
protocol card, and the new token declarations.
- With the setting on, the Artifacts page's view tabs set two URL
parameters (`groupBy`, `kind`) at once; the group-by menu and search are
unchanged.
- A picture with unknown dimensions renders at 4:3 until it loads, then
the print refits once; the frame's height is fixed so nothing below it
moves.
- About thirty new `--artifact-*` tokens, namespaced and documented in
place.

## Model Used

- Claude Fable 5.1 by Anthropic, model ID `claude-fable-5-1`, used
through Claude Code in the desktop app. Extended reasoning was on.
Capabilities used: tool use (shell, file edits, a headless Playwright
browser for the lab's measurements, the Figma MCP server for the mocks
during the lab work) and image input. The context window is the Claude
Code session's; its exact size is not surfaced to the 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 (#17213 is the lab this builds on)
- [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 (the suites listed above;
CI runs the full set)
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes (the
plan document; no command or product behaviour changes outside the
setting)
- [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

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-22 15:14:58 -07:00
DottaandPaperclip 25f2d05282 fix(ui): remove the provider trace run button (#17211)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The agent header provides actions to assign work and start runs.
> - A second run button starts a run with raw provider tracing.
> - Agent configuration already has a switch for raw tracing on future
runs.
> - This pull request removes the extra run button and its unused code.
> - The header keeps one normal run action and the saved tracing status.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The action buttons in the agent detail header.

**Current behavior**

Administrators see Run now and Run with provider trace next to each
other.

**Proposed behavior**

Remove Run with provider trace from the header. Use Capture raw provider
traces in the configuration Debugging section to enable tracing for
future runs.

**Reason and benefit**

Keep the normal run action clear. Put the tracing setting with the other
agent settings.

**Breaking changes**

The separate trace button is removed. The tracing configuration, trace
API, and run inspector actions stay available.

## What Changed

- Remove the trace button, its property, and its mutation.
- Remove the property from the agent detail page.
- Update tests for normal runs with saved tracing on and off.
- Check normal actions for Codex, Dot, and Muse.
- Document the tracing setting in the feature map.

## Verification

- Passed: 178 focused UI tests across AgentActionButtons,
AgentDetail.accounting, RunnerInspector, AgentConfigForm, and
AgentConfigForm.render.
- Passed: pnpm check:token-gates.
- Passed: node scripts/check-maps.mjs.
- Passed: git diff --check.
- Passed: [PR CI
workflow](https://github.com/paperclipai/paperclip/actions/runs/39796866659),
including the required verify and e2e gates.
- Passed: Greptile 5/5 with no open review threads.
- Two optional job badges still say running. Their test, cleanup, and
final job steps passed. The parent workflow completed with success.
- The broad local checks could not complete with the installed
dependencies. The full typecheck and build require smol-toml. The UI
checks also require @spekoai/client and the plugin SDK UI build. The
full test run was stopped after many suites could not load. The PR
workflow and both required gates passed for the current head.
- To inspect the UI, open an agent. Confirm there is one Run now action.
Enable Capture raw provider traces under configuration, Debugging. Save
the change. Confirm the header shows Raw tracing on and still has one
run action.

## Risks

- Low risk. This removes one UI action and its unused code.
- Administrators use the saved Debugging setting for tracing future
runs.
- No API, database, or permission changes.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, tool use, and code
execution. The exact serving model ID and context window are not exposed
in this run.

## 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-10-22 10:02:51 -05:00
TonioandPaperclip 043f2514e6 fix(ui): keep task tabs steady when switching views (#17068)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - A task side panel contains properties, artifacts, and document
views.
> - These views share one row of tabs.
> - Selecting Artifacts adds an upload control beside the row.
> - That control reduces the space available to the tabs and changes
their widths.
> - This pull request reserves the upload control space while the
Artifacts tab is open.
> - Switching views now keeps the tab widths and positions stable.

## Linked Issues or Issue Description

Refs #14949. This fixes a layout shift observed after that PR merged.

**What happened?**

In a narrow task panel, tabs shrink when Artifacts is selected. They
expand when another tab is selected. The upload control enters and
leaves the header during selection.

**Expected behavior**

Tab selection must not change the space available to the tab row. Tabs
must keep equal widths while the panel width and open tabs remain
unchanged.

**Steps to reproduce**

1. Open Properties, Artifacts, and a document or attachment in a task
side panel.
2. Make the side panel narrow enough for tabs to compress.
3. Switch between Artifacts and the other tabs.
4. Observe the tab widths and positions as the upload control appears
and disappears.

## What Changed

- Keep an upload control slot in the header while an upload-capable
Artifacts tab is open.
- Hide the control and make it inert when another tab is active. Remove
the slot when Artifacts is closed. Agent conversations do not reserve
upload space.
- Add a component regression test for selection, focus exclusion, and
closing the Artifacts tab.
- Add a constrained production-panel Storybook case with assertions for
equal widths, stable widths across selections, and upload-control
visibility.

## Verification

- The focused TaskSidePanel and SidePanelTabs suites passed: 52 tests.
- UI typecheck, UI build, and token gates passed after replaying the fix
onto current master.
- The Storybook catalog check and all 28 map/catalog tests passed.
- The browser ran `html-artifacts-03-task-journey--stable-tab-widths`
successfully. All three tabs measured 71.328125px before and after
selecting Properties, the report, and Artifacts.
- Review the Stable Tab Widths story under HTML artifacts / 03 Task
journey. The fixture mounts the production task panel. Upload requests
are outside its scope.
- Full repository typecheck, tests, and build were not rerun locally.
This machine has no Cargo, and an earlier broad test run hit unrelated
server workspace/runtime failures. Full PR CI passed on commit
`019e324c0eca815f90d9797194e768fb48cb46b6`.

- All 55 successful PR checks are green on the latest head, with no
pending or failing checks. The failed end-to-end shard passed on one
rerun after a transient database lock timeout during test cleanup; no
code changes were needed for the rerun. [CI
run](https://github.com/paperclipai/paperclip/actions/runs/39557963507).

## Risks

- A blank upload-control space remains when Artifacts is open but
inactive. This keeps the tab row stable.
- Hidden controls use both visibility and inert state to exclude them
from keyboard navigation and accessibility exposure.
- No API, database, upload permission, or saved-tab format changes.

## Model Used

- OpenAI Codex, GPT-6. The runtime did not expose a more specific model
ID or context window. Used reasoning, code execution, and browser
inspection.

## 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-10-21 22:21:42 -07:00
DottaandPaperclip 734c265339 Default new Pi agents to Paperclip Runner (#17142)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Users choose a harness during agent setup.
> - Claude, Codex, and OpenCode already receive their qualified Runner
default.
> - Pi has a qualified native integration but new Pi agents still use
the direct adapter.
> - This change gives new Pi agents the native default on supported
targets.
> - Saved agents keep their runner and compatible settings. Legacy
remains available in Advanced.

## Linked Issues or Issue Description

Refs #17120, #14921, #14922, #14923, #14924, and #14956. Related generic
default work: #15422. This PR is the separate Pi follow-up to the merged
OpenCode change.

**Current behavior**

Choosing Pi for a new agent saves the direct Pi adapter. The native Pi
integration remains behind the generic experimental flag.

**Proposed behavior**

Default new Pi agents to ACPX Pi on macOS ARM64/x64 and GNU/Linux x64
with supported glibc. Keep unsupported targets and explicit Legacy
selections on the direct adapter. Require an explicit provider/model
before test or hire. Permit model-free inactive setup drafts.

**Reason and benefit**

Users choose Pi once and receive its qualified runner. Saved agents
retain their identity and settings. Conversions reject unsupported
legacy thinking and launch settings instead of dropping them.

## What Changed

- Add Pi to the shared platform/default contract and server creation
selection.
- Admit native Pi without the generic experimental flag.
- Preserve provider models, credentials, workspace settings, exact
thinking, and saved native policies.
- Add Pi runner controls, branding, setup resume, onboarding, built-in
configuration, and import handling.
- Add managed Pi OpenRouter routing and matching native provider API-key
accounts. Keep subscription and custom gateway exclusions. Clear
alternate credentials and reject custom Pi provider overrides.
- Keep Pi draft models empty instead of applying Claude's default model.
- Verify setup against the pinned Pi runtime. For native Pi on the
official OpenRouter route, reverify the API key live without requiring a
global Legacy Pi CLI.
- Match Pi’s bounded controller close window to its native snapshot
cleanup and lifetime verification, preserving explicit caller deadlines
and the mandatory drain/suspension proof.
- Bind Pi sidecars to the package that owns the pinned native assets,
including source and vendored server layouts. Other providers retain
their existing package authority.
- Keep protocol-owned finish/block tools out of the ACPX forwarded
catalog. The trusted bridge installs these tools itself; the complete
Rust authorization catalog and terminal receipt ledger remain intact.
This fixes actual Pi session startup and applies to other ACPX
consumers.
- Advance Copilot’s shared-source attestation to v58 because it pins the
shared files touched by Pi. Preserve immutable v57 bytes and historical
decoding; Pi’s own release identity is unchanged.
- Add regression coverage and update the paired maps and developer
documentation.

## Verification

- Passed: full repository typecheck and full production build on final
head 656d304783, including the generated attestation repair.
- Passed: focused shared/server/UI suites covering default selection,
platform fallback, conversion preservation, inactive drafts, managed
account compatibility, credential isolation, OpenRouter routing/model
IDs, exact thinking controls, and saved-account selection. Relevant
batches include 375 server/conversion tests, 267 account/routing tests,
and 110 UI setup/account tests.
- Passed: 179 attestation, historical-profile, qualified-profile, and
native-execution contract tests after CI identified stale Copilot source
hashes. The identity generator check passes; the only delta after the
passing Pi browser run is this Copilot attestation/history repair.
- Passed: 145 managed-account tests, including actual service
preparation and API-key adoption/rejection for native Pi without the
Legacy CLI; 6 pinned-installation probe tests.
- Red then green: an actual task failed session.open because its
54-operation catalog included the bridge-owned terminal tools. The
regression with those tools failed before the filter; all 399 Rust
library tests pass after it. The full product retry exposed an
additional package-authority mismatch. Four authority tests failed
before that repair; 11 authority checks and 14 installation/asset checks
pass afterward. Direct real Pi session initialization with the corrected
package root and catalog succeeds. No model prompt was sent by that
diagnostic.
- Red then green: real Pi posted Hello from Pi but its controller closed
before native cleanup could finish. The cleanup-budget test failed with
the old default and passes with the bounded Pi window. All 46 selected
suspension, drain, and package-authority tests pass after building their
native fixture.
- Passed: token gates, paired map checks, Rust formatting, and git diff
--check.
- Passed real browser acceptance on macOS ARM64, generic native runner
flag disabled, source a433748a12 (Pi code unchanged afterward): the UI
selects Paperclip Runner by default, retains Pi and the selected
model/account, and verifies the pinned runtime plus live OpenRouter key.
A fresh UI-created task, assigned to the UI-created native Pi agent,
posted exactly `Hello from Pi` and reached Done without retry or
restart. The native run and workspace finalization succeeded; the
response and Done persisted after Reload.
- Evidence: 8 preserved browser attempts, including the final passing
18-step journey with all screenshots. Prior failures remain recorded.
The earlier failed checkpoint run recovered on server restart; that
recovery is separate from the fresh final task’s clean success.
- Preserved browser failures: missing account control/inherited Claude
draft model; incompatible managed-account/model-prefix handling; generic
npm probe for Pi; Legacy CLI hello check; duplicate terminal tools and
wrong provider-package authority at actual native session.open; a real
Hello from Pi comment followed by premature checkpoint cleanup timeout.
Each failure has retained screenshots/logs and a corresponding focused
repair. The fresh final task proves these repairs end to end.
- The exact Runner Vitest shard was also run locally after the
attestation fix: the stale-hash failure is gone; 1,833 tests passed, 10
skipped, and two Codex retained-control settlement scenarios failed with
`native_cleanup_maintenance_unproven` during terminal ACK/suspension
replay. Both scenarios passed in an isolated rerun (2/2), and the same
19-test file passed in the preceding Linux CI run. The precise
full-shard timing cause is not established. These Codex scenarios are
outside the changed Pi paths; the original local failures are retained;
no complete local Runner-shard pass is claimed. The corresponding Runner
shard now passes on the final head in hosted Linux CI. All 60 final-head
check runs are now terminal and clean (55 successful, 1 neutral, 4
skipped), and the legacy Snyk status is successful.
- Local full repository tests were attempted but not completed:
provisioning briefly confused a workspace symlink, then a later run was
stopped before browser-driven repairs. No full local-suite pass is
claimed. Final-head hosted CI is green and fresh Greptile review is 5/5
with all review threads resolved; earlier jobs canceled by runner
shutdown are not counted as a pass.

## Risks

- Pi cleanup has a finite 45-second default window, accounting for the
native 30-second snapshot cleanup and 5-second lifetime fence. Other
providers and explicit caller deadlines retain their prior behavior.
- Pi requires explicit operator setup with `paperclipai runtime setup
pi` on the execution host. This PR does not add automatic downloads.
- Linux ARM64, Windows, musl, and unqualified targets retain Legacy.
- Legacy thinking levels minimal, medium, and xhigh cannot be translated
exactly. Native max thinking, warm lifecycle, or restricted permissions
cannot be dropped during a return to Legacy.
- Copilot’s bound profile advances to v58 with exact current launch
admission; v57 remains decodable for recovery. No historical identity is
rewritten.
- Existing agents and immutable run descriptors are not migrated. Cloud
Pi availability is unchanged.

## Model Used

OpenAI GPT-6 through Codex with reasoning, code editing, command
execution, and browser use. The exact serving 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
- [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-10-21 17:10:00 -05:00
DottaandPaperclip 0f15f82b19 feat: offer existing Claude and Codex agents a runner upgrade (#17122)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Each agent stores its harness, model, account and runtime
configuration.
> - New Claude and Codex agents now use Paperclip Runner on qualified
targets.
> - Existing agents keep their legacy runner and need a clear upgrade
action.
> - The existing configuration API already translates settings and
records revisions.
> - This pull request adds an explicit upgrade action that uses that
API.
> - Operators can retain supported settings and correct rejected
settings in place.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Existing Claude and Codex agent configuration. Related defaults: #15683
and #15993.

**Current behavior**

Existing agents retain their legacy runner. The operator must find the
runner selector in Advanced to change it.

**Proposed behavior**

Show Upgrade runner when Paperclip Runner is the qualified default for
the saved environment. One click saves pending edits and requests the
existing server conversion. Show any rejected settings without changing
saved configuration.

**Reason and benefit**

Operators can adopt the current runner while retaining their harness,
model, account bindings, instructions and history. Unsupported settings
remain visible and editable.

**Breaking changes**

None. Visiting configuration and saving unrelated changes do not upgrade
an agent. The server API, authorization and conversion rules are
unchanged.

## What Changed

- Add an upgrade notice, pending state, saved result and retry feedback
to the production configuration form.
- Include pending profile, runtime and environment-variable edits in the
upgrade request.
- Bind asynchronous upgrade feedback and save receipts to their original
agent. Navigating away cannot show success on another agent or redirect
back.
- Keep the notice absent for native agents, other harnesses, unavailable
targets and failed discovery.
- Add configuration/API regressions and database session-reset checks
for Claude and Codex.
- Add 13 production-page Storybook states with browser checks in both
themes and on mobile.
- Update the product contract and feature/access maps.

## Verification

- Configuration form and original-agent save receipts: 135 tests passed.
Existing agent route/rename helpers also pass.
- Runner selection, configuration API and database migration
regressions: 220 tests passed.
- Storybook browser checks: 26 passed. Interactive cases wait for
Storybook's visible Pass report. Static cases check the rendered
production form. These use simulated HTTP boundaries.
- Full typecheck, build, map checks and token gates passed on the
current head. Storybook build and public preview verification passed.
- Published fixture preview:
https://storybook.paperclip.page/storybook/branches/codex~2Fagent-runner-upgrade/?path=/story/agents-runner-upgrade--legacy-codex
- All 58 current-head PR checks passed, including the full test shards,
browser suites, build and aggregate gates. The duplicate local pnpm
test:run was stopped after 34 minutes once the same-head full CI suite
passed; it had not finished its general-server phase. No local
full-suite pass is claimed.
- Real disposable local test drive: Codex used gpt-5.4 and Claude used
claude-sonnet-4-6. Both completed one task on Legacy, upgraded through
the browser button, and completed another task on Paperclip Runner with
the same model and API credentials. Independent file checks confirmed
saved instructions and environment bindings before and after conversion.
- Reopened both configurations and compared identity, model, credential
references, instruction hashes, working directories, run policies and
configuration revisions.
- A Claude Chrome setting produced a field-specific rejection. The saved
agent stayed Legacy. Clearing Chrome in the form and clicking Upgrade
runner saved the pending correction and completed conversion.

## Risks

- The existing translator rejects settings that the new runner cannot
honor. The notice shows that error and leaves the form available for
correction.
- Converted agents start fresh sessions. Prior runs remain available.
- Real task execution was checked on local macOS with API credentials.
SSH, sandbox targets and subscription credentials were not exercised in
this change.
- Storybook responses simulate persistence. The real test drive and
database tests provide separate persistence evidence.

## Model Used

- OpenAI GPT-6 through Codex. The exact serving variant and
context-window size were not exposed in this session. Used reasoning,
code editing, shell tools and browser interaction. No subagents.

## 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-10-21 15:13:42 -05:00
DottaandPaperclip 39e44a9d9b Default new OpenCode agents to Paperclip Runner (#17120)
Default new OpenCode agents to Paperclip Runner on qualified macOS and Linux x64 targets. Preserve saved runner choices, explicit Legacy selection, and unsupported-target fallback. Pi remains a separate change.

Verified the complete browser path with a real OpenRouter connection: create the new agent, assign a task, observe its response and Done status, and reload to confirm persistence. CI passes and Greptile is 5/5 with no unresolved findings.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-21 15:09:15 -05:00
DottaandPaperclip 0a5f1546ee feat(cases): add reusable prompt workflows (#17114)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Cases keep facts, documents, and one primary task across agent
handoffs.
> - Each case currently needs its own procedure text.
> - Agents need to reuse procedures and move cases between them without
replacing the task.
> - This change adds company workflow definitions with a name and
Markdown prompt.
> - Existing handoff and document transactions preserve authority,
revisions, and recovery.
> - Cases remain behind `experimental.enableCases`.

## Linked Issues or Issue Description

Refs #16959. Related proposal: #3951 uses task graphs and a visual
editor. This change extends existing Cases with prompt definitions and
keeps its current handoff model.

**Problem or motivation**

Agents cannot share a reusable procedure across cases or inspect a
case's movement between procedures.

**Proposed solution**

Add name-and-prompt workflow definitions. Adopt a prompt into the
primary task's revisioned workflow document through a handoff. Keep
phases as free text.

**Alternatives considered**

Defer graphs, workflow versions, run entities, role schemas, authoring
screens, and Spec Kit integration.

**Roadmap alignment**

This extends the existing Cases experiment and same-task review flow. It
adds no work queue or new execution engine. The maintainer approved this
scope in the implementation plan.

## What Changed

- Add company-scoped definition storage, shared request schemas, REST
routes, and four optional Cases tools.
- Accept a workflow ID at kickoff. Agent handoffs can adopt, refresh,
preserve, or detach a workflow.
- Capture prompt text and the document base revision at acceptance.
Apply workflow, phase, and document revision together after outgoing
execution settles.
- Hold conflicting document edits for recovery. Preserve cancellation,
replay, and restart behavior.
- Show current workflow names and captured transition names/phases in
Work, history, and Audit.
- Update instructions, API/tool contracts, capability maps, and the
isolated workflow journey.
- Pin bounded workflow prompt reads to a content fingerprint;
continuation conflicts on edits and can restart safely.
- Remove experimental Cases/workflow/Mermaid guidance from the always-on
native prompt. Extract runtime-context prompt strings into a
CODEOWNERS-protected constants file while preserving the public imports.
- Refresh Copilot’s pinned source identity to v57, including the
extracted prompt file and retaining historical identities.

## Verification

Local checks: repository `pnpm -r typecheck` and `pnpm build` pass on
the prompt-extraction tree (`88222d45d8`). Full repository coverage
previously completed through the supported isolated shard groups (1,082
general server suites, 161 serialized suites, and all three workspace
groups). The earlier default serial run was interrupted and remains
incomplete. The first sharded run retained the failures described below;
targeted corrections and separate limited-concurrency reruns pass. All
CI jobs, security checks, and the 5/5 Greptile review passed on
`fc1bd79c28`. Fresh CI and review are pending for the prompt extraction
in `88222d45d8`. Focused verification passes: real-database handoff
recovery and reuse; 2,002 native-tool/API contract checks; 144 Runner
catalog/discovery checks; 27 Runner context/coverage checks; 37
case/Audit UI checks; and Product E2E oracle calibration. Token gates,
migration safety/numbering, module boundaries, capability maps, and
generated tool/Storybook catalogs pass. The final route/context
corrections pass 49 API/native-tool tests, 90 real-database handoff
tests, and server typecheck; 142 Copilot installation/sidecar tests pass
with the refreshed identity.

Greptile’s first review found that successive prompt pages could mix
definitions after an edit. The fix returns a content fingerprint,
requires it for continuation, and rejects edits with 409. Strict
live/catalog schemas pass (171 Runner checks). The 2,005 API/OpenAPI
tests pass; the initial native regression caught compression’s weak ETag
prefix, and all 23 native integration tests pass after handling it. The
regression covers same-length edits and a four-byte restart window. No
stored version fields or entities were added.

The prompt extraction passes all 462 checks across six focused suites,
including persisted-context recovery and provider transport. The first
local transport attempt lacked the required debug Runner binaries (102
failures, retained); after building the normal prerequisites, all 283
tests in that suite pass without source or assertion changes. Existing
saved snapshots retain their recorded prompt text, and new executions
use core-only prompt v7. The extracted prompt source is now covered by
both CODEOWNERS and Copilot’s source fingerprint.

Live-provider evidence is separate from those simulated checks: the
isolated API-key campaign `reusable-workflows-api-final-2026-10-21`
passed with local code matching `a1d73b4652`. Four actual Codex API runs
read the adopted task documents, moved one case A → B → A on the same
task, completed normally, and passed all nine durable checks. Browser
assertions verified the current workflow/phase, historical names/phases,
five handoff records including terminal completion, and the completed
original task. Cleanup passed. The local report remains under
`tests/runner-e2e/results/reusable-workflows-api-final-2026-10-21/`; no
credentials or screenshots are committed.

CI initially caught an omitted route-inventory entry and a stale pinned
instruction-source hash; both are corrected and separately verified.
Local serialized coverage also recorded an unrelated environment-route
socket disconnect and activity-route timeout; their separate 11-test and
17-test suites passed without code or timeout changes. An unchanged
chunked-webhook check also passed its separate four-test rerun. The
initial adapter/database workspace groups hit time and resource limits
under default worker counts; complete reruns with `VITEST_MAX_WORKERS=2`
pass, including all 55 database files and 211 tests. The UI/CLI groups
passed 837 files and 9,442 tests in the original run. Original failures
remain retained and are not regraded.

Earlier failed live campaigns remain unchanged: subscription HTTP 429
before agent execution; an obsolete exact-four-row oracle that rejected
the valid terminal fifth row; and a chat-marker expectation that did not
account for the existing explicit-comment presentation policy. The final
fixture requires terminal completion and places the marker in its
authoritative comment. Positive/negative oracle tests and the fresh live
campaign pass.

## Risks

- The additive migration adds a table and nullable case/handoff fields.
Existing rows keep null workflow metadata; no assignments are inferred.
- Adoption can wait on an intervening task-document edit. Recovery must
cancel the old intent and accept a new one after readback.
- Shared definition edits affect future adoptions. Existing case copies
keep their revisions.
- The feature remains experimental. This PR does not merge or deploy the
change.
- Live acceptance covers native Codex before the prompt extraction; this
cleanup has contract/transport verification rather than a new
live-provider campaign. The refreshed Copilot identity has static
compatibility evidence, not new live-provider qualification.

## Model Used

OpenAI Codex, configured model ID `gpt-6-astra`, xhigh reasoning. Used
terminal execution, file editing, and tool calls. The active
context-window size is 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 (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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-21 15:00:12 -05:00
Nicky LeachandPaperclip 42715d459f Support authenticated WebSocket routes and agent views in plugins (#17111)
## Thinking Path

> - Paperclip manages agents and their work.
> - Plugins provide optional views and connect to external runtimes.
> - A live runtime view needs a binary browser connection.
> - The current plugin API supports JSON routes but cannot proxy that
connection.
> - Agent detail tabs are declared in the plugin contract but are not
mounted on agent pages.
> - This PR completes those two host capabilities and keeps upstream
credentials on the server.

## Linked Issues or Issue Description

**Subsystem affected**

Plugin scoped API routes and agent detail views.

**Problem or motivation**

Plugins cannot expose a binary or text stream through a browser session
without exposing an upstream credential or adding a separate browser
gateway. Agent-scoped detail contributions also have no mount on the
agent page.

**Proposed solution**

Allow declared board GET routes to select a server-only WSS upstream.
Run upgrades through the existing HTTP authentication pipeline and
trusted Origin check. Add agent company resolution with the existing
`agent:read` decision. Mount contributed detail views in agent
navigation.

**Alternatives considered**

A separately hosted viewer needs its own browser credentials and
cross-origin policy. JSON or SSE transport adds encoding and buffering
to a binary protocol.

**Roadmap alignment**

This extends the existing plugin API and detail-tab contract. It adds no
desktop provider to Core. I checked ROADMAP.md and searched related open
PRs; I found no equivalent transport and agent view change.

## What Changed

- Add declared WebSocket routes requiring board authentication, GET, and
`http.outbound`. Reject body-based company resolution because browser
upgrades cannot send a body.
- Keep worker-selected upstream URLs and headers out of browser JSON
responses. Strip browser cookies and Origin. Preserve binary frames and
socket backpressure.
- Close both sockets on disconnect or worker shutdown. Reauthorize on
reconnect after a five-minute connection lifetime. Preserve HTTP
idle-work accounting for the stream lifetime.
- Resolve agent scope through `agent:read` and mount generic agent
plugin detail views, with current agent/view breadcrumbs and browser
titles.

## Verification

- Final head `9d8d269040acf9dc7bb65524876406af522dacb5`: CI passes
(including Runner Rust, build, and browser E2E); Greptile 5/5; no
unresolved review threads; no merge conflicts. Verified 2026-10-21.
- Core server TypeScript check: `node node_modules/typescript/bin/tsc -p
server/tsconfig.json --noEmit`.
- Focused server suites: 17 passing tests
(`server/src/__tests__/plugin-scoped-api-routes.test.ts` and
`server/src/http/server.test.ts`), including arbitrary build-output and
metrics channels with real local text and binary WebSocket round trips,
disconnect cleanup, denied actors and origins, credential exclusion,
agent-read denial, and cross-company 404 equivalence. The test replaces
TLS with local HTTP while retaining the real upgrade and binary stream.
- UI suites: 9 passing tests for independent Insights and Notes
contributions, removed contributions, built-in route preservation,
sidebar links, direct plugin entry and heading updates after tab
navigation. These contributions do not require the WebSocket transport.
- Shared validator suite: 42 passing tests, including rejecting
body-based WebSocket resolution while retaining ordinary HTTP body
resolution and accepting query/entity scopes.
- UI token gates pass.
- UI TypeScript check: `node ../scripts/storybook-catalog.mjs` then `tsc
-b`.
- Shared and plugin SDK builds pass.
- Full Runner build reached its unrelated Rust step and stopped because
cargo is unavailable. Runner TypeScript build was run separately. No
live remote VM was used.

## Risks

- This adds a browser ingress path for trusted installed plugins. The
plugin must select its upstream from a trusted binding. HTTP requests
cannot retrieve the upstream descriptor.
- Membership or binding changes are rechecked on reconnect. Connections
last at most five minutes, and worker shutdown is checked every five
seconds.
- Initial CI caught a missing cross-company 404 guard and an old test
that assumed exactly one upgrade listener. Both were corrected.
Greptile's body-resolution and stale-heading findings are fixed with
regression coverage; latest-head CI passes and Greptile scored 5/5 with
no unresolved findings.
- No schema migration. Rollback restores the previous Core image;
plugins using this transport must be disabled or rolled back first.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning and code/tool execution.
The exact runtime model ID and context-window size are not exposed in
this session.

## Checklist

- [x] Thinking path and issue description included
- [x] Model described
- [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] No internal issues, private links, or runtime credentials included
- [x] Descriptive branch name
- [x] Focused tests and relevant typechecks run
- [x] Tests and documentation updated
- [x] Risks documented
- [x] All CI gates green
- [x] Greptile 5/5 with no unresolved findings
- [x] I will address review findings before requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-21 10:10:00 -07:00
Nicky LeachandPaperclip 79b2bf78dd Create agent records when onboarding names are submitted (#17005)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Core onboarding selects an agent and connects its provider account.
> - The current flow creates the agent record after authentication.
> - Setup needs a stable agent identity as soon as the user submits its
name.
> - This PR saves a paused setup record on name submission and finishes
the hire on that same record.
> - The existing sandbox authentication and approval paths continue to
apply.

## Linked Issues or Issue Description

**Subsystem affected**

Core agent lifecycle, shared validators, and onboarding UI.

**Current behavior**

Onboarding creates the database record at the final hire step. Earlier
authentication and saved setup have no agent record.

**Proposed behavior**

Create a paused agent with a setup hold when the user submits its name.
Do this before adapter selection or authentication. Update that same
record after adapter selection. Reuse its ID on retries and saved setup.
Finish that record through the existing hire path.

**Reason and benefit**

Give setup a stable identity without coupling this refactor to computer
provisioning or a new execution backend.

**Breaking changes**

Incomplete setup now leaves an inactive agent record. Existing clients
can still create and hire agents without the new optional fields. The
sandbox authentication flow and API key support remain in place.

**Additional context**

Requested Core-only refactor. Related work: #15422 changes runner
defaults. This PR preserves those choices. No duplicate early-record
refactor was found in the issue and PR search.

## What Changed

- Save the agent when the user submits its name in both onboarding entry
points. Use a provisional adapter until the user chooses one. Reopen
name-only drafts at adapter selection.
- Add retry-safe setup creation and same-record hire completion. Keep
approval checks at final hire.
- Save and restore setup configuration in both onboarding entry points.
Show Finish setup for paused setup agents.
- Restrict setup changes to authorized board users. Block generic resume
until setup finishes.
- Add lifecycle, authorization, connection, and UI coverage. Update the
specification and feature maps.

## Verification

- Latest focused server run: 126 lifecycle and AI-connection tests
passed after the Apex fixes. An earlier broader run passed 301
lifecycle, instruction, adapter-validation, and AI-connection tests.
Earlier authentication, retry, cross-company, and direct-create
regressions also passed.
- Name-save verification: 336 tests across the wizard, naming dialog,
New agent, action-button, and wizard-step suites passed. Coverage
includes retry identity, repeated submission, closing during a save,
saved-model restoration, and a disabled process adapter.
- Shared, server, and UI TypeScript checks passed. The latest UI package
check and direct server TypeScript check passed. The server package
preparation command could not finish locally because Cargo is
unavailable; full build preparation runs in CI. Map checks, token gates,
and `git diff --check` passed; each pushed diff was scanned for
credentials and PII.
- All six onboarding browser tests passed together with installed Chrome
against a fresh throwaway instance after the Apex fixes. They include
numbered duplicate names, first-time Copilot without a connected
account, and Grok’s saved model. They verify early persistence in both
entry points, closing and reopening a name-only draft, same-record
adapter selection, sandbox sign-in, login reload, and failed-connection
gating. Provider responses are simulated; Core persistence is real.
- Regression coverage includes incomplete Copilot creation versus final
validation, Kimi settings through redacted responses, stale local
drafts, company switches during creation, saved environments, and
provider changes with personal/shared old bindings.
- Apex found five name-only setup gaps: numbered names, early Copilot
account validation, the Grok model default, same-name draft ownership,
and provisional runner restoration. The fixes preserve server names,
defer implicit account binding until hire, set Grok’s model, avoid
name-based reuse of unfinished records, and restore Auto for pending
adapter choices. UI, database, and browser regressions cover these
cases.
- Standard Greptile found a Grok provider mismatch in the new adapter
save. The save now uses ACPX with the Grok profile. Both the 129-test
dialog/setup run and a real-API browser regression passed after the fix.
The first browser attempt stopped on an ambiguous empty-roster button
selector; it now scopes the click to the toolbar.
- Moving the save point exposed a saved-model reset and timing
assumptions in the same-name and portal fixtures. The source choice now
preserves the restored model, and tests cover same-name recovery without
a second hire.
- Initial CI exposed direct-create compatibility, concurrent setup
effects, fixture assumptions, and a missing-fields assumption in the
provider-validation guard. These were fixed and verified locally. Review
findings were addressed with authorization, recovery,
credential-persistence, and restored-configuration regressions.
- The final desktop capture passed after host resource cleanup. A repeat
first failed before Core started because macOS had exhausted
shared-memory IDs. Standalone PostgreSQL initialization reproduced the
same error. Releasing only unattached control segments from this task’s
stopped test databases allowed the unchanged revision to pass. No Core
or system setting changed.
- Local database tests required port access outside the sandbox. Missing
declared development dependencies were supplied outside the branch. No
live provider sign-in was tested locally.
- [Full monorepo
CI](https://github.com/paperclipai/paperclip/actions/runs/39522434236)
is green on `82b82fec189a172a885d4dd565ae2f4a18c73efc`. Standard
Greptile scored 5/5 with zero new comments (check `118969424903`). The
subsequent Apex review also scored 5/5 with zero new comments (check
`118972866331`) on that same commit. All review threads are resolved.
- The separate Superagent Security scan returned neutral/inconclusive
because its pinned merge-base checkout failed or timed out. GitHub
returned 404 for check and suite rerun requests. This is not a
successful security scan; the CI workflow and other security checks
passed.

## Risks

- Users can leave inactive setup records behind, including after name
submission alone. These records cannot run until hire completes.
- Setup completion touches hiring and approval boundaries. Tests cover
retries, company isolation, creator permissions, and approval snapshots.
- An uncertain credential-save result retains its new secret reference
for retry. A confirmed client rejection removes only credentials staged
by that attempt.
- No schema migration or VM provisioning change is required.
Agent-computer integration is out of scope.

## Model Used

OpenAI Codex, based on GPT-6, with repository search, code editing, and
tool execution. The exact deployment 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] Apex Greptile is also 5/5 on the same commit as standard review
and green CI
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-20 18:08:57 -07:00
DottaandPaperclip d33b40a5c3 fix: recover saved work and provide reliable task Retry (#16965)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The control plane must retain work when an execution or workspace
export fails.
> - Retained-workspace holds can leave saved input waiting with no
usable Retry action.
> - Users cannot verify process ownership or repair provider
allocations.
> - This pull request gives system recovery a durable budget and gives
each deliberate Retry a durable intent.
> - Safe recovery can preserve files, settle an accepted result, or
prepare an independent workspace.
> - One task state keeps infrastructure diagnostics out of the ordinary
conversation while preserving real permission and approval gates.

## Linked Issues or Issue Description

**What happened?**

A task with a retained workspace can show recovery, failed-run and
saved-message warnings at the same time. Historical runs without native
workspace descriptors cannot use the native restore path. Old recovery
metadata can prevent a new attempt even when an independent workspace
would be safe.

**Expected behavior**

Paperclip owns bounded infrastructure retries and file preservation. A
user can request another attempt with ordinary Retry. Thinking appears
immediately. The service preserves completed effects and current user
controls. It does not claim that starting fresh recovered the old files.

**Steps to reproduce**

1. Retain a failed run and its workspace after export or process-stop
failure.
2. Save a follow-up while the recovery hold is active.
3. Open the task and try to continue without infrastructure credentials
or operator certification.

Refs #16906, #16835, #16883. This extends their recovery and receipt
contracts. Related work: #16962 and #16963.

## What Changed

- Add task-level Retry with company-scoped authorization, all-status
idempotency and durable admission before physical work. Keep exact-run
Retry compatible.
- Add typed recovery phases, finite persisted backoff, historical
adoption and durable local failure diagnostics.
- Preserve native workspaces or verified historical snapshots. Admit an
independent fresh workspace only after execution containment. Keep
old-source preservation and cleanup obligations separate.
- Carry completed publication and API receipts forward. Fence uncertain
mutation retries across replacement runs. Preserve connected-chat
identity and authorization.
- Re-enter normal dispatch for saved input. Reuse accepted results
through the existing finalizer.
- Use one task interruption projection across the thread, composer and
task list. Show optimistic Thinking, ordinary Retry and genuine user
gates.
- Add PostgreSQL, filesystem, API, browser-fixture and controlled
provider coverage. Document the behavior and update the feature/access
maps.

## Verification

- All GitHub Actions CI jobs pass on
`6d8c6d27d50586d8548b31d03b47f6d73a0ee11d`: typecheck, all
server/chat/workspace and serialized suites, Runner checks, eight
browser shards, canary and build. The required merge gate passes.
- Greptile reviewed the final commit at 5/5, with no actionable findings
or unresolved review threads. Its two earlier P1 findings are fixed.
- Full recursive typecheck and build pass locally on the final commit.
All 16 task Retry cases pass against isolated real PostgreSQL. The
unrelated-success case and both stale Retry cases fail on the previous
code and pass after the fix.
- The corrected gateway fixture passes its uncertain-mutation and
independent-read case. Four real HTTP API cases pass for definite
403/422 rejection, completed-effect reuse, and uncertain-effect fences
across deliberate and automatic retries. These focused gateway/API
checks used a temporary database lifecycle harness on an existing
healthy local PostgreSQL process. The standard repository helper is
unchanged.
- Earlier qualification covers 291 task UI cases, saved-file copyback
and ancestry, current Agent Chat ownership races, nine chat Retry API
browser cases, and six assembled browser recovery fixtures. A real
API/PostgreSQL/native-runner journey showed Thinking in 25 ms despite a
delayed response, admitted one successor in a separate workspace,
retained original files, and survived reload.
- The controlled Daytona test interrupts export, joins the controller,
restarts it in a separate process, and verifies one agent start, one
external sentinel operation, retained file contents and no premature
cleanup. It does not establish abrupt-kill or live LLM/GitHub
acceptance.
- The full local `pnpm test:run` was attempted and was not green: an
OAuth row-lock timing assertion failed, and a later suite exhausted
macOS PostgreSQL semaphores. The ten OAuth timing cases passed on rerun
against a separate database. Later embedded database initialization
failures remain recorded; the final CI matrix passes.
- Security scanning passed on production-code commit
`63953edf069b111c6becc3144dffa6deb52f68b5`. Its only successor changes
one test-fixture identity line. The final scan is neutral/inconclusive
because its pinned merge-base checkout failed or timed out. Both rerun
API requests returned 404, so no fresh successful scan is claimed.
Socket and Snyk checks pass on the final head.
- The optional Paperclip Review remains queued behind an earlier run in
workspace finalization. Its prior completed assessment was incomplete
because a comparison tool was blocked by the platform filter. It is not
counted as a completed code review. GitHub does not require this check
for merge.
- Hosted acceptance remains pending deployment. Local and CI results do
not establish recovery of a hosted task or its retained files.

## Risks

- Recovery changes span admission, physical ownership and dispatch.
Incorrect evidence could permit overlapping work. Existing physical
locks and authoritative stop requirements remain in place.
- The migration adds concurrent indexes. It requires the existing
top-level migration runner and retries incomplete index creation safely.
- A fresh attempt can complete while old-source preservation remains
unresolved. The service retains that obligation and does not report
those files as recovered.
- Unknown tool mutations remain blocked until their authoritative
receipt owner resolves them. Generic upstream tools have no universal
result-query protocol.
- Recovery and diagnostics stay inside the stack. No Cloud incident
endpoint, notification worker or new outbound reporting channel is
included.

## Model Used

OpenAI Codex, GPT-6 family. The runtime does not expose a more specific
model version or context-window size. The model used reasoning, shell
execution, source editing and browser tools. No model subagents were
used for this implementation.

## 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 (focused suites; the full
local run limitation is 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-10-20 19:58:53 -05:00
DottaandPaperclip b11010b0d4 Simplify failure banners and show only the latest error (#16982)
Remove dashed failure dividers and show only the latest adjacent run or recovery error. Preserve permitted retries, pending state and unrelated notice boundaries. Add production-component Storybook examples and browser regression coverage.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-20 14:29:39 -05:00
DottaandPaperclip 505e1a5582 feat(cases): add persistent workflows with same-task agent handoffs (#16959)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - An agent workflow needs persistent facts and a safe way to transfer
work.
> - Creating a task for each phase splits the objective, discussion,
workspace, and review policy.
> - A case can retain the facts while one primary task moves between
agents.
> - Transfers must survive process failure and preserve private access,
budgets, and completion gates.
> - This pull request adds durable case handoffs, native case tools, and
read-only case pages.
> - Prompts describe the workflow. Existing task controls decide when
work can run and finish.

## Linked Issues or Issue Description

**Problem or motivation**

Prompt-driven agent teams need a persistent record that can move through
triage, implementation, verification, and correction. Ordinary
reassignment does not provide a durable instruction, safe release
barrier, or recoverable delivery receipt for an agent handing off its
own running task.

**Proposed solution**

Extend standalone cases with one primary task, a descriptive phase,
retained access sources, and a handoff ledger. Apply assignments after
source execution and workspace settlement. Deliver each transfer through
the existing durable wake queue. Provide `create_case`, `read_case`,
`update_case`, and `handoff_case` in the native runner. Creation
requires kickoff and explicit workflow text. An explicit handoff to
`done` closes the case when normal task completion is accepted.

**Alternatives considered**

Do not add a workflow engine, filesystem queue, configured state graph,
or one task per phase. The workflow document combines transition prose
with an optional Mermaid `stateDiagram-v2` map. The server does not
execute the diagram. The Pipelines experiment removed on master stays
removed.

**Roadmap alignment**

This extends Agent Reviews and Approvals, Enforced Outcomes, Bounded Run
Recovery, and Activity Log attribution. Existing approval, review,
budget, privacy, workspace, and responsible-user rules remain
authoritative.

Related work: [ordinary handoff wake
recovery](https://github.com/paperclipai/paperclip/pull/15019). This
feature adds a separate persisted case-handoff receipt and release
barrier.

## What Changed

- Add case routing fields, retained access sources, durable handoff
history, delivery leases, and replay-safe migrations.
- Keep the same primary task across agent phases. Preserve each
returning agent's own session and the task's workspace.
- Fence outgoing mutations, wait for provider and workspace release, and
recover delivery without duplicate task comments or runs. Recheck
current assignment permissions as the original caller before applying a
delayed transfer. Scope a run Stop to that run’s own handoff intents, so
repeated old Stop requests preserve newer work. Cancelling terminal
intent without a source run also requires fenced current task ownership,
including native retries and preparation with an old checkout. For Cloud
callers, revalidate current stack membership with an uncached Cloud RPC
and derive owner elevation from the current managed setting.
- Keep case reads, documents, assets, Audit, and live events inside
retained task/project permissions.
- Add native case creation/read/update/handoff tools. Store required
workflow text and initial documents on the first task. Page oversized
case facts and referenced document bodies through the dedicated tool
with bounded UTF-8 JSON, current routing versions, snapshot conflicts,
and current source authorization on every page.
- Add read-only case lists and detail pages, task-style list controls,
compact dotted field tables, linked handoff tasks, and case filters in
Audit.
- Add native/legacy integration tests, migration/restart tests, browser
coverage, and bounded live receipt fixtures. Extend the trusted sandbox
condition to cover the new subscription fixture profile.
- Hide obsolete paused-agent warnings on completed or cancelled task
threads.
- Synchronize the company-switch settings test with React effects after
a CI failure. Preserve its security assertions and production remount
behavior.

## Verification

The branch directly includes master `9ef434fe79`. The required `ci /
verify` and `ci / e2e` gates pass on head `765fccd67c`. [Current-head
CI](https://github.com/paperclipai/paperclip/actions/runs/39464348614)
passes typecheck, build, tests, and all eight browser shards. Security
checks pass. [Greptile gives this exact head
5/5](https://github.com/paperclipai/paperclip/pull/16959#issuecomment-6291156549),
with no unresolved review threads. The optional Paperclip Review check
remains queued because its assigned agent is paused. It is not a
required branch check. No check result was overridden.

Local workspace typecheck and build pass after the master merge, along
with database migration checks, token gates, map checks, Storybook
catalog checks, and the Copilot profile identity check. Standard builds
refresh Runner vendor output. Focused checks pass 2,008
API/paging/context tests and 7 strict case protocol tests. The final
commit changes one test fixture only; its ten tests, UI typecheck, and
token gates pass. No production source changed in that commit.

On current head `765fccd67c`, all **194 critical workflow tests**
executed and passed with no skipped tests in those files:

- 38 Stop/ownership tests, including board completion intent, native
retries, stale Stop, and preparation with an old checkout.
- 2 actual legacy process/HTTP handoff tests, including scratch failure,
a closed-stdio child that continues writing, and recovery through a
fresh worker after the process group stops.
- 5 migration tests, including SQL column metadata, preserved null
authority context, and all six prior-numbering receipts.
- 3 process-settlement and 5 scratch tests.
- 88 handoff-service, 18 heartbeat handoff, and 21 native case-tool
integration tests.
- 7 bounded case/document-read projection tests and 7 strict
protocol-contract tests.

The current CI checkout was `fed65d49`, merging `765fccd67c` into master
`9ef434fe79`. Its new document regressions reconstruct exact
Unicode/escaped bodies and revisions through real native authority and
authenticated HTTP with generic API tools disabled. They cover
case-owned, primary-task, and linked-task documents; routing on every
page; stale document snapshots; access loss and unlinking;
unrelated/foreign/private sources; system documents; and quarantined
content. Active-task document tools retain their existing behavior.
These are current-head test results from the first CI attempt; the
browser-only retry did not rerun these suites.

The full `64fdd3403f` CI failed one separate settings test: after a
company switch, it observed an unsettled API-key draft. The production
component and test were unchanged from prior green source. Production
switches remount both keyed settings layers; the test directly reused an
unkeyed view and used a timer tick instead of waiting for React effects.
The final commit replaces that fixture synchronization with React `act`.
The exact secret-clearing assertions and all timeouts remain unchanged.
The original assertion failure remains recorded; no unchanged retry was
used. The narrow unchanged baseline and fixed fixture each pass 10
tests.

The upstream result-paging merge preserves case capture namespaces and
current asset privacy. Its API integration suite executed 39 of 41 tests
successfully, with two skipped; the optional assigned-result PRP
integration test was skipped. Neither skipped suite is counted in the
194 critical tests or as live provider proof.

All 361 upstream migration entries and SQL bodies remain unchanged. Six
case migrations follow master as 0363–0368 with identical SQL hashes.
Official Drizzle generators produced the combined metadata and five
retained snapshots. Generation reports no schema changes, and the
snapshot drift test passes. The earlier `ce361ae5d0` CI passed on
attempt 1, including its then-current 179 critical tests. Fresh review
later identified unusable document references with generic API tools
disabled; the bounded document reads and ten additional authenticated
HTTP tests address that finding.

The full local `pnpm test:run` attempt was cancelled after this Mac
exhausted PostgreSQL semaphore capacity; it is **not** counted as a
pass. Later database attempts also stopped before assertions or skipped,
including one sandbox socket denial. Two original stale-Stop regressions
did reproduce the bug against the old source. A REST serialization
assertion passed after two preserved database-startup failures. No test
timeout was increased. All 194 assertions listed above executed and
passed in current-head CI. The complete 385-file, 3,963-test UI shard
also passed after the fixture repair.

A configured-provider receipt workflow passed 13 backend checks across
triage → implementation → verification → correction → done, using one
task and four work runs. The saved receipt is revision 2 with total 6
USD; case and task both closed. The original canonical attempt remains
failed because its browser assertion confused the terminal destination
with completed-task tooltips. The corrected full browser verifier passed
on the same retained database and original runs, with no additional
provider calls. The last clean-build browser readback is on
`6a86c54a53`; later changes affect recovery, authorization, bounded
reads, and settlement. Accounted work cost is a $1.010574 rate-card
estimate; provider billing and setup-probe usage are unavailable.

Copilot profile 49 passed the unchanged seven-fixture private protocol
pack (46/46 checks, no retries) and the product file-edit canary after
master's completion-replay change. All 60 bound implementation hashes
remain unchanged on the current source. Historical profile-47/48
identities and results remain intact. See the [profile-49 compatibility
record](https://github.com/paperclipai/paperclip/blob/codex/persistent-case-handoffs/doc/plans/2026-10-20-copilot-completion-recovery-compatibility-v49.json).
This is bounded compatibility evidence, not a fresh full matrix,
installed-package product test, or Daytona rollout.

Preserved CI failures and retries:

- On `20662930ac`, Slack managed setup failed a five-second success
assertion after reload. Its test/application path was unchanged from a
prior green head. One unchanged-source retry passed all 25 tests in that
shard; no source or timeout changed.
- On `9402b4f17a`, two CI workers received shutdown signals at 15:24:19
UTC. Neither log had an assertion failure before interruption. One
unchanged-source retry of each passed all Runner static checks and all
32 tests in browser shard 6; both aggregates passed. The next head,
`7b4374edaf`, passed all CI without retries.
- On `295f289b5a`, serialized shard 9 timed out during its first
device-login test, then the next test found an active login lease.
Direct login/test paths were unchanged from a prior green head. Cold
import plus a timed-out async body using the next test's mutable
actor/store is the supported fixture-race explanation; no request trace
proves that sequence. The original failure remains recorded. One
unchanged-source retry passed all 294 tests in 19 files, including all
41 device-login tests. No login source or timeout changed. The
subsequent `ce361ae5d0` CI passed without retries.
- On `64fdd3403f`, one company-switch settings assertion observed an
unsettled draft. The final test-only commit uses React `act` without
changing assertions, timeouts, or production code. On `765fccd67c`, all
ten settings tests and the complete 385-file, 3,963-test UI shard
passed.
- On `765fccd67c`, browser shard 3 completed the split-handoff
assertions, then cleanup received HTTP 500 from run cancellation after a
one-second PostgreSQL row-lock timeout. The extra chat run was reporting
completed work while teardown began. Cleanup stopped before restoring a
global experiment flag, causing a later assertion to fail. Relevant
production and test paths are unchanged from an earlier green commit.
Stop's lock order is consistent, and no nested self-lock was found; the
exact PostgreSQL blocker was not recorded. One unchanged-shard retry
passed. The original failure, trace, and downstream flag failure remain
recorded. No Stop implementation, cleanup assertion, or timeout changed.
The retry supports intermittent cleanup contention; it does not identify
the original blocking transaction.


## Risks

- Local process transfers require host-owned PID/group absence. Missing
or uncertain termination evidence keeps delivery pending, independently
of scratch setup.
- Handoff admission and task cancellation share execution ownership. New
regression tests cover temporary holds, late source writes, and
uncertain provider termination.
- Retained private sources use an intersection of existing permissions.
This intentionally fails closed when a source is missing or an existing
task cannot preserve that boundary.
- Migrations add tables and indexes. They preserve master history and
can replay over prior feature installs. Migration 0368 adds nullable
internal authorization provenance with no default or authority backfill.
Historical transfers still awaiting release without this context fail
closed; an operator must cancel them and request a new handoff.
- Delayed Cloud handoffs depend on the current Cloud membership RPC. An
unavailable, ambiguous, expired, or mismatched response holds the
handoff for retry; it does not reuse cached authority or grant access.
- Bounded reads reload and reauthorize the selected projection per page.
Underlying work grows with the data size and number of pages. Changed
data or routing requires restarting from offset zero without the old
snapshot.
- Phase names and workflow diagrams remain advisory. They do not satisfy
review or approval gates.
- This is a large, cross-cutting PR. The maintainer requested one PR for
the whole feature; the commits separate data, runtime, UI, and
qualification work.

## Model Used

OpenAI Codex, GPT-6 family, with tool use, code execution, and delegated
code review. The exact deployment model ID and context-window size were
not exposed in the session. Live fixture agents used the explicitly
configured provider model recorded in their test evidence.

## 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-10-20 12:46:14 -05:00