Commit Graph
1274 Commits
Author SHA1 Message Date
Devin FoleyandPaperclip 799e4d556f fix: make accounting durable and synchronize cost reporting (#14997)
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-06 22:26:48 -07:00
Devin FoleyandPaperclip 892b0b3606 fix: scope quota reports to authorized subscription accounts (#14994)
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-06 18:20:37 -07:00
Devin FoleyandPaperclip 228f0e2807 fix(ui): make pull request review waits visible (#15375)
## Thinking Path

> - Paperclip lets people supervise agent work and review its outputs.
> - A task can wait for a human to review a pull request while an agent
schedules checks.
> - The PR work product and detected external links use separate display
paths.
> - A private PR can disappear from the useful sidebar view when its
provider lookup fails.
> - The monitor countdown says when the next check runs but omits the
saved review request.
> - This change shows the saved PR and requested review in the task's
existing surfaces.

## Linked Issues or Issue Description

**What happened?**

A task kept checking whether a private GitHub PR had merged. Its work
product requested board review, but the Properties sidebar used detected
external objects instead. The PR URL was stored only in metadata, which
the PR refresh path did not read. The composer showed a generic monitor
countdown with no PR link or review action.

**Expected behavior**

Show saved PR links even if provider access fails. During a GitHub
monitor wait, make outstanding review requests visible with the next
check time and a status-check action. Stop requesting review when a PR
merges or closes.

**Steps to reproduce**

1. Register a PR work product with `reviewState: needs_board_review` and
its URL in `metadata.url`.
2. Schedule an external-service monitor for GitHub.
3. Open the task with external-object lookup unavailable or unable to
access the private repository.
4. Inspect Properties and the composer wait strip.

Related work: #14469 added rich artifact cards. #8759 addresses
attention on monitored task blockers. This change uses the existing work
products and monitor action; it adds no blocker or approval mechanism.

## What Changed

- Show saved PRs in Properties, including metadata-only links,
independent of external-object availability.
- Deduplicate equivalent GitHub PR URLs while preserving the saved
navigation link, and put explicit review requests first.
- Keep provider status and freshness on the combined PR row; keep
private PR links usable when lookup fails.
- Show the saved PR review request above the composer and in the
existing monitor banner during a GitHub monitor wait.
- Label the existing monitor action `Check status` and show check
failures inline.
- Suppress review prompts for merged, closed, or archived PRs even if
their review flag is stale.
- Refresh PR metadata using `metadata.url` and the existing `repository`
alias.
- Share saved work-product reads across the thread, Properties, and
Artifacts. Refresh GitHub in a separate query and enrich only matching
PR versions.
- Start a fresh saved-row request on live invalidation so late provider
responses cannot hide new artifacts or changed review requests.
- Cover stalled GitHub lookups in both panels so refresh latency cannot
hide saved work.
- Scope monitor-check mutation state to the task so failures and late
responses do not leak across navigation.
- Refresh GitHub status when the displayed run finishes, including when
saved PR rows have not changed.
- Clarify that PR review and external release handoffs need a saved
human-input interaction with an agent assigned for continuation; a flag,
monitor, or handoff comment alone does not create that card.

## Verification

- 386 tests pass across eleven affected UI and server suites on
`184c7d8746`. Regressions cover saved links, provider status, cold-cache
loading, panel reopening, monitor errors during navigation, and live
updates during provider refresh.
- Three live-update regressions and two run-completion regressions fail
before their fixes and pass afterward. These tests use the real API
client's GET coalescing and abort handling.
- Full repository typecheck and build passed on the merged parent
`1a49112dd2`. The latest UI changes pass UI typecheck and token gates;
CI also verifies the latest build. Capability contract/inventory checks
pass.
- Storybook build and browser checks passed before the query race fix.
Browser checks cover desktop and 390px mobile review waits, plus video,
mixed-file, and empty artifact galleries after background refresh.
- The earlier full local `pnpm test:run` was stopped under disk
pressure. It reported failures outside the changed suites; an isolated
skill-cache run reproduced three existing macOS permission failures. The
full local suite was not rerun for this follow-up.
- Latest-head CI passes on `184c7d8746`, including the browser shards
and canary dry run. Apex is 5/5 with no actionable findings and no
unresolved threads. All eight reported findings are addressed.

## Risks

- This uses saved PR review state. When GitHub access fails, the saved
state can remain stale until the agent updates it. The link remains
visible and the status check remains available.
- `Check status` wakes the existing monitor owner. It does not merge a
PR, accept an approval, or mark the task done.
- No schema, permissions, or scheduler behavior changes.

## Model Used

OpenAI GPT-6 via Codex, with reasoning, repository analysis, code
editing, and test execution. The exact deployment model ID and context
window were not exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-06 16:03:13 -07:00
DottaandPaperclip ee3c728b95 fix(ui): keep No project available in new composer (#15382)
Keep the no-project action first and available during project search, while preserving matching-project keyboard selection. Add focused regression coverage for ordering, projectless submission, and filtered Enter behavior.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-06 16:04:08 -05:00
DottaandPaperclip 582911ba74 fix(access): give Operators default company editing permissions (#15377)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Human company members receive permission grants from their role
preset.
> - Human invitations use the Operator role by default.
> - The old Operator preset only granted task assignment, so ordinary
members could not edit agents or manage connections.
> - This pull request gives Operators company editing and audit access
while keeping join approval and member-permission management separate.
> - Members can configure their agents and accounts without an Owner
role.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The default permission grants for human Operators and the invitation
role description.

**Subsystem affected**

server/ permission presets and invitation authorization, plus ui/
invitation and tool access gates.

**Current behavior**

Operators receive only `tasks:assign` as an explicit default grant.
Agent configuration and managed account setup fail their permission
checks.

**Proposed behavior**

Operators receive agent creation/configuration, skills, environments,
invitations, task assignment, pipelines, connections, tool
management/use, and audit grants. The preset excludes `joins:approve`
and `users:manage_permissions`. Operators can invite Operators and
Viewers. Inviting a role with either excluded power requires that power,
so invitations cannot bypass the restriction.

**Reason and benefit**

Ordinary company members can edit company work and connect accounts
through the existing routes.

**Breaking changes**

The Operator preset grants more permissions. The existing startup and
Cloud sign-in seeding paths can insert these missing grants for existing
Operators. They retain custom grant scopes. Explicit invitation grants
still take precedence. Inviting Admins now requires join approval;
inviting Owners also requires member-permission management. This PR adds
no migration or new backfill path.

Related: #5945 describes missing role grants in another membership entry
point. This PR changes the preset and does not change that endpoint.

## What Changed

- Expanded the Operator preset to 14 company editing, invitation, tool,
and audit grants.
- Kept join approval and member-permission management out of the preset.
- Required those powers when an invitation's selected human role
includes them, preventing Operators from delegating the excluded powers
through Owner/Admin invitations.
- Updated the invitation role copy and the product specifications.
- Allowed active Operators (including legacy Member roles) through the
invite shortcut and advanced tool/profile UI gates. Kept inactive
memberships, Viewers, and other companies excluded; API grants remain
authoritative.
- Added tests for the default Operator grants, both excluded actions,
agent editing, company boundaries, and invitation role authorization.
- Simplified adapter-route test imports so authorization errors and the
error handler use one module graph; retained the upstream
mock-initialization fix.
- Kept Owner/Admin/Viewer presets and explicit invitation grants
unchanged. Added no EE code or database migration.

## Verification

- Permission and invitation tests: 38 passed across access service,
invitation defaults, and invitation creation routes.
- UI access tests: 61 passed across invitation shortcuts, Operator
tool/profile access, and invitation UI.
- Adapter route tests: 15 passed after resolving the upstream test setup
conflict.
- `pnpm -r typecheck`, `pnpm build`, and `pnpm check:token-gates`:
passed on the final branch.
- The initial local `pnpm test:run` general-server batch reported three
tool-access failures and eight upload-helper timeouts. Both complete
affected suites passed in isolation on the final branch: 403 tests. The
initial full local run was not green.
- Both complete tool-access and adapter route suites also passed on an
untouched snapshot of base `88ff98b83`: 387 tests. The earlier tool
failures did not reproduce there.
- [All CI gates
passed](https://github.com/paperclipai/paperclip/actions/runs/37527422346)
for `068be153b9c2a064f2aaccc0627fdf458e73747e`, including the previously
failing serialized adapter lane, general tests, E2E, typecheck, build,
Runner checks, and canary dry run.
- Greptile scored that exact commit 5/5. Superagent passed. Both
invitation review threads are resolved.

## Risks

- Operators gain broad company editing and invitation access by design.
- Existing default seeding can add the new missing grants during startup
or Cloud sign-in. It does not replace existing scopes.
- Company boundaries and the two excluded permission checks still apply.
- An Admin without member-permission management can no longer invite an
Owner. Operators retain invitation access for Operator/Viewer roles and
agent-only invites.
- This PR changes company permissions. Cloud workspace invitation rules
remain separate.

## Model Used

OpenAI Codex, GPT-6. The exact deployment model ID and context window
were not exposed in this session. Used 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 a merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-06 15:55:38 -05:00
DottaandPaperclip 2ca0d26a99 fix(connections): recover missing personal AI credentials in chat (#15376)
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-06 15:36:01 -05:00
DottaandPaperclip e38d6d16b6 feat(connections): add advanced provider setup and live browser qualification (#15341)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Users connect accounts and choose an agent harness and model.
> - The runtime change in #14970 supports custom providers on those
connections.
> - Normal setup must stay simple while advanced users can choose a
compatible gateway.
> - Shared connector rows and access controls keep these choices
consistent.
> - This pull request refines the agent setup UI and adds review stories
and repeatable browser qualification.
> - The qualification checks real tools and downloaded outputs, not only
a successful run status.

## Linked Issues or Issue Description

Refs #14970, #37, #13083, #14104, #14565, #12692.

The core implementation in #14970 is merged. This branch incorporates
its squash commit and targets `master`. Both PRs contain our
implementation. #14016 is a reference only and is not a dependency. This
PR has 96 changed files.

## What Changed

- Complete model-provider connector presentation beside other
connectors. Each row uses the existing Connect action and connection
list. Tags are stored without category UI. The base PR includes the
provider forms and routes.
- Show persistent Subscription, API Key, and Advanced choices. Label
Advanced as Custom Gateway. Reuse provider logos, connection lists, and
permissions controls. Default access to the organization and all agents
when permitted; keep narrowing controls under Advanced.
- Keep Configure reachable before subscription sign-in, so users can
select a supported environment when the default cannot sign in. Testing
and saving still require a connection. Show the execution environment in
Configure. Preserve the confirmed Connect choice. Editing a method,
credential, saved account, or advanced choice requires that current
choice to connect before testing or saving. Use matching model and
thinking-effort dropdowns and retain connection icons in selected
values.
- Preserve the new harness model default when switching an existing
OpenCode agent to Codex or Claude, and resolve user-selected model names
with the effective harness.
- Load popular OpenRouter models through the shared connection-model
discovery path. Keep explicit model lists and manual model entry
available.
- Group onboarding, connection setup, agent runtime, management,
recovery, and production-component stories under AI Connections /
Provider routing.
- Add an explicit-only provider-connections browser suite for managed
local or existing local/staging targets. Use private browser profiles
and credential handoffs. Support human-assisted subscription sign-in
without sharing passwords or tokens in reports.
- Verify persisted connection identity, runtime probes, tool execution,
exact artifact bytes, completion, and context-dependent follow-up.
Retain source/model provenance, cost bounds, closed error diagnostics,
original failures, and cleanup evidence.
- Add Gemini startup-model and skill-root fixes, Grok private-history
detection, ACP filesystem regression fixtures, selected-workspace
handling for local Hermes, and artifact-helper workspace fallback.
- Keep managed Grok runtime homes disposable. Remove host-side
transcript retention/restoration because private file modes do not
isolate same-user agent processes. Ignore earlier development archives
and use a fresh task handoff when history is unavailable. Verify the
absence of restored transcripts with a separate same-user process.
- Capture stopped-run diagnostics before deleting an attached-company
fixture agent. Track creation and owned sign-in receipts; revoke only
this attempt's accounts and never adopt a concurrent campaign's newly
created account. Preserve failure signals and final status through
cleanup.
- Require the requested environment in the saved agent and every run,
including follow-ups. Reject a forced incompatible target. Keep one
cancellation state through startup, every cell, reporting, and teardown
for SIGINT, SIGTERM, and SIGHUP. Stop further paid cells after
interruption. Document qualification limits.

## Verification

- Current head `b3bb3e94d577d43d9965a6b9daba039f599b2e49` includes
master `d9f600043`. The security fix in `a758fde31` passes full
workspace typecheck, production build, and 119 connection/Grok
regressions. The unchanged UI passes all 126
configuration/model-discovery tests and token gates. The final
published-guide correction passes Grok adapter typecheck. Earlier head
`eebd8225c` passed the complete deterministic runner suite (1,404 Vitest
tests and 128 Node tests) and all CI jobs. Current-head CI run
`37520147514` passed all 47 jobs, including the full sharded Vitest and
browser matrix, production build, and canary dry run. All 55 checks
completed: 53 successes and two expected skips. The current-head
security scan passed, Greptile is 5/5, and no review threads remain
open.
- A separate same-user process reproduced reading a restored Grok
transcript before the security fix. The regression now finds no
transcript. Existing fresh-session fallback and ordinary session
metadata behavior pass.
- The final account-choice and cleanup fixes pass 85 setup tests and 26
qualification-harness tests. Regressions verify that editing a
connection invalidates confirmation, Configure remains reachable before
sign-in, diagnostics are captured before fixture deletion, and
concurrent campaigns cannot adopt or revoke each other's accounts. UI
and E2E typechecks pass.
- The Storybook build and actual Chromium production-component stories
passed during this change. Review the neighboring AI Connections /
Provider routing stories, regular connector rows, three connection
modes, model discovery, and the single execution-environment control in
Configure.
- Cancellation smoke verified authenticated cleanup before browser close
for SIGINT, SIGTERM, and SIGHUP. Regressions cover interruption during
startup and reporting, missing-file ACP resource errors, and preserved
permission denials. Both ACP runtime versions and 54 ACPX/Grok
regressions passed. The deterministic connection-intent browser suite
passed two tests.
- Historical local qualification retained 43 passing API/gateway cells
out of 46, with downloaded outputs and follow-up receipts. These
attempts span earlier builds; they do not qualify this exact commit or
staging. Subscription combinations, Gemini overloads, and the unresolved
follow-up failure remain recorded rather than counted as passing.
- Use `pnpm test:e2e:runner -- --list --suite provider-connections` to
inspect the matrix. Follow `tests/runner-e2e/PROVIDER-CONNECTIONS.md`
for credentials, target URL, sign-in assistance, budget, evidence, and
cleanup. Paid live tests remain opt-in.

## Risks

- The core implementation in #14970 is merged. This PR adds no database
migration of its own.
- Subscription login needs an interactive provider session. Dedicated
accounts and staging qualification remain follow-up work; this PR does
not certify every login combination for production.
- Managed Grok transcript resume is deferred until provider history has
an OS isolation or authorized broker solution. Follow-ups start fresh
with Paperclip task context; earlier live Grok results do not qualify
this behavior.
- Gemini CLI 0.58.0 has an upstream ACP new-file error conversion
defect. Live overloads and one unresolved follow-up timeout remain
recorded. The stock CLI is unchanged, and those cases are not marked as
passing.
- Real-provider tests spend credits and use private credential/evidence
directories. The launcher requires explicit selection and checks target
ownership. It must not attach to a developer's database by accident.
- OpenClaw Gateway, Hermes Gateway, Claude Managed, AWS AgentCore,
Process, HTTP, and legacy ACPX local remain outside custom provider
setup.

## Model Used

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

## Checklist


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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-06 15:21:22 -05:00
DottaandPaperclip a7a2ed63a0 fix(ui): restore wheel and touch scrolling in task selectors (#15374)
Restore wheel and touch scrolling in nested task selectors and keep mobile picker controls reachable above the keyboard.

Stabilize the affected server route test harnesses for Vitest 5.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-06 15:18:07 -05:00
DottaandPaperclip a590ab769d Give managed agents persistent cryptographic identities (#15352)
Give agents persistent Ed25519 identities encrypted with the existing instance master key. Create keys transactionally for new agents and lazily before supported managed runs, expose public identities in the API and agent UI, and protect private material during runtime delivery and output persistence.

Preserve identities in recovery backups while giving imported and development-cloned agents fresh keys.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-06 13:57:03 -05:00
DottaandPaperclip 9f7057e122 feat(connections): configure custom model providers across agent harnesses (#14970)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents use a harness, a model, and a credential to run tasks.
> - Connections already store credentials and control who can use them.
> - Custom providers also need an endpoint and a supported API format.
> - A per-agent endpoint would duplicate credentials and access rules.
> - This pull request stores routing on the connection and projects it
into the harness.
> - Isolated credentials and protocol checks keep the selected
connection authoritative.

## Linked Issues or Issue Description

Refs #37, #13083, #14104, #14565, #12692.

#14016 is a reference only. This PR has its own schema, vault
persistence, routing validation, runtime projection, and tests. None of
the five commits in #14016 is an ancestor of this branch. We do not
depend on or plan to merge it. #14967 addresses task-pinned account
pools. #14422 addresses another provider integration.

This is the first of two linked PRs. Merge this connection change before
#15341, which refines agent setup and adds the qualification harness.
The split keeps each review below 100 changed files. Provider catalog
entries have usable setup forms in this PR. Local browser subscription
sign-in is included.

## What Changed

- Store non-secret routing metadata on AI connections. Vault provider
API keys, including Bedrock bearer API keys. Reject general AWS access
keys.
- Enforce company, owner, human audience, agent access, connection
status, and protocol checks before resolving credentials. Keep reconnect
destinations immutable and retain connection identity during key
rotation.
- Project OpenRouter and compatible custom endpoints into Codex, Claude,
OpenCode, and local Hermes. Carry these settings through both legacy and
native runner transports. Clear conflicting host credentials and redact
keys from diagnostics.
- Preserve older OpenRouter accounts and native personal defaults. Add
Google API-key accounts and migration `0306` for the two
provider-default constraints.
- Run local Claude and Codex subscription sign-in behind the existing
browser sign-in card. Use private attempt homes and owner-bound
completion instead of a copied terminal command.
- Seed isolated Gemini authentication and preserve OpenCode workspace
permissions. Keep the selected connection authoritative. The independent
Gemini and Grok workflow fixes are in #15341.
- Keep native OpenCode custom gateway keys in a runner-owned
selected-model proxy; the harness config contains only a session-scoped
capability. Honor runtime outgoing proxy and certificate settings.
Preserve streamed responses and revoke the proxy on close or startup
failure.
- Allow ordinary members to connect native personal accounts before an
agent exists.
- Repair routed accounts from task cards using the saved provider
destination, protocol, model aliases, and connection identity.
- Add provider catalog definitions, model discovery, pinned logos, and
complete native and routed setup forms. Allow a personal routed
connection before a new agent exists. Keep endpoint authentication keys
out of Hermes terminal children.
- Recover cancelled or restarted browser sign-in with a clear restart
action. Support no-auth endpoints without a vault credential. Add
isolation and recovery regressions and runtime documentation.

## Verification

- Updated with `origin/master` at `22a3ea341`. Migration `0306` follows
the new master migration and passes migration and snapshot checks.
- The integrated connection regressions passed 152 tests and 50 native
OpenCode driver tests, including key-free child-shell configuration
reads, authenticated/no-auth forwarding, streaming, model/path
restrictions, cancellation, outgoing proxy routing, and NO_PROXY bypass.
Provider setup has 14 passing tests. The pinned real OpenCode 1.18.34
executable also completed a turn through the proxy against a local
synthetic provider; the reusable key was absent from its config. A
second real-executable smoke passed with an HTTPS CONNECT proxy and
runtime-specific synthetic certificate trust. Certificate-file and
certificate-directory regressions pass.
- Task-card repair passed 48 tests, including OpenRouter, Bedrock, and
custom gateway reconnect cases. UI typecheck and token gates passed.
- The prior core regression set passed 133 tests across new-agent setup,
provider forms, browser sign-in, routing projection, and connection
authorization. Token gates and UI typecheck passed.
- Full workspace typecheck and production build passed again after the
latest integration and credential-proxy fix. The merged deterministic
runner E2E suite passed 1,400 Vitest tests and 128 Node tests.
- Full workspace typecheck passed on the prior linked combined
implementation. Production build, Storybook build, 1,316 browser-harness
Vitest tests, and 128 Node tests passed. Head `9d964c8d9` includes the
latest master integration and regenerated migration. This exact head
passed 54 remote checks with four expected skips and Greptile 5/5; no
review threads remain open. An unchanged server fixture had a random
six-character issue-prefix collision on its first attempt. All 245 tests
passed locally and the single CI retry passed.
- A provider-free terminal check used the cited supported Hermes source
and dummy keys. Gateway and OpenRouter terminal children could not read
the selected key.
- The broad local Vitest attempt passed 15,442 tests but was not green.
It had an embedded-Postgres startup failure, an HTTP logger timeout, an
origin socket error, and a browser cancellation wait timeout. The
cancellation wait was corrected. The relevant connection tests and the
full origin test file passed separately. Latest-head CI must pass before
merge.
- Prior credential-backed acceptance exercised task creation, tool use,
artifact delivery, completion, and context-dependent follow-up. Claude
legacy and native runners passed Bedrock with `us-east-1` and
`us.anthropic.claude-sonnet-4-6`.
- Historical local qualification retained 43 passing API/gateway cells
out of 46. Those attempts span earlier builds. They do not qualify this
exact commit or staging. All subscription combinations and staging
remain unqualified.
- Verify native subscription and API-key setup. Connect a regular
provider catalog row. Verify an incompatible harness and a changed
reconnect URL are rejected. Use #15341 for the complete browser
campaign.

## Risks

- Migration `0306` changes two check constraints. It preserves rows and
is safe to reapply. It takes normal constraint-change locks.
- Credential projection touches several harnesses. CLI upgrades can
change provider configuration and session behavior.
- The native OpenCode proxy adds a loopback hop, pins requests to the
selected model, limits request bodies to 16 MiB, rejects redirects, and
expires at session close. It prevents reusable keys in the child
configuration; it is not an OS isolation boundary against a process
debugger running as the same user.
- Custom endpoints must be reachable from the agent environment. Saving
a connection does not prove connectivity. Bedrock keys require rotation
before expiry.
- Gemini CLI 0.58.0 has an upstream ACP new-file error conversion
defect. Provider overloads and an unresolved follow-up timeout also
affect live Gemini qualification. We have not patched the installed CLI
or marked those cases as passing.
- OpenClaw Gateway, Hermes Gateway, Claude Managed, AWS AgentCore,
Process, HTTP, and legacy ACPX local are excluded. Vertex, ambient AWS
identity, arbitrary auth headers, and custom routing for other harnesses
are excluded.
- These PRs do not establish production or staging qualification for
every provider and login method.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-06 13:29:03 -05:00
DottaandPaperclip 22a3ea3414 Invite assistants from Connections with scoped browser and device consent (#14933)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Public MCP lets people use their organization from an external
assistant.
> - Operators need a visible control for this experimental access.
> - Hosted users should select an organization once and then approve its
permissions.
> - This pull request adds the setting, invitation-first setup, and
browser or device consent.
> - Connections provides a copyable invitation with public instructions
that grant no access.
> - Users reach browser consent from their assistant and return to
inspect or revoke access.

## Linked Issues or Issue Description

Builds on merged foundation #14846. This PR now targets master. Related
settings convention: #13905.

**Current behavior**

The preview uses an environment variable to enable MCP. Hosted consent
repeats organization selection. Assistant access has no entry in
Connections, so users must already know the endpoint and how to reach
consent.

**Proposed behavior**

An administrator enables Settings → Experimental → Assistant connections
(MCP). A hosted connection shows the selected organization and its icon,
then asks for permissions. Requested write access starts checked when
the user’s role permits it; the user can opt out before connecting.
Direct instance connections show an organization picker with the first
available organization selected. The selection stays fixed across
refetches and still requires an explicit Connect action. Connections
includes Assistant Connection (MCP). Its setup page explains the
canonical endpoint, client configuration, browser authentication, and
connected access. It connects as the current person and does not select
or impersonate an agent.

**Reason and benefit**

Operators manage access with the other experiments. Users select one
organization, and both the UI and server enforce that choice.

**Breaking changes**

The old enable variable has no effect. Preview operators must enable the
setting once. Apply the additive consent-request migration before
deploying the tenant, then deploy the compatible Cloud broker. Existing
direct requests and grants keep their behavior.

## What Changed

- Simplify OAuth and device consent: show the Paperclip logo beside
“Connect {client} to Paperclip”, fall back to “your assistant”, and show
the identifying origin plus its favicon below, with the callback URL
also visible when different. Remove the hosted-organization creation
action. Default to the first available organization without silently
changing it on refetch; preserve company restrictions and write
opt-outs. Keep the button row contained on narrow screens.
- Make Copy invitation the primary action, using the shared animated
AgentSetupPrompt and a collapsed manual setup section with icon-labeled
line tabs. Remove redundant link actions, copy-status text, the extra
first-prompt well and revocation explanation from the setup page. Serve
shared version-aware HTML and Markdown instructions without private
organization data.
- Support guarded Client ID Metadata Documents alongside dynamic
registration, and include authorization response issuer identification.
- Add RFC 8628 device authorization with separately hashed codes,
expiry, shared request quotas, persistent polling backoff and atomic
redemption. Reuse human consent, role checks, scoped grants, audit and
revocation.
- Add CLI device login and a local stdio bridge. Store credentials
separately with private permissions and serialize rotating refreshes.
- Add device consent stories and five cold-start paid Product E2E cases
with independent grant, configuration and durable-work assertions.

- Add `enablePublicMcp` to the settings validator, normalizer, feature
catalog, and toggle UI. Check it live for OAuth, tools, subscriptions,
and event delivery. Keep connection management and revocation available
while disabled.
- Default the MCP origin to the existing auth public URL, with strict
validation and an explicit override.
- Persist the optional OAuth `company_id` restriction. Describe only
that company and reject approval for any other company, even if the
person belongs to both. Keep active-membership and role checks.
- Show the Paperclip icon and a large organization icon during consent.
Return the saved company logo through the company-scoped request
response and reuse the standard fallback icon. Use the requested concise
permission labels: “Read all of your Paperclip data” and “Allow write
access and creating tasks as me”. Use concise permission copy, retain a
compact client and callback-origin disclosure, and remove the footer
link.
- Default requested write access on for eligible roles. Preserve opt-out
across organization changes and refetch, reset defaults for a new
request, and submit read-only access when the request or role does not
allow writes. Align the shared checkbox with its label.
- Use organization wording in consent, management, settings, and
walkthroughs. Keep the organization fixed for hosted requests and retain
direct-instance choice.
- Add an Assistant Connection (MCP) card to the Connectors catalog, a
setup page in the app shell, and a return link from Experimental
settings. Include Codex, Claude Code, OpenCode, and generic remote MCP
instructions.
- Read the live gate and canonical server URL through authenticated
setup metadata. Show only the current person’s grants for the selected
organization, refresh after consent, and support revocation. Surface
catalog status failures with an explicit retry action; do not present
them as an empty connection list. Opening setup grants no authority.
- Start the eight guided chapters in Connections. Keep presenter notes
and chapter controls around real product pages in the app shell. Explain
the terminal, consent, delegation, retrieval, and revocation handoffs.
Mark conversation examples as illustrative. Cover first use, client
setup, connected, loading, and error states. Keep the existing consent
and management stories.
- Keep the paid-eval setup and browser helper aligned with the setting
and consent button.

## Verification

- Warm-standby integration fix `ec64ea05e`: public MCP ingress now
follows the Cloud claim guard; MCP and discovery paths return 503
instead of SPA HTML while unclaimed. Event polling checks the in-memory
claim before reading the persisted experimental setting. All 97 focused
OAuth/Cloud tests and server typecheck pass, including new request and
timer regressions for idle-before-claim and resume-after-claim behavior.
Fresh review is 5/5 with no unresolved threads, and all security scans
pass on this final head. All browser shards, typecheck, build, canary
installation and other test groups passed on the first attempt. The
unchanged Cursor sandbox default-command test timed out at 10 seconds;
the exact test passed locally without edits in 587 ms. The single
failed-job retry passed, with the original failure retained in workflow
37500711895. All 54 final-head checks pass on
`ec64ea05e9a03e2179d4e2f84c2de03761f7ce26` (two optional Storybook jobs
are intentionally skipped).

- Final master integration `8457828fc`: merged foundation #14846 and
current master, preserving the invitation changes and all 33 files from
the two newer upstream changes. No migration renumbering was required.
All 95 focused OAuth/Cloud integration tests, full recursive typecheck
and token gates pass. All CI gates passed on that integration head;
review identified the warm-standby issue fixed above.

- Security-review fix `8c1d0b696`: commit shared global/per-source
admission before outbound CIMD work, preserve failed-attempt receipts,
and validate resource/scope before fetching. Added migration
`0305_chubby_vin_gonzales.sql` and six concurrent/adversarial regression
cases. All 69 OAuth/metadata tests, 26 migration checks, full recursive
typecheck and production build pass. The security scanner passed that
commit. Follow-up `87f9658e7` limits only actual cache-miss fetches; 18
authorization requests sharing one proxy across two service instances
use just two fetches. All 70 OAuth/metadata tests and server typecheck
pass after that refinement. Final follow-up `8ebeae84c` reports
admission-storage failures as retryable HTTP 503 instead of invalid
client metadata. Its regression proves no outbound request before
admission and successful retry after storage recovers. All 71
OAuth/metadata tests and server typecheck pass. Final-head security
scanning passes; Greptile is 5/5 with no unresolved findings. CI passed
all browser shards, typecheck, build, token gates and canary
installation. One unchanged adapter-utils bridge test raced a
response-file write (expected a JSON error, received the safe
file-changed error). The exact test passed locally without edits. The
single failed-job retry passed; the original failure is retained in
workflow 37490609192. All 54 checks now pass on final head
`8ebeae84ca77c0cf7ac12c2006f0f8743fe50e0b`, with security scan and fresh
Greptile 5/5 and no unresolved threads. Foundation #14846 subsequently
merged as `e34abee670069cca84afb2efb86041bce7dccbec`; the final
integration above now targets master.

- Integration with current master: preserved the new Connections source
filters and pagination, kept all eval suites, and regenerated the
consent/device snapshots as migrations 0303/0304. All four MCP migration
SQL hashes are unchanged from the staging versions. Full recursive
typecheck and production build, 132 focused UI tests (including catalog
filtering), 89 server authorization/settings tests, 26 migration tests,
120 eval calibration tests and token gates pass. Review follow-up
`4820ce74c` also keeps active assistant grants in Installed, with
pending/error recovery and revocation/company-isolation coverage. All 76
setup/catalog tests, UI typecheck and token gates pass after that fix.
The unchanged signoff browser test timed out waiting for a heartbeat in
CI at `4820ce74c`; the exact test passed locally without code changes,
and the preceding CI head passed that shard. That same unchanged test
failed at the reviewer stage in the next CI run. All five signoff tests
passed three times locally (15/15), without test changes. All eight
browser shards pass at final head `8ebeae84c`; no browser-test edits or
failed-browser-job retries were needed.

- Setup-page refinement at `9ab009178`: all 17 focused setup/consent
tests pass, along with UI typecheck, production build, Storybook build
and token gates. Browser exercised the shared prompt preview and client
tab switching, and the updated InvitationCopied Storybook interaction
checks its clipboard fixture. All final-head CI checks pass at
`9ab009178`, with no unresolved review findings. Deployed successfully
to Butter in
https://github.com/paperclipai/paperclip-cloud/actions/runs/37475189524.
Verified the actual page, tab switching and line styling, removed
actions/copy, and successful native copy/paste of the complete Butter
invitation into a local-only test field. The existing Claude grant was
left intact.
- Consent follow-up at `dc8e9fd11`: all 10 consent tests and token gates
pass. UI typecheck and production build passed again at `4e4d5e4d9`;
Storybook build and eval-helper typecheck passed for `28101cf91`.
Follow-ups let the primary button wrap on narrow screens, preserve a
distinct callback URL, and use only bundled icons to avoid pre-consent
requests to client-selected sites. Browser-verified the real consent
component in desktop and 320px mobile stories, including default
selection, write access and preserved opt-out. Updated E2E
heading/default-selection helpers. All CI checks passed at `dc8e9fd11`,
with review 5/5 and no unresolved threads. The Butter preview
publication needed a retry because npm initially accepted the DB package
before making it visible; the retry succeeded and `dc8e9fd11` deployed.
Verified a fresh, unapproved native Codex CIMD request on Butter:
default organization/write selection, known-client heading and icon,
distinct callback origin, and removed creation action. No grant was
approved for this UI check. Prior paid runs below retain their exact
source provenance; this UI-only follow-up did not rerun paid
qualification.
- Source-pinned paid matrix at
`2992ef2710f47230e7f484c709c6ba02524f884c`: **15/15 passed**, five cases
each on GPT-5.4 Mini, Claude Haiku and Sonnet. Campaign
`local-2026-10-06T02-41-14-462Z`. Covers cold start, existing config,
unavailable host, denied consent and reconnect/later retrieval, with
independent configuration/grant/task/run/document assertions. Original
failures, transcripts, source fingerprints and billing remain retained.
- Final instruction follow-up `cda8178af`: **3/3 cold starts passed** on
Mini, Haiku and Sonnet. Campaign `local-2026-10-06T02-58-30-041Z`.
Latest `0637b9f1c` shares that same guidance across HTML, Markdown and
manual UI after review; generated Markdown is verified byte-identical to
the paid-evaluated version. Shared build, server/UI typechecks, token
gates and 63 auth/metadata tests passed again. Every CI gate passed at
prior HEAD `0637b9f1c`, with review 5/5 and no unresolved threads.
- Other focused checks: 11 CLI credential/refresh-lock tests, 120 eval
calibration tests, server/UI/eval typechecks, token gates and Storybook
build passed. Full recursive typecheck and production build passed
during implementation; CI also passed them at `2992ef271`.
- Local full-suite limitations: a large-file Git streaming test times
out on this Mac, and broader CLI/route runs hit DB hook timeouts. Fresh
MCP reruns passed, and the corresponding CI groups passed. No claim that
the local full suite is green.
- Actual clients: Codex 0.153.4 and Claude Code 2.1.245 reach CIMD
consent; device CLI reaches verification/consent. New grants await human
approval. Existing local OpenCode retrieved a saved result in a fresh
conversation through its previously approved grant.
- Fresh OpenCode 1.18.17 on Butter: started with no MCP config, received
the exact copied invitation, read public setup, configured its server
and started PKCE consent. Its shell command timed out; background retry
reached the client's own callback deadline while approval remained
pending. Latest instructions cover that handoff. **No completed Butter
read/delegation/result retrieval is claimed.**
- Cloud companion
https://github.com/paperclipai/paperclip-cloud/pull/672 passes
checks/review and deployed. Anonymous setup and device-protocol routing
verified. Core `2992ef271` deployed successfully and the actual Claude
web flow now reaches consent. Its extra JWT-bearer metadata is filtered
to implemented grants; unsupported token grants remain rejected. Final
`0637b9f1c` deployed successfully to Butter in
https://github.com/paperclipai/paperclip-cloud/actions/runs/37409195300;
live HTML and Markdown both contain the final guidance. The superseded
instruction-only build was canceled before deployment. This is a
core-only staging preview; private Cloud plugins are omitted. ChatGPT
web is signed out, so browser connector use is unverified.
- Screenshot gallery begins at Butter's dashboard and distinguishes real
setup/pending consent from local reuse and fixtures. It records the
timeout finding. New persistent access needs human confirmation before
the remaining actual-client acceptance work.
- Manual path: Connectors → Assistant Connection (MCP) → Copy invitation
→ paste into assistant → configure and start authorization → sign in and
approve → verify `paperclip_connection` → delegate → retrieve the saved
report later.
- Plan and instructions: `doc/plans/2026-10-05-assistant-invitations.md`
and `doc/public-mcp.md`.

## Risks

- Apply additive, replay-safe migration `0304_curvy_shadow_king.sql`
before using device authorization. The public setup link carries no
credential. Device codes and tokens stay private; neither sharing
instructions nor installing a plugin authorizes access.
- Apply additive migration `0305_chubby_vin_gonzales.sql` before
deploying the shared metadata admission gate. It retains at most 60
short-lived, hashed-source receipts per instance and rejects excess
attempts with 429.
- CIMD metadata fetching is a new external-input boundary. It requires
HTTPS, exact client ID and redirect validation, bounded responses and
guarded DNS/network access. Client names remain self-reported.
- Device support is per-instance. The central Cloud broker retains its
existing grant support. Host installation and tool reload capabilities
vary by client; instructions describe manual settings and restart
requirements.

- Consent names the registered client in its heading and displays its
identifying origin below. Known-origin icons are bundled; all other
origins show a neutral site icon without contacting client-selected
sites. Client names are self-reported; the callback origin is the
recipient check. The Cloud chooser also displays the original client and
receiving origin before tenant handoff.

- A user who accepts the preselected write permission can create tasks
and comments. Task creation and comments can start or wake agents and
use execution budget; the consent label uses the concise wording
explicitly requested by the maintainer. Scope requests, role checks, and
the final Connect action still apply.
- Migration `0303_supreme_garia.sql` adds one nullable UUID column with
`IF NOT EXISTS`. Requests without a company restriction keep the
direct-instance picker. The binding stays recorded if its company is
deleted; consent then fails closed.
- Deploy tenant support before the Cloud broker sends `company_id`.
Unknown or inaccessible organizations must never fall back to a
different company.
- The setting defaults off. Disabling access does not cancel work
already delegated. Existing tokens and unexpired subscriptions can
resume when enabled again; revocation remains separate.
- The catalog entry is visible for discovery while the feature is off.
Setup instructions, OAuth, and tool execution remain gated. No access is
granted by viewing the entry.
- Assistant sign-in starts in the external client so it owns PKCE and
callback state. Client command syntax can change and links to official
setup documentation are included.
- An authenticated instance and valid public URL are required. Hosting,
paid execution, and store publication remain separate rollout steps.

## Model Used

OpenAI GPT-6 in Codex, with tool use and code execution. The exact
serving model version 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 (focused checks pass;
unrelated local full-suite timeouts are explicitly recorded above)
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-06 12:35:16 -05:00
DottaandPaperclip f2715e02bb fix(native): surface model capacity errors and retry automatically (#15347)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native runs preserve provider events and results, then decide task
state.
> - Codex can fail a turn because the selected model is temporarily at
capacity.
> - Paperclip displayed a generic native-session failure and left the
task in recovery.
> - A known capacity failure needs a clear message and a durable delayed
retry.
> - This pull request uses committed terminal evidence, the
status-effect ledger, and existing dispatch gates.
> - The task can continue automatically without an unbounded retry loop
or a model switch.

## Linked Issues or Issue Description

Related: #13993 adds launcher capacity deferrals before provider
startup. This change handles a committed native Codex `serverOverloaded`
terminal after provider work has started.

**What happened?**
A native Codex turn ended with `codexErrorInfo: serverOverloaded` and
“Selected model is at capacity. Please try a different model.” Paperclip
saved the result, showed a generic failure, and required recovery
instead of waiting and retrying.

**Expected behavior**
Show the capacity error directly. Schedule bounded retries after a short
delay. Preserve saved work and honor current execution gates.

**Steps to reproduce**
1. Run a native Codex task.
2. Commit a `turn.failed` event with `serverOverloaded`, then accept a
failed result for the same turn.
3. Inspect the task error and its recovery state. The regression test
reproduces this without a paid provider call.

**Paperclip version or commit**
Reproduced against master `16b7db35ffa0f9a95913c8cbdeea3d595435691f`.

## What Changed

- Classify capacity failures from committed runner events and the pinned
execution identity. Preserve accepted results and display the specific
capacity error.
- Atomically persist one scheduled successor with the status decision.
Retry after one minute, then two minutes. Share the existing failure
budget and stop after two automatic retries.
- Reuse dispatch gates for ownership, task holds, dependencies, budget,
and locks. Wait for predecessor execution, finalization, and cleanup
before claiming a retry.
- Preserve pending reviewer authority and suppress retries after
reassignment or a successor claim.
- Consume the failed run's resume receipt and delivered wake input.
Rebuild ordinary continuation from the failed run so explicitly resumed
tasks can retry without borrowing one-run authorization.
- Label scheduled retries “Model at capacity.” Add a Storybook example
and avoid duplicate punctuation in the existing retry card.
- Add regression coverage and document the runtime contract.

## Verification

- Targeted recovery and UI suites: 125 tests passed. Additional final
cleanup and lock regressions passed.
- Latest-head continuation and authorization regressions: 57 tests
passed, including all four capacity integration tests against an
isolated PostgreSQL database.
- Rechecked all four capacity integration tests with the full runner's
isolated `PAPERCLIP_HOME`, config, temporary directory, and serial fork
settings: passed.
- `pnpm -r typecheck`: passed. Final server typecheck passed.
- `pnpm build`: passed.
- `pnpm check:token-gates`: passed.
- Browser: checked the real Storybook card. It shows the capacity
message, automatic retry time, and existing Retry now action.
- `pnpm test:run`: attempted and restarted after an interruption. The
resumed run started before the final review correction and was stopped
after recorded workspace/native test failures and the five-minute Git
streaming timeout already documented on master. Exit 130; no complete
local full-suite pass is claimed. Current-head isolated capacity tests
and the complete CI suite pass.
- A combined local recovery-suite attempt also hit PostgreSQL
initialization failures at this macOS host's global shared-memory limit
(32 slots). The focused recovery suites passed separately; final-head
capacity tests also pass with the full runner's isolated environment
settings.
- Latest-head GitHub checks: all 56 checks green, including general and
serialized test shards, browser E2E, typecheck, build, Runner
verification, and canary dry run. No merge conflicts.
- Greptile: 5/5 on `813a470b8c18c05aeb7e31e63e573c3a3a2f5cac`, with zero
unresolved findings after fixing the resumed-task continuation issue.

## Risks

- Capacity retries can repeat a task turn after partial work. They start
a fresh provider session with task history and wait for predecessor
cleanup. They do not resume the failed turn.
- Retries retain the configured model unless an operator changes
configuration. Persistent overload consumes the existing failure budget
and then needs an explicit retry or model change.
- Only run-bound native Codex `serverOverloaded` failures qualify.
Usage-limit exhaustion, model/account incompatibility, unbound text, and
unknown provider failures retain their current recovery behavior.
- No schema migration is required.

## Model Used

- OpenAI GPT-6 through Codex. The exact model ID and context-window size
are not exposed to this session. Used reasoning, repository tools, code
execution, and browser verification. No subagents.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-06 10:59:18 -05:00
DottaandPaperclip 9b3fe260ba fix(tasks): surface Codex ChatGPT model rejection (#15299)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for work.
> - Native Runner runs report provider errors and can also save a structured failure result.
> - Codex rejects a model that the user's ChatGPT account cannot use.
> - Master now diagnoses this rejection, but the task's compact run data omits its message. The thread can still call it a generic run failure.
> - Users need the account restriction and a clear step to repair the model selection.
> - This pull request shows the existing diagnosis as “Model unavailable” on the task.

## Linked Issues or Issue Description

**What happened?**

Codex returns HTTP 400 with `invalid_request_error` and the message `The 'gpt-6.1-sol' model is not supported when using Codex with a ChatGPT account.` Master now stores an actionable diagnosis for this rejection. The task thread still labels it “Run failed” and does not receive its error text in compact run data.

**Expected behavior**

Show the account restriction on the task and in the run error. Tell the user to choose a supported model or clear the task's model override before retrying.

**Steps to reproduce**

1. Use a Native Runner Codex agent signed in with a ChatGPT account.
2. Select a model that produces the rejection above and start a task.
3. Let the runner save its generic failed result. Inspect the task's failure marker and recovery notice.

**Additional context**

Refs: #15304. That merged PR diagnoses the provider failure and preserves worker and review recovery rules. This PR adds its task-facing message and guidance without changing that diagnosis or those rules.

Refs: #13134. That PR improves model discovery for ChatGPT accounts. This PR exposes the rejection when a configured model still fails at execution time.

## What Changed

- Return a bounded model rejection message in compact issue-run data.
- Show “Model unavailable” and model-change guidance in the task thread and recovery notice.
- Add database and UI regression tests, including both the original rejection text and master's fixed diagnosis. Document the new failure message.

## Verification

- Focused merged-branch validation: 279 tests passed across activity service, native provider failure observation and PostgreSQL integration, TaskChatThread, and ExecutionBlockerNotice.
- `pnpm -r typecheck`, `pnpm build`, and `pnpm check:token-gates` passed on the merged source tree.
- Greptile reviewed conflict-resolution commit `1db39c4e636a92e2e76ba224b71c6f1e2f556c81` at 5/5 with no findings or inline comments.
- All 55 check runs completed without failure on that commit. The two optional Storybook jobs were skipped. The legacy Snyk status passed. The branch has no merge conflicts.
- UI regression assertion: the task's failure marker says “Model unavailable” and retains the account restriction. It no longer says that this failure happened after a final response.

## Risks

- Provider recognition and recovery are owned by the existing master implementation. This PR exposes only bounded error text for failed runs with `native_provider_model_rejected`.
- Historical runs with the generic `adapter_failed` code are not reclassified. No stored run is rewritten.
- Existing retry and reconciliation gates remain in place. No schema migration or model configuration change is required.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, code execution, and browser inspection. The exact deployment model ID and context window are not exposed in this session.

## Checklist

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

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-06 08:05:25 -05:00
DottaandPaperclip 81cd03b3b5 test(ui): keep initial reasoning with the saved reply (#15107)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - The issue thread shows saved replies and agent run history.
> - History that appears after the reply can move the page.
> - Master now waits for initial run history before it shows the thread
in #15228.
> - This pull request checks that reasoning and the saved reply appear
together in the first visible frame.
> - The test protects that behavior from a later change.

## Linked Issues or Issue Description

No public issue tracks this report. This is a bug regression test.

**What happened?**
The issue thread showed a saved answer before its reasoning and tool
history loaded. The later history moved the page.

**Expected behavior**
The first visible thread contains the initial reasoning and the saved
reply in order.

**Steps to reproduce**
1. Open an issue with an agent run and a saved reply.
2. Delay initial run-history hydration.
3. Observe the saved reply before its reasoning appears.

Related work: #15228 now contains the reveal gate. This PR adds a direct
regression assertion for that gate. #14667 takes a different loading
approach and remains open.

## What Changed

- Add a saved agent reply to the initial-history test.
- Assert that the native run's reasoning appears before that reply when
the thread becomes visible.
- Assert that the thread stays inert until history is ready.

## Verification

- `vitest run ui/src/components/TaskChatThread.test.tsx
ui/src/pages/IssueDetail.test.tsx` passed: 353 tests.
- `git diff --check origin/master...HEAD` passed.
- GitHub CI checks are in progress for the rebased head.

## Risks

- Low risk. This PR changes only a test.
- The production fix is already in #15228. This PR must not restore the
older code from the previous branch head.

> 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 CLI assisted with tool use and code execution. The exact
model ID and context window were not exposed to this agent 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 remote branch name describes the change and contains no
internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes (no
user-facing documentation changed)
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-05 21:09:09 -05:00
DottaandPaperclip 0e0b63e5a5 feat(connections): add experimental task-pinned AI routing (#14967)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - AI Connections separate account access from models and harnesses.
> - A pool must act as one connection while retaining each task’s
account.
> - Core must enforce member access and preserve session and recovery
rules.
> - A plugin supplies rotation policy without receiving credentials.
> - This change adds durable routing and native connector setup and
management.

## Linked Issues or Issue Description

**Subsystem affected**

AI Connections, Connectors, plugins, run dispatch, and session
compatibility.

**Problem or motivation**

Operators need to rotate new tasks across saved accounts while each task
keeps its account and session. Pool setup must fit the existing
connector catalog and account workflow.

**Proposed solution**

Add an experimental router binding, a capability-gated plugin hook, and
transactional task pins. Plugins declare native pooled connectors
through `aiConnectionRouter`. Core hosts the existing-account picker,
ordering step, and account settings. Related usage contract: #14936.
Companion private plugin:
https://github.com/paperclipai/paperclip-cloud/pull/643.

**Roadmap alignment**

This extends Apps and AI Connections. Core supplies generic enforcement
and native connector UI; the private plugin owns rotation and quota
policy. The prior duplicate search found no matching router
implementation.

## What Changed

- Add a router binding without changing existing concrete bindings. Keep
the instance flag and new pools disabled by default. Require manual
operator configuration. Show no routing toggle in Experimental settings
on either open-source or Cloud installs, even after routing is enabled.
- Persist company-scoped pools, one shared cursor per pool, and pins
keyed by company, pool, agent, and task. Commit pins and cursor advances
together with revision checks and bounded retries. Persist run-ID
affinity before allocation.
- Pass only authorized metadata and normalized usage to plugins. Core
retains credential handling, member access checks, runtime
qualification, and recovery evidence. Probe outside locks with a shared
15-second budget and freshness cache.
- Resolve routing before credential preparation and backend selection.
Preserve pins through turns, session resets, removed members, and quota
waits. Retain admitted recovery after disable or uninstall.
- Separate credential session epochs from token generations. Verified
refresh preserves the epoch; reconnect and manual replacement change it.
Include the credential slot ID in session and usage-cache identity, so
reconnecting an indexed legacy account invalidates its old session even
when both epochs are zero.
- Validate pool member installations before accepting saved-agent
bindings and recheck compatibility when the harness changes. Install
only authorized members in the new-agent transaction and record their
IDs in local activity. Pool membership cannot install a restricted
shared connection.
- Preserve pool bindings when agents hire teammates through either
creation API or native caller runtime inheritance. Block stale manager
credential references; retain explicit child authentication precedence
and reject incompatible inherited pools.
- Add native connector registration through plugin metadata. Reuse the
Connectors catalog, setup header, account header, sidebar, dialogs, and
usage display. Setup selects and orders saved connections. Advanced
settings hold usage rules and member runtime defaults. New-account setup
opens in another tab.
- Use revision-checked pool archival from the Connectors catalog and
account page. Keep task pins, cursors, recovery evidence, and underlying
connections. Reject ordinary connection updates or removals that bypass
pool revisions.
- Add pool selectors, composer models, override notes, quota status, run
details, activity records, and local run-log records. Keep
session-adoption copy minimal.
- Show **Used by** below the pool connections. List current company
agents with shared avatars and profile links. Include paused agents;
exclude terminated agents and agents using another pool.
- Add Core stories for the generic connector workflow and runtime
surfaces. Cloud stories reuse these production routes and tokens through
a preview-only alias.

## Verification

- Final head `73cb953bca30ed83e4505dd820edd9b5edffd28b`: full workspace
`pnpm -r typecheck`, `pnpm build`, and `pnpm check:token-gates` pass
locally.
- All 422 focused connector/settings/shared-contract/migration tests and
all 156 database-backed AI connection, hiring, reconnect, and
durable-routing cases pass (69 hiring cases rerun after the final
auth-precedence fix). The merged shared contract retains connection
instructions and pool metadata. The pool migration is generated at
sequence 0299 after the latest upstream migrations; this PR makes no
lockfile changes.
- All four full-app Playwright tests pass on the final head after a cold
restart and migration, against the installed private plugin and isolated
database, with no route or pool-API mocks. They cover hidden routing
controls after manual opt-in, native pool creation, ordering, membership
edits, rename, paused defaults, enabling/save/refresh persistence, stale
edits, cancellation/removal, preserved underlying accounts, unavailable
routers, and Used by avatars and profile links. Exact command:
`PAPERCLIP_CONNECTION_POOL_E2E=1
AI_CONNECTIONS_TEST_COMPANY_ID=a37b9625-5ecf-4e29-8081-04df3d6e7d6f
AI_CONNECTIONS_TEST_URL=http://127.0.0.1:3108 pnpm exec playwright test
--config tests/ai-connections-app/playwright.config.ts
connection-pools.spec.ts`.
- [Native setup, ordering, and management
screenshots](https://github.com/paperclipai/paperclip/pull/14967#issuecomment-6006976278)
address the review follow-up. [Earlier selector, quota, and run-detail
screenshots](https://github.com/paperclipai/paperclip/pull/14967#issuecomment-5971537316)
show the runtime surfaces. Core previews: `pnpm --filter @paperclipai/ui
storybook`, then **Connectors / Pool host** or **AI Connections /
Connection pools**. Cloud owns its host-backed plugin stories; both
repositories’ Operator Setup Required story assertions pass.
- Live acceptance used OpenAI/Codex and Anthropic/Claude ACPX, resumed
both exact sessions after restart, preserved pinned accounts through
explicit reset and controlled quota deferral/recovery, and committed
only two allocations across fourteen runs. A later UI-created task test
again rotated OpenAI then Anthropic and resumed OpenAI through
follow-up/restart/quota recovery. That later Anthropic execution was
blocked by its saved OAuth token expiring (provider 401). No live usage
probes ran.
- The full local `pnpm test:run` was attempted earlier and did not
complete because of macOS embedded PostgreSQL bootstrap/shared-memory
failures and the 40,000-file Git fixture timeout. The focused database
suites above now pass; full-suite verification is provided by the split
CI lanes. The preceding CI run had one runtime readiness timeout; it
passes locally both alone and inside the larger runtime suite. That
larger local suite also encountered an embedded PostgreSQL setup failure
and two macOS temporary-path alias assertions; those two assertions pass
with canonical TMPDIR=/private/tmp. All final-head CI checks are
terminal green, including full general/serialized server suites, Runner
checks, browser E2E shards, canary verification, build, and typecheck.
Greptile is 5/5 on that exact head with no unresolved threads.

## Risks

- The migration adds routing tables and a credential epoch column.
Install the private plugin only with the compatible Core contract.
- Routing and each pool require opt-in. Production distribution and
fleet defaults remain unchanged.
- Unknown usage stays eligible. Known pinned exhaustion waits; revoked
access requires operator repair.
- Legacy adapters require compatible members. Runner model and effort
overrides remain limited by qualified backend support.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository editing, code
execution, and browser testing. The exact deployment model ID and
context window are not exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-05 20:44:37 -05:00
DottaandPaperclip 2c43b39167 refactor(ui): share task composer and project/worktree controls (#15091)
Use the shared composer for new tasks, including project and worktree selection, rich mentions and slash commands, and remembered task settings.

Save project preferences after successful task updates. Show known agent models by name and use Default for unknown runtime defaults.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-05 18:06:40 -05:00
DottaandPaperclip ad0c4f0767 fix(ui): keep mobile task output above the composer (#15282)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People read agent output in the task conversation.
> - Mobile tasks scroll the document and keep the composer above the
footer.
> - The document body keeps a fixed height while the thread grows.
> - The old observer misses late thread growth, and a layout scroll
event can cancel follow mode.
> - This pull request observes the thread and preserves follow mode
until the reader scrolls up.
> - The benefit is visible new output without repeated manual scrolling.

## Linked Issues or Issue Description

**What happened?**

New task output can move behind the mobile composer while the reader is
already at the bottom. Late content layout does not resize the
fixed-height body. A scroll event after layout growth can also clear
follow mode before the resize observer runs.

**Expected behavior**

Keep new output visible above the composer while the reader follows the
bottom. Hold the reading position after an upward scroll. Resume
following when the reader returns to the bottom.

**Steps to reproduce**

1. Open a long task conversation on mobile and scroll to the bottom.
2. Let a streamed row or delayed content grow after the parent renders.
3. Check whether the latest output stays above the composer.
4. Scroll up to read earlier output, then return to the bottom.

**Paperclip version or commit**

Reproduced by regression tests against master at 6c36c07a4.

**Deployment mode**

Built from source. This is a mobile UI bug and does not depend on an
adapter or database.

Related work: #15228, #13229, and #13095. The search found no duplicate
fix for mobile document auto-follow.

## What Changed

- Observe the conversation box as well as the body for late layout
growth.
- Preserve bottom-follow intent when a layout scroll event arrives
without an upward scroll.
- Reconcile document scrolling when the viewport resizes.
- Add regressions for late growth, event ordering, reading position,
return to bottom, and viewport changes.
- Add a bounded Storybook streaming fixture with the production thread,
composer, and mobile footer.

## Verification

- 244 focused tests pass across `useWindowAutoFollow`,
`TaskMessageScroller`, and `TaskChatThread`. Three new regressions fail
before the fix.
- All 7,439 UI tests pass across 683 files (`pnpm exec vitest run
--project @paperclipai/ui`).
- `pnpm check:token-gates`, `pnpm -r typecheck`, and `pnpm build` pass.
- The full repository test shards and browser E2E checks pass in CI on
commit 43354eb38. The duplicate local `pnpm test:run` was stopped after
37 minutes once those CI test shards passed; that local run did not
complete.
- Browser check at 402 by 874: controlled streamed output stayed at
document bottom, with the newest paragraph above the composer. Scrolling
up held position as output grew. Returning to bottom resumed following.
- Open Storybook's **Task chat / Mobile streaming follow / Streaming**
story to repeat the check. The fixture makes no agent or provider calls.
- Greptile is 5/5 on commit 43354eb38. All review threads are resolved.
- All CI checks pass on the final commit, including the canary packaging
gate.

## Risks

- Scroll event order differs between browsers. The regression tests
cover a scroll event before resize reconciliation and deliberate upward
scrolling during growth.
- The change affects the mobile document scroll owner. Desktop scrolling
stays covered by its existing tests.
- Existing same-task targets and browser history restoration still pass.

## Model Used

OpenAI GPT-6 through Codex. The exact serving variant and context window
are not exposed in this session. Capabilities used: reasoning, code
editing, tool execution, and browser verification.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-05 17:33:29 -05:00
DottaandPaperclip b43073d11f feat(connections): sync and group accounts managed by aggregators (#15254)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Connections give agents governed access to external tools.
> - Aggregator gateways can expose accounts that users already connected
upstream.
> - The Apps catalog did not show those accounts or their current
provider status.
> - Separate cards and setup tasks also made account ownership unclear.
> - This pull request discovers upstream accounts and groups them under
one app card.
> - Users can find connected apps while each provider keeps control of
its accounts.

## Linked Issues or Issue Description

**Subsystem affected**

Connections across the database, shared contracts, server, and board UI.

**Problem or motivation**

Users cannot see which apps are connected through a saved aggregator
gateway. Native and upstream accounts need one app card. Discovery must
preserve company, user, gateway, and credential boundaries.

**Proposed solution**

Sync account metadata from Composio, Arcade, and supported Executor
gateways. Keep upstream account management in each provider. Use source
chips and search to browse the catalog. Preserve native setup and the
gateway's existing access policy.

**Alternatives considered**

Creating a local executable connection for each upstream account would
duplicate authorization state. Using an agent task for routine Composio
setup would add an unnecessary step. The board now calls the saved
gateway directly for that setup.

**Roadmap alignment**

This extends the shipped Connected Apps and MCP Tool Gateway features in
ROADMAP.md. The duplicate search found no open PR for managed account
discovery.

Related work: Refs #13755, Refs #13941, Refs #14725, Refs #13855. Open
PR #12906 covers adjacent toolkit routing work.

## What Changed

- Add provider-neutral discovery, sync, and refresh APIs. Preserve the
Composio API paths.
- Cache observations by company, saved gateway, viewing user, and
credential version. Retain stale observations after failed or incomplete
scans.
- Add optional Arcade account sync credentials in the vault. Discover
Executor accounts through its supported inventory interface.
- Group native and upstream accounts in one app card. Imported account
menus open their provider. Gateway menus own refresh and sync setup.
- Add Paperclip, Composio, Arcade, Installed, and All chips. Show 50
catalog entries per page. Keep connected accounts above discovery. Keep
explicit provider searches scoped.
- Simplify Composio app setup and refresh its connected app list on the
gateway Permissions page.
- Add a compact agent access card and task creation defaults for
connection setup. Preserve explicit blocks and approval policies.
- Add two replay-safe migrations, service and UI tests, Storybook
journeys, and acceptance stories.

## Verification

- Passed the repository typecheck, full build, token gates, and
migration ordering check.
- Passed the focused provider adapter, connection interaction, and
catalog tests after rebasing onto master.
- Passed all nine database sync and migration replay tests using a
disposable database on the test-drive PostgreSQL cluster. Removed that
database after the run.
- Verified Arcade cursor pagination against its official Go SDK and
passed all eight adapter tests, including short and incomplete pages.
- Passed all 45 interaction tests after making the exact requested tools
and their Allowed/Ask first permissions visible before granting access.
Verified the compact card in Storybook.
- Passed the complete UI suite on the final code: 683 files and 7,432
tests, including the corrected Composio destination assertions. Passed
130 focused tests for the UUID, management-link, and health-status
corrections.
- Passed 22 Composio setup/sync tests, 23 connection-intent service
tests, and the connection migration test in separate disposable
databases. Database startup alone was substituted; the suites exercised
their real SQL and services.
- Passed all 10 OpenAPI route checks and the full-stack
connection-intent browser test, including scoped consent, agent
continuation, and task completion.
- The local full runner encountered embedded PostgreSQL startup failures
on this loaded macOS host. The earlier in-flight run also held the
pre-fix Arcade transform; a fresh run of the final provider suite
passes. The final-head CI is queued during GitHub’s active Actions
incident: https://www.githubstatus.com/. The previous run also lost
several runners simultaneously; its real catalog assertion failures are
fixed and the fresh complete UI suite passes.
- Tested the real test-drive server in the embedded browser with a live
Composio gateway. Detected Airtable and Circleback. Verified refresh
progress, account rows, source chips, search scope, and 50-entry
pagination.
- Arcade and Executor coverage uses provider fixtures. Live credentials
were unavailable.
- Storybook builds successfully and includes grouped native/provider
accounts, stale and unavailable discovery, optional Arcade setup, and
mobile states. The acceptance document records the simulated and live
coverage separately.

- Greptile reviewed final commit
`217b024c27b5933e773ce9419c4e92b1032042c6` at 5/5. All six review
threads are resolved, security scans pass, and the PR has no merge
conflicts. The outstanding remote checks are `ci / Select trusted
runner` and `review`, queued by GitHub. They need to complete before
merge.

## Risks

- Provider response changes can break inventory discovery. Failed scans
retain observations and show stale status.
- Composio scans only the supported catalog and can take time. Large
inventories run in the background with progress and a bounded lease.
- Arcade requires a project API key and user ID when the gateway cannot
supply them. This key is used only for discovery.
- Executor discovery depends on the server's exposed inventory tools.
Unsupported servers report unavailable discovery.
- Cached account rows do not grant access or create executable
connections. Gateway policies still govern tool use. Account deletion
and per-app authorization remain upstream.
- The migrations add tables and one nullable column. Replay preserves
existing rows and company-scoped foreign keys.

## Model Used

OpenAI Codex, based on GPT-6. The session does not expose a more
specific serving model ID or context limit. Used reasoning, repository
tools, code execution, and browser verification.

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-05 14:57:04 -05:00
Devin FoleyandPaperclip 55e0c895ef test(ui): finish sidebar focus cleanup before JSDOM teardown (#15255)
Finish deferred Radix focus cleanup before the sidebar test environment
closes. Use React act and controlled timers, check the real unmount focus
events for both menus, and assert no timer work remains.

Validation: all 7,368 UI tests, repository typecheck and build passed.
Hosted CI passed, including server tests, browser tests and canary packaging.
Greptile 5/5 on the exact reviewed head; no unresolved comments.
Local full-suite limitations and clean-base comparisons are recorded in the PR.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-05 12:11:32 -07:00
DottaandPaperclip 7498705642 fix(ui): stabilize mobile task reading and document navigation (#15228)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People read tasks and send instructions from phones as well as
desktop browsers.
> - The mobile footer let page text show through its labels, and small
text fields made Safari zoom on focus.
> - Small scroll changes made the footer switch direction, and its
changing page padding moved the conversation.
> - Task pages also showed comments before question cards and run
history arrived, so the composer and reading position moved again.
> - Document links also used native navigation, which reset the reading
position or reloaded a task through its UUID URL. Desktop tabs were
crowded in the mobile drawer.
> - This pull request keeps navigation steady, opens documents in the
mounted task, and gives mobile readers a full-height panel with a
vertical tab selector.
> - The benefit is a stable task view and smoother scrolling on mobile.

## Linked Issues or Issue Description

**What happened?**

The mobile footer was translucent. Safari zoomed when a person focused a
small text field. The footer switched abruptly while scrolling. A large
task could show saved comments, then move the page again when a question
card or run history arrived. In a local test with delayed responses, a
late question moved the mobile composer by about 374 pixels. Opening a
plan from the feed could reset the view or reload the task through a
UUID link. The mobile document drawer left part of the feed exposed
above small desktop tab controls.

**Expected behavior**

The footer has an opaque surface and moves smoothly after deliberate
scrolling. Text fields do not cause automatic focus zoom. A task shows
its initial conversation and composer together at the final scroll
position. Background refreshes keep the existing conversation visible.
Document links open in the mounted task with its existing cache and
reading position. Mobile documents fill the viewport, show a clear close
button, and offer a vertical list of open tabs.

**Steps to reproduce**

1. Open a task with many long comments and a pending question in iOS
Safari.
2. Delay its interactions, activity, and runs responses by different
amounts.
3. Reload the page and watch the conversation and composer move as each
response arrives.
4. Scroll down and back up, including small direction changes and edge
bounce.
5. Focus the task composer, search field, and new-task title and
description.
6. Open a plan or another task document from the feed, including a link
that uses the task UUID. Close the panel and check the reading position.
7. Open several documents on a phone. Switch tabs and close both active
and inactive tabs.

**Paperclip version or commit**

Developed from `1c07b5903` and rebased onto `59015846a`.

**Deployment mode**

Built from source. Tested in an isolated local test drive with iOS 26.5
Simulator Safari and Chrome. A temporary local proxy delayed independent
responses for the layout test.

Related work found in the duplicate search:

- Refs #14727. It made saved replies appear before supporting history.
This PR keeps its parallel requests and narrows the tradeoff in favor of
a stable first layout.
- Refs #14667. This open PR takes a different approach with per-run
placeholders and retries. This PR fixes the observed question/composer
movement and mobile navigation behavior.
- Refs #13095 and #13597. These earlier fixes added task scroll anchors
and skipped transcript waits for scheduled retries.
- Refs #6550. Earlier mobile board polish.
- Refs #9467. This related open PR changes list and generic tab reflow.
The task-pane selector uses a separate component.

## What Changed

- Give the mobile footer an opaque semantic surface.
- Set a base-size floor for editable text on touch devices to prevent
Safari focus zoom. Preserve larger title text.
- Share mobile scroll tracking between both layouts. Accumulate scroll
distance, ignore edge bounce and changed document bounds, and update
once per frame.
- Use shared motion tokens for the footer and composer. Keep page
padding stable and honor reduced motion.
- Wait for the initial question cards, attachments, work products,
activity, runtime selection, plan, and relevant transcript history
before the first reveal. Skip scheduled retries and older runs outside
the initial comment window.
- Bound the first reveal to 15 seconds. A stalled supporting request
leaves saved conversation and the composer accessible with an explicit
loading notice.
- Keep concealed mobile history from stretching the document. Keep the
composer mounted but concealed until the same reveal. Keep both visible
during later refreshes.
- Route first and repeated same-task document clicks in place. Recognize
UUID and identifier links. Preserve the thread history entry and feed
position. Keep modifier clicks, downloads, external links, and classic
document behavior.
- Give the mobile task panel the full viewport and safe-area padding.
Use a visible X and 44-pixel touch controls. Replace the horizontal tab
strip with a vertical selector that wraps titles and supports keyboard
focus.
- Add four interactive Storybook states for a few tabs, long names, many
tabs, and the last tab. Reuse the production selector and tab
controller.
- Add navigation and tab regressions, update first-reveal regressions,
and document the behavior in `DESIGN.md`.

## Verification

- 392 tests passed across the seven focused task-loading, scroll,
mobile-navigation, layout, and composer suites. After review fixes, all
339 tests across the four affected suites passed, including
stalled-loading fallback on mobile and desktop and the motion-token
catalog.
- All 442 focused document, tab, task-thread, and scroll tests pass. The
final click-propagation cleanup also passes all 136 task-detail tests.
UI typecheck, UI production build, and `pnpm check:token-gates` passed.
- All four cases in `artifact-tab-arrival.spec.ts` and
`text-attachment-tabs.spec.ts` pass locally, covering desktop and mobile
selection, composer focus, document rendering, and downloads of the
original bytes.
- `pnpm --filter @paperclipai/ui build-storybook` passed. Open the
mobile tab stories under `Prototypes/Task detail/Mobile tabs`.
- A local diagnostic proxy measured cached plan content at about 250 ms
after the first click. The HTML load count and task request count did
not change. Feed scroll stayed at the same position. First, repeated,
and UUID document links were tested at phone and desktop widths.
Task-reference links close their preview before the document reader
opens.
- In Chrome at desktop and phone widths, the delayed-response task
showed one complete reveal. The late question no longer moved an already
visible composer.
- In iOS Simulator Safari, verified the large-task reload, opaque
footer, navigation hide/reveal, and search/new-task/composer focus
without automatic zoom.
- Full workspace typecheck and build passed. The updated UI also passes
typecheck, production build, and token gates.
- All 54 checks pass on the final commit
`bf5c9914e61833e7cc8794a69d72cf8c7057b952` (two additional checks are
intentionally skipped). Greptile reviewed that commit at 5/5, and all
review threads are resolved.
- Full local `pnpm test:run` was attempted but stopped after
server-fixture failures. Embedded PostgreSQL startup failure reproduced
in an isolated native-interaction fixture after five startup attempts.
The broad run also reported a rapid Slack callback ordering test
failure. These server paths are unchanged by this PR, and their CI
shards pass on the latest head. The full local suite is not claimed as
passing.
- A localhost proxy stalled the activity response for 30 seconds. Chrome
revealed the available conversation after the 15-second deadline at both
desktop and phone widths, kept the composer accessible, and cleared the
loading notice when the response arrived.

## Risks

Slow initial history requests can delay the first conversation reveal by
up to 15 seconds. If that deadline expires, late data can change the
available conversation while a loading notice remains visible. The
reveal waits only for runs in the initial comment window, and later
refreshes do not conceal an existing conversation. The larger editable
text can change line wrapping on phones. Mobile navigation and composer
motion use shared tokens and respect reduced-motion settings. Mobile tab
selection changes the control layout. Document links retain URL history
while sharing the task reading position; other tasks and external links
keep their normal navigation behavior.

I checked `ROADMAP.md`. This is a fix for existing UI behavior.

## Model Used

OpenAI GPT-6 in Codex. The runtime does not expose a more specific model
ID or context-window size. The agent used reasoning, code editing,
terminal tools, and Chrome and iOS Simulator testing.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-05 12:33:34 -05:00
DottaandPaperclip 59015846ae fix(chat): keep dismissed task questions in the feed (#15229)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents ask users questions in task chats and Agent Chat.
> - Agent Chat keeps unanswered questions as compact entries in the
feed.
> - Regular task chats still show a pending composer badge after
dismissal.
> - A page reload can also open a dismissed question form again.
> - This pull request applies the same feed behavior to both chat types
and saves dismissal per person and task.
> - Users can continue the chat and return to the original question
later.

## Linked Issues or Issue Description

**What happened?**

Dismissing a question in a regular task chat leaves a pending composer
badge. The question can return after a page reload. The earlier feed
behavior only applied to Agent Chat.

**Expected behavior**

A dismissed question stays in the feed. Its form and pending badge leave
the composer. Reload preserves dismissal. Opening the feed entry
restores the original question and draft answer.

**Steps to reproduce**

1. Open a regular task chat with a pending question.
2. Select an option, then dismiss the form.
3. Reload the page. Check that the composer stays clear.
4. Open the question in the feed. Check that the draft is restored.
5. Submit the answer. Check that the answered receipt appears.

**Paperclip version or commit**

Reproduced on master at `a386a599983519eb1d399f8b770bfccdb2a74762`.

**Deployment mode**

Browser UI in local and authenticated instances. This change does not
depend on the agent adapter.

Related work: Refs #14613, which added the Agent Chat feed behavior.
Refs #9141, which validates real answers on the server. Refs #11434,
which tracks comment-driven changes to interaction state. This PR
changes question presentation only.

## What Changed

- Show compact unanswered question entries in regular task chats.
- Exclude durable questions from composer pending counts and navigation.
- Save dismissal in local storage per person and task. Merge the latest
saved IDs so dismissals from another tab survive reload. A new question
can still open its form.
- Keep the original question pending and answerable. Keep approval and
permission controls.
- Run the question-history regressions in both chat modes. Add reload,
new-question, user/task scope, and stale-tab coverage.
- Share the real-component Storybook fixture. Add a regular task test
drive and an interactive dismissal/answer scenario.
- Update the planning-mode browser test to check a dismissed question in
the feed after reload and on mobile.
- Update the design rules, implementation spec, and preview
instructions.

## Verification

- 329 focused thread, composer, and interaction-card tests pass.
- `pnpm -r typecheck` passes. The UI typecheck also passes after the
review fix.
- `pnpm build` passes for the full repository.
- UI build, Storybook build, and token gates pass. The UI build and
token gates were rerun after the review fix.
- Greptile gives final commit `98f71f221` a 5/5 score. The current-head
check passes, and there are no unresolved review threads.
- All 56 current-head checks are terminal: 54 pass and two conditional
Storybook jobs skip. The CI run includes the full test shards, build,
typecheck, browser tests, aggregate verification gate, and package
canary.
- The stale-tab regression fails in both chat modes before the review
fix and passes after it.
- `pnpm exec playwright test --config tests/e2e/playwright.config.ts
tests/e2e/planning-mode-visual-verification.spec.ts` passes against a
throwaway local server. It checks dismissal, reload, task navigation,
and desktop/mobile planning controls.
- The duplicate local `pnpm test:run` attempt was stopped after the full
CI test suites passed. It did not complete locally.
- Manual browser test: select Green, dismiss, reload, reopen, submit the
saved answer, and inspect the answered receipt. Also send a new message
while the unanswered question remains in the feed. The test drive uses
real UI components with fixture response callbacks.
- To repeat the browser test, run `pnpm storybook`. Open **Chat &
Comments → Task Chat Unanswered Questions → Test Drive**.

## Risks

- Dismissal is a browser-local preference. It does not sync to another
browser or device. Clearing local storage removes it.
- When local storage is unavailable, dismissal lasts for the mounted
thread only.
- Unanswered questions can accumulate in the feed. They stay pending
until answered or resolved through the existing API.
- No database migration, API change, or change to approval permissions.

## Model Used

OpenAI Codex, `gpt-6.1-sol`, with xhigh reasoning, repository editing,
code execution, and browser control. The context-window size is not
exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-05 10:55:38 -05:00
DottaandPaperclip a386a59998 Reduce repeated native completion guidance and preserve final replies (#15151)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native agents receive task constraints and completion tools from
Paperclip.
> - Completion tools already define the procedure for reporting a
result.
> - Repeated procedure text adds instructions to each full task turn.
> - The final reply must still explain a blocker and link a saved
document.
> - This pull request removes repeated procedure text and keeps these
visible outcome requirements explicit.
> - A document receipt supplies the exact link, and stricter evals check
the persisted reply and browser navigation.

## Linked Issues or Issue Description

Refs: #14961. Related: #14948 and #15007.

**What happened?**

Native task envelopes repeat completion procedure text. A reduced
envelope needs explicit final-reply requirements. The `write_document`
receipt also lacks a canonical document link.

**Expected behavior**

Keep the completion tools as the source of procedure details. Require
one accepted completion result before the final reply. A blocked reply
must explain the reason, owner and unblock action. A document reply must
contain a working link to the saved document.

**Steps to reproduce**

1. Run the native assigned-skill document case and native blocker case.
2. Inspect the run-attributed provider final and its persisted comment.
3. Check the blocker explanation or open the final reply's document
link.

## What Changed

- Remove repeated completion procedure text from the native task
constraints and backend instructions.
- Keep explicit blocker and document-link requirements in full task
turns.
- Return a company/task-scoped `documentHref` from `write_document`.
Preserve the link in the idempotent mutation receipt.
- Repeat canonical links for this run's current saved revisions in
accepted completion feedback. Give blocked providers final-response
guidance for the cause, owner and unblock action.
- Keep internal document/comment anchors when Markdown issue links load
cached issue details.
- Add a manual six-cell comparison suite with strict source, build,
default-instruction and budget admission.
- Capture eighteen shared runnerd RPC projections and six direct
OpenCode HTTP projections across start, resume and continuation phases,
using scripted local transports and no provider execution.
- Apply v3 checks only to the manual instruction comparison; preserve v2
checks for the existing native completion suite. Check the actual
persisted blocker reason and exact saved-document link. Click the
rendered document link and check the original content marker in the
classic document card or the new document tab.
- Forward exact OpenCode finishing calls through the controller. Wait
for acceptance, keep accepted feedback and concrete rejection text, and
reject malformed responses. Preserve ordinary dynamic-tool response
handling.
- Settle the completion decision and tool response before mapping a
racing idle/error/abort event or handling explicit close/interruption.
Reject a concurrent finishing call before controller admission.
- Add a provider-free regression through real runnerd, the OpenCode
proxy and a fake provider. Reject the first completion, accept the
corrected report in the same turn, and propose one result.
- Keep all original verdicts unchanged. Treat replay under new checks as
separate diagnostics.

## Verification

- `pnpm -r typecheck` and `pnpm build` pass locally.
- Native document-authority tests pass, including company/run
authorization and idempotent replay.
- Native runtime-context, backend and measurement tests pass.
- Final-answer calibration, protocol scoring, source-admission and
catalog tests pass. Wrong reasons, absent links and wrong link targets
fail.
- `pnpm test:e2e:runner:typecheck` passes. Discovery lists exactly six
single-attempt local cells with the declared models.
- Exported `prepareNativeInstructionPreflight` then
`verifyNativeInstructionPreflight` pass on this clean committed source.
They build locally and make zero provider calls.
- Corrective live confirmation is incomplete. Source 3a7349d passed both
Claude and both Codex cases. OpenCode saved the correct document but
omitted its final link; its blocker case was canceled before paid
execution. Preserve this failure. The e171282 confirmation was stopped
during build after fresh review found a completion-settlement race; it
executed zero providers. Source c3e0cb303 fixes that race. Two affected
OpenCode cases await fresh review and one bounded confirmation; earlier
results remain attributed to their original source.
- OpenCode proxy parsing, driver, factory and input tests: 81 pass
across retained focused runs, including six settlement races.
Evaluator/scoring/admission checks: 122 pass. The real proxy regression
passes. Fresh local prepare then verify passes with 18 shared and 6
direct scripted captures, fresh SDK/Rust builds and zero providers.
- The full local suite recorded two failures: a webhook timeout and a
Git-scan load count mismatch. Both files pass in isolation with
unchanged assertions/time budgets; preserve the original failure log.
Fresh c3e0cb303 CI and review are pending. This PR remains draft.

## Risks

- Final-answer wording can vary by provider. The checks cover the
declared release-access blocker and saved document fixture, not general
answer quality.
- A single trial does not establish general equivalence, cause, speed,
cost or live resume behavior.
- `documentHref` is an additive receipt field. It points to the current
saved document, not an immutable historical revision. Replaying an older
receipt does not fabricate a new link.
- The correction adds four production paths for document receipts,
accepted completion feedback and UI navigation, plus four OpenCode
controller/proxy paths, beyond the original three instruction paths.
Completion rejection must remain repairable; the production-boundary
regression covers it.
- Preserve the frozen comparison context for live measurement. A
merge-tree check against current master is clean. Do not relabel earlier
live results as results from a later source tree.

## Model Used

- OpenAI Codex, GPT-6 family. The exact serving model ID and context
window are unavailable in this session. Capabilities used: reasoning,
code editing, shell execution, test authoring and evidence review.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-05 08:10:14 -05:00
1c07b5903b feat: Chat leads the left nav, agent work beside chats, and a Combined Inbox + Task List flag (#15100)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The left nav is the main way people move between tasks, the inbox,
and Agent Chat
> - The nav has separate Inbox and Tasks rows that show overlapping
work, and Chat is one row among many
> - The side panel beside a chat shows the conversation's own artifacts,
not the work the agent did
> - People want Chat to be easy to find, and they want one place for
their task views
> - This pull request moves Chat to the top of Work, shows the agent's
tasks and artifacts beside each chat, and adds an experimental flag that
folds Inbox into Tasks
> - The benefit is a shorter nav and a chat view that shows what the
agent is working on. Both changes stay off until an operator enables
them

## Linked Issues or Issue Description

Refs #14706 (the secondary Agent Chat navigation this change builds on)
Refs #14848 (reopen the last visited agent chat)

**Subsystem affected**
UI navigation (left nav, mobile tab bar), Agent Chat side panel, task
list and inbox, and the company artifacts API.

**Problem or motivation**
Inbox and Tasks are two nav rows for overlapping work. Chat sits in the
top group with no clear home. The chat rail lists only agents you
already talked to, so you cannot see your other teammates there. The
side panel beside a chat shows only the conversation's own artifacts. It
does not show the tasks and files the agent made.

**Proposed solution**
With Agent Chat on, Chat leads the Work section and the rail lists every
eligible agent. The chat side panel opens on the agent's tasks as cards,
and the agent's artifacts are available from +. A new experimental flag,
Combined Inbox + Task List, makes Inbox a set of views inside Tasks.

**Alternatives considered**
Rebuilding the inbox inside the task list. Instead, `/issues` hosts the
existing Inbox component for inbox views and the existing task list for
status views, so all inbox behaviour stays the same.

**Roadmap alignment**
Agent Chat (ROADMAP.md, "Agent Chat (including CEO Chat)"). All changes
are behind experimental flags that are off by default.

## What Changed

- **Agent Chat nav (streamlined shell):** Chat is the first row of Work,
not a top-group row. Workspaces leaves the nav while Agent Chat is on.
The mobile tab bar is Home · Chat · + · Tasks · Agents. The legacy shell
keeps master's top-group Chat row.
- **Chat rail:** `AgentConversationsSidebar` lists every eligible agent.
The open chat is first, then conversations by recent activity, then the
rest of the roster alphabetically. Terminated agents and agents you left
are omitted unless you have history with them. The picker still marks
only real conversations as "Open chat".
- **Chat side panel:** a new default Tasks tab shows one card per task
the agent created, was assigned, commented on, or acted on, newest
first. It has the task list's filter popover and a sort control. **+ →
Artifacts** shows the agent's artifacts as cards. Cards open in a new
tab. Agent Chat off keeps the old Artifacts tab.
- **Artifacts API:** `GET /api/companies/:companyId/artifacts` accepts
`agentId`. The filter applies to documents, work products, and
attachments by the agent each result is attributed to. The shared
validator and the UI client carry the new parameter, and the OpenAPI
entry picks it up from the shared schema.
- **Combined Inbox + Task List flag (`enableCombinedInboxTasks`, off by
default):** new card in Settings > Experimental. The Inbox row goes away
and its badge moves to Tasks. A Views menu on `/issues` covers Mine,
Unread, Blocked, Recent, Everything, All, Active, Backlog, and Done.
Bare `/issues` opens the last-used view (default Mine). Links that carry
`assignee`, `workspace`, `participantAgentId`, or `q` open All so the
filter is kept. `/inbox/*` and
`/issues/{all,active,backlog,done,recent}` redirect to the matching
view. `/inbox/requests` stays its own page.
- **Task detail breadcrumb:** the view key now decides the source, so
quick-archive still works after a reload from an inbox view.
- **Docs:** `doc/PRODUCT.md` and `doc/SPEC.md` describe the chat rail,
the chat side panel, and the new flag.

## Verification

- `cd ui && npx vitest run --no-file-parallelism src/components/chat
src/components/task-side-panel/TaskSidePanel.test.tsx
src/components/AgentConversationsSidebar.test.tsx
src/components/Sidebar.test.tsx
src/components/SidebarCompanyMenu.test.tsx
src/components/Layout.test.tsx src/pages/AgentChats.test.tsx
src/pages/InstanceExperimentalSettings.test.tsx
src/lib/task-views.test.ts src/lib/issueDetailBreadcrumb.test.ts
src/pages/Inbox.test.tsx src/pages/Issues.test.tsx src/App.test.tsx
src/App.activity-routing.test.tsx
src/components/MobileBottomNav.test.tsx
src/components/CommandPalette.test.tsx`: 20 files, 356 tests pass.
- `cd server && npx vitest run
src/__tests__/company-artifacts-service.test.ts`: 13/13 pass, including
the new agent-filter test across all three artifact sources.
- The new rail test fails against the unmodified rail.
- `pnpm check:token-gates`: all gates clean.
- Manual: enable Agent Chat in Settings > Experimental. Open Chat. The
rail lists all agents. Open a chat. The side panel shows the agent's
tasks. Use **+ → Artifacts** to see the agent's artifacts. Then enable
Combined Inbox + Task List. The Inbox row goes away, and Tasks shows a
Views menu.
- Snapshot baselines are intentionally not updated. See
`doc/design/DECISION-SHEET.md`, "Per-change snapshot verification
demoted to dormant (Jul 13 2026)".

## Risks

- With both flags off, the app behaves like master. The only exception
is the API: it accepts a new optional query parameter.
- With Agent Chat on, the rail can list many agents in a large company.
It uses the agent list the app already loads, and search filters it.
- The Tasks panel reads at most 200 recently updated tasks per agent and
says so when it reaches the limit. The Artifacts panel reads at most 500
of the agent's artifacts.
- Combined Inbox + Task List changes what bare `/issues` opens for
people who enable it. Deep links with a task filter still open All.

## Model Used

- Claude (Anthropic), model ID `claude-opus-5-5`, through Claude Code
with tool use (shell, file edit, test runs). Extended thinking was
enabled.

## Checklist

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

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

---------

Co-authored-by: scotttong <squadbot000@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 02:13:46 -07:00
DottaandPaperclip db72ad4c73 fix(ui): explain branch artifacts without remote links (#15051)
## Thinking Path

> - Paperclip helps people manage agent work and inspect its results.
> - The issue artifact list presents those results as work-product
cards.
> - A branch can have no remote URL or structured metadata.
> - The current card hides its summary and has no action in that case.
> - This pull request shows the summary and provides an accessible
details action.
> - The card labels the absent link without making a false link.

## Linked Issues or Issue Description

**What happened?**
A branch work product without a URL showed a short title and an icon. It
did not show the saved summary or provide an action.

**Expected behavior**
The card must show what the branch contains. People must be able to open
the saved details. It must not imply that a remote URL exists.

**Steps to reproduce**
1. Open the artifact list of an issue with a branch work product that
has `url: null` and `metadata: null`.
2. Find the branch card. Its summary and details action are missing
before this change.

Related work: #12717 introduced rich work-product cards.

## What Changed

- Keep linkless branch cards concise: show the title and no-link state.
Keep the full summary behind an optional Saved description toggle.
- Label a branch with no URL as having no remote link. Let a person open
its details with a keyboard-accessible button.
- Add a focused interaction test and two Storybook states for the
no-link branch.

## Verification

- `pnpm --filter @paperclipai/ui typecheck` passed.
- Focused Vitest tests passed: 45 tests in two files.
- `pnpm --filter @paperclipai/ui build` passed.
- `pnpm --filter @paperclipai/ui build-storybook` passed.
- `pnpm check:token-gates` passed.
- The Storybook collapsed and expanded states rendered in Chromium. Both
screenshots were captured.
- Full workspace typecheck could not finish: the runner Rust package
requires `cargo`, which is not installed in this environment.

## Risks

- Low risk. The change affects card text and the action for records
without a URL. It does not change the saved data or routes.
- Long saved summaries on other linkless work products expand the card
height after a person selects Details.

## Model Used

- OpenAI Codex coding agent. The execution environment does not expose
the exact model ID or context window to this agent. It used code
execution and a browser to validate the change.

## 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
(the managed execution workspace fixes this branch name)
- [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
(Storybook examples)
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-03 21:05:48 -05:00
DottaandPaperclip 2a8a99e4a5 fix(ui): reveal completed thinking caret beside label (#15048)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - The task thread shows completed agent work and its reasoning.
> - The completed work row places the disclosure caret at the far right.
> - The caret stays visible even when the reader does not inspect the
row.
> - The row needs a quiet control that stays close to the work label.
> - This pull request places the caret after that label and shows it on
hover or keyboard focus.
> - The change keeps the timestamp on the right and does not move
content on hover.

## Linked Issues or Issue Description

**What happened?**

The completed agent work row shows a disclosure caret at the far right
of the task thread. The caret stays visible when the pointer is
elsewhere.

**Expected behavior**

The caret stays near the work label. It appears on hover or keyboard
focus. The timestamp stays on the right.

**Steps to reproduce**

1. Open a task with a completed agent run.
2. Look at the completed work row without hovering over it.
3. Hover over the row and then use the keyboard to focus its button.

Related: #11772 addresses a different caret and composer layout.

## What Changed

- Move the completed work caret next to the work label.
- Keep its space reserved. Show it on hover or keyboard focus.
- Add a test for caret position, visibility classes, and the open state.

## Verification

- `node node_modules/vitest/vitest.mjs run
ui/src/components/IssueChatThread.test.tsx` passes all 100 tests.
- `node scripts/check-token-gates.mjs` passes all token gates.
- `git diff origin/master...HEAD --check` passes.
- CI passes on the latest head, including typecheck, build, tests, and
verification. The local isolated worktree could not run typecheck
because dependency installation failed while applying the existing
`codex-acp` patch.

## Risks

- Low risk. The same button still opens the work detail. Only the caret
position and visibility change.
- On a touch device, the caret is not visible without hover. The work
row stays a button that users can tap.

> This is a focused UI fix. It does not add a planned core feature from
`ROADMAP.md`.

## Model Used

- OpenAI Codex coding agent. The runner does not expose the exact model
ID or context window. The agent used reasoning, shell tools, 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 the details available in this
runner
- [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 linked public issues or described the issue in-PR
following the relevant issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal
ticket ID
- [x] I have run focused tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have checked documentation impact; no documentation change is
needed for this visual fix
- [x] I have considered and documented the risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-03 12:41:22 -05:00
DottaandPaperclip 1c3abf5075 fix(ui): use available space for composer labels (#15050)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - The task composer shows the next assignee and model before a message
starts work.
> - Fixed width limits shortened both labels when the composer had
unused space.
> - People could not read the selected agent and model even when the
full text could fit.
> - This pull request makes the capsule use the available composer
width.
> - It keeps the ellipsis when Plan mode or a narrow layout causes real
space pressure.
> - The benefit is clearer run settings without damage to the compact
composer layout.

## Linked Issues or Issue Description

**What happened?**

The task composer truncated the assignee name at 6rem and the complete
assignee and model capsule at 16rem. It did this even when the composer
had more available space.

**Expected behavior**

The composer must show the complete assignee and model labels when they
fit. It must use an ellipsis only when another control or a narrow
viewport limits the available width.

**Steps to reproduce**

1. Open a task composer with a long assignee name and a long model name.
2. Use a wide desktop layout.
3. Observe that the old capsule shortened both labels while unused space
remained.

**Paperclip version or commit**

Current `master` before this change.

**Deployment mode**

Local dev (`pnpm dev`).

**Installation method**

Built from source.

**Agent adapter(s) involved**

Not adapter-specific. This is a core UI bug.

**Database mode**

Not database-related.

**Access context**

Board.

**Additional context**

The Storybook cases cover a wide composer and a narrow composer with
Plan mode.

## What Changed

- Removed the fixed maximum width from the assignee and model capsule.
- Removed the fixed maximum width from the assignee label.
- Kept overflow ellipsis behavior when the parent row has insufficient
space.
- Added stable label selectors and focused component coverage.
- Added Storybook cases for complete labels and Plan-mode truncation.

## Verification

- `pnpm --filter @paperclipai/plugin-sdk build`
- `pnpm --filter @paperclipai/ui typecheck`
- `vitest run
ui/src/components/task-chat/ComposerRunSettingsPicker.test.tsx`
- `node scripts/check-token-gates.mjs`
- Storybook production build under Node.js 24.20.0
- Captured and inspected the two new Storybook cases.
- The complete repository typecheck and build reach the Rust Runner
step. This local environment does not have `cargo`. Hosted CI supplies
the Rust toolchain.
- The repository test suite reaches workspace-runtime tests. This local
runner does not allow their required temporary home directories. Hosted
CI supplies a writable test home.

## Risks

- Low risk. The change only removes fixed width limits from one flex
item.
- A very narrow composer can still shorten both labels. This is the
intended fallback.
- The Storybook constrained case verifies that Plan mode and Send remain
usable.

> 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 GPT-5 through the Paperclip Codex runner. The run used
reasoning, tool use, code execution, browser automation, and image
inspection.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-03 12:39:18 -05:00
DottaandPaperclip cc67d4e1d8 fix: preserve steering and recover stopped task conversations (#15015)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - A task conversation must let a user guide a running agent and resume
stopped work.
> - The active run owns its input protocol, even when the user changes
the next model or effort.
> - Queue delivery waits for a provider receipt, which must be able to
persist during the request.
> - A stopped startup also needs a clear user action that passes normal
task admission.
> - This pull request fixes steering delivery, makes queue actions
immediate, and restores explicit continuation.
> - The benefit is a responsive conversation that can recover without
losing saved input.

## Linked Issues or Issue Description

**What happened?**

A queued message could change from Steer to Interrupt while a native run
prepared. A steer request could wait on its own database lock and fail
to deliver. A stopped startup could then leave the conversation without
a working Retry or message continuation. Interrupt also waited for the
server and showed a toast.

**Expected behavior**

The active run keeps its input protocol. Steer delivers input to that
run. Steer and Interrupt clear the submitted queue rows and show the
input in the conversation immediately. Failed delivery restores the
latest queue with an inline error. An eligible stopped run offers Retry,
and authenticated user input can start a fresh turn through normal task
admission.

**Steps to reproduce**

1. Start a task with a native Paperclip Runner.
2. Change the selected model or effort while that run prepares.
3. Queue a message and press Steer.
4. Observe the provider receipt and queue state during the request.
5. Stop a startup before its provider process begins, then try Retry or
send a new message.
6. Repeat queued delivery with a legacy runner and press Interrupt.

**Paperclip version or commit**

Reproduced on the parent of this branch, `59c07ede7`.

**Deployment mode**

Authenticated private deployment. The fixes also cover local task
conversations.

Related work: Refs #12834, Refs #13354, Refs #13275. The open refactor
in #13160 moves the same queue route; it does not fix the receipt lock
or stopped-run continuation addressed here.

## What Changed

- Select queue behavior from the active run's immutable dispatch and
runtime resolution.
- Leave the run row unlocked during provider acknowledgement, then lock
and read it before merging the receipt.
- Retain queued input if the target run stops during that wait. Keep
inline delivery errors visible after empty queue updates.
- Permit exact Retry and authenticated continuation after verified
native startup cancellation. Preserve pause, approval, budget,
ownership, and process-stop gates.
- Carry undelivered native queue input into a fresh turn once the old
execution is confirmed stopped.
- Show Steer and Interrupt input in the conversation and clear submitted
composer rows immediately. Restore the latest queue inline on failure.
Remove delivery toasts.
- Keep optimistic delivery stable across stale polls, empty queues, and
paginated history. Preserve classic Interrupt error handling.
- Document recovery and optimistic delivery behavior. Add regression
tests across server, shared queue projection, and UI boundaries.

## Verification

- Red-green regression tests reproduced the queue protocol, receipt
lock, stopped-startup continuation, and optimistic delivery failures.
- The focused server route, continuation, queue, and runner boundary
suites passed during implementation.
- The queue-route suite passes with 78 tests. The three complete
conversation UI suites pass with 347 tests.
- UI typecheck, production build, and `pnpm check:token-gates` pass.
- Workspace `pnpm -r typecheck` and `pnpm build` pass. The local
monolithic `pnpm test:run` is still running; remote CI verifies the
complete suite on the latest commit.
- All CI gates pass on `bd9031ad56abfcde13d13a13488c1b9217c2fd3a`,
including the full test shards, runner verification, browser E2E,
typecheck, release registry, and canary dry run.
- Greptile reports 5/5 for that commit. Both review threads are
resolved.

## Risks

This changes queue display and explicit continuation admission. The UI
must restore rejected delivery without losing other-session edits. The
server must preserve concurrent provider result updates and must not
resume a process whose stop is uncertain. Focused tests cover these
boundaries. This change has no database migration.

## Model Used

OpenAI Codex, an agent based on GPT-6. The exact runtime model ID and
context window are not exposed in this session. Used reasoning,
repository tools, code execution, and browser inspection.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-02 22:07:14 -05:00
59c07ede72 fix(ui): let a selected saved subscription be used without a tile click (#14996)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - A user creates an agent in the New Agent flow and connects a model
provider in the model step.
> - When a saved subscription exists, the step shows it as the selected
default and labels the primary button "Use saved subscription".
> - The button stays disabled until the user clicks the provider tile,
which adds no auth step on this path.
> - This extra click is a papercut: the visible choice looks ready but
does not work.
> - This pull request lets a selected saved subscription enable the
button without the tile click.
> - The benefit is one less confusing step, with no change to new
sign-ins or API keys.

## Linked Issues or Issue Description

No public issue exists. The description follows the bug template.

**What happened**
In New Agent > Connect model, choose a provider that has a saved
subscription (for example OpenAI with a saved default). The saved
subscription shows as selected and the primary button reads "Use saved
subscription". The button stays disabled until you click the provider
tile.

**Expected behavior**
The button is enabled when a saved subscription is selected. A click on
it reuses that subscription.

**Steps to reproduce**
1. Have a saved OpenAI subscription.
2. Open New Agent and go to the model connection step for a Codex agent.
3. Do not click the OpenAI Subscription tile.
4. See that "Use saved subscription" is disabled.

**Paperclip version or commit**
master at `4abff286c`.

## What Changed

- `AgentProviderConnection.tsx`: the `!opened` gate on the footer
primary button no longer applies when `method === "subscription"` and a
saved subscription is selected. All other disabled conditions stay
(pending auth, loading saved keys, login readiness, API key input).
- `connect()` never reads `opened`, so no auth step is skipped. New
sign-ins and API keys still require the user to open the provider tile.
- `AgentProviderConnection.test.tsx`: a regression test that renders the
initial state (tile not opened, saved subscription selected) and expects
the button to be enabled and to connect with the saved subscription. A
guard test checks that a new sign-in still requires opening the tile.

## Verification

- `cd ui && npx vitest run src/components/new-agent
src/components/ai-connections --no-file-parallelism`: 6 files, 64/64
tests pass.
- The new regression test fails on master and passes with this change.
- `pnpm --filter @paperclipai/ui typecheck`: 0 errors.
- `node scripts/check-token-gates.mjs`: all gates clean.
- Component QA in Storybook (real component, provider verification
simulated): before, the button is disabled and skipped by Tab until the
tile click. After, a direct click and Tab+Enter both connect, with
exactly one verification callback. Selecting a new subscription still
requires opening the tile.
- Full-app before/after QA with a disposable empty backend and a
simulated provider response: same result.
- Not tested: a live OpenAI sign-in. Repo-wide `pnpm -r typecheck`,
`pnpm test:run` and `pnpm build` are left to CI.

Manual check: open New Agent with a saved subscription, go to the model
step, and click "Use saved subscription" without clicking the tile.

## Risks

- Low risk. The change is one condition in one component.
- If a future change makes `connect()` depend on the tile being opened
for saved subscriptions, this path would skip that work. The comment at
the condition records why the gate is skipped.
- Open PR #14698 edits nearby lines in the same component. A small merge
conflict is possible.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, via Claude Code with
tool use (shell, file edit, browser automation). Extended reasoning on.

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

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

Co-authored-by: scotttong <squadbot000@users.noreply.github.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-02 17:19:45 -07:00
DottaandPaperclip d7bdfc422c fix(ui): show agent avatar and align chat header controls (#14726)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - Agent chat shows which agent receives each message.
> - The chat header used initials instead of the agent avatar.
> - The name and controls did not use the same center alignment.
> - This change uses the shared avatar and centers the header content.
> - Users can identify the agent and open its settings from the same
row.

## Linked Issues or Issue Description

**What happened?**
The agent chat header showed initials instead of the agent avatar. The
settings control did not align with the name and avatar.

**Expected behavior**
Show the agent avatar. Put the avatar, name, and settings control on the
same horizontal center line.

**Steps to reproduce**
1. Enable Agent Chat in Experimental settings.
2. Open a conversation with an agent that has an appearance set.
3. Check the avatar and settings control in the top bar.

Related navigation work: #14706.

## What Changed

- Use `AgentAvatar` in the conversation breadcrumb.
- Update the breadcrumb key when the agent appearance changes.
- Center breadcrumb labels that have an adjacent action. Keep task
identifier baseline alignment unchanged.
- Add regression checks for avatar props, appearance changes, and center
alignment.

## Verification

- PASS: affected Vitest suites, 129 tests.
- PASS: `pnpm check:token-gates`.
- PASS: `pnpm --filter @paperclipai/ui typecheck` on an isolated retry.
- PASS: `pnpm --filter @paperclipai/ui build`.
- PASS: browser checks at 1000 and 390 CSS pixels. Avatar, name, and
settings control all have center Y = 29.5 CSS pixels.
- Screenshots use the real header and avatar renderer with isolated
context fixtures. No screenshot or fixture is part of this diff.
- Full typecheck and build cannot complete because Cargo is not
installed.
- Full tests stopped with SIGKILL. The first UI typecheck also stopped
with exit 137. These runs do not prove full-suite success.

## Risks

- Low risk. The change only affects UI rendering. It changes no API or
database contract.
- Breadcrumbs with adjacent actions now use center alignment. Ordinary
task identifiers keep baseline alignment.

## Model Used

OpenAI Codex agent, with code editing, shell tools, and browser checks.
The runtime did not expose the exact 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)
- [ ] 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

No behavior or command documentation needs an update for this rendering
fix. The execution environment requires the assigned branch name to stay
unchanged. Pending review gates are not marked complete.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-02 22:06:50 +00:00
abderrahmen bejaouiandabderbj 92ad158ce1 fix(claude-local): order Claude models the way the Claude app does (#14917)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Each agent runs on an adapter, and the operator picks the agent's
model from a list the adapter advertises.
> - The `claude_local` adapter advertises a static list and merges in
the models the Anthropic API returns. Neither list has a deliberate
order.
> - The model dropdown then sorts every list by id. For Claude this
shows "Fable 5", "Fable 5.1", "Haiku 4.5", "Mythos 5", "Opus 4.6" ...
which is not the order of capability, release, or version (#14877).
> - This pull request gives the adapter one defined order, the one the
Claude app uses: the newest release of each family first, by decreasing
capability, then older releases grouped by family. The server applies it
to discovered models, and the dropdown keeps the adapter's order instead
of re-sorting.
> - The benefit is that a user who knows the Claude app finds the right
model at once, and older models sit at the end of the list.

## Linked Issues or Issue Description

Fixes #14877.

Related: #14147 touches the same adapter's model list (the
`ANTHROPIC_MODEL` default label) and does not change ordering. #14878 is
the Codex counterpart and depends on the dropdown change in this PR.

## What Changed

- `packages/adapters/claude-local/src/server/model-order.ts` (new):
`sortClaudeModels()` and `parseClaudeModelId()`. The parser reads the
current scheme (`claude-opus-4-8`), the legacy scheme
(`claude-3-7-sonnet-20250219`), dated snapshots, `-latest` aliases, the
`[1m]` suffix, and Bedrock ids (`us.anthropic.…-v1`, `…-v2:0`). The sort
puts the newest release of each family first (Fable, Mythos, Opus,
Sonnet, Haiku), then older releases grouped by family with versions
descending. An alias sorts before its dated snapshots, and dated
snapshots of one release sort newest first. Ids that are not Claude
models keep their incoming order at the end.
- `packages/adapters/claude-local/src/server/models.ts`: apply the order
to the static fallback, to the merged API list, and to the Bedrock list.
Reorder `BEDROCK_MODELS` to match.
- `packages/adapters/claude-local/src/index.ts`: reorder the advertised
`models` list to the same order.
- `ui/src/components/AgentConfigForm.tsx`: `ModelDropdown` gets a
`preserveOrder` prop. With it the dropdown shows the list as the adapter
ordered it; without it the list is sorted by id as before.
`ui/src/lib/model-utils.ts` adds `adapterCuratesModelOrder()`, true for
the built-in adapters whose list arrives in a deliberate order
(`claude_local`, `codex_local`, `paperclip_runner`, `gemini_local`,
`grok_local`, `kimi_local`, `openclaw_gateway`, and `opencode_local` /
`pi_local`, which the server sorts when discovered and which lead with
the default model when it falls back to the declared list). Cursor is
not in the set because its list comes from `agent models` discovery, and
adapters not named there, including externally installed ones, keep the
alphabetical fallback. The three dropdown call sites (`AgentConfigForm`,
`ConfigureBuiltInAgentModal`, `NewAgentSetup`) pass it; `NewAgentSetup`
decides by the resolved brand type, because a `paperclip_runner` agent
fetches the Claude or Codex list for its brand. Grouped lists
(`opencode_local`, `pi_local`) are unchanged.
- Tests: `model-order.test.ts` (adapter, including the snapshot-date
tie-breaker), `ModelDropdown.test.tsx` (ui: preserved order with the
prop, alphabetical without it, provider groups unchanged),
`model-utils.test.ts` (which adapters opt in), and two updated
expectations plus one new order assertion in
`server/src/__tests__/adapter-models.test.ts`.

Mythos is not in the Claude app's list. This PR ranks it directly after
Fable, in the top capability tier. The rank table in `model-order.ts` is
one line to change if you prefer a different slot.

## Verification

Run from the repository root:

```sh
pnpm exec vitest run packages/adapters/claude-local server/src/__tests__/adapter-models.test.ts ui/src/lib/model-utils.test.ts ui/src/components/ModelDropdown.test.tsx ui/src/components/AgentConfigForm.render.test.tsx ui/src/components/ConfigureBuiltInAgentModal.test.tsx ui/src/pages/NewAgent.test.tsx
pnpm --filter @paperclipai/adapter-claude-local typecheck
pnpm --filter @paperclipai/ui typecheck
pnpm --filter @paperclipai/server typecheck
pnpm check:module-boundaries && pnpm check:token-gates && pnpm check:tokens
```

Red on `master`, green here:

- `ModelDropdown.test.tsx` fails against the unmodified dropdown because
the ids come back sorted alphabetically even with `preserveOrder`.
- `adapter-models.test.ts` fails against the unmodified adapter because
the first model is `claude-opus-4-8`, not `claude-fable-5-1`.

Manual check: open an agent that uses `claude_local`, open the model
dropdown. With no `ANTHROPIC_API_KEY` the list reads Fable 5.1, Mythos
5, Opus 5.5, Sonnet 5, Haiku 4.5, Fable 5, Opus 5, Opus 4.8, Opus 4.7,
Opus 4.6, Sonnet 4.6, Sonnet 4.5. With a key, the discovered models slot
into the same order.

## Risks

- The other built-in adapters in the set (Gemini with `Auto` first,
Grok, Kimi, OpenClaw, the runner's Codex list, and the OpenCode and Pi
lists in the built-in-agent modal) are now shown as their adapter
delivers them instead of alphabetized. Cursor's discovered list and
every adapter outside the set, including externally installed ones, keep
the alphabetical order they had, so no option moves between refreshes.
Grouped lists are unchanged.
- The first entry of the Claude list changes from Opus 4.8 to Fable 5.1.
Nothing reads the first entry as a default: `DEFAULT_CLAUDE_LOCAL_MODEL`
is `claude-opus-5` and is resolved separately.
- No API, schema, or migration change.

## Model Used

Anthropic Claude Fable 5.1 (`claude-fable-5-1`) through Claude Code,
extended thinking on, with tool use for reading the repository, running
vitest and tsc, and editing files. The account holder reviewed the
change and owns the commit.

## 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: abderbj <115119179+abderbj@users.noreply.github.com>
2026-10-02 13:24:04 -07:00
Devin FoleyandPaperclip 144083fd48 fix(interactions): wait for workspace readiness before enabling approval (#14893)
## Thinking Path

> - Paperclip lets people manage AI agents and review their work.
> - Task confirmations must use the work produced by their source run.
> - The server blocks approval while that run still needs to sync its
workspace.
> - The card currently enables approval before that check can pass, so
an ordinary click produces an error.
> - This PR exposes the existing readiness check and shows “Preparing
approval…” with acceptance disabled.
> - The card refreshes itself and enables approval when the source
workspace settles.

## Linked Issues or Issue Description

**What happened?**

A confirmation appears while its source run is still preparing or
syncing its workspace. Its enabled approval button returns a conflict
asking the user to retry after syncing.

**Steps to reproduce**

1. Run an agent in an isolated workspace.
2. Have it create a confirmation before workspace finalization
completes.
3. Click the approval button while the source workspace is still active.

**Expected behavior**

The card explains that approval is preparing. Acceptance becomes
available automatically when the same server check permits it. Reject
and revise remain available.

Related work: #10770 handles this conflict after a click with retries.
#9520 proposes changing the workspace acceptance barrier. This PR
preserves that barrier and exposes readiness before the click, including
in compact task chat. It preserves the terminal-finalize behavior from
#10099.

## What Changed

- Add an optional, read-only `acceptanceBlocker` to interaction
responses. Readiness uses the existing source-run workspace predicate,
with one check per pending source run.
- Disable acceptance and show a shared preparation notice in classic and
compact confirmation cards, including checkbox and secret-binding
confirmations.
- Refresh preparing cards every two seconds in task detail, attention,
pipelines, and Skill Studio. Restore each surface's previous polling
cadence when preparation clears.
- Preserve live tool reviews, questions, rejection, revision, and the
server acceptance barrier. No automatic acceptance occurs.
- Document the preparation state and cover readiness, terminal sync
outcomes, unrelated runs, historical cards, and automatic refresh.

## Verification

- Focused service, card, query-refresh, and helper tests: 217 passed
across five files.
- `pnpm -r typecheck`: passed.
- `pnpm build`: passed.
- `pnpm build-storybook`: passed.
- `pnpm check:token-gates`: passed.
- `pnpm test:run`: incomplete locally. Stopped after about 17 minutes
once it reproduced seven existing environment failures: two Slack tests
and two email tests lack ancestor-directory skill fixtures; three
company-skills tests fail on macOS runtime-cache staging permissions.
These are outside this change. The full CI test matrix passed.
- CI: all 53 checks passed; two optional Storybook jobs were skipped.
The branch has no conflicts with `master`.
- Greptile: 5/5 on commit `8a6f216d8d`, with no review threads.
- Reviewed added lines and new files for credentials, private URLs,
internal task references, user paths, and run artifacts. None found.

## Risks

- No database migration or change to acceptance authorization. Readiness
is advisory; the server still enforces its existing gate at acceptance.
- An open preparing card adds a read every two seconds. This cadence
stops after readiness clears; historical cards add no workspace checks.
- Failed or stale finalization retains the existing server behavior.
This PR does not change recovery policy.

## Model Used

OpenAI GPT-6 through Codex. The exact serving model ID and
context-window size are not exposed in this session. Used reasoning,
repository inspection, tool execution, and automated tests. No
sub-agents.

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-02 13:08:25 -07:00
DottaandPaperclip 7a52dcdc74 fix: repair MCP validation and cancelled execution recovery (#14951)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The tool gateway gives agents access to connected services. Recovery
controls what happens when a run stops.
> - Generated tool names can exceed the provider limit after the MCP
client adds its prefix.
> - The same invalid definition can fail each automatic retry. A
cancelled run can also hold saved messages without showing its cause.
> - This pull request bounds tool names, stops configuration retries,
and retains cancellation evidence.
> - It shows the stopped run and admits saved input only after the
existing safety checks pass.
> - The benefit is a clear recovery path that preserves operator Stop
and prevents duplicate message delivery.

## Linked Issues or Issue Description

**What happened?**

A long connected MCP tool name makes the provider reject the entire
request. Automatic recovery repeats the invalid request. Separately,
unexpected legacy cancellations can leave saved input behind a recovery
hold. The notice does not identify the stopped run or its cause.

**Expected behavior**

Complete MCP names fit the provider limit. Tool-definition errors
require configuration repair. Cancelled runs retain their source and
reason. The recovery notice shows the cause and saved-message count.
Verified unexpected cancellations can start a fresh turn through the
existing admission checks.

**Steps to reproduce**

1. Assign an App gallery connection with a long application key and tool
name to a Claude agent.
2. Start a run. The provider rejects a name over 128 characters,
including its MCP prefix.
3. For cancellation recovery, stop a legacy provider turn without an
operator Stop request and send a user message while the recovery hold is
active.
4. Inspect the recovery notice and the deferred message queue.

**Paperclip version or commit**

Rebased onto master at `cf8ad63c806685bfd7c48e3ed4a919d61a7c55f1`.

**Deployment mode**

Hosted or self-hosted server with legacy Claude or Codex execution.

Related public work:

- Refs #14017. That PR caps name segments. This PR preserves existing
short names and uses stable hash aliases for long complete names. It
also covers classification and recovery.
- Refs #4510. That PR adds a cancellation-source column. This PR records
bounded evidence in the existing run result, without a migration.
- Refs #12552 and #4506. Those PRs suppress recovery after operator
cancellation. This PR preserves operator intent and uses the existing
continuation gates.

## What Changed

- Bound gateway names with the full provider prefix in the 128-character
budget. Retain the original upstream tool name for dispatch and
permissions.
- Classify invalid tool definitions as configuration failures before
diagnostic redaction. Stop automatic retries and continuation attempts
for that error code.
- Persist cancellation source, expectedness, initiator, reason, and
time. Preserve recorded Stop intent when adapter results arrive. Report
unexpected started cancellations with closed diagnostic labels.
- Show the run cause, saved-message count, and Inspect run link. Offer
Continue for eligible unexpected cancellations. Require verified
provider stop, empty tool inventory, ownership, and the existing pause,
budget, approval, and dependency gates. Use the existing queue for
single delivery.
- Add regression coverage and update the execution, MCP gateway, and
run-log documentation.

## Verification

- `pnpm -r typecheck` and `pnpm build` passed.
- `pnpm check:token-gates` passed.
- Ran `pnpm test:run` and completed its workspace and serialized groups.
Initial resource and timing failures passed on isolated reruns. All 149
serialized route suites passed.
- Reran the changed server, adapter, and UI suites after the rebase.
Coverage includes long-name upstream dispatch, configuration retry
suppression, cancellation evidence retention, privacy labels, oversized
run projection, and concurrent saved-message delivery.
- `pnpm test:e2e tests/e2e/legacy-failure-continuation.spec.ts` passed
all six browser scenarios. The recovery notice shows the run cause and
inspection link, and each recovery entry point reaches one new response.
- Added database-backed checks for active, removed, paused, unavailable,
and disabled chat connections. The final continuation and
recovery-notice suites passed 167 tests. Externally bound chats hide
board Continue and show a usable next action.
- All 55 GitHub checks passed on
`42afbf1371dcaeb72646e3d8f65c19ff7cddf8de`. Two unrelated Storybook jobs
were skipped by their normal conditions. Greptile reviewed that commit
at 5/5 with no findings and no open review threads.

## Risks

- Long tool names change to aliases. Existing short names stay
compatible. The original connection and upstream name remain the
dispatch authority.
- Invalid tool definitions no longer get automatic retries. An operator
must repair the configuration before a new attempt.
- Continuation changes apply only to positively identified unexpected
legacy cancellations with complete empty tool inventory. Operator Stop,
unknown historical cancellations, outstanding tools, and unverified
provider termination keep their holds.
- No database migration. The added projection fields are optional.
Cancellation reason and initiator IDs remain local run evidence; Sentry
receives only closed source and initiator-type labels and expectedness.

## Model Used

- OpenAI GPT-6 through Codex, with reasoning, repository editing, shell
execution, and GitHub tool use. The runtime does not expose the exact
model variant or context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-02 13:47:59 -05:00
DottaandPaperclip 7d59de6113 feat(connections): probe provider usage limits on demand (#14936)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Connections store the AI accounts used by legacy and native runners.
> - Subscription accounts can reach session, weekly, model, or paid
usage limits.
> - Operators need to read these limits for a specific stored account
before making a routing decision.
> - This pull request adds an on-demand usage probe to the connection
service and account detail.
> - The result preserves provider limits, reset times, paid usage, and
unknown values for later consumers.

## Linked Issues or Issue Description

**Subsystem affected**

Shared contracts, the connection service and API, and the account detail
UI.

**Problem or motivation**

Managed AI accounts lack a common operation to read their current usage
limits. A local harness probe can read a different login from the
account selected for an agent.

**Proposed solution**

Add `aiConnectionService.probeUsage()` and a board-only connection usage
endpoint. Probe the selected credential grant on request. Support Codex,
Claude, and Grok subscriptions, plus OpenRouter API key limits.

**Alternatives considered**

Harness-specific automatic polling would couple the read to execution
and can read ambient credentials. This change uses the managed
connection credential and leaves scheduling and admission decisions to
later work.

**Roadmap alignment**

This extends the existing Personal & Shared AI Accounts capability. It
adds no routing or quota enforcement. Related: Refs #14459 for managed
OpenAI quota reads; Refs #14781 and Refs #13379 for downstream pacing
and budget work. This operation reads one requested account across all
three subscription providers.

## What Changed

- Add typed usage snapshots and a probe capability flag to managed AI
connections.
- Normalize Codex, Claude, Grok, and OpenRouter responses. Keep model
scopes, provider admission, reset periods, and paid allowances separate.
Preserve unknown values.
- Enforce company membership, credential audience, grant identity, and
connection lifecycle before reading the stored secret.
- Add a board-only `GET
/api/companies/:companyId/ai-connections/:connectionId/usage` endpoint
with `no-store` responses.
- Add manual **Check usage** and **Refresh** actions to account details.
Show compact usage bars, resets, admission and overage status; remove
repeated descriptions and account-default copy. Clear previous results
during a new request or error.
- Add Storybook previews using the production account components for all
four providers, initial checks, loading, and permission errors.
- Add provider, authorization, runner selection, API, and UI coverage.
Document provider sources and live qualification.

## Verification

- Initial provider, authorization, selection, API, and UI validation
passed (96 focused tests): `pnpm exec vitest run
server/src/services/ai-connection-usage.test.ts
server/src/__tests__/ai-connections.test.ts
ui/src/components/ai-connections/AiConnectionUsagePanel.test.tsx
server/src/__tests__/openapi-routes.test.ts`.
- `pnpm -r typecheck` passes for the initial implementation. After
simplifying the UI, 9 usage-panel and date-helper tests, UI typecheck,
token gates, and Storybook build pass. The initial feature module
boundary check also passed.
- Real Codex, Claude, and Grok credentials were saved to encrypted
disposable connections. The actual usage HTTP route returned 200 with
`status: ok`. Legacy and native runner selection checks passed. The
tests started no model turn and exchanged no refresh token. The
disposable databases and vaults were removed.
- Live Claude responses added structured scoped limits. Live Grok
responses omitted included-plan usage. Tests now cover both shapes and
preserve the Grok omission as unknown.
- The full workspace build passes. A full local test run hit a heartbeat
feedback timeout. That case passes in isolation. The duplicate local run
was stopped after all remote checks passed. The Slack ordering and
OpenCode transport CI flakes also pass in isolation and on the CI rerun.


- Current head: `ff3d479029a1c4248190323e221b2803cfb0d79d`. All 54
active checks pass. Two Storybook checks are intentionally skipped by
the workflow. Greptile is 5/5 with no unresolved review findings; the
branch is mergeable.

## Risks

- Subscription usage endpoints can change. Credentials can lack
usage-read permission. The probe returns explicit errors without fresh
limits in these cases.
- A successful probe can contain partial data. Missing utilization or
admission remains unknown. An enabled paid-usage switch does not prove a
funded balance.
- This change adds no migration. It does not change runner admission or
automatic provider selection. Provider requests use fixed endpoints,
disabled redirects, bounded response sizes, and a 15-second deadline.

## Model Used

OpenAI Codex, GPT-6, with reasoning, file editing, shell execution, and
HTTP tools. The session does not expose the exact runtime model variant
or context window size. Real provider credentials were used only for the
authorized live checks.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-02 11:47:14 -05:00
DottaandPaperclip 6c1a75da49 feat(connections): make AgentMail a default connection with inline setup (#14772)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Connections give agents access to external services.
> - AgentMail needs both a saved key and an inbox assigned to the agent.
> - Chat requests offered a setup link instead of an inline card and
could treat a saved key as complete.
> - Inbox setup also hid address conflicts behind a generic server error
and a separate review step.
> - This pull request makes AgentMail a default connection, adds the
inline card, reduces setup to two steps, and shows conflicts beside the
address.
> - Shared native dropdown styles also give every caret a consistent
inset.

## Linked Issues or Issue Description

**What happened?**

AgentMail requests in chat did not show a usable inline connection card.
Manual setup required extra screens, ignored saved account keys, and
could trap new-address setup in a locked inbox dropdown. Agent selectors
omitted the avatar from the selected value. A taken address could
produce an HTTP 403 from AgentMail and appear as an internal server
error. Native dropdown arrows also touched the right edge of their
fields.

**Expected behavior**

Make AgentMail available as a default connection. Ask for the API key
inline, with a direct link to its provider page. Default human access to
the company and agent access to the requesting agent. Resume the agent
only after an assigned inbox is active. Manual setup should ask for an
agent and email address, then finish. Address checks should run as the
user types. Taken addresses should show clickable alternatives. A domain
dropdown beside the name should prefer a verified custom domain. Setup
should suggest authorized saved AgentMail keys and show agent avatars in
the picker and selected value.

**Steps to reproduce**

1. Ask an agent to connect AgentMail when it has no assigned inbox.
2. Check that an inline API-key card appears and links to the provider's
API-key page.
3. Open AgentMail setup, choose an agent, and request an address that is
already taken.
4. Correct the inline error, refresh, and finish setup with the same
request ID.
5. Inspect native dropdown carets in light, dark, disabled, and
right-to-left states.

Uses the bounded provider-error parser merged in #14768. Related work:
#13256 introduced AgentMail; #14725 expanded connection search.

## What Changed

- Stop recurring email queries for tasks that have no email thread.
Share the query between the thread provider and activity view. Keep
email-task updates and invalidation-based discovery.
- Make AgentMail available without the experimental chat setting. Keep
the catalog, setup and management routes, agent Channels tab, task email
feed, receiving worker, and agent tools available by default. Other
experimental chat providers stay gated.

- Make the email address and copy icon a single clickable action with
the shared Copied! confirmation. Add View inbox linking directly to the
matching AgentMail console inbox, with the address encoded as one URL
path segment.

- Reorganize inbox Settings around the copyable email address, usage
instructions, and receiving status. Move reconnect credentials into a
disclosure and separate the Disconnect action. Add production Settings
stories for active, paused, unassigned-address, revoked, webhook,
long-address, mobile, and reconnect states. Show repair controls when
the inbox has an error. Keep usage instructions tied to an active inbox
with an address.

- Add AgentMail channel intents and an inline key field with the direct
API-key URL.
- Keep setup and retry state tied to the interaction. Require an active
inbox for completion. Preserve company and agent access checks.
- Reduce manual setup to agent selection and email selection. Put the
domain dropdown beside the address and default to a verified custom
domain. Preserve explicit choices across reloads. Keep receiving
settings under Advanced options.
- Check the initial address and edits after a 350 ms pause. Abort
superseded requests and ignore stale responses. Show clickable
suggestions and retain known creation conflicts across reloads.
- Add a company-scoped, manager-only address check using the saved
credential. Search the visible inbox list instead of fetching an
uncreated inbox: live AgentMail retains negative lookups that can break
subsequent access-key creation. Unlisted addresses remain unknown;
creation is authoritative.
- Suggest labeled saved AgentMail keys in both manual setup and the
inline card. Filter by company, provider, active credential, and
current-user grants on the server. Prefer an account key and preserve
the selected key or an explicit new-key choice across refresh. Use
verified scope metadata and bounded concurrent checks for legacy keys.
Never return secret values.
- Catch an inbox-only key before the email step. Allow its existing
inbox only after an explicit choice. Recover old locked drafts at the
key picker. Save the replacement key before retiring an empty draft,
then use a new setup URL so refresh preserves the switched account; stop
if cleanup fails. Preserve already allocated addresses and their
original accounts.
- Use the shared AgentSelect in email setup. Show the canonical agent
avatar in each option and the selected value, including other consumers
of the shared component. Add regression coverage for legacy and current
Lucide agent-mention icon formats.
- Start each catalog Add connection with a fresh setup identity. Honor
Finish setup's exact draft/account/address instead of resuming an
unrelated browser draft. Return Cancel and Done to Connectors and Email
settings to the inbox. Group the task/thread explanation in a How it
Works card.
- Route AgentMail catalog removal through the email inbox control API,
including unfinished drafts. Refresh both the catalog and inbox views.
- Render each inbox management tab separately. Access uses the saved
account grants and agent controls; Conversations and Activity use the
shared persisted email feed. Activity lifecycle actions use the email
API. Reconnect returns to inbox Settings. Conversation failures show a
retry instead of a false empty state. Email delivery recovery stays in
the task.
- Map documented provider address conflicts to a field error. Preserve
actionable messages for other failures.
- Preserve non-secret draft fields across refresh, scoped to the
requested agent. Never save API keys in browser storage. Resume partial
inbox creation with the original agent, address, and request ID.
- Show an already-created address with explicit retry and new-address
recovery instead of locked inputs. Preserve the original inbox and
resumable draft when choosing another address. Distinguish runtime-key
404 errors and log safe provider status/operation/code.
- Apply final agent access once within email setup authorization for a
new account whose original installs are unchanged. Preserve later
permission edits and reused account installs. Support in-place retry of
progress loading.
- Let a failed inline setup change keys after retiring an empty draft.
Persist its replacement setup identity without storing secrets. Recover
a server-saved account when refresh interrupts the save response, while
preserving intentional account changes.
- Render the production setup in Storybook and add error, recovery, and
mobile states.
- Inset native select carets in shared CSS. Preserve custom icons,
listboxes, keyboard behavior, and forced-color controls.
- Add browser regression coverage and an AgentMail Product E2E case with
persisted-state and rendered-card evidence.

## Verification

- Full `pnpm -r typecheck`, `pnpm build`, `pnpm check:token-gates`, and
`git diff --check` passed after the default-availability change.
- All 485 focused tests passed. These cover setup, management, catalog
and route gates, connection intents, email authorization, Cursor
execution, and the OpenAPI contract. All 39 email integration tests run
with the experimental chat setting off.
- The shared polling change passed four behavioral tests, UI typecheck
and build, and token gates.
- `tests/e2e/agentmail.spec.ts` passed with the actual server setting
off. This full-stack browser test uses simulated provider responses. It
covers catalog entry, saved keys, editable address and domain controls,
creation, conflicts, retry, all management tabs, clipboard feedback, the
provider link, and task email rendering.
- In the live local browser, Add connection reached the editable email
step with the saved account key. The verified custom domain was selected
by default. Both domain choices worked. The existing inbox Settings page
remained available. Both active inboxes completed new mail checks with
the setting off. No new provider inbox or email message was created for
this pass.
- Earlier live provider acceptance covered creation on a verified custom
domain, Finish connecting on the reported draft, successful mail checks
after refresh, and catalog removal of disposable draft and active
connections. Clicking the email address copied the exact address and
showed Copied!. View inbox opened the same inbox in AgentMail’s console.
No email messages were sent.
- Production setup and Settings Storybook builds and interactions
passed. Settings states include active, paused, unassigned, revoked,
webhook, long-address, mobile, and reconnect. Receiving and
revoked-access stories had zero accessibility violations.
- Full local `pnpm test:run` on an earlier revision completed with
14,709 passing, 87 skipped, and four transient failures. All four failed
cases passed in focused reruns without product changes. That serial full
local command was not repeated after each follow-up. The latest-head
full CI suite is the final test gate.
- CI found an obsolete browser assertion that hid every channel when the
flag was off. Updated it to keep AgentMail and the Channels surface
visible while preserving the GitHub chat route gates. All 11 provider
browser tests passed locally after scoping the Channels selector to the
agent sidebar. Two initial local attempts stopped at temporary Postgres
initialization. The passing run used a separate disposable database on
the existing local Postgres server; it was removed after the test.
- Updated the remaining sidebar and aggregator discovery assertions for
default AgentMail availability. Ordinary task fixtures now return no
email thread. All 128 sidebar/task-page tests and all 42 aggregator
tests passed locally.
- Latest head `b42bb4cd5cc9f2d01a99ab8026832d5a956ea85f`: full CI
passed, with 54 successful checks including Snyk and two intentional
Storybook skips. The CI run is
https://github.com/paperclipai/paperclip/actions/runs/37020833647. A
fresh Greptile review scored 5/5 with no unresolved threads. Live model
evaluations and inbound/outbound email delivery were not run.

## Risks

- AgentMail no longer needs experimental opt-in. Setup still requires a
human to connect an account and assign an inbox. Inline setup creates an
inbox after a human submits a new or saved key. Company access, agent
access, inbox assignment, and completion checks remain enforced.
- AgentMail read APIs cannot prove global address availability. The
visible-list check is bounded to 100 entries and cannot see inboxes
outside the key’s scope. The UI reports this limitation, suggests
alternatives without claiming they are free, and keeps final creation
conflicts inline. Lookup outages show an error without preventing the
authoritative creation attempt.
- Native select CSS affects the whole app. Custom-icon selects and
multi-row lists are excluded. Forced-color mode keeps the browser caret.
- Saved-key discovery uses stored verified scope metadata and checks
authorized legacy credentials concurrently within a shared three-second
deadline. Provider outages mark legacy choices unavailable; users can
still enter another key. Final use rechecks authorization and provider
access.
- No database migration or transport default change. Live connection
remains the default.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-02 10:01:15 -05:00
DottaandPaperclip ec3bacc9bd fix(chat): hide ignored provider information (#14929)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task and agent chats show agent progress and problems that need
attention.
> - Codex also sends account, skill, and unrelated thread notifications.
> - The runner correctly ignores that information but reports it as a
warning.
> - Chat then shows an internal diagnostic as an actionable provider
notice.
> - This pull request keeps the diagnostic in run logs and removes it
from chat.
> - Real provider warnings, errors, and agent replies remain visible.

## Linked Issues or Issue Description

**What happened?**

Chat showed “Received a provider update” and a warning with the text
“ignored
unrelated provider information”. Its details said “User Actionable: Yes”
even
though no user action was needed. Saved conversations retained the same
noise.

**Expected behavior**

Keep ignored provider information in the run log. Do not show it as chat
activity
or a user warning. Preserve real warnings and errors.

**Steps to reproduce**

1. Start a conversation with the native Codex runner.
2. Have the provider send an account update, skill change, or unrelated
thread
   notification during the turn.
3. Inspect live chat and reload its saved history.

The regression tests also reproduce the old stored notice without a live
account.

**Paperclip version or commit**

Source implementation on master at `e00d10d5d`. The duplicate search
found no
open PR for this fix. Related prior work: #13109 improved
provider-notice
presentation. #12367 added Codex thread normalization. This change
addresses
the internal information that those paths still projected as chat
warnings.

**Deployment mode**

Native Paperclip Runner with the Codex app-server provider. The issue
was seen
in hosted chat and can be reproduced with local provider fixtures.

## What Changed

- Map ignored unrelated Codex information to `harness.diagnostic` in the
Rust
  and TypeScript normalizers.
- Retain a bounded allowlist of redacted provider method and thread/turn
identifiers.
- Use the same Unicode character limit and truncation marker in both
normalizers.
- Share the text redactor through a pure helper. Keep provider
connection code
  out of the standalone demo's source closure.
- Omit that diagnostic and the matching legacy notice from live chat.
- Omit the matching legacy notice from saved chat history.
- Test diagnostic retention, account-notification integration, live and
saved
  chat, and continued visibility of real warnings, errors, and replies.
- Document the local run-log event and historical display behavior.

## Verification

- Passed: 68 tests in the two affected UI transcript suites.
- Passed: 60 TypeScript tests across provider events, transport
behavior, and
  the standalone demo boundary.
- Passed: 13 Rust provider-event tests and the Codex
account-notification
  integration test.
- Passed: `pnpm check:token-gates` and Cargo formatting checks.
- Passed: full `pnpm build` and `pnpm -r typecheck`. After the review
fix,
the provider package build, typecheck, and both provider-event suites
passed again.
- Full local `pnpm test:run` failed: 608 files / 10,904 tests passed, 30
server
suites failed, and 104 files / 4,012 tests were skipped. Most failures
were
  embedded PostgreSQL startup errors. Two tests timed out in
`heartbeat-comment-wake-batching` and
`workspace-git-snapshot-streaming`.
  PostgreSQL startup also failed in `heartbeat-run-event-sequencing` and
`native-finalization-migration`. These server files are unchanged by
this PR.
Isolated heartbeat reruns were skipped locally. The stable test script
stopped
  after this general-server group, so later groups did not run locally.
- The original review thread is resolved. Greptile is 5/5 on current
head
  `683dab7cce57187c57e84c83f5e9da4ad75c9c04`.
- All current-head CI gates passed, including the full
server/chat/workspace
test matrix, Rust and TypeScript runner suites, browser E2E, build,
typecheck,
and release canary. [CI
run](https://github.com/paperclipai/paperclip/actions/runs/37021330663).
- Replay the exact old warning in either transcript adapter. It must
produce
no chat row. A genuine provider warning or error must still produce a
row.

## Risks

- Low risk. The display filter matches one diagnostic code or the
complete
  legacy warning shape. Other provider notices remain visible.
- New ignored-information events use the existing harness-diagnostic
event
type. They retain diagnostic evidence without original account payloads.
- No database migration, API permission, provider execution, or recovery
  behavior changes. This affects the local run log, not Telemetry or
  OpenTelemetry exports.

## Model Used

OpenAI Codex, GPT-6. The exact backend model ID and context-window size
are
not exposed in this session. Used reasoning, repository inspection, code
editing, tool use, 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 the affected tests locally and they pass (the broad
local run has PostgreSQL startup errors and timeouts documented above;
the full CI matrix passed)
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-02 09:59:34 -05:00
DottaandPaperclip e00d10d5d5 fix(connections): repair stale AI defaults from agent settings (#14916)
## Thinking Path

> - Paperclip manages AI agents and controls the credentials used for
their work.
> - Managed AI connections resolve each responsible user's provider
default.
> - Agent settings created another account but kept the old default
selected.
> - A rejected provider test left the old account marked as connected.
> - Claude ACP reported a typed login failure as a generic
terminal-access error.
> - This pull request repairs the selected account or selects the new
login explicitly.
> - Agents can save and run with the repaired credential, and failed
logins request sign-in.

## Linked Issues or Issue Description

- Fixes #14831.
- Refs #13867. Environment failures remain separate from
credential-health failures.

## What Changed

- Add an agent-settings action to reconnect an unavailable personal
default in place. Keep its connection, grant, default, and agent access.
- State that a new account becomes the user's provider default. Select
its returned grant before changing the agent binding. Keep the actual
sign-in method.
- Show default-update errors and allow retry without another provider
login.
- Show the agent-access choice. Connection managers start with
company-wide access for their own tasks. Other members start with access
for the current agent.
- Use the server's connection-manager permission in the shared list
response. This includes members with a custom management grant.
- Mark credentials as needing attention after an explicit login
rejection in Test or Save. This includes API-key 401 and 403 responses.
Network, quota, and server failures keep the credential health
unchanged.
- Reuse the credential-generation check so an old failure cannot
invalidate a newer reconnect.
- Route Claude's typed provider `access` failure to the existing
login-recovery flow. Replace its generic terminal-access fallback with a
sign-in message.
- Add regression tests and update the AI Connections documentation.

## Verification

- Red: the UI tests failed on the missing reconnect action, unused
returned grant, missing access choice, and lost default-update error.
The server tests failed because rejected credentials stayed connected.
The real ACP fixture returned `acpx_turn_failed` for typed login
failures.
- Green: 156 tests passed across the AI connection, hiring, agent field,
and New Agent suites. All 37 environment-route tests passed. The Claude
ACP authentication fixtures also passed.
- `pnpm check:token-gates` passed.
- `pnpm -r typecheck` passed.
- `pnpm build` passed.
- The full local `pnpm test:run` passed 707 files and 14,503 tests, then
exited with an agent-conversation timeout and embedded PostgreSQL
startup failures in unchanged suites. The isolated conversation and
migration tests passed on rerun. Later local test groups did not run
after this failure.
- [All CI gates
passed](https://github.com/paperclipai/paperclip/actions/runs/37012669356)
on commit `38513dfe2`. This includes the full test matrix, browser
tests, typecheck, build, Runner checks, and canary dry run.
- Greptile reviewed commit `38513dfe2` and returned 5/5 with no open
findings.
- The regression tests use a real embedded database and a real ACP
fixture process. Live provider sign-in requires a valid account and was
not run.

## Risks

- Connecting a new account from agent settings changes the user's
provider default. The dialog states this before sign-in.
- The displayed access choice can allow all company agents to use the
account for its owner's tasks. Reconnect keeps the existing access.
Server permissions still control installs.
- Claude's typed `access` category maps to the provider's
`auth_required` signal. Tool and workspace request failures retain their
existing classification.
- No database migration or provider credential format changes are
required.

## Model Used

- OpenAI GPT-6 through Codex. The exact served model identifier and
context window are not exposed in this session. Capabilities used:
reasoning, repository tools, code editing, and command execution.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-02 08:57:52 -05:00
Devin FoleyandPaperclip 4b2bd6563d fix(chat): hide obsolete execution status and system notices (#14874)
## Thinking Path

> - Paperclip lets people oversee agent work through task conversations.
> - Conversations should show failures and waits that still affect the
task.
> - Old run errors and recovery notices remained visible after later
work or task completion.
> - These messages looked current even when no action remained.
> - This change hides obsolete execution status while preserving the
responses and activity.
> - The full diagnostic record stays available in run history.

## Linked Issues or Issue Description

**What happened?**

Task chat kept showing “Run failed”, “Stopped”, and “Waiting to resume”
after the execution had been superseded or the task had finished. Stored
system notices also remained in the conversation. Completed tasks
disabled Retry but kept the error message.

**Expected behavior**

Hide system status that no longer applies. Keep the latest unresolved
failure, active recovery holds, and useful recovery actions visible.
Preserve messages, files, questions, session boundaries, and inspectable
activity.

**Steps to reproduce**

1. Let a task run fail, then record a pre-start recovery wait.
2. Complete a later attempt or mark the task done.
3. Open the task conversation. Before this change, the old error and
wait remain visible.

**Paperclip version or commit**

Reproduced in component tests against `0f9e9be408`.

**Deployment mode**

Task chat in local or hosted deployments; both legacy adapters and the
native runner.

Related: #14857 and #14869 address execution recovery. This PR addresses
the remaining conversation presentation. Searched GitHub for historical
chat status, historical errors, and “Waiting to resume”; no duplicate PR
found.

## What Changed

- Determine status relevance from task state, attempt order, successor
evidence, and recovery state. Time alone does not hide errors.
- Hide obsolete run markers and stored execution notices. Require run or
recovery provenance, so unrelated system updates such as child-task
blockers remain visible. Keep errors from the latest failed attempt
actionable.
- Keep unresolved execution holds visible. A refused pre-start retry
does not replace a real attempt, and another agent’s work does not
resolve a run-specific error.
- Show historical activity without Worked/Stopped labels. Keep
historical failures out of the current turn’s summary.
- Anchor activity to visible comments so removing a notice cannot remove
the response or activity with it.
- Document the presentation rules and cover both runner modes and both
task presentation modes.

## Verification

- 334 focused component and status-policy tests passed across four
files, including the child-task relay regressions.
- `pnpm build` passed. The UI build also passed after the final
presentation changes.
- `pnpm exec vitest run --project @paperclipai/ui`: 667 files and 7,157
tests passed. Subsequent focused tests cover the final activity-anchor,
live-successor, and notice-provenance changes.
- `pnpm -r typecheck` passed. UI typecheck and build passed again after
the review fix.
- `pnpm test:run` completed its general-server phase with 14,716 tests
passed, 17 failed, and 87 skipped; it stopped before later phases. The
failures occurred in four unchanged server suites: chat channels, email
channels, company skills, and runtime skill cache. A targeted rerun
reproduced missing bundled skill paths and `EACCES` during
cache-directory rename on macOS. All Linux CI suites pass for the final
commit, including these server suites.
- Design token gates and diff checks pass.
- All 53 checks pass on commit `7af9753859`; two optional Storybook
checks are skipped. [Final CI
run](https://github.com/paperclipai/paperclip/actions/runs/36931968751)
includes build, full typecheck, all server and workspace test shards,
all eight end-to-end shards, runner verification, and the canary dry
run.
- Greptile scores the final commit at 5/5. No review threads remain
unresolved. The branch is current with `master` and has no merge
conflicts.

## Risks

This changes presentation only. It does not change execution, recovery,
stored comments, or run history. The main risk is hiding a current
diagnostic too early. Tests cover active holds, refused retries,
different agents, missing timestamps and provenance, live successors,
preserved responses, and the current retry target.

The base branch has a dependency override/lockfile mismatch. Local
installation used the same resolution fallback as CI, then restored the
tracked lockfile. No dependency changes are included.

## Model Used

OpenAI Codex (GPT-6). The exact runtime model identifier and context
window are not exposed in this session. Used reasoning, repository
inspection, code execution, and regression tests.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-01 15:18:47 -07:00
DottaandPaperclip efc2e6810e fix: show each task once in dashboard agent cards (#14847)
## Thinking Path

> - Paperclip helps people manage AI agents and their tasks.
> - The dashboard shows recent agent activity in compact cards.
> - Those cards use run records, so two runs for one task can create
duplicate task cards.
> - An operator needs to see each task once when scanning the dashboard.
> - This pull request selects one run per linked task before it applies
the card limit.
> - The live runs page still shows each run for run inspection.

## Linked Issues or Issue Description

**What happened?**

The dashboard showed the same task in two agent cards when that task had
both an active run and a completed run.

**Expected behavior**

The dashboard should show a linked task at most once. It should keep the
active run card when one is present.

**Steps to reproduce**

1. Start an agent run for a task that already has a completed run.
2. Open the company dashboard.
3. Observe two cards linked to the same task.

**Paperclip version or commit**

Reproduced on the pre-change master at `8b4aa0692`.

**Deployment mode**

Local dev, built from source. The bug is in the core dashboard UI and
does not depend on an agent adapter or database mode.

## What Changed

- Select distinct linked tasks from capped active and recent run samples
before applying the dashboard card limit.
- Keep separate cards for runs without a linked task.
- Preserve the dashboard's count of additional distinct cards behind the
live-runs link.
- Add UI and embedded Postgres regression tests for duplicate runs and
document the dashboard rule.
- Give the existing multi-request cross-tenant authorization test enough
time on loaded CI runners.

## Verification

- `pnpm --filter @paperclipai/ui exec vitest run
src/components/ActiveAgentsPanel.test.tsx`
- `pnpm --filter @paperclipai/ui exec vitest run
src/api/heartbeats.test.ts`
- `pnpm exec vitest run server/src/__tests__/dashboard-service.test.ts
server/src/__tests__/agent-live-run-routes.test.ts`
- `pnpm exec vitest run
server/src/__tests__/agent-cross-tenant-authz-routes.test.ts`
- `pnpm --filter @paperclipai/ui typecheck`
- `pnpm --filter @paperclipai/server typecheck`
- `pnpm --filter @paperclipai/ui build`
- `pnpm -r typecheck`
- `pnpm build`
- `pnpm check:token-gates`
- Review the dashboard with an active and a completed run on the same
task. Confirm that it shows one card. Open Live agent runs to inspect
both run records.

## Risks

- A very high volume of recent runs for one task can fill the capped
sample and leave older tasks off the dashboard. The Live runs page
remains available for full run inspection.
- The dashboard may fetch up to 50 distinct run representatives to
preserve its overflow count. The default run API response and persisted
data are 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-6. The runtime does not expose the exact model ID or
context window size to this task. The model used reasoning, tool calls,
and code execution.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-01 12:18:35 -05:00
DottaandPaperclip 527e146980 feat(ui): share animated agent setup prompts (#14862)
Use the shared animated prompt-copy control across setup, invitations, webhooks, and task handoffs. Preserve first-click copying, clipboard recovery, and logo continuity. Add Storybook coverage and restore mention icon masks for the current Lucide data shape.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-01 11:46:14 -05:00
842efe0181 fix(ui): stack project field save indicator below its label (#14765)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The web UI has a project detail page. A properties panel on that
page lets a user edit the project name, description, and other fields.
> - Each field shows a "Saving...", "Saved", or "Failed" indicator while
an edit is in progress.
> - The indicator was rendered next to the label text in a fixed 80px
label column. The "Description" label almost fills that column, so the
indicator spilled into the value column and covered the description
text.
> - A user cannot read the description while the indicator is visible.
This looks broken and it hides content.
> - This pull request stacks the indicator directly below the label
text, so it stays inside the label column.
> - The benefit is that the indicator never covers the field value, for
the description and for every other labelled field.

## Linked Issues or Issue Description

No public GitHub issue exists for this bug. The issue is described here.

**What happened?**

When a user edits a project description in the project properties panel,
the "Saving..." and "Saved" indicator appears next to the "Description"
label. The label column is 80px wide. The indicator does not fit, so it
overflows into the value column and overlaps the description text.

**Expected behavior**

The "Saving..." / "Saved" / "Failed" indicator must appear directly
below the "Description" label. It must not overlap the description text
or any other field value.

**Steps to reproduce**

1. Open a project in the Paperclip web UI.
2. Click the Description field in the properties panel and change the
text.
3. Click outside the field to save.
4. Look at the "Description" label while the "Saving..." and then
"Saved" indicator is visible. The indicator overlaps the description
text.

**Paperclip version or commit**

master at `5edf55d7350c7f08c9dd132c7e0f1421fa0bf2fb`.

**Deployment mode**

Local development (`pnpm dev`). The bug is in the UI layout, so it
applies to every deployment mode.

## What Changed

- `ui/src/components/ProjectProperties.tsx`: `FieldLabel` now renders
the label text and the `SaveIndicator` in a vertical flex column
(`flex-col`) instead of a horizontal row. The indicator sits directly
below the label and stays inside the 80px label column. This applies to
every labelled property row (Name, Description, Env, and so on), so no
label can overflow.
- `ui/src/components/ProjectProperties.save-indicator.test.tsx`: new
regression test. It asserts that the indicator is a stacked sibling
under the Description label for the `saving` and `saved` states, and
that no indicator renders for the `idle` state.

## Verification

- Run `pnpm --filter @paperclipai/ui exec vitest run
src/components/ProjectProperties` from the repo root. All
ProjectProperties tests pass, including the new save-indicator test.
- The new test fails against the previous inline layout (2 of 3 cases
fail) and passes with this change (3 of 3 cases pass).
- The existing `ProjectProperties.concurrency`,
`ProjectProperties.managed-sandbox`, and `ProjectDetail` tests pass (18
tests).
- `tsc -b` in `ui/` reports no errors in the changed files.
- Manual check: open a project, edit the description, and save. The
"Saving..." and "Saved" indicator now appears below the "Description"
label and does not cover the description text.

## Risks

- Low risk. The change is a single flex-direction swap on the label
wrapper in one component.
- Every labelled row in the project properties panel gets a slightly
taller label cell while an indicator is visible. This is intentional and
it matches the requested layout.
- No data, API, or migration changes.

## Model Used

- Claude Fable 5.1 (Anthropic), model id `claude-fable-5-1`, with
extended thinking and tool use, run through Claude Code inside a
Paperclip agent session. A human reviewed the change and the pull
request text.

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

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

Co-authored-by: Bender (Fable) <bender@paperclip.local>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-30 18:34:41 -07:00
d6fa1fd1ef feat(ui): streamline account menu profile access and add Invite shortcut (#14480)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Humans work in teams, so Paperclip has a multi-user system with
logins, profiles, and a company sidebar.
> - The account menu in the lower-left corner of the sidebar is the main
entry point for a user's own settings.
> - The account menu spent half of its rows on "View profile" and "Edit
profile". Users open these rows rarely.
> - The account menu had no fast path to invite a new member. The invite
flow is different on a self-hosted instance and on Paperclip Cloud.
> - This pull request removes the two profile rows, makes the header a
link to the profile, adds an "Edit profile" button on the profile page,
and adds an "Invite" row.
> - The benefit is a shorter account menu that keeps profile access and
gives users with the invite permission a one-click path to invite
people.

## Linked Issues or Issue Description

No public GitHub issue exists for this change. The description below
follows the enhancement template.

Refs #14060. That earlier pull request holds the first two commits and
the first Greptile review. It closed when the branch got a new name to
remove an internal ticket id. All Greptile findings from both reviews
are fixed in this branch.

**What existing behavior does this improve?**

The account menu in the sidebar (`SidebarAccountMenu` and its
`.production` variant) and the user profile page at `/u/:userSlug`.

**Subsystem affected**

ui/ — React + Vite board UI

**Current behavior**

The account menu shows the user's picture and name at the top. Below
them, the menu shows "View profile" and "Edit profile" rows, then the
other rows. The header is not a link. The menu has no row to invite
people. On a self-hosted instance, the user must open Company settings,
then Members, then the Invites tab. On Paperclip Cloud, the user must
open the Members page and use the Cloud People link there.

**Proposed behavior**

The account menu does not show "View profile" or "Edit profile". The
picture and name at the top of the menu are a link to the user's own
profile page. The profile page shows an "Edit profile" button when the
viewer looks at their own profile. The account menu shows an "Invite"
row with the same `UserPlus` icon as the company menu. On a self-hosted
instance, the row opens the Members page on the Invites tab, and shows
only to boards that hold the `users:invite` grant (company owners and
admins, instance admins, and local boards). On Paperclip Cloud, the row
opens the People settings for the current stack, and shows only to the
owner or admin of the stack, the same rule the Members page uses.

**Reason and benefit**

Users open their profile rarely, but the two rows took half of the menu.
Inviting people is a common task, but it needed three clicks and a
different path on Cloud. The new menu is shorter, keeps profile access
in one tap on the header, and gives one "Invite" entry point on both
hosting modes to the users who can invite.

**Breaking changes**

None. Routes, API responses, and settings keys do not change. The
profile page and the invite pages keep their current URLs.

## What Changed

- `SidebarAccountMenu.tsx` and `SidebarAccountMenu.production.tsx`:
remove the "View profile" and "Edit profile" rows. Make the picture and
name header a link to the user's profile. Add the "Invite" row after
"Settings" in the streamlined menu and first in the production menu.
- Header structure: `master` added a staging commit SHA link under the
email in the same header. The profile link is now a stretched overlay
behind the header content, so the SHA anchor sits beside the email and
the header has no nested anchors.
- `ui/src/lib/userProfileLinks.ts` (new): build the profile path from
the user id first. The profile endpoint treats the id as the one unique
slug, so two members with the same display name get different links.
Name and email are a fallback only when the session has no id.
- `ui/src/hooks/useCloudInviteUrl.ts` (new): read the Cloud stack
portfolio and return the People settings URL only when the current stack
role is owner or admin. This is the same rule as the Members page.
- `ui/src/hooks/useCompanyInviteAccess.ts` (new): read the current board
access snapshot and report whether the board may invite people to the
selected company on a self-hosted instance. Local boards and instance
admins pass. Other boards need an active owner or admin membership, the
roles that carry `users:invite`. This follows the same client-side gate
pattern as `ToolsAdminGate` and the run ledger. The server stays
authoritative.
- Invite row visibility: the row is hidden when the operator hides
`company.members` or `company.invites`, and until the health check
resolves. On self-hosted instances, the row is hidden until the board
access snapshot loads and when the board cannot invite. On Cloud, the
row is hidden when no People URL can be built. The in-app Invites tab is
never a fallback on Cloud, because it drives a different flow.
- `ui/src/pages/UserProfile.tsx`: add an "Edit profile" button that
links to `/company/settings/instance/profile`. The button shows only on
the viewer's own profile and follows the `instance.profile`
hidden-settings gate.
- Tests: extend `SidebarAccountMenu.test.tsx`; add
`userProfileLinks.test.ts`, `UserProfile.test.tsx`, and
`useCompanyInviteAccess.test.ts`.
- No documentation references the removed menu rows, so no docs change
is needed.

## Verification

Run the focused tests from the `ui/` directory:

```bash
pnpm vitest run src/components/SidebarAccountMenu.test.tsx src/hooks/useCompanyInviteAccess.test.ts src/lib/userProfileLinks.test.ts src/pages/UserProfile.test.tsx
```

- 52 tests pass in these four files. They cover the header link by user
id, the removed rows, the header overlay with no nested anchors, the
self-hosted invite target, the self-hosted permission gate (owner,
admin, instance admin, and local board see the row; an operator does
not, on both menu variants), the Cloud invite target with no
`target="_blank"`, the menu order, the hidden-settings gate on both
variants, the Cloud role gate (a plain member sees no row), the
no-fallback rule when Cloud stack metadata is missing, the staging
commit SHA link from `master`, and the own-profile-only "Edit profile"
button.
- `tsc -b` in `ui/` reports no errors in the changed files. The only
errors are pre-existing `@paperclipai/plugin-sdk/ui` resolution errors
in `PluginOrganizationSwitcher.tsx` from an unbuilt workspace package.

Manual steps:

1. Sign in and open the account menu in the lower-left corner. Confirm
the menu has no "View profile" or "Edit profile" rows.
2. Click your picture or name at the top of the menu. Confirm your
profile page opens and shows an "Edit profile" button.
3. Open another user's profile. Confirm the page shows no "Edit profile"
button.
4. On a self-hosted instance, as a company owner or admin, click
"Invite". Confirm the Members page opens on the Invites tab. As an
operator or viewer, confirm the menu shows no "Invite" row.
5. On Paperclip Cloud, as a stack owner or admin, click "Invite".
Confirm the Cloud People settings page opens in the same tab. As a plain
member, confirm the menu shows no "Invite" row.

## Risks

- Low risk. The change is limited to the UI and touches ten files.
- Users who know the "View profile" and "Edit profile" rows must learn
the new header link. The header has hover and focus styles to show that
it is a link.
- On self-hosted instances, the "Invite" row depends on the board access
snapshot from `/cli-auth/me`, which other gates in the UI already use. A
member with a custom `users:invite` grant but an operator or viewer role
does not see the row. That member can still use the Members page. The
row is a shortcut, not the only path.
- On Paperclip Cloud, the "Invite" row depends on the stack portfolio
query. When that query fails or the role is unknown, the menu hides the
row instead of sending the user to the wrong flow.
- Both menu variants change together, so a behavior difference between
them is not expected.

## Model Used

- Provider: Anthropic. Model: Claude Fable 5.1 (`claude-fable-5-1`).
- Run through Claude Code on the Claude Agent SDK inside a Paperclip
`claude_local` agent, with extended thinking and tool use (file edits,
shell, tests, GitHub API).
- The model wrote the code, the tests, and this description. A human
reviewed the pull request and requested the review fixes.

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

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

---------

Co-authored-by: Bender (Fable) <bender@paperclip.local>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com>
2026-09-30 16:18:59 -07:00
DottaandPaperclip 33f2b3a159 fix: separate GitHub tools and code review bot connections (#14750)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The Connectors catalog lets people give agents tools or connect
agents to conversations.
> - GitHub put these two uses behind one card and an extra choice.
> - People should choose the connection they need from the catalog.
> - This pull request keeps GitHub for tools and adds GitHub Code Review
Bot as a separate card.
> - Each card opens its setup directly. Both use the existing connection
code.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

GitHub connector discovery and setup.

**Current behavior**

With chat connectors enabled, GitHub opens a menu that asks whether to
use tools or create a bot. Saved tools and bots share the same catalog
entry.

**Proposed behavior**

GitHub opens tool account access. GitHub Code Review Bot opens agent
selection. Saved bots and drafts appear under the bot card.
Chat-disabled instances show only GitHub tools.

**Reason and benefit**

The catalog names the two uses and removes an extra setup choice. The
bot keeps the existing GitHub provider, credentials, endpoint IDs, setup
steps, and runtime.

**Additional context**

Related work: https://github.com/paperclipai/paperclip/pull/12843 and
https://github.com/paperclipai/paperclip/pull/14594 established GitHub
account identity. This change preserves that tool flow. No duplicate
catalog split was found.

## What Changed

- Split the generated app definitions into GitHub tools and GitHub Code
Review Bot. Reuse the existing GitHub logo and channel method.
- Open bot setup directly, including old resume and reconnect links.
- Put existing bot endpoints and drafts under the bot card. Hide
duplicate internal chat applications.
- Keep pasted GitHub URLs mapped to the tool connection.
- Add seven Storybook states for the catalog, saved connections,
disabled chat, both setup paths, mobile, and light mode.
- Fix narrow-screen bot rows so the label cannot overlap status and
setup actions.
- Update catalog, route, browser, and API tests, plus the GitHub
connector guide.

## Verification

- [Hosted
Storybook](https://d1p6rlowie26tp.cloudfront.net/storybook/branches/codex~2Fgithub-review-connection/?path=/story/connections-github-and-code-review-bot--catalog):
seven states built from this branch. The deployment passed its
public-file verification.
- All GitHub checks pass on `d13a2cd53561645bb2a15c6f8e75a61a936d6459`.
Two optional Storybook jobs skip under their normal trigger rules; the
manual Storybook deployment passes. The branch has no merge conflicts.
- Greptile: 5/5 on the current head, with no review comments or
unresolved threads.
- `pnpm -r typecheck`, `pnpm build`, `pnpm check:token-gates`, and `pnpm
build-storybook` passed. The final Storybook fixture also passed UI
typecheck and the hosted build.
- Targeted catalog, URL matching, routing, grouping, brand, and chat UI
contract tests passed.
- GitHub provider browser tests: 2 passed. These cover direct tool setup
and the bot setup and management lifecycle with provider responses
mocked.
- Embedded-browser test on an isolated local instance: opened both
cards, selected an agent, saved a bot draft, and resumed the same
endpoint under the bot card after a reload.
- Storybook Tool Setup and Bot Setup assertions pass in the published
preview. Chat Disabled assertions pass locally. Inspected mobile and
light mode, including the draft-row layout and official GitHub marks.
- Local full-suite limitation: `pnpm test:run` was not clean. A
cross-company route assertion failed in the aggregate run and passed in
isolation; a workspace-runtime test reached its 30-second hook timeout.
Some isolated database reruns skipped when the embedded-PostgreSQL
availability probe failed. The local aggregate was stopped after CI
completed. The corresponding full CI suites pass all 360 tool-access
tests and all 162 workspace-runtime tests.
- No live GitHub authorization or installation was performed. The
isolated instance correctly stopped at the cloud enrollment or public
HTTPS prerequisites.

## Risks

- Low scope: catalog presentation and routing change. There is no
database migration or provider credential change.
- Existing GitHub bot URLs now open bot setup directly. The tool route
remains `/apps/connect?source=github`.
- The bot remains behind the existing chat-connectors feature flag.
Existing endpoints retain `provider: github`.
- Channel applications are represented by endpoint rows. Regression
tests cover legacy bot applications, tools, active bots, and drafts
together.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, code execution, and
embedded-browser tools. The exact deployed model ID, context window
size, and reasoning setting are not exposed to 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-30 17:15:02 -05:00
DottaandPaperclip 018993140f feat: let agents name prompt-only tasks (#14761)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Users create tasks with a title and a description.
> - A required title adds work when the prompt already explains the
request.
> - An agent can name the task once it reads that request.
> - This pull request accepts prompt-only tasks and starts them with a
short prompt slice.
> - A scoped title tool lets the assigned agent replace that slice early
without changing execution state.
> - A live browser eval checks the real agent call, saved title, audit
entry, and preservation of user titles.

## Linked Issues or Issue Description

**Subsystem affected**

Cross-cutting: task creation, shared contracts, database, server, runner
tools, and board UI.

**Problem or motivation**

Users must currently write a title before they can submit a detailed
task prompt. The agent has enough context to write a useful title
itself.

**Proposed solution**

Make the title optional when a description is present. Save the first
120 characters of the normalized prompt as a provisional title. Ask the
assigned agent to call `set_task_title` early. Use an atomic
provisional-title guard to preserve titles supplied or edited by users.
Keep explicit titles supported.

Related: #14543 and #14556 concern empty-title submission. This change
intentionally enables that submission when a prompt is present, instead
of requiring a title.

## What Changed

- Add the `titleNeedsGeneration` field with an idempotent migration.
Keep existing titles unchanged.
- Add `PUT /api/issues/:id/title` and the native and legacy
`set_task_title` tool. Enforce company access, active-run ownership,
shared, bounded retry receipts across native/HTTP calls, and
transactional audit logging. Refresh external-object links after commit,
with the same feature gate and plugin detectors as ordinary title edits.
- Add early naming guidance in Standard, Ask, and Plan task context.
Preserve the description, status, and assignment.
- Allow prompt-only root and child task creation, plus draft restoration
in the New Task dialog. Keep user titles supported.
- Add an opt-in Product E2E suite for prompt-only Standard and Ask
tasks, plus an explicit-title control. It checks actual provider calls
within the first five tools, persisted state, audit attribution, and the
reloaded UI.
- Preserve a closed vocabulary of API key maintenance phrases in
declared prose while rejecting opaque credential suffixes. Add one
bounded naming retry after wording is rejected, without treating the
rejected call as a saved title.
- Repair the native cleanup receipt check exposed during full
verification: accept matching input digests, retain legacy input checks,
and reject conflicting receipts.

## Verification

- Live Product E2E on `f43478473800e3a46b85c5ee79677efdb15108e7`: **3/3
passed** with native Codex `gpt-5.4-mini`, first attempts only,
automatic retries disabled. Standard and Ask each saved “Rotate expired
API key” on their first tool call, with matching persisted state and a
single same-run audit entry. The explicit-title control retained its
user title with zero title writes. All three verified the reloaded
browser UI.
- Campaign: `local-2026-09-30T21-30-11-021Z`. Earlier failed campaigns
are retained separately; they exposed credential-prose handling and
prompted the naming recovery fix. No failed result was regraded or
deleted.
- Reproduce with `pnpm test:e2e:runner -- --id
task-titles.runner-codex-mini.local.prompt-title-standard --id
task-titles.runner-codex-mini.local.prompt-title-ask --id
task-titles.runner-codex-mini.local.preserve-explicit-title
--max-automatic-retries 0` and an authorized provider key.
- Full `pnpm -r typecheck` and `pnpm build` passed on the latest commit.
The runner build used the configured external eval source tree.
- Product E2E unit suite: **61 files, 818 tests passed**; E2E typecheck
and UI token gates passed.
- Title API/native regressions cover prompt-only and explicit child
creation, user edits, ownership/company isolation, external reference
refresh, cross-surface retry replay, and the 64-key limit without
receipt eviction. All passed. Prompt-context coverage: **44 tests
passed**.
- Rust credential regressions: **35 tests passed**, including benign
maintenance qualifiers and opaque credential rejection in every declared
prose field. Catalog/report reconciliation: **28 tests passed**. Native
recovery: **560 tests passed**.
- Broad local `pnpm test:run`: **14,555 tests passed** in the general
server group; two suites failed to initialize embedded PostgreSQL and
the existing 40,000-file Git streaming stress test exceeded its
300-second macOS timeout. All three suites then passed in isolation (**5
tests passed**) without code or timeout changes. The original full local
command exited nonzero and is not being represented as a clean full run.
- Latest-head GitHub checks are green: **53 passed, 4 skipped, zero
failed or pending**, including all test shards and the canary packaging
dry run. Greptile reviewed the same commit at **5/5**, with zero
unresolved review threads.

## Risks

- The additive database field must reach the server and UI together. The
migration uses `IF NOT EXISTS` and defaults existing tasks to a final
title.
- Title generation depends on the assigned agent running. Tasks without
a run keep their provisional title.
- Live qualification covers the native Codex path in Standard and Ask
modes. API/legacy and Plan behavior have deterministic coverage.
- The credential-prose exception validates the entire suffix against a
closed maintenance vocabulary. Unknown suffixes, assignments, quoted
values, credential prefixes, and diagnostics retain strict checks.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, tool use, and code
execution. The exact deployment ID and context window are not exposed in
this session. The live eval uses the native Codex `gpt-5.4-mini`
profile.

## 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-30 16:48:24 -05:00
DottaandPaperclip d432dc7fa3 Add GitHub-synced skill sources (#14713)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Company skills supply instructions and files to those agents.
> - GitHub imports already exist, but users cannot manage repositories
as skill sources.
> - Repository refresh also needs caller-authorized access and complete
local packages.
> - This pull request adds Sources inside Skills and reuses GitHub
connections from Apps.
> - Installed snapshots let agents use skills without fetching GitHub
during a run.
> - Manual refresh preserves skill identity and leaves failed imports on
their last good version.

## Linked Issues or Issue Description

**Subsystem affected**

Cross-cutting: skills UI, server, database, shared contracts, and
runtime materialization.

**Problem or motivation**

Users keep skills in GitHub repositories. They need a clear way to
select, import, and refresh those skills. Existing imports do not expose
repository management or consistently preserve supporting files.

**Proposed solution**

Add company-scoped skill sources. Browse repositories from all
accessible GitHub connections, or paste a public repository or branch
URL. Select whole skill packages, inspect included files and reference
warnings, and install complete, immutable snapshots. Refresh each source
manually.

**Alternatives considered**

Project repository settings hide the workflow from Skills. A second
GitHub connector would duplicate credentials and grants. Upstream
editing and PR creation are separate work.

**Roadmap alignment**

This implements the Skills Manager direction in ROADMAP.md. The
maintainer requested this scope and reviewed the component and full-app
journey stories before implementation.

Related reports: Refs #10285, Refs #10949, Refs #13464. Related work:
#14356, #13656, #9268.

## What Changed

- Add source and entry records, an idempotent migration, company-scoped
APIs, and legacy GitHub import adoption.
- Reuse current caller grants and credential refresh. Combine and
deduplicate repository inventories across accessible connections. Pasted
public URLs also prefer the active user’s authorized connections. Tokens
stay in the Git child environment, never argv or disk.
- Fetch a shallow Git snapshot at one immutable commit. Scan the full
local tree, including hidden and nested folders. Read Git objects
without checkout or archive transformations and enforce nested package
boundaries.
- Bound Git downloads to 128 MiB and three minutes. Cancel active
process groups and remove incomplete downloads. Preserve cancellation
and deadlines while progress drains; close stalled HTTP progress streams
after 30 seconds. Reuse caller-scoped temporary snapshots for
preview/import after reauthorization.
- Index repository package boundaries once and cap expanded work at
1,000 packages, 10,000 files, and 100 MiB, including repeated copies of
shared blobs. Bound path depth and the shared path index. Discovery
keeps audited manifests without retaining all package bodies.
- Resolve moving branches before fetching so unchanged discovery reuses
caller-scoped snapshots. Limit active scans, scan frequency, and new
downloads per caller and company; quotas apply before metadata reads and
across connections, and cached scans do not consume the download quota.
- Store complete versions with script content, binary bytes, and
executable modes. Preserve these through copies, runtime caches, and
runner packaging.
- Stage downloads before publication. Use source leases, revision
checks, and transactional activity records. Keep installed versions
after failures, upstream deletion, deselection, and disconnect.
- Add the approved import flow, Sources page, selection tree,
provenance, read-only Studio behavior, and saved return from GitHub
setup.
- Add package manifests, commit-pinned file previews, and separate
runtime requirements and reference warnings. Supporting files are
included together; nested skills remain independently selectable.
Preview requests reauthorize the caller and re-audit package content.
- Show installed skills as compact links beneath each source. Repository
titles open GitHub. Keep Refresh, Select skills, and Disconnect source
in a three-dot menu. Source rows omit the branch, imported count, and
refresh timestamp; action alignment and repository titles work at narrow
widths.
- Stream discovery metadata over an opt-in NDJSON response. Show
measured Git download progress and real package/file counts, animate
newly checked skills, support cancellation, and require a complete scan
before selection. Keep the existing JSON API.
- Retain component stories and add a separate full-app journey story
group. Include fixed progress states and interactive scan,
large-repository, interruption, and saving stories.
- Update Skills documentation and product contracts. Suppress private
GitHub skill references in telemetry. Privacy review requested for the
telemetry changes.

## Verification

- Local repository typecheck, full build, token gates, and Storybook
build passed during this work. Focused transport, authorization,
scanner, persistence, route, and UI tests pass. The final UI refinement
passes all eight focused UI tests, UI typecheck/build, and token gates.
The scanner resource and repeated-discovery fixes pass 132 focused
scanner, transport, authorization, source-service, route, and rate-limit
tests, plus server typecheck/build. Full-suite verification comes from
CI; the older full local Vitest run was stopped after unrelated chat
failures and a font-test failure, all of which passed in fresh focused
runs. At commit `1098d5996`, all 54 active checks pass; two optional
Storybook jobs are skipped. CI covers repository typecheck, build, the
full test suites, browser shards, and the canary dry run. Greptile is
5/5 with no open findings; the security scan also passes.
- Adversarial scanner tests verify repeated-blob byte accounting with
and without declared sizes, package/file/path caps, one-time repository
indexing, metadata-only discovery audits, and nested package boundaries.
Additional tests cover branch movement, snapshot reuse, caller/company
quotas, isolation across connections, active-lease cleanup, quota
recovery, and rejection before any metadata API call.
- Real Git tests verify hidden paths, exact binary bytes, executable
modes, export-ignore preservation, symlink/submodule reporting, pinned
commits, caller-scoped cache reuse, cancellation, cleanup, and
credential isolation. Regression tests hold both download slots with
permanently blocked progress callbacks, verify timeout/cancellation
cleanup and retry, and exercise HTTP backpressure cancellation. Access
tests cover automatic public-URL connection selection and revoked
grants. Database tests verify company and grant audiences.
- Live isolated browser test: the public `anthropics/skills` scan now
completes and discovers all 20 skills without connecting an account.
Imported canvas-design with all 83 files, opened it from Sources, and
verified the installed binary-font preview/download control. Package
previews also expose the complete file inventory before import.
Cancelled an active Git download and retried successfully to all 20
discovered skills; the browser displayed measured download progress. The
current audits reject four other packages; eligible selections remain
importable.
- Browser checks verify the simplified source rows at desktop and narrow
widths, keyboard navigation into the actions menu, Refresh from the
menu, selection, and fixture disconnect with installed skills retained.
Storybook includes a menu-open checkpoint and a 320px layout.
- Storybook includes receiving/preparing download checkpoints and a
timed full-app import journey, plus cancellation, retry,
large-repository, and saving states. Streaming tests cover split UTF-8
frames, incomplete streams, late responses, cross-company requests, HTTP
errors, and JSON compatibility.
- Earlier live acceptance on this PR imported `stitch-skill` with
`DESIGN.md`, assigned it to an agent, disconnected its source, and ran a
successful Studio test that read both installed files. An editable copy
changed independently. Both Skills variants, mobile selection, and
return from GitHub setup were exercised.
- Private access, revoked credentials, OAuth success return,
binary/script preservation, concurrent refresh, transaction rollback,
version pins, and legacy adoption have automated coverage. A real
private-repository OAuth grant was not created during this test.

## Risks

- The migration groups recognizable legacy imports without provider
calls. Their first successful refresh completes the local package
snapshot.
- Reference checks are advisory. They cover Markdown links and explicit
relative resource paths, not arbitrary runtime dependency graphs.
Preview text is capped at 64 KiB; imported bytes remain complete.
- Git must be installed on the server. Shallow fetches still download
the branch snapshot, including files outside selected packages.
Downloads have size/time/concurrency limits. Temporary caches are
bounded and caller-scoped. GitHub API quota still applies to repository
metadata and the connection picker; content no longer uses per-file API
requests. Failed scans retain installed content.
- Sources depend on the current caller's GitHub access. A saved
connection does not grant access to another person's token.
- GitHub script support and immediate manual refresh are explicit
maintainer-approved requirements. The operator trusts the selected
repository and accepts upstream script and executable-mode changes on
refresh. Static audits are not a sandbox or a guarantee of safe code;
agents may later invoke installed helpers under their runtime
permissions. Import and refresh do not execute scripts, hooks, package
installation, or builds. Raw URL and skills.sh imports keep their prior
script restrictions.
- Source originals remain read-only. Refresh affects subsequent unpinned
runs; explicit pins and active runs retain their versions.
- The telemetry change removes source-managed GitHub identifiers from
skill-reference events. It introduces no event or field. Please review
the privacy boundary.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-30 13:32:58 -05:00
DottaandPaperclip 3c561642b4 fix(chat): resolve approvals and preserve unanswered questions (#14613)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents ask for decisions and optional details through cards in chat.
> - A clear approval in a message can leave the matching card pending.
> - An unanswered question can also block an unrelated later reply.
> - Decisions need a saved source message, while optional questions need
to remain answerable in history.
> - This pull request records conversational decisions and lets users
move on from questions and answer them later.

## Linked Issues or Issue Description

**What happened?**

Native Claude and Codex could act on approval in chat while the original
approval card stayed pending. Pending question forms stayed above the
composer, were absent from history, and could suppress later chat
replies. A late native question answer could wait for a finished run to
reconnect.

**Expected behavior**

The active agent records a clear approval or refusal against the exact
card and user message. Ambiguous replies do not grant consent. Users can
send another message without answering a question. The question remains
pending in history and can be reopened and answered later. The saved
answer reaches the agent.

**Steps to reproduce**

1. Ask an agent to propose work with a confirmation card, then approve
it in chat.
2. Check that the original card records that approval before work
starts.
3. Ask an interactive question, send an unrelated message, and reload.
4. Open the unanswered question from history and submit an answer.

Related work: #14408 added completion delivery. #14607 tests completion
reporting turns. Neither records conversational answers on approval
cards.

## What Changed

- Add a confirmation endpoint backed by a user comment, with schema
validation, OpenAPI discovery, and native Plan-mode access. Ask mode
remains read-only.
- Check company, active run, actor, current session, message provenance,
revision, and resolver policy. Save the decision and audit in one
transaction. Retries do not repeat effects. Emit resolution telemetry
after commit.
- Give fresh and resumed chat turns the actual pending confirmation
identities. Teach agents to save clear conversational decisions before
acting and to clarify ambiguity.
- Keep unanswered Agent Chat questions as compact history entries. A
newer user message closes the old form. Question cards never contribute
to composer pending counts or navigation, including after dismissing a
fresh form. The history card is the sole reminder; clicking it restores
that exact form and draft.
- Preserve Agent Chat questions when later messages or questions arrive.
Historical ordinary inputs no longer gate later chat replies.
Current-run requests, task execution, and governed approvals keep their
gates. Remove the special acknowledgement-publication proof helpers that
this rule replaces.
- Route answers to finished native runs through durable fresh-wake
delivery, with existing idempotency and source-question context. Settle
late replies against contiguous completed conversation turns and freeze
their history replay; failed, unhandled, and newly arriving messages
remain actionable.
- Add real-component Storybook scenarios, database and UI regressions,
and a three-turn native Claude/Codex E2E case. Capture distinct,
UI-ready screenshots and report the individual assertions.

## Verification

- Focused decision/publication/UI regressions after merging master: 288
passed; subsequent UI draft, failed-send, and conversation checks: 199
passed.
- Native question and durable delivery regressions: 106 passed,
including all four terminal run states and exactly-once late delivery.
Seven targeted regressions fail against the original implementation and
pass with the fix.
- Latest conversation/decision/native-delivery regressions after the
master merge: 121 passed. Covers completed progress, missing or failed
intervening turns, new messages during a late reply, stale sessions, and
frozen retry/replay boundaries. Four new assertions fail before the
ordering fix.
- E2E support suite after the master merge: 792 passed. Negative
controls reject expired cards, wrong questions/answers, stale or missing
replies, unrelated clarification forms, and unexpected tasks.
- The embedded-browser walkthrough caught one additional defect:
dismissing a fresh question still showed a composer badge. Both Cancel
and close-button regressions failed before the fix. The fix at
`65f2ade12` passes 170 chat-thread tests and 792 E2E support tests.
After merging master, 232 chat-thread/confirmation tests, server/UI
typechecks, and token gates pass. The preview and two-provider live E2E
pass at `e5512a206`; Greptile is 5/5 with zero unresolved threads at
that commit. All 55 checks are now successful at `e5512a206` (four
conditional checks skipped), including the aggregate verification gate
and clean-install canary test. The first attempt was interrupted by
simultaneous CI worker shutdowns; one failed-job rerun passed without
code changes.
- [Published
Storybook](https://d1p6rlowie26tp.cloudfront.net/storybook/branches/codex~2Fchat-approval-resolution/?path=/story/chat-comments-agent-chat-unanswered-questions--moved-on):
nine real-component scenarios. Manually exercised move on, reopen,
preserve draft, answer later, answer one of multiple questions, and a
custom mobile answer in the embedded browser. Retested fresh Cancel and
close-button dismissal in the updated build, then reopened and submitted
the preserved Green selection and inspected its answered receipt. Static
preview has no live model/backend; its callbacks are fixture responses.
- [First live
campaign](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-36714504406-1/)
reproduced the late-answer completion-state defect on both providers
despite correct saved answers and acknowledgements. It also exposed a
valid imperative clarification rejected by the old oracle. Both issues
are fixed with regression controls; this failing run is retained as
evidence.
- [Four-cell
qualification](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-36717804064-1/)
passed 4/4 at `2bf8a1009`: unanswered-question return and ambiguous
confirmation, each on native Claude and Codex. Inspected saved state,
source-message decisions, visible cards, and agent replies. Both
late-answer chats settled to waiting; no unrequested tasks were created.
[Final branch
rerun](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-36719666238-1/)
passed 2/2 at `142630720`: the same unanswered-question journey after
merging master, plus an additional screenshot and browser assertion for
the actual late-answer acknowledgement.
- [Composer-reminder
E2E](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-36727006818-1/)
passed 2/2 at `5b62c52d9`: native Claude and Codex, three turns each,
with explicit no-badge assertions before and after reload. Inspected
saved pending/answered state, both screenshots with a clear composer,
and actual Blue acknowledgements; all five behavioral matchers passed
per provider and neither created tasks. Cost coverage is partial; this
is bounded workflow qualification.
- [Fresh-dismissal
E2E](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-36742773318-1/)
passed 2/2 at `e5512a206`: native Claude and Codex, including fresh
Cancel, clear composer, reopen, unrelated message, reload, late Blue
answer, and actual agent acknowledgement. All five behavioral matchers
pass per provider. Inspected the fresh-dismissal screenshots and saved
pending/answered identity; neither created tasks. Cost coverage is
partial (4/6 runs).
- Prior evidence remains available in [the earlier
campaign](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-36642252725-1/).
Its early loading screenshot and overwritten final capture prompted the
UI-ready, distinct screenshot fixes.

## Risks

- The model interprets intent. The server verifies permission and
provenance; it does not infer consent from text. Ambiguous and unrelated
replies are not approvals.
- Historical questions can accumulate. They remain visible, pending, and
answerable; no automatic answer or expiry is invented.
- The change to completion gates is scoped to Agent Chat and ordinary
historical inputs. Current-turn and governed approvals retain their
existing controls.
- Live qualification is limited to the selected stories. Broader native
onboarding finalization remains separate work.
- No database migration. Telemetry adds no fields or values; the
contract and README document the commit boundary. Privacy review was
requested on the PR.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository tools, code
execution, and browser-test orchestration. The exact model ID and
context-window size are not exposed to 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-30 11:46:46 -05:00
DottaandPaperclip 0e5830887b perf: reveal task content sooner and parallelize issue reads (#14727)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - A task page must show saved replies quickly so a person can read the
work.
> - The title could appear while the conversation waited for unrelated
metadata and transcripts.
> - Thread requests also waited for enriched task details, while the
server read several independent fields in sequence.
> - This change shows saved content as soon as it is ready, starts
thread reads earlier, and runs independent server reads together.
> - Native event history takes priority over legacy log fallback, and
mentioned tasks load on intent.
> - Content-free timing spans make the remaining server delays visible
without recording task content.

## Linked Issues or Issue Description

**What happened?**

Task titles and properties appeared quickly, but saved conversation
content stayed hidden for several more seconds while metadata and run
transcripts loaded.

**Expected behavior**

Saved replies and the task description should be readable without
waiting for supporting history. Returning to a cached task should show
content within a frame or two.

**Steps to reproduce**

1. Open a task with saved comments and completed runs.
2. Delay the task activity and runs responses by five seconds in the
browser.
3. Observe whether saved content remains hidden until those responses
finish.
4. Navigate away and return to the task to check cached navigation.

**Paperclip version or commit**

The change was developed from `1b48e73e0` and rebased onto `44736c9c7`.

**Deployment mode**

Built from source, tested in an authenticated staging deployment and
with local response replay.

Related: #14667 overlaps the transcript reveal behavior and adds
separate retry UX. This PR also changes navigation prefetch, parent
metadata gates, native log fallback, server read scheduling, and timing
spans. #12647 proposes a separate SQL predicate optimization in the runs
service. #13597 and #13095 are earlier loading fixes.

## What Changed

- Start activity and runs when the task page mounts, alongside task
details and comments, using the route reference for shared query keys.
Hover/focus prefetch does not start full history reads.
- Reveal saved comments and descriptions while metadata and transcripts
load. Preserve strict waits for linked-comment navigation and tasks with
only runtime content.
- For settled native runs, fetch legacy logs only when event history is
empty or fails. Preserve live-log subscriptions for queued and running
native runs. Fetch mentioned-task details on hover or focus.
- Run independent issue-detail enrichment and run metadata reads in
parallel while preserving recovery dependencies.
- Add `Server-Timing` phases and opt-in OpenTelemetry spans, plus
regression tests and observability documentation.

## Verification

- **313 tests passed** across the initial seven focused component,
cache, timing, and scroll suites. After review fixes, **313 tests
passed** across five task-page, cache, prefetch, and live-transcript
suites (`pnpm exec vitest run` with `--maxWorkers=1`; these sets
overlap).
- `pnpm -r typecheck` and `pnpm build` passed locally before the final
UI-only review fixes. UI typecheck/build and `pnpm check:token-gates`
passed after those fixes. The final commit also passes full typecheck
and build in CI.
- The full local Vitest run was attempted. Several unrelated embedded
PostgreSQL fixtures failed to start, and parallel test workers hit
timeouts. Focused reruns passed. A later local full-suite rerun was
stopped after the complete CI suite passed; it is not claimed as a local
full-suite pass.
- Final commit `d1e147145`: **54 checks passed, 2 skipped**, including
all server/workspace test shards, all eight browser E2E shards, full
build/typecheck, Runner checks, release registry, and canary
clean-install verification. [CI
run](https://github.com/paperclipai/paperclip/actions/runs/36734642034).
Greptile **5/5** after two reviews; both findings fixed and all review
threads resolved. No merge conflicts.
- Live browser tests on an existing task with two saved replies: median
full reload to visible content fell from **1.92 s** (3 samples) to
**1.40 s** (5 samples). Cached return fell from **421 ms** (1 sample) to
**29 ms** (3 samples). These are observed samples, not a performance
guarantee.
- With activity and runs delayed by five seconds, saved content appeared
in **1.38 s** on desktop and **1.33 s** on mobile. The inspected comment
did not move when metadata arrived. Verified history expansion, task
properties, pending-input navigation, dashboard return, and mobile
layout.
- A separate local replay with fixed responses reduced visible-content
time from **5.12 s** to **2.15 s**. This isolates frontend behavior and
is not a live-server benchmark.

## Risks

Progressive history can change the thread after first paint. Existing
anchor behavior is retained and covered by tests and delayed-response
browser checks. Query aliases must stay aligned for invalidation.
Parallel reads can increase short bursts of database work; dependent
recovery operations remain ordered. Full reloads still depend on network
and task-detail latency.

No schema or authorization change. OpenTelemetry remains disabled
without an operator endpoint. The added spans use a closed set of phase
names and carry no task IDs, task content, or exception text.

I checked `ROADMAP.md`; this is a performance fix within the existing
task page.

## Model Used

OpenAI GPT-6 in Codex. The runtime does not expose a more specific model
ID or context-window size. The agent used reasoning, code editing,
terminal tools, and Chrome performance profiling.

## 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-30 10:26:28 -05:00
DottaandPaperclip 44736c9c7c fix(ui): align runner commentary with chat replies (#14716)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - Agent chat shows run commentary and the agent's reply in one thread.
> - The runner commentary text starts 4px left of the following reply.
> - The runner activity group omits the gutter that the reply bubble
uses.
> - This pull request gives runner commentary the same token-based
gutter.
> - Both text blocks now share one left edge.

## Linked Issues or Issue Description

**What happened?**

In agent chat, the first commentary line of a completed run starts about
4px left of the following agent reply. This is visible in the Codie
conversation.

**Expected behavior**

Runner commentary and ordinary agent reply text should have the same
left edge.

**Steps to reproduce**

1. Open an agent chat with a completed run that has commentary and an
agent reply.
2. Compare the first commentary line with the following reply at the
left edge.
3. Inspect the wrappers. Before this change,
`task-chat-phase-interstitial` has zero left padding and
`task-chat-agent-bubble` has 4px.

## What Changed

- Add the existing `px-1` spacing token to runner commentary.
- Add a regression test that compares the runner commentary gutter with
the ordinary agent reply gutter.

## Verification

- `pnpm check:token-gates`
- `pnpm --filter @paperclipai/ui exec vitest run
src/components/task-chat/TaskChatRunnerActivityGroup.test.tsx
src/components/task-chat/TaskChatTurn.test.tsx
src/components/task-chat/TaskChatBubble.test.tsx`
- `pnpm --filter @paperclipai/ui typecheck`
- `pnpm --filter @paperclipai/ui build`
- A full repository typecheck and build passed earlier on this branch.
All latest-commit CI gates passed, including the server shard after a
transient preview readiness failure was rerun.
- Browser render: runner commentary and reply paragraphs both start at
x=32px after the change.

## Risks

Low risk. This changes only the horizontal padding of runner commentary.
Long commentary lines may wrap 8px sooner. The full local test suite was
stopped after the code changed during its run; the focused UI tests and
latest-commit CI suite passed.

> I checked `ROADMAP.md`. This bug fix does not duplicate planned core
work.

## Model Used

OpenAI GPT-6 in Codex. The runtime did not expose a more specific model
ID or context window size. The agent used reasoning, shell tools, and
read-only browser inspection to diagnose the layout and verify the
change.

## 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-30 09:48:41 -05:00
DottaandPaperclip 1b48e73e0b feat(ui): add secondary navigation for agent chat (#14706)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent Chat already provides a persistent conversation with each
agent.
> - Its shortcuts share the primary navigation and do not give chats a
dedicated place.
> - People need to find agents, start a chat, and switch conversations
without moving the page layout.
> - This pull request adds a secondary chat sidebar and a landing page
around the existing chat surface.
> - The same conversation, composer, history, and context panel remain
in use.

## Linked Issues or Issue Description

Refs #13283 and #13420. This extends the existing experimental Agent
Chat navigation after review of the component and page stories. It
supports the CEO Chat roadmap item through the existing task-backed
conversation model.

**Subsystem affected**

The board UI and the company-scoped conversation list API.

**Current behavior**

Chat shortcuts sit inside the primary navigation. There is no dedicated
landing page with a searchable conversation list. A separate landing
header also moves the sidebar when an agent is selected.

**Proposed behavior**

Show a Chat entry in primary navigation. Keep a searchable agent sidebar
beside the chat content. The plus button starts or reopens the current
user's single conversation with that agent. Keep the header and sidebar
in the same positions before and after selection.

**Reason and benefit**

People can find agents and return to persistent conversations without
leaving the chat area or creating duplicate chats.

**Breaking changes**

The experimental chat navigation changes. Explicitly adding a chat now
resolves its conversation immediately. Direct visits to unused agent
chat URLs remain read-only. The existing per-agent routes and message
contracts remain compatible. No database migration is required.

## What Changed

- Add an account- and company-scoped conversation list endpoint with the
existing access checks, feature gate, and OpenAPI entry.
- Add the live secondary sidebar, landing page, avatars, search, loading
states, errors, and retry controls.
- Make the agent picker wait for chat creation and display failures.
Existing agents reopen the same conversation. A dismissed selection
cannot close a reopened picker or navigate over a newer choice.
- Preserve recent-activity ordering and terminated agents’ chat history.
Scope live list refreshes to the current user’s conversation events. A
failed historical-agent lookup leaves healthy chats usable and offers a
focused retry.
- Keep the sidebar and header stable across chat routes. Keep mobile
selection in the navigation drawer.
- Use the production components in Storybook. Prepare the theme and
mobile viewport before mounting the page to avoid the startup flash.
- Update product documentation, the design guide, and navigation tests.
Replace old browser expectations for stars and recent shortcuts with
persistent conversation and layout coverage.

## Verification

- `pnpm -r typecheck`, `pnpm build`, and `pnpm check:token-gates` pass
after rebasing onto master.
- Focused UI tests pass, including 105 sidebar, picker, and live-update
checks after review fixes. The 33 conversation service and route tests
and 10 OpenAPI checks pass, including ownership, feature gating, and
concurrent creation.
- The full local test run passed 14,163 server tests before three
environment or timeout failures. The embedded Postgres startup,
connector socket, and native runner failures all passed direct reruns.
- Browser test-drive verification covers a real provider reply, add and
reopen, persisted history after reload, no-match search recovery, mobile
drawer dismissal, and top-aligned context panels.
- Browser measurements confirm that the sidebar has the same position
and dimensions on the landing page and an agent conversation.
- Storybook builds and its add-and-reopen interaction passes.
- The revised browser regression passes locally against a freshly built
throwaway instance. It covers stable sidebar geometry, add/reopen
uniqueness, drafts, search, history, and terminated-agent history after
reload. The full CI browser suite also passes.
- Latest commit `b323577d9523180104df4000eaceedea2772608c`: all 54
completed checks pass, including the complete server/workspace/browser
suites, aggregate verification, build/typecheck, security scans, and
canary packaging. The two Storybook jobs are skipped by their workflow
conditions. [CI
run](https://github.com/paperclipai/paperclip/actions/runs/36714052050).
- Greptile reviewed this same commit at 5/5 with no remaining actionable
findings; all review threads are resolved.
- Reviewer path: enable Agent Chat, click Chat, use plus to choose an
agent, send a message, switch away, and reopen that agent. One
conversation must remain, with its history intact.

## Risks

- The new sidebar lists persistent conversations instead of starred and
recent shortcuts.
- Chat creation is asynchronous. Errors stay visible in the picker, and
delayed responses cannot navigate into a previous company or account.
- The shell adjustment is limited to chat routes and preserves the
existing conversation implementation.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, code execution, and browser
tools. The session does not expose the exact API 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
#123` / `Refs #123` 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-30 07:35:32 -05:00
DottaandPaperclip d72389bee2 feat: add Browser Use Cloud connector and live task browsers (#14627)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The Apps gateway gives agents governed access to external tools.
> - Browser Use Cloud can run browser work, but a tool result alone does
not let a person watch or take over.
> - A task needs a durable browser session, a visible viewer, and
recorded costs.
> - This pull request adds a Browser Use Cloud v4 connection and
interactive browser tabs on tasks.
> - People can follow the work, interact with the page, and retain the
browser after the agent finishes.

## Linked Issues or Issue Description

**Problem or motivation**

Agents need governed access to Browser Use Cloud. People need to see and
interact with the same browser from the task. A browser must remain
available after a run finishes and appear at the correct point in the
task feed.

**Proposed solution**

Add a native REST connection for the v4 API. Bind each session to its
company, task, agent, and credential grant. Open its interactive viewer
in the task side panel. Record provider costs as financial events. Use
`browser-use-cloud` as the app and connector key. Keep its skill with
the connector and deliver it only with authorized connection tools.

**Alternatives considered**

A v3 MCP connection would expose tools without the v4 lifecycle
integration. An external viewer link would leave the task. A fixed
viewer size would prevent pages from responding to changes in the task
pane.

**Roadmap alignment**

This extends the governed Apps gateway and Connected Apps roadmap. It
uses the existing task, grant, secret, approval, and financial records.
The work was requested by the maintainer. A search found no duplicate
Browser Use connector PR or issue.

## What Changed

- Add the Browser Use Cloud app, brand asset, API-key connection, and
profile settings under the `browser-use-cloud` key.
- Bundle the `browser-use-cloud` skill with the connector. Keep it out
of global `skills/` discovery. Deliver it only with authorized task/run
connection tools. Remove retired connector skill keys from runtime
overlays and preserve unrelated browser skills.
- Expose seven v4 tools through the governed gateway and deliver them to
native and CLI agents.
- Persist sessions, browsers, runs, event and recovery cursors, shutdown
leases, and cumulative cost accounting. Recover uncertain paid starts
without replaying them.
- Enforce task ownership, credential grants, approvals, revoked access,
and budget limits.
- Add interactive task browser tabs and compact chronological feed
entries. Retain the viewer across tab switches and keep visible idle
browsers open.
- Add debounced automatic viewport fitting, standard size presets, and a
viewer ownership lease.
- Add lifecycle, authorization, accounting, viewport, UI, and Storybook
coverage.
- Add an idempotent database migration after the current master
migration. Preserve deployed migration hashes. Migrate pre-release Cloud
connection and financial keys without replacing grants, credentials, or
browser history.
- Document provider behavior, live acceptance results, and the lack of
documented passkey forwarding.

## Verification

- Full workspace typecheck and production build pass on the updated
branch.
- Token gates, brand asset validation, module boundaries, and migration
ordering pass.
- Cloud tests verify global skill exclusion, authorized task/run
delivery, unassigned agents, disabled connections, revocation, adapter
isolation, and secret exclusion. The existing AgentMail connector
assignment test also passes.
- Migration replay runs twice against existing browser work and
financial records. It preserves the records and avoids duplicate costs.
- The focused provider, app catalog, OpenAPI, connection gateway, and
migration regression suites pass. Recovery coverage includes lost
replies, process crashes, provider rejection, and browser arrival
acknowledgement.
- All 54 checks pass on `2974b5f03641ad0cea3c941d8c02579316fa8c92`,
including the full test matrix, browser E2E shards, build, typecheck,
security, and release canary. Two optional Storybook jobs are skipped.
- Greptile is 5/5 on the same commit, with zero unresolved review
threads. The corrected review uses the actual master-to-head diff.
- The local `pnpm test:run` started and was stopped after the full CI
matrix passed. It did not complete locally; the full-suite result above
comes from CI.
- Earlier live acceptance used an isolated company with a capped
provider credential. The agent opened paperclip.ing, the embedded viewer
accepted navigation, and the same browser stayed available after
completion and tab switches.
- The local Storybook build passes. Stories cover the panel, footer,
feed entries, settings, lifecycle failures, and viewport modes with an
offline viewer fixture.

## Risks

- Browser Use charges for hosted work. Provider caps and local budget
checks reduce exposure; reported costs can arrive after work completes.
- Viewer and CDP URLs grant access to the browser. The server validates
and restricts them. They are excluded from agent results and durable
event data.
- Runtime resizing of v4 agent browsers uses a provider option confirmed
by live testing but absent from its published agent schema. Resizing
during a click may invalidate coordinates. Fixed presets remain
available.
- Viewport ownership is process-local and resets on restart. The
lifecycle and accounting records remain in the database.
- The original intermittent embedded-viewer stall has not been fully
diagnosed. A bounded reconnect and active-session recovery cover the
observed failure paths.
- Live tests did not cover every revocation, approval, rate-limit, or
restart case. Deterministic integration tests cover those paths. Passkey
forwarding is not claimed.
- Unknown create outcomes keep the credential available for cleanup.
Run-list absence cannot prove a paid POST was rejected, so recovery
stays pending until it can identify provider work.

## Model Used

OpenAI Codex, GPT-6. Used reasoning, repository search, code execution,
browser interaction, and test tools. The exact serving model ID and
context-window size were not exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `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-30 07:13:16 -05:00
DottaandPaperclip 2f6fa3b6dc fix: recover provider authentication inside tasks (#14629)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents need a working model provider connection to run a task.
> - A provider can reject a stored credential after the task starts.
> - The failed run must ask the responsible user to repair that
connection.
> - This pull request adds that request directly to the task and reuses
Connections sign-in.
> - The user can choose an API key or subscription, then continue the
task with a fresh session.

## Linked Issues or Issue Description

**What happened?**

A run that ended with `acpx_auth_required` or another known provider
authentication error did not immediately offer an inline way to connect
the provider. A repair form could also lock the user to the failed
account's sign-in method.

**Expected behavior**

Show a provider connection card in the task as soon as the
authentication failure is saved. Allow the responsible user to connect
or repair the provider with any supported sign-in method. Keep the
connection name automatic and resume the task after successful setup.

**Steps to reproduce**

1. Run a task with a supported provider and an expired or invalid
credential.
2. Let the run fail with a provider authentication error.
3. Open the task and attempt to repair the connection.

Related work: Refs #13724 and #13726. This change adds the inline task
repair flow and method choice.

## What Changed

- Classify provider authentication failures and create one connection
request for the current task. A persisted blocked classification
suppresses automatic retries only after the repair card is created;
unsupported providers retain their existing recovery path.
- Mark only the attributed, unchanged credential as needing sign-in.
Preserve credentials that were refreshed after the failed run started.
- Reuse the provider sign-in controls inside the task. Allow API key and
subscription choices for Claude, Codex, and Grok. Keep names hidden and
generate a default from the user, provider, and method.
- Keep the existing account when reconnecting with the same method.
Create and select another account when the method changes. Validate
updates to explicit agent bindings through the normal agent save path.
- Require explicit adoption for legacy agent authentication. Validate in
the agent environment, then commit the binding, connection install,
audit, and card completion in one transaction. Keep failed setup and
account selection visible and retryable.
- Add regression tests and update the specification and Connections
documentation.

## Verification

- Fresh local verification: 199 tests passed across the inline form,
provider method selector, default naming, authentication and recovery
classifiers, run liveness, OpenAPI routes, database adoption/rollback,
and Cursor execution suites. The adoption database suite also passed
against disposable Docker PostgreSQL.
- Full repository `pnpm build` and `pnpm -r typecheck` passed on the
latest commit. Token gates are clean.
- Embedded browser: opened real task cards from seeded authentication
failures; switched Claude from API key to subscription and back;
switched Codex from subscription to API key; confirmed the name field
stays hidden. Provider sign-in was not completed with real credentials.
- The broad local `pnpm test:run` started before review fixes and was
interrupted after the working tree changed; it is not counted as a
passing full run. Fresh focused tests passed. CI supplies the full test
and browser suite results for the current commit.
- CI is green on commit `4b97a4e447045ff3d7516525a187a5d1d21e0d4c`: 54
checks passed and two Storybook checks were skipped by their path rules.
The workspace preview job passed on one rerun after a local-server
startup timeout; its rerun passed 835 tests.
- Greptile is 5/5 on the same commit with no actionable findings and no
unresolved review threads.

## Risks

- Incorrect authentication classification could prompt for a connection
unnecessarily. Tests exclude tool authorization, quota, and unrelated
runtime failures.
- A method change selects the new personal provider default, which also
applies to other agents that use that user's default. Explicit account
bindings use the existing permission and runtime validation path.
- Credential invalidation must not race with refresh or reconnect. The
code compares the saved credential generation and grant update time
under locks.
- No database migration or new credential storage format is required.

## Model Used

OpenAI GPT-6 through Codex. The exact model ID and context window size
were not exposed in this session. Capabilities used: reasoning,
repository editing, shell commands, database tests, and embedded-browser
interaction.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass (focused tests 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-30 06:39:37 -05:00