mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-21 16:27:18 +02:00
87d9386ae637c652d1fed09d2046be1bcaeb413b
5420
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
87d9386ae6 |
fix(ui): retain first-chat uploads through task creation (#16896)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agent Chat lets a person attach files before the first message. > - The first upload creates the saved chat task while the upload is still pending. > - Initial history loading used that new task ID to reset the open composer. > - Resetting the composer discarded its pending upload even when the server saved the file. > - This pull request uses the conversation's stable draft key for its history readiness. > - The benefit is a first message that retains its selected files and their saved references. ## Linked Issues or Issue Description **What happened?** The first file upload in a new Agent Chat saved on the server but disappeared from the composer. The initial history change in #16878 can unmount the active composer when an empty chat receives its task ID. The pending upload belongs to that unmounted composer, so the new composer has no selected file. **Expected behavior** The same conversation keeps its active composer and pending file while the task is created. Sending the message binds the saved attachment once. Initial history loading for an existing conversation and ordinary task still waits before mounting its composer. **Steps to reproduce** 1. Open Agent Chat for an agent with no saved conversation. 2. Attach a text file before sending a message. 3. Let chat creation finish while the upload is pending. 4. Observe that the file chip disappears, although the attachment POST returns 201. **Paperclip version or commit** Reproduced by a deterministic real-composer regression on master |
||
|
|
b928c6698f |
fix(heartbeat): explain deferred monitor dispatch (#16891)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - One-shot task monitors request future work through the normal heartbeat queue. > - Queue admission can hold execution until recovery or ownership is reconciled. > - The scheduler retained those monitor schedules but recorded no monitor diagnostic. > - Agents could repeatedly reschedule the same blocked check without seeing why it did not run. > - This pull request records safe deferral and failure activity while retaining all execution gates. > - Agents and operators can inspect the actual blocker and use its existing recovery path. ## Linked Issues or Issue Description Related: #15556 handles transient monitor client errors. #14590 handles parked monitor wakes. This change records the diagnosis when queue admission defers or fails; it does not change their admission or monitor consumption policies. **What happened?** A due monitor on a task with an unresolved execution-recovery hold was claimed, passed to queue admission, and released without monitor activity. The saved monitor continued to look scheduled. Unexpected dispatch errors had the same audit gap. Repeated rearming could not clear the recovery hold. **Expected behavior** Keep the monitor and the recovery hold. Record the reason that prevented its wake. Do not execute uncertain work or consume an attempt. Limit repeated identical diagnostics. If audit storage fails, release the claim so a later tick can retry. **Steps to reproduce** 1. Schedule a due monitor on an agent-owned task in progress. 2. Add an active recovery action for an interrupted legacy execution. 3. Run the monitor scheduler twice. No provider may start while the hold remains. 4. Before this fix, neither attempt writes monitor deferral activity. 5. Resolve the hold through its existing recovery path. The saved monitor can then request one wake. **Paperclip version or commit** Reproduced on master |
||
|
|
370fb50ad4 |
fix(mcp): keep sibling tools available after transient calls (#16890)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agents use remote MCP tools through a governed gateway. > - The gateway lists tools only while their shared connection is healthy. > - One failed call currently marks the whole connection as unhealthy. > - Later calls to healthy sibling tools then fail with `tool_not_found`. > - This pull request keeps non-authentication call failures on their invocation. > - Agents can continue their work while credential and access gates remain in force. ## Linked Issues or Issue Description Refs #10147. Related work: #15462 fixed oversized and malformed response handling. #15448 covers timeout and JSON-RPC health handling together with separate SSE and catalog discovery changes. Its patch still marks fetch failures and HTTP failures as connection errors. #15325 proposed a transport failure counter; it has merge conflicts and has not changed since October 6. #11910 is an older timeout fix with merge conflicts. This PR covers the remaining fetch and HTTP failure paths on current master, with the same narrow call-health rule for timeouts and JSON-RPC failures. It does not include the SSE or discovery changes from #15448. The timeout session-reset check follows the recovery case discussed in #15448. **What happened?** A shared remote MCP connection works until one call has a network failure, timeout, HTTP 503, or JSON-RPC error. Every later call on that connection returns `tool_not_found`, including healthy sibling tools. Connection setup then asks for user attention even though the failure did not prove that credentials need repair. **Expected behavior** The original invocation retains its failure. Authorized sibling tools remain callable. The gateway does not replay an ambiguous action. HTTP 401/403, missing credentials, and explicit insufficient scope keep their access gates. **Steps to reproduce** 1. Give an agent access to two read tools on one remote MCP connection. 2. Make one tool fail with a network error or HTTP 503. 3. Call the other tool in the same gateway session. 4. Before this fix, the second call fails with `tool_not_found` before provider dispatch. **Paperclip version or commit** `master` at `e6dcd1e8e9`. The regression runs against source with synthetic data. **Deployment mode** Any deployment that uses a shared remote MCP connection. This is a core gateway issue. ## What Changed - Preserve connection health after a network failure, timeout, non-authentication HTTP error, or JSON-RPC error from one tool call. - Retain HTTP 401/403 and insufficient-scope health gates. - Retain HTTP 401/403 gates during MCP initialization and its initialized notification, with HTTP 503 controls for both stages. - Discard only the upstream session used by a network failure or timeout. Let the next explicit call initialize again. - Add sibling-tool regression cases, authentication controls, and real HTTP header/body timeout checks. - Update runtime recovery guidance and the feature and access maps. ## Verification - Red: the four new sibling-tool cases failed on the original implementation. Each second call returned HTTP 404 with `tool_not_found`. HTTP 401/403 control cases passed. - Green: the same six-case selection passed after the production change: `pnpm --filter @paperclipai/server exec vitest run src/__tests__/tool-gateway-service.test.ts -t 'keeps sibling MCP tools usable|keeps the connection blocked' --maxWorkers=1`. - The regression checks the actual gateway and embedded PostgreSQL. The injected provider fault preserves the call boundary. It checks failure recording, no automatic replay, catalog retention, and successful sibling dispatch. - The real local HTTP fixture checks cancellation before headers and during a body, then a successful explicit call with a fresh MCP session. - `node scripts/check-maps.mjs` and `git diff --check` pass. - Complete nearby suites pass: 166 tests across `tool-gateway-service.test.ts`, `tool-gateway.test.ts`, `remote-mcp-protocol.test.ts`, and `mcp-http.test.ts`, with one test worker. - `pnpm --filter @paperclipai/server exec tsc --noEmit` passes after refreshing Runner TypeScript declarations. The first package typecheck used declarations from before the rebase and failed two unchanged native-session call sites; rebuilding that dependency resolved both errors. - The rebased head also passes all 11 selected sibling/authentication/session regressions. - Review regression red: setup-stage HTTP 401/403 controls failed because connection health stayed `ok`; the two setup-stage HTTP 503 controls passed. Green: all six setup controls and the complete 166-test nearby run pass. The fix separately handles typed initialization authentication failures and preserves the existing caller error. The server compiler also passes after this change. - Full repository CI passes on `256a65ccc302c1c31a80e87f1f91411d955028de`: typecheck, build, test shards, Runner checks, browser checks, Canary dry run, and aggregate gates. All checks are terminal: 55 successful, 2 expected skips, and the separate Paperclip Review check is neutral. Greptile is 5/5 on this exact head, with no open findings. - Full repository checks were run in CI. Local verification in this worktree used the focused suites and server compiler to keep parallel work bounded. - This change has no live provider or staging deployment proof. ## Risks - A provider that remains unavailable can stay listed until a health check detects the outage. Each call still fails with its original controlled reason code. - No automatic retry occurs because a failed remote action may already have run. - Already unhealthy connections still need a successful health check after an upgrade. - No schema, credential policy, or permission contract changes. ## Model Used - OpenAI Codex, GPT-6 family, with tool use and code execution. The runtime does not expose the exact serving model ID or context window. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
6f045207bb |
fix(runner): explain rejected API response windows (#16889)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agents use the API fallback when dedicated tools cannot express an operation. > - Large responses can be read in bounded text windows. > - The declared schema rejects windows larger than 24576 bytes. > - The runner hid the rejected field behind a generic semantic tool error. > - This pull request returns safe schema locations and the accepted byte range. > - Agents can correct a call without guessing or changing route permissions. ## Linked Issues or Issue Description Refs: #16868, which added repair guidance for task monitor arguments. **What happened?** A native call_api request with responseText.limitBytes set to 60000 returned invalid_tool_call with no field or size guidance. The declared 4..24576 byte range already matches the server validator. The missing repair guidance is in the runner bridge. **Expected behavior** Reject invalid input before dispatch. Show bounded schema locations and the accepted window range. Do not echo submitted values or unknown field names. A corrected request can reuse the rejected call ID. **Steps to reproduce** 1. Use the generated call_api tool contract to request a GET text window with limitBytes 60000. 2. Read the semantic tool error. Before this fix, it contains only a generic rejection. 3. Retry with limitBytes 16000. The corrected call must be admitted. **Paperclip version or commit** Reproduced on master |
||
|
|
24067a16b5 |
fix(workspaces): classify restricted shared repository admission (#16895)
## Thinking Path > - Paperclip manages agents, their tasks, and their saved work. > - Workspace preparation must check access before an agent starts. > - A shared project checkout can contain another task's private worktree. > - The access guard correctly rejects a run that cannot read that work. > - The isolated-source path reports this as a configuration blocker after #16545. > - Shared project repository admission missed that classification and returned a generic setup failure. > - This change uses the same blocker at that boundary so recovery names the required workspace repair. ## Linked Issues or Issue Description Refs #16545 and #16095. The open retained-reader repair in #16832 addresses deleted identities, a separate condition. **What happened?** A task reused a shared project workspace. Another worktree in that checkout retained a private task that the run could not read. Repository admission rejected access before provider startup. The run reported `setup_failed`, and recovery showed a generic no-live-execution notice. **Expected behavior** Keep the access denial. Report `configuration_incomplete` with reason `workspace_source_restricted`. Preserve the workspace and files. Give the owner the existing workspace repair action. Do not queue an automatic failure retry or report this expected blocker as an unexpected Sentry failure. **Steps to reproduce** 1. Bind a task to a shared project checkout. 2. Add a private task worktree beneath that checkout. 3. Continue the shared task as an agent that cannot read the private task. 4. Inspect the run result and recovery action. **Version and deployment** Reproduced in the full heartbeat service from source revision `06d4fe3121`, with PostgreSQL and real Git worktrees on macOS. The provider never starts. The regression also covers the existing Git-worktree path. ## What Changed - Apply the existing restricted-source classifier to task repository admission. - Extend the heartbeat regression to shared project workspaces. - Assert one run and one recovery action, no provider start, no unexpected Sentry report, and preserved binding and files. - Update the workspace documentation and both capability maps. ## Verification - Red: the shared project regression returned `setup_failed`; the Git-worktree control passed. - Green: the same two cases pass after the change. - `node scripts/check-maps.mjs` and `git diff --check` passed. - Current head `e26cdd45da76c6edaa1622856f9c69e9f48b81fb`: 55 successful checks, one neutral check, two skipped Storybook checks. Greptile 5/5, no review threads, mergeable. - All 337 tests passed across `heartbeat-workspace-branch-containment`, `heartbeat/workspace-preparation`, `run-failure-report`, and `recovery/stranded-notice`. - `pnpm -r typecheck` and `pnpm build` passed. All full current-head CI suites passed in [run 39315969013](https://github.com/paperclipai/paperclip/actions/runs/39315969013). The duplicate local full Vitest run was stopped after 11 minutes when CI completed; it has no local full-suite completion claim. The 337 affected local tests completed successfully. - Running-app acceptance at `e26cdd45da76c6edaa1622856f9c69e9f48b81fb`: a synthetic private Git worktree caused the shared task to stop with the visible Workspace source restricted notice and no process start. The normal workspace API selected a separate task directory. Resolving the recovery action resumed the same assignee. A real process fixture completed, the output persisted after reload, and both source files remained intact. Checkout and execution locks cleared. There were no automatic failure retries. - The first recovered process wrote its report to the command cwd. This was a fixture output-path mistake. The corrected fixture reads the selected workspace from the authenticated API before writing. One explicit additional admission verified that output. The record retains both successful process runs and the earlier configuration-blocked run. This is local process-adapter acceptance, not live Codex/provider qualification. - Staging diagnosis confirmed a retained private source and failure before provider startup. The original task has not been recovered. The deployed UI hides its workspace selector, and no authenticated task-write API is available in this session. No live Codex recovery is claimed. ## Risks The same exact 403 denial is now a configuration blocker during shared repository admission. Other failures retain their original type. Access policy, cloning, credentials, provider execution, and workspace contents do not change. An existing task still requires a permitted workspace repair before it can run. ## Model Used OpenAI GPT-6 through Codex, with reasoning, code execution, and browser tools. The exact deployment identifier and context-window size are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
ac9459bae3 |
feat: configure company agent observability (#16874)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Companies use several agent harnesses and execution environments. > - Operators need one place to select where native agent logs and traces go. > - An inference proxy would add a dependency to the agent request path. > - This pull request supplies native OpenTelemetry settings to managed Codex and Claude Code processes. > - Company secrets protect destination credentials. Export failure does not change the task result. ## Linked Issues or Issue Description **Subsystem affected** Company settings, shared contracts, database, server, adapters, and runner. **Problem or motivation** An operator cannot configure a company destination for native agent logs and traces. Manual harness configuration is hard to apply across local and remote execution. **Proposed solution** Add one company destination: Braintrust or a custom OTLP HTTP/protobuf endpoint. Apply a transient snapshot when execution preparation starts. Keep credentials out of API reads, task environment manifests, recovery files, and command arguments. Replace a warm process when its export settings change and preserve its conversation. **Alternatives considered** Multiple destinations can use a user-operated collector for fan-out. This change does not add a collector, an inference proxy, or transcript scraping. **Roadmap alignment** This extends company settings, secret management, and support for multiple harnesses. The maintainer requested this implementation. Searches for observability and Braintrust found no duplicate company destination feature. Related infrastructure tracing work in #16236 has a separate content-free contract. ## What Changed - Add strict schemas, revision checks, encrypted secret storage, activity records, and board-only settings routes. - Add explicit synthetic logs and traces tests with a bounded HTTP request and sanitized results. - Supply native Codex configuration and Claude Code environment values through local and remote launch paths. - Preserve Codex login refresh through the existing managed credential link. Retain unsaved drafts across background reads. Require complete custom header re-entry when the endpoint origin changes. - Separate process export compatibility from conversation identity. Isolate generated Codex configuration and preserve resumable sessions, including remote home refresh after export changes. - Advance the immutable Pi/Copilot source attestations for shared environment and sidecar code changes. Keep their provider payloads unchanged and retain prior identities for decoding. - Redact destination credentials throughout launch diagnostics and HTTP logs. - Add the production settings form, Storybook states and journey, documentation, and feature/access map entries. ## Verification - Real managed local Codex 0.160.0 and Claude Code 2.1.286 tasks exported to Braintrust. API readback and the Braintrust UI showed the test records. A real remote Daytona Codex task exported through the legacy `exec` path. - Live tests exercised content capture off, export disabled, warm conversation reuse, and a destination that accepted connections but never replied. Agent work succeeded and export requests stopped at the configured three-second timeout. The UI connection test returned “Test payload accepted”; the saved API key stayed masked after reload. - All current-head CI test lanes, typechecks, packaging/build checks, and required aggregates passed on `71e994b2be9c8fb6d6e938a4ad7cf4c95fdafe31` ([CI run](https://github.com/paperclipai/paperclip/actions/runs/39319194318)). Greptile completed on that exact commit at 5/5, with zero unresolved review threads. The additional optional Paperclip Review check remains queued waiting for its assigned agent. - Local workspace typecheck and build passed. Focused verification included 239 combined runner tests, 789 API/native-session tests, 107 Codex home/ACP/sandbox-site tests, 204 feature/privacy tests, and the affected Rust suites. Migration, token, map, Storybook catalog, and Storybook build checks passed during acceptance. These checks ran at the relevant implementation or merge boundary; the current-head CI is the complete final gate. - Managed AI credential projections now receive enabled and disabled company export settings; genuine caller-owned Codex homes remain untouched. Two regressions reproduced the skip before the repair. All 276 engine/lifecycle tests and adapter-utils typecheck pass afterward. The launched TOML retains provider/MCP settings, credential continuity, and redaction. - Settings saves, removal, and the real company-deletion owner acquire secret mutation ownership before database locks. PostgreSQL NOWAIT probes cover all three paths; concurrent save/rotation/removal/deletion requests settle correctly. The affected suites passed 137 tests, followed by all 32 service/connection cases after expanded deletion coverage. Server and Codex adapter typechecks pass. - Codex source profiles use the effective CLI argument list. A spawned fixture CLI reproduced both ignored-argument failures; all three precedence/fallback cases now pass. - Real tar staging reproduced remote conversation loss in both API-key and subscription modes before the repair. Both now pass: changing managed settings preserves sessions, archives, native indexes, and refreshed subscription credentials. A corrupt upload preserves the prior config and conversation. - Preserved failure evidence: initial CI caught stale Pi/Copilot source attestations, a missing test-harness helper, and packaging fixture/probe mismatches; those were corrected and covered by focused checks. Superseded heads had intermittent attachment-composer timeouts despite successful uploads; [the original trace and screenshot remain available](https://github.com/paperclipai/paperclip/actions/runs/39309701089/artifacts/12215109203). The same attachment case passed on the final head: [25/25 tests in shard 3](https://github.com/paperclipai/paperclip/actions/runs/39319194318/job/118288637051). - A connection-fault fixture also exposed a stale pooled socket after its hang case; closing fixture responses isolated scenarios and the full affected suite passed. - The broad local test run was not clean: database resource failures, timeouts, an older cached module graph, and a stale optional-resource manifest assumption were recorded. Focused checks passed after the documented fixes. This does not establish a clean full local pass. - Native remote Codex, remote Claude, and the full ACPX Codex bridge remain unqualified. The direct Codex resume test does not establish full bridge acceptance. ## Risks - Native exporters perform network requests from each execution environment. A server connection test does not prove remote reachability. - Prompts, assistant responses, and tool content are enabled by default when supported. Native caps and harness-specific controls still apply. - Caller-owned Codex homes are unsupported for automatic configuration and remain untouched. - Native harnesses and their tool processes can inspect export credentials. The settings form and documentation advise using ingestion-scoped credentials. Retained headers remain bound to their saved scheme, host, and port; changing origin requires fresh values or removal. - Migration 0357 adds a company-scoped row and secret reference. It is safe to reapply. Secret removal and company deletion use the existing secret lifecycle. - Slow or unavailable destinations must not block task settlement. Export settings take effect at the next execution preparation boundary. ## Model Used OpenAI Codex, GPT-6, with reasoning, tool use, code execution, and browser verification. 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> |
||
|
|
8a3d2cb04f |
fix(recovery): avoid recursive holds for undispatched waits (#16894)
## Thinking Path > - Paperclip manages AI agents and their work. > - Queue admission must stop work while a previous execution needs recovery. > - The final dispatch gate can cancel a queued run before it starts. > - Legacy recovery treats this known wait as an unknown provider outcome and creates another hold. > - The extra hold can survive repair of the original execution and leave saved messages stuck. > - This pull request uses one database proof to prevent the extra incident and recognize old false holds. > - Saved input can then pass through normal admission with the original work and safety gates intact. ## Linked Issues or Issue Description Refs #15483. **What happened?** The dispatcher writes an `execution_reconciliation_required` cancellation when an existing recovery hold denies a queued run. No runtime is selected and no provider starts. Legacy recovery later creates a `legacy_execution_requires_reconciliation` action for that cancelled admission. Its settled `replay: blocked` record remains an effective hold after the real source recovery finishes. The task has saved messages but no eligible Retry or Continue action. **Expected behavior** A verified admission denial stays a wait. It must not create another provider-outcome incident. Existing false incidents must stop blocking after the server verifies their recorded source. Real execution, uncertain outcomes and file recovery stay held. The harness determines these infrastructure facts; the user does not certify them in a form. **Steps to reproduce** 1. Persist a queued-run gate cancellation with its task-bound `executionWait` receipt and no execution authority or resource evidence. 2. Run legacy reconciliation. On the old code, it creates a second incident. 3. Persist the old incident as resolved with replay blocked, then clear the original source hold. 4. Restart queue recovery with saved user messages. On the old code, no successor is admitted. Related work: #15965 covers other pre-start dispatch cancellations but explicitly excludes this existing-hold code and leaves historical holds unchanged. #16634 covers stale-cancel classification and queue drain, without re-evaluating historical effective holds. #15383 covers an operator Stop during conversation startup. This change addresses the existing-hold receipt and its persisted false incident; it does not copy those broader changes. ## What Changed - Add one database proof for a legacy admission denied by an existing execution hold. Require the exact dispatcher receipt, matching task identity, no runtime or process claim, no lease or finalization coordinator, and no execution events. - Use the proof before legacy recovery creates an incident and when it computes effective historical holds. Keep the old audit rows. - Preserve source file obligations and the original recovery action. Keep the normal queue, pause, ownership, company and budget checks. - Add real PostgreSQL regressions for incident prevention, old state, concurrent queue recovery, message order, conflicting evidence and scope boundaries. - Update the execution contract and both recovery maps. ## Verification - Red: the regression on unfixed source fails on incident classification, historical hold projection and actual periodic saved-message admission. The other 24 safety cases pass. - Green: all 27 new database cases pass. Two safety assertions were aligned with the existing contract: daily limits stop dispatch after queue promotion; a human comment can intentionally reopen a terminal task. The final regression checks the real daily dispatch gate and agent pause. - Existing `explicit-native-continuation.test.ts`: 255 tests pass. Existing legacy recovery and PostgreSQL dispatcher suites: 61 tests pass. - `pnpm -r typecheck`, `pnpm build`, `node scripts/check-maps.mjs` and `git diff --check` pass. - GitHub PR CI run `39313204660` passed on `ef6009e656b7c9b4c788480dce322874565960ac`. All 54 successful check-runs and the Snyk status are green. Two optional Storybook checks were skipped. The independent Paperclip Review completed with a neutral check and a 5/5 assessment with no findings. Greptile also reports 5/5 on the same commit. There are no unresolved review threads. - `pnpm test:run` is still running locally. Its overall result is pending; no full local suite pass is claimed. The exact-head GitHub CI suite passed. - A read-only probe of an affected hosted task verifies the same database proof and projects no false blocker with the working source. No live rows were changed. Deployment and a real resumed provider run remain unverified. ## Risks - An incorrect exclusion could admit work with uncertain effects. The proof fails closed on missing receipts, source mismatches, runtime/process ownership, any retained lease, coordinator, execution event or file obligation. Real upstream file recovery remains blocking in the regression. - The effective-hold query adds indexed existence checks scoped to the recorded run and company. It makes no provider calls and performs no database repair writes. - Historical audit records keep their recorded outcome. Only their effective blocking status changes when the server can prove the admission never ran. - No schema, permission, credential or UI form changes are included. Live recovery still needs verification after rollout. ## Model Used OpenAI Codex, model ID `gpt-6.1-sol`, with reasoning, tool use and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
2e5bf12411 |
test(adapter-utils): retry HTTP/2 fixture port collisions (#16888)
## Thinking Path > - Paperclip manages work for AI agents. > - Sandbox agents use a callback bridge to reach the API. > - Tests start the generated HTTP/2 gateway on an assigned loopback port. > - The test probe releases that port before the gateway binds it. > - Another process can claim the port during that gap. > - This PR retries that specific fixture startup collision and tests its limits. ## Linked Issues or Issue Description **What happened?** The unchanged callback bridge test failed in #16605 because its selected port was already in use. [CI job 118251110752](https://github.com/paperclipai/paperclip/actions/runs/39308303837/job/118251110752) reports `EADDRINUSE` before the gateway READY frame. The same helper is present on master `4d92589799`; no merged or open fix for this exact failure was found. **Expected behavior** The fixture starts on a fresh port after a confirmed bind collision. It stops after three attempts and preserves other startup failures. **Steps to reproduce** The new held-probe case keeps the selected socket open before the real child starts. Before the correction, the original authorization test fails with `EADDRINUSE`. The unchanged no-collision case passes. **Additional context** This is the separate scoped correction for #16605's unrelated CI failure. It changes one test file. ## What Changed - Retry only pre-READY gateway exits with code 1 and the specific `EADDRINUSE` bind diagnostic. - Wait for child close and fully drained stderr before classifying startup. Kill failed attempts and preserve the original failure after three collisions. - Keep the real probe socket open to inject collisions without a timing race. - Verify successful recovery, bounded exhaustion, delayed stderr, and immediate failure for unrelated startup errors. Accept successful starts anywhere within the three-attempt limit. Preserve the original authorization and header-stripping assertions. ## Verification - Negative controls: the held-port authorization case fails with `EADDRINUSE`, and retry exhaustion observes only one attempt before the correction. The ordinary case passes. - `pnpm exec vitest run packages/adapter-utils/src/sandbox-callback-bridge.test.ts`: all 89 tests pass on the final head. - `pnpm --filter @paperclipai/adapter-utils typecheck`: passes. - Initial standard Greptile returned 4/5 for late stderr classification and exact success-count assertions. Both are corrected. The final real-pipe control reproduces missing diagnostics with the old exit listener and passes with close-based readiness. An initial pause-only control was not discriminating because Node resumes pipes on exit; the final control holds that resume until after exit. - Diff checks and the complete secrets/PII review pass. - Full local repository tests and build were not run for this one-file fixture change. Hosted CI and standard Greptile are pending. ## Risks The fixture can still fail after three consecutive collisions. Other startup failures remain failures. The generated gateway and its assigned-port protocol are unchanged. ## Model Used OpenAI Codex, GPT-6, with reasoning, repository inspection, code execution, and 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 (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.1019.0-canary.12 |
||
|
|
313fb265db |
feat(plugins): invalidate runtimes when connector access changes (#16605)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Runtime preparation depends on access and credential state as well as tool definitions. > - Grant, membership, secret, and endpoint changes need committed invalidation. > - Their writers must acquire locks before journal fanout can lock agent rows. > - This pull request adds access hooks with the corresponding transaction guards. > - Plugins can refresh preparation immediately while task-time authorization remains authoritative. ## Linked Issues or Issue Description **What happened?** Grant changes, credential rotation and revocation, company access changes, and connector endpoint configuration do not request runtime synchronization. Journal fanout exposes lock inversions between credential persistence, access cleanup, and connection assignment writers. **Expected behavior** Committed access changes request runtime preparation without polling or credential values in the journal. Agent-specific secret bindings and new personal delegations affect their target agent. Company access changes remain conservative. Provider bookkeeping does not create preparation work. **Steps to reproduce** 1. Change an audience, delegation, membership permission, referenced credential, vault configuration, or endpoint instruction. 2. Expect a committed runtime event in the correct company and scope. 3. Run reconnect, credential refresh, SSH setup, or membership cleanup concurrently with related writes. 4. Expect both operations to preserve access checks and finish without a lock-order cycle. **Additional context** Final feature extraction from #16503. The earlier slices, #16604, and the separate delivery-test correction #16871 are merged. This PR is now the active change against master. The rebase preserves the merged assignment and definition recipient rules, Unicode selector semantics, and profile/reference transaction guards. ## What Changed - Add migration 0356 for grants, audiences, delegation, membership/permissions, secret bindings, referenced credentials and vaults, and chat/email endpoint configuration. - Keep events content-free. Ignore health, delivery, publication, Vercel verification, and GitHub webhook bookkeeping while retaining credential and repository-access changes. - Target agent secret bindings and all personal delegation changes to their old and new target agents. Coalesce delegation changes per transaction. - Lock existing grants before connections and credential persistence in OAuth and cleanup writers. - Reject superseded refresh leases before rotating stored credentials. Ignore lease acquisition and release when access metadata is unchanged. - Serialize audience replacement, validate membership, and preserve unchanged audiences. - Lock membership before permission-only saves and grant before Railway SSH setup. Individual delegation revocation locks its grant and target. Whole-grant and membership cleanup lock company recipients before deleting scoped delegations. - Lock grants and connection inputs before static-key reconnect writes. Lock company agents before cascading secret deletion; use a nonblocking secret lock and bounded retries to avoid a new cycle with credential writers. - Add PostgreSQL concurrency coverage for access writers and endpoint publication/configuration behavior. - Preserve the owner lock for plugin instance-secret removal; these secrets cannot use ordinary bindings. - Align Slack search refresh, callbacks, and disconnect with grant-before-connection locking. Recheck newly discovered grants without waiting before provider work. - Retry complete membership transactions when a credential deletion candidate is busy. Cover all four cleanup entry points and process company access in ID order. - Document final invalidation coverage and task-time authorization boundaries. ## Verification - Current head: `78aace55bef7f52bc5742b131e0b3961eb5c0f11`. All 1,061 tests across 23 affected suites pass. The named Slack authorization integration scenario also passes; it exercises authorization, refresh, disconnect, and rejection of a late callback. Server/database typechecks, migration safety and numbering, five-snapshot retention, feature maps, and diff checks pass. The complete PR diff was reviewed for secrets and personal data before push. Final acceptance: [CI run 39308303837, attempt 2](https://github.com/paperclipai/paperclip/actions/runs/39308303837) is green, with 55 successful checks and two optional Storybook skips. The current-head Greptile reassessment returned **Apex 5/5** at 19:16 UTC on 2026-10-19. Its full summary reports no actionable issues. Security passed, all threads are resolved, and GitHub reports no merge conflicts. The reassessment was requested as a standard review after the fixes; Greptile retained the Apex tier. - On this head, [CI run 39308303837](https://github.com/paperclipai/paperclip/actions/runs/39308303837) failed the unchanged adapter-utils HTTP/2 fixture with `EADDRINUSE` before READY. Its closed probe left a port handoff race. That test and its gateway are byte-identical on master. No upstream fix was found. The deterministic fixture correction is isolated in #16888; no adapter test changes are included here. The failed jobs recovered on retry without a feature source change. The original failure remains documented here, and #16888 carries the fixture correction separately. That retry demonstrates recovery; the held-probe negative control establishes the port handoff race. - Rebased onto master `194fc11406`, including merged #16604 and #16871. Replayed only the access-hook commit. Resolved OAuth, test, and documentation conflicts while retaining both sets of tests. Migration 0356 preserves the merged assignment/definition recipient rules, Unicode selector semantics, and profile/reference guards. - Apex returned 3/5 on `0fb65bc27`. Negative controls reproduce its Slack delegation and member-cleanup deadlocks (`40P01`) and unwanted Vercel/GitHub bookkeeping events. Slack grant writers now take their locks before the connection. A separate late-grant control reproduces `40P01` without the post-lock recheck; the complete guard passes. All four membership cleanup commands retry from a fresh transaction when the credential is busy. Tests verify successful cleanup and no journal rows from failed attempts. Credential IDs and repository-access changes still notify runtimes. - Earlier review corrections remain covered: static-key reconnect and cascading secret removal each reproduce `40P01` without their guards. Grant lease acquisition/release is ignored. Secret removal releases agent locks when a credential writer is busy. Instance-secret removal retains the owner lock and passes its public plugin API contention regression. Delegation updates and revocations target old/new agents; unrelated-peer, coalescing, unchanged-update, and rollback cases pass. Three negative controls verify the required whole-grant and membership cleanup guards after narrowing delegation scope. - Preserve prior acceptance failures: the first rebased 20-suite run passed 1,025/1,026; its only failure was a draft uninstall fixture blocking a random peer. Blocking the assigned agent corrected that assumption, and all 44 access/assignment tests passed. Later, all 1,044 tests across 21 suites, [CI run 39302185527](https://github.com/paperclipai/paperclip/actions/runs/39302185527), standard Greptile 5/5, and security passed on `0fb65bc27`. That did not clear the later Apex findings described above. Draft run 38975428081 failed a server shard; its cause was not re-investigated. A later green run does not establish that earlier cause. - Local fixture corrections are recorded separately from product failures: an assignment filename filter initially matched no file; the actual suite was included in full runs. A delegation fixture omitted its required creator, and a guard run omitted a query import. The new global-access cleanup fixture now uses its own user to avoid earlier fixtures' memberships. All were corrected before publishing their final iterations. - Local checks target affected services and real PostgreSQL boundaries. A full local build and repository-wide test run were not performed. Hosted CI supplies broader verification. Provider responses in tests are controlled; live provider behavior was not qualified. ## Risks Migration 0356 adds triggers without changing table schema. Apply it through the normal migration flow. Most access changes retain synchronous company-wide invalidation. Company fanout takes O(eligible company agents) locks and journal rows, without a fanout ceiling or mutation quota. Agent secret bindings and individual delegation changes retain narrower recipients. Events contain no credentials. Physical removal of non-instance secrets takes ordered locks on all company agents before cascading into bindings. This costs O(company agents) locks even for an otherwise unreferenced secret. Instance secrets cannot use ordinary bindings and retain their owner lock. A busy secret lock releases the transaction guards and retries up to three times. Continued contention returns a retryable conflict. Provider deletion stays outside that transaction; a retry resumes removal of an already disabled secret. Membership cleanup uses nonblocking credential guards and retries the full membership transaction. Slack search adds two grant queries, scoped to the subject and connection. Its retries occur before provider work or credential persistence. Each retry loop is limited to three attempts. Invalidation requests preparation; task-time authorization and provider session activation remain authoritative. Provider calls use fixtures; no live provider qualification is claimed. ## Model Used OpenAI Codex, GPT-6, with reasoning, repository inspection, code execution, and 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 (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> |
||
|
|
06d4fe3121 |
perf(runner): preload essential Claude task tools (#16885)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The Runner exposes assigned tools to Claude through an authenticated MCP bridge. > - Claude can defer these tools and search for them before a simple task can finish. > - Title and terminal tools are common requirements for a task turn. > - This pull request marks those three tools for immediate loading by Claude. > - The remaining tools keep the SDK deferral policy and the existing access checks. ## Linked Issues or Issue Description Refs #15993, #15994, #15997. **What existing behavior does this improve?** Claude Runner tool discovery during task execution. **Current behavior** Claude can use ToolSearch to discover the mandatory title and terminal tools before it answers a simple task. **Proposed behavior** Expose `set_task_title`, `paperclip_finish`, and `paperclip_block` in the first Claude request through per-tool `anthropic/alwaysLoad` metadata. Keep other tools deferred under the SDK policy. **Reason and benefit** Remove an avoidable tool discovery step without changing the model, effort, or authorization. Repeated product measurements will check the latency benefit. ## What Changed - Add closed metadata for the three essential tools only in Claude runtime hosts. - Keep incoming metadata discarded and private tools hidden. Keep other providers unchanged. - Test real bridge catalogs and provider routing. Check the pinned Claude SDK request against a loopback fixture with no paid calls. - Advance the pending Copilot source binding because it attests the shared bridge file. Preserve historical profile readers and qualification limits. ## Verification - Focused bridge, admission, profile, and effort controls: 185 passed, one skipped. Three provider-routing cases pass. - Runner TypeScript compilation passes. - The production SDK fixture loads exactly three essential tools with the change and zero in the controlled baseline. The document tool stays deferred. - Six real API-key tasks used Opus 5.5 / High in alternating order A B B A A B. Median first assistant receipt was 22.021 s baseline vs 17.060 s candidate (22.5% lower). Median total was 24.119 s vs 19.150 s (20.6% lower). ToolSearch was 3/3 baseline vs 0/3 candidate. All six tasks saved a title and accepted finish. A separate candidate follow-up resumed the same provider session and finished without ToolSearch. - Median startup was 4.786 s baseline vs 5.381 s candidate. This change does not improve startup. Three samples per version give directional evidence only. - Estimated cost for the six tasks was $0.850900800. Candidate total was $0.450341800 vs baseline $0.400559000; the first candidate wrote a new cache prefix. These rate-card estimates are not invoices. - The benchmark used source `5aed3c6a083cf8e6246815455abde3b29ecbbbac`. Rebuilding both bundles at master-reconciled head `d2da07259048c0a2bebd210c35cc0ebb3ff42c67` produced identical SHA-256 values. Baseline bundle SHA-256: `10a92c373bba4fb630bf4fefeab953d850a77cf8258bc2e94711410a73a78ecd`. Candidate: `40348fc67a3b1ae5cc1f27f933f369981d31bcdf5d1bdc7b1797968ddfe53938`. Baseline differs only by compiling the Claude preload selector as false. Fresh task sessions avoid checkpoint changes. - Full local runtime-host runs exposed credential lease collisions in existing cases. A later complete host run passed 67 cases and timed out in an existing admission-abort case; that case passes in isolation. All failures are retained. Focused controls pass. Complete Runner suites, repository typecheck, tests, browser checks, and build pass in cloud CI on this head. ## Risks - These three tool schemas add input to Claude requests. Measurements must include token usage and cost. - Copilot source identity changes because it includes the bridge source hash. It remains pending qualification. Its catalog and executable closure do not change. - The test fixture proves request shape. It does not prove real-provider latency or platform package qualification. ## Model Used OpenAI Codex, GPT-6 family, with reasoning, tool use, and code execution. The exact serving model ID and context window are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass (focused controls and isolated cancellation check; broad local failures are retained above) - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [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> |
||
|
|
e6dcd1e8e9 |
feat: add Commentary to Audit with filters and shareable messages (#16884)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agents can submit suggestions and complaints while they work. > - Operators currently need database access to read those messages. > - That makes it hard to find feedback from one agent or share a specific message. > - This pull request adds a standard Commentary tab in Audit. > - Operators can filter messages, browse 50 at a time, and share links to full message dialogs. ## Linked Issues or Issue Description Refs #15367, which added feedback storage and agent submission. The duplicate search found no open PR for a commentary reader. **Subsystem affected** Server, shared API contracts, and the board UI. **Problem or motivation** Agent suggestions and complaints are stored but have no board reader. Operators must query the database to inspect feedback. **Proposed solution** Add Commentary to Audit without an experimental toggle. Show previews, agent and message-type filters, text search, and 50-message pages. Opening a row updates the URL. A copied URL opens the full message with its agent, task, and run context. **Alternatives considered** Direct database queries remain useful for operators, but do not provide a normal product workflow. An experimental setting would add setup to a read-only audit page. **Roadmap alignment** This completes the operator view for the existing feedback feature. It supports human oversight and does not change agent execution or task ownership. ## What Changed - Add company-scoped, board-only list and detail endpoints with audit permission and source-task privacy checks. - Return bounded previews and counts. Fetch full bodies only when a message opens. - Add the Commentary tab, search, filters, 50-row pagination, and URL-based selection. Audit tab destinations work in both layouts, with a classic sidebar entry for Commentary. - Add production Storybook examples for populated, filtered, linked, long, paginated, empty, loading, failed, denied, mobile, and light states. - Update API documentation and the feature and agent access maps. ## Verification - Final head `abc4a251c14cfbfec007542214beec528f2b18bf`: 55 checks pass; two conditional Storybook checks are skipped. The PR workflow is successful. Greptile is 5/5 with all findings resolved. - Focused database, HTTP, submission, OpenAPI, and UI regression tests cover company isolation, task privacy, filter bounds, 50-row pagination, and copied message links. - Browser Storybook journeys cover row opening, direct links, combined filters, search, and pagination. Storybook uses synthetic API fixtures; database authorization is tested separately. - Token gates, feature maps, and Storybook catalog validation pass. - `pnpm -r typecheck`, `pnpm build`, and `pnpm build-storybook` pass on the rebased branch. All 80 focused tests and all 37 Audit tests pass, including the real App route table in both layouts, task grant/revocation through HTTP, deleted-task privacy, and URL UI regressions. The full suite passes in the parallel PR CI matrix. The local serial full-suite run was stopped before completion after checking the recorded 94-minute serial duration. Local focused tests, workspace typecheck, production build, and final server/UI checks pass. - The linked-message Storybook test initially asserted against the loading dialog. It now waits for the message body; both direct-link and row-open journeys pass. - Native and legacy deleted-task privacy regressions failed before the fix and pass afterward. The reader checks the run task binding after the task foreign key clears. - A rapid search-then-agent-filter browser regression reproduced the search overwriting the selected agent. The pending search now restarts when URL filters change. The same browser test passes with both filters applied. - CI found two existing AuditHub assertions that still expected five tabs. They now assert the six-tab model and selected-company Commentary rendering. All 37 Audit tests pass. All other test and build jobs passed before this test-only correction. - The [agent-chat attachment browser test](https://github.com/paperclipai/paperclip/actions/runs/39307881171/job/118250189664) timed out waiting for an attachment preview. The [same shard passed on the prior head](https://github.com/paperclipai/paperclip/actions/runs/39306658703/job/118245498343) with identical application code; the intervening change only updates AuditHub unit tests. The single retry passed on the same head. The precise cause of the earlier failure remains unconfirmed. ## Risks - Commentary may contain sensitive task context. The reader requires board access and audit permission, and filters source-task visibility before returning previews, counts, or full bodies. - Text search scans stored message bodies. Pages are bounded and full bodies are fetched on demand. - Offset pagination can shift if new messages arrive while paging. Ordering uses timestamp and ID for stable ties. - No database migration or agent submission behavior changes are required. ## Model Used - OpenAI Codex, GPT-6 family, with reasoning, tool use, browser interaction, and code execution. The exact backend model ID and context-window size are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
d747752496 |
fix(runner): record why an OpenCode turn fails when opencode serve stops (#16863)
When `opencode serve` stops during a turn, the OpenCode driver now fails the active turn itself with a closed-vocabulary cause (server exit code or known signal, allowlisted socket error code, HTTP status, or closed stream) instead of leaving runnerd to close it with `error: null`. The proxy flushes stdout before a fatal exit so the failed turn reaches runnerd, and the server records OpenCode failed turns as `nativeTurnFailure` (live and persisted-recovery paths) so the run-failure diagnostic names the cause. Provider text is never copied. Run status, retries and recovery behaviour do not change. Co-Authored-By: Paperclip Sentry triage <Paperclip-Paperclip@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
8193abb936 |
feat(claude): default qualified macOS and Linux targets to Paperclip Runner (#15997)
## Thinking Path > - Paperclip must run the selected agent on its selected host. > - Claude needs verified packages for each supported target. > - A Mac controller must select the correct Linux provider pack. > - New defaults must follow package and execution evidence. > - This PR adds Claude platform packaging and target-specific pack selection. > - Existing Codex Linux ARM64 behavior remains intact. ## Linked Issues or Issue Description Refs #15683. This PR depends on #15993 and #15994. Related scope: #15422 and #15224. ## What Changed - Reuse the merged four-target daemon producer/consumer matrix. Add target-owned Linux provider packs and carry their immutable identities through release assembly and vendoring. - Reuse master’s landed pinned Claude SDK ARM64 executable admission and retain package-integrity, architecture and no-follow admission. - Select target-specific remote packs so Mac controllers can use Linux hosts without a development pack override. - Preserve read-only runtime context on SSH startup and resume without accepting unverified old content. - Check ordinary installed Claude readiness without injected package authority. Retain Codex and Linux x64 consumer checks. - Extend Claude automatic target selection for the remaining qualified package targets. Retain unsupported-platform and external-override behavior. - Qualify managed Daytona snapshot names through provider IDs during Claude Connect. Pin native acquisition to the measured ID. Preserve a revocation marker after failed probes or target edits, and block native acquisition until requalification instead of falling back to a mutable name. Preserve immutable-image proof, company and account boundaries, and Legacy acquisition. ## Verification - Reconciled with master `9179d8dcc3e908c217fde4f63c9d08ccf8132eeb` through the prerequisite stack, retaining the merged startup fix and latest Codex Linux ARM64 behavior. - [Four-target exact-source package qualification](https://github.com/paperclipai/paperclip/actions/runs/39267321383) passed on source `04e0202ca81387b17cbe7fd094a8338648356fe9`: all four native builds, public-package assembly, Linux x64 verification and clean installed consumers on Apple Silicon, Intel Mac and Linux ARM64. The later master reconciliation adds shared OpenRouter attribution and changes runtime source. This historical result keeps its original source identity; [later qualification](https://github.com/paperclipai/paperclip/actions/runs/39281100929) passed at `dca62c7aeb4b45f0dd91a8e18d386a16a2658ef8`. It predates the subsequent TypeScript startup fix. - Fresh local product acceptance on integrated source `b2c9fe43f9cd3bc5dd9d22552da0148845ba71a4` completed a useful file and follow-up through native Claude/Opus 5.5, High effort and the API-key connection. Both actual browser downloads were independently checked; the revision preserves the original body and session continuity. Total task estimates: $0.518432800. Ordinary web and API creation saved defaults with the native experiment disabled. - Local focused verification passed 993 startup/session tests, 243 UI tests, 12 workflow security tests, direct server/UI TypeScript checks, and token/palette gates before the last review changes. Initial DB-backed snapshot pin/revocation coverage passed 18 cases; the final serial route suites pass 122 credential/permission and 232 snapshot/environment cases after correcting a test hook timeout. Current-head cloud suites pass. - Preserved the failed pre-provider local fixture and its full pending reservation. The successful fixture has no unpriced or pending usage. Historical failed Cloud journeys, accounting holds, source identities and subscription limitations remain in the dated plan. - All Docker/Rust release production was performed in cloud CI. No local Docker image was built. An inadvertently invoked local Rust prerequisite was stopped. - Current-head cloud CI is green. All three stack PRs have fresh Greptile 5/5 reviews and zero unresolved review threads. Required typecheck, test and build gates ran in cloud CI; Docker work stayed remote. Earlier failed checks remain in their original runs. - The final master merge preserves task-loading, permission, skill-retention and OpenRouter changes. Pi uses a fresh combined profile 27, preserving both historical profile-24 declarations; Copilot remains profile 22. Focused protocol checks passed 155 cases (one skipped), the updated Pi attestation check passed 18 (one skipped), and 91 evaluation/catalog checks passed. - Latest-application manual continuation passed in 37.942 seconds on `695e5c005a85bddc8711d3fcddcaf6b7e1fb64d0`, with High effort, native Opus 5.5, Anthropic API attribution, the same resumed Claude session, an independently checked 635-byte file and persisted Done status. It uses the earlier verified Mac daemon; the preceding-source package qualification passed at `dca62c7aeb4b45f0dd91a8e18d386a16a2658ef8`. That package run predates the small TypeScript startup fix and is not relabeled as qualification for it. - Upgrade limitation: changed compiled sidecar identity rejected old durable launch state and recovery hit session-open bounds before eventually resuming. That attempt was operator-cancelled and retained; the successful manual continuation does not qualify seamless upgrades. - Local latency profile, Opus 5.5/High unchanged: three alternating real-ACP loopback samples per variant reduce median provider-ready time from 5.081s to 4.034s. The matched real API task startup improves from 5.533s to 4.348s, but total reply time changes from 17.933s to 20.221s because agent work varies. This establishes a startup saving of about one second, not a consistent total-reply speedup. A real candidate follow-up passed in 20.146s and resumed the same saved session. The loopback fixture makes no external model requests; failed initial probes remain retained. - The startup change passes 107 focused runtime/effort/lease tests, 53 profile checks (one skipped), TypeScript checking and the TypeScript-only runtime build. Native hire fixture checks pass 70 tests; their first local run retained a socket-hangup failure and stale OpenCode expectation, both accounted for before the passing rerun. Broader required checks run in cloud CI. ## Risks - **Experience needs improvement:** successful connection setup still shows “Connection needs attention” because runtime checks are deferred. Cold provider-pack upload took 122–126 seconds per run while the task mainly showed “Thinking.” The tested Core-only preview excludes private Cloud UI plugins; this is not full Cloud distribution or subscription qualification. Desktop dark theme was tested; mobile and comprehensive accessibility were not. The portable report validates, but gallery interaction could not be inspected because host preview was queued. - The optional supply-chain scan returned neutral/inconclusive because GitHub Actions package coverage and infrastructure parsing are unavailable. It is not counted as a successful supply-chain qualification. Exact package, daemon and image integrity checks passed. - A stale, missing or wrong-architecture pack must fail admission. It must not change runner or target silently. - Provider-pack source changes invalidate affected earlier execution results. Existing unknown-cost and cleanup holds remain intact. - Live subscription execution remains unverified under the API-key qualification direction. Built-in authentication flows are retained. ARM64 cloud-image production is deferred. Merge and production deployment remain separate. ## Model Used OpenAI Codex, GPT-6 family, with reasoning, repository tools, code execution and browser testing. 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 - [ ] Focused local tests and final cloud verification pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.1019.0-canary.11 |
||
|
|
5739a53f5f |
fix(tests): sanitize installed-consumer validation processes (#16797)
Start installed-consumer validation through Node and remove ambient Node startup settings before test processes start. Keep pinned historical source fixtures available in shallow checkouts and set filesystem fixture conditions explicitly. Co-Authored-By: Paperclip <Paperclip-Paperclip@users.noreply.github.com> |
||
|
|
4d92589799 |
perf(ui): defer hidden task rendering until history is ready (#16878)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - People open a task to read saved work and reply. > - The conversation waits for its initial data so messages do not move after reveal. > - The hidden conversation and editor still render while those reads are pending. > - Profiling showed a useful cold-load gain when that hidden rendering was delayed. > - Prepare ordinary task content after its initial data is ready. Keep the existing preparation path for comment links. > - Keep the skeleton, measured reveal, timeout, and mounted conversation during refresh. ## Linked Issues or Issue Description Follow-up to #16862 and #16849. Related task-layout work: #14758. Searches found no overlapping open rendering change. **What existing behavior does this improve?** Opening a task mounts hidden message rows and the rich editor while supporting reads are still pending. These trees can render again as data arrives before the user can see or use them. **Subsystem affected** UI task conversation startup and its browser acceptance suite. **Proposed behavior** Keep the existing skeleton and outer layout containers. Prepare the hidden conversation and composer when initial history is ready, then use the existing measured reveal. Keep content mounted after reveal. Hash navigation retains eager preparation so older comment targets can be positioned before reveal. The existing 15-second timeout still reveals available history and the composer. ## What Changed - Gate concealed history and composer children with the existing history readiness, revealed-task latch, timeout, and scroll-navigation hash. - Keep data queries, shell geometry, scroll ownership, and the reveal frame unchanged. - Update unit coverage for deferred content, comment-link preparation, task changes, history timeout, and mounted editor identity during refresh. - Add a real browser journey that holds a background task read, retains the same editor and draft, reloads the saved draft, sends one reply, and checks the persisted comment independently. - Document the loading and draft acceptance paths. ## Verification - Repository-wide `pnpm -r typecheck` and `pnpm build` passed locally. Token gates and all 231 task-thread unit cases passed. - Seven regression cases failed against the old rendering behavior before the source change. - All 14 loading and layout browser cases passed again against the final production UI and API build at `15c360aa63e01ad9318aaf7865c07d1ee0d36968`. Coverage includes delayed initial data, reading anchors, media growth, composer sizing, older history, cold comment links, desktop/mobile same-task links and Back, rapid switching, reduced motion, failed reads and retry, stalled history, plan reuse, and cached-task profiling. - The new draft journey retained the same editor during a blocked background task refresh, restored the draft after reload, and persisted exactly one reply. - Final performance comparison used current master `249ab47d41834f174ddd5e9523dc07fa8ebd8e4c` and implementation `15c360aa63e01ad9318aaf7865c07d1ee0d36968` against the same local 160-message Markdown conversation and API process. Conditions: 50 ms network latency, 9 Mbps down/1.5 Mbps up, 4x CPU slowdown, fresh browsers, five alternating pairs per scenario, no CPU profiler, and no concurrent local build/test work. Warm task navigation improved in all five pairs: median paired saving **405 ms**; variant medians **1,787 → 1,456 ms**. Cold results were mixed: paired saving **−89 ms** (slower), despite variant medians **3,188 → 3,021 ms**. There is no consistent cold-load gain established by this comparison. - Earlier prototype comparisons showed paired cold savings of 259–283 ms. Those gains did not consistently reproduce in the final comparison. These are bounded local measurements and do not establish deployed staging latency. - The first prototype delayed comment-link preparation too and failed the older-comment anchor check by 240.5 px. The narrowed implementation keeps hash navigation on the existing eager path. That case and the full suite now pass. The original failure trace is retained locally. - A visual browser walkthrough read the saved conversation and plan, restored a draft after reload, sent it once, reloaded again, and independently checked that exactly one reply was saved. - Greptile reviewed this exact commit at 5/5, with no actionable findings or inline comments. - The duplicate local `pnpm test:run` attempt was interrupted while the same suites were completing in sharded CI so local performance could be measured on an idle host. It is not counted as a local full-suite pass. - All current-head [CI jobs passed](https://github.com/paperclipai/paperclip/actions/runs/39296740548), including the server, workspace, Runner, serialized, browser, typecheck, build, canary, and final verification gates. The first run failed one native-process supervision test (`preserves a real listening process and its marker when a health RPC times out`). Its unchanged shard and dependent gate passed on retry. The specific test also passed locally. No source change was made for that transient failure. ## Risks Delaying preparation can change initial scroll geometry. Hash navigation keeps the existing preparation path because it needs the target present before positioning. The revealed-task latch keeps refreshes from removing history or the editor. The existing timeout still makes saved content and the composer accessible when reads stall. No API, database, permission, or provider changes. ## Model Used OpenAI Codex, GPT-6, with reasoning, repository tools, code execution, and browser verification. A more precise runtime model identifier and context-window size are unavailable. ## 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> |
||
|
|
45b67f1d93 |
feat: default new Apple Silicon Claude agents to Paperclip Runner (#15993)
## Thinking Path > - Paperclip lets users choose an agent harness and account. > - The server resolves the runner for new agents. > - Claude still needs the same ordinary native-default journey as Codex. > - Existing agents must retain their runner, model and account. > - This PR defaults new Apple Silicon Claude agents to Paperclip Runner with Opus 5.5. > - Users can connect and work without a runner override. ## Linked Issues or Issue Description Refs #15683. This PR depends on #15994 and precedes #15997. Related scope: #15422, #13978 and #15224. ## What Changed - Resolve new Apple Silicon Claude agents to `paperclip_runner`, `provider: acpx`, `acpxAgent: claude`. Keep explicit Legacy, models, provider routing and saved execution. - Use `claude-opus-5-5` for ordinary Claude defaults and retain explicit overrides. - Reuse existing API-key/subscription connections, credential storage and checks. Generalize the shared Advanced runner control with Claude branding. - Carry configured effort into the shared v9 contract. Preserve compatible permissions, instructions, skills, timeouts and session behavior. Require Legacy for unsupported settings. - Qualify a new immutable managed Claude target at explicit Connect through the existing permission-gated probe. Use fresh scoped discovery for test and hire. Discard stale results and require an explicit Connect after settings change. - Retain merged Codex onboarding recovery, auth preparation, import/effort corrections and Grok Bot gates. - Check the Claude first-task wizard's saved default directly. Update configuration/runtime documentation and exact Opus 5.5 accounting. - Align hire fixtures with the merged host-environment restriction. Native agent-authenticated hires cannot inject host env settings; both creation endpoints verify that no extra agent is saved. ## Verification - Updated onto master `9179d8dcc3e908c217fde4f63c9d08ccf8132eeb` through #15994. Native input v9 carries effort while preserving v7 home modes and v8 Muse. Codex defaults remain unchanged. - Focused local verification passed 285 server tests, 323 UI tests, 124 setup/registry tests, and two v9 permission-pin transport cases. Direct server/UI TypeScript checks passed. An initial 30-second hook timeout was resolved by serial verification with a longer hook budget: all 122 credential/permission cases and 232 snapshot/environment cases pass. Direct server TypeScript checking also passes. - Ordinary web creation with the experiment disabled saved native Claude, Opus 5.5 and High effort without runner/model overrides. The actual product task and follow-up both succeeded on integrated source `b2c9fe43f9cd3bc5dd9d22552da0148845ba71a4` with the cloud-built daemon from `04e0202ca81387b17cbe7fd094a8338648356fe9`. The final master reconciliation also changes shared runtime source. Historical proof retains its source identity; a final-source cloud qualification is running before refreshing the preview daemon. - Both actual browser downloads were checked: v1 has three sections/six checkboxes (451 bytes); v2 preserves the original body and adds two Rollback checks (612 bytes). The original attachment stayed byte-identical. The follow-up records session resume and the same provider session. Total estimated API usage: $0.518432800, with no pending/unpriced usage in the successful fixture. - Fixed the live-discovered setup incompatibility: native API-key validation no longer depends on the global Legacy Claude CLI. The existing provider endpoint verifies the key without a paid prompt; subscription/custom routing probes remain intact. - Fixed security review's native-hire credential redirection: agent-supplied URLs, proxy/launch settings and other host environment controls are rejected before inheritance. Native credential references remain supported and partial edits use the saved harness. Added create/hire/update regression coverage. - Current-head cloud CI is green. All three stack PRs have fresh Greptile 5/5 reviews and zero unresolved review threads. Required typecheck, test and build gates ran in cloud CI; Docker work stayed remote. Earlier failed checks remain in their original runs. - Docker and native release builds ran in cloud infrastructure. An inadvertent local Rust prerequisite was stopped; no local Docker build was run. - The final master merge preserves task-loading, permission, skill-retention and OpenRouter changes. Pi uses a fresh combined profile 27, preserving both historical profile-24 declarations; Copilot remains profile 22. Focused protocol checks passed 155 cases (one skipped), the updated Pi attestation check passed 18 (one skipped), and 91 evaluation/catalog checks passed. - Latest-application manual continuation passed in 37.942 seconds on `695e5c005a85bddc8711d3fcddcaf6b7e1fb64d0`, with High effort, native Opus 5.5, Anthropic API attribution, the same resumed Claude session, an independently checked 635-byte file and persisted Done status. It uses the earlier verified Mac daemon; the preceding-source package qualification passed at `dca62c7aeb4b45f0dd91a8e18d386a16a2658ef8`. That package run predates the small TypeScript startup fix and is not relabeled as qualification for it. - Upgrade limitation: changed compiled sidecar identity rejected old durable launch state and recovery hit session-open bounds before eventually resuming. That attempt was operator-cancelled and retained; the successful manual continuation does not qualify seamless upgrades. - Local latency profile, Opus 5.5/High unchanged: three alternating real-ACP loopback samples per variant reduce median provider-ready time from 5.081s to 4.034s. The matched real API task startup improves from 5.533s to 4.348s, but total reply time changes from 17.933s to 20.221s because agent work varies. This establishes a startup saving of about one second, not a consistent total-reply speedup. A real candidate follow-up passed in 20.146s and resumed the same saved session. The loopback fixture makes no external model requests; failed initial probes remain retained. - The startup change passes 107 focused runtime/effort/lease tests, 53 profile checks (one skipped), TypeScript checking and the TypeScript-only runtime build. Native hire fixture checks pass 70 tests; their first local run retained a socket-hangup failure and stale OpenCode expectation, both accounted for before the passing rerun. Broader required checks run in cloud CI. ## Risks - Missing packages, authentication rejection, unsupported settings and unavailable models must fail explicitly. Existing agents retain saved execution; explicit runner changes use existing revision/session invalidation. - Subscription follow-up remains unverified; remaining live acceptance uses API keys per human steering. Historical accounting holds and the separate $50 ceiling remain intact. - The subscription acceptance limit remains explicit for review. No Claude database migration is introduced. ## Model Used OpenAI Codex, GPT-6 family, with reasoning, repository tools, code execution and browser testing. 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 - [ ] Focused local tests and final cloud verification 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> |
||
|
|
9e8a9f28d5 |
fix(github): recover long publications from durable receipts (#16883)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agents publish GitHub reviews through governed tools. > - GitHub can accept a publication before the caller receives its result. > - Exact retries must return the existing publication receipt. > - The gateway compared a shortened audit hash with a complete request hash. > - Long reviews therefore failed the retry check even when their content was unchanged. > - This pull request checks the complete saved publication and returns its current receipt. > - Agents can confirm their work without another provider write. ## Linked Issues or Issue Description Refs #16284, which added durable publication recovery. Refs #16275, which extended the GitHub tool deadline. **What happened?** An exact review retry returned an idempotency conflict after GitHub had published the review. The invocation hash uses an audit preview that shortens strings to 500 characters and arrays to 50 entries. The gateway compared that hash with the complete request hash. The earlier retry tests used short assessments. **Expected behavior** An unchanged request returns its durable receipt. Changed content, changed authority, or a missing publication must not cause another write. **Steps to reproduce** 1. Submit a review with a summary and rationale longer than 500 characters. 2. Let publication finish after a short caller deadline. 3. Repeat the exact request. Before this fix, the gateway returns an idempotency conflict. **Paperclip version or commit** Reproduced on master at `c5226daf7a37559ddc007446681717791d80a223`. ## What Changed - Use the durable publication's complete request check for GitHub retries. Keep run, agent, task, connection, tool, and current authority checks. - Return the saved receipt through normal gateway validation and bookkeeping. Leave pending provider work to the durable worker. - Refuse retries without a saved publication. Keep existing invocation keys and audit previews unchanged. - Cover long reviews, comments, progress updates, text suffix changes, nested coverage changes, pending receipts, missing publications, and revoked access. - Document the recovery contract and verification recipes. ## Verification - Red: both long-review receipt cases failed on unchanged production code with the expected idempotency conflict. - Green: all 144 GitHub review workflow tests passed on the final source. This includes long reviews, comments, progress updates, pending and missing receipts, revoked policy, and the native assigned-tool entry point. - Server and workspace typechecks passed. The production build passed. - Map checks passed. These are structural checks. - The first broad run found an incorrect new fixture assumption: its discovery query returned two review tools. The fixture now selects the exact submission tool. An existing description-edit polling test also timed out; it passed separately without a production change, then passed in the complete 144-test rerun. Both earlier failures remain recorded. - Final commit `7cdcdc3a1ac79cb4ed77510a32d795228e3315e8` passed all 55 CI checks. Two optional Storybook jobs were skipped. [Complete CI run](https://github.com/paperclipai/paperclip/actions/runs/39304187397). Greptile is 5/5 on this exact commit, with zero unresolved review threads. - The earlier local full-suite attempt was stopped after the fixture correction. The final local full-suite attempt was stopped after complete final-head CI passed. No complete local full-suite pass is claimed; full-suite acceptance uses the current-head CI matrix. - Provider responses are controlled fixtures. Native assigned-tool coverage uses the production gateway and disposable PostgreSQL. No live GitHub fault injection, deployment, or historical task recovery is claimed. ## Risks A pending receipt remains pending. It does not complete the task. Caller retries no longer dispatch provider work; the durable worker retains that responsibility. A missing durable publication returns a conflict because the gateway cannot establish the original write's outcome. Existing approval and revocation checks remain effective. No database migration or audit hash change is required. ## Model Used OpenAI GPT-6 through Codex, with reasoning, tool use, and code execution. The session does not expose a more specific serving model ID or context-window limit. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and 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> |
||
|
|
95672307f4 |
feat(runner): carry acknowledged Claude effort through native resume (#15994)
## Thinking Path > - Paperclip manages AI agents and their work. > - The native runner must carry each supported agent setting. > - Claude effort must reach its ACP session before a prompt and after resume. > - Installed Claude setup must find the owning server package without a qualification override. > - This PR adds those shared contracts and preserves historical readers. > - The Claude default change can then use the same runner path. ## Linked Issues or Issue Description Refs #15683. This prerequisite follows the actual Codex squash `adb69e8f09852c772d9901ae270e5b2d66e39c77`. Consumers: #15993 and #15997. Related scope: #15422, #13978 and #15224. ## What Changed - Add native-input v9 for Claude effort. Preserve v1–v8 readers, including v7 explicit home modes, v8 Muse, Dot and Grok Bot. - Preserve prepared task input and constraints through the newer contracts, including completion-only continuation without wrapping compact model input again. - Carry effort through daemon/sidecar admission; require provider acknowledgment before prompting and after resume. - Find installed server package authority through the verified canonical layout. Retain package-integrity, digest, architecture and no-follow checks. - Return Claude startup cancellation promptly while retaining unfinished settings writes and the lifetime lease through cleanup. Preserve merged Codex close/cleanup behavior. - Retain both independently authored historical Pi profile-24 declarations. Combined master/Claude source attestations use Pi profile 27; pending Copilot remains profile 22. This does not expand either provider's qualification boundary. - Avoid a spare verified executable snapshot when Claude effort control reuses its initialized provider. Preserve cold-control snapshot renewal and acknowledged effort. ## Verification - Reconciled with master `9179d8dcc3e908c217fde4f63c9d08ccf8132eeb`, retaining its task-loading, progress, skill-retention, permission and OpenRouter changes. - Final focused protocol/provider checks passed 155 tests (one skipped), the updated Pi attestation check passed 18 (one skipped), and 91 evaluation/catalog checks passed. Generated TypeScript/Rust profile checks and Rust formatting pass. The integrated consumer's TypeScript-only runtime build also passes. - Earlier branch checks passed 369 protocol tests (one skipped), 72 catalog checks and TypeScript checks/build; their source identities remain historical. No Rust compilation or Docker build is needed locally for this proof. - Current-head cloud CI is green. All three stack PRs have fresh Greptile 5/5 reviews and zero unresolved review threads. Required typecheck, test and build gates ran in cloud CI; Docker work stayed remote. Earlier failed checks remain in their original runs. - [Earlier four-target package qualification](https://github.com/paperclipai/paperclip/actions/runs/39267321383) passed on source `04e0202ca81387b17cbe7fd094a8338648356fe9`; it is not relabeled as proof for the final merge. Existing failures and unknown-cost holds remain preserved. - Current-head cloud CI is green. All three stack PRs have fresh Greptile 5/5 reviews and zero unresolved review threads. Required typecheck, test and build gates ran in cloud CI; Docker work stayed remote. Earlier failed checks remain in their original runs. - Latest-application manual continuation passed in 37.942 seconds on `695e5c005a85bddc8711d3fcddcaf6b7e1fb64d0`, with High effort, native Opus 5.5, Anthropic API attribution, the same resumed Claude session, an independently checked 635-byte file and persisted Done status. It uses the earlier verified Mac daemon; the preceding-source package qualification passed at `dca62c7aeb4b45f0dd91a8e18d386a16a2658ef8`. That package run predates the small TypeScript startup fix and is not relabeled as qualification for it. - Upgrade limitation: changed compiled sidecar identity rejected old durable launch state and recovery hit session-open bounds before eventually resuming. That attempt was operator-cancelled and retained; the successful manual continuation does not qualify seamless upgrades. - Local latency profile, Opus 5.5/High unchanged: three alternating real-ACP loopback samples per variant reduce median provider-ready time from 5.081s to 4.034s. The matched real API task startup improves from 5.533s to 4.348s, but total reply time changes from 17.933s to 20.221s because agent work varies. This establishes a startup saving of about one second, not a consistent total-reply speedup. A real candidate follow-up passed in 20.146s and resumed the same saved session. The loopback fixture makes no external model requests; failed initial probes remain retained. - The startup change passes 107 focused runtime/effort/lease tests, 53 profile checks (one skipped), TypeScript checking and the TypeScript-only runtime build. Native hire fixture checks pass 70 tests; their first local run retained a socket-hangup failure and stale OpenCode expectation, both accounted for before the passing rerun. Broader required checks run in cloud CI. ## Risks - Explicit Claude effort needs a daemon and sidecar that support input v9. Historical readers stay available; downstream builders and permission-pin transport checks must also use v9. - Source-bound profile changes may require reopening older Pi/Copilot sessions. Copilot remains pending and executable package closures remain unchanged. - This prerequisite changes shared runtime behavior; Claude default selection remains in #15993/#15997. No database migration or Codex default change is introduced. ## Model Used OpenAI Codex, GPT-6 family, with reasoning, repository tools, code execution and browser testing. 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> |
||
|
|
c5226daf7a |
fix(cloud): enable experimental toggles on staging (#16876)
Allow instance admins to change approved experimental feature controls on managed Cloud staging. Preserve production restrictions and managed access and execution policy. Co-Authored-By: Paperclip <noreply@paperclip.ing>canary/v2026.1019.0-canary.10 |
||
|
|
194fc11406 |
feat(plugins): invalidate runtimes when tool definitions change (#16604)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Lifecycle plugins must refresh runtime preparation when tool definitions change. > - Standing assignments alone do not cover catalogs, profile entries, or policies. > - New journal hooks must preserve the order used by setup finalization. > - This pull request adds tool-definition invalidation and its required writer guards. > - It leaves credentials and provider access changes for the next independent capability. ## Linked Issues or Issue Description **What happened?** Catalog, profile-entry, policy, gateway, and connection-configuration changes do not request agent runtime synchronization. A new profile-entry trigger also exposes a deletion/finalization deadlock if the child row is changed before its parent is locked. **Expected behavior** Committed tool-definition changes advance runtime revisions without polling. Bookkeeping does not. Entry changes and profile replacement use a consistent parent/reference lock order and commit atomically. **Steps to reproduce** 1. Change a catalog descriptor, profile entry, policy, or connection configuration. 2. Expect committed runtime events for the affected agents. 3. Run profile-entry deletion concurrently with setup finalization while both wait for an agent row. 4. Expect both operations to complete without PostgreSQL deadlock 40P01. **Additional context** Extracted from #16503. Catalog publication #16602 and standing assignments #16603 are merged. This PR is rebased onto master and is the active review. It addresses the original Apex profile-entry deletion finding. Credential/access hooks #16605 remain a draft without review requests. ## What Changed - Add migration 0355 for application/connection configuration, catalog, profile-entry, policy, and MCP gateway invalidation. - Preserve transaction coalescing and ignore health bookkeeping and trust-rule usage counters. - Keep credential-only fields outside this migration's coverage. - Preserve merged recipient scoping for bindings and installations. Profile-entry edits resolve old/new standing profile bindings. Policy edits resolve old/new agent selectors with their intersection/list semantics. - Lock old and new profile-entry references before parent profiles and child mutations. Recheck the reference set under the parent lock, retry changed snapshots up to three times, and merge unspecified fields from the locked profile. - Make entry add/edit/delete and profile replacement transactional, including validation and profile reads on the reserved connection. - Lock policy rows in ID order and change priorities in one statement so scoped agent locks are ordered across the full set. - Lock the managed profile before connection removal deletes its entries in the same transaction. - Update assignment tests whose old absence assertions are superseded by expanded configuration coverage. - Document the supported capability and the remaining credential/access boundary. ## Verification - Final head: `809fcb11794bfb12c545af0a2f96ab9bc2b570a2`. It is rebased onto master with merged #16623. GitHub reports no merge conflicts. [CI run 39293925136](https://github.com/paperclipai/paperclip/actions/runs/39293925136) has 55 successful checks and two optional Storybook skips. - Standard Greptile returned an independent 5/5. The final Apex review returned 5/5 on this exact head at 17:47 UTC on 2026-10-19. Its summary explicitly clears this PR for merge independently of draft #16605. The security scan passed. All review threads are resolved. - Two real-PostgreSQL negative controls reproduce `40P01` without the old-reference guard or the concurrent-snapshot check. Both regression tests pass with the final correction. Server typecheck, migration safety and numbering, five-snapshot retention, journal history, feature maps, and diff checks pass. The actual PR diff was scanned for secrets and personal data before push. - The final 15-suite local run passed 821/822 tests. The one failure was in the unchanged runtime-delivery test: a startup callback changed its global callback count during an independent transaction. The test-only correction is isolated in #16871. That PR passes all 17 runtime-hook tests, server types, hosted CI, and standard Greptile 5/5. Its notification-disabled control fails at the independent event-delivery assertion. No changes from #16871 are included here; this feature head passes hosted CI independently. - Earlier affected-suite runs passed 814 tests after rebase and 820 tests after recipient and whitespace corrections. Four affected suites passed 514 tests before the second reference-contention regression was added. Single-connection tests cover entry add, edit, delete, and replacement. Validation and profile reads use the reserved transaction connection. - Review fixes have negative controls: the old code hangs with a one-connection pool; parent-lock omissions deadlock entry deletion or app removal against setup finalization; per-row policy reorder deadlocks under contention; unscoped triggers journal unrelated peers; default SQL trimming misses JavaScript whitespace. Corrected cases pass. Selector tests cover all 25 ECMAScript whitespace characters. Recipient tests cover repeated edits, old/new targets, ignored bindings, rollback, coalescing, and company scope. The definition suite now has 28 cases. - Earlier standard scores that depended on #16605 were not accepted as independent clearance. The first Apex review returned 4/5 for replacement versus application deletion. The final correction locks old and new references, checks the reference set again under the parent lock, and retries before any mutation. The final independent reviews clear that correction. - Preserve prior failures for acceptance: draft run 38975432017 had failures whose causes were not re-investigated. Run 38990400765 exposed the unrelated durable-resume watchdog race, fixed in merged #16623. In run 39287657148, two jobs reported cancellation without a failed-test summary; the cause remains unknown. Both passed on retry without source changes. Initial local fixtures and SQL bindings also needed correction: an internal helper name was replaced with public `archiveConnection`, unchanged priorities were changed to exercise reorder, a driver timestamp was bound as ISO text, and a superseded company-fanout assertion was updated. These recovered checks do not establish a cause for the unexplained CI failures. - Local checks target the affected services and real database boundaries. A full local build and repository-wide test run were not performed. Hosted CI supplies the broader checks. Provider responses in tests are controlled; live provider behavior was not qualified. ## Risks Migration 0355 adds statement triggers without changing table schema. Apply it through the normal migration flow. A tool-definition event can advance a runtime revision without changing the bounded assignment snapshot. Consumers still need authorized readers for definitions. Credential-only changes, grants, secrets, and endpoints remain for the access-hook migration. Profile replacement now rolls back as a unit if any entry fails. Binding and install notifications retain scoped recipients. Profile-entry changes use standing bindings, and policies use old/new agent selectors. Unscoped policies, company-bound profiles, and other conservative definition changes retain synchronous transaction-atomic company-wide fanout: O(eligible company agents) locks and journal storage, without a fanout ceiling or mutation quota. This retains the accepted tradeoff from #16603 for company-wide changes. ## Model Used OpenAI Codex, GPT-6, with reasoning, repository inspection, code execution, and 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 (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 local checks; results and the isolated test failure 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> |
||
|
|
4d8770f6dd |
test(plugins): assert runtime delivery by event identity (#16871)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Plugins receive committed runtime events without polling. > - The delivery test checks that an independent writer is visible after commit. > - Startup baseline callbacks can still arrive during that transaction. > - A total callback count mixes startup work with the event under test. > - This pull request checks the transaction's specific event ID instead. ## Linked Issues or Issue Description **What happened?** The runtime-delivery test failed during #16604 verification. It expected one callback before an independent transaction committed, but received two. The test waits for a total callback count derived before startup baseline delivery is known to be complete. An older baseline event can arrive during the transaction and fail that assertion. The failing test and delivery implementation are unchanged from master. This PR isolates the test-only correction from #16604. **Expected behavior** The event created by the independent transaction is absent from delivered callbacks before commit. That exact event arrives after commit. Other committed startup callbacks can arrive at any time. **Steps to reproduce** 1. Start lifecycle delivery with startup events still pending. 2. Begin an independent agent update after the expected callback count is first reached. 3. Let a baseline callback arrive before that transaction commits. 4. The old global-count assertion fails even though the transaction's event is not delivered early. **Additional context** Scoped maintenance follow-up for #16604. No runtime behavior or feature files change here. #16605 remains a draft without review requests. ## What Changed - Read the new journal event ID inside the independent writer's transaction. - Assert that this ID is not delivered before commit. - Wait for that same ID after commit and check its company, resource, and type. - Remove the total callback-count assumption. - Wait for the company startup baseline, its acknowledgments, and coordinator idleness. Flush earlier listener notifications with a barrier, then wait for that barrier wake to settle before the independent write. ## Verification - The earlier full feature run passed 821/822 tests and failed this exact count assertion with two callbacks instead of one. That failure remains recorded in #16604. - The failing test file is byte-identical on the reviewed feature head and master. Neither the profile-replacement correction nor this PR changes the delivery implementation. - `pnpm exec vitest run server/src/__tests__/agent-runtime-hooks.test.ts`: all 17 tests pass with the event-ID assertion. - `pnpm --filter @paperclipai/server typecheck`: passed. - Standard Greptile initially returned 4/5: startup delivery could still hide a missing independent wake. The correction adds observable startup acknowledgment, listener flushing, and coordinator idleness. All 17 runtime-hook tests and server typechecking pass with it. A negative control drops runtime notifications while forwarding the barrier and fails the after-commit delivery assertion; startup work cannot mask that loss. - `git diff --check` and the full PR diff scan for secrets and personal data passed. - Full local build and repository-wide tests were not run for this test-only correction. At `714a74bf0991617c9ad85ce17bae22c533d1ed22`, hosted CI run 39295664656 passed: all 55 checks succeeded, with two optional Storybook checks skipped. Standard Greptile returned 5/5, the security scan passed, all review threads are resolved, and the branch is mergeable against master. The tests use real PostgreSQL and controlled plugin callbacks; live provider behavior is not qualified. ## Risks Test-only change. The commit boundary assertion remains: the new event ID must be absent inside the transaction and present after commit. Existing startup callbacks no longer count as early delivery of a different event. Runtime notification and retry behavior are unchanged. ## Model Used OpenAI Codex, GPT-6, with reasoning, repository inspection, code execution, and 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 (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> |
||
|
|
985d3b12b6 |
fix(runner): explain rejected task monitor arguments (#16868)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agents use task monitors to resume work after a future check. > - The runner rejects monitor arguments that fail the tool schema. > - It returned a generic error with no field or repair guidance. > - An agent could treat a repairable call as a scheduling outage and block its task. > - This pull request adds safe repair guidance and shows the nested request shape. > - Agents can correct the call and confirm a saved schedule before they yield. ## Linked Issues or Issue Description Refs: #15446, #16686. **What happened?** A rejected native `set_task_monitor` call returned `invalid_tool_call` with only “Paperclip rejected this semantic tool call.” The agent could not identify the invalid field. A retry could fail again and leave unfinished work without a scheduled wake. **Expected behavior** Reject invalid arguments before any mutation. Give the provider bounded schema locations and clear repair guidance. A corrected call must save a monitor and allow one wake without duplicate effects. **Steps to reproduce** 1. Call `set_task_monitor` with `idempotencyKey`, `nextCheckAt`, and `notes` at the top level. 2. The schema rejects the call because scheduling fields belong inside `monitor`. 3. Before this change, the provider received no guidance about the required shape. **Paperclip version or commit** Reproduced against master `35c75b56d4` with a failing Rust regression. **Deployment mode** Source checkout. This affects the native runner tool bridge. ## What Changed - Add monitor-specific repair guidance to the runner's existing safe schema error path. - Keep feedback within 512 bytes and omit submitted values and unknown field names. - Show the nested monitor request in the production tool description. Refresh generated contracts and catalog identities. - Test flat and nested invalid input, private value handling, and unchanged authorization errors. - Test rejection, correction with the same key, saved schedule and audit, receipt replay, and one timer wake with real PostgreSQL and the native tool authority. - Update execution documentation and the task verification recipes. ## Verification - Red/green: the Rust provider error regression failed on master because monitor repair guidance was absent. It passed after the fix. - Passed: 29 PostgreSQL monitor and scheduler integration tests. These use the real tool authority and scheduler, with a no-op process agent for wake delivery. - Passed: the native Codex server vertical-slice test. It runs the rebuilt Runner binary with a fake provider and checks durable results and session resume. - Passed: map structure checks, Rust formatting, and `git diff --check`. - Passed locally: full repository `pnpm -r typecheck`, `pnpm build`, and all 392 Rust library unit tests. - Passed on commit `3b667ad24763c1828edd48f56ef7a10766aeb946`: [CI run 39290889768](https://github.com/paperclipai/paperclip/actions/runs/39290889768), including all server, Runner, serialized, browser, typecheck, build, and canary gates. Across the PR, 56 checks passed and four conditional checks were skipped. No check remains pending or failed. - Greptile: 5/5 on that exact commit. The check concluded success, with no review comments or unresolved threads. - The duplicate local `pnpm test:run` attempt did not complete. It was stopped after the full CI suite passed; it is not counted as a local full-suite pass. - The first PostgreSQL attempt could not bind localhost inside the shell sandbox. It passed with normal localhost access. The first broader Rust attempt had 37 socket-permission failures and 355 passes; all 392 passed with localhost access and no code change. - Live model recovery was not run. Local execution policy did not authorize an extra acceptance run through the signed-in provider account. This PR does not include a deployment or recovery of an existing task. ## Risks - Error feedback must not reveal submitted values. Tests cover private values, unknown keys, nested constraints, length bounds, and unchanged generic authorization errors. - This changes guidance only. It does not relax the schema, retry calls automatically, or change scheduling authority. - A new runner binary and refreshed provider contract must reach the target instance before agents receive this guidance. ## Model Used OpenAI Codex, GPT-6, with reasoning, tool use, and code execution. The exact runtime suffix and context window size are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
249ab47d41 |
docs: use the Paperclip Discord invite URL (#16870)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Its READMEs direct users to the community for help and discussion. > - Both READMEs still use the old Discord invite code. > - Users have reported that the invite does not work. > - This PR uses the confirmed `https://discord.gg/paperclipai` invite in both READMEs. > - Users get the same community link from GitHub and the published CLI README. ## Linked Issues or Issue Description Fixes: #2172 Website companion: https://github.com/paperclipai/paperclip-website/pull/157 ## What Changed - Update the Discord header link, badge link, and community link in `README.md` and `cli/README.md`. - Keep the issue-template link, which already uses the correct invite. ## Verification - A byte comparison confirms that each changed file contains only the expected invite substitutions: six replacements across two files. - A tracked-file search confirms that the old Paperclip invite is absent. - `git diff --check` passed. - Attempted `pnpm -r typecheck`, `pnpm test:run`, and `pnpm build`. Each stopped before running because the host pnpm bootstrap could not fetch registry data to verify pnpm 9.15.4. This checkout also has no installed dependencies. These full local checks remain unverified. - Current-head CI passed: 55 successful checks and two intended skips. This includes build, typecheck, unit tests, serialized server tests, runner verification, canary dry run, and browser E2E checks. - Greptile reviewed commit `b0a0088f1a71c5831005790aa40edeed58cbaa68`: 5/5, with no inline findings. - No runtime code or visual styles changed. No new automated tests are needed for these link edits. ## Risks - Low risk. Only public Discord link destinations change. ## Model Used - OpenAI Codex, GPT-6, with tool use and shell execution. The exact runtime 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> |
||
|
|
3e5a9f5afe |
perf(ui): load recent tasks with bounded summaries (#16851)
Replace passive recent-task detail reads with bounded, authorized summaries. Keep account isolation, stored history, task actions, and live recovery behavior. Overlap access checks with shell settings and avoid duplicate session and health reads on the first healthy socket opening. Retain domain reconciliation. Add focused coverage and local performance evidence. Isolate the existing cache capacity test from entry expiry on slow CI runners. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
23b2ceb0d1 |
feat(connections): add unified Google Workspace connector (#15545)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Connected Apps supply governed tools to those agents. > - Google services currently require separate connections or one broad request. > - Users need one account and control over which services it can access. > - A picker must change the OAuth request, not just the screen. > - This pull request binds selected services to consent and tool access. > - The benefit is simpler setup without enabling unselected tools. ## Linked Issues or Issue Description **Subsystem affected** Connections catalog, OAuth grants, and the MCP tool gateway. **Current behavior** Google setup uses separate service profiles. A combined request alone cannot express the user's choice before Google consent. Accumulated Google grants can be broader than a new request. **Proposed behavior** Offer one Workspace connection. Let users choose Gmail, Drive (including Docs, Sheets, and Slides), and Calendar. Start all three with read and write access. Let users disable groups or choose read-only access. Do not offer Chat, Contacts/directory, or cross-service Search in new setup. Bind selected scopes to durable OAuth state. Cap effective tool access to both the saved request and provider-reported consent. **Reason and benefit** Users can choose services without managing several accounts. Existing company, identity, agent, and action-policy controls remain in force. **Breaking changes** No database migration. Existing service connections and grants remain supported. New Workspace requests require the companion broker change in https://github.com/paperclipai/paperclip-cloud/pull/823. Old brokers reject narrowed requests safely. Related work: #14740 reduced Google scopes; #14774 introduced the earlier catalog hold. #15412 proposes a separate Gmail REST implementation. This maintainer-requested change extends the existing Connections and governed tool gateway paths. It does not replace them. ## What Changed - Add one Workspace catalog entry and a namespaced action catalog. Retain legacy definitions and saved accounts. - Use the approved production service picker in Apps and task-hosted setup. Keep dropdowns between names and toggles. Block empty selection. - Derive exact scopes from a closed registry. Default selection requests nine scopes. New requests exclude Chat, Contacts/directory, and Search scopes. - Bind selected scopes through managed and customer-owned OAuth state, callback, claim redemption, and refresh. - Cap accumulated Google grants to the saved selection. Recheck grant-specific permission at discovery, listing, and dispatch, including cached actions. - Restore the current subject's saved request on reconnect. Block on grant-load failure. Preserve draft selection on cancel and retry. Do not create an account on picker cancellation. - Preserve healthy services during partial outages, without combining grants across identities. Keep writes from being automatically replayed. - Preserve the original 21-scope legacy Workspace envelope contract as individual profiles evolve. - Add production-component Storybook stories, request validators, consent regression tests, and rollout guidance. Integrate the stories with the current feature catalog while preserving their IDs. ## Verification - Integrated branch merges current master and has no merge conflicts. - Full workspace build passed on the integrated checkout. - Token gates passed. Storybook catalog structure check passed: 283 files and 2,750 stories. - Final affected app suites: 914 passed. This includes 502 database-backed service/gateway tests and 412 UI/shared/validator/broker-handoff/governance tests. The production picker tests cover defaults, identity-specific reconnect, and failed-load recovery. - Full workspace typecheck passed after adding required current-master Storybook annotations. The final UI build also passed. - The full repository suite is still running and includes the two pre-fix retry assertions. Both were updated for the current gateway's explicit-retry contract and pass in the clean 502-test database run. No complete final-head full-suite pass is claimed. - The initial local database startup failure came from missing native-library symlinks in the fresh dependency install. The package's postinstall repair fixed it; the clean database-backed run has no skipped tests. - Broker focused suite: 47 passed, including real signed session → callback → claim redemption and wrong-scope rejection. Full broker suite before the final test-only follow-up: 3,562 passed, 103 skipped. - Real integrated-app walkthrough: Connectors → Workspace → customer-owned app → service picker. Verified all three defaults, empty-selection blocking, cancel/reopen with the selected read-only access preserved, preserved form values, and zero saved connections after cancel. Credentials were synthetic; no Google grant was made. - Current-head CI and Greptile review remain pending. Previous-head results are not treated as current. ## Risks Ship the companion broker before app instances send narrowed requests. Enable the intended Workspace client/profile separately on the target broker. This pull request does not deploy a tenant app, start a fleet rollout, alter Google Console, or upgrade the pinned reviewer stack. The three-group picker is not proof of live provider access. Before production, verify a real selected-service grant, reconnect, refresh, allowed reads/writes, and denied unselected actions on the isolated staging reviewer app. Google verification and preview enrollment remain separate requirements. Legacy service profiles stay compatible. New grant metadata keeps provider scope evidence separate from requested scope evidence. Missing or unsupported evidence fails closed. No scope union across user or organization grants is allowed. ## Model Used OpenAI Codex, GPT-5-based coding agent, with repository editing, code execution, and browser tools. The exact serving model ID and context-window size were not exposed. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have 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 issue ID - [ ] I have run all final-head 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 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> |
||
|
|
d5b92cc41b |
perf(ui): reduce task startup initialization and redundant reads (#16862)
## Thinking Path > - Paperclip users open tasks to read saved work and reply. > - Faster startup must preserve message positions and composer state. > - Chrome CPU samples showed unused shared schemas and catalog indexes being initialized before task content. > - The shared package exports definitions and module-local data, with no required import-time registrations. > - Let the browser bundler discard unused shared modules. > - Readiness marks also exposed a duplicate plan read even though full task detail contains that plan. > - Keep both improvements measurable through CPU profiles, gate transitions and real browser acceptance. ## Linked Issues or Issue Description Follow-up to #16849. Related layout work: #14758. Searches found no overlapping plan-cache PR. **What existing behavior does this improve?** Task startup evaluates unused schemas and catalog indexes reached through the shared package barrel. The task also waits for a second plan-document request after full task detail arrives, even when that response already includes the plan or an explicit absent-plan value. Profiling showed that removing the request alone gave a small and variable total gain; unused initialization was the larger cold-load opportunity. **Subsystem affected** Board task loading, shared-package bundling metadata, plan-query caching, and local issue-detail profiling. **Proposed behavior** Discard unused shared modules during browser bundling. Fill an unused plan query when a full task response arrives. List-only snapshots keep their normal plan fetch. Keep the existing coordinated reveal. ## What Changed - Declare the shared package side-effect free so the bundler can drop unused module initialization. Used schemas and catalog data still initialize normally. - Seed an absent plan query at the successful full-task HTTP response boundary. Use a 30-second plan-query freshness window. List cache merges do not update this plan cache, and a later detail response never overwrites an existing plan query. - Preserve document-scope invalidation for plan creation, edits and deletion. - Add opt-in Chrome CPU profiles and readiness transitions to the existing performance harness. Diagnostic runs use one sample per scenario/profile and are labelled separately from latency benchmarks. - Record only fixed gate names and readiness booleans in local browser marks. Reset the gate effects on task changes so fully cached navigation is profiled too. ## Verification - Production UI build, UI typecheck and token design gates passed. - 258 focused unit tests passed. The final freshness follow-up passed 14 tests, including query eviction followed by a list refresh, preserving a separately fetched newer plan, missing projection, task isolation, and document-event refresh/deletion. - Two focused reuse tests fail with the original HTTP cache function and pass with the fix. The original production browser case makes redundant plan reads and fails. - All 13 final browser cases passed serially: eight layout scenarios, four plan-present/absent and direct/list startup cases, and a cached-task switch that records every gate. The cached-switch case failed before the identity dependencies were added. - One earlier concurrent browser run failed a properties-resize reading-anchor assertion. Two isolated repeats and the final serial suite passed. This outlier is retained in the local logs; it was not treated as a reason to change the unchanged scroll owner speculatively. - Actual CPU samples and readiness artifacts were captured on a disposable local production preview. This is browser timing data, not exported telemetry. - Audited 247 non-test shared modules for required import-time registration. The four top-level loops construct exported local catalog data. No required registration or side-effect-only shared imports were found. - A compiled browser-library contract accepted valid task input, rejected an empty title, retained all seven agent statuses, and retained GitHub metadata plus 1,576 catalog entries. All 13 browser scenarios passed against the initialization candidate too. - Plan reuse alone did not establish a reliable total gain: a final local run was 4,356 ms cold and 1,116 ms warm on Fast 4G/4x CPU. - The next five-sample run with unused shared initialization removed measured **3,298 ms cold (24% faster)** and 1,079 ms warm. Median issue API server time was 35 versus 39 ms. First contentful paint fell from 2,808 to 1,648 ms. JavaScript before content fell from 1,722 to 1,670 KiB; CPU initialization mattered more than byte size. - Final alternating comparison: five samples per variant for both cold and warm navigation, same persisted task and Fast 4G/4x CPU settings, fresh browser per sample, order alternated between variants. **Cold content paint: 4,588 → 3,688 ms (20% faster). Warm: 996 → 1,030 ms (+35 ms).** No CPU profiler was active. The final initialization commit is the only source difference between these two builds. - These local measurements do not establish deployed staging latency or a speedup across every profile. Unthrottled timings varied with API latency. - Actual UI walkthrough on the final bundle: read the saved plan and conversation, submit one unassigned reply, refresh, navigate to Projects and Back, and inspect the new-task dialog. The reply persisted exactly once, confirmed independently through the comments API. No paid agent was woken. - Final head `a7043c474d`: Greptile 5/5, all review threads resolved, and all 56 checks passed, including full typecheck, build, unit and E2E suites. ## Risks Bundlers can discard unreferenced shared modules. Future required registrations or global initialization must be declared in the package side-effects metadata. Current module-local catalog construction remains when its exports are used. Merged list snapshots can retain old plan fields while receiving a new task-cache timestamp. This change seeds only from a new full HTTP response, rather than inferring plan freshness from those merged snapshots. Existing plan-query state is never overwritten. List-only, stale, invalidated, or incomplete data still uses the normal plan read. Existing document invalidations refresh the query. No API, database, permission or reveal-policy changes. ## Model Used OpenAI Codex, GPT-6, with reasoning, repository tools, code execution and browser verification. A more precise runtime model identifier and context-window size are unavailable. ## 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> |
||
|
|
35c75b56d4 |
fix(pi): credit Paperclip for default legacy OpenRouter requests (#16864)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Legacy adapters can use host credentials and provider settings. > - OpenRouter assigns app credit from the final request headers. > - The first attribution change covered managed connections and explicit provider configs. > - Legacy Pi with only an API key bypassed those config changes. > - This pull request applies attribution at Pi's request boundary. > - The benefit is Paperclip credit without replacing the user's Pi home. ## Linked Issues or Issue Description Follow-up to #16850. A search of related OpenRouter PRs and issues found no duplicate fix for this path. **What happened?** A legacy `pi_local` agent with `OPENROUTER_API_KEY` and no `PAPERCLIP_PI_PROVIDERS` could send requests without Paperclip attribution. Existing Pi home configs could also retain the previous harness title. **Expected behavior** Paperclip receives credit for OpenRouter requests from its legacy Pi adapter. The adapter preserves credentials, routing, model settings, and other providers. **Steps to reproduce** 1. Configure a legacy Pi agent with an OpenRouter model and API key. 2. Leave `PAPERCLIP_PI_PROVIDERS` unset. 3. Start a run and inspect its outgoing headers or OpenRouter generation record. **Paperclip version or commit** Reproduced after #16850, on master commit `9179d8dcc3e908c217fde4f63c9d08ccf8132eeb`. ## What Changed - Load a temporary attribution extension for every legacy Pi run, including remote targets and retries. - Apply headers after credential and model-header resolution on Pi 0.74 and at provider dispatch on Pi 1.0. - Check the actual endpoint. Cover custom aliases and regional OpenRouter hosts. Preserve other endpoints, credentials, unrelated headers, and explicit visibility preferences. - Keep the Pi home, auth file, settings, and model catalog in place. Remove the temporary extension after the run. - Prevent repeated wrapping when Pi recomposes a provider after a registry refresh. Add regression tests and update the connector playbook. ## Verification - Final head `902399468a9033d12e3ff6ab30c8463daef50bad`: Greptile **5/5**, with no actionable comments. CI is waiting for runner assignment. - Complete legacy Pi adapter suite: **124 tests passed across 12 files**, including extension, runtime-config, and remote execution coverage. The initial focused subset passed 30 tests. - `pnpm -r typecheck` and `pnpm build` passed. After the lifecycle guard, all 124 Pi tests and the Pi package typecheck passed again. Full `pnpm test:run` is in progress. - Actual Pi 0.74 outgoing-request comparison with dummy credentials: the baseline sent no attribution headers. The patched request sent all four Paperclip headers and retained the same credential. The transport returned an intentional 401 after capture; this check does not claim successful inference. - Final-head Pi 0.74 request-capture matrix: **8/8 passed**. Cases cover bare keys, host aliases, per-model overrides, EU/US endpoints, a repointed built-in provider, an unrelated provider, and an HTTP endpoint. Credentials, custom routing headers, and visibility preferences survived. These captures used dummy credentials and intentional 401 responses. - Live request through the actual legacy adapter with Pi 0.74: response `legacy attribution verified.`; generation `gen-1792424885-G3THa6DdJXmAL3C841DI`; OpenRouter app ID **3118063**; cost **$0.0002268**. - Live request through the actual legacy adapter with the Pi 1.0 bundled CLI: response `legacy attribution verified.`; generation `gen-1792425530-LlpIbfBFyjs6XRP5l5PV` on final head `902399468a9033d12e3ff6ab30c8463daef50bad`; OpenRouter app ID **3118063**; cost **$0.0002391**. Its usage record became available on a later read. - Both live runs preserved the existing `models.json`, `settings.json`, and `auth.json` byte for byte. Pi 0.74 also retained the custom `X-Route` header while replacing the conflicting harness title. - Built-package smoke passed. `npm pack --dry-run --ignore-scripts` includes `dist/server/openrouter-extension.js`, and the compiled helper produced a working self-contained extension. The pack check used a temporary npm cache because the default cache was not writable. - Remote asset delivery is covered through the SSH execution test boundary. No live remote sandbox was used. - Initial capture attempts produced no requests because the test left stdin open. A separate source-checkout live attempt lacked the TypeScript loader and did not reach the provider. Correcting the test setup produced the evidence above. Pi 1.0's bundled transport bypassed the global-fetch capture shim; its acceptance evidence is the successful live request and provider-side app ID. ## Risks - The extension depends on Pi 0.74's request-auth registry and Pi 1.0's provider API. Harness upgrades require a fresh request capture or live credit check. - Missing extension delivery stops remote startup rather than silently losing attribution. - A private gateway that replaces headers and an externally managed harness remain outside this adapter's control. Public listing metadata still belongs to OpenRouter. - No database, API, credential ownership, or telemetry contract changes are required. ## Model Used OpenAI GPT-6 through Codex, with reasoning, repository editing, shell execution, and live API verification. The exact runtime model identifier and context-window size are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass — the focused suites above; the full suite is still running - [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> |
||
|
|
18e9ca7277 |
fix(server): retry read-only delivery lookups after a pooled disconnect (#16859)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Execution workspaces have a close-readiness check. The board uses it
before it archives or cleans up a workspace. The terminal-workspace
reaper and workspace hydration use the same delivery assessment.
> - The delivery assessment reads the source issue tree and the pull
request work products of the source issue.
> - A pooled database connection can become stale. Then postgres.js
rejects the query with `write CONNECTION_CLOSED`.
> - The issue-tree read had no retry. One stale socket failed the full
close-readiness request with a 500.
> - The database client does not replay disconnects globally, because a
write can commit before the disconnect (#14773). Callers that know a
lookup is read-only opt in with `retryIdempotentDatabaseOperation`
(#14873, #15248, #15300).
> - This pull request wraps the two read-only delivery lookups in that
helper.
> - The benefit is that close readiness, hydration and the reaper
recover from one stale pooled socket.
## Linked Issues or Issue Description
Refs #14773, #14873, #15248, #15300 (same retry pattern for other
read-only lookups).
**What happened?**
A hosted staging server returned an error for an execution workspace
close-readiness request. The issue-tree query in the delivery assessment
failed with `write CONNECTION_CLOSED` through a transaction-mode
database pooler.
**Expected behavior**
A read-only lookup recovers after one transient pooled disconnect.
Persistent failures still propagate.
**Steps to reproduce**
1. Use a pooled PostgreSQL endpoint that closes idle client sockets.
2. Let a pooled connection go stale.
3. Request close readiness for an execution workspace that has a source
issue.
4. The first query on the stale socket fails and the request fails.
**Paperclip version or commit**
`master` at
|
||
|
|
5245959023 |
fix(github): simplify App reconnection and credential recovery (#16856)
Show clear GitHub connection recovery guidance and reconnect the saved App before requesting replacement credentials. Preserve PEM bytes through paste, upload, and retry, with production-page Storybook and browser regression coverage. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
d20cb69ce5 |
fix(heartbeat): preserve active retries when comments arrive (#16855)
## Thinking Path > - Paperclip manages agents and their work. > - Heartbeat retries preserve task ownership after a recoverable failure. > - The issue read model includes retries that are scheduled, queued, or running. > - The human comment route treated every retry in that model as parked work. > - A normal status comment could therefore cancel a running continuation and return its task to Todo. > - This pull request limits comment supersession to parked retries and checks that state at the cancellation fence. > - The agent can keep working when a person adds context. Explicit Stop and Interrupt remain available. ## Linked Issues or Issue Description **What happened?** A Board comment on an in-progress task cancelled its running recovery continuation. The handler read a live retry from `getCurrentScheduledRetry` but did not check its status. The cancellation also forced workspace recovery when copy-back did not complete. **Expected behavior** A comment must preserve queued and running execution. Only a retry that is still `scheduled_retry` may be superseded. If promotion wins the race, the comment must keep the task in progress and follow the normal wake path. **Steps to reproduce** 1. Let a task retry advance from `scheduled_retry` to `running`. 2. Keep its retry reason and source run identity in the stored row. 3. Post a normal human comment, without an Interrupt request. 4. Observe the old handler cancel the run and move the task to Todo. **Paperclip version or commit** Reproduced on master base `9966f31bee`. The staging incident served `f3cd3f4ea89539b68410841d39ec15a5c626007f`. **Deployment mode** Staging server with a remote runner. The defect is in the core comment and cancellation path. Refs #16835 and #16843. Those repairs cover runner health and workspace preservation. This change prevents a normal comment from requesting the wrong cancellation. Related #9732 promotes human wakes on parked retries; it does not protect a retry that is already running. ## What Changed - Check the live retry status in both comment routes: POST comments and PATCH issue with a comment. - Add an optional expected-status fence to cancellation. A concurrent promotion or terminal outcome returns a no-op result. - Make due-retry promotion honor a cancellation claim under its issue and run row locks. A scheduler cannot promote work after cancellation has won. - Finish persisted cancellations of parked retries through the existing startup and periodic recovery sweep. Preserve their original request and retry a failed settlement without starting provider work. - Keep the task active when guarded cancellation does not win. Do not record a cancellation that did not occur. - Add route regressions, real PostgreSQL race tests, and pending-retry and explicit Stop safety coverage. - Exercise both normal HTTP comment routes with real services, stored Board membership, PostgreSQL, and a live child process. Assert that the process can still perform work, the task keeps its original execution, and no second executor starts. - Document the comment supersession contract and update the task feature/access maps with the local regression coverage and deployed acceptance recipe. ## Verification - Before the fix, all four POST/PATCH regressions cancelled queued or running work. - Before the fix, the real PostgreSQL race test cancelled a retry that became running after lookup. - The comment-route suite passes **103 tests**. The final dispatch, cancellation, restart recovery and HTTP/live-process suites pass **119 tests**, for **222 affected tests** across these runs. They cover comment delivery, both sides of the promotion race, concurrent terminal outcomes, pending retries, explicit Stop, and a live process that can continue work. - Command: `node node_modules/vitest/vitest.mjs run server/src/__tests__/issue-comment-reopen-routes.test.ts server/src/services/heartbeat/run-control.test.ts`. - The normal HTTP/live-process acceptance suite passes all **14 tests**, including both comment endpoints with stored Board membership and deterministic wakeup teardown. - Review exposed a second race after the cancellation claim. Its new PostgreSQL test failed before the dispatch guard with `promoted` and passes afterward with `not_promoted`, followed by completed cancellation. - A real PostgreSQL constraint interrupts the terminal cancellation write after its intent commits. The assembled recovery service failed to settle that row before the repair. Afterward a fresh service settles it, clears its task lock, cancels its saved wake, preserves the original request and leaves unrelated parked retries alone. A repeated database failure preserves the intent for a later successful sweep; a second successful sweep adds no duplicate event. - Full `pnpm -r typecheck` and `pnpm build` pass. Server typecheck and build pass again after the final server-only review fix. A local full-suite attempt started on `f8773bf` did not return an overall result; its log is preserved and no local full-suite pass is claimed. The new recovery change passes the focused suites and fresh server typecheck/build. Latest-head CI on `8f928adee67c089e1ac405d2ad3b169eedb8da27` is green: the full PR workflow and commitperclip review passed; only the two optional Storybook jobs skipped. - Greptile reviewed final head `8f928adee67c089e1ac405d2ad3b169eedb8da27` at **5/5**, with no unresolved findings. All actual latest-head CI checks passed; the two optional Storybook jobs skipped. - `node scripts/check-maps.mjs` passes after the map updates (34 areas, 172 capability IDs); it checks structure only. - Fixed-revision staging acceptance is pending deployment. The original workspace remains held and its latest source checkpoint is backed up and verified. ## Risks - A promoted retry must keep its execution and ownership when a comment arrives. The database status predicate and route no-op handling enforce this at the race boundary. - A cancellation intent must prevent promotion without leaving work parked forever after a restart. The recovery sweep consumes at most 20 such intents per pass through guarded cancellation, and a failed settlement keeps its intent for retry. - A parked retry must still accept fresh instructions. Its existing cancellation and wake behavior remains covered. - Ordinary Stop and Interrupt calls omit the expected-status option. Their cancellation authority is unchanged and remains covered by the run-control suite. - No schema migration or API request contract changes are required. ## Model Used OpenAI `gpt-6.1-sol` in Codex, with extra-high reasoning, tool use, and code execution. The session does not expose its context-window limit. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.1019.0-canary.8 |
||
|
|
36e4c6657f |
fix(sentry): report a native retry failure only when the retry ends (#16865)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - The server sends a Sentry `run_failure` event when an agent run
reaches a terminal failure.
> - A native run that waits for a same-run retry is stored as `failed`
with `nativePhase: "retryable_failure"`. That state is not terminal.
> - `reportRunFailure` reported that pending state. Runs that later
recovered, for example after a workspace copy-back retry, still sent a
run failure event.
> - These events make one catch-all Sentry group noisy and hide the real
terminal failures in it.
> - This pull request skips the pending retry state and reports once
when the retry ends as a terminal failure.
> - The benefit is that run failure events match runs that really
failed.
## Linked Issues or Issue Description
**What happened?**
Two staging runs had a workspace copy-back failure during settlement
(`Daytona syncOut tar command failed ... No space left on device`). The
executor stored each run as `failed` with `nativePhase:
"retryable_failure"` and `errorCode: native_session_interrupted`. Sentry
received a `run_failure` event for each run. About two minutes later,
the copy-back retry succeeded and both runs finished as `succeeded` with
`workspaceFinalizeStatus: "succeeded"`.
**Expected behavior**
A run that waits for a same-run retry must not send a terminal run
failure event. If the retry ends as a terminal failure, the server must
send one event at that time.
**Steps to reproduce**
1. Set `PAPERCLIP_SENTRY_RUN_FAILURES=unexpected`.
2. Start a native run that fails retryably. For example, make the
workspace copy-back fail once.
3. See the `run_failure` event in Sentry, and then see the run finish as
`succeeded` after the retry.
## What Changed
- `reportRunFailure` returns without a report for a native run that is
`failed` with `nativePhase: "retryable_failure"`.
- New `isNewTerminalRunFailure(before, after)`: a status change counts
as before. A failed run that leaves the pending retry state but stays
`failed` also counts.
- Three terminal writers can keep the status `failed` → `failed`. They
now use `isNewTerminalRunFailure`, so they still report once:
- the resume reconciler's ambiguous-state write;
- the restart recovery `blocked` write;
- the committed-result projection (`projectCommittedRun`).
- Result-less retries already reset the run to `running` before they
start, so their terminal write still reports through the existing
status-change guard.
- `doc/observability.md` describes the new rule.
## Verification
- `pnpm exec vitest run
src/services/__tests__/run-failure-report.test.ts
src/__tests__/run-failure-sentry.test.ts
src/__tests__/native-session-resumption.test.ts
src/services/native-runtime/native-run-finalizer-telemetry.test.ts
src/services/native-runtime/native-runner-restart-recovery.integration.test.ts
src/__tests__/heartbeat-status-preserving-telemetry.test.ts
src/services/execution-control-reconciliation.test.ts` (from `server/`):
7 files, 363 passed, 9 skipped.
- New tests:
- `run-failure-report.test.ts`: a pending native retry does not report,
and a `terminal_failure` run does. Unit cases cover
`isNewTerminalRunFailure`.
- `native-session-resumption.test.ts`: a sweep that ends an unreported
pending retry sends one event.
- `native-run-finalizer-telemetry.test.ts`: a committed failure for a
pending-retry row sends one event, and a replay sends none.
- `native-runner-restart-recovery.integration.test.ts`: a restart
recovery `blocked` write for a pending-retry row sends one event.
- I removed each of the three writer changes one at a time. The matching
new test failed each time (`expected [] to have a length of 1` / `to
deeply equal [ [ ObjectContaining{…} ] ]`).
- I did not run the full server `tsc --noEmit` locally. The local
container has a 4 GiB memory limit, and the process was killed (exit
137). CI runs the typecheck.
## Risks
- A run that stays in the pending retry state and never resumes no
longer sends a run failure event. The run stays visible on the board as
failed with a scheduled retry. A later terminal write still reports it.
- The finalizer's `failed` + `retryable_failure` write for a failed
provider result also stops reporting. The terminal write that ends that
retry reports instead: retry exhaustion in `recordRetryableFailure`
reports unconditionally, and commit goes through `finalizeNativeRun` or
`projectCommittedRun`.
- A run that was reported in the pending state before this change can
report once more when it becomes terminal after deploy. This affects
only runs in flight during the upgrade.
- There are no schema, migration, or API changes. Run status, retries,
and recovery do not change.
> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.
## Model Used
- Anthropic Claude Opus 5.5 (`claude-opus-5-5`) in Claude Code, with
tool use (shell, code search, test runs) and a read-only code
exploration subagent. Context window: the standard window for that
model.
## 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: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
||
|
|
2cbca4ceb0 |
fix: retain channel tools across task continuations (#16806)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Chat channels give an agent tools for its assigned task. > - Each later run must resolve the task and its accepted requester again. > - Some native runs store the task in a database column without the older JSON fields. > - Tool discovery read only the JSON fields. GitHub calls also required a new inbound comment. > - This pull request uses the durable task binding and accepted request history. > - Later runs retain their channel tools while current access checks still apply. ## Linked Issues or Issue Description **What happened?** A GitHub task can find `begin_review` on its first run, then receive an empty tool list on a later native run. If discovery is repaired alone, a call can still fail because the later run has no new inbound comment. Slack and voice tool access also read the older JSON task fields. **Expected behavior** A later run for the same task can find and call its assigned channel tools. The current requester, task, company, agent, endpoint, and access rules must still allow the call. Revoked access must fail. **Steps to reproduce** 1. Start a GitHub task and accept its linked requester. 2. Confirm that the runtime can find `begin_review`. 3. Start a later native run with `nativeIssueId`, accepted parent identity, and no JSON task ID or new wake comment. 4. Search for `begin_review` again. Before this change, the search returns an empty list. 5. Repair discovery alone and call `read_pull_request`. Before the request-history fix, the call fails with no active conversation capability. **Paperclip version or commit** Reproduced in source tests before this patch. The branch includes master at `fa50cab5685b9cdbb26ad9c610cc5b6c373d3ff4`. **Additional context** This is a core run-binding bug. The tests use PostgreSQL and synthetic provider responses. They do not send live reviews, Slack messages, or phone calls. ## What Changed - Resolve run task IDs from durable columns, with legacy JSON fields as a fallback. - Use the same binding in the gateway, access policy, identity service, and channel runtime preparation. - Recover accepted channel request history across later runs. Keep company, task, agent, and requester boundaries. - Recover older wake sources through verified parent runs, including after same-user board follow-ups. Clear the board message’s own legacy wake fallback. Keep cycle checks without a fixed limit on valid task history. - Retain the GitHub origin after a board comment from the same accepted user. Skip GitHub origin lookup results from other providers. - Keep ordinary board tools available when the requester changes. Accept legacy user comments without an author-type field. Still reject explicit malformed task IDs. - Prevent a later failure reply from replacing an earlier final GitHub answer. Recheck this rule under the publication lease. - Rotate the native tool contract to replace retained sessions with an older tool list. - Add continuation, publication, revocation, and boundary tests. Update the access and feature maps. ## Verification - Red: the later GitHub assigned-tool search returned an empty list before the binding fix. - Red: the later GitHub read failed with no active conversation capability before the request-history fix. - Green: runtime MCP discovery, GitHub read/begin/submit review, and response publication pass for monitor and same-user board continuations. - Green: Slack history, retained access controls, revocation, and voice gateway continuation pass. - Green: 35 channel, failure-publication, legacy-origin, long-history, and provenance tests pass. Both review findings had failing tests before their fixes. - Green: 107 gateway, operation-credential, identity, and provenance tests pass. These cover both first-run CI failures without changing their tests. - Green: 122 runtime, discovery-policy, and native-session tests pass; 2 unrelated tests are skipped. - Map checks and whitespace checks pass. - Updated to master in `cfcaba22628772d7fe1fb32b57ff7031c7072781`. The sole conflict was two tests added at the same location. Both the continuation test and the publication 403/401 test are retained. - Current local verification: all 179 gateway, credential, requester-identity, access-policy, runtime-context, and session-resume tests passed. Repository typecheck and build passed. Map and whitespace checks passed. - The new review regression first returned no source for a same-user board follow-up over legacy wake metadata. After the repair, all 27 provenance and channel cases passed. The combined GitHub discovery/read/begin/submit path and revoked access are covered. - The broader local channel run passed 176 cases and failed four timing/setup cases: a 15-second Slack authorization timeout, webhook-verification polling, a Slack acknowledgement deadline, and Discord setup polling. All four passed in isolation without source, assertion, or deadline changes. The earlier failure record is retained; the exact load/order cause is not established. Full CI must pass on the latest commit. - Current head: `7b9a08dcbc7b8140b589742f136944270b0496bb`. Repository typecheck and build pass on this commit. Greptile completed on this exact commit with 5/5; all four review threads are resolved. The final-head [CI run](https://github.com/paperclipai/paperclip/actions/runs/39278921653) passed: 55 checks passed and 2 intentionally skipped, with no failures or pending checks. This includes the full sharded test matrix, browser tests, typecheck, build, and Runner verification. Results were delayed during the [GitHub Actions incident](https://www.githubstatus.com/incidents/8tzbpcnl75jp). An additional unsharded local full test run has not completed; the completed full-suite evidence is CI. - Earlier verification: the first PR commit failed two server suites. Those failures were fixed and verified before this update. The original 4 GiB sandbox could not complete full local typechecking or tests; the current checkout completed typechecking and build. The full test suite runs through the CI shards. No full local test-suite pass or live provider delivery is claimed. ## Risks - Request history can restore the wrong authority if its scope is too broad. The resolver checks each accepted parent against the task, company, agent, and requester. Tests cover invalid and cyclic history. - The native contract change starts a new provider session for older contracts. - No database migration or public API schema changes are required. Each tool call still checks live access. ## Model Used - OpenAI Codex, GPT-6 family. The runtime does not expose the exact deployment model ID or context-window size. The agent used reasoning, repository tools, code edits, and local test execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
7fed88e78d |
fix(server): retry heartbeat run read checks after a dropped connection (#16857)
`canActorReadHeartbeatRun` now wraps the issue existence read and the `issue:read` authorization decision in separate `retryIdempotentDatabaseOperation` calls, so one pooled-connection drop (`CONNECTION_CLOSED`) no longer fails heartbeat run, activity, live-event and issue-source reads. Adds a regression test and a note in doc/DATABASE.md. Refs #15248. Refs #15300. Refs #14773. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
9179d8dcc3 |
fix: credit Paperclip for managed OpenRouter requests (#16850)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - AI connections choose credentials and routes independently of the agent harness. > - OpenRouter assigns app credit from the final request headers. > - Harness defaults can assign Paperclip work to the underlying harness. > - This pull request applies one public Paperclip identity to managed OpenRouter requests. > - The benefit is consistent app credit across supported harnesses and internal model calls. ## Linked Issues or Issue Description **What existing behavior does this improve?** App attribution for existing OpenRouter connections and explicit provider configurations. **Current behavior** Requests can omit attribution or carry the harness identity. Paperclip does not receive consistent credit in OpenRouter rankings. **Proposed behavior** Use `https://paperclip.ing`, the title `Paperclip`, and the coding categories `cloud-agent,programming-app` for managed requests to OpenRouter. Keep credentials, routing, and unrelated providers intact. **Reason and benefit** The provider URL identifies the app across personal and shared API keys. A search of public issues and pull requests found no duplicate attribution work. This improves existing AI connections and does not add a separate roadmap feature. ## What Changed - Add a shared attribution policy and a parity-checked copy for the standalone Runner. - Apply it to managed Codex, Claude, OpenCode, and Hermes connections, plus native Pi and explicit legacy provider configs. - Preserve attribution across Codex config filtering, Claude environment filtering, OpenCode proxy requests, and model-level overrides. - Attribute direct fast-response and decision-model requests, including custom connections to the OpenRouter endpoint. - Add positive and negative regression tests and provider attribution requirements to the connector playbook. - Advance native Pi to profile 24, preserving historical identities and binding the attribution source in its declaration and release checks. ## Verification - Final head `6df282d2a58c2698e41127443903d6fc85b4b72f`: all CI/status checks passed or were intentionally skipped; Greptile is **5/5**, with zero unresolved review threads. [Final CI run](https://github.com/paperclipai/paperclip/actions/runs/39274938069). - Focused server/shared/config suites: 132 tests passed before the final edge-case additions. Expanded adapter suites pass 48 tests; the final OpenCode merge passes 15 tests; global/EU/US endpoint and policy-parity suites pass 26 tests. - Focused Runner suites: 85 tests passed, including model overrides and recovery/config boundaries. Profile installation/environment/config tests subsequently passed 72 tests (one optional distribution test skipped); historical decoding passed 11 tests and updated recovery coverage passed 27 tests. The Rust profile admission test and all five native Pi launch/recovery tests passed. - All 114 managed AI connection tests pass together. They include custom-header preservation for legacy and native Claude runs, both OpenRouter and other gateways, inherited headers, and unresolved secret references. - Actual requests from installed Codex 0.160.0, Claude Code 2.1.245, OpenCode 1.18.34, Pi 0.74.0 and 1.0.0, and the managed Hermes runtime carried all four Paperclip headers. A local endpoint used dummy credentials and returned an intentional 401 after capture. Codex and Claude retry requests retained attribution. This proves outgoing header precedence; it is not a successful model-inference test. The first Claude capture had an argument-separation error and sent no request; correcting the command produced the captured requests. - A live request through `fastResponseModel` completed with `attribution verified`. OpenRouter recorded generation `gen-1792420273-Ez1GUTCc7YuZ1FJMCGob` under app ID `3118063`, at a cost of $0.00000375. The public app record maps that ID to `https://paperclip.ing/`. - Full `pnpm -r typecheck` and `pnpm build` passed, including a repeat after the review fixes. The final server build stamp records commit `6df282d2a58c2698e41127443903d6fc85b4b72f`. `pnpm check:token-gates` passed. - CI first caught the stale Pi source attestation; it is now a new immutable profile. Greptile caught custom-header loss, now fixed and covered by the complete managed-connection suite. The next CI run caught the missing Docker allowlist entry for profile 24; the allowlist and release smoke pins are now synchronized. Local Docker verification cannot run because its daemon socket is absent; The exact Docker context check passed in CI on the final head. - The initial local `pnpm test:run` did **not** pass. It ran across source/build edits, reported chat/tool-access collection failures, three workspace-runtime failures, two new managed-header failures, one Dot Runner readiness failure, and two native-session-resume failures, and was interrupted after the final-head CI server coverage passed. Its secrets suite also reported 91 cases skipped. The isolated tool-access suite passed all 428 tests, and the complete managed-connection suite passed all 114 tests. These retries establish recovery, not the cause of the original local failures; no claim of a successful full local run is made. Final acceptance uses immutable final-head CI plus the focused local and live checks above. - Final-head CI encountered one unchanged UI assertion in `FileViewerSheet.copy.test.tsx` (missing “Copied link” feedback after clipboard completion). That shard passed on the earlier head with identical UI code, and all six clipboard tests passed locally. A timing race around the asynchronous React update is suspected but not conclusively established. The single CI retry passed, with no product/test code changed for it. The earlier failure remains part of this verification record. ## Risks - Native Pi profile 24 requires a fresh provider session when encountering a profile 23 identity; recovery tests cover that boundary. - Harness upgrades can change header precedence. The playbook requires actual request capture when changing provider paths. - Externally managed agents, unmanaged harness settings, and gateways that replace headers need separate qualification. This change does not intercept arbitrary model calls made by task scripts. - The existing OpenRouter entry for the Paperclip URL still displays an old title, “PrettyFly Opus Testing,” and no categories on the final public-page recheck. The live request received credit under that URL's app ID. Public title propagation and leaderboard placement remain controlled by OpenRouter. - Global, EU, and US OpenRouter hosts are recognized explicitly; other subdomains are not treated as OpenRouter. No database migration, credential ownership change, or Paperclip telemetry event is involved. Attribution contains public product constants only. ## Model Used OpenAI GPT-6 through Codex, with reasoning, repository editing, shell execution, web research, and live API verification. The exact deployment identifier and context-window size are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass — the focused suites listed above; the unsuccessful full local attempt is explicitly recorded, with full final-head coverage supplied by CI - [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> |
||
|
|
a7504784e5 |
perf(chat): avoid snapshot reads in native progress polls (#16845)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Chat connectors publish safe progress from native runs. > - A recurring query joins each run to its conversation through JSON context. > - Large snapshots make repeated JSON reads expensive. > - Issue-scoped runs already have a typed issue binding. > - This pull request uses that binding and retains the legacy JSON fallback. ## Linked Issues or Issue Description **What existing behavior does this improve?** The native chat-progress candidate query in `enqueueSafeNativeChatProgress`. **Subsystem affected** `server/` database queries and chat publication. **Current behavior** The conversation join extracts `issueId` from each run's JSON snapshot. A local plan probes the run repeatedly and reads a large snapshot for each probe. **Proposed behavior** Use the run's typed `issue_id` when present. Read the JSON key when that column is null. Keep the existing company, endpoint, event, publication, cursor, and cadence conditions. **Reason and benefit** Avoid repeated snapshot reads for scoped runs. Related: #15802 changed delivery queue scheduling; it left native progress projection on its existing cadence. ## What Changed - Change only the native-progress conversation join. Leave the separate milestone query, which already uses its expression index, unchanged. - Add a disposable PostgreSQL benchmark that captures the real service SQL and compares complete rows on one shared fixture. It includes a legacy null binding, unrelated tenants, 2,400 historical decoys, and 144 KiB of random bytes per snapshot (about 192 KiB after base64 encoding). - Compare cardinality across independent fixtures. Their generated conversation and event IDs are not deterministic. - Add PostgreSQL regressions for a typed issue binding without the JSON key and for the legacy NULL-column fallback. ## Verification - Full-size paired local measurement: native baseline 57.67 ms median, treatment 19.35 ms median, **2.98× faster**. Both return the same 41 complete rows. Five timed samples follow warmups, with baseline and treatment alternated. The unchanged milestone query is a control. - An independent full-size run also passed complete row equality and measured 65.22 → 24.08 ms (2.71×). - The small 1 KiB control passed the same 41-row equality check and was neutral: 15.20 → 15.45 ms median. The improvement targets large snapshots, not small payloads. A repeat of the final JavaScript entry point also passed equality and measured 2.97× while the full test suite was running; its wider timing spread is not the primary performance result. - Four PostgreSQL cases pass: typed issue scope without a legacy JSON key, NULL-column JSON fallback, native-progress cadence, and paused-endpoint no-replay behavior. The remaining tests in that file were excluded by the name filter. - Reproduce with `node --import ./cli/node_modules/tsx/dist/loader.mjs scripts/benchmark-chat-native-progress.mjs --phase=baseline` before applying the query change. Run the same command with `--phase=treatment` after applying it. The tool stores SQL, parameters, plans, all samples, and equality evidence under `.scratch/`. - Full workspace typecheck and final server typecheck passed locally. Four focused PostgreSQL cases passed. The duplicate unsharded local full-suite run was stopped after the same commit passed all CI test shards; the full local tests/build sequence was not completed. CI Build and the aggregate verification gate passed on that commit. - Current-head CI is green at `82c9ef9` (55 successful checks, two valid skips). An unchanged runtime-supervision test failed in the first attempt; its isolated local reproduction passed, and one failed-job rerun passed on the same commit. The local reproduction runs on macOS and does not exercise the Linux process-identity branch. - Greptile reviewed `82c9ef9` at 5/5 with no unresolved threads. ## Risks - The typed issue binding takes precedence when present; older rows retain JSON fallback. Company and publication ownership checks remain in the query. - Measurements use local embedded PostgreSQL 18 with synthetic data. The hosted motivation used PostgreSQL 17. Absolute timings and plans can differ on other compute and data distributions. - The milestone benchmark returns an empty candidate set and is a performance control; the nonempty native comparison is the correctness and performance target. - No schema migration or provider network request is added. This PR does not deploy a query change to a live database. ## Model Used OpenAI GPT-6 through Codex, with reasoning, repository inspection, tool use, and code execution. The exact serving model ID and context-window size are not exposed. Z-AI GLM 5.3 Prime through OpenRouter (`openrouter/z-ai/glm-5.3-prime`) assisted the initial query treatment and benchmark. Codex repaired the comparison, narrowed the production change, and ran the full-size proof. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and 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> |
||
|
|
fa50cab568 |
perf(ui): speed task loading without shifting the conversation (#16849)
## Thinking Path > - Paperclip's board should open a task quickly while keeping its conversation and composer stable. > - The browser currently downloads unrelated screens and unopened dialog implementations before task content appears. > - Splitting routes alone creates many shared requests and did not improve measured cold loading. > - This change groups the startup and task dependency trees, preloads the task chunk, and defers optional routes and dialogs. > - Existing coordinated history reveal stays intact so late data does not insert content above the reader. > - Hidden routes must not overwrite saved scroll positions with zero-height geometry. > - Repeated browser measurements and delayed-response tests establish the result independently of bundle-file size. ## Linked Issues or Issue Description Refs #14758. Related prior work: #10463 and #14727. **What existing behavior does this improve?** Cold task-page opening downloads and evaluates code for other screens and globally mounted, unopened dialogs. A direct task link should reach its saved conversation sooner without moving already-visible messages or the composer. **Subsystem affected** Board UI startup, route boundaries, dialog loading, task scroll restoration, and the issue-detail performance harness. **Proposed behavior** Load optional screens and dialogs when needed, keep startup requests bounded, and preload the task route. Preserve the current history reveal policy. Keep the shell mounted during route loading and preserve the reader's position when a route is temporarily hidden. **Additional context** The older bundle-splitting attempt in #10463 is still open from August. This implementation targets current master and deliberately preserves today's editor, composer, and transcript reveal behavior. It does not implement the alternative transcript-row design discussed in #14758. ROADMAP.md does not describe overlapping startup-bundle work. ## What Changed - Lazy-load board routes, standalone screens, the legacy layout, onboarding, and unopened create dialogs. - Keep activated dialogs mounted across close/reopen to retain their existing draft lifecycle. - Group startup and issue dependencies and preload the emitted issue chunk from the production HTML. - Contain route loading within the shell and retain existing chunk-error recovery. - Contain dialog import failures locally, support cancellation, and keep setup dismissed after a late download. Warm the task module from task lists and keep the small chat redirect eager. - Wait for task-creation dialog fields in the browser fixture before filling an explicit title. - Ignore zero-height scroll geometry while a route is hidden. - Reuse the same persisted performance fixture between builds, record actual network spans, and distinguish concealed loading content from the ready thread in browser assertions. ## Verification - Production UI build and UI TypeScript check passed. - Recovery follow-up: 74 focused UI tests passed; the cancellation change passed 23 focused tests plus all 131 onboarding tests (the latter with a 15-second per-test timeout on the contended local host). - Setup cancellation was reproduced against the prior production build and verified fixed after releasing the held real wizard download. - 91 focused UI tests passed; the final route registrations were checked again after making standalone screens lazy (33 routing tests passed). - All eight real-browser layout scenarios passed: delayed comments, late media, properties changes, growing drafts, older history, Back navigation, deep links, desktop/mobile same-task links, request failure/retry, and stalled native/log reads. - Browser walkthrough: read a populated task, submit one reply, refresh, navigate to Projects, and return. The reply persisted once and the normal composer remained usable. - Token design gates passed. The separate repository-wide publish-token scan fails on pre-existing references to the local maintainer username in unchanged files; this change adds none. - Production-build measurements use the same persisted task, local API/database, fresh browser contexts for cold opens, and five samples per scenario/profile. These measurements do not establish deployed staging latency. - Final head `076466816a`, consecutive before/after production builds: five samples per scenario/profile, same saved task and server. Cold Fast 4G/4x CPU content paint: **5,775 → 4,248 ms (26%)**; issue API server timing was 23 ms in both sets. Warm Fast 4G: 989 → 971 ms. JavaScript transferred before content: **2,596 → 1,722 KiB (34%)**. - Unthrottled cold content paint: 1,306 → 676 ms; warm: 269 → 224 ms. These local timings vary with host load. Earlier measurements showed about 20% cold improvement, and a contended intermediate run had substantially higher API latency; those runs are retained in the local evidence. The final matched pair meets the proposed 25% target, but it does not establish a guaranteed 25% improvement across environments. - All four browser scenarios that failed on the first CI run passed locally after the readiness fixes; the subsequent CI run passed all eight browser shards. - Fault-injection browser checks: delayed route loading preserves shell geometry; a failed route recovers through Back; cancelled or failed dialog loading preserves an unsent reply; Back dismisses pending setup and contains its late failure. - Final head `076466816a`: all CI gates green (55 successful checks, no pending or failed checks); Greptile 5/5 with no actionable findings and all review threads resolved. ## Risks - Dynamic chunks add a loading state on first entry to optional screens and dialogs. Route failures use the existing error boundary. Optional dialog failures are dismissible without unmounting the board; retrying a rejected import requires a reload. - The task preload prioritizes the primary board journey, including when another screen is opened first. - Chunk grouping should be revisited when the dependency graph changes; bundle size alone does not establish a speedup. - No API, authorization, migration, editor semantics, or transcript-reveal policy changes. ## Model Used OpenAI Codex, GPT-6, with reasoning, repository tools, code execution, and browser verification. The runtime does not expose a more precise model identifier 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> |
||
|
|
06c5bc471d |
fix(skills): unblock retention for legacy run selections (#16852)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agent runs can select saved skill versions. > - The server keeps those files in a cache that must protect active and unresolved runs. > - Older runs can lack the newer pin map even when their saved execution input records the full selection. > - Finished interrupted runs can also keep a company blocked after all execution and cleanup have settled. > - This pull request uses existing selection evidence and recognizes settled interruptions so safe cache expiration can resume. ## Linked Issues or Issue Description Related: #16433. **What happened?** Skill cache retention reports `unknown_run_pins` for a whole company when it finds a finished interrupted run without pins, or an older native run whose complete selection is stored only in its execution input. Old cache directories cannot expire. **Expected behavior** Release pins from fully settled interruptions. Preserve exact versions from valid saved native selections. Continue to block cleanup when selection evidence is missing, invalid, or belongs to another run. **Steps to reproduce** 1. Materialize an old, restorable skill version and let its idle grace period expire. 2. Add a finished interrupted run with settled ownership and cleanup, or an unresolved native run with a valid saved execution input but no modern pin map. 3. Run the retention service. Before this change, it skips the company with `unknown_run_pins`. ## What Changed - Treat `interrupted` as terminal only when the existing finish, controller, finalization, and environment cleanup checks allow it. - For native runs with no modern pin-map field, parse the saved execution input with the existing recovery parser. Validate its digests and company, run, agent, and issue binding. - Keep captured version IDs protected. Unversioned skills use separate captured asset bundles. Do not replace a malformed modern map or write any recovery records. - Add database regressions and document the fallback. Remove an unused status list that no longer represented the actual eligibility query. ## Verification - Passed 41 focused tests: `skill-version-cache.test.ts`, `skill-version-retention.test.ts`, and `skill-version-retention-config.test.ts`. - The tests perform real PostgreSQL reads, directory eviction, and restoration from saved bytes with upstream unavailable. They cover leases, unfinished cleanup, invalid digests, invalid versions, and mismatched identities. - Passed `node scripts/check-module-boundaries.mjs` and `git diff --check`. - A read-only evaluation of the candidate selector against existing legacy data cleared the unknown-pin blocker while retaining exact version pins. - Passed `pnpm -r --workspace-concurrency=2 typecheck` and `pnpm build`. The full remote CI suite passed, including all server, workspace, Runner, and end-to-end shards. The full local test command remains in progress; its focused cache suites passed as recorded above. - Greptile reviewed this head at 5/5 with no actionable comments or unresolved threads. - Initial local database attempts did not run the cases: sandbox access prevented a listener, then an install with scripts disabled lacked PostgreSQL library symlinks. After running the package's symlink setup, the binary started and all focused tests passed. ## Risks The main risk is releasing a cache still in use. The existing ownership and cleanup checks remain in force. The native fallback applies only when the modern field is absent and the saved input passes the same parser used for recovery. Invalid or missing evidence still blocks the company. Current versions and explicit agent pins stay protected. Saved version rows and runtime asset bundles are not deleted. There is no migration. The selector reads execution inputs only for legacy native runs that need the fallback. Normal runs still load only their pin maps and binding columns. A representative read-only selector check completed in 98 ms; this is a sample, not a latency guarantee. ## Model Used OpenAI Codex, GPT-6 family, with tool-assisted coding and 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 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> |
||
|
|
9966f31bee |
fix(chat): keep permission failures scoped to the rejected operation (#16847)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - External channels deliver agent replies through a durable publication queue. > - A provider can reject one operation while other operations remain allowed. > - The shared error classifier treated generic 403 and permission errors as failures of the whole connection. > - Failure handlers then changed the user's enabled setting and removed all assigned channel tools. > - This pull request limits permission failures to the rejected operation and preserves connection intent during authentication failures. > - Unrelated work can continue, while confirmed authentication failures still stop endpoint traffic. ## Linked Issues or Issue Description Refs #16137. Follows #16138, which distinguishes local authorization errors from provider errors. This change also narrows provider permission failures. Related #16806 handles a separate task-continuation tool-binding defect. A provider 403 or missing-scope response currently disables a connection that may still support other operations. The expected behavior is a visible operation failure with unrelated work preserved. Confirmed authentication failures must stop sends without changing the user's enabled setting. ## What Changed - Classify generic 403, adapter permission errors, and Slack missing-scope/no-permission responses as failed operations. - Preserve rate-limit retries, known destination quarantine, and confirmed authentication failures. - Preserve connection status and enabled intent when publication, provider-reply, or form-open authentication fails. The endpoint still enters attention and its runtime stops. - Add GitHub regressions for retained discovery and successful later publication after 403, and no further sends after 401. - Mark authentication health failed and fence persistent receiver startup, background reconciliation, and receiver callbacks. Keep signed GitHub lifecycle events available during an authentication stop. Verify Discord reconciliation and Photon restart preserve the stop, while transient Discord disconnects still recover. - Update provider, publication, and modal regression expectations and the execution contract and verification maps. ## Verification - Red: five new classifier cases returned endpoint attention before the repair. The signed-installation-removal regression also reproduced a blocked lifecycle event after a 401 before narrowing the receiver guard. - Green: all 35 classifier tests pass. - Green: 19 PostgreSQL-backed cases pass through the production channel services, including GitHub discovery/publication, Slack provider replies and question modals, Telegram credential/destination failures, rate limiting, and Discord/Photon authentication-stop persistence. - Map structural checks and `git diff --check` pass. - `pnpm -r typecheck` and `pnpm build` pass. All CI gates are green on `7e379bcd98aa8363e42efe7f8a4b2589b7111ae6`; Greptile is 5/5 on that exact commit with no unresolved findings. - The monolithic local `pnpm test:run` was started, then stopped after its revision passed the full CI matrix and was superseded by the authentication-stop repair. Final full-suite verification passed in CI shards; all 19 final local provider regressions pass. - The tests run from this source checkout on macOS arm64 with isolated PostgreSQL and controlled provider failures. They do not prove live GitHub recovery or deployment. No live connection settings were changed. ## Risks - Permission failures now leave unrelated work available. The rejected operation remains failed and is not automatically replayed. Provider authorization still applies to every request. - Keeping a connection enabled must not bypass an authentication stop. GitHub verifies blocked tool discovery and later sends; Discord and Photon verify background reconciliation and restart cannot clear the stop. Failed connection health is an execution gate while the endpoint requires attention. - Explicit disable, disconnect, signed installation revocation, and existing destination-specific denial handling remain unchanged. No migration or API schema change is required. - Previously disabled connections are not automatically re-enabled because an upgrade cannot safely infer the user's intent. ## Model Used - OpenAI Codex, GPT-6 family. The runtime does not expose the exact deployment model ID or context-window size. Used reasoning, shell tools, repository edits, and test execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.1019.0-canary.7 |
||
|
|
016e40d532 |
fix(recovery): preserve shutdown export ownership through finalizer drain (#16843)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Legacy adapters must save sandbox files before Paperclip releases their source. > - Graceful shutdown gave each adapter a shared 30-second settlement wait. > - When that wait ended, cleanup could stop the sandbox while the adapter still exported files. > - That race created a restore failure and blocked the next turn. > - This pull request keeps export ownership through the finalizer drain and renews its cleanup fence. > - A successful late export can release its source and schedule one bounded continuation. ## Linked Issues or Issue Description Refs #15857. This corrects the timeout path introduced by the shutdown settlement fence. Refs #16478. That repair clears verified historical holds; this change prevents an active export from losing its source. Refs #16835. That merged fix handles remote native runner ownership. This change handles legacy shutdown settlement. ## What Changed - Keep a late adapter settlement in the shared execution finalizer set. Wait for it before lease release, recovery classification, and retry scheduling. - Renew the exact owned settlement fence every 10 seconds. Use a 30-second lease, one renewal in flight, a one-second database lock timeout, and a five-second statement timeout. Report bounded failure categories without raw database errors or credentials. - Refuse ordinary cleanup while the local adapter still owns settlement. Preserve the explicit owner stop-and-retain path. - Give the finalizer drain a further shared 30-second wait after the initial shutdown drain. - Document the ownership rule, the acceptance recipe, and the controller-loss limit. ## Verification - Red before the repair: the database-backed expired-wait regression expected cleanup denial but received permission to stop the still-owned source. - Green on `615a4382c5`: all 526 tests in `recovery.test.ts`, `legacy-workspace-restore-recovery.test.ts`, `shutdown.test.ts`, and `heartbeat-process-recovery.test.ts` passed. - The assembled heartbeat regression passed. It verifies no early release or retry, joining the late owner, successful cleanup, one durable scheduled continuation, and no duplicate after service reload. - Safety coverage includes other-controller fencing, controller loss, exact source retention, stop-only cancellation, completion winning the status race, and real database lock contention during renewal. - `pnpm -r typecheck`, `pnpm build`, and `node scripts/check-maps.mjs` passed on the final source revision. - A broad local `pnpm test:run` crossed the rebase and reported eight companion supervision failures. It was stopped and its log retained. The complete companion file then passed all 753 tests on current source. This is not a passing full local suite; current-head CI covers the complete repository checks. - The 34 recovery tests include real lock-timeout classification and credential-shaped error redaction. - Current-head CI: 53 checks passed; two optional Storybook checks skipped. Greptile is 5/5 on `615a4382c5`; no unresolved review threads. - Live sandbox acceptance remains unverified. Three disposable local-controller/Daytona attempts used legacy Codex ACP, `gpt-6-astra`, API-key authentication, and the verified image `ghcr.io/paperclipai/paperclip-daytona-runner@sha256:a2bd08cefb68d9217bdd75cf87a6b51f1705b18a4796eff3f97b2726a548b8fb`. ACP initialization exited before model execution on macOS Node 26.4.0 and again on Node 24.21.0; one attempt exposed a local process-session socket `ECONNRESET`. That does not establish the transport failure's root cause. No attempt reached the delayed export or second turn, so this PR remains draft pending faithful live acceptance. Probe setup defects were retained separately from product failures, and all test-owned sandboxes were cleaned up. ## Risks - Shutdown can spend up to 30 more seconds joining finalizers. The shipped Compose stop grace remains 90 seconds. - Renewal adds at most one database operation per owned run every 10 seconds during shutdown. Lock and statement deadlines bound database contention. The local adapter still protects its source if renewal fails. - Controller death or an export that outlives the whole process still needs retained-source repair. This change does not reconstruct a legacy export after process death or clear historical failed-restore holds. - No schema or public API changes. Native restart ownership, approval gates, and retry limits retain their existing behavior. - This PR has not been deployed. It does not recover an existing retained sandbox by itself. ## Model Used OpenAI Codex, GPT-6 family, with reasoning, repository inspection, code execution, and test tools. The exact backend model identifier and context window were 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> |
||
|
|
0ed760ce9a |
fix(server): keep local authorization failures from disabling chat endpoints (#16138)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Chat endpoints publish agent replies to providers such as GitHub, and a durable outbox classifies each send failure > - A GitHub review run that fails posts a "review failed" reply. When the run has no request binding, Paperclip throws its own `forbidden()` before any GitHub request > - The classifier reads that local 403 as a provider credential failure. The endpoint goes to `attention`, its tool connection is disabled, and new `pull_request` webhooks are dropped > - One failed review can stop all reviews on that endpoint until an operator reconnects it > - This pull request classifies Paperclip's own 401/403 `HttpError` without a provider status as a failure of that publication only > - The benefit is that only real provider credential failures lock an endpoint ## Linked Issues or Issue Description Fixes: #16137 ## What Changed - `server/src/services/chat-publication-errors.ts`: an `HttpError` (Paperclip's own class) with status 401 or 403 and no numeric `details.providerStatus` returns `{ kind: "failed" }`. The check runs before the credential branch. - Provider errors do not change. Adapter `AuthenticationError`/`PermissionError`, Octokit errors (named `HttpError`, but not this class) and Paperclip-wrapped provider rejections that carry `providerStatus` still return `endpoint_attention`. - `server/src/services/chat-publication-errors.test.ts`: a new test covers a local `forbidden()`, a local `unauthorized()` and a wrapped provider 403. ## Verification - `pnpm --filter @paperclipai/server vitest run src/services/chat-publication-errors.test.ts` - I ran the classifier source with type stripping on Node 22: local `forbidden("GitHub failure has no request binding")` → `failed`; local `unauthorized()` → `failed`; `new HttpError(403, …, { providerStatus: 403 })` → `endpoint_attention`; an Octokit-shaped 403 → `endpoint_attention`. - I applied the same change to the built `dist` of a self-hosted install and called its classifier with the same four errors. The results were the same. ## Risks - Low risk. The change applies only to Paperclip's own `HttpError` with status 401/403 and no provider status. Such an error now fails one publication and does not disable the endpoint. Code that throws a local 401/403 to report a provider credential problem must attach `providerStatus`. I found no such caller in `server/src/services`. ## Model Used - Claude Opus 5.5 (`claude-opus-5-5`, Anthropic), in Claude Code with tool use (shell, file edits, test runs). It helped to find the cause, write the change and the test, and run the 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 - [ ] I have run tests locally and they pass (classifier checked with type stripping; the full vitest suite runs in CI) - [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 mergecanary/v2026.1019.0-canary.6 |
||
|
|
56e09cd19f |
docs: add native Runner integration playbook (#16846)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Native Runner connects those agents to harnesses through provider drivers. > - Adding a harness crosses protocol, setup, lifecycle, packaging, and product boundaries. > - Existing guidance does not provide one complete procedure for this work. > - This pull request adds a native Runner skill, detailed playbook, and working templates. > - Contributors can use them to define a release, implement the integration, and verify the delivered result. ## Linked Issues or Issue Description **Issue type** Missing documentation. **Where is the issue?** Native Runner contribution guidance in `doc/DEVELOPING.md` and `packages/paperclip-runner/README.md`. **What's wrong?** Contributors must reconstruct the requirements, protocol mapping, normal setup, lifecycle rules, packaging, and acceptance process when they add a harness. The legacy direct-adapter recipe covers a different execution path. **Suggested fix** Add a self-contained native Runner procedure. Include capability research, a finite release contract, implementation boundaries, reproducible tests, normal installation, and release evidence. State each lesson directly so contributors need no private chats, tasks, or evidence archives. The duplicate search found no existing playbook PR. ## What Changed - Add `create-runner-adapter` for new native Runner harness integrations. - Add a detailed playbook based on the Pi, Cursor, and Copilot integration lessons. - Cover model and instruction admission, connection setup, rich events, durable interactions, recovery, cancellation, packaging, and Product E2E acceptance. - Add templates for scope, capabilities, attempts, failures, jobs, and release handoff. - Link the procedure from the development guide and Runner README. - Keep legacy adapters as a compatibility boundary. ## Verification - `git diff origin/master --check` passed. - `node scripts/validate-doc-links.mjs` passed from `packages/paperclip-runner` and checked 53 documentation files. - All 71 Markdown links in the new reusable files resolve to repository paths or public provider documentation. - Skill YAML, naming, description, and scaffold checks passed. - A private-reference audit passed for the reusable skill, playbook, and templates. - The legacy direct-adapter skill matches the base version. - Full local runtime checks were attempted with pnpm 9.15.4. `pnpm -r typecheck` stopped because Node type definitions are missing. `pnpm test:run` and `pnpm build` stopped because `cli/node_modules/tsx` is missing. This checkout has no installed dependencies. These commands did not establish runtime test or build results. - Full remote CI passed on commit `88b4fc4832d95807da1f5e48029a183b3dc62b6c`: build, typecheck, general and serialized server tests, Runner checks, browser tests, and the canary dry run. [CI run](https://github.com/paperclipai/paperclip/actions/runs/39262297681). - All 55 applicable checks passed. The two Storybook checks were skipped for this change. - Greptile gave the current commit 5/5. There are no review comments or unresolved threads. ## Risks Low risk. The procedure can drift as the Runner contracts and test entry points change. It records its source baseline and tells contributors to inspect current declarations. Historical lessons describe failure patterns; they do not certify current binaries. ## Model Used OpenAI Codex with `gpt-6-astra` and `gpt-6.1-sol`, both using xhigh reasoning. Context-window sizes were not exposed. The models used repository search, terminal tools, and file edits. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used, including available version and capability details - [x] I have checked ROADMAP.md and confirmed this documentation does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs - [x] I have described the issue in this PR using the documentation issue template fields - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal ticket or instance details - [x] I have run the relevant local documentation checks; they pass. Blocked runtime checks are recorded above - [x] I have considered tests for this documentation-only change and validated its links and skill metadata - [x] I have updated relevant documentation to reflect my changes - [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 merge Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
98ca6ff7c5 |
perf: reuse verified provider files during sandbox startup (#16493)
Build provider-pack transport layers once, reuse verified image files in private directories, and upload only missing layers. Preserve archive integrity checks and directory fallback on unsupported hosts. Verified with 44 focused tests, all 48 main CI jobs, cloud Docker Runner checks, and Greptile 5/5 on the merged head. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
661b104e04 |
docs: discourage utility scripts in package manifests (#16842)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Its review process protects package manifests because they define dependencies. > - New convenience scripts also change these protected files and cause extra review. > - Greptile needs a clear instruction to discourage these additions. > - This pull request adds the requested sentence to the Greptile prompt. ## Linked Issues or Issue Description **Issue type** Missing documentation. **Where is the issue?** The repository review prompt in `.greptile/rules.md`. **What's wrong?** Agents add package scripts for utilities and specialized checks. These additions trigger the extra review intended for protected package manifests. No duplicate open PR or issue was found in the GitHub search. **Suggested fix** Add this exact instruction: Do not add package.json scripts for new utilities, checks, benchmarks, or specialized tests. ## What Changed - Added the requested sentence to `.greptile/rules.md`. ## Verification - `git diff --check` passed. - Confirmed that the diff contains only the requested sentence and its separating blank line. - Local prompt and PR-template checks passed. - Full typecheck, test, and build checks were not completed. This worktree has no installed dependencies. The typecheck attempt stalled during pnpm startup and was stopped; the test and build commands were not run. ## Risks - Low risk. This changes review instructions only. Greptile may flag future additions in the listed categories. ## Model Used - OpenAI GPT-6 through Codex, with repository inspection and shell tools. The exact runtime model ID and context window size were not exposed to this session. The user supplied the added sentence verbatim. ## 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 prompt and PR-template checks only; full-suite limits are recorded above) - [x] I have added or updated tests where applicable (no new tests needed for this prose-only change) - [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> |
||
|
|
f3cd3f4ea8 |
fix(runner): require confirmed exit before remote replacement (#16835)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Remote runs need one runner to own their process identity and listener. > - A health request can fail while that runner continues to work. > - The active monitor treated a failed request as a process exit. > - Recovery could then launch another runner against the occupied listener. > - This pull request retries health reads and requires proof of exit before replacement. > - A brief outage can recover on the same runner without replaying agent work. ## Linked Issues or Issue Description Refs: #16341 adds remote recovery diagnostics. Refs: #16686 retries verification when restoring a saved remote session. This change applies the shared probe policy to active process supervision. **What happened?** The active remote monitor settled its completion promise after a timed-out or rejected health request. The transport treated that result as an exit and started process recovery. An existing runner could still own the listener. Replacement then failed with `runner_ingress_bind_conflict` until the reconnect deadline expired. Missing or changed ownership markers also did not prove that the old process had exited. **Expected behavior** Retry transient read failures on the same runner. Require a matching ownership marker and proof of process exit before replacement. Preserve uncertainty when identity or liveness cannot be verified. **Steps to reproduce** 1. Start a remote runner and leave its listener alive. 2. Make one process-health request time out or reject. 3. Observe completion and the restart decision. Before this change, the monitor settles while the process is alive, and the restart wrapper permits another launch. **Paperclip version or commit** The defect was reproduced on master at `6e89919631`. The patch is based on current master at `c6a0cf4bce`. ## What Changed - Reuse the bounded read-only recovery probe for active supervision. Retry up to three reads within 30 seconds. - Check the saved process generation when available. Accept only the specific process-not-running receipt as exit proof. - Add an exit-confirmation contract to remote process handles. Require it for restart and shutdown completion. Preserve the cause of supervision errors. - Test transient failures, exhausted retries, conflicting identities, real listening processes, and an authenticated runner with a fake provider. Keep confirmed-exit replacement covered. - Document the recovery policy and coverage limits in the execution contract and maps. ## Verification - Red: the timeout and transport-error regressions failed before the patch because completion settled while the runner was alive. The restart-guard regression also failed because replacement was allowed. - Green: 14 server supervision cases passed, including a real listening process. All 120 shared control-plane tests passed. Focused Runner tests passed for authenticated live-runner fault injection and confirmed-exit replacement. - Review regression: a replacement-health test first failed because its error cause was lost. It passed after preserving the cause and detail. The four affected transport cases and Runner typecheck then passed. - `node scripts/check-maps.mjs` passed for 35 areas and 176 capability IDs. - `pnpm -r typecheck` and `pnpm build` passed locally. The sequential local full-suite run was stopped before completion; no local full-suite pass is claimed. Final commit `bcc1b1d339` passed the complete CI matrix: 55 checks passed and two optional Storybook checks were skipped. Greptile is 5/5 with no unresolved conversations. The PR has no merge conflicts. - The first real-listener attempt could not bind inside the execution sandbox. The same test passed with local socket access. The first package-test invocation used the root configuration and selected no tests; the package configuration ran all selected tests. - CI attempt 1: nine test jobs were cancelled together at 12:54:59 UTC. Their test steps report cancellation. The build and uninterrupted jobs passed. The interrupted jobs were retried once. That retry exposed one confirmed-exit message assertion failure in the Runner shard; the other jobs passed. The compatibility correction preserves the prior message. The failing case and four recovery cases then passed locally. The complete CI matrix passed after that correction. - No live sandbox restoration, deployment, or historical task recovery is claimed. ## Risks - A persistent outage now ends supervision with explicit exit uncertainty. It cannot authorize a competing process. Existing ownership and workspace recovery checks remain required. - Health reads can take up to 30 seconds before reporting an unavailable runner. Retries are read-only and bounded. - Local launchers keep their existing completion contract. No database migration or public API change is required. ## Model Used OpenAI GPT-6 through Codex, with reasoning, tool use, and code execution. The exact serving snapshot and context-window size are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.1019.0-canary.5 |
||
|
|
9077748894 |
Remove the Pipelines experiment and preserve its data (#16834)
## Thinking Path > - Paperclip manages AI agents and their work. > - Pipelines was an unused experiment with its own UI, API, CLI, and automation. > - Keeping it leaves unsupported product surfaces and extra task-detail queries. > - Removing the experiment must preserve data that users already saved. > - This pull request removes the feature and keeps its database schema and migration history. > - Cases and Routines remain available as separate features. ## Linked Issues or Issue Description **What existing behavior does this improve?** Remove the unused Pipelines experiment across the application. **Current behavior** The experiment includes pipeline boards, stage settings, case automation, review queues, learnings, permissions, and CLI commands. Task detail also queries pipeline links. **Proposed behavior** Remove all these product surfaces and their implementation. Preserve existing tables, records, and documents. Ignore the retired boolean in older managed configurations so upgrades still start. **Breaking changes** Pipeline URLs, API endpoints, CLI commands, and `pipelines:write` are removed. Task detail no longer includes the old `linkedCases` field. The independent Cases API remains available. No database migration or cleanup is included. Related feature work: #7907, #9110, #10905, #11375, #13004, #14671, #16133. Related issues: #9663, #10310, #10312. This removal supersedes the feature; it does not implement those pending enhancements or delete their saved data. ## What Changed - Remove Pipeline UI pages, navigation, gates, clients, query keys, helpers, and unused design tokens. - Remove Pipeline REST routes, services, automation dispatch, task-detail queries, and OpenAPI discovery. - Remove the CLI commands, shared contracts, experimental flag, catalog entry, and permission defaults. - Remove feature-specific tests, tutorials, smoke scripts, maps, and Storybook examples. - Preserve database schema, migration history, and the reserved document key used by old records. - Keep Cases routes independent and cover obsolete stored and managed settings. ## Verification - Passed: `pnpm build` and `pnpm -r typecheck`. - Passed: targeted settings, managed configuration, sidebar, settings UI, routing, and feature-catalog tests. A first sidebar run caught a shared Workspaces icon import; the import was restored and the sidebar rerun passed. - Passed: 40 tests covering Cases routes, OpenAPI discovery, retained Pipeline table constraints, and schema snapshot drift. - Passed: token gates, map validation, generated API metadata check, Storybook catalog validation, and 28 map/catalog tests. - Passed: isolated local browser verification of navigation and Experimental settings with Pipelines absent; Cases and Routines still open normally. Live GET/POST requests to retired Pipeline endpoints return 404, and the retired setting is absent. CLI help has no Pipeline commands. - Passed: 22 access-service and agent-default-grant tests after restoring unrelated permission assertions flagged in review. - Local full run: `pnpm test:run` reported one failure in the unchanged workspace-runtime port-allocation test. That test passed in an isolated rerun. The long local run was stopped after full CI passed; it is not reported as a complete local pass. - Passed: all 56 checks on `def9181f3a4491d95fca1d38e9739f5b821aae3e` (2 conditional checks skipped), including build, typecheck, test shards, and browser suites. Eleven interrupted CI jobs reported “The operation was canceled”; their one-time retry passed. [CI run](https://github.com/paperclipai/paperclip/actions/runs/39255211006). - Greptile: 5/5 on the final commit, with the only review finding fixed and resolved. - Sandbox socket restrictions affected the first build/API test attempts. The same commands ran with local sockets available. ## Risks - Existing Pipeline clients must stop using the removed endpoints and commands. - Existing data remains in the database and backups, but the removed UI no longer displays it. - Historical boolean `enablePipelines` values are ignored. They cannot restore the feature. - Cases and Routines must retain their separate behavior. Targeted route tests cover this boundary. ## Model Used OpenAI Codex, GPT-6, with repository inspection, editing, shell execution, and browser verification. The exact deployed model ID and context-window size are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [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> |
||
|
|
f96a1e6406 |
refactor(skills): keep test audit evidence in tasks and PRs (#16833)
## Thinking Path > - Paperclip manages AI agents that perform work. > - The test-audit skill guides test maintenance. > - Its Paperclip reference tells agents to commit audit receipts under doc/plans/. > - This adds repository documents to small test cleanups, as seen in #16639. > - This change keeps audit decisions and validation evidence in the task and PR description. > - Test gardening creates no repository documentation unless a human asks for it. ## Linked Issues or Issue Description **Where is the issue?** `.agents/skills/test-audit/references/paperclip.md`, with related reporting instructions in the entry point, campaign guide, and validation reference. Related example: #16639. **What's wrong?** The skill requires repository audit receipts. A six-line test deletion in #16639 added an 88-line report under doc/plans/. The task and PR already provide a place for this evidence. **Suggested fix** Keep the evidence in the task and a concise PR description. Require an explicit human request before changing repository documentation during test gardening. ## What Changed - Removed the instruction to commit dated audit receipts under doc/plans/. - Added the reporting rule to the skill entry point. - Directed campaign ledgers and plans to the task. - Kept the existing coverage, validation, and delivery requirements. ## Verification - Skill validation passed with `quick_validate.py` from the skill-creator tool. - `git diff --check` passed. - Read the entry point and all bundled references to check for conflicting reporting instructions. - This change edits skill instructions only. Repo-wide typecheck, runtime tests, and build were not run locally. - [PR CI](https://github.com/paperclipai/paperclip/actions/runs/39253050703) passed on head `d0b68db878fa4da83858da5f74fd25e6120723b5`, including typecheck, test suites, build, and E2E checks. - Greptile reviewed that head at 5/5 with no open findings. ## Risks - Evidence must remain accessible in the task and PR. The instructions still require decisions, keepers, commands, results, and limitations. - An installed copy needs a refresh to receive this source change. An operator can also apply the rule in the agent and routine instructions immediately. > 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, based on GPT-6. The exact runtime model ID and context-window size were not exposed. Used repository search, instruction editing, and shell validation. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes: #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass (skill validation; no runtime changes) - [x] I have added or updated tests where applicable (not applicable to this instruction edit) - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.1019.0-canary.4 |
||
|
|
c6a0cf4bce |
test(server): retire duplicated resolveShell darwin fallback row (#16639)
<!-- Write all pull request text in Simplified Technical English (ASD-STE100): short sentences, one instruction per sentence, simple approved vocabulary, and the active voice. --> ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The server prepares task workspaces in `workspace-runtime.ts`. One helper, `resolveShell()`, picks the shell that workspace commands use. > - `resolveShell()` computes its fallback with one two-arm ternary: `"sh"` for win32, else `"/bin/sh"`. There is no separate darwin arm. > - The tests for this helper had three unset-SHELL fallback rows: linux, win32, and darwin. The darwin row repeated the linux row. It observed the same ternary arm and asserted the same value through the same code. > - This pull request removes the duplicated darwin row. The linux row keeps the non-win32 arm pinned. > - The benefit is one less repeated registration per suite run and a smaller platform matrix to maintain. No wall-time saving is claimed. ## Linked Issues or Issue Description - No public GitHub issue exists for this cleanup. The underlying problem: the `resolveShell` fallback tests registered two cases that could not fail separately. Any change to the non-win32 fallback arm breaks both rows at the same assertion. One row is enough to protect that arm. The audit receipt in `doc/plans/2026-10-17-workspace-runtime-resolveshell-test-audit.md` records the full decision table, the deferred candidate, and the retained rows. ## What Changed - Deleted `falls back to /bin/sh on darwin when SHELL is unset` from the `resolveShell (shell fallback)` describe in `server/src/__tests__/workspace-runtime.test.ts` (6 test lines). - Kept the win32 row (the only observation of the `"sh"` arm), the linux row (the only needed observation of the `"/bin/sh"` arm), the empty-string and whitespace-only rows (missing versus invalid input; whitespace-only also pins the trim-before-check order), and the missing-absolute-path row (the only observation of the `existsSync` guard). - Added the audit receipt `doc/plans/2026-10-17-workspace-runtime-resolveshell-test-audit.md` with evidence, commands, and the deferred candidate. - Corrected the receipt's mutation-control record (head |
||
|
|
1d24bd8e47 |
docs(skills): add fix-failed-paperclip-run workflow (#16830)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Failed or stalled tasks need a repair that restores useful work without weakening execution safety. > - The existing diagnosis skill stops at a plan and relies on private historical task links. > - A repair can pass a narrow test while still failing in the deployed runtime or permitting duplicate work. > - This PR adds a task repair workflow with failing-before/passing-after evidence, safety tests, real workflow verification, and PR checks. > - The old skill name remains usable and preserves explicit diagnosis-only or caller approval limits. ## Linked Issues or Issue Description **Issue type** Outdated documentation. **Where is the issue?** `.agents/skills/diagnose-why-work-stopped/SKILL.md`. **What's wrong?** The skill requires a plan approval even when implementation is authorized. Its private task links do not provide usable guidance to other contributors. It does not carry a repair through regression proof, second-order checks, real workflow verification, and a green PR. **Suggested fix** Add `fix-failed-paperclip-run` and route the old name to it. Keep the failure patterns self-contained. Keep explicit diagnosis-only requests and the Terminal-Bench caller's approval boundary effective. Related: #7658 established the maintainer skill location. A search for the old and new skill names found no competing task-repair skill PR. ## What Changed - Added a workflow from incident evidence through a verified repair and current-head PR checks. - Added eight standalone failure patterns with behavioral test oracles and common verification traps. - Replaced the old plan-only workflow with a compatibility entry point. Preserved issue-tree classification and the three liveness invariants. - Distinguished PR readiness, deployment, and recovery of the original task. Reuse an existing sufficient fix instead of creating a duplicate patch. ## Verification - Rename commit `b979b632ee8f1ef57f1e7d6c37c711d1c83f5844`: both skill validators, local reference checks, and whitespace checks pass. CI and review are pending for this commit. - The standard skill validator passes for both skill entry points. - All Markdown references resolve. Referenced repository workflows exist. The new files contain no historical task IDs, private URLs, or machine-specific paths. - `git diff --check` passes. - Manually reviewed scenarios for an existing merged fix, unknown historical cause, unsafe duplicate execution, live-only failure, explicit diagnosis-only scope, and the Terminal-Bench approval boundary. This is instruction review, not a live agent evaluation. - Attempted `pnpm -r typecheck`, `pnpm test:run`, and `pnpm build`. All stopped before execution because pnpm could not fetch and verify the pinned version in the sandbox. This worktree also has no installed repository dependencies. No runtime pass is claimed from these attempts. - No product code changed. At head `90ee31270420d2dac20dc3a41b12cddb5134d6ec`, 55 PR checks passed and 2 were skipped. Typecheck, tests, build, and the aggregate verification gate passed in CI. Greptile is 5/5 with no inline findings or unresolved review threads. ## Risks - The old skill now continues into implementation when a fix is authorized. Its explicit scope rule preserves diagnosis-only requests and approval requirements from callers. - This change is workflow guidance. Structural validation and scenario review do not prove how a future agent will execute it on a live incident. ## Model Used OpenAI Codex, `gpt-6-astra`, with tool-assisted history inspection, repository review, and Markdown authoring. 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 (skill validation; repository-wide commands could not start, as noted above) - [x] I have added or updated tests where applicable (no runtime behavior changed) - [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> |
||
|
|
6e89919631 |
refactor(storybook): check recovery disclosure visibility (#16828)
## Thinking Path > - Paperclip helps people manage AI agents and their work. > - Recovery previews show when work can continue and when an operator must inspect it. > - Saved-source reconstruction keeps its inputs inside a closed disclosure. > - The browser query can find those mounted inputs while the disclosure is closed. > - The old assertion required the inputs to be absent and failed before testing the disclosure. > - This pull request checks that each input is hidden, then keeps the existing open-and-inspect assertions. ## Linked Issues or Issue Description Refs #16686. The `SourceReconstruction` story fails with “Found multiple elements with the role textbox” while its disclosure is closed. The inputs are mounted but hidden. Their visibility is the intended contract. ## What Changed - Assert that all reconstruction text fields are hidden before opening the disclosure. - Keep the checks for the saved attachment and the disabled continuation button after opening it. ## Verification - Baseline: the browser play function failed at `queryByRole("textbox")` because it found two hidden fields. - Treatment: the same story passes all six browser interaction steps. Both hidden-field checks execute before the disclosure opens. - All ten play-enabled recovery notice stories pass in the browser, including automatic recovery, operator and reader blockers, missed recovery, read failure, mobile, reconstruction, and queued continuation. Revisiting automatic recovery after the error and reconstruction fixtures also passes. - Catalog validation passes. All 28 map and catalog tests pass. - UI typecheck and token gates pass. All 57 current-head checks pass or have their expected skipped state, including workspace typecheck, tests, and build. - Greptile scored this head 5/5 with no unresolved threads. The initial description gate did not recognize Storybook play files as tests; the assertion-only change is classified as a refactor and its rerun passed. - These stories use production components with fixture data. They do not prove provider recovery or a production deployment. ## Risks Low risk. This changes one Storybook assertion. A regression that exposes a reconstruction field before opening the disclosure still fails the visibility check. ## Model Used OpenAI Codex, `gpt-6.1-sol`, xhigh reasoning, with tool use and code execution. The host does not expose the context-window limit. ## 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> |
||
|
|
51c81d0129 |
feat(sentry): link run errors to task and run pages (#16803)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Operators use Sentry to inspect run and server failures. > - Reports identify the run and task, but the existing links open API records. > - Operators need a direct path from an error to the normal task and run pages. > - This change adds navigation links through the shared server Sentry hook. > - Saved company and task records determine the links. A failed lookup preserves the error report. ## Linked Issues or Issue Description Related work: #16300 added saved run API references. **What existing behavior does this improve?** Sentry event context for run failures, Stop timeouts, and server errors from an authenticated agent run. **Current behavior** Reports show task and run UUIDs. The existing run URL opens an API record. The operator must find the normal task page separately. **Proposed behavior** Add `task_url`, `run_url`, and `task_identifier` tags when saved run metadata is available. Add `taskUrl` and `runPageUrl` to the event context. Use the company prefix and saved task identifier in normal board URLs. **Reason and benefit** An operator can open the task or run directly from the error report. ## What Changed - Add a shared Sentry hook for events with a known run identity. - Read only the saved company prefix, task identifier, and run identity. Keep the lookup within the recorded company and agent. - Include authenticated run identity on request errors. Use the existing run identity on Stop errors. - Bound optional lookups to one second and eight unfinished reads. Preserve the original event on failure. - Keep the existing API references and error grouping. - Document the fields and add SDK, timeout, and company-boundary coverage. ## Verification - Passed: `pnpm -r typecheck` and the final server TypeScript check. - Passed: `pnpm build`. - Passed: 332 tests across the affected server suites, plus 25 final link and real Sentry SDK tests after review fixes. The SDK test checks outgoing event envelopes for run failures, request errors, and Stop errors. It checks that unrelated errors receive no links. The database test verifies saved metadata and company boundaries. It passes with embedded PostgreSQL and with an explicitly configured disposable test database. - Passed in CI on `bec0cdac853efdef71041d59a66261941827653e`: the full test matrix, typecheck, build, Runner checks, browser suites, and the real Sentry SDK contract. All 56 active checks pass. Two Storybook jobs are skipped. - The full local `pnpm test:run` attempt first failed because PostgreSQL library links were missing. The package setup script repaired the install. The affected database suites then passed. The repaired full local run was stopped after all CI test jobs passed; it did not complete locally. - Greptile: 5/5 on the final commit. All three review threads are resolved. - Read-only browser inspection confirms that Sentry displays context URL values with an Open link control. - No live test event was posted. Validation uses the real SDK with an in-memory transport. ## Risks - A slow or unavailable database can prevent optional links. It does not discard the error. At most eight unfinished lookups can remain active. - Missing or unsafe public origins omit the links. URLs longer than the tag limit remain in context. - This change applies to newly captured events. It does not update existing Sentry events. - The change adds no schema, permission, or first-party Telemetry contract change. ## Model Used OpenAI Codex, `gpt-6.1-sol`, xhigh reasoning, with tool use and code execution. The exact context window is not exposed in the session metadata. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.1019.0-canary.3 |