Commit Graph
4598 Commits
Author SHA1 Message Date
DottaandPaperclip 78ce96a48b fix(runner): restore native Claude context and read permissions (#13422)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The native runner supplies each agent with instructions, assigned
skills, and tools.
> - Native Claude lost its skill snapshot before provider launch. It
also changed exact model IDs to aliases.
> - The read permission mode denied ordinary Paperclip reads because
this runner has no interactive approval handler.
> - This pull request restores the missing context and permits only
assigned tools that Paperclip defines as reads.
> - Other requests that need approval stop with a clear action for the
operator. They do not retry automatically.
> - Agents can complete read tasks. Users can see why a restricted task
stopped.

## Linked Issues or Issue Description

**What happened?**

Native Claude could not find assigned skills. The ACP layer could
replace an exact model ID with an alias and then fail identity
verification. The default `approve-reads` mode denied Paperclip read
tools. A denied write showed a generic transport failure.

The tool descriptions also called live operations “mock” operations. The
completion prompt said to call a completion tool once, although the
protocol can reject a claim and require a corrected call.

**Expected behavior**

Load assigned skills before launch. Keep the selected model ID. Allow
assigned Paperclip reads. Stop an operation that needs approval with
clear instructions when no approval handler exists.

**Steps to reproduce**

1. Configure a native Paperclip Runner agent with ACPX Claude and an
exact model ID.
2. Assign a skill and ask the agent to use it.
3. Select the read permission mode and ask the agent to read task
context and list documents.
4. Ask the agent to write a document. Check the task state and recovery
message.

**Paperclip version or commit**

Reproduced from `d351e08deee1b49d3467a950d1a3f01131943441`.

**Deployment mode**

Local native runner with real Claude, Rust runnerd, the Paperclip
server, and embedded PostgreSQL.

Related: #13196 fixed remote skill staging in the legacy `claude_local`
adapter. The native runner uses a separate path, which this pull request
fixes.

## What Changed

- Carry the runtime context through Rust and the ACPX sidecar. Load
assigned Claude skills after the provider lifetime lease is held.
Refresh the files on each open.
- Write the exact requested model ID into the isolated Claude settings.
- Grant exact MCP permissions for the intersection of assigned tools and
Paperclip's read catalog. Provider hints cannot grant access. Existing
task-control permissions stay in place.
- Stop requests that need an unavailable approval handler. Preserve the
typed error through the server. Show “Approval required” on the task and
require operator action without automatic retry.
- Label the setting “Allow Paperclip reads.” Remove “mock” from live
tool descriptions and regenerate the contracts.
- Change one completion-prompt sentence to require one accepted result.
Add regression tests and update the runner documentation.

## Verification

- Red/green regression tests cover read admission, unavailable approval
handling, server recovery, and the task error message.
- A real Claude read trial failed before the fix and completed after it:
[red
trace](https://www.braintrust.dev/app/Paperclip/object?object_type=project_logs&object_id=fda74078-b00d-495a-90d3-ea1be019d71b&id=95e6a326e24437f1),
[green
trace](https://www.braintrust.dev/app/Paperclip/object?object_type=project_logs&object_id=fda74078-b00d-495a-90d3-ea1be019d71b&id=85a1f347db5604d1).
- Full browser tests used real Claude and the production tool authority.
Reads completed. A write stopped with “Approval required.” No document
was created and no automatic retry was scheduled. All nine checks
passed: [events and
screenshots](https://www.braintrust.dev/app/Paperclip/object?object_type=project_logs&object_id=fda74078-b00d-495a-90d3-ea1be019d71b&id=1c4ff10be0d779cc).
- A separate full browser test assigned a skill, invoked it, and
completed with a marker absent from the task prompt: [skill
evidence](https://www.braintrust.dev/app/Paperclip/object?object_type=project_logs&object_id=fda74078-b00d-495a-90d3-ea1be019d71b&id=ba5fbcb29a60be52).
- Post-rebase checks passed: 128 targeted runner tests, 46 Rust tests,
27 sidecar/protocol contract tests, `pnpm -r typecheck`, and `pnpm
build`. The server/UI red-green checks and `pnpm check:token-gates` also
passed. The full suite passed in CI, including all general and
serialized test shards, all three browser shards, and runner
`check:all`. The duplicate unsharded local full-suite run was stopped
after CI passed.

Braintrust links require project access. The traces contain
provider/runner events and app outcomes. They do not contain raw model
HTTP requests.

## Risks

- `approve-reads` now allows assigned Paperclip reads. Other operations
that need approval stop the turn. Users must review the operation and
change permissions before retrying.
- The Claude settings depend on the pinned ACP and SDK behavior.
Automated tests and real Claude trials cover this boundary.
- The native Codex path is unchanged. The ACPX Codex fallback shares the
clearer approval failure handling.
- Local execution was tested end to end. Remote execution was not run.
This change has no database migration.

## Model Used

OpenAI GPT-6 through Codex. The agent used reasoning, code execution,
and browser tools. The exact deployment ID and context-window size were
not exposed in the session. Live acceptance tests used
`claude-sonnet-5`.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (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-09-14 10:56:24 -05:00
DottaandPaperclip 728f7185f6 feat: add native in-app announcements with persistent dismissal (#13403)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Self-hosted boards need a way to show occasional product
announcements.
> - An app release should not be required to publish or withdraw a card.
> - Native card controls keep publishing consistent; the hero can use a
static image or isolated HTML/CSS animation.
> - This pull request renders a validated JSON feed with native
components.
> - It stores dismissals per account on each instance, so a closed card
stays closed across companies and browsers.
> - Named staging feeds let authors test content before production
publication.

## Linked Issues or Issue Description

**Subsystem affected**

Board application shell, announcement delivery, and user preferences.

**Problem or motivation**

Operators need a small, optional announcement card. Users need reliable
dismissal state. Authors need to test remote content without changing
the production feed.

**Proposed solution**

Add one non-modal AnnouncementWell. Fetch validated JSON and
content-addressed media through the instance server. Keep card controls
native, with optional sandboxed HTML/CSS animation in the hero. Use
stable announcement IDs for dismissal, an explicit empty manifest and
quiet 404 handling. Provide a staged publishing helper and isolated
test-drive guide.

**Alternatives considered**

Hosting the entire card as a page would move navigation and dismissal
into remote content. This change limits HTML to a scriptless, isolated
visual hero and keeps controls native. Browser-only storage would lose
dismissals across browsers, so the instance stores account preferences.

**Roadmap alignment**

ROADMAP.md has no overlapping announcement feature. A GitHub title
search found no related announcement pull requests. This work implements
a maintainer-requested feature.

## What Changed

- Add shared feed types, strict validation of every object, supported
routes, expiration and version checks.
- Add a board-only current-feed API, constrained media proxy, and
idempotent dismissal API. Store the first dismissal and its company
audit entry in one transaction.
- Cache upstream data for one hour. Use conditional requests, request
deduplication, response limits, public destination checks, and a
three-second deadline. Treat a remote 404 as an empty feed with a
fifteen-minute retry cooldown.
- Keep announcement visibility stable when focus moves to browser chrome
or another app pane; only tab visibility starts a return check.
- Add a responsive native announcement card. Respect onboarding, dialogs
and toast placement. Sync pending dismissals across tabs and retry after
reconnect or return.
- Add idempotent migrations for dismissals and validated publication
IDs, design-guide examples, static and animated Storybook examples, and
focused tests. The publication registry supports offline retries without
accepting caller-invented IDs.
- Add HTML/CSS animated heroes with static posters, automatic playback,
reduced-motion handling, strict DOMPurify validation, an empty iframe
sandbox and CSP that blocks scripts/network resources.
- Add validated staging publication, content-addressed assets, an empty
production manifest, preview fixtures, and authoring/operator
documentation.

## Verification

- The preceding implementation passed 98 targeted
shared/server/publisher/route/OpenAPI/UI tests and 127 tests including
the master rebase. The playback-control removal passes all 21
announcement UI tests, covering the rendered sandbox, fallback, reduced
motion, dismissal and slow/stale state lookups. The preceding
shared/server tests cover HTML validation and response sandbox headers.
- The playback-control removal passes UI typecheck, production UI build,
Storybook build and token gates locally. Browser verification confirms
the animated card has only its dismiss button and two links, with no
page errors. The full canonical CI matrix passed on current head
`00e416431edb610861599d50490270bbd0f3c6b6`: 32 successful checks and two
optional Storybook deployment checks skipped. This run needed no
retries. Greptile reviewed this same head at 5/5 with no outstanding
findings.
- The local canonical general-server run passed 12,063 tests before
reporting embedded-PostgreSQL startup failures in an unrelated fixture.
All 31 tests in that fixture passed across isolated retries. The UI
group passed 6,219 tests and other workspace groups passed 3,201; two
CLI database-startup failures also passed individually. Serialized
server suites were verified by the full CI matrix rather than repeating
them locally. No source changes were needed for these environment
failures.
- The real S3/CloudFront staging manifest and both media asset headers
were verified. Production remains empty/unpublished. The guide
distinguishes the preview host's disabled edge cache from production
cache requirements.
- In the isolated test-drive, the animation visibly moves without
playback controls. A 390×844 browser viewport keeps the card above
navigation. Reduced motion makes no animation request. Both themes
render correctly and browser page errors are empty. Browser fault
injection verified that scripts cannot execute and CSS cannot make
network requests; a missing animation leaves its poster and controls.
- Refresh leaves the animated card visible. Closing it persists after
reload and the API returns null. Earlier live checks verified dismissal
across browsers, company-relative CTA navigation, modal
deferral/restoration, and new-ID eligibility after restarting the same
database.
- The deployed empty feed and a real remote 404 return HTTP 200 with
null from the board API, with a usable dashboard and no announcement
popup or browser warnings.
- Authoring documentation covers staging, animated HTML constraints,
test-drive, withdrawal, ID reuse and cache-refresh steps.

## Risks

- Animation supports self-contained visual HTML/CSS and inline SVG,
without JavaScript or external resources. A static image is required.
Older builds that do not recognize the optional animation field quietly
hide that unsupported feed.
- The default feed makes an outbound request from an instance when a
board is used. Operators can disable it. Requests contain no account
IDs, company data, cookies or interaction events.
- Feed publication and withdrawal can take about 65 minutes to reach
returning users because of CDN and instance caches. Expiration also
removes visible cards locally.
- Dismissals follow an account within one instance. No-login instances
share the existing local-board identity. Separate installations do not
share state.
- Both tables are additive. A unique key prevents duplicate dismissals;
the transaction prevents duplicate first-dismissal audit entries. The
publication registry retains only validated IDs. AGENTS.md and the
implementation spec document the required exception to company scope for
these instance-level records.
- Publication was limited to separate public staging prefixes on the
existing preview host. Production remains empty/unpublished. No AWS
policies or infrastructure were changed.

## Model Used

OpenAI GPT-6 through Codex. The exact runtime model ID and
context-window size are not exposed in this session. Capabilities used:
reasoning, code editing, shell execution, tests, browser interaction,
and tool use.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.914.0-canary.1
2026-09-14 10:19:54 -05:00
DottaandPaperclip f1d57863d2 fix: make connection checks and task handoffs reliable (#13404)
Preserve connection-probe outcomes through cleanup, reduce unrelated startup work, and report selected Claude authentication accurately. Make artifact download actions match their labels.

Route delegated feedback through its active child, retain accepted messages across completion, and avoid redundant worker runs for proven closing notes. Preserve explicit follow-ups, human input, company boundaries, source provenance, and mixed issue references.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-09-14 10:06:06 -05:00
Michael Nguyen 2d47a8058d fix(apps): update connector artwork and theme fallback (#13361)
> Awaiting author review. Do not merge until the author explicitly
approves.

## Thinking Path

> - Paperclip helps people manage AI agents for work.
> - Connector screens need recognizable app artwork.
> - Several bundled marks have inconsistent artwork or dark-theme
behavior.
> - The shared logo component should retain the existing frame.
> - This change replaces selected artwork and fixes local theme
fallback.
> - Users see consistent connector icons across shared component
callers.

## Linked Issues or Issue Description

**Current behavior**

Some connector marks use outdated artwork or unsuitable theme variants.
A remote dark logo can override a canonical local mark that works in
both themes.

**Proposed behavior**

Use the selected bundled artwork with the existing gray rounded frame.
Use local light artwork in both themes unless a distinct local dark
variant exists.

**Subsystem affected**

Connector artwork, the shared AppLogo resolver, and its validation.

**Breaking changes**

No connector capability, permission, credential, or catalog activation
changes. No duplicate PR was found in the earlier search.

## What Changed

- Update 46 artwork files and only the app definitions whose logo paths
need to change.
- Keep a compact public manifest of identities, paths, visibility, and
aliases.
- Prefer local artwork in both themes and preserve the existing frame
and padding.
- Add locally runnable artwork safety checks and a light/dark Storybook
gallery; leave PR workflows unchanged.
- Document artwork conventions. Source research is kept outside the
public manifest.

## Verification

- Artwork check: 69 identities pass.
- Node artwork validation tests: 13 pass (rechecked September 14).
- Focused resolver, component, and catalog tests: 40 pass (rechecked
September 14).
- Maintainer decision: dedicated icon-validation CI is not required; the
workflow remains unchanged. Greptile acknowledged 5/5 with no remaining
code concerns on September 14.
- UI typecheck, token gates, and Storybook build pass.
- Earlier full build and repository typecheck passed. The broad local
test run was stopped after workspace-runtime dependency fixture failures
outside this change. Current GitHub CI remains the full-suite gate.
- Visual approval remains outstanding. Review the canonical icon
registry in both themes at 24–48px.

## Risks

The SVG checker rejects common active features; it is not a general
sanitizer for arbitrary uploads. Optical balance still requires human
review. Remote fallback for unknown brands retains existing behavior.
This change does not add an asset importer or new connector
capabilities.

## Model Used

OpenAI Codex, assisted by GPT-5 and GPT-6 with code execution and
browser tooling. Exact hosted model IDs and context window sizes were
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
- [ ] 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


## Artwork comparison

Before and after for every affected identity. Images follow your GitHub
light/dark theme and are pinned to the base and PR commits. This
compares artwork; the existing gray rounded product frame and padding
are unchanged.

| Connector | Before | After |
|---|:---:|:---:|
| AgentMail | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/agentmail-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/agentmail.svg"
alt="AgentMail" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/agentmail.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/agentmail.svg"
alt="AgentMail" width="48" height="48"></picture> |
| Airtable | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/airtable.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/airtable.svg"
alt="Airtable" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/airtable.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/airtable.svg"
alt="Airtable" width="48" height="48"></picture> |
| Asana | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/asana.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/asana.svg"
alt="Asana" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/asana.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/asana.svg"
alt="Asana" width="48" height="48"></picture> |
| ClickHouse | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/clickhouse.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/clickhouse.svg"
alt="ClickHouse" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/clickhouse-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/clickhouse.svg"
alt="ClickHouse" width="48" height="48"></picture> |
| Cloudflare | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/cloudflare.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/cloudflare.svg"
alt="Cloudflare" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/cloudflare.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/cloudflare.svg"
alt="Cloudflare" width="48" height="48"></picture> |
| Cloudinary | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/cloudinary-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/cloudinary.svg"
alt="Cloudinary" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/cloudinary-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/cloudinary.svg"
alt="Cloudinary" width="48" height="48"></picture> |
| Discord | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/discord.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/discord.svg"
alt="Discord" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/discord-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/discord.svg"
alt="Discord" width="48" height="48"></picture> |
| GitHub | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/github-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/github.svg"
alt="GitHub" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/github-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/github.svg"
alt="GitHub" width="48" height="48"></picture> |
| Gmail | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/gmail.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/gmail.svg"
alt="Gmail" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/gmail.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/gmail.svg"
alt="Gmail" width="48" height="48"></picture> |
| Google Calendar | <picture><source media="(prefers-color-scheme:
dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-calendar.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-calendar.svg"
alt="Google Calendar" width="48" height="48"></picture> |
<picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-calendar.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-calendar.svg"
alt="Google Calendar" width="48" height="48"></picture> |
| Google Chat | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-chat.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-chat.svg"
alt="Google Chat" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-chat.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-chat.svg"
alt="Google Chat" width="48" height="48"></picture> |
| Google Docs | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-docs.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-docs.svg"
alt="Google Docs" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-docs.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-docs.svg"
alt="Google Docs" width="48" height="48"></picture> |
| Google Drive | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-drive.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-drive.svg"
alt="Google Drive" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-drive.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-drive.svg"
alt="Google Drive" width="48" height="48"></picture> |
| Google People | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-people.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-people.svg"
alt="Google People" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-people.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-people.svg"
alt="Google People" width="48" height="48"></picture> |
| Google Sheets | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-sheets.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-sheets.svg"
alt="Google Sheets" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-sheets.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-sheets.svg"
alt="Google Sheets" width="48" height="48"></picture> |
| Google Slides | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-slides.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-slides.svg"
alt="Google Slides" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-slides.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-slides.svg"
alt="Google Slides" width="48" height="48"></picture> |
| Google Workspace Search | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-workspace-search.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/google-workspace-search.svg"
alt="Google Workspace Search" width="48" height="48"></picture> |
<picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-workspace-search.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/google-workspace-search.svg"
alt="Google Workspace Search" width="48" height="48"></picture> |
| Hugging Face | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/hugging-face.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/hugging-face.svg"
alt="Hugging Face" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/hugging-face.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/hugging-face.svg"
alt="Hugging Face" width="48" height="48"></picture> |
| Jam.dev (library only) | New library entry | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/jam-dev-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/jam-dev.svg"
alt="Jam.dev" width="48" height="48"></picture> |
| Jira | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/jira-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/jira.svg"
alt="Jira" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/jira.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/jira.svg"
alt="Jira" width="48" height="48"></picture> |
| Linear | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/linear.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/linear.svg"
alt="Linear" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/linear-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/linear.svg"
alt="Linear" width="48" height="48"></picture> |
| Manufact | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/manufact.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/manufact.svg"
alt="Manufact" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/manufact-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/manufact.svg"
alt="Manufact" width="48" height="48"></picture> |
| Microsoft Teams | <picture><source media="(prefers-color-scheme:
dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/microsoft-teams.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/microsoft-teams.svg"
alt="Microsoft Teams" width="48" height="48"></picture> |
<picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/microsoft-teams.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/microsoft-teams.svg"
alt="Microsoft Teams" width="48" height="48"></picture> |
| Miro | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/miro-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/miro.svg"
alt="Miro" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/miro.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/miro.svg"
alt="Miro" width="48" height="48"></picture> |
| Mixpanel | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/mixpanel.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/mixpanel.svg"
alt="Mixpanel" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/mixpanel-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/mixpanel.svg"
alt="Mixpanel" width="48" height="48"></picture> |
| Netlify | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/netlify.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/netlify.svg"
alt="Netlify" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/netlify-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/netlify.svg"
alt="Netlify" width="48" height="48"></picture> |
| Notion | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/notion-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/notion.svg"
alt="Notion" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/notion.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/notion.svg"
alt="Notion" width="48" height="48"></picture> |
| PagerDuty | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/pagerduty.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/pagerduty.svg"
alt="PagerDuty" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/pagerduty.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/pagerduty.svg"
alt="PagerDuty" width="48" height="48"></picture> |
| PostHog | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/posthog-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/posthog.svg"
alt="PostHog" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/posthog-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/posthog.svg"
alt="PostHog" width="48" height="48"></picture> |
| Postman | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/postman.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/postman.svg"
alt="Postman" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/postman.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/postman.svg"
alt="Postman" width="48" height="48"></picture> |
| Shopify | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/shopify.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/shopify.svg"
alt="Shopify" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/shopify.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/shopify.svg"
alt="Shopify" width="48" height="48"></picture> |
| Slack | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/slack.png"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/slack.png"
alt="Slack" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/slack.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/slack.svg"
alt="Slack" width="48" height="48"></picture> |
| Stripe | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/stripe.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/stripe.svg"
alt="Stripe" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/stripe.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/stripe.svg"
alt="Stripe" width="48" height="48"></picture> |
| Supabase | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/supabase.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/supabase.svg"
alt="Supabase" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/supabase.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/supabase.svg"
alt="Supabase" width="48" height="48"></picture> |
| Telegram | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/telegram.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/telegram.svg"
alt="Telegram" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/telegram.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/telegram.svg"
alt="Telegram" width="48" height="48"></picture> |
| Todoist | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/todoist.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/todoist.svg"
alt="Todoist" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/todoist.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/todoist.svg"
alt="Todoist" width="48" height="48"></picture> |
| Wix | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/wix.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/wix.svg"
alt="Wix" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/wix-dark.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/wix.svg"
alt="Wix" width="48" height="48"></picture> |
| Zapier | <picture><source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/zapier.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/c9e3bb7ca40160b2ff80958ec1a8c0254638ad42/ui/public/brands/apps/zapier.svg"
alt="Zapier" width="48" height="48"></picture> | <picture><source
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/zapier.svg"><img
src="https://raw.githubusercontent.com/paperclipai/paperclip/ea053c60d9d2c5c3470275e2f4dfde5f8fe5db53/ui/public/brands/apps/zapier.svg"
alt="Zapier" width="48" height="48"></picture> |
2026-09-14 05:05:27 -10:00
DottaandPaperclip 3052686b1e fix(ui): hide task chat attribution badge (#13251)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The task chat shows messages from agents and users.
> - An agent message can contain an internal on-behalf-of user value.
> - The new task view showed this value as a badge next to the agent
name.
> - This badge added unwanted identity text to the task chat.
> - This pull request removes the badge from the new task view.
> - The benefit is a simpler agent identity row in the task chat.

## Linked Issues or Issue Description

**What happened?**

The new task view shows a `for <user>` badge next to an agent name when
a message has an on-behalf-of user value.

**Expected behavior**

The task chat shows the agent name without the on-behalf-of badge.

**Steps to reproduce**

1. Open the new task view.
2. Show an agent message that has an on-behalf-of user value.
3. See the attribution badge next to the agent name.

**Paperclip version or commit**

The issue occurs on `master` at commit `d0b7ba419`.

**Deployment mode**

Local dev and all other modes that use the web UI.

## What Changed

- Removed the attribution chip from the task chat agent identity.
- Added a regression test that supplies an on-behalf-of value and
confirms that the badge is absent.

## Verification

- `pnpm --filter @paperclipai/ui exec vitest run
src/components/task-chat/TaskChatBubble.test.tsx` passed with 21 tests.
- `pnpm check:token-gates` passed.
- `pnpm --filter @paperclipai/ui typecheck` passed.

## Risks

- Low risk. The change only removes one badge from the new task chat
view.
- The message data remains unchanged.

> This is a small UI fix. It does not add roadmap scope.

## Model Used

- OpenAI Codex, GPT-5.4, with reasoning and tool use. The provider did
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/no-internal-issue-references`, `fix/sandbox-secret-resolution`)
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-09-14 09:58:44 -05:00
DottaandPaperclip ef84f363b7 fix(ui): remove execution workspace access card (#13406)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - Execution workspace pages show the tools and state for one isolated
workspace.
> - The workspace access card repeats runtime state that the page
already shows.
> - The card also adds open and repair actions that are not needed on
this page.
> - This pull request removes the complete workspace access card from
execution workspace detail pages.
> - The benefit is a smaller page that keeps attention on workspace
controls and work results.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The execution workspace detail page shows a workspace access status
card.

**Current behavior**

The page can show Ready, preparation, degraded, failed, or Workspace is
not running states. The card can also show Open workspace and repair
actions.

**Proposed behavior**

The page does not show the workspace access status card or its page-only
actions.

**Reason and benefit**

The card adds status and controls that are not needed on this page. Its
removal makes the isolated workspace page simpler.

**Breaking changes**

The workspace access card and its actions are no longer available from
the execution workspace detail page. Workspace runtime controls remain
available.

## What Changed

- Removed the workspace access status card from execution workspace
detail pages.
- Removed the page-only login handoff and repair mutations that served
the card.
- Added a regression test for the removed card and text.

## Verification

- `pnpm exec vitest run ui/src/pages/ExecutionWorkspaceDetail.test.tsx`
passes with 8 tests.
- `pnpm typecheck` passes.
- `pnpm check:token-gates` passes.
- `pnpm build` passes.
- `pnpm test:run` found unrelated failures in
`server/src/__tests__/workspace-runtime.test.ts` during the local broad
run. The focused changed-area tests pass.
- The complete GitHub Actions matrix passes on the latest run, including
build, typecheck, server tests, runner verification, and e2e tests.

## Risks

- Low risk. The change removes one UI card and the page-only code that
supported it.
- Users must use the remaining workspace runtime controls instead of
this card.

> This change is focused UI cleanup. It does not add a roadmap feature.

## Model Used

- OpenAI Codex based on GPT-5, with reasoning, tool use, and code
execution. The exact context window is not exposed in this environment.

## 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-09-14 09:47:10 -05:00
DottaandPaperclip 4cd7b40255 fix: recover new messages after historical native runs stop (#13405)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native recovery must distinguish a fresh user request from replay of
failed work.
> - Older runs can lose their process fields before a local stop receipt
exists.
> - A suspended durable session can still prove that the exact runner
and provider session are idle.
> - The message admission path ignored that evidence and kept new user
messages blocked.
> - This pull request uses the existing exact-state verifier for those
historical runs.
> - The user can start one fresh turn while the old history and unknown
outcomes remain intact.

## Linked Issues or Issue Description

**What happened?**
A user sent a new message after a native run exhausted recovery.
Paperclip saved the message but said the previous run had no verified
stop record. The old runner was suspended, with no active provider turn
or pending output. Its process fields had been cleared before stop
receipts were added.

**Expected behavior**
A new user message starts a fresh turn when the exact retained session
proves it is suspended and the other execution gates pass.

**Steps to reproduce**
1. Retain a failed native run with a terminal controller, cleared
process fields, and no process receipt events.
2. Retain its exact suspended runner state and idle provider state. Keep
its recovery hold.
3. Send a new user comment. Before this fix, admission returns no
successor.

**Paperclip version or commit**
Reproduced on master at d351e08de.

**Deployment mode**
Self-hosted server. The regression uses an embedded PostgreSQL test
database and real durable state files.

Related work: Refs #13270, Refs #13338. This adds compatibility for
older stopped runs. Refs #13332 concerns separate recovery-hold scope
rules.

## What Changed

- Add exact suspended-state evidence to explicit native message
admission for runs that predate process receipts.
- Reuse the existing failed-retry verifier for run, runner, workspace,
provider identity, and pending-work checks.
- Reject this fallback if any server-authored process receipt or launch
event exists.
- Add a red/green regression with real message admission, duplicate
delivery, dry-run behavior, and blocked-state cases.
- Document the new-message recovery rule.

## Verification

- Red: the historical suspended-state regression failed on master
because admission returned null. Eight rejection cases passed.
- Green: 469 tests passed across explicit native continuation and native
session execution.
- Full repository `pnpm -r typecheck` and `pnpm build` passed locally.
- The complete Vitest CI matrix and all browser test shards passed. The
duplicate local `pnpm test:run` was stopped after these CI results; it
did not complete locally.
- The first runner verification worker received an infrastructure
shutdown signal during compilation. The single retry passed.
- Greptile reviewed commit `6836d7310` at 5/5 with no findings.
- Inspected the affected server's database and durable state read-only.
It has the historical missing-PID shape and an exact suspended runner
with no active provider turn, pending tools, or undelivered output.

## Risks

- Incorrect idle evidence could allow overlapping work. The fallback
requires an exact suspended root and rejects active or pending work,
mismatched identities, missing files, and newer process evidence.
- Normal task, controller, lease cleanup, decision, and active-run gates
remain in force.
- This does not resume old provider actions or reset recovery attempts.
Unknown outcomes remain unknown.
- No schema change or deployment is included.

## Model Used

OpenAI Codex, GPT-6. The session does not expose the exact model
snapshot or context-window size. Used reasoning, repository inspection,
code editing, shell execution, and test 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-09-14 09:45:34 -05:00
DottaandPaperclip d351e08dee fix(ui): stop Recent Tasks storage feedback across tabs (#13402)
Version recent-task snapshots separately from activity, reject stale cache updates, and publish only on query or membership changes. Migrate history into an isolated storage namespace while preserving restart retries.

Add regression coverage for conflicting caches, migration, comments, unchanged writes, and storage implementations on Node 24 and Node 26.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
canary/v2026.914.0-canary.0
2026-09-14 08:05:06 -05:00
Devin Foley 13368c5183 fix: unblock clean-machine onboarding for api_key AI connections (nightly smoke) (#13372)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The release pipeline gates each nightly on a Docker onboarding
smoke. The smoke proves a clean machine can finish onboarding and hire
the first agent.
> - #13247, #13248, #13344, and #13351 changed the Connect step. Connect
now creates an AI connection that the server verifies live with the
provider.
> - The managed adoption check also demanded a CLI hello probe. A clean
machine has no provider CLI and cannot complete a subscription login.
Onboarding dead-ends and the nightly gate fails.
> - This pull request lets a live-verified API key adopt on the engine's
own verdict, and re-verifies the key with the provider at adoption time.
> - It also drives the release smoke through the API-key path against a
provider mock that lives inside the test harness.
> - The benefit is a green, deterministic release gate with no paid
credential in CI, and a working first run for API-key users on clean
installs.

## Linked Issues or Issue Description

No public issue exists. The failure surfaced in the nightly release
gate. Related PRs (no duplicates found): #13247, #13248, #13344, #13351
(the Connect changes), and #12423, #12135, #12151 (earlier release-smoke
updates).

**What happened?**

The nightly Release cut failed its gate: [run
34749840498](https://github.com/paperclipai/paperclip/actions/runs/34749840498),
job `smoke_nightly / smoke`, on published canary `2026.913.0-canary.2`.
The wizard never left the "Connect a model" step. The subscription path
waits for a human to run `claude auth login` on the server. The API-key
path saves and live-validates the key, but the environment test then
fails with `Command not found in PATH: "claude"` and
`ai_connection_validation_incomplete`, and the wizard blocks the hire.

**Expected behavior**

A clean machine with a provider-accepted API key completes onboarding
and hires the lead agent. The release smoke passes without a real paid
credential in CI.

**Steps to reproduce**

1. Run `scripts/docker-onboard-smoke.sh` with
`PAPERCLIPAI_VERSION=2026.913.0-canary.2`.
2. Sign in, complete onboarding to "Connect a model", select "Use API
key instead", pick Claude, enter a valid API key, and press Connect.
3. The environment test fails on the missing `claude` CLI and blocks the
hire.

**Paperclip version or commit**

`2026.913.0-canary.2` (nightly candidate `c9e3bb7ca`).

## What Changed

- `server/src/routes/agents.ts`: `testManagedEnvironment` no longer
forces the CLI-lane hello probe for a resolved `api_key` binding. It
re-verifies the key against the provider's live endpoint instead (the
same `validateAiApiKey` check the save performed, which needs no CLI). A
key the provider rejects fails adoption with
`ai_connection_api_key_rejected`. Subscription adoption keeps the strict
hello-probe requirement.
- `scripts/docker-onboard-smoke.sh`: the harness now serves
`api.anthropic.com` itself. A sibling container (the already-built smoke
image) runs a small HTTPS mock. The app container gets `--add-host` for
that one hostname and trusts the mock's certificate through
`NODE_EXTRA_CA_CERTS`. The private key stays mode 600 in the mock
container; the app container mounts only the certificate. The mock
serves only `GET /v1/models` and returns 404 for every other path.
`SMOKE_PROVIDER_MOCK=false` disables it.
- `tests/release-smoke/docker-auth-onboarding.spec.ts`: the spec drives
the API-key path — switch the credential mode before the source tile
(the link hides when the row collapses), enter the key, and Connect.
Loopback targets use a placeholder key that the mock accepts. Any other
target must set `PAPERCLIP_RELEASE_SMOKE_ANTHROPIC_API_KEY`, and the
test fails on arrival without it.
- `server/src/__tests__/agent-test-environment-routes.test.ts`: three
new route tests cover accepted keys (no CLI probe consulted),
provider-rejected keys, and subscriptions that cannot complete a hello
probe.

## Verification

- `npx vitest run src/__tests__/agent-test-environment-routes.test.ts` —
26/26 pass.
- `npx vitest run src/__tests__/ai-connections.test.ts
src/__tests__/ai-legacy-compatibility.test.ts` — 42/42 pass.
- `tsc --noEmit` reports no errors in the touched files.
- Full local harness + suite run against the exact failing canary: the
app container reaches the mock (request visible in the mock log), the
placeholder key validates, and the connection saves as the default. The
flow then stops at the forced CLI hello probe — the exact server check
this PR removes, still present in the published canary. The next canary
that includes this fix is the end-to-end proof.
- Hardening check: from inside the app container, the mock answers with
status 200 and `key.pem` is not visible.

## Risks

- Behavior shift: `api_key` adoption no longer requires a CLI hello
probe. It re-verifies the key with the provider at adoption instead.
Subscription adoption is unchanged.
- The mock returns 404 for unexpected provider calls, so a future
onboarding change that calls a new endpoint fails the smoke loudly
instead of passing silently.
- Release-smoke runs against non-loopback targets now require an
explicit key and fail fast without one.
- No database migration. No dependency change. No provider routing
change.

## Model Used

Claude Fable 5 (`claude-fable-5`) through the Claude Code CLI, with
extended thinking and tool use (shell, file edits, Playwright runs,
GitHub CLI). No other models were used.

## 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-09-13 17:02:02 -07:00
DottaandPaperclip f2c5e54dca fix(runner): preserve handoff work and publish requested files (#13355)
## Thinking Path

> - Paperclip lets people manage AI agents and their tasks.
> - A task keeps its instructions, progress, and files when its assigned
agent changes.
> - The replacement runner lost the interrupted run's context and could
overwrite an existing draft.
> - A saved message also stayed attached to the former agent and could
reopen the task after the replacement finished.
> - File tasks could report Done with only a local path that the user
could not open.
> - This pull request transfers handoff context and saved messages, and
makes requested files accessible through the existing attachment
contract.
> - Users can change agents and collect completed work without repeating
instructions or confirming bookkeeping.

## Linked Issues or Issue Description

Refs #13338. Builds on merged #13354 for queue admission and #13353 for
remote workspace retry. #10123 concerns restricted recovery-model
escalation; this change instead covers ordinary native handoff and file
completion.

**What happened?**

Codex wrote a draft before a user assigned the task to Claude. The
replacement lacked continuation context and replaced the draft. A queued
user message could later restart the former agent and reopen the
completed task. Separately, a runner could finish a requested file but
return only a machine-local path. Remote native runs had no bound file
publication tool.

**Expected behavior**

The replacement reads and preserves existing work, receives saved
messages once, and keeps each message's author. The former agent stays
stopped. A requested file has a working attachment or accessible work
product before Done. Text-only tasks do not require attachments.

**Steps to reproduce**

1. Ask Codex to save three newsletter names and then wait.
2. Queue an instruction to keep those names and expand the draft.
3. Use Interrupt and assign to select Claude.
4. Verify the original names survive, the result has a working download,
and only the source and replacement runs exist.
5. Ask either provider for a Markdown checklist and open the file from
its completed response.

## What Changed

- Carry the exact same-task interrupted run's summary, semantic
receipts, and history into handoff context. Tell the replacement to
inspect existing files before editing.
- Adopt saved ordinary task comments into the successor's receipt under
the task lock. Preserve authors and separate mention, chat, and
interaction contracts.
- Prevent a former-assignee comment wake from reopening a completed task
or starting a stale execution.
- Reject workspace-only, fabricated, and cross-task file completion
references with actionable runner feedback. New file output also needs a
matching current-run publication receipt and asset filename/size/hash,
or an accessible work product registered by the current run. Prior
output can remain context alongside a current file, or be verified and
re-registered internally. Authorized chat attachment reuse retains its
verified current-run clone receipt; older receipt shapes require an
intact matching source.
- Bind remote file reads to the active environment runner and reuse the
existing attachment and work-product publication path.
- Enforce workspace confinement, regular single-link files, stable
identity, a 10 MiB limit, and exact size and SHA-256 checks. Rotate the
native session fingerprint for the updated tool contract.
- Contain rejected remote signals and protocol-failure cleanup,
including logging failures. Preserve the original cleanup rejection for
its owner; a rejected operation never supplies stop acknowledgement or
cleanup proof.
- Allow exactly one maximum-size base64 file through the native SSH
command adapter, preserving a finite output cap.
- Document handoff and accessible file completion rules.

## Verification

- Each observed bug has a failing regression before its fix. Final
post-rebase integration passed 732 tests across 13 files before the
final receipt and signal guards; final affected results are below.
- Publication provenance and compatibility: 8 provenance regressions and
2 compatibility regressions failed before their fixes; the final four
affected suites pass 53 tests, including mixed old/new references and
real authorized chat reuse. Controls cover old attachments and work
products, filename/size/hash/origin mismatch, missing/wrong receipts,
current-run publication, same-run durable proof, internally
re-registering preserved bytes, and no-new-file follow-ups.
- Remote signal rejection: the real Node subprocess previously exited 1
when the production launcher signalled a deleted sandbox. It now stays
alive for both a failed signal and failed logging; all 349 executor
tests pass. The failed signal still provides no termination proof.
- Remote file reader and SSH command boundary: 33 tests passed,
including real Linux descriptor reads and the actual SSH adapter
subprocess output cap (network executable replaced by a deterministic
fixture). Exact 10 MiB bytes pass, one byte beyond the encoded cap
fails.
- Live local Claude and Codex Stop journeys preserve the saved file,
deliver queued instructions once, and reach Done with two total runs.
The handoff journey preserves the original names and download with
exactly two runs. Both local providers deliver exact checklist files
without a completion confirmation.
- Live combined Daytona verification passed: the original failed task's
Retry reused its sandbox; a selected Git subfolder produced an exact
downloadable file; warm and deliberately resumed Claude runs took about
33 seconds. Codex produced a 240-byte download in 33.1 seconds after 134
seconds of contention/backoff. Both cloud downloads retained exact bytes
after the two owned sandboxes were deleted.
- The sandbox-deletion retest identified a separate ignored promise in
protocol-failure cleanup. Two real Node subprocess regressions failed
under fatal unhandled-rejection policy before the fix; all 36 protocol,
lifecycle, and integrity tests now pass. The original close promise
still rejects to its owning runtime. The final live retest passed: a
normal Claude Daytona task completed in 132.352 seconds, then its
sandbox was deleted. Thirteen samples over 361 seconds confirmed the
same controller stayed healthy, the task stayed Done with unchanged run
IDs, and its attachment retained exact bytes. The post-deletion browser
download passed with zero page errors; all five owned sandboxes are
confirmed absent.
- Full repository typecheck and build passed on final commit
`de64d16f1`. Final-head Greptile is 5/5 with no unresolved threads.
[Final-head
CI](https://github.com/paperclipai/paperclip/actions/runs/34736623758)
passed: 32 successful checks and two conditional skips. The earlier
mixed-source full local test invocation was deliberately stopped before
rebase, so no pristine green full local aggregate is claimed. Its known
failures passed in later affected suites.

## Risks

- Handoff may adopt only ordinary comments from its validated former
owner. Other delivery contracts must remain independent.
- File verification fails closed if a remote file changes during
reading. The runner must retry publication or explain a blocker.
- The updated session fingerprint starts a fresh provider process where
needed to install the new tool contract.
- No schema migration or historical status reconciliation is included.

## Model Used

OpenAI `gpt-6-astra` through Codex, with reasoning, code execution,
browser testing, and tool use. The context-window size is not exposed in
this task.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.913.0-canary.3
2026-09-13 08:41:20 -05:00
DottaandPaperclip 827ba8a434 fix: cancel stalled sandbox startup without waiting for setup (#13352)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Sandbox runs prepare credentials and files before an agent starts.
> - Stop must work during that preparation.
> - ACPX registered cancellation, but did not handle it while a setup
command was waiting.
> - Daytona cleanup waited for that same command before stopping the
sandbox.
> - This change stops the run's sandbox first and requires proof before
abandoning setup.

## Linked Issues or Issue Description

**What happened?**

Stop left a sandbox run active when remote credential setup stalled. The
run kept its connection lease until the sandbox was stopped separately.

**Expected behavior**

Stop terminates the selected run's sandbox, prevents later setup from
launching the agent, and lets run cleanup finish. It must not report
success without proof from the provider.

**Steps to reproduce**

1. Start an ACPX agent in Daytona.
2. Hold a command during remote credential or file setup.
3. Select Stop before the agent starts.
4. Before this fix, cleanup waits for the held command and never reaches
sandbox stop.

Related: #13351 exposed this during connection acceptance testing.
#12150 addresses scheduler load and session initialization limits, a
separate startup problem.

## What Changed

- Handle cancellation during ACPX sandbox preparation with a host-owned
stop callback.
- Pass an explicit active-work cancellation flag through environment
cleanup.
- Stop Daytona before draining setup commands. Keep normal graceful
cleanup.
- Require an exact run and lease termination receipt. Keep ownership of
outstanding requests when stop cannot be verified.
- Reject late setup work and defer sandbox resume until old requests
settle.
- Add regression tests and document the cancellation boundary.

## Verification

- Red: both the stalled ACPX setup test and the Daytona cancellation
test failed before the fix because Stop never reached the provider.
- Green: adapter and Daytona suites passed, along with cancellation
boundary and database-backed receipt/isolation tests.
- Two real Daytona probes ran a five-minute setup command. Cancellation
returned matching stopped receipts in 6.01 and 6.533 seconds. No later
setup command ran. Both test sandboxes were deleted.
- Repository typecheck and build passed locally. The full required CI
suite passed, including all server/workspace tests, browser shards,
Paperclip Runner verification, and canary packaging. The duplicate local
full-suite run was interrupted after CI passed; it is not claimed as a
completed local pass.
- No UI changes. The live probe uses the actual adapter cancellation
boundary and Daytona plugin; it is not a browser acceptance test.

## Risks

- Provider stop failures remain unacknowledged. The adapter keeps
ownership while its original requests remain active.
- A retry can receive a settling-work error until old provider requests
finish.
- Cancelled sandboxes are stopped and retained under their existing
provider expiry policy.
- Local execution and cancellation after the agent turn starts keep
their current behavior.
- Other providers must return an exact termination receipt to permit
early setup cancellation. No database migration.

## Model Used

OpenAI GPT-6 through Codex, with code execution and tool use. The exact
deployment identifier and context window are not exposed in this
session.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-13 08:35:43 -05:00
DottaandPaperclip c9e3bb7ca4 fix: preserve queued work after native Stop and honor steering support (#13354)
## Thinking Path

> - Paperclip lets people manage AI agents and their tasks.
> - The runner owns execution, while the task keeps user instructions
and status.
> - Stop must stop the current response without losing instructions that
the user already sent.
> - The queue stored its original reason inside saved context. Recovery
checked the outer deferred reason and left the message waiting.
> - Claude also exposed Steer through a shared method even though its
driver did not support it. A rejected request could remove its own error
row.
> - This pull request keeps queued work until execution has stopped,
uses the driver's real capability, and preserves completion event order.
> - Users can continue work without repairing task state or repeating
messages.

## Linked Issues or Issue Description

Refs #13338. Related recovery work: #13353.

**What happened?**

A message sent during a native run stayed queued after Stop. Claude
exposed an unsupported Steer action. A steering failure could hide the
queued row and its error. A terminal event could also precede the final
provider result, and subtree Stop omitted the board actor.

**Expected behavior**

Stop ends the current execution. Once Paperclip proves that execution
has stopped, it delivers the saved instruction once through normal
admission. Pause and recovery holds still prevent dispatch. Unsupported
controls stay disabled, and a rejected action leaves an actionable error
visible. Final results precede terminal events.

**Steps to reproduce**

1. Start a Claude or Codex task that writes a file and then waits.
2. Send a follow-up instruction while it runs.
3. Press Stop. Check that the queued instruction runs once and preserves
the file.
4. Check Claude's Steer control and simulate a server rejection on the
only queued message.

## What Changed

- Recover saved native comments after acknowledged Stop using their
original wake reason.
- Require durable remote termination receipts or verified local process
termination before dispatch.
- Preserve actor identity, queued-message deduplication, Pause, and
recovery gates.
- Derive steering support from the driver descriptor and reject
unsupported calls.
- Keep the queue mounted until a steering request succeeds so its error
remains visible.
- Emit provider results before terminal events and pass the board actor
into subtree Stop.
- Document Stop and steering behavior.

## Verification

- Final-head continuation suite: 104 passed, after failing regressions
for saved wake reasons, cleanup proof, and deduplication of every queued
message. Steering UI: 121 passed. Driver capability: 26 passed. Runner
backend/transport: 205 passed; Rust library: 285 passed.
- Real Claude and Codex browser journeys both preserved the saved file,
delivered the queued instruction once after Stop, and reached Done with
exactly two total runs. The process Stop browser fixture also passed.
- Local full repository typecheck and build passed on `afaa35139`;
server typecheck and the affected 104-test suite passed after the final
queue changes. Token gates passed. Final-head CI verifies the complete
integrated source.
- Local aggregate evidence has explicit limits: the general-server
invocation overlapped the queue fixes and finished with 11,989 passed, 2
failed, and 80 skipped; both failures are covered by the final 104-test
pass. The UI and CLI then passed all 6,184 and 485 tests; the complete
145-file serialized rerun passed all 2470 tests. The shared-package lock
fixture passed unchanged on rerun, but the package phase subsequently
stopped at an embedded-Postgres bootstrap resource failure. No single
pristine green local full aggregate is claimed.
- Greptile reviewed `fa66e2bd5` at [5/5 with no unresolved
findings](https://github.com/paperclipai/paperclip/pull/13354#issuecomment-5650334242).
[Final-head CI completed
successfully](https://github.com/paperclipai/paperclip/actions/runs/34733781888/attempts/2):
33 successful checks, 2 conditional skips, including all server,
package, UI, browser, runner, typecheck, and build gates. The first
attempt hit a preview-readiness/port-collision fixture; its unchanged
local control passed 25 tests with 3 skips, and one supported unchanged
CI retry passed the affected shard and aggregate gates.

## Risks

- Queue recovery must never overlap an old execution. Unknown cleanup
state remains blocked.
- Driver descriptors are now authoritative for steering; a wrong
descriptor disables the action instead of attempting it.
- No schema migration or historical status reconciliation is included.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, code execution, browser
testing, and tool use. The exact hosted model ID and context-window size
are not exposed in this task.

## 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
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.913.0-canary.2
2026-09-12 22:29:54 -05:00
DottaandPaperclip 6809314a3f fix: recover sandbox workspace setup and retries (#13353)
## Thinking Path

> - Paperclip manages AI agents and their tasks.
> - Sandbox tasks need a workspace and a provider session before work
can start.
> - A selected Git subfolder is a valid workspace, but it is not a
repository fetch source.
> - A resumed sandbox must keep one resource identity when the provider
fills in its region.
> - Workspace reuse does not prove that a provider session has started.
> - A recorded continuation must not leave an old failure blocking Retry
for a newer attempt.
> - This pull request fixes those setup and recovery boundaries while
preserving ownership checks.

## Linked Issues or Issue Description

**What happened?**

A Daytona task failed before provider startup when its project folder
was inside a parent Git repository. After the folder was repaired, Retry
resumed the same sandbox and verified its workspace sentinel, but
workspace preparation reported that the lease was no longer active. A
later attempt could fail because the resumed workspace had no provider
checkpoint. The old run also kept a recovery projection after the server
recorded its explicit successor, hiding Retry for the new failure.

**Expected behavior**

Sync the selected folder without importing parent files or history. Keep
the existing sandbox identity stable. Allow a new provider session only
with proof that its exact session has never started. Let the current
failed attempt retain Retry once the old recovery has a recorded
successor.

**Steps to reproduce**

1. Select a subfolder of a Git repository as a project workspace and
start a Daytona task.
2. Leave the target region unset. Release its reusable sandbox after
setup fails, then resume and realize the workspace.
3. Retry a provider setup that failed before any session directory or
checkpoint was created.
4. Record an explicit successor for a native failure, fail that
successor during setup, and inspect Retry in the task thread.

**Paperclip version or commit**

Reproduced against `8d1f0c20a` with new failing regressions before each
production fix.

**Deployment mode**

Local controller with a Daytona environment. Automated tests use
deterministic provider fixtures and real filesystem operations.

Related: #13338, #13163, #13264, #13349. The open work-folder stack in
#13264 includes a broader fresh-session authority change. This patch
addresses the independently reproduced startup failure with existing
durable bootstrap proof and atomic directory creation. It does not
include the work-folder migration or credential changes from that stack.

## What Changed

- Classify only the selected Git repository root as a fetch source. Sync
subfolders as directories and preserve their enclosing Git ignore rules
on upload and restore. Recognize the shared scheduler’s completed
non-repository result so ordinary folders still sync; timeout,
cancellation, and output-limit failures remain closed.
- Remove the placement target from Daytona account cache identity. Keep
API endpoint, credential digest, company, environment, driver, and
sandbox ID boundaries.
- Preserve closed-lease admission until a sentinel-verified resume
reopens that same resource.
- Show the already-recorded explicit successor of a resolved recovery.
Keep the old failure evidence and unresolved holds. No historical status
writes occur.
- Permit a resumed workspace to create a new session directory only with
matching durable identity, zero connections and events, untouched
bootstrap commands, no backup, and an absent remote session. Claim the
directory atomically. Existing, partial, or ambiguous state still blocks
startup.

## Verification

- Final head `c43c7403f`: [CI completed
successfully](https://github.com/paperclipai/paperclip/actions/runs/34733846820/attempts/2),
with 32 successful checks and 2 conditional skips. This includes every
server, UI, package, serialized-route, browser, native-runner,
typecheck, and build gate. Greptile reviewed the same head at [5/5 with
no unresolved
findings](https://github.com/paperclipai/paperclip/pull/13353#issuecomment-5650270168).
- New regressions failed before each of the four production fixes.
Git/archive/restore suites: 148 passed. The scheduler-wrapped non-Git
regression also failed before its fix; 135 affected Git/sync/Codex tests
then passed.
- Daytona plugin: 230 passed, 6 opt-in live tests skipped. Native
executor, projection, and TaskChatThread: 494 passed, including
existing/partial state, wrong identity, prior connections or turns,
backups, unavailable proof, and unresolved recovery controls.
- Local full-repository typecheck, build, and token gates passed on the
final head. Local CLI: 485 passed. Complete single-worker package rerun:
3,224 passed, 19 skipped.
- Local verification is an aggregate with recorded retries, not one
pristine green invocation: the general-server run began on `e721a920a`
and finished with 12,002 passed, 3 failed, 70 skipped. Its real Codex
scheduler failure is fixed above; the socket and workspace-runtime
timeout failures passed unchanged in focused reruns. Both Inbox failures
passed unchanged in the full 27-test Inbox file; database/shared-package
failures passed in the single-worker package rerun. The supplemental
local serialized-route rerun remains in progress; all five corresponding
final-head CI lanes passed.
- The first final-head CI attempt hit a Daytona fixture-readiness race
and a signoff-browser heartbeat receipt timeout. One supported unchanged
failed-job rerun passed both and the aggregate gates. Live combined
user-journey verification is tracked in the related follow-up; this PR's
provider tests use deterministic fixtures and real filesystem checks.

## Risks

- A selected subfolder uses directory sync and does not carry parent Git
history. Its ignored files stay local.
- The target region remains a creation setting and part of workspace
reuse policy; it does not split the account identity of an existing
sandbox.
- Incomplete or conflicting provider state still fails closed. This
change does not erase a session, infer completed work, bypass a user
decision, or replay uncertain actions.
- A later remote setup failure can leave a claimed partial session
directory. It remains blocked rather than being overwritten.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, and code
execution. The exact hosted model ID and context-window size are not
exposed in this task.

## 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-09-12 22:19:42 -05:00
DottaandPaperclip 8d1f0c20af fix: let responsible users choose either AI subscription or API key (#13351)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - AI Connections select the account used for each run.
> - A responsible-user binding must follow the person whose work the
agent performs.
> - The saved sign-in method currently blocks users with another method
for the same provider.
> - This pull request resolves a personal default by company, user, and
provider.
> - Each user can use a subscription or API key with the same bot and
model.

## Linked Issues or Issue Description

Refs #13247, #13248, #13346, #13347.

**What happened?**
A bot configured with a Claude subscription rejects another responsible
user’s Claude API key. Inline repair also limits that person to the
original sign-in method.

**Expected behavior**
The same bot uses each responsible user’s default Claude account,
whether it is a subscription or API key. Explicit shared account
selections remain fixed.

**Steps to reproduce**
1. User A connects a Claude subscription and creates a bot using the
responsible user’s connection.
2. User C connects a personal Claude API key.
3. User C runs the same bot. Before this fix, credential resolution
fails.

## What Changed

- Add a personal provider-default table. Preserve legacy per-method
preferences and backfill the most recently updated preference, including
unavailable defaults. Repeated migration does not replace a selection. A
database trigger propagates old-server default updates without treating
new accounts as replacement defaults.
- Resolve responsible-user bindings by provider. Retain the method as a
wire compatibility hint for old servers. Explicit selections still
require the exact method and grant.
- Use the selected account’s method for credential isolation, refresh
locking, and run attribution.
- Update onboarding, agent setup, the picker, and inline task repair.
Keep existing authentication components and harness/model settings.
- Add mixed-method runtime, migration, repair, and Storybook coverage.
Include upstream’s duplicate Anthropic option fix through the base
branch.

## Verification

- Focused resolver, migration, connection-intent, onboarding, agent
setup, model, and connector UI suites: 331 tests passed.
- Onboarding and new-agent regression suites passed during the initial
focused run.
- UI typecheck, token gates, and Storybook build passed.
- Live browser checks passed for Claude and Codex API-default execution,
switching both back to subscriptions, and both existing shared-account
bots. Bot configuration remained unchanged.
- One Daytona startup command stalled before Claude launched. The test
run was cancelled, its sandbox stopped, and the same account/task passed
on retry. Startup cancellation remains a separate environment finding;
this PR does not change that command transport.
- Browser review: all eight assertions passed in the new mixed-method
story, including shared selection, return to responsible-user selection,
and unchanged harness/model.
- Repository build and typecheck passed after refreshing upstream
dependencies. Final resolver and historical rollback verification: 38
tests passed. All latest-head CI gates passed, including
server/workspace/serialized suites, browser E2E, build, typecheck, and
runner verification. The extra serial local full-suite run was stopped
after equivalent CI passed; focused local checks completed.

## Risks

- Users with both historical method defaults get their most recently
updated preference as the initial provider default. They can change it
explicitly in Connections.
- A revoked or unavailable default blocks. Connecting an additional
account does not silently replace it.
- Existing legacy authentication is unchanged. Managed responsible-user
bindings intentionally stop pinning a method.
- Live staging: the same Claude and Codex bots completed real API-key
runs after changing only the personal default, then completed
subscription runs after restoring the original defaults. Read-only
database verification confirms unchanged bot configuration and actual
method attribution. Distinct-user concurrency is covered by automated
real-database tests with synthetic credentials, not two live human
logins.

## Model Used

OpenAI GPT-6 (Codex), with reasoning, repository tools, code execution,
and browser interaction. 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>
canary/v2026.913.0-canary.1
2026-09-12 20:27:26 -05:00
DottaandPaperclip 422287eecd fix: preserve runner recovery, warm sessions, and task outcomes (#13338)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The native runner connects task messages, provider execution, and
task outcomes.
> - First-time user tests exposed gaps in recovery, completion
permissions, message delivery, and Stop behavior.
> - These gaps left usable output hidden, completed work waiting for
bookkeeping, or safe work unable to continue.
> - This pull request fixes the shared lifecycle and receipt paths while
preserving process ownership and action checks.
> - Users can continue work with accurate task state and durable
messages.

## Linked Issues or Issue Description

**What happened?**

A stopped local Codex execution could remain blocked even after its
processes had stopped and its complete transcript proved that no
external action needed replay. Claude under Conservative permissions
could fail to call task completion tools. Recovery could reuse an
assistant item ID and overwrite prior output. A delivered comment could
remain marked uncertain after navigation. Stop could look like Pause or
a new recovery incident. Workspace contention could look like
cancellation. A direct reply reopening Done could enter a clarification
loop.

**Expected behavior**

Recover automatically only with verified termination and complete action
receipts. Preserve answers and messages. Keep task completion available
under Conservative permissions without broad tool access. Show crashes
as Blocked, actual human decisions as In Review, and ordinary workspace
contention as waiting. Stop the current response and allow a new
direction.

**Steps to reproduce**

1. Create ordinary response tasks with local Codex and Claude Code, then
send follow-up messages through the task composer.
2. Interrupt a disposable local Codex runner during text-only work.
Verify automatic continuation and retained output.
3. Stop a response, send a new request, answer a clarification, and
reopen completed work with another message.
4. Navigate or reload while a comment submission is pending. Confirm the
exact persisted request receipt settles it without removing newer draft
text.
5. Run two tasks in a shared Daytona workspace. Confirm waiting does not
appear as failure.

**Paperclip version or commit**

Initial acceptance baseline: `c9021c6721f91e2c74bd9fee9d3fd41c999d17b7`.
Current integration base: `6cef9743c`. Both operator-interruption and
workspace-waiting guards are preserved; native restart and legacy
permission rules remain documented.

**Deployment mode**

An isolated source-built test-drive instance, with real local Codex and
Claude Code providers and disposable Daytona environments.

Related work: #13314, #13316, #13327, #13344, #13239, #13254, #13163.
This PR addresses additional failures from ordinary task journeys,
including controller restart handoff and repeated warm sandbox setup.
Historical task status reconciliation is excluded.

## What Changed

- Persist runner ownership immediately at spawn and resume an explicitly
adopted runner even when the controller crashed before the first driver
checkpoint. Detach the controller safely across graceful restarts,
including session startup. Prevent an old finalizer from suspending or
signaling an adopted runner. Checkpoint idle warm sessions before
shutdown. Preserve the same run and queued follow-up messages.
- Scope saved legacy queue successor checks to the queue owner while
preserving ordinary task locks, operator identity, assignment gates, and
exactly-once delivery.
- Preserve managed Codex credential files when an old session is
detached for restart; normal owned cleanup still copies refreshed auth
back and removes the scoped copy.
- Reuse the bound warm shared sandbox and fully verify an existing
staged provider pack before using it. This avoids repeated uploads when
the pack is already valid.
- Add a narrow local Codex replacement path with stopped-process proof,
a closed transcript inventory, exact completion receipts, and
fresh-session lineage. Preserve no-replay holds when evidence is
incomplete. Recovery may clear only the same run's recorded Blocked
status version; manual re-blocking and dependency changes invalidate
that receipt, while queued comments do not. Later blocks stop scheduled,
queued, and final dispatch; queued/final checks re-read dependencies
even when the task status stays In Progress.
- Permit only task delivery and human-input tools through the isolated
Claude runner's exact task bridge.
- Scope assistant item identity to the provider turn and ignore only
authority-free Codex skill-change notifications during startup.
- Reconcile composer submissions by client request ID across response
loss, navigation, and reload. Retain text typed during delivery.
- Keep acknowledged run-only Stop neutral and show workspace contention
as waiting. Project exhausted native failures as Blocked.
- Restore the guarded task-page retry action for failed legacy runs,
including the server-supported explicit new-attempt path for stopped
conversation adapters. Preserve native/process recovery holds and avoid
promising Retry while a decision or execution gate hides it.
- Refresh delivered artifacts and handle direct user replies that reopen
completed work without a clarification loop.
- Check the embedded PostgreSQL PID, data directory, and actual port
before connecting or migrating.
- Document accepted behavior and add focused regressions at lifecycle,
route, transcript, and UI boundaries.

## Verification

- Final head `fece606ac2` passes the complete GitHub CI matrix: **34
green checks, two expected Storybook skips, no failures or pending
checks**, including `ci / verify`, `ci / e2e`, full runner verification,
typecheck, build, every server/workspace shard, and all browser shards.
[CI
run](https://github.com/paperclipai/paperclip/actions/runs/34727183287).
Greptile is **5/5 with no open findings**. The final two commits only
refine test fixtures; both affected suites pass 24/24 locally and in CI,
with server typecheck green.
- Complete local Vitest coverage uses the canonical groups/shards: all
635 general server suites, all 145 serialized suites, and all workspace
packages. The aggregate began on `0a8001c18` while the final queue fix
arrived: 23,903 passed, five failed, 87 skipped. The five
port/socket/timing failures passed unchanged in follow-ups (60 tests in
the exposure/file suites and 412 tests covering the serialized failures
and unrun tails). The final queue/operator-identity suites separately
passed 52/52. This is aggregate coverage plus explicit reruns, not a
pristine single-command final-head run.
- After integration with current master,
queue/operator-identity/continuation suites passed 162/162 and affected
UI suites passed 140/140. ACP Stop/continuation and legacy
task/Inbox/message browser suites passed 9/9, including both task
recovery Retry and thread Try again, automatic saved-message delivery,
exactly one new run, Done, and retained output after reload. The default
process Stop/Pause/Resume browser case passed (the native-provider case
is opt-in and skipped by default). The complete Board attachment/receipt
browser suite passed 11/11 on a disposable instance, covering both
composers, exact receipts after lost responses, no replay, bound
attachments, and newer drafts after reload.
- Blocking-intent regressions cover pre-existing Blocked, a mismatched
run/cause, an explicit manual re-block, changed dependencies, a queued
comment after failure, and a block arriving between scheduling and
provider dispatch. The negative cases reproduced before the fix. All 478
affected executor/recovery/dispatch tests passed; both database suites
ran separately after availability-probe skips in the first combined
command. The final late-dependency check passed all 143 affected
recovery/dispatch tests (zero skips) after two new negative cases
reproduced the bug.
- Focused runtime regressions cover awaited runner ownership
publication, authenticated adoption before the first checkpoint,
old-finalizer detachment, idle and busy warm-session shutdown, rejected
checkpoint propagation, provider-pack verification, and managed-Codex
credential preservation. Four managed credential detachment cases
reproduced the bug before the fix; normal owned cleanup still succeeds
exactly once.
- Live local Claude: SIGKILL 2.6 seconds into startup recovered the same
run automatically in 53 seconds, then a normal follow-up completed in 24
seconds. SIGTERM 2.5 seconds into startup preserved the same run (54
seconds) and its queued follow-up (21 seconds). Answers remained visible
and the task reached Done.
- Live Claude Daytona: a warm follow-up retained its sandbox and fell
from 121 seconds to 44 seconds. A separate cold turn took 127 seconds;
after controller shutdown and checkpointing, its follow-up completed in
33 seconds with the same sandbox, workspace, native session, and runner.
Both answers remained visible and the task was Done.
- Other live journeys covered task completion and follow-up with local
and Daytona Codex, local Codex crash recovery, Stop then new direction,
clarification response, live artifact refresh, and shared-workspace
waiting.
- Validation limits: the opt-in native composer Stop/Pause→subtree
Resume fixture exposes terminal/result ordering and subtree-cancellation
attribution bugs that can leave a child task blocked; that new finding
is assigned to a separate follow-up and is not claimed fixed here.
Default CI skips this optional native-provider fixture. Managed-Codex
credential handoff and the queue-agent integration use automated
regression evidence. Cold custom provider-pack uploads still add startup
latency.

## Risks

- Automatic replacement remains deliberately narrow: local Codex,
verified stopped identities, unchanged retained state, and a complete
text/completion-only turn. Unknown actions, partial history, or changed
ownership remain blocked.
- Claude completion permission handling changes an upstream package
patch. The exact isolated task bridge must remain pinned; unrelated
tools keep their existing permissions.
- New task failure projection changes user-visible status. No historical
status backfill or database migration is included.
- This is a broad lifecycle fix across server and UI. Live proof covers
graceful local Claude restart during startup and idle Claude Daytona
session recovery across controller shutdown. Live abrupt SIGKILL during
local Claude startup also recovered the same run. Unknown ownership or
missing action evidence still blocks reuse. Cold custom provider-pack
uploads still add startup latency; this change avoids unnecessary repeat
uploads.

## Model Used

OpenAI GPT-6 (Codex), with reasoning, code execution, browser
automation, and tool use. The exact hosted model ID and context window
are not exposed in this task.

## 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-09-12 19:41:15 -05:00
DottaandPaperclip 13bae6fa21 fix: reject unsupported REST tool connections without stdio validation (#13346)
## Thinking Path

> - Paperclip manages AI agents and their connections.
> - Connection checks must use the configured transport.
> - The tool service treated every remaining transport as local stdio.
> - Anthropic's old REST method therefore failed with a templateId
error. A REST connection with a valid stdio template could incorrectly
pass.
> - Anthropic now has a supported AI-account flow. This pull request
removes its obsolete REST setup option and limits stdio checks to stdio
connections.
> - Users can connect an AI account, and existing unsupported
connections receive an accurate error.

## Linked Issues or Issue Description

Related: #13248 added the supported AI-account flow. Searches for
related REST health and templateId bugs found no duplicate fix.

**What happened?**

The Anthropic REST API-key connection showed `Local stdio MCP
connections must use an approved templateId`. Health checks and catalog
discovery both fell through to the local stdio path. A REST connection
with an approved template could report success and expose the template's
catalog without a REST integration.

**Expected behavior**

Only local stdio connections use command templates. Unsupported
transports return an accurate HTTP 422 error. New Anthropic accounts use
the supported runtime authentication flow.

**Steps to reproduce**

1. Check out the test-only commit `924e6e85a` in a separate worktree and
install dependencies.
2. Run `pnpm exec vitest run packages/shared/src/app-definitions.test.ts
server/src/__tests__/tool-access-service.test.ts -t 'unsupported
REST|obsolete Anthropic'`.
3. The tests exercise saved Anthropic REST configuration and an
unsupported REST connection containing an approved stdio template. They
cover health checks and catalog discovery separately.
4. Run the same tests on the fix commit. They pass. The full affected
files also pass.

**Paperclip version or commit**

Reproduced against master `6cef9743c`.

**Deployment mode**

Server transport handling. Reproduced with an isolated embedded
PostgreSQL test database. No provider account or live credentials are
required.

## What Changed

- Restrict stdio health checks and tool discovery to `local_stdio`.
- Return and audit `tool_connection_transport_unsupported` with HTTP 422
for unsupported tool transports.
- Remove Anthropic's obsolete REST method from the generated catalog and
its durable ingestion source. Keep its subscription and API-key AI
methods.
- Cover the reported error, false-success case, rejected obsolete setup,
connection removal, and the UI's AI-account submission path.
- Replace impossible reconnect forms for removed methods with supported
setup, while preserving connection removal.
- Preserve AI-versus-tool intent isolation for legacy requests and
reject new unsupported Anthropic tool requests.
- Document recovery for existing unsupported connections.

## Verification

- Clean-worktree red/green: the same command failed all six regression
cases at `924e6e85a` and passed all six at `4d3de9de0`. The failing run
includes the reported templateId error.
- Green: all 555 tests across the six affected test files passed.
- Recovery UI red/green: three added cases failed before the recovery
fix and passed afterward; all 200 tests across setup, detail, and
advanced controls passed.
- After the recovery UI update, UI typecheck/build and token gates
passed again.
- `pnpm -r typecheck` — passed.
- `pnpm build` — passed.
- `pnpm check:token-gates` — passed.
- Catalog regeneration — passed with the documented
`PAPERCLIP_CONTENT_TEMPLATES` override for the local capture corpus.
- Full CI on `69fb31fd4` — passed all general and serialized test
shards, browser shards, typecheck, build, runner verification, and
canary dry run:
https://github.com/paperclipai/paperclip/actions/runs/34726975425.
- The local serial `pnpm test:run` was stopped after the fixture
correction superseded that run; full-suite verification above comes from
CI. All 555 affected tests passed locally, including all 17
connection-intent tests after the correction.
- Greptile — 5/5, successful check on final commit `69fb31fd4`, no
unresolved findings.
- No live Anthropic validation was performed. The UI regression uses a
fake key and a mocked AI-account response.

## Risks

Existing obsolete REST connections remain in needs-attention state.
Users must add an account through the supported flow and remove the old
connection. Credentials and grants are not transferred automatically.
Removal remains covered. The specialized AgentMail and Composio paths
keep their existing behavior. There are no schema or permission changes.

## Model Used

OpenAI GPT-6 through Codex. The exact serving model ID and
context-window capacity are not exposed in this session. Used reasoning,
code editing, shell tools, 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-09-12 19:26:58 -05:00
DottaandPaperclip e704e1c9ae fix: keep AI subscription locks safe through transaction pooling (#13347)
## Thinking Path

> - Paperclip manages AI agents and their credentials.
> - AI Connections must preserve account ownership from login through
execution.
> - A subscription environment check can pass and leave a session
advisory lock on a pooled database backend.
> - The next execution then reports that the subscription is busy.
> - Onboarding can also lose its completion callback when the connection
list refreshes before the login poll.
> - This change keeps each credential lease in one transaction and keeps
the login controller mounted until completion.

## Linked Issues or Issue Description

Refs: #13247, #13248, #13344.

**What happened?**

A real hosted subscription login saved successfully and passed its
environment check. The first task then failed with an AI connection busy
error. A connection-list update could also leave onboarding on
Connecting.

**Expected behavior**

A completed environment check releases its credential lease. A saved
login completes onboarding without another sign-in.

**Steps to reproduce**

1. Run Paperclip with a transaction-pooling PostgreSQL proxy.
2. Connect a Claude subscription through onboarding and reuse it for an
agent.
3. Start a task after its environment check succeeds.
4. For the UI race, refresh the managed connection list before the login
completion poll.

## What Changed

- Hold the grant lock inside one transaction. Roll back on cleanup or
failed acquisition.
- Disable the lease transaction's idle timeout so long provider
executions retain the lock.
- Keep the onboarding login controller mounted while its authorization
URL is active; restore saved-account retry if later agent creation
fails.
- Add lock-lifetime and Claude/Codex completion-order regressions.
- Document the pooling requirement.

## Verification

- 104 focused connection and onboarding tests passed.
- Workspace typecheck, production build, Storybook build, and token
gates passed.
- All 34 latest-head checks are terminal: 32 passed and two Storybook
workflows skipped by their normal filters. CI covers all
server/workspace/serialized test shards, browser tests, typecheck,
build, runner verification, and canary packaging. The additional local
full-suite run is still in progress.
- Real browser sign-ins saved Claude and OpenAI subscriptions on both
new and existing staging stacks. On the patched new stack, both
providers completed tasks and immediate repeat executions with the same
saved accounts. Read-only database inspection confirmed live
transaction-scoped locks and no remaining locks after completion. On the
final deployed head, both shared accounts on the existing stack also
completed actual tasks. Both personal accounts passed a fresh
environment check followed immediately by execution after a deployment
restart.

## Risks

- Each active subscription reserves one database connection and holds an
otherwise idle transaction until cleanup. This is required to pin the
backend through a transaction pool.
- Old session locks from earlier versions may need operator cleanup
after active runs drain. This change does not bypass existing locks.
- No database migration, credential routing, or legacy authentication
change.

## Model Used

OpenAI GPT-6 in Codex, with code execution and browser tools. The exact
deployment model ID and context-window size are not exposed to this
task.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.913.0-canary.0
2026-09-12 19:05:18 -05:00
DottaandPaperclip 6cef9743c0 fix: deliver saved user messages after recovery stops (#13327)
Deliver saved user messages after legacy recovery stops. Validate undelivered comments and queue ownership under the task lock, preserve the operator identity checks from #13315, and prevent duplicate successors.

Add a recovery notice with Retry and inline errors, plus service, route, component, and browser coverage.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-09-12 18:08:04 -05:00
DottaandPaperclip b2acc674be fix: enable isolated subscription login on authenticated self-hosted instances (#13344)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - AI Connections store reusable provider credentials with company and
owner boundaries.
> - Self-hosted instances can require board authentication while running
agents on the local server.
> - The login UI treated those instances as unsupported and displayed
instructions without a command.
> - Removing that restriction must not expose the server operator's
existing CLI account.
> - This pull request enables owner-scoped login attempts and reuses the
existing login UI.
> - Users can connect Codex and Claude subscriptions on an authenticated
self-hosted instance.

## Linked Issues or Issue Description

**What happened?**

On an authenticated self-hosted instance, OpenAI subscription setup
displayed terminal instructions with no command and a disabled Connect
button. Claude also could not complete the local connection flow.

**Expected behavior**

An authorized board user can prepare an isolated sign-in attempt, sign
in on the server, and save the verified account as a Connection. This
must not import another user's or the operator's ambient credentials.

**Steps to reproduce**

Run Paperclip in authenticated mode with a local environment. Open
Connections, choose OpenAI or Anthropic, and select Subscription. The
previous UI never enabled local login preparation.

Related: #13247, #13248, and #10751. This fix preserves the restriction
on remote access to the operator's ambient Claude login.

## What Changed

- Allow company-authorized users to create, check, cancel, and complete
their own isolated local login attempts.
- Keep ambient Claude credential import restricted to the local
operator.
- Support isolated Claude credential files without falling back to the
host account or mutating process-wide environment variables.
- Use Codex device authorization so sign-in does not depend on a browser
callback to the remote server's localhost.
- Gate server-host login on authenticated public deployments unless a
trusted runtime host is configured. Publish the capability through
health so setup shows supported alternatives.
- Read isolated Claude credential files through bounded,
descriptor-bound opens with ownership, permission, and symlink checks.
Try the alternate filename after malformed JSON.
- Reuse shared login instructions and lifecycle hooks in onboarding,
agent setup, and Connections. Show health-query failures explicitly.
- Document authenticated self-hosted behavior and add authorization,
isolation, lifecycle, and UI regression tests.

## Verification

- Passed 71 focused tests across connection routes, credential
isolation, legacy compatibility, the shared login hook, and agent setup.
- Passed 89 onboarding regression tests.
- Passed `pnpm -r typecheck`, `pnpm build`, Storybook build, and `pnpm
check:token-gates`.
- Completed real Codex device authorization and Claude browser
authorization on an authenticated Linux self-hosted instance. Both
accounts were detected automatically and saved as Connected. Both
completed attempt directories were removed.
- These live checks cover login, credential validation, and connection
creation. They do not establish a new model execution or long-running
refresh result.
- Review follow-up: 68 focused checks passed after rerunning one route
socket error; the full route/health rerun passed all 49 tests. The
70-test onboarding suite also passed. Final workspace typecheck,
production build, and Storybook build passed again.
- The broad local run exposed an instance-name assumption in two new
assertions. The fixture now uses an explicit non-default instance, and
all 32 connection tests passed with a different inherited instance name.
The superseded broad run was stopped; this is not a claim that the full
local suite completed. Full CI results will be recorded before merge.

## Risks

- The server must have the provider CLI installed. Users still run the
displayed command on the server that hosts Paperclip.
- Authorization checks must keep login attempts scoped to the company,
owner, provider, and reconnect target. Regression tests cover cross-user
and cross-company access.
- Existing local-trusted Claude behavior stays available. Authenticated
remote users cannot use its ambient import path.
- No database migration, dependency change, agent binding change, or
provider routing change is included.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, code execution, and browser
tools. The runtime does not expose a more specific model version 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
- [ ] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.912.0-canary.12
2026-09-12 23:06:55 +00:00
8b84ae5b35 fix(ui): improve mobile entity picker sheets (#13343)
Co-Authored-By: Paperclip CodexRunner <codexrunner@paperclip.local>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-09-12 22:42:37 +00:00
DottaandPaperclip df984cbc2c fix: dispatch queued legacy messages with operator identity and task permissions (#13315)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task conversations save messages that arrive during an active turn.
> - Legacy adapters deliver these messages in a later turn.
> - A run can stop before the saved queue is delivered.
> - The Interrupt button previously required an active run, so it could
not release this queue.
> - This pull request lets a board operator send the saved queue after
the run stops and retries queues missed during finalization.
> - Manual dispatch must use the clicking operator and must not require
permission to create agents.
> - The task can continue without a duplicate message or a second
execution owner.

## Linked Issues or Issue Description

**What happened?**

A legacy task retained a queued message after its run stopped. Interrupt
was disabled because the queue had no active target. Finalization and
deferred message admission can also leave a queue without a successor.

**Expected behavior**

Interrupt sends the saved messages when no runner is active. Messages
that arrive during normal completion are delivered automatically. An
uncertain previous execution still requires proof that its process or
sandbox stopped.

**Steps to reproduce**

1. Queue a user message during a legacy conversation turn.
2. Let the turn stop or simulate a server restart before queue
promotion.
3. Open the task with a deferred queue and no active run.
4. Try Interrupt. Before this change, the button is disabled.

**Paperclip version or commit**

Reproduced against `8f40b4ad4`.

**Deployment mode**

Legacy conversation adapter. The same persisted queue state is covered
with an isolated PostgreSQL fixture.

Related public work: #13275 adds active legacy interruption. #13291
addresses automatic sandbox conversation recovery. This change handles
explicit saved-queue delivery and late queue promotion.

## What Changed

- Accept a null Interrupt target while retaining queue identity,
revision, company, and assignee checks.
- Save the operator's request on the existing queue. Reuse normal
admission after verified stop, including older messages, different
authors, and queues whose original wake came from the system.
- Strip interruption authority from caller-supplied wake payloads. Only
the board queue route can persist that authority.
- Retry durable interruption requests after restart and deferred queues
after legacy cleanup.
- Let an explicit Interrupt retry cleanup for its stopped run, including
old ephemeral leases that recorded success without a provider stop
receipt. Preserve retained resources, other lease owners, and the
automatic retry limit.
- Preserve the server's waiting explanation when normalizing and
combining queue entries.
- Revalidate the consumed board queue receipt at dispatch so a different
message author does not cause setup failure.
- Use the Interrupt user's execution identity for the new run. Preserve
original message authors. Validate the receipt independently at startup
and inherit the resulting identity on retry.
- Persist authenticated board authority for ordinary manual wakes too.
Adopting someone else's queued messages cannot switch a manual run to
that author's permissions. Strip caller-supplied authority markers and
retain private conversation ownership checks.
- Keep the clicking user when a manual wake is merged into an older
deferred receipt. Update its requester and payload in the same
transaction.
- Use the same current-queue/revision API on task details and pipeline
conversations; show Interrupt after a legacy target stops.
- Keep manual wakes out of active runs, including unscoped agent wakes.
They receive their own execution identity; a matching receipt requester
is not sufficient because an exact retry can retain a different
originating identity.
- Authorize both existing-agent wake endpoints with `agent:wake`,
available to active non-viewer company members. Keep `agents:create` for
hiring. Validate the stored task and current assignee before an exact
task retry.
- Reject viewer Interrupt requests before saving intent or stopping
execution. Keep external chat retry authorization and per-action
agent/user permission checks.
- Preserve edits and discards until dispatch. Prevent another queue
promotion when the same agent already has a successor. Keep independent
reviewer recovery available.
- Suppress cancelled/failed run toasts for intentional operator
interruption. Keep ordinary runtime error notices.
- Add UI, route, admission, restart, successor ownership, and toast
regression tests. Document the behavior.
- Reuse the existing socket reservation helper for both
credential-quorum test cases after CI exposed an ambient-port collision.
This changes test preparation only; production credential staging is
still called exactly once.

## Verification

- Failing regression tests reproduced the message-author identity bug
and an operator's `agents:create` rejection before the fixes.
- All 316 focused tests pass across eight route, queue, identity,
authorization, continuation, and responsible-user suites, including the
44-test rerun of queue admission and actual startup after the final
manual-wake restriction. Regressions reproduce cross-user merging both
with and without a task, and same-requester receipt ambiguity. The
cross-company existence guard also passes both tests.
- Startup integration tests reach adapter execution under the clicking
operator and retain that identity through follow-up. Coverage includes
mixed authors, adopted queues, system-origin queues, restarts, forged or
stale receipts, viewers, suspended memberships, changed assignees,
private conversations, and caller-supplied authority markers.
- The earlier queue/cleanup/UI regression suite passed 402 tests. The
final review corrections pass another 180 tests across queue
admission/persistence, real heartbeat startup, UI API, conversation
rendering, and pipeline suites. Regression tests reproduced both review
findings before correction. The final head has a 5/5 review with no
unresolved threads. Full CI passes on `c2002979c`, including every
general and serialized server shard, all browser shards, Paperclip
Runner verification, typecheck, build, canary dry run, and the aggregate
gates.
- Full `pnpm -r typecheck`, `pnpm build`, and UI token gates pass after
the final application changes. CI identified an outdated task-page API
mock after the shared helper extraction; the fixture now exercises the
real helper, and all 131 task-page/API tests pass. The final application
build passes with the additional manual-wake restriction.
- CI exposed a pre-existing port collision in the Codex
credential-quorum fixture. It reproduced locally; both listener cases
now use the existing bounded reservation helper. All 41 credential tests
pass on rerun. One intervening local run hit a separate ambient bind
collision in the two-occupied-port case.
- The full local `pnpm test:run` attempt was stopped after host
contention caused focused-suite timeouts. The affected focused tests
passed on rerun. An expiring trace fixture and a missing
private-conversation state were corrected. The successful full CI run is
the complete-suite verification.
- Hosted Interrupt previously cleared the original queue and produced
exactly one successor with neutral interruption feedback. It exposed the
dispatch authorization defect. Retry on that earlier build was rejected
for missing `agents:create` before creating another run.
- Deployed the final application build (`38257f391`) to the scoped
hosted instance and verified readiness. The latest PR commit changes
only the credential test fixture; application code matches that
deployment. A live Retry by the same operator without `agents:create`
created one successor attributed to that operator, passing the former
dispatch permission gate. Startup then stopped at
`configuration_incomplete` because that operator has not configured
their required personal Claude Code OAuth secret; the post-deployment
run page confirms the operator identity and no provider work started,
and the My secrets UI still shows the token as not set. Provider
execution remains unverified pending that credential. No permission
grants or credentials were changed.

## Risks

Queue admission and finalization can race. The task lock, durable queue
receipt, current comment IDs, and successor guard prevent duplicate
dispatch. Process and lease stop checks, task pauses, approvals,
ownership, and budgets remain in force. The API change only allows null
on legacy Interrupt; native steering still requires an active run. No
schema migration is required. Active non-viewer board members can now
invoke existing agents without agent-creation permission. Agent
self-invocation rules, raw provider-trace admin access, task retry
scope, external chat authorization, and action-specific user/agent
permissions remain enforced.

## Model Used

OpenAI GPT-6 through Codex. The session does not expose an exact backend
model ID or context-window size. Used reasoning, repository search, code
execution, 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
#` 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-09-12 17:11:30 -05:00
DottaandPaperclip 8d6232e7b0 feat: reuse provider sign-in across AI connection workflows (#13248)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Users connect provider accounts during onboarding and agent setup.
> - They should reuse and manage those accounts through the existing
Connectors interface.
> - A second login wizard would diverge from the established provider
workflows.
> - This pull request composes the existing sign-in components into
Connections and agent configuration.
> - Users can select accounts without changing their agent's harness or
model.

## Linked Issues or Issue Description

**Problem or motivation**
AI credentials are configured separately from Connections. Agents cannot
consistently reuse a responsible user's account or a permitted shared
account.

**Proposed solution**
Manage AI accounts with the existing Connections grants and permissions.
Keep model and harness selection independent from credential selection.
Preserve legacy authentication until validated adoption.

**Alternatives considered**
A separate credential registry would duplicate ownership and access
policy. Automatic fallback would risk using the wrong account.

**Roadmap alignment**
This extends the shipped Apps, multi-user, secrets, and agent-runtime
capabilities. The maintainer requested the feature and reviewed the UI.
Related groundwork: #11899 (connection permissions), #10910 (connection
wizard), #11692 (Claude subscription profiles), and #11854 (Codex
account rotation).

## What Changed

- Add compact AI-account management to the existing Connectors pages.
- Reuse AgentProviderConnection, AdapterLoginPanel, AdapterLoginChrome,
and authentication controllers.
- Add the shared connection picker to agent setup/settings and task
requests.
- Preserve onboarding's sequence and reuse existing accounts.
- Add local-login recovery, retry, cancellation, and React StrictMode
handling.
- Add interactive Storybook scenarios, design-guide examples, and app
acceptance checks.

This is part 2 of the AI Connections change. The runtime foundation in
#13247 is merged. This PR now targets master.

## Verification

- Updated against master `47ded8bf9`, including the landed runtime
foundation and upstream task-search changes.
- Full workspace typecheck, production build, Storybook build, and token
gates passed on the integrated branch. Final local-login changes passed
59 focused tests; new-agent and inbox regression suites passed 63 tests.
- Browser checks verified automatic local Claude account detection,
resumable Codex login commands, retry, focus restoration, and
desktop/phone layouts. Commands create their isolated directory before
invoking the CLI.
- All CI test, browser, build, packaging, and runner jobs passed on
final head `dd17d3211931dd70aaa6ea619d83a7f9966dd18e`. The fresh
Greptile review is 5/5, the security scan passed, and there are no
unresolved review threads. The final CI aggregate gates passed.
- Local general-server coverage passed 11,804 tests; three
port-collision failures passed in an isolated 25-test rerun. All 6,111
UI tests passed. CLI coverage passed 484 tests; its remaining doctor
test requires port 3199, which is occupied by an unrelated report server
on this Mac. The complete CLI suite passed in CI.
- Live browser testing verified Codex API-key reconnect inside a task
card on desktop and phone. Real provider runs resumed and completed with
unchanged connection/grant identity and agent routing.
- Tested opening, cancelling, reopening, and completing connection
creation. A regression confirms Connect another account cannot submit
the new-agent form or copy provider keys into agent settings.
- Added shared inline repair, automatic local sign-in checks, and
responsive connection dialogs. Standalone Daytona installation ignores
workspace configuration and suppresses dependency scripts. Its
standalone build also passed with CI's exact pnpm 9.15.4.
- Destructive live tests are excluded by default. Explicit opt-in, local
deployment checks, and matching disposable fixture identities are
required before any mutation.

## Risks

- Local Codex/Grok creation requires the connection-specific terminal
login command.
- Browser sign-in uses the existing supported-environment controllers.
- This update verifies live local Claude detection and Codex API-key
task repair. New subscription authorization/refresh and
independent-human/native-runner isolation were not reverified in this
update.
- No agent automatically adopts managed Connections.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, code
execution, and browser testing. The exact runtime model identifier and
context-window size are not exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-12 16:51:26 -05:00
DottaandPaperclip 47ded8bf97 feat: manage AI runtime credentials through Connections (#13247)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent runs need credentials for a specific provider and sign-in
method.
> - Connections already owns accounts, grants, and access permissions.
> - AI authentication should use those same boundaries.
> - This pull request adds the storage, API, adoption, and runtime
foundation.
> - Legacy agents keep their authentication until they explicitly adopt
a managed connection.

## Linked Issues or Issue Description

**Problem or motivation**
AI credentials are configured separately from Connections. Agents cannot
consistently reuse a responsible user's account or a permitted shared
account.

**Proposed solution**
Manage AI accounts with the existing Connections grants and permissions.
Keep model and harness selection independent from credential selection.
Preserve legacy authentication until validated adoption.

**Alternatives considered**
A separate credential registry would duplicate ownership and access
policy. Automatic fallback would risk using the wrong account.

**Roadmap alignment**
This extends the shipped Apps, multi-user, secrets, and agent-runtime
capabilities. The maintainer requested the feature and reviewed the UI.
Related groundwork: #11899 (connection permissions), #10910 (connection
wizard), #11692 (Claude subscription profiles), and #11854 (Codex
account rotation).

## What Changed

- Add AI-purpose/runtime-auth contracts and an additive, idempotent
migration.
- Add Claude, OpenAI, OpenRouter, and Grok provider capabilities and
catalog entries.
- Store credentials on grants. Resolve responsible-user defaults or
explicit permitted grants.
- Isolate managed credentials and provider sessions across accounts.
Block missing credentials without ambient fallback.
- Keep imported legacy secrets unchanged during reconnect. Use
independent local Codex/Grok sign-in attempts for rotating credentials.
- Add authorization, migration, concurrent refresh, retry, cancellation,
and legacy-compatibility tests.

This is part 1 of a two-PR stack. The app UI follows in #13248. Merge
the foundation first.

## Verification

- Updated against master `04e364236`, preserving upstream provider login
and connector workflows.
- Full workspace typecheck, production build, Storybook build, and token
gates passed on the integrated branch. Final local-login changes passed
59 focused tests; new-agent and inbox regression suites passed 63 tests.
- Browser checks verified automatic local Claude account detection,
resumable Codex login commands, retry, focus restoration, and
desktop/phone layouts. Commands create their isolated directory before
invoking the CLI.
- All current-head CI checks passed on `2a996560a`, including all
server/workspace tests, browser shards, runner verification, typecheck,
build, and canary dry run. Greptile reviewed that commit at 5/5 with no
unresolved threads. Earlier local full-suite attempts hit the Mac
PostgreSQL shared-memory limit; the complete suites passed in CI.
- Renumbered the additive AI migration to `0276` after upstream
migrations and regenerated its snapshot. Existing legacy agents retain
their configuration.
- Added local login status checks, owner-scoped retry, managed OpenCode
remote homes, credential-aware model discovery, and task
connection-repair delivery.

## Risks

- Managed credential failures intentionally block execution. They do not
restore legacy fallback.
- Preview-era copied Codex/Grok subscriptions require independent
reconnect.
- The integrated branch has live provider acceptance coverage. This
update verifies local Claude detection and Codex API-key task repair; it
does not add a new subscription authorization/refresh or Daytona stress
pass.
- Runtime-auth connections must stay excluded from tool and channel
handling.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, code
execution, and browser testing. The exact runtime model identifier and
context-window size are not exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.912.0-canary.11
2026-09-12 16:30:10 -05:00
DottaandPaperclip 1652a5c7f2 fix: improve task search relevance with a PostgreSQL rubric (#13335)
Unify full and quick task search around PostgreSQL term coverage, explicit relevance bands, and conservative typo recovery. Preserve matching evidence and navigation, and add a judged corpus, regression tests, and documented performance measurements.

Validation: local typecheck, build, focused PostgreSQL tests, and task-list tests pass. All final-head CI gates pass and Greptile is 5/5.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-09-12 16:22:58 -05:00
github-actions[bot]andlockfile-bot 04e364236b chore(lockfile): refresh pnpm-lock.yaml (#13336)
Auto-generated lockfile refresh after dependencies changed on master.
This PR only updates pnpm-lock.yaml.

Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com>
2026-09-12 15:30:59 -05:00
Devin Foley 6b45db0c35 fix(deps): force one @codemirror/state resolution via pnpm overrides (#13324)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The web UI embeds CodeMirror editors, and CodeMirror validates
extensions with `instanceof`
> - Different CodeMirror packages pin different transitive minors of
`@codemirror/state` (6.7.1 / 6.7.2) and `@codemirror/view` (6.43.9 /
6.43.11), so the bundle ships two module instances
> - The second instance makes valid extensions fail the `instanceof`
check and crashes the editor
> - This pull request adds a shared caret override to `pnpm.overrides`,
the same mechanism the existing `react` and `rollup` overrides use, so
every consumer resolves one copy of each package
> - The lockfile is not edited by hand; the lockfile automation
regenerates it from the manifests
> - The benefit is that the editor stops crashing with "Unrecognized
extension value in extension set"

## Linked Issues or Issue Description

**What happened?**

The production UI throws `Error: Unrecognized extension value in
extension set ([object Object]). This sometimes happens because multiple
instances of @codemirror/state are loaded, breaking instanceof checks.`
Observed 43 times in one week.

**Expected behavior**

The editor loads its extension set without errors. One instance of
`@codemirror/state` and `@codemirror/view` serves every CodeMirror
package.

**Steps to reproduce**

1. Run `grep "'@codemirror/state@" pnpm-lock.yaml` on master: two
versions resolve (6.7.1 and 6.7.2).
2. Build `ui/` and search the output for `Unrecognized extension value`,
a string unique to `@codemirror/state`: two chunks each carry a full
copy, one with a 6.7.1-only code pattern and one without it.
3. Open a view that composes extensions from packages on different
copies: the extension set rejects the foreign-instance extension.

**Paperclip version or commit**

master (0e14c61da)

## What Changed

- `package.json` (`pnpm.overrides`): added `"@codemirror/state":
"^6.7.2"` and `"@codemirror/view": "^6.43.11"`. A shared range forces
every consumer onto one resolution of each package.
- `pnpm-workspace.yaml`: the mirror overrides block gets the same two
entries, kept in sync with `package.json`.
- `ui/src/lib/codemirror-single-instance.test.ts`: regression pin that
fails when the lockfile resolves more than one version of either
package.
- No lockfile change in this PR. The `policy` job regenerates
`pnpm-lock.yaml` from the manifests for downstream jobs; CI owns
lockfile updates.

## Verification

- With the override, `pnpm install` resolves a single
`@codemirror/state@6.7.2` and a single `@codemirror/view@6.43.11`.
- Built `ui/` before and after. Before: two chunks each carried a full
copy of `@codemirror/state` (four total occurrences of its unique error
string; one chunk fingerprints as 6.7.1, the other as 6.7.2). After: one
chunk carries one copy (two occurrences, no 6.7.1 fingerprint).
- `pnpm vitest run src/components/IssuesList.test.tsx` in `ui/` — 46/46
pass.
- New test `ui/src/lib/codemirror-single-instance.test.ts` pins the
invariant: the lockfile must resolve exactly one version of
`@codemirror/state` and `@codemirror/view`. The PR CI policy job
regenerates the lockfile from the manifests, so the test evaluates this
PR's real resolution — verified locally against a lockfile regenerated
the same way (`pnpm install --resolution-only`): 2/2 pass, and the same
test fails against the current master lockfile with its two resolved
copies.

## Risks

- Low risk. The override stays inside the caret ranges every consumer
already declares, so no package receives a version outside its stated
compatibility. Rollback is removing the two override lines.
- A future CodeMirror consumer that needs a major bump of these packages
must update the override; the override comment states why it exists.

## Model Used

Claude (Anthropic) — claude-fable-5 (Claude Fable 5), Claude Code
harness, extended thinking with tool use.

## Checklist

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

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Channels connect external conversations to company tasks and agent
execution.
> - Slack, Discord, and AgentMail already provide durable delivery and
access controls.
> - People also need to reach an agent from Apple Messages and send
photos.
> - Photon provides shared Pro DMs, dedicated numbers, and authenticated
event recovery.
> - This pull request connects Photon to the existing channel services.
> - People can message an agent while Paperclip retains task ownership
and approval authority.

## Linked Issues or Issue Description

**Subsystem affected**

Cross-cutting: channel services, shared contracts, database constraints,
Apps, and agent Channels UI.

**Problem or motivation**

Paperclip has no iMessage channel. A person cannot use Apple Messages to
start a task, send a photo, or answer an agent's pending question.

**Proposed solution**

Add experimental **iMessage Photon** with Pro-compatible shared DMs or a
dedicated Photon Cloud number per agent channel. Reuse channel
admission, identity links, task generations, publication, and
interaction continuation. Keep groups disabled for shared allocation.
Dedicated lines support groups that an operator explicitly enables.
Require a fresh linked message and a published agent response before
setup completes.

**Alternatives considered**

Shared allocation has no owned phone number, so it reserves one project
and allows DMs only. Dedicated allocation reserves one stable number.
Local Mac access needs a separate deployment model. The upstream Photon
Chat SDK adapter does not persist the poll mappings and send receipts
required here. This change uses the lower-level SDK without adding
another agent runtime.

**Roadmap alignment**

This extends Connected Apps and agent communication through the existing
channel subsystem. It does not add a parallel tool connection or agent
loop. GitHub searches for Photon and iMessage found no matching provider
implementation.

**Additional context**

This ships behind the existing experimental channel gate. Dedicated-line
release qualification remains incomplete. Real Photon Pro DMs passed
task/reply, native poll, text answers, confirmation rejection, media,
restart, pause, reconnect, revocation, and removal tests. An
operator-supplied iPhone camera HEIC also passed the full round trip.
Dedicated groups remain unqualified. See [the verification
record](doc/connections/IMESSAGE-PHOTON-VERIFICATION.md) and [the
implementation plan](doc/plans/2026-09-11-imessage-photon.md).

## What Changed

- Add the provider catalog entry, shared setup contracts, and a forward
migration. A global partial index reserves the dedicated number or
shared project until its endpoint is archived.
- Add Cloud project inspection, vaulted project credentials,
selected-line token renewal, and a leased receiver. Persist checkpoint
updates under the receiver lease. Shared project replay accepts sparse
increasing sequences only after a complete recovery barrier.
- Connect DMs and enabled groups to existing task generations, sender
authorization, ordered delivery, and publication services. Keep each
iMessage conversation on its task after completion; only explicit `/new`
or `/close` releases the binding. Publish committed inbound comments
live and label their human bubbles “Sent from iMessage” in both
task-chat renderers.
- Persist immutable text/file send identities, upload receipts, poll
IDs, option IDs, per-person drafts, and canonical interaction
continuation proofs.
- Add source-bound file recovery, bounded HEIC/HEIF conversion, JPEG
previews, and related Live Photo companion video retention.
- Add the three-step setup flow and channel management surfaces with
official branding. Preserve the experimental gate and existing
pause/disconnect behavior.
- Add interactive production-component Storybooks for setup, access,
recovery, and ongoing conversations. Add provider, integration, catalog,
and browser regression coverage. Document setup, recovery, supported
boundaries, and qualification gaps.

## Verification

- Live Photon Pro, SDK 2.1.0: linked iPhone messages create a task and
receive native Codex replies in Apple Messages. Unlinked senders cannot
start work.
- Three real follow-ups each reopened the same completed task. Incoming
bubbles appeared on its open page without reload and showed “Sent from
iMessage.” The third follow-up ran after restarting the server on
`4d7222110`; the agent correctly repeated its previous reply from before
the restart.
- Native polls after restart, sequential text drafts, required-field
correction, explicit submission, approval rejection with a required
reason, and native continuation passed against Photon.
- PNG, text documents, synthetic HEIC, and a real iPhone camera HEIC
passed in both directions. The camera photo produced a 3024×4032 JPEG
preview. The native agent described it and returned the received HEIC
byte-for-byte.
- Pause/resume, reconnect, identity revocation, removal, `/status`,
`/new`, `/close`, and stale answers after close passed live. Messages
suppressed by pause did not become work on resume. Removal stopped
intake and removed credential bindings.
- All 304 focused tests passed on `4d7222110`. These cover Photon
unit/integration behavior, both task-chat renderers, live comment
hydration, completed-task continuity after restart, enabled groups,
duplicate delivery, and explicit reset/close. The selected Teams
completion-boundary regression also passed. Full workspace
typecheck/build and token gates passed for the conversation fix; the
final UI changes passed their affected typecheck/build and tests.
- All 26 new Photon Storybook Playwright cases passed in light and dark
themes, including the complete shared-DM setup journey and 390px mobile
follow-ups. UI typecheck and the Storybook build passed. These stories
use simulated Photon responses and do not replace the live evidence
above.
- The full chat-adapters browser suite previously passed all 39 cases.
Migration checks passed, and migration 0275 applied to the isolated live
instance with the earlier Photon migration already applied.
- The local full Vitest run was previously interrupted by the host's
embedded-Postgres shared-memory limit; it is not a full-suite pass. All
30 applicable CI checks passed on preceding head `7a5419cac`, with two
skipped checks and Greptile 5/5. Head `24f8e1aae` adds an explicit
required-story discovery guard to the 26 passing Storybook cases.
Greptile rates this final head 5/5 with no unresolved review threads.
All 30 applicable CI checks passed, with two optional checks skipped.
- A repeated live send key suppressed the duplicate but returned gRPC 6
/ SDK `internalError` without an original receipt. Paperclip keeps
unknown delivery unresolved. This provider behavior is covered by a
regression test.
- See [the verification
record](doc/connections/IMESSAGE-PHOTON-VERIFICATION.md) for package
versions, redacted live evidence, deterministic coverage, and remaining
qualification gaps.

## Risks

- Dedicated group qualification remains unrun; groups are disabled for
the approved Pro scope. Real iPhone camera HEIC passed transport,
preview generation, agent inspection, and return. Keep the channel
experimental; the dedicated-line release matrix remains incomplete.
- Shared recovery and attachment aliases were verified against the live
gateway. Duplicate writes currently return an error without the original
receipt; unresolved sends require operator resolution. The
implementation fails visibly on invalid replay ordering, a reset cursor,
or changed identity.
- The HEIF converter passed on macOS arm64 and in Linux CI. Windows HEIF
binaries have not been executed in this work. Linux musl has no packaged
converter. Unsupported conversion retains the original and reports the
missing preview.
- The migration adds a global reservation across companies for Photon
numbers and shared projects. Paused and revoked endpoints keep that
reservation until removal.
- Integration touches shared channel services. Existing provider browser
coverage passes; broad repository verification is recorded above.
- `pnpm-lock.yaml` is intentionally excluded under repository policy.
The repository bot owns lockfile updates. The additional Superagent
supply-chain scan is neutral/inconclusive because these new dependencies
are not yet in the committed lockfile. Its security scan passed; all
required CI checks pass.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository inspection, code
execution, browser testing, and tool use. The exact served model
identifier and context-window size are not exposed in this session. No
sub-agents were used.

## 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-09-12 15:23:50 -05:00
Devin FoleyandPaperclip 44f6312cd8 fix(ci): reuse one available Cloud registry cache (#13334)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip Cloud needs a verified image for each merged source
commit.
> - Fresh builders restore compiled native dependencies from registry
caches.
> - The current workflow imports up to eleven historical cache manifests
at once.
> - Live builds missed native layers that a fresh builder reused from
one manifest.
> - This PR selects the nearest available cache and tests reuse across
fresh builders.

## Linked Issues or Issue Description

Refs #13329 and #13330. A search of open cache PRs found no duplicate of
this change.

**What existing behavior does this improve?**

Remote Docker cache reuse on fresh Cloud image builders.

**Current behavior**

[Cloud run
34714483272](https://github.com/paperclipai/paperclip/actions/runs/34714483272/job/103609096836)
imported the previous cache manifest successfully but rebuilt
`cargo-chef` and Rust dependencies. The dependency compile took 3m43s.
The preceding image build had already exported those layers.

A controlled [fresh-builder
diagnostic](https://github.com/paperclipai/paperclip/actions/runs/34715336530)
used the same source and registry cache. The single-manifest job reused
both layers immediately. The multiple-manifest job rebuilt them and
failed the cache assertion. Both jobs used GitHub-hosted runners with
read-only access.

**Proposed behavior**

Inspect cache manifests in first-parent order and import only the
nearest available one. Keep full-SHA cache exports, the ten-commit
search bound, and the legacy fallback. If caches cannot be read, permit
a cold build.

**Reason and benefit**

Avoid the observed cache misses without changing image contents or
builder sizes. Expected savings include about four minutes of native
tool/dependency compilation when those inputs are unchanged. The final
merge-to-deployable gain still needs a post-merge measurement.

**Breaking changes**

No image, artifact, deployment, or runner-routing contract changes.

## What Changed

- Select one available ancestor cache after Docker login and Buildx
setup.
- Preserve separate writable cache tags for each full source SHA.
- Test cache ordering, missing caches, registry errors, and workflow
integration.
- Add the selector tests to the existing release-registry suite.
- Export a local test cache, remove the first builder, and verify a
source rebuild on a fresh builder.
- Document cache selection and the stronger Docker check.

## Verification

- Passed 456 focused workflow, routing, readiness, preview-artifact, and
cache-selector tests.
- Passed shell syntax, ShellCheck for the changed probe, actionlint
workflow validation, and `git diff --check`. actionlint's shell checks
were disabled for the workflow validation because unchanged
migration-label commands trigger existing SC2012 notes.
- The fresh-builder registry diagnostic proves the single-cache
behavior. The [permanent two-builder probe
passed](https://github.com/paperclipai/paperclip/actions/runs/34715771048/job/103612624090),
including a changed real binary and dependency-declaration invalidation.
- Passed all 35 latest-head checks (green or intentionally skipped),
including full typecheck, test, build, and browser suites in [PR CI run
34715771217](https://github.com/paperclipai/paperclip/actions/runs/34715771217).
- The real selector CLI inspected registry metadata and chose the
nearest available ancestor cache.
- Fresh Greptile review is 5/5 with no open findings. The PR title was
corrected to meet the source-change naming rule; the review check passed
after that correction.
- Local full-suite runs and Docker builds are unavailable because the
local Docker daemon is unresponsive after disk exhaustion. CI provides
the Linux verification.

## Risks

- Missing or unreadable caches cause a slower cold build. The selector
logs that condition and preserves image publication.
- Inspecting several missing ancestors adds lookup time. Each lookup has
a ten-second timeout and the search is bounded.
- The Docker test now exports a local cache. It removes the first
builder before starting the second to release disk space, then cleans up
its builders and files.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, and code
execution. The exact serving model ID and context window are not exposed
by this environment.

## 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-09-12 13:20:18 -07:00
Devin FoleyandPaperclip 0ce7df2648 ci: keep Cloud readiness markers out of the builder queue (#13330)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip Cloud consumes versioned readiness markers for each merged
source commit.
> - Those markers can be published only after the required checks and
artifacts pass.
> - The marker jobs currently wait for the same AWS runner capacity as
builds and tests.
> - A busy builder pool can delay readiness after all required work has
finished.
> - This PR moves the small readiness jobs to GitHub-hosted runners
while retaining every dependency gate.

## Linked Issues or Issue Description

Refs #13326 and #13328.

**What existing behavior does this improve?**

Time from completed Cloud verification to a deployable marker, and AWS
capacity occupied by artifact polling.

**Current behavior**

In [Cloud readiness run
34711557083](https://github.com/paperclipai/paperclip/actions/runs/34711557083),
all builds and tests finished at 18:43:05 UTC. The source marker did not
start until 18:44:21, and the deployable marker did not start until
18:44:37. Merge-to-deployable was 11m33s, although the prerequisite work
finished in 9m44s.

**Proposed behavior**

Run the artifact wait and both versioned marker jobs on `ubuntu-latest`.
Keep the compute jobs on the approved post-merge AWS fleet.

**Reason and benefit**

Avoid builder-pool queue delays after verification finishes. This also
removes the long artifact-wait job from AWS capacity. Expected savings
depend on queue depth: the observed run had over 90 seconds of avoidable
marker waiting. The marker commands themselves take only seconds.

**Breaking changes**

Runner placement changes for three bookkeeping jobs. Marker names,
exact-source artifact checks, required verification, and image
verification stay the same.

**Additional context**

Searched the related runner and Cloud readiness work. This addresses
queue time observed after the parallel verification change.

## What Changed

- Place the artifact wait, source-verification marker, and deployable
marker on GitHub-hosted runners.
- Keep all existing job dependencies, source guards, permissions, and
commands.
- Extend routing regressions to enforce this placement and retain
fail-closed readiness gates.
- Document why readiness bookkeeping uses separate runner capacity.

## Verification

- Passed 433 workflow, routing, source-verification, and Cloud readiness
tests with `node --test .github/scripts/tests/*.test.mjs
scripts/cloud-source-verification.test.mjs
scripts/cloud-readiness.test.mjs
scripts/__tests__/release-verify-workflow.test.mjs`.
- Passed `actionlint` and `git diff --check`.
- Passed all latest-head CI gates in [run 34712624340, attempt
2](https://github.com/paperclipai/paperclip/actions/runs/34712624340),
including typecheck, build, browser, Runner, and all general/serialized
tests.
- Attempt 1 had one localhost readiness timeout in an unchanged test. A
single targeted retry passed all 166 files (3,225 tests passed, one
existing skip), including all seven tests in that file. No timeout,
assertion, or application source was changed; the retry is documented in
the PR comment.
- Local full-suite verification is limited by local disk exhaustion; the
focused checks above pass.
- Fresh Greptile review is 5/5 with no unresolved findings.

## Risks

- GitHub-hosted capacity can also queue, but these jobs no longer
compete with AWS build/test demand. The change does not reserve
instances or change box sizes.
- Readiness must still fail if any prerequisite fails. The existing
`needs` relationships and success-only execution are preserved and
tested.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, and code
execution. The exact serving model ID and context window are not exposed
by this environment.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.912.0-canary.10
2026-09-12 12:32:46 -07:00
Devin FoleyandPaperclip 7435b2ee9c ci: cache compiled Docker Rust dependencies separately from source (#13329)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip Cloud deploys images that contain the native Rust Runner.
> - The image already builds that Runner before copying ordinary app
source.
> - A Rust source change still invalidates its entire compiled
dependency layer.
> - Compiled dependencies can survive source changes when their recipe
is unchanged.
> - This PR adds a separate locked dependency build before compiling the
real workspace.

## Linked Issues or Issue Description

Refs #13195. A search of related Docker and Cargo cache PRs found no
duplicate dependency-recipe change.

**What existing behavior does this improve?**

Docker image build time after Rust source or embedded protocol changes.

**Current behavior**

The `runner-build` stage compiles dependencies and workspace code in one
layer. In Cloud readiness run 34698143548, that stage took about 3m48s
when its cache was unavailable.

**Proposed behavior**

Generate a recipe with pinned cargo-chef 0.1.73. Build locked release
dependencies in `runner-deps`, then copy and compile real Rust source
and embedded protocol inputs in `runner-build`. Source edits can reuse
the dependency layer from the existing registry cache.

**Reason and benefit**

Reduce dependency recompilation during source changes and merge bursts.
Expected savings are roughly 2–4 minutes when the old native layer would
miss but dependency layers are available. Full cold builds also pay for
the recipe tool installation. Ordinary app-only cache hits gain little
from this change.

**Breaking changes**

None to the shipped application or image tags. The recipe tool and
compiled dependencies remain in build stages.

## What Changed

- Install a pinned recipe generator with its locked dependencies and the
existing package-owned compiler.
- Add recipe planning and compiled dependency stages. Use the same
release profile, package, binary, and lockfile enforcement as the real
native build.
- Remove generated source stubs before copying actual source. Preserve
protocol inputs, timestamp normalization, binary staging, and
application checks.
- Add Docker cache wiring regressions and update the Docker cache
documentation.
- Run a two-build probe in Docker Runner check. It requires dependency
reuse, changed real binary metadata after a source edit, and a changed
recipe after a dependency declaration edit. It uses a disposable
tracked-source context and exports only small metadata files.

## Verification

- Passed all five Docker build-stamp and dependency-cache tests with
`pnpm exec vitest run server/src/__tests__/docker-build-stamp.test.ts`.
- Passed the local ARM64 `docker buildx build --target runner-build
--progress plain`. Local Docker then hit storage errors during a runtime
probe; cache invalidation verification continues on GitHub-hosted Linux.
- Passed `bash -n scripts/check-docker-runner-cache.sh`, `actionlint`,
and `git diff --check`.
- Passed a [Linux AMD64 cache
probe](https://github.com/paperclipai/paperclip/actions/runs/34711042199)
against the PR source: dependencies compiled in 3m49s for the baseline
and were `CACHED` after a source edit; real source compilation took
about 37 seconds. Binary metadata changed and dependency declaration
changes altered the recipe. The permanent probe is also running in
latest-head Docker Runner check.
- Passed latest-head [Docker Runner
check](https://github.com/paperclipai/paperclip/actions/runs/34711145160),
including the permanent source/dependency invalidation probe.
- Passed full [PR
verification](https://github.com/paperclipai/paperclip/actions/runs/34711145352/attempts/2):
typecheck, all grouped tests, native verification, build, release dry
run, and browser checks. One unrelated signoff-policy browser test
failed waiting for a heartbeat run on attempt 1; only that failed shard
and dependent checks were retried, and passed.
- Latest-head Greptile is 5/5 with no unresolved findings. Full local
tests/build were limited by local disk exhaustion; Linux CI completed
those checks.

## Risks

- The two-build CI probe has a 20-minute job limit to cover the cold
build and source rebuild. It adds no AWS routing.
- A fully cold build must install cargo-chef and populate the dependency
layer. Both become reusable registry layers; no Actions cache is added.
- The recipe and final build must keep the same compiler, build profile,
package, binary, and directory layout. A source-change rebuild probe
checks real cache reuse and binary invalidation.
- Dependency or compiler changes still require rebuilding dependencies.
Existing image verification and full-SHA publication gates remain
unchanged.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, and code
execution. The exact serving model ID and context window are not exposed
by this environment.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.912.0-canary.9
2026-09-12 11:57:32 -07:00
Devin FoleyandPaperclip 8df3ee2cf5 ci: rebalance serialized tests with current suite durations (#13328)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Cloud deployments wait for verified source commits.
> - Verification splits serialized server tests across independent
runners.
> - The shard duration estimates came from August and no longer match
current tests.
> - Stale estimates put much more work on one runner than the others.
> - This PR refreshes the estimates from a complete successful run to
balance the existing runners.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The time spent waiting for the slowest serialized server-test shard in
PR and release verification.

**Current behavior**

In [Cloud readiness run
34705914878](https://github.com/paperclipai/paperclip/actions/runs/34705914878),
the five serialized shards spent 479, 371, 322, 390, and 365 seconds
running tests. The recovery suite had a 55-second estimate but now takes
about 156 seconds including process overhead.

**Proposed behavior**

Use fresh per-suite measurements with the existing deterministic
duration balancer. Applying the same measured costs to the new
assignment gives 385, 385, 386, 385, and 385 seconds. This predicts
about 93 seconds less waiting for the slowest shard, before runner/setup
overhead. Live CI will confirm the result.

**Reason and benefit**

Use the existing runners more evenly. No extra runner, test parallelism,
cache, timeout, or routing change is needed.

**Breaking changes**

Suite-to-shard assignments change. The full suite set, assertions, and
per-suite process isolation stay the same.

**Additional context**

Searched related CI and shard PRs. This updates the existing duration
manifest, without duplicating a pending sharding implementation.

## What Changed

- Refresh all 145 serialized suite weights from the same successful
release verification run.
- Record source job IDs and the measurement method in the manifest.
Durations include process startup, imports, collection, tests, and
shutdown.

## Verification

- Passed all 30 shard and release-workflow tests: `node --test
scripts/__tests__/run-vitest-stable-shard.test.mjs
scripts/__tests__/release-verify-workflow.test.mjs`.
- Confirmed every measured suite appears exactly once across all five
source logs.
- Compared old and new assignments using the same measured weights. The
maximum fell from 478862ms to 385551ms.
- In [PR CI run
34710696242](https://github.com/paperclipai/paperclip/actions/runs/34710696242),
all five serialized jobs passed in 7m05s–7m27s including setup. The
measured assignment is now balanced in a live run.
- The same run passed full typecheck, all grouped tests, native
verification, build, release dry run, and browser checks. Local
full-suite verification on this base was limited by disk exhaustion;
local typecheck and targeted shard tests passed.
- Latest-head Greptile is 5/5 with no open findings. Every current-head
CI check must be green or intentionally skipped before merge.

## Risks

- Individual durations vary with load and future test changes. These
estimates affect assignment only; missing or renamed suites receive the
existing median weight.
- Both PR and release verification read this manifest, so both receive
the new assignments. Each suite still runs in its own serialized Vitest
process.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, and code
execution. The exact serving model ID and context window are not exposed
by this environment.

## 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-09-12 11:36:20 -07:00
DottaandPaperclip ed50a39c3f fix: preserve NUL characters in run-event payloads (#13325)
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-09-12 13:34:45 -05:00
Devin FoleyandPaperclip d2e940f4c1 ci: run release Runner protocol and Rust checks in parallel (#13326)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip Cloud deploys verified images from merged source commits.
> - Cloud readiness waits for every release verification check.
> - Runner verification currently runs long TypeScript tests before Rust
checks.
> - These checks can run on independent runners with their own build
directories.
> - This PR runs them in parallel while preserving all checks and the
shared dependency cache.

## Linked Issues or Issue Description

Refs #13194. Related prior work: #13142 and #13259. A search found no
duplicate parallel release-check change.

**What existing behavior does this improve?**

Time from merge to Cloud source verification and deployment readiness.

**Current behavior**

Recent successful runs take roughly 13 minutes from merge to deployable.
In run 34705914878, Runner verification took 11m23s. Protocol tests
finished before Rust tests and API authority checks started.

**Proposed behavior**

Run protocol and Rust verification in two matrix jobs. Cloud readiness
still requires both jobs to pass.

**Reason and benefit**

Remove the serial dependency between independent checks. Expected
improvement is about 2–3 minutes on a typical cached run, until the
image build or server tests become the longest job. This is an estimate;
post-merge timing will confirm it.

**Breaking changes**

Individual release Runner job names gain a lane suffix. Cloud source and
readiness marker names stay the same. PR runner routing is unchanged.

## What Changed

- Split release Runner checks into protocol and Rust lanes. Keep every
constituent of `check:all` exactly once.
- Restore the existing Rust dependency cache in both lanes. Allow only
the Rust lane to save it after warming both build profiles.
- Add coverage and cache authorization regressions. Document the
parallel verification and single cache writer.

## Verification

- Passed 477 workflow and source-verification tests with `node --test
.github/scripts/tests/*.test.mjs
scripts/cloud-source-verification.test.mjs
scripts/__tests__/release-verify-workflow.test.mjs`.
- Passed `actionlint`, `git diff --check`, and the private AWS routing
regression suite.
- Passed local `pnpm -r typecheck` and the standalone `check:runner &&
check:api-authority` lane, including all 1,671 API tests before the
protocol lane had built TypeScript output.
- The broad local protocol run under Node 25 had four failures. The two
affected files passed under CI's Node 24.19.0: 67 passed, 6 platform
skips.
- Local `pnpm test:run` aborted when disk space ran out; local `pnpm
build` could not run afterward. These are local verification limits.
[Linux CI run
34710421424](https://github.com/paperclipai/paperclip/actions/runs/34710421424)
passed full typecheck, all grouped tests, native verification, build,
release dry run, and browser checks. Native protocol CI passed 1,986
tests, plus 1,671 API tests and the Rust suites.
- Latest-head Greptile is 5/5 with no open findings. All 33 current-head
checks are successful or intentionally skipped.

## Risks

- Uses one additional short-lived verification runner per release
verification. The existing AWS exact-master restriction remains in
place.
- The Rust lane warms debug dependencies so its cache save also serves
protocol tests. Both lanes always rebuild workspace code.
- A workflow regression could omit a check. The new coverage test
compares the matrix checks directly with `check:all`; Cloud readiness
depends on the complete reusable workflow.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, and code
execution. The exact serving model ID and context window are not exposed
by this environment.

## 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-09-12 11:33:20 -07:00
Devin Foley a59f5a8adc fix(server): stop reporting expected managed-cloud transients to Sentry (#13323)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The server reports crashes to Sentry so operators can find real
faults
> - Three expected conditions report as crashes: a client that closes
the connection mid-request, one stale pooled database socket after a
pooled endpoint recycles, and the short boot window where a supervised
cloud stack runs a new app image before its migration runner has caught
up
> - These events arrive in the hundreds and bury real errors
> - This pull request classifies each condition as expected and stops
the Sentry capture for exactly that condition, with behavior unchanged
everywhere else
> - The benefit is a Sentry feed where each event is a real fault

## Linked Issues or Issue Description

**What happened?**

Three noise classes fill the backend Sentry project on managed cloud
fleets:

1. `Error: aborted` (ECONNRESET) reports as a 500 crash when a client
closes the tab or loses its network mid-request. Observed 18 times in
one week from routine client disconnects.
2. `Error: write CONNECTION_CLOSED ...` reports from many query paths
after a pooled Postgres endpoint suspends. The existing single retry in
cloud actor resolution still fails, because a suspended endpoint kills
every pooled socket at once and the one replay draws another dead
socket.
3. `Error: PostgreSQL has pending migrations (...). Refusing to start`
reports from every supervised stack during a fleet upgrade. The
supervisor delivers the new app image before it runs the migration
runner, so each stack crash-loops briefly by design. One fleet roll
produced 329 events (11 per container).

**Expected behavior**

A client disconnect ends the request quietly. A transient dead socket is
replayed until a live socket answers. A supervised mid-upgrade boot
refusal logs and exits nonzero without a Sentry capture, while the same
refusal on a self-hosted deployment keeps reporting.

**Steps to reproduce**

1. Abort an HTTP request mid-flight: the error handler reports a crash
to Sentry.
2. Suspend a pooled Postgres endpoint under an idle server, then issue
two quick requests: the first replay can draw a second dead socket and
surface `CONNECTION_CLOSED`.
3. On a deployment with `PAPERCLIP_CLOUD_API_ORIGIN` set, add a
migration file without running the migration runner and boot: the
refusal reports to Sentry.

**Paperclip version or commit**

master (0e14c61da)

## What Changed

- `server/src/middleware/error-handler.ts`: a request abort (`Error:
aborted` with `ECONNRESET`) ends the response with status 499 and skips
crash reporting and telemetry.
- `server/src/middleware/auth.ts`: `retryOnTransientDbConnectionError`
replays up to twice with a short pause, so a pool-wide recycle does not
defeat the retry.
- `server/src/startup-refusals.ts`: pending migrations on a database
with applied history classify as a supervised-transient refusal
(`schema-migration-pending`). The capture skip applies only when
`PAPERCLIP_CLOUD_API_ORIGIN` is set. A wiped journal beside real tables
keeps reporting. Self-hosted behavior is unchanged.
- Tests updated and added for all three behaviors.

## Verification

- `pnpm vitest run src/__tests__/startup-refusals.test.ts
src/__tests__/cloud-tenant-transient-db-retry.test.ts
src/__tests__/error-handler.test.ts` in `server/` — 25 tests, all pass.
- The abort test asserts no `captureException` and no telemetry crash
track.
- The refusal tests pin all three classifications: never-migrated,
pending-with-history, wiped journal.

## Risks

- Low risk. The abort path only triggers on the exact `aborted` +
`ECONNRESET` pair; every other error keeps reporting.
- The refusal reclassification suppresses a capture only under a cloud
supervisor. If an operator breaks a migration runner, the supervisor's
own deploy gates surface it; self-hosted deployments still report.
- The retry widening adds at most ~150 ms before a genuine connection
fault surfaces.

## Model Used

Claude (Anthropic) — claude-fable-5 (Claude Fable 5), Claude Code
harness, extended thinking with tool use.

## Checklist

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

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The heartbeat service starts and tracks agent work on issues.
> - An issue can be in review before a user comment starts more agent
work.
> - The previous checkout rule did not claim an issue from review for
this continuation.
> - The issue could stay in review while an agent actively worked on it.
> - This pull request lets a resolved interaction continuation claim an
issue from review.
> - The existing checkout update then sets the issue to in progress.
> - The benefit is that issue status now shows active agent work
correctly.

## Linked Issues or Issue Description

**What happened?**

An issue stayed in review when a new agent continuation started work on
it.

**Expected behavior**

The issue must move to in progress when an agent starts work. An idle
issue must stay in review.

**Steps to reproduce**

1. Put an assigned issue in review.
2. Resolve an interaction that starts a continuation.
3. Start the heartbeat run.
4. Observe that the issue remains in review while the run works.

**Paperclip version or commit**

The problem reproduces on the master branch before this change.

## What Changed

- Allow a resolved interaction continuation to claim an assigned issue
from review.
- Keep idle review issues unchanged.
- Add regression tests for both behaviors.

## Verification

- Run `node_modules/.bin/vitest run
server/src/__tests__/heartbeat-auto-checkout.test.ts`.
- Confirm that all four tests pass.

## Risks

- Low risk. The change only expands checkout eligibility for resolved
interaction continuations.
- The existing guarded checkout update still controls ownership and the
status update.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI Codex with GPT-5.5. The model used reasoning, tool use, and
code execution.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-12 13:11:10 -05:00
DottaandPaperclip c9021c6721 fix: require explicit native completion reviews (#13314)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native runs report their outcome through paperclip_finish.
> - The server previously turned incomplete reports into human approval
requests.
> - Those requests could block a later successful run, even when no
person had requested review.
> - This pull request creates review cards only for explicit attention
requests and withdraws proven old fallback cards.
> - Agents receive useful completion feedback, while explicit approval
gates and task state protections remain in force.

## Linked Issues or Issue Description

Related: #13266 removed reviews caused by policy upgrades. This change
removes the separate completion fallback.

**What happened?**

An agent reported needs_review while waiting for checks without
requesting a human decision. Paperclip created a generic Native
completion review. A later successful report could not complete the task
because that old card remained pending.

**Expected behavior**

Ordinary low-risk work completes after a valid done report, a successful
run, and workspace finalization. Incomplete work stays with the agent.
Explicit approval requests remain visible and must be resolved.

**Steps to reproduce**

1. Complete a native run with needs_review and no attention requests.
2. Continue the task and submit a successful done report.
3. Observe that the old implementation leaves the task in review behind
a generic confirmation card.

## What Changed

- Require explicit attention requests to create native review cards.
Route each request independently and preserve pending or declined
decisions.
- Withdraw only pending system cards with matching old decision,
assessment, effect, contract, and prompt provenance. Preserve history
and explicit or answered requests.
- Reassess an affected current result without overwriting later task
edits, runs, contracts, or workspace failures.
- Return pending approval links and required actions through the
completion tool. Reject contradictory done reports and empty review
requests before accepting a result.
- Allow one corrective continuation for incomplete results, then expose
a recovery action.
- Update status fixtures, database regressions, runner tests, and the
completion contract documentation.

## Verification

- `pnpm -r typecheck` passed after merging current master.
- `pnpm build` passed after merging current master.
- The combined branch passed 89 completion and Agent Chat tests. Other
targeted tests passed: 170 external-chat and reconciliation tests; 50
runner-resume and control-plane tests; 13 arbiter tests; 7 chat delivery
tests; 21 runner completion and runtime-context tests.
- The full local test attempt exposed old review fixtures and a missing
fake-provider binary. The fixtures are fixed and the helper is built.
All affected suites pass in fresh reruns. The timing-sensitive Discord
test also passed on rerun.
- All latest-head CI checks passed, including build, typecheck, general
and serialized tests, runner verification, browser tests, and canary dry
run. Greptile is 5/5 with zero unresolved comments.

## Risks

- Cleanup changes existing pending cards. It requires exact system
provenance and only applies to low-risk agent-claim contracts. It does
not delete history or dismiss explicit requests.
- Status still commits after the turn and workspace finalization.
Completion feedback reports current constraints and does not claim an
early status commit.
- Incomplete reports now request a bounded corrective run instead of an
automatic approval. Repeated failures expose recovery.

## Model Used

OpenAI Codex, GPT-6, with repository inspection, code execution, and
test tools. The exact deployment identifier and context window size are
not exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-12 13:00:04 -05:00
DottaandPaperclip 7e6d512597 fix(onboarding): make chief-of-staff hiring reliable (#13317)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The first agent helps the board define work and hire other agents.
> - That agent can have the general role while its instructions require
hiring skills.
> - Missing skills and blocked schema discovery make valid requests
fail.
> - Repeated confirmation and invalid waiting guidance can turn these
failures into extra runs.
> - This PR supplies the required skills, opens read-only schema
discovery, and corrects the guidance.
> - The agent can complete an authorized hire while company approval and
duplicate checks still apply.

## Linked Issues or Issue Description

Refs #13068 — the first-task onboarding flow that this change repairs.
Refs #12029 — related drift between the sandbox allowlist and bundled
hiring guidance. This PR adds schema access; it does not replace the
earlier hiring-route fix.

**What happened?**

A general-role onboarding chief received hiring instructions without the
core hiring skills. Sandbox requests to the documented OpenAPI endpoint
failed. The agent then guessed question and hire payloads. The persona
required new confirmation after validation errors and described waiting
states that agents cannot set.

**Expected behavior**

A direct request authorizes the requested hire. The chief asks only for
material missing details, uses valid API payloads, and completes the
task. Formal company approval gates still apply. A saved human-input
card gives the task a valid waiting state.

**Steps to reproduce**

1. Create an onboarding chief with role `general` through the board.
2. Ask it to hire a friendly robot with a supplied name and
responsibilities.
3. Check its assigned skills, schema requests, question cards, hire
requests, and final task state.

**Paperclip version or commit**

Reproduced on the first-task onboarding implementation after #13068. The
live local verification used this branch at `112f44610`.

**Deployment mode**

The original failure used a hosted sandbox with legacy Codex ACP. Live
verification used an isolated local instance and real `codex_local`
execution. Queue and HTTP/2 transport access is covered by automated
tests.

## What Changed

- Give board-created onboarding chiefs the existing core skills
regardless of role. Preserve explicit skill version pins, including
aliases. Keep ordinary general-agent defaults and authorization checks.
- Allow exactly `GET /api/openapi.json` through both sandbox bridge
transports.
- Publish validator-tested question, free-text, hire, and waiting
examples. Regenerate the runner API reference and capability inventory.
- Clarify direct authorization, material ambiguity, and correction of
confirmed pre-creation validation failures. Preserve uncertain-outcome
reconciliation, duplicate protection, and company approval gates.
- Align disposition instructions with agent permissions and the saved
human-input waiting path.

## Verification

- After rebasing onto current `master`: 69 targeted server tests, 110
queue/HTTP2 bridge tests, and 4 capability inventory tests passed. These
cover core skill defaults, version pins, actor restrictions, schema
access, published examples, hire validation, idempotency, and approval
gates. Waiting recovery tests and live question flows also passed before
the rebase.
- `pnpm -r typecheck` and `pnpm build` passed again after the rebase.
Frozen dependency installation and both generated capability checks
passed.
- Ran the full `pnpm test:run` suite. The initial run had 14 failed
server files due to local database resource limits, a missing built test
fixture, and socket failures. All 14 files passed after fixture repair
and isolated retries. UI, CLI, workspace packages, database tests, and
all 145 serialized server files passed.
- Real one-request hiring replay: one hire, one successful run, task
done in 2m16s. No repeated approval or recovery escalation.
- Real two-turn browser conversation: start with an unspecified hire,
then supply a name and friendly robot responsibilities. One
clarification card, one hire, two successful runs, task done in 3m27s of
execution. No failed writes, confirmation cards, or recovery actions.
- Assigned the hired robot a welcome-message task through the browser.
It produced a warm message under 100 words and finished in one
successful 66-second run, with no questions or recovery actions.
- The two-turn flow still asked an optional preferences question and
gave a technical final reply. These are remaining presentation limits.
- Greptile: 5/5 on `b71f83ba2`, with zero unresolved review threads.
Fixed its generator finding and passed 1,655 published-example/runtime
API tests plus server typecheck. All latest-head CI checks are green (32
passed; 2 unrelated Storybook checks skipped). The signoff-policy
browser test initially timed out while waiting for an approver run. Its
shard passed on one rerun without code changes. [CI
run](https://github.com/paperclipai/paperclip/actions/runs/34698211049).

## Risks

- Onboarding chiefs receive more default skills. Ordinary general agents
retain existing defaults, and explicit versions take precedence.
- Prompt guidance can affect model behavior. The live replays are
examples, not a guarantee that every model follows the guidance.
- Retry guidance applies only when validation confirms that nothing was
created. Uncertain outcomes still require checking existing agents.
- No database migration or new public endpoint. Existing company
boundaries, approval gates, and bounded recovery remain in force.

## Model Used

OpenAI Codex, model `gpt-6-astra`, with reasoning, tool use, code
editing, and live browser verification. The exact 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
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.912.0-canary.8
2026-09-12 12:59:42 -05:00
DottaandPaperclip 0e14c61da7 fix: fence native startup against cancellation (#13316)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Users can pause a task while its runner prepares to start.
> - Cancellation must prevent preparation from creating new execution
authority.
> - Native runtime selection could run after cancellation and leave an
unclaimed recovery coordinator.
> - Saved user messages then waited for recovery that had no eligible
worker.
> - This pull request fences startup and lets explicit user continuation
settle verified, unclaimed startup state.
> - Tasks can continue after cleanup while keeping provider ownership
and execution safeguards.

## Linked Issues or Issue Description

Refs #13285 for startup controller leases and #13270 for explicit
continuation and saved-message recovery. Related #13293 covers retained
processes that actually started; this change covers cancellation before
the native provider claim. Related #13315 covers legacy queued-message
delivery.

**What happened?**

Pausing a task during startup could cancel its heartbeat before native
runtime selection. Stale preparation then created an observed native
coordinator on the cancelled run. The coordinator had no provider result
or eligible recovery worker. A later Continue message stayed queued
indefinitely.

**Expected behavior**

Cancellation fences native startup. After verified cleanup, a newer user
message starts one fresh conversation turn. An unverified execution
keeps its hold and a clear explanation.

**Steps to reproduce**

1. Start a task with the native runner and delay startup preparation
before runtime selection.
2. Pause the task, then release preparation.
3. Resume the task and send Continue.
4. Before this fix, native selection can persist after cancellation and
block the saved message.
5. Repeat from persisted cancelled startup state after a server restart.

**Paperclip version or commit**

Reproduced against master at `586b5ec82` with isolated PostgreSQL
regression fixtures.

**Deployment mode**

Self-hosted server built from source, with Paperclip Runner.

## What Changed

- Serialize the cancellation fence and native runtime selection on the
run row. Revalidate the startup controller lease.
- Refresh the runtime before dispatching cancellation, and reject
terminal or cancelled runs at the native provider claim.
- Recognize never-claimed coordinators only after startup and
environment cleanup are verified. Reject process, provider, owner, and
conflicting launch evidence.
- Settle that coordinator atomically with a new authenticated user turn.
Preserve history, unknown outcomes, and attempt counts.
- Reuse the saved-message worker after restart and retain pause, budget,
approval, and ownership gates.
- Add startup, restart, duplicate-admission, and negative-proof
regressions. Document the rule.

## Verification

- All 687 tests pass across the complete heartbeat recovery, explicit
continuation, and native session executor suites on the rebased branch.
- Six focused race regressions also pass: cancellation before and after
native selection, Stop racing adapter registration, process termination
during a database failure, and a run finishing during cancellation.
- `pnpm -r typecheck` and `pnpm build` pass after rebasing on master at
`ab15aff39`.
- Greptile is 5/5 on `f3dea2ab27facdf0360b56172ebd3e5219e25538`, with no
open review threads. Policy and security checks pass.
- All 32 CI checks pass on the final head, including the full
server/workspace test matrix, all three browser shards, runner
verification, typechecks, build, and canary dry run. The two optional
Storybook jobs are skipped. [CI
run](https://github.com/paperclipai/paperclip/actions/runs/34697945514).
- Local full-suite limitation: the broad `pnpm test:run` attempt
reported two failures outside the changed area after unusually long test
durations (about 65 seconds for supporting skill-file saves and 933
seconds for setup-token login). Both cases passed isolated reruns, with
no code changes. The broad local run was stopped after CI completed
successfully; no clean full local-suite pass is claimed.

## Risks

Cancellation and startup overlap. The run and coordinator locks provide
the authority fence; cleanup and process evidence provide the
containment proof. Historical runs without sufficient evidence remain
blocked. A saved user message authorizes a fresh turn, not automatic
replay. No schema migration or dependency change.

## Model Used

OpenAI GPT-6 through Codex, using reasoning, repository inspection, code
execution, and tests. This session does not expose the exact backend
revision 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>
canary/v2026.912.0-canary.7
2026-09-12 11:39:36 -05:00
DottaandPaperclip 9132e8279f chore(skills): allow verified PR merges (#13313)
## Thinking Path

> - Paperclip uses repository skills to guide agent work.
> - The PR preparation skill controls the pull request workflow.
> - One hard rule prevents an agent from merging a verified pull
request.
> - The requested workflow must permit that action when other authority
allows it.
> - This pull request removes only that one rule.
> - All other PR safety and review rules stay unchanged.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The `prepare-paperclip-pr` agent workflow.

**Current behavior**

The skill always prohibits the agent from merging a pull request itself.

**Proposed behavior**

The skill no longer adds that universal prohibition. Other permissions
and workflow rules still apply.

**Reason and benefit**

An authorized workflow can merge a verified pull request without
conflict with this skill.

**Breaking changes**

The skill no longer blocks every agent-initiated merge.

## What Changed

- Remove the single universal no-merge rule from the PR preparation
skill.

## Verification

- Confirm the pull request changes one file and deletes one line.
- Run `git diff --check` against the pull request commit.

## Risks

- An agent can merge when its other instructions and permissions allow
it.
- Existing review, CI, and work-preservation rules remain in place.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI Codex, GPT-5.6, with reasoning and tool use.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.912.0-canary.6
2026-09-12 09:03:07 -05:00
DottaandPaperclip ab15aff390 feat: add experimental persistent agent chat (#13284)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Conversations must use the same tasks, controls, and execution
history.
> - Users need an ongoing chat with an agent without managing task
properties.
> - Agents should clarify and plan work, then hand execution to assigned
project tasks.
> - This pull request combines the reviewed Agent Chat stack for one
squash merge.
> - The benefit is persistent conversation with normal task governance
and shared UI.

## Linked Issues or Issue Description

**Subsystem affected**

Task lifecycle, agent runtime tools, shared task UI, and browser/paid
runner tests.

**Problem or motivation**

Users need one persistent conversation with each agent. A separate chat
store or renderer would duplicate task behavior and bypass existing
controls.

**Proposed solution**

Use a task-backed chat per company, user, and agent. Reuse the task
composer and transcript. Clarify and plan in chat, then create assigned
project tasks with the relevant plan. Keep Agent Chat behind its own
disabled-by-default experimental setting.

**Roadmap alignment**

This implements the task-backed direction in [CEO
Chat](https://github.com/paperclipai/paperclip/blob/master/ROADMAP.md#-ceo-chat).
Related proposals: #2504 and #9693. Related request: #7981. The
maintainer requested one squash merge of the complete stack.

Consolidates the reviewed runtime
[#13281](https://github.com/paperclipai/paperclip/pull/13281), backend
[#13282](https://github.com/paperclipai/paperclip/pull/13282), and UI
[#13283](https://github.com/paperclipai/paperclip/pull/13283) layers
with this PR's E2E coverage. All four layers passed CI and received
Greptile 5/5 before consolidation. This PR targets master and includes
the complete feature.

## What Changed

- Add personal canonical chat tasks with ordinary company visibility,
immutable identity, idempotent first sends, and an idle waiting state.
- Process `/new` in queue order. Preserve history, release a chat pause,
and fence old provider context and delayed writes.
- Keep chat lifecycle rules across recovery, finalization, assignment,
task lists, and rollups.
- Support research and plan revision in chat. Hand plans to ordinary
assigned project tasks before execution starts. Reject new chat
subtasks.
- Add repository-aware project creation and discovery tools, including
multiple repository IDs and GitHub URLs, authorization, idempotency, and
durable project-created cards.
- Reuse task UI components for chat, with starred/recent agent
navigation and a separate `enableAgentChat` experimental flag.
- Add deterministic browser tests and 24 paid chat cells across four
Codex/Claude profiles, with validated reports and screenshots.
- Integrate current master recovery, controller lease, queued-message,
and task UI changes. Gate chat interruption and deferred promotion on
ownership/feature policy. Guarantee lease renewal and active controls
are stopped even if teardown fails.
- Preserve master's migration 0273 and generate chat migration 0274 with
idempotent replay for development databases.

## Verification

- Prior exact heads of all four PRs passed Linux CI, including build,
typecheck, general/serialized tests, and browser E2E. Each had Greptile
5/5 and no unresolved findings.
- Integrated local verification passed: full repository typecheck and
production build, Storybook build, token gates, 340 focused UI tests,
all 20 deterministic chat browser tests, two migration replay tests, 88
focused chat/queue/native/controller tests, and provider/session
regressions including real lease expiry. These include the three
lifecycle regressions for the final admission/teardown fixes; server
typecheck also passes. Current head
`1268eda16cc2af892055917e7292f068820be135` has Greptile 5/5 with no
unresolved findings and passing security scans. All final-head CI gates
passed: build, full Runner verification, typecheck/release registry,
canary, all general/serialized test shards, and all browser E2E shards
([CI
run](https://github.com/paperclipai/paperclip/actions/runs/34696739927)).
Local PostgreSQL startup contention required serialized retries; skipped
fixtures do not count as passing coverage.
- The earlier paid campaign passed all 24 chat cells and retained 32
screenshots:
[report](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-34648511170-1/index.html?report=agent-chat#suite-agent-chat).
It tested `abacbdfd2f660709ec37312cdb758284c8399d04`; it is prior
evidence, not a paid run of this integrated head.
- Manual check: enable Agent Chat in Experimental settings, open an
agent, clarify and revise a plan, then hand off to an assigned project
task. Stop a reply, send `/new`, and verify fresh context with retained
history. Disable the setting and verify agent shortcuts/new chat turns
are blocked.

## Risks

- Queue/session integration can affect retries and delayed writes. Tests
cover ownership, cancellation, reset boundaries, idle recovery, and
ordinary task behavior.
- Migration 0274 adds conversation fields and constraints. Replay is
idempotent and preserves existing development chat history.
- This combines the previously reviewed stack at the maintainer's
request. Agent Chat remains off by default and is separate from
Conference Room.

## Model Used

OpenAI Codex, GPT-6 Astra (`gpt-6-astra`), with reasoning, code
execution, browser tools, and parallel review. The exact context-window
size is not exposed in this session. Codex and Claude also ran as test
subjects in the linked paid campaign.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.912.0-canary.5
2026-09-12 08:56:04 -05:00
github-actions[bot]andlockfile-bot e830180139 chore(lockfile): refresh pnpm-lock.yaml (#13279)
Auto-generated lockfile refresh after dependencies changed on master.
This PR only updates pnpm-lock.yaml.

Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com>
2026-09-12 08:36:40 -05:00
DottaandPaperclip 586b5ec828 fix(ui): improve mobile task spacing (#13304)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - The task detail view is the main place for task conversation.
> - The mobile view used too much horizontal space for gutters and
controls.
> - The status control and identifier also reduced the title width.
> - This pull request gives the title its own mobile row and reduces
mobile padding.
> - The benefit is a clearer task view with more space for useful
content.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The mobile task detail header, conversation list, and message composer.

**Current behavior**

The title shares one row with status and identifier controls. The
conversation and composer also use larger mobile gutters than needed.

**Proposed behavior**

The title uses the full mobile width. Status and metadata use the next
row. The conversation and composer use smaller mobile gutters.

**Reason and benefit**

Long titles have more readable line lengths. The reduced padding gives
task content more room on small screens.

**Breaking changes**

None.

## What Changed

- Put the task title on a full-width mobile row.
- Move the mobile status and metadata below the title.
- Reduce the mobile conversation and composer padding.
- Update the composer dock class test.

## Verification

- `pnpm --filter @paperclipai/ui typecheck`
- `pnpm exec vitest run ui/src/components/TaskChatThread.test.tsx
ui/src/components/task-chat/TaskChatComposer.test.tsx
ui/src/pages/IssueDetail.test.tsx --reporter=dot`
- `pnpm --filter @paperclipai/ui build`
- `pnpm check:token-gates`
- `git diff --check`

## Risks

- Low risk. The layout changes apply only at the mobile breakpoint.
- Desktop spacing stays unchanged.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI Codex, GPT-5.6, with reasoning and tool use.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [ ] 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-09-12 08:27:14 -05:00
DottaandPaperclip 8f40b4ad4b fix(connections): repair and simplify Google Workspace setup (#13289)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - App connections give agents controlled access to external services.
> - Managed Google Workspace methods depend on profiles enabled for each
Paperclip instance.
> - The catalog used those profiles, but connection creation used static
availability and rejected enabled connections.
> - Switching capabilities also reset personal ownership to company-wide
ownership.
> - This PR uses the same availability rules for catalog and setup, and
preserves supported ownership choices.
> - Paperclip is the default Google authentication method. A small link
opens custom OAuth settings when needed.
> - Local and cloud instances can start the selected Workspace
connection without broadening its audience.

## Linked Issues or Issue Description

**What happened?**

A fresh enrolled instance showed managed Google Workspace apps as
available. The issue was first found with Gmail. Selecting Continue to
sign in returned HTTP 422 with “This app does not have an available
connection method.” Changing from Read & create drafts to Read only also
reset Just me to company-wide ownership.

**Expected behavior**

Start Google authorization for an enabled profile. Keep personal
ownership when the selected method supports it. Reject profiles that the
instance cannot use.

**Steps to reproduce**

1. Start a fresh source test-drive and enroll the instance with
Paperclip Cloud.
2. Open Apps and select Gmail.
3. Select Just me and choose the agents that can use the connection.
4. Continue to setup and select Read only.
5. Go back to inspect ownership, then continue to sign in.

**Paperclip version or commit**

Reproduced on master commit 250deab910.
The fix is rebased onto current master.

**Deployment mode**

Local source test-drive. Regression tests also cover authenticated cloud
mode, HTTPS callbacks, and instance credentials supplied through
environment variables.

Related PRs: #13098 preserves task context through enrollment and OAuth.
#12619 introduced the managed Google Workspace rollout. This PR fixes
availability validation and ownership changes in that setup flow.

## What Changed

- Share instance-specific managed-method filtering between catalog
discovery and connection creation.
- Keep stored managed methods recognizable during callback, refresh, and
revoke.
- Preserve credential ownership when switching to another method that
supports it.
- Replace the Google authentication radio cards with a small Use your
own Google OAuth app link. Reveal custom fields only when selected, with
a Use Paperclip instead link to return. Associate the toggle with its
labeled field region for screen readers.
- Test all 16 managed Google Workspace profiles in local and
authenticated cloud modes, including cloud environment credentials and
unavailable profiles.
- Test ownership across all nine Workspace app cards, including
capability changes, authentication changes, and enrollment return.
- Document the shared availability and ownership behavior.

## Verification

- All 135 setup tests pass after the UI change. The focused connector
and service suites also passed before this presentation-only change.
- The expanded Workspace matrix includes 32 local/cloud callback cases,
16 cloud environment-identity cases, 32 unavailable-profile cases, and
18 UI ownership cases.
- `pnpm -r typecheck`, `pnpm build`, and `pnpm check:token-gates` pass.
UI typecheck and token gates also pass on final commit `2071002d6`.
- Browser tests cover Gmail, Calendar, Chat, Docs, Drive, People,
Sheets, Slides, and Workspace Search in an isolated source test-drive.
- Each app reaches Google sign-in with its expected read-only scopes.
Personal ownership persists after capability or authentication changes.
Chat also resumes its saved setup with read-only access intact.
- Browser verification of the new layout: custom fields start hidden,
the small link reveals them, and keyboard activation of Use Paperclip
instead hides them. Personal ownership and read-only selection persist.
- Google consent was not granted. Live provider reads and a deployed
cloud instance remain unverified.
- The local repository-wide suite was stopped at the maintainer's
request. Full CI verification passed for final commit `2071002d6`: 31
successful checks, two optional Storybook checks skipped. This includes
repository tests, browser E2E, typecheck, build, and canary dry run.
Greptile reviewed that commit at 5/5 with no outstanding findings.

## Risks

- The shared availability helper affects all managed connectors. It
filters methods by the instance's advertised profiles and does not
mutate the static catalog.
- Stored connections can resolve their managed method after availability
changes. The broker still enforces current access during authorization
and refresh.
- No database migration or provider scope change is included.

## Model Used

OpenAI Codex (GPT-6), with reasoning, code editing, shell tools, and
browser automation. The session does not expose an exact runtime 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>
canary/v2026.912.0-canary.4
2026-09-12 07:57:48 -05:00
DottaandPaperclip eb9f954bae fix(ui): stabilize steered chat activity presentation (#13246)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The task chat shows live agent work and user steering.
> - Steered messages showed a second timestamp that did not match normal
chat messages.
> - Folded live work also changed height as new commands arrived.
> - Status carets and dots did not use the same vertical alignment.
> - This pull request gives these states one stable presentation.
> - The benefit is a task chat that is easier to read while an agent
works.

## Linked Issues or Issue Description

**What happened?**

Steered chat messages showed a separate queued or steered timestamp.
Folded live activity could grow and shrink. Some carets and status dots
did not align vertically.

**Expected behavior**

Steered messages use the normal timestamp. Folded live activity shows
one latest line until the user opens it. Carets and dots use the same
vertical center.

**Steps to reproduce**

1. Open a task chat with a running agent.
2. Steer the chat and inspect the message timestamp.
3. Keep live activity folded while new commands arrive.
4. Compare the caret with the status dot in the Reconnecting state.

**Paperclip version or commit**

Current `master` before this change.

**Deployment mode**

Local development mode.

## What Changed

- Use the normal timestamp for steered chat messages.
- Keep folded live activity to one line and replace it with the latest
activity.
- Keep the full activity timeline available after explicit expansion.
- Vertically align carets and status dots, including Reconnecting.
- Add focused component tests and Storybook review states.

## Verification

- `pnpm --filter @paperclipai/ui exec vitest run
src/components/task-chat/TaskChatRunnerTurn.test.tsx
src/components/task-chat/TaskChatStatusPill.test.tsx
src/components/task-chat/task-chat-adapter.test.ts` (63 tests passed)
- `pnpm --filter @paperclipai/ui typecheck`
- `pnpm check:token-gates`
- `pnpm --filter @paperclipai/ui build-storybook`

## Risks

- Low risk. The change is limited to task chat presentation and its
tests.
- A live activity item can replace the folded text. The expanded
timeline keeps the full history.

> This fix does not overlap with planned work in `ROADMAP.md`.

## Model Used

- OpenAI Codex. The runtime did not expose the exact model ID or context
window. The agent used reasoning, tool use, and code execution.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] 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>
nightly/v2026.912.0-nightly.0 canary/v2026.912.0-canary.3
2026-09-11 21:26:44 -05:00
DottaandPaperclip 30aa3740ba fix(ui): make feed cards fully clickable (#13294)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - The activity feed shows cards for recent work.
> - A feed card showed a linked entity, but only some card content
behaved as one clear click target.
> - Users expect the image, title, and blank card space to open the
entity.
> - This pull request makes the full visible card use the entity link.
> - It also adds a regression test for the full-card click target.
> - The benefit is a larger and consistent navigation target.

## Linked Issues or Issue Description

**What happened?**

Clicks on some feed card content or blank card space did not reliably
open the linked entity.

**Expected behavior**

A click anywhere in a linked feed card opens its entity quick view.

**Steps to reproduce**

1. Open the activity feed.
2. Find a card that links to an entity.
3. Click its image, title, or blank space.
4. Observe that only part of the card acts as the link before this
change.

**Paperclip version or commit**

Current `master` before this pull request.

## What Changed

- Made each linked feed card anchor use the full available width.
- Made the visible card width account for its existing page margins.
- Added a component test that clicks the card and confirms link
navigation.

## Verification

- `pnpm --filter @paperclipai/ui exec vitest run
src/components/FeedCard.test.tsx`
- `pnpm check:token-gates`
- `pnpm --filter @paperclipai/ui typecheck`

## Risks

- Low risk. The change only expands the existing link click target.
- The width calculation can affect feed card layout. The regression test
checks the expected width classes.

> This bug fix does not add a roadmap feature.

## Model Used

- OpenAI GPT-5.6, Codex agent, with reasoning and code execution 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
- [ ] 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>
canary/v2026.912.0-canary.2
2026-09-12 01:58:25 +00:00
Devin FoleyandPaperclip 09e208c54f ci: activate shared PR dependency cache restores (#13302)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - PR checks share a repository cache budget with post-merge cloud
verification.
> - Per-PR dependency store copies consume about 700 MB each and
displace useful build caches.
> - The reviewed workflow now restores shared dependency caches without
saving PR copies.
> - The public entry point must pin an approved immutable workflow
before it can use AWS runners.
> - This PR activates the merged workflow after the runner group
accepted its exact SHA.
> - Native verification and the app build also run in parallel, as
defined in the merged workflow.

## Linked Issues or Issue Description

Refs #13300. Refs #13301.

The cache definition is merged, and its exact SHA is authorized in the
restricted runner group. This PR activates it. Its base also contains
the two synthetic fixture fixes from #13301. No duplicate activation PR
was found.

## What Changed

- Advance the `pr-trusted.yml` pin from
`03609aa6ecc9a047ed53d6b6469d8be554fbc46d` to merged commit
`44dde2dec42a22746a2f36b595acacc9ccfa1df6`.
- Update the adjacent pin comment to identify #13300 and the activated
behavior.
- Activate restore-only pnpm caching and removal of redundant Node setup
steps from #13300.
- Activate the already-merged separate native verification job, required
by the aggregate `verify` check. The app build no longer waits for
native verification inside the same job.
- Activate the merged module-boundary and source-verification checks and
explicit Runner Evalbook viewer build.

## Verification

- Passed all 505 workflow, routing, cache, sharding, and
source-verification tests.
- Passed `actionlint` for both workflow files and `git diff --check`.
- Passed the runner infrastructure's workflow routing regression tests.
- Confirmed that the gate is unchanged between the old and new workflow
definitions. The restricted runner group permits the exact merged SHA
and retains its existing workflow pins.
- Full workspace typecheck and build passed on the timeout-fix branch.
Its 107 targeted runner tests and all Linux CI groups passed. The broad
local Mac test command had 15 unrelated permission and
missing-skill-path failures, documented in #13301; it stopped before
later groups.
- [Current-head CI run
34662664879](https://github.com/paperclipai/paperclip/actions/runs/34662664879)
passed. All 33 checks are green or intentionally skipped at
`ded4f1d093644b9279cdf56457f69a196fcf8cc2`. Greptile is 5/5, with no
unresolved findings.
- The live build restored the master pnpm cache, downloaded the resolved
lockfile artifact, and completed a frozen install. It had no
dependency-cache upload step. GitHub reports zero cache entries for this
PR. Native verification and the app build started together and both
passed.
- [Post-merge cloud readiness for
#13301](https://github.com/paperclipai/paperclip/actions/runs/34662389233)
passed all 30 jobs in 12m42s from merge. Native verification restored
the master Rust cache and passed the formerly failing fixtures.

## Risks

A new PR-only dependency can require a download until a master cache
contains it. The new pin also activates the merged workflow changes
listed above, so the live PR must pass all checks. The repository
storage cap is still 10 GB; this PR does not increase it. No allowlist
or runner permission logic changes.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, and code
execution. The exact serving model ID and context window are not exposed
by this environment.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.912.0-canary.1
2026-09-11 18:05:36 -07:00
Devin FoleyandPaperclip 5cc7784986 test: remove cold executable reads from runner integrity deadlines (#13301)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native runner protocol tests verify that invalid authenticated input
fails closed.
> - Cloud readiness requires those tests to pass before a source commit
can deploy.
> - Two test fixtures hash the host Node executable twice even though
its process launcher is synthetic.
> - Cold reads of a large Linux executable consume time unrelated to
protocol failure handling.
> - This PR gives both synthetic runner fixtures tiny real artifacts and
keeps their existing deadlines.
> - Real authentication, encrypted frames, and request and notification
failures remain covered.

## Linked Issues or Issue Description

**What happened?**
Cloud readiness repeatedly failed in `DurablePrpControlPlane > promptly
fails the real transport request and notification paths on authenticated
bad semantic input (throwing observer: false)` with `Test timed out in
5000ms`. The image built, but the failed source check prevented
deployment. See runs
[34656885170](https://github.com/paperclipai/paperclip/actions/runs/34656885170)
and
[34657111560](https://github.com/paperclipai/paperclip/actions/runs/34657111560).

The first case took 5.6–11.4 seconds; the following case took about 0.4
seconds. The original test reads and hashes `process.execPath` once
itself and once through the real transport. The Node executable is
122,678,944 bytes in the local Linux Node 24 container, versus 68,672
bytes on the development Mac. Instrumented Mac runs pass; cold
executable reads are a likely cause of the CI-only timeout.

**Expected behavior**
The deadline should measure real protocol rejection and consumer
failure, without reading a large unrelated executable as test fixture
data.

**Steps to reproduce**
1. Run the named test with the real transport and synthetic process
launcher.
2. For a deterministic probe, inject a six-second delay into the first
`readFileSync(process.execPath)` call.
3. The original test exceeds its existing five-second deadline. Both
cases pass after this change because neither reads the host executable.
The probe is temporary instrumentation, not part of this commit.

**Paperclip version or commit**
f12b647ae; the same failure also occurred on a38ccf997 and 9031516a7.

**Deployment mode**
Cloud readiness in GitHub Actions on Linux AWS runners. No duplicate
open PR found after searching runner timeout and durable PRP changes.

## What Changed

- Write a 26-byte synthetic runner artifact inside each existing
temporary test directory.
- Bind both the real authority and test client to that artifact's actual
SHA-256 digest.
- Retain synthetic process launchers, real wire exchange, all observer
and composed-runtime cases, integrity assertions, cleanup, and existing
five- and fifteen-second timeouts.

## Verification

- Passed all 107 tests across
`src/control-plane/durable-prp-control-plane.test.ts` and
`src/drivers/codex/codex-protocol-integrity.test.ts` using the package
Vitest configuration.
- With a temporary six-second host-executable read delay, the original
case times out. Both fixed cases pass in 235 ms combined under the same
fault injection.
- Passed `git diff --check`.
- Full workspace typecheck and build passed. The full local test command
stopped after the general server group: 10,694 tests passed and 15
failed. Thirteen failures involve macOS directory rename permissions in
the skill-cache suites. Two failures involve a missing local AgentMail
skill path. Later groups did not run in that local invocation. The
targeted runner tests passed; all Linux CI test groups passed.
- [Current-head CI run
34661107658](https://github.com/paperclipai/paperclip/actions/runs/34661107658)
passed. All 32 checks are green or intentionally skipped at
`e7053594e647fd8e9b71fc569cab6b7a3e9cd210`. Native runner verification
passed in 15m25s. Greptile is 5/5 on that head, with no unresolved
review findings.

## Risks

Low risk: this changes test fixture data only. The launcher never
executes the file. Artifact hashing and authentication still use real
bytes. Protocol behavior and existing test deadlines do not change. The
current Linux CI run passed both fixtures and the full native runner
verification. Further post-merge runs will test repeatability.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, and code
execution. The exact serving model ID and context window are not exposed
by this environment.

## 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 (targeted runner tests;
full local suite limitations are listed 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-09-11 17:39:57 -07:00
Devin FoleyandPaperclip 44dde2dec4 ci: reuse dependency caches without per-PR uploads (#13300)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Cloud releases wait for source verification before deployment.
> - That verification reuses compiled Rust dependencies to finish
sooner.
> - PR jobs save large pnpm stores under separate merge refs and
different lockfile keys.
> - Those copies compete with master build caches for the repository's
10 GB cache limit.
> - This PR makes PR dependency caches restore-only and reuses
master-compatible keys.
> - A separate pin update will activate the reviewed workflow.

## Linked Issues or Issue Description

**What happened?**
PR merge refs accumulated roughly 700 MB copies of the same pnpm store.
Master Rust caches disappeared, and Cloud readiness run
[34656098157](https://github.com/paperclipai/paperclip/actions/runs/34656098157)
rebuilt dependencies after cache misses. The repository currently has a
10 GB limit. GitHub rejected a request for 50 GB; that setting needs
separate organization/billing access.

**Expected behavior**
PR jobs should reuse downloaded packages without evicting post-merge
compilation caches through duplicate uploads.

**Steps to reproduce**
1. Run several PRs while the checked-in lockfile needs policy
regeneration.
2. Compare the setup-node keys in PR jobs and master jobs.
3. List Actions caches by ref, key, and archive size. The PR keys repeat
across merge refs.

**Paperclip version or commit**
f12b647ae, before this change.

**Deployment mode**
GitHub Actions, with GitHub-hosted and allowlisted AWS PR runners.

Refs #13267 (empty pnpm store prevention). Searched open issues and PRs
for pnpm cache duplication and found no duplicate implementation. This
change leaves the paused capacity documentation PR #13280 alone.

## What Changed

- Replace setup-node cache writes with pinned `actions/cache/restore` in
all seven PR install job definitions.
- Restore against the checked-in lockfile before downloading the
regenerated policy artifact. Keep every install frozen against that
artifact.
- Allow an OS/architecture-specific pnpm fallback and disable automatic
setup-node caching.
- Remove dependency-store caching from the resolution-only policy job.
- Add eight regression tests, update the existing stacked-lockfile cache
assertion, and document cache behavior and storage settings.

## Verification

- Passed 505 workflow, routing, cache, and source-verification tests:
`node --test '.github/scripts/tests/*.test.mjs'
scripts/__tests__/e2e-shard.test.mjs
scripts/__tests__/run-vitest-stable-shard.test.mjs
scripts/__tests__/release-verify-workflow.test.mjs
scripts/cloud-source-verification.test.mjs`.
- Passed `actionlint .github/workflows/pr-trusted.yml` and `git diff
--check`.
- The AWS routing gate is unchanged. Author, event sender, and rerun
actor must still be allowlisted.
- This definition PR does not change the active `pr.yml` pin. After
review and merge, authorize its immutable merge SHA additively and
activate it in a separate PR. Verify a populated restore and no cache
uploads in an allowlisted PR.
- All 32 checks passed or were intentionally skipped on
`44b31eca590f61b75cae646de43c491b6c4deae7`, including full native Runner
verification, application build, server/workspace tests, and browser
shards. Current-head Greptile is 5/5 with no findings. No application
code changes in this PR.

## Risks

- New dependencies present only in a PR may download again on each run
until master saves a cache containing them. Frozen installation remains
the source of dependency resolution.
- Missing or expired stores fall back to normal package downloads.
- Existing PR copies remain until expiry or a separate targeted cleanup.
No cache entries are deleted here.
- The workflow only takes effect after the separate immutable pin
rotation. Storage billing settings are not changed by this PR.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, and code
execution. The exact serving model ID and context window are not exposed
by this environment.

## 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-09-11 17:31:15 -07:00
Michael Nguyen fe38085174 fix(ui): hide profile feedback flag on Cloud (#13292)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The sidebar provides account controls and a feedback link.
> - Cloud now has Plain chat through the snippet support in #13168.
> - The feedback flag creates a second feedback route on Cloud.
> - This PR uses the existing Cloud metadata to hide the flag.
> - Self-hosted users keep the existing feedback link.

## Linked Issues or Issue Description

Refs #13168 and #10850. Related: #12778 proposes a separate native
feedback relay; this PR only hides the existing flag on Cloud.

**What happened?**
Cloud users see both Plain chat and the profile feedback flag, which
opens the external feedback form.

**Expected behavior**
Cloud users use Plain chat. Self-hosted users keep the profile feedback
flag.

**Steps to reproduce**
Open a Cloud instance with Plain enabled and expand the sidebar. Both
feedback controls are visible.

## What Changed

- Use `useCloudInstance()` in both account-menu variants.
- Render the feedback flag only when the sidebar is expanded and the
instance is not Cloud.
- Extend existing tests for Cloud and authenticated self-hosted
behavior.

## Verification

- Account-menu tests: 6 passed (`cd ui && pnpm exec vitest run
src/components/SidebarAccountMenu.test.tsx`).
- `pnpm check:token-gates`: passed.
- `pnpm --filter @paperclipai/ui typecheck`: passed.
- Full typecheck: failed in unchanged `plugin-workspace-diff` code
(`editStateKey` required by `UseFileDiffInstanceProps`).
- UI build: blocked by four missing exports in the installed
`assistant-cloud` dependency, including `createRunReport`.
- Repository build: failed on the same unchanged workspace-diff plugin
types.
- Full test suite: started, then stopped after broader validation hit
dependency failures. Only the six targeted account-menu tests are
claimed as passed.
- Fresh installation used `--no-frozen-lockfile --lockfile=false`
because the base lockfile and server manifest differ. No dependency or
lockfile changes are included.
- After deployment, check that Cloud has no profile feedback flag and
self-hosted still links to `https://paperclip.ing/feedback`.

## Risks

Low risk. The hook reads the existing health query cache and adds no
request. CloudAccessGate loads health before the main UI mounts. The
flag is hidden on all Cloud instances, so operators must keep Plain
configured. No backend, settings, or Plain integration changes.

## Model Used

OpenAI GPT-6 Codex, with code inspection and command execution. The
exact 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
2026-09-11 17:03:38 -07:00
9b7bd41833 feat(ui): refine dashboard cards, charts, and recent lists (#13269)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Operators use the dashboard and Live runs page to inspect current
and recent runs.
> - Large transcript cards take space and make it hard to compare run
states.
> - A compact card must show the agent, linked task, and time, with
access to run details.
> - This pull request applies the supplied card design to both views.
> - Operators can scan more runs and open a run or task for details.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The agent run cards on the dashboard and Live runs page, plus dashboard
charts and recent lists.

**Subsystem affected**

`ui/` — React board UI.

**Current behavior**

Both views show large cards with embedded transcripts. Queued and
running cards share a live treatment. The dashboard chart grid leaves an
empty column, recent lists use different row sizes, and some activity
labels expose raw event names.

**Proposed behavior**

Both views use the same compact grid. Each card shows the existing
initials avatar, the agent name, one linked task row, and a
right-aligned timestamp. There is no status chip next to the agent name.
The timestamp uses small Inter text and the same muted gray as dashboard
metric descriptions. Recovery details remain in the task view. Run
status remains in the header tooltip and accessible label, and run
transcripts remain in the run detail view. The shared in-progress task
icon is now an animated circular spinner across the app.

**Reason and benefit**

Operators can scan task states without scrolling through embedded
output. The in-progress spinner keeps the shared task icon sizes,
circular shape, and stroke width. It honors reduced-motion preferences.

**Breaking changes**

The dashboard and Live runs page no longer show transcripts inside
cards. Open the agent header to inspect a run. There are no API or
database changes.

**Additional context**

Related public work found during the duplicate search:

- Refs #4317 — related run-state display concerns. This change does not
change server state reconciliation.
- Refs #11394 — related live-run cache updates. This change retains the
existing data flow.
- Refs #2118 — related navigation from agent cards. The card header here
opens the specific run.

## What Changed

- Apply compact cards to the dashboard and Live runs page, with status
icons and theme tokens.
- Use 16 × 16px status icons in the shared cards, including the
missing-task clock.
- Keep the existing circular initials avatar. Remove the status chip
beside the agent name while preserving the run label for tooltips and
accessibility.
- Replace the shared in-progress task glyph with an animated open
circle. Use the same 10-unit radius and 2-unit stroke as the other task
glyphs, with a reduced-motion guard across all task status surfaces.
This is the requested workflow-status indicator across the app,
including between runs; live indicators separately report active
execution.
- Use the same Tailwind blue tokens as nav dots and Live labels for the
progress icon: blue-400 in dark mode and blue-600 in light mode.
Covered-blocked icons follow the same blue token.
- Match the Tasks by Status chart's In Progress bar and legend to the
spinner's theme-aware color token.
- Distribute the three visible dashboard charts across equal-width
desktop columns, preserving existing gaps, card padding, and page
margins. Retain four columns when the optional priority chart is
enabled.
- Use the done task icon's `--status-task-icon-done` token for green
bars in Run Activity, Tasks by Status, and Success Rate, including their
legends.
- Use the blocked task icon's `--status-task-icon-blocked` token for red
bars and legends in Run Activity, Tasks by Status, Success Rate, and
priority charts.
- Align Recent Tasks live counts to the sidebar's right edge. Reveal the
ellipsis over a fading row surface on hover, keyboard focus, and while
its menu is open, without moving the label or count.
- Keep the ellipsis backdrop synchronized with the row background during
fade-out, using the actual sidebar surface in both themes to prevent a
darker flash.
- On coarse-pointer devices, reserve space for the always-visible
ellipsis and disable its fade so the live count remains readable beside
it.
- Order desktop dashboard Recent Tasks as status icon, task title, agent
avatar/name, 11px monospace task ID, then timestamp. In narrow cards,
keep the ID right-aligned beside the truncated title and place the agent
and timestamp on the second line.
- Give both dashboard lists the same 48px desktop rows, 24px leading
slots, 80px desktop task ID columns, and 64px right-aligned timestamp
columns. Use an 8px icon-to-content gap matching the task detail
heading. Narrow layouts use matching 76px rows with intrinsic-width IDs
on the title line; activity timestamps stay below.
- Order dashboard Recent Activity as actor avatar, actor name, verb,
task title, 11px monospace task ID, then timestamp. Use direct verbs
such as “Board read …” instead of “issue read marked”. Truncate titles
to preserve IDs and timestamps; keep full names and titles in tooltips.
- Use 12px task status icons in the top breadcrumb and Properties status
row. Keep the main task title icon at 20px.
- Reduce monospace task IDs to the 11px micro type token in breadcrumbs
and shared run cards, aligning them to the adjacent task titles' text
baseline while keeping status icons centered.
- Show the task title and identifier in one bordered row. Keep
missing-task links usable and show lookup failures.
- Remove the recovery chip and place the timestamp below the task row.
- Keep the link to all runs available when the dashboard has four or
fewer runs.
- Avoid transcript polling for compact cards.
- Fix bundled Inter font URLs and update the design guide and Storybook
fixtures.
- Cover run navigation, task status, failed lookups, shared icon sizes
and stroke, and reduced-motion-safe animation in tests.

## Verification

- Latest review fixes: targeted SidebarRecentTasks, SidebarNavItem,
StatusGlyph, StatusIcon, ActiveAgentsPanel, activity-format,
ui-font-assets, and Dashboard suites — 65 tests pass, including
read/unread verbs and reduced-motion-safe task animation.
- `pnpm --filter @paperclipai/ui typecheck` — passes.
- `pnpm check:token-gates` — all gates pass.
- `git diff --check` — passes.
- Related component suites passed during development: run cards, status
glyphs, breadcrumbs, issue properties, charts, sidebar navigation,
recent-task actions, and settings sidebar.
- Full repository `pnpm -r typecheck` and `pnpm build` pass on the final
commit using the temporary Rust toolchain. Storybook build passed
earlier in preparation.
- All CI gates pass on `c85e949b12b471d425d216caa609aee41dc58bde`: all
general/workspace and serialized server test shards, all three browser
shards, build/runner verification, typecheck/release registry, canary
dry run, policy, and security checks. The duplicate local `pnpm
test:run` was stopped after CI completed the same test suites; it is not
claimed as a completed local pass. The two Storybook jobs are skipped by
the configured draft-PR workflow.
- Greptile reviewed the final commit at 5/5 with no actionable findings
and zero unresolved review threads.
- Browser measurements at 1654px, 860px, and 390px confirm matching 48px
desktop and 76px narrow rows (plus 1px dividers), right-aligned IDs on
the title line, 64px timestamp slots, and no horizontal overflow. Narrow
Recent Tasks rows retain readable agent names below the title. Activity
reads as actor, verb, title, ID, time. Additional reference details can
expand an activity row.
- Verified three equal-width desktop charts with 16px gaps and aligned
outer edges. Chart blues, greens, and reds resolve to the matching
task-icon tokens.
- Verified real queued, running, succeeded, failed, cancelled, and
timed-out runs in the dev dashboard. Checked compact cards, task/run
links, timestamps, light/dark themes, and narrow layout.
- To inspect: open Dashboard, then Live runs. Both pages use the same
small cards. Open an agent header for run output, or the task row for
task details.
- Verified the updated spinner on the real dashboard cards, Recent
tasks, and task list. Checked actual SVG circle radius, rendered size,
and stroke width. Confirmed the spinner, nav dots, and Live labels
resolve to the identical blue-400 color in the dark-mode preview; light
mode uses their shared blue-600 token.
- Verified 12px computed width and height in the task breadcrumb and
Properties pane, the restored 20px main task icon, and 11px task IDs
with baseline alignment in the breadcrumb and shared dashboard/Live runs
cards.
- Verified the chart bar and legend resolve to the spinner color; Recent
Tasks counts align with Dashboard's count. Checked the fading ellipsis
overlay with keyboard focus and its open-menu state, then dismissed the
menu.

## Risks

- Operators must open run details to read output that was previously
embedded.
- Run outcomes are available in the header tooltip and run details
instead of a visible status chip. An in-progress task icon reflects task
status, independently of an individual run's outcome.
- Long names and task titles truncate within the compact layout. Full
labels remain available through links and tooltips.
- Font loading changes affect all UI text that uses the bundled Inter
font. The files remain served from the existing public fonts directory.
- No schema, API, adapter, or execution-policy changes.

## Model Used

OpenAI Codex, GPT-6 Astra (`gpt-6-astra`), with extended reasoning,
repository tools, code execution, and browser verification. 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
- [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: Scott Tong <scott@scotts-mbp-m5-max.local>
Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.912.0-canary.0
2026-09-11 17:02:40 -07:00