mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-21 16:27:18 +02:00
c6a2734311d29f3af4ba97dd3cea656fa112d071
2451
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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
|
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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 merge |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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 |
||
|
|
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> |
||
|
|
2f6ad2226a |
fix(heartbeat): reconcile stranded running agent status (#16791)
Serialize agent completion status updates with new execution starts. Repair stranded running flags through existing recovery after durable work and cleanup settle. Share exact failed-lease cleanup proof with idle sleep, bound recovery work, and keep repair failures from blocking unrelated recovery. Verified with 54 successful CI checks, 292 affected regressions after review fixes, workspace typecheck/build, and Greptile Apex 5/5 with no unresolved comments on the merged head. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
1a79c8bdc7 |
fix(runtime): honor provider startup budgets on sandbox resume (#16802)
## Thinking Path > - Paperclip manages AI agents and their execution environments. > - Follow-up runs reuse saved sandbox computers to keep their workspace. > - Starting a stopped or archived computer can take more than one minute. > - Acquisition already uses the provider's startup budget, but reuse imposed a separate one-minute deadline. > - This pull request gives resume the configured or declared provider startup budget. > - The benefit is that a healthy slow start can continue on the same computer. ## Linked Issues or Issue Description **What happened?** A follow-up run failed during setup with `ReusableSandboxResumeError`. The saved computer became ready just after the host stopped waiting. The environment had no explicit timeout. Its provider declared a five-minute startup default, which the resume path ignored. **Expected behavior** Resume must honor the configured startup budget or the provider's declared default. It must retain the same lease. Failed or uncertain resumes must keep the saved computer. **Steps to reproduce** 1. Use a reusable sandbox provider with a startup budget longer than one minute. 2. Retain its lease and start a follow-up run. 3. Make provider resume finish after 61 seconds, within that budget. 4. Observe that the old host rejects at 60 seconds. **Paperclip version or commit** Reproduced on `aaeff418cf72341c674ff3393cd94f40dc4855f6`. **Deployment mode** Hosted sandbox execution. The regression uses a local isolated PostgreSQL database and controlled worker RPC timers. Searched open and closed PRs and open issues for sandbox resume and timeout fixes. No duplicate fix was found. Related acquisition timeout handling already exists on the base branch. ## What Changed - Use the provider's declared acquisition timeout when no explicit startup timeout exists. - Apply the resolved RPC budget to the shared resume/retry deadline instead of 60 seconds. - Add two deterministic 61-second resume regressions for declared and explicit startup budgets. Assert exact RPC budgets, including the 30-second margin, and check that the same lease remains active without replacement. - Document the timeout behavior, provider-author contract, and verification recipe. ## Verification - Red: both new cases failed before the production change with `ReusableSandboxResumeError`, caused by `Plugin RPC timed out`. - Green: `pnpm exec vitest run --fsModuleCache server/src/__tests__/environment-runtime.test.ts` passed all 163 cases. The final review follow-up also passed both slow-resume cases with exact RPC-budget assertions (330 seconds by declaration; 150 seconds by explicit config). - An earlier full run passed the 161 existing cases but timed out in the two new tests because their fake clock also captured database scheduling. The corrected test restores real timers before lease persistence. The complete rerun then passed. - `node scripts/check-maps.mjs` passed. - `pnpm -r typecheck` and `pnpm build` passed locally. - Started `pnpm test:run`, then stopped the duplicate serial run in favor of complete parallel PR CI. The repository timing data totals about 126 minutes for server suites alone. Full parallel CI passed on the final head. - CI attempt 1 had one unrelated failure: `FileViewerSheet.copy.test.tsx` expected the asynchronous `Copied link` confirmation before React rendered it. That test and component are unchanged from the base branch. All six cases passed unchanged locally. A single rerun of the failed shard passed; attempt 2 of the full workflow succeeded. The timing-race diagnosis is an inference from the test helper, not a claim that this PR repairs that UI test. - Greptile scored the final head 5/5. Both review findings are fixed and both threads are resolved. - The consequential assumption is that provider startup may exceed one minute. The test preserves the RPC timeout race with controlled timers and uses real lease persistence. Read-only provider evidence also showed the retained computer ready just after the failed run ended. The patch has not been deployed to that instance. ## Risks - A slow or unavailable provider may hold setup for its configured startup budget instead of one minute. Retries still share one finite deadline. Providers with no explicit or declared timeout keep the one-minute default. - Lease identity, company scope, backup validation, and replacement decisions use the existing paths. No schema or dependency changes are required. ## Model Used - OpenAI Codex, GPT-6. This session supports reasoning, tool use, code editing, and test execution. The exact runtime variant and context-window size are not exposed. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have 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> |
||
|
|
b85a69b334 |
test(server): record observer load in native event replay (#16800)
Record observers and polling in synthetic native replay measurements, with zero-viewer controls and correctness checks. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
3858d2341d |
fix(recovery): default saved-monitor waits and keep task recovery quiet (#16686)
## Thinking Path > - Paperclip manages AI agents and their work. > - A task must keep a durable path to its next action. > - A provider can save a task monitor, then fail to yield because it omits internal continuation fields. > - An interrupted provider-pack check can then be reported as permanent artifact incompatibility. > - The task asks its user to certify recovered workspace files, even though this is an operator responsibility. > - This pull request derives the saved monitor continuation, bounds verification retries, and removes that task form. > - Normal recovery stays quiet. Unresolved holds retain inspection and the existing safety checks. ## Linked Issues or Issue Description **What happened?** A yielded completion without `continuation` is rejected even after the provider saves an eligible monitor on the task. Repeated attempts cannot finish. Remote verification also treats timeouts and missing exit status as artifact incompatibility. The task recovery notice exposes raw diagnostics and asks the task user to certify infrastructure files. **Expected behavior** Use current persisted task state to fill routine continuation fields. Retry interrupted verification reads within a fixed bound. Keep normal recovery in the working state. Show a compact notice only when work cannot safely continue. **Steps to reproduce** 1. Save an eligible monitor on the active task. 2. Call `paperclip_finish` with `reportedWorkDisposition: "yielded"` and omit `continuation`. 3. Return a timed-out remote provider-pack command with empty stderr during recovery. Inspect the resulting task notice. **Paperclip version or commit** Source baseline: `aaeff418cf` (master integrated with its current task visibility and saved-source reconstruction rules). Related changes: #15824, #16104, #16451, #16493, #16690. This fix complements saved-result recovery and verified pack reuse. It does not replace their workspace ownership checks. ## What Changed - Allow omitted or null continuation at the provider input boundary. Read current authorized task context and fill a monitor continuation only for the bound run and an eligible saved monitor. Keep accepted results strict. Apply this to Codex, OpenCode, both direct and production-sidecar ACPX paths, and external drivers. Reserve the semantic call identity during the saved-context read and reject cancellation or a changed run/turn. - Bind the shared completion change and continuation helper in a new Copilot v21 source declaration. Preserve v20 history and its decoder support. Qualification stays pending. - Expose the eligible continuation in task context. Completion admission still checks persisted monitor state. No schedule is created or renewed by the default. - Retry read-only provider verification at most twice per command. Hold exhausted reads with a distinct verification-unavailable cause. Reattachment cannot renew the read budget through an unchanged provider-attempt counter. Keep completed verification failures and wrong versions incompatible. - Remove the task file-certification form. Hide the notice only for a matching durable recovery path without an unknown-action replay hold. Keep missed retries, unsafe outcomes, and unresolved file holds visible. - Add production-component stories for automatic recovery, blocked and expired holds, reader access, persisted repair decisions, source reconstruction, queued continuation, and mobile. Preserve master’s guarded saved-source reconstruction choice after confirmed source destruction. Update the execution contract and access maps. ## Verification - Completion, helper, Codex, OpenCode, ACPX, and profile regressions pass. After the sidecar review fix, 271 tests across the production sidecar and three provider suites pass, plus 72 helper/profile tests. The real sidecar MCP bridge tests cover saved-monitor acceptance, no-monitor refusal, cancellation, duplicate call identity, and raw-versus-forwarded semantic receipt hashes. The OpenCode tests also cover eligible-monitor acceptance and refusal without one. - The fresh full native executor suite passes all 743 tests. Four profile, installation-integrity, and ACPX driver suites pass all 168 tests. The earlier CI fingerprint failure required a new immutable source declaration; its follow-up Docker failure required the matching context allowlist entry. Both fixes are verified locally. Targeted server monitor, tool authority, and provider verification suites pass. The probe tests include a real timed-out subprocess, an unrelated responsive timer, transport errors, and completed integrity rejections. - All 90 tests in the merged task notice, reconstruction choice, recovery display, and lineage suites pass. They cover reader access, live/missed/mismatched recovery, unknown outcomes, saved messages, retry refusal, and removal of the file form. Both review findings have failing-baseline/passing-treatment regressions: identical polling across retry expiry, and a failed refresh after cached running activity. - Browser walkthrough passed for automatic recovery, unresolved details, a 390px mobile story, and the merged saved-source reconstruction and queued states. The reconstruction control starts disabled and normal automatic recovery shows only Working. The stories use production components and fixture API data. They do not prove live cloud recovery. - Token gates, map checks, and Storybook catalog generation pass. The exact Docker context integrity command passes locally after adding the new build declaration to its allowlist. - Workspace typecheck and build pass on the final source, including the versioned identity update. The final server and UI guards pass their focused tests, typechecks, builds, and token gates. The final standalone Storybook builds. The saved-monitor default retains master’s stricter child-task visibility filter. Re-review caught an additional production-sidecar validator before forwarding; the fix now defaults at that boundary and has passing regression controls. After preserving master’s new reconstruction capability, 68 targeted reconstruction, tool-authority, and provider-verification server tests pass. The current-master integration at `2a80050a0d` has a fresh 5/5 review with zero unresolved threads. Its complete CI matrix, including Runner tests, is the merge acceptance record. - On the final master integration, local typecheck, build, and all 90 recovery UI tests pass. A concurrent runner run hit five 5-second sidecar startup timeouts; an isolated sidecar run passed 86 tests and timed out in the unrelated unsupported-bootstrap case. Those local deadline failures remain recorded; the canonical CI Runner lanes use their normal deadlines and pass. The unsharded local full-suite attempt did not complete. It spanned source edits; the fresh native executor run above passes. An unrelated workspace fixture timed out once and then failed to reserve 32 contiguous ports on this host. Its unchanged-base control and CI server suite pass. Full-suite acceptance uses the fresh latest-head CI matrix; this PR does not claim a passing unsharded local run. ## Risks The default applies only to an eligible persisted monitor. An explicit invalid continuation still fails validation. The added read occurs only when a yielded report omits its continuation. Admission rechecks current state after that read. An interrupted verification command can add one extra 30-second probe. Completed rejections stay closed. These probes do not change the pack, launch provider work, or replay external tools. Two inconclusive reads hold the original run. They do not schedule another reattachment with an unchanged provider-attempt counter. This PR’s pending Copilot v21 declaration binds the changed shared contract, resolver, direct driver, and production sidecar sources. The previous v20 declaration is immutable and remains decodable, but launch requires the new exact identity. Qualification remains pending. Task users lose the file-certification form. Board-authorized source-only repair remains available through the resolution API with the original evidence and stop-receipt requirements. This branch does not deploy or recover historical held runs. > This is a bug fix and UI polish within existing recovery behavior. ROADMAP.md was checked. ## 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 (changed-area suites; the full local run limitation is recorded above) - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
023f4a5d0c |
fix: preserve repository cache negotiation refs (#16687)
## Thinking Path > - Paperclip manages agent work and its execution environments. > - A fresh repository task needs an independent checkout before its runner can start. > - The object cache from #16487 should reduce repeated network transfer. > - The cache kept Git objects but dropped remote-tracking refs during its bare clone. > - Git needs those tips to negotiate which objects it already has. > - This pull request preserves the tips in a versioned mirror cache and records explicit cache outcomes. > - The benefit is less repeated transfer and clearer evidence when a cache does not help. ## Linked Issues or Issue Description Refs #16487 and #16454. No duplicate cache-negotiation fix was found in the public PR search. **What happened?** A valid object cache could make a fresh clone slower. A controlled staging probe took 45.87 seconds and received 184.39 MB even though the reference already held the objects. An earlier probe took 52.33 seconds. An uncached clone took 20.94 seconds. `git clone --bare` copied the pristine checkout's objects, local branches, and tags, but omitted its remote-tracking refs. The source had about 1,200 remote branches. Git could not use the missing tips to negotiate those objects. **Expected behavior** Keep the pristine reference's negotiation tips. Each task must still authenticate online, use the current remote refs, and end with independent Git objects. **Steps to reproduce** 1. Clone a repository with many remote branches into a fresh checkout. 2. Publish a reference with `git clone --bare --no-hardlinks` from that checkout. 3. Clone the remote with `--reference-if-able` and `--dissociate`. 4. Compare with a reference that retains the remote-tracking tips. Use Git Trace2 and count received pack bytes. **Paperclip version or commit** The staging runtime was `27ab902d3db2770ada79c9f42a9c06e1d346f34b`, with Git 2.47.3. The cache implementation was unchanged from #16487. **Deployment mode** Docker on a persistent application volume. The probe used the application file owner and the public Paperclip repository. It did not start agent tasks or alter the application cache. ## What Changed - Publish pristine object caches with `--mirror` to retain remote-tracking tips. - Put cache format version 2 in the key and receipt. The first checkout builds a new generation. Existing generations stay under the current storage limits. - Keep the existing online authentication, current remote refs, credential and company isolation, independent objects, quotas, and fallback behavior. - Add closed Honeycomb cache outcomes and a boolean that states whether a reference was supplied to clone. - Document that a lookup hit or supplied reference does not prove Git avoided transfer. ## Verification - Controlled staging component experiment: a disposable reference copy held exactly the same 210,057 objects as the original. It added 1,187 advertised branch tips whose commits were already in those objects. - Before: 45.87 seconds and 184.39 MB received, one sample in this comparison. - After: 12.20 and 14.58 seconds; median 13.39 seconds. Received pack sizes were 1.99 and 1.95 MB. - All comparison clones used the same current remote HEAD and ended without an alternates file. - The remaining repack took 9.72–9.81 seconds. Checkout file writing took 0.86–0.96 seconds. - The staging experiment restored tips on a disposable cache copy. It did not deploy this patch or measure complete agent latency. - Confirmed both staging scratch locations were empty afterward. The original cache timestamps stayed unchanged. The temporary operator SSH key was revoked and its local files removed. - TypeScript 5.9.3 transpilation reported zero syntax diagnostics across the four changed TypeScript files. `git diff --check` passed. - The new negotiation regression fails with the old `--bare` publisher and passes with the mirror publisher. - Focused Vitest suites: 26 tests passed across repository-object-cache and execution-preparation-timing. These cover independent objects, current refs, unavailable/revoked remotes, scope separation, invalid storage, tracing isolation, and endpoint-off behavior. - The first full focused run passed 24 tests but failed its existing localhost HTTP fixture because the sandbox denied `listen` on `127.0.0.1`. The rerun with local loopback permission passed all 26 tests. - Server semantic typechecking passed with `tsc -p server/tsconfig.json --noEmit` after building the required workspace declarations. Initial attempts lacked generated dependency outputs; the completed dependency build and rerun passed. - A full application build was not run locally. CI passed: 55 checks passed and two optional checks were skipped. Greptile is 5/5 on the current head, with both findings resolved. ## Risks - Version 2 causes one cold cache rebuild. Old cache generations retain their disk usage, and the existing quota can prevent publication. - A cache still needs a full repack to produce an independent task checkout. This PR does not remove that cost. - The component experiment establishes the negotiation effect on staging. It does not establish an end-to-end agent speedup or the under-30-second goal. - The new trace fields remain behind the existing OTLP gate. Their values are closed enums or a boolean. They export no refs, paths, URLs, cache keys, credentials, or error text. ## Model Used OpenAI Codex, GPT-6 family, with code and tool use. The exact serving model ID and context window are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
aaeff418cf |
fix(acpx): add a positive control to stalled-tool permission evidence (#16769)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The ACPX engine runs Claude agents. A watchdog ends a turn when a pending tool call gets no update for 30 minutes. > - #16688 added a field to stalled runs. The field records if the stalled call's permission request reached Paperclip. > - Recent stalled runs show `acpStalledToolPermissionRequested: false`. We can read this as "the call stopped before its permission request". That reading is correct only if calls of the same kind usually send a request. > - We have no data that shows if finished calls of that kind sent requests. Thus we cannot tell if the missing request is a real signal. > - This pull request records a positive control: the number of finished calls of the stalled call's kind, and how many of them sent a permission request. > - The benefit: the next stall event tells us if the missing request locates the stall, or if it gives no information. ## Linked Issues or Issue Description Refs #16688 **What happened?** Runs stop with the stalled-tool watchdog error. The diagnostics show that the stalled call sent no permission request. The diagnostics do not show if finished calls of the same kind sent requests. **Expected behavior** The stalled-run diagnostics contain enough data to show if a missing permission request is a real signal. **Steps to reproduce** A pending tool call gets no ACP update for 30 minutes. The watchdog ends the turn. The run result contains the stalled-tool fields. ## What Changed - `packages/adapter-utils/src/acpx-engine/execute.ts`: when the watchdog fires, count the finished calls of the stalled call's kind, and count how many of them sent a permission request. Write the counts to the run result as `acpSettledSameKindToolCount` and `acpSettledSameKindToolPermissionRequestedCount`. - `server/src/services/run-failure-diagnostics.ts`: allow the two new fields as non-negative safe integers. Other values are dropped. - `doc/observability.md`: explain how to read the two fields with the existing permission-request field. - Tests: extend the existing stalled-tool tests in `execute.test.ts` and `run-failure-diagnostics.test.ts`. ## Verification - `pnpm exec vitest run src/acpx-engine/execute.test.ts` in `packages/adapter-utils`: 244/244 pass. - `pnpm exec vitest run src/services/__tests__/run-failure-diagnostics.test.ts` in `server`: 115/115 pass. - Mutation check: remove the kind filter, or count every finished call as "requested". Each mutation makes the stalled-tool test fail. - `tsc --noEmit` passes in `packages/adapter-utils` and in `server`. Note: the full `server` `typecheck` script did not run locally, because the runner vendor build step failed in this sandbox. I ran `tsc --noEmit` directly. ## Risks - Low risk. The change only adds two counts to the run result after the watchdog fires. It does not change the decision to stop the turn, or any permission decision. - The fields hold only counts. They contain no tool titles, inputs, or identifiers. This is the run-log and run-result path. It is not Telemetry. The fields reach Sentry through the existing allowlist in `run-failure-diagnostics.ts`. ## Model Used - Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, used through Claude Code with tool use (shell, file edits, test runs). ## 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> |
||
|
|
1558d9962c |
fix(idle): exclude completed feedback history from background work (#16764)
Allow private feedback history and acknowledged uploads to stop blocking idle sleep. Pending, failed, unfamiliar, and inconsistent delivery records remain blocked; preserve all other work and cleanup gates. Verified with 220 idle-safety tests, workspace typecheck/build, full CI, and Greptile Apex 5/5 on the reviewed head. Local full-suite limitations and isolated rechecks are documented in the PR. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
5dced3c766 |
perf(tools): narrow profile and attention catalog reads (#16761)
Read only the catalog, connection, and invocation fields needed by profile summaries, reviews, and attention counts. Preserve company scope and response contents while reducing query payloads. Verified with 445 affected service tests, workspace typecheck/build, full CI, and Greptile Apex 5/5 on the reviewed head. Local full-suite limitations and isolated rechecks are documented in the PR. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
27709a99b1 |
perf(scripts): emit a server module beside the runtime bundle entry (#16765)
The runtime bundle now also has a server entry point, dist-runtime/server.mjs: the bundled dist/index.js without the argv shim. index.mjs loads it, so importing server.mjs loads the server code without starting it, and a compile cache warmed from it covers exactly the files a boot loads. bundleRuntime reports it as serverModule. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
8de28c12e4 |
test(server): prove execution span overlap with explicit barriers (#16712)
Prove overlapping execution spans with per-run promise barriers, live recording checks, and exported span identity matching. Preserve the existing run ownership, parent, ingress-link, count, and test-budget assertions. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
6bec153410 |
fix(runtime): retain cancelled workspaces before reconstruction (#16700)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Native runs must preserve files when Stop ends a turn before its result is saved. > - The cancellation path could skip file retention and leave a prepared remote workspace active. > - An older controller could also admit an extra run while an earlier lost-source hold was unresolved. > - Rejecting every later run then prevented recovery even after that extra run was stopped and its files were reconciled. > - This change retains cancelled workspaces and records the exact proof for a safely reconciled intervening cancellation. > - Recovery can proceed without changing cancelled history, replaying actions, or weakening execution gates. ## Linked Issues or Issue Description Refs: #16583, #16690, #16696. **What happened?** Stop could acknowledge a native turn without recording its unsaved file obligation. Reconstruction also rejected a later cancelled run after its exact environment and files had been reconciled. The task could remain inactive with an `in_progress` status, which the reconstruction endpoint rejected. **Expected behavior** Retain unsaved files after Stop. Permit a board operator to reconstruct from saved sources only after each intervening cancellation has a confirmed stop and a file-only repair record. Preserve the original failed export and the cancelled run. **Steps to reproduce** 1. Prepare a native workspace and cancel the turn before a structured result exists. 2. Inspect its file retention and remote lease state. 3. For a task with an older destroyed export, reconcile the later cancelled run's exact files and unperformed actions. 4. Request reconstruction from verified same-task attachments. ## What Changed - Pin prepared native files before cancellation settlement. Defer teardown if pinning fails. Use the existing stop-only cleanup worker. - Repair active warm and ephemeral sources, plus stopping and confirmed-stopped historical cancellations in bounded startup and periodic batches. Preserve the existing exact-source checks. Bound row-lock waits and advance past a busy source. - Accept only same-owner native run-only cancellations with no result or current coordinator, confirmed stopped leases, and board file-only repair with `not_performed` action outcomes. - Save hashes of each intervening repair and recheck them at queue claim and final dispatch. Reject changed evidence or another later run. - Expose saved-source reconstruction in the issue API for inactive `blocked` and `in_progress` tasks, and hide it when an execution or checkout owner exists. Permit the same inactive source at submission. Keep the source, owner, version, attachment, budget, pause and retry checks. - Update the shared evidence type, recovery runbook and capability maps. Add an optional cancelled-native no-action confirmation to file recovery, resetting evidence when its source changes. No migration, new endpoint, permission or dependency. ## Verification - The new fixture fails on the original validator with `workspace_reconstruction_stale` after valid cancelled-run file repair. - Focused source and Stop retention tests: 94 passed before the final contention case. The subsequent three-suite run passed 123 tests, including real PostgreSQL lock contention and public startup/API/final-dispatch paths. The final narrow-query rerun passed all 123 tests. Review correction: all 143 tests passed across four suites, including real lock contention through the teardown boundary and stopping/stopped allocations. - Six broader cancellation, executor, heartbeat and restart suites: 831 passed, 9 existing skips. - Final correction: all 145 backend tests and all 36 recovery UI tests passed. Real contention covers both warm reusable and ephemeral sources. Optional no-action confirmation defaults to uncertified, and changing source clears evidence. Workspace `pnpm -r typecheck` and token gates passed on these sources. - Maps, module boundaries and Git whitespace checks: passed. Full `pnpm build` passed on the final `4e8c0e73ac` revision as well as the prior reviewed heads. A full local run of the preceding fix completed with 21,724 passes, 109 skips and three failures in webhook body limits, a status-card timeout, and a port-allocation fixture. All three suites then passed unchanged in an isolated rerun (209 tests). The full local run remains recorded as failed; the final head's full CI passed (55 completed checks, no failures). A fresh full local run is also in progress on the frozen reviewed head. - Preserved failures: the first attempt lacked a built plugin SDK; after building prerequisites, the regression reached the expected validator rejection. Treatment tests caught the file-only action's deliberately null continuation owner. A real lock test then caught the database driver's wrapped timeout error. Both defects were corrected and retested. Independent review then found a teardown race after a failed retention write. A second review found active warm sources excluded by the historical policy filter; the regression reproduced both warm failures before correcting the query. Its real-row-lock fixture reproduced the failure; the fixed release guard and historical stopping/stopped cases pass. No checks were weakened. - A pre-deployment walkthrough caught the issue API still hiding reconstruction for an inactive `in_progress` task. The status/capability baseline reproduced three failures, including inappropriate capability flags for execution/checkout owners. The fix uses the same inactive-state requirements as submission; its positive fixture reads the assembled issue API before reconstructing. All 117 tests in those three recovery suites pass, and all 28 heartbeat-recovery tests pass separately. Full workspace typecheck passed again. Full build passed with the exact `4e8c0e73ac` stamp; latest-head independent review is 5/5 with no open findings. All 55 latest-head checks completed with no failures. - Live tenant acceptance remains pending. No successful reconstruction, export or warm-process proof is claimed by these local tests. ## Risks - Stop retains unfinished work, so storage remains until file recovery and explicit cleanup complete. - Reconstruction remains held for unknown or performed external actions, foreign owners, live or rebound environments, accepted results, changed evidence, and unrelated later runs. - The sweep examines at most five candidates per pass. It uses a fair cursor and bounded transaction waits. It performs no provider call and starts no new turn. - Intervening verification reads only the needed JSON fields. The source transaction still serializes recovery for the same task. ## Model Used OpenAI Codex, GPT-6 family, with reasoning, tool use and code execution. The session does not expose an exact backend model ID or context-window size. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
69ac928d2b |
fix(runtime): preserve bounded retries after workspace reconstruction (#16696)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - An operator can rebuild a destroyed workspace from saved task attachments. > - The first reconstruction run must pass current source and execution checks. > - A temporary bootstrap failure can create a bounded retry before provider work starts. > - The retry has a new run ID, so the first-run-only reconstruction check rejects it. > - This change verifies the retry chain back to the approved first run and keeps current safety checks. ## Linked Issues or Issue Description Refs #16690. **What happened?** After an operator records workspace reconstruction, a safe bootstrap retry is cancelled before provider startup. The normal retry scheduler creates the successor. The reconstruction check then rejects its immediate predecessor because it expects the original failed export run. **Expected behavior** A verified automatic retry can continue under the same reconstruction decision and remaining retry budget. Changed sources, unrelated executions, uncertain outcomes, pause and later human blocks must still stop startup. **Steps to reproduce** Record reconstruction with a retry budget remaining. Let its first run fail before provider work starts with recorded bootstrap evidence. Use the normal bounded retry scheduler and the locked dispatch gate. Before this change, the scheduler succeeds but dispatch returns false. ## What Changed - Verify the predecessor chain back to the recovery action's exact first continuation. - Check company, task, agent, terminal predecessor state and each scheduler-owned wake. Reject cycles, foreign parents and forged wakes. - Exclude only those verified predecessors from the unrelated-newer-run check. Keep source hashes, original result identity and all current execution gates. - Reuse the existing reconciliation proof for failed predecessors. Keep the original retry limit. - Add real PostgreSQL scheduler and assembled-heartbeat regressions. Update the recovery guide and feature map. ## Verification - The baseline regression failed at final dispatch after the normal retry scheduler created its successor. - The corrected focused group passes 133 tests across reconstruction, retry scheduling and dispatch. It admits two bounded bootstrap retries and refuses a third. The assembled heartbeat enters the provider once for an eligible retry and zero times after a controlled post-claim human block. - An intermediate negative case exposed missing predecessor-outcome validation. Reusing the existing reconciliation proof fixes it. Deleted sources, pause, forged wakes, foreign parents, unrelated runs and new recovery holds remain refused. - Full workspace typecheck and build pass on rebased head `bd301ec8a703fa1cdc9e1db2638440d203e8d57a`. The rebased focused group passes all 133 tests. All CI gates pass on that exact head, including general/serialized tests, Runner, build and browser gates. Greptile is 5/5 with no unresolved threads. A clean full local `pnpm test:run` is running; the local source stays frozen for that run. - Module boundaries, maps and diff whitespace checks pass. Live staging acceptance follows the qualified full Cloud deployment. - The earlier full local run for #16690 failed while files changed and its PATH hid `lsof`. All five affected suites then passed in a clean run: 246 passed, three skipped. Those results do not establish a full local pass for this follow-up. ## Risks - Retry ancestry is a rare recovery path. Its primary-key reads grow with the chain and stop at 64 predecessors. Ordinary runs perform no new ancestry reads. - Unknown effects and active recovery obligations stay held. This does not reset budgets, change provider lifecycle policy, grant access or replay completed actions. - No schema migration or new API is included. ## Model Used OpenAI Codex, GPT-6 family, with reasoning, tool use and code execution. The session does not expose an exact backend model ID or context-window size. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass (focused checks; full-run scope is recorded above) - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
1678aae862 |
fix: expire unused bases with generated repository ignore metadata (#16695)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - Finished tasks can release Git caches that Paperclip can restore
later.
> - Nested repository preparation adds an ignore entry to the base
repository.
> - Base cleanup currently treats this generated entry as custom
metadata.
> - This pull request accepts the exact generated entry and keeps other
metadata protected.
> - Unused private bases can then expire with their workspaces and
return on demand.
## Linked Issues or Issue Description
Refs #16691. Related #15404 and #14443 change repository preparation or
sync, not base expiration.
**What happened?**
A finished workspace with a nested project repository expires, but its
unused private base remains with `custom_git_metadata`. Normal
preparation added `/.paperclip-repositories/` to the stock Git exclude
file.
**Expected behavior**
Cleanup removes a verified, unused base with this generated entry.
Custom metadata still prevents base deletion.
**Steps to reproduce**
Create an isolated workspace with a nested repository through normal
preparation. Finish the task, wait for the retention period, and run
expiration. The workspace disappears but its private base remains.
**Paperclip version or commit**
|
||
|
|
2befcd9a0a |
Harden Board CLI approval and native verification fixtures (#16482)
Preserve governed Board CLI authority and strict verification fixtures on the Muse stack.
Keep approval/cancel ownership, current membership/key authority and durable first-change audit atomic. Bound Retry-After scheduling within the original challenge; never automatically resubmit consent. Retain descriptor ownership until identity-based cleanup and close it on success and error. Keep strict Git-origin and synchronized provider-entry fixture assertions.
Related public work: LukeAbell's existing PR #13919 proposes the same production descriptor-lifetime fix. This independently measured local integration retains the original tests and adds real-descriptor coverage. Do not treat this local integration as ownership of that contribution.
Carry actual merged UI source
|
||
|
|
63306f6660 |
fix(acpx): record whether a stalled tool call's permission request arrived (#16688)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Hosted `claude_local` runs use the ACPX engine. Claude can start
background subagents, and those subagents call the runtime MCP tools
that Paperclip attaches.
> - #16671 added a stalled-tool watchdog. It ends a Claude turn when a
pending tool call gets no ACP update for 30 minutes. That PR said the
most likely cause of the stall is a lost ACP permission round trip, but
it could not prove it.
> - A staging run tripped the watchdog. Two background subagents started
12 MCP calls. ACP reported each call as `pending`, and no call got
another update. The MCP gateway logs show the 9 earlier calls from the
parent agent, but no request from the 12 subagent calls.
`MCP_TOOL_TIMEOUT` (15 minutes) did not end them. So the calls stalled
before Claude sent them to the MCP server.
> - The run record cannot say if the permission request for a stalled
call reached Paperclip. Without that fact, the next stall gives no new
evidence about the cause.
> - This pull request records, for a stalled run, whether the stalled
call's permission request reached Paperclip, and how many pending calls
had a permission request.
> - The benefit is that the next stall tells us which side of the
permission round trip stopped, so the real fix can go to the correct
layer.
## Linked Issues or Issue Description
- Refs #16671 (the stalled-tool watchdog; this PR tests the cause that
PR suspected)
- Refs #16360 (the MCP client deadline that cannot reach a call that was
never sent)
**What happened?**
A hosted staging `claude_local` run started two background subagents.
Each subagent started six `execute-sentry-tool` MCP calls. ACP reported
all 12 calls as `pending`. None got a result, an update, or an error.
The MCP gateway received no request for them. The parent turn finished
its answer but stayed open for the subagents. After 31 minutes the
watchdog ended the turn with `acpx_tool_stalled`. A single background
subagent with six parallel calls to the same tool did not stall in a
later test.
**Expected behavior**
When a tool call stalls, the run record shows if the call's permission
request reached Paperclip. Then the stall can be put on the agent side
or on the relay side of the round trip.
**Steps to reproduce**
1. Start an ACP `claude_local` run in a sandbox that uses two background
subagents to call runtime MCP tools.
2. Wait until a subagent's tool calls stay `pending` with no further ACP
update (in staging this happened without a known trigger).
3. See that the watchdog fails the run with `acpx_tool_stalled`, but the
record has no evidence about the permission round trip.
**Paperclip version or commit**
`master` at
|
||
|
|
7c7d2d8d2c |
fix(runtime): continue from saved sources after workspace loss (#16690)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The runtime must preserve saved work and prevent duplicate execution. > - Older cleanup could destroy a sandbox before its workspace export finished. > - The existing recovery controls require either the original sandbox or recovered original files. > - Surviving attachments can support a rebuild, but they do not prove that missing edits were recovered. > - This pull request adds an explicit reconstruction decision and one fresh continuation through the normal execution gates. > - Operators can continue useful work while the original failed run remains truthful. ## Linked Issues or Issue Description **What happened?** A historical failed export can have an accepted result, a prepared workspace descriptor, and a confirmed destroyed sandbox. Its notice can also say `new_source_execution_path` and disappear. The task then has neither a truthful original-file repair path nor a supported reconstruction path. **Expected behavior** Keep the missing-file obligation visible. Let an authorized operator choose surviving task attachments and record lost work and external action outcomes. Start one fresh continuation after current execution checks. Keep the old result and failed export intact. **Steps to reproduce** 1. Seed a failed native export with a prepared descriptor and an exact destroyed-lease receipt. 2. Resolve its notice with the historical `new_source_execution_path` bookkeeping value. 3. Read the task. The baseline hides the hold even though no source reconciliation exists. 4. With this change, choose **Continue from saved sources** and submit a reconstruction decision. Related public work: #16451 preserves healthy warm sessions. #16583 prevents destructive cleanup of unexported work. This change handles historical source loss that those fixes cannot undo. Searches of open and closed work found no equivalent reconstruction endpoint. ## What Changed - Add a board-only reconstruction endpoint with `runtime:manage` and task visibility checks. - Validate the exact run, result, descriptor and destroyed lease. Reject active copyback, competing owners, newer work, stale task status, and foreign attachments. - Record attachment hashes, missing work, and external action outcomes. Preserve the original failed run, accepted result, prepared descriptor and terminal failure. - Hold other continuation paths until the durable reconstruction intent admits its successor. Record that successor in the same transaction and preserve the retry count. - Add an operator control that distinguishes reconstruction from original-file recovery. Update the recovery runbook and capability maps. ## Verification - Exact baseline source returns no blocker for the destroyed-source fixture. The same fixture returns a required recovery hold with this change. - New real PostgreSQL and assembled API/heartbeat suite: 25/25 pass. It covers duplicate submissions, lost acknowledgement, context reset, source identity, task ownership, concurrent execution attachment scope, later human blocks, deleted sources and agent pause. - Existing export retry, explicit continuation and recovery-action suites: 386 cases pass. One new-fixture constraint error in the combined run was corrected; the full new suite then passed. - UI recovery suites: 46/46 pass across three files. They cover disabled actions, loss acknowledgement, failure retention and runtime authority. - `pnpm -r typecheck` and `pnpm build` pass. The first sandboxed typecheck attempt could not open the TypeScript IPC socket; the authorized rerun passed. - Module boundaries, map checks, token gates and diff whitespace checks pass. - OpenAPI route coverage: 21/21 pass. The first CI head exposed a missing endpoint registration; this head adds the registration and the focused suite passes. - Review identified a missing dispatch-time check and an isolated attachment cache. Both are fixed. Claim and final handoff recheck the exact successor, sources and current execution gates. A controlled post-claim operator block prevents the assembled heartbeat from entering the provider. The shared attachment cache refreshes uploads and removes deleted selections. - Final focused run: 180/180 pass across six suites, including reconstruction, existing dispatch/stale-queue contracts and UI recovery. - A second review reproduced cancellation by an already satisfied historical connection card while the task was `todo`. Read-only connection availability now works before checkout; active-task mutation checks remain strict. The baseline failed two cases; after the fix all 74 connection and reconstruction tests pass, including revoked access, pending questions and pending approvals. - All current-head CI gates pass on `9d197236da11fa24f1ceadf5589cb2b81179d824`, including general/serialized tests, Runner, build and browser gates. Greptile is 5/5 for that exact head with no unresolved threads. The full local `pnpm test:run` is still running its serial server group; no full local pass is claimed. Live staging recovery is pending deployment. ## Risks - Reconstruction cannot restore missing bytes. The operator must identify surviving sources and actions that must not be repeated. The agent must verify those attachments before rebuilding. - This path is limited to exact, confirmed destroyed remote sources with an accepted result. Retained or uncertain sources keep their existing repair path. - No schema migration, credential change, budget increase or warm-session policy change is included. Normal pause, ownership, budget, approval and dispatch gates still apply. ## Model Used OpenAI Codex, GPT-6 family, with reasoning, tool use and code execution. The session does not expose an exact backend model ID or context-window size. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass (focused suites; full local run limitation recorded above) - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
790b729086 |
fix: restore nested project repositories and settings after expiration (#16691)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agents use isolated Git workspaces with managed project repository copies. > - Finished workspaces can expire when Git can reproduce their contents. > - The saved recipe records the main commit but omits nested commits and local settings. > - Reopening can therefore use newer nested code and lose merged user settings. > - This pull request saves and restores those contents before workspace provisioning. > - It also permits verified FETCH_HEAD metadata so ordinary fetches do not block safe expiration. ## Linked Issues or Issue Description Refs #16457, #16586, #16621. Related performance work: #16579. **What happened?** After a finished workspace expires, its nested project checkout can reopen at the current upstream commit instead of its previous commit. Cleanup also treats local Claude settings as disposable, although that file can contain user settings. Ordinary linked-worktree FETCH_HEAD metadata prevents otherwise safe cleanup. **Expected behavior** Restore the main and nested repositories at their saved commits. Preserve local settings bytes and permissions. Skip files and Git state that cannot be reproduced. Permit standard fetched metadata only when its commits remain recoverable. **Steps to reproduce** 1. Prepare a managed nested project repository at commit A and add ignored local settings. 2. Advance upstream to B, finish the task tree, and expire its workspace and base. 3. Reopen the workspace through the normal service path. Before this fix, nested preparation selects B. ## What Changed - Extend the existing restoration recipe with exact nested commits, branches, source identity, and encrypted local settings. Keep the schema compatible with older recipes. - Restore nested repositories and settings before provisioning. Recheck company/project source access and preserve conflicting files on retry. - Recheck recorded contents under cleanup locks before deletion. Persist lock ownership before atomic publication so process exits recover safely and foreign locks stay intact. Preserve changed or unsupported contents, including tracked settings. - Keep saved project repository selections through normal preparation. Checkpoint restored contents before provisioning so failed setup can retry without overwriting later edits. - Accept bounded linked-worktree FETCH_HEAD records only after local ancestry or fresh upstream proof. Preserve local-only fetched commits. - Add real Git/Postgres lifecycle cases and focused content, access, publication-retry, and fetched-state controls. Document the behavior. ## Verification - `pnpm -r typecheck` passed. - `pnpm build` passed. - The original real Git/Postgres experiment failed with nested B instead of A. The same path passes with this change. - The integrated lifecycle suite passed 42 cases in 91.66s. Related preparation, credential, content, and Git metadata controls passed 46 cases in 24.41s. The final heartbeat checkpoint persistence case passed separately in 8.17s. - Coverage includes exact main/nested commits, encrypted settings and modes, upstream failure and retry, provisioning order, concurrent reopening, changed unique files, tracked settings, malformed metadata, and company boundaries. - Exact-head CI passed the implementation, typecheck, build, security, and test matrices. One browser shard passed on a single rerun after an unrelated fixture teardown raced an activity-log write; its feature assertions passed in the initial attempt. - The broad local test run was stopped after about 12 minutes of unrelated serial tests. Full parallel CI is required before merge; no local full-suite pass is claimed. - Single-workspace deployment, real-backlog reclamation, and ordinary product reopening remain required acceptance work after merge. ## Risks - Expired Git repositories still depend on upstream access. A failed restoration returns the existing retryable error and never substitutes the default branch. - Saved settings use the existing local encryption provider. Recovery requires that encryption key to remain available. - Unsupported files, tracked settings, unknown sources, and unverified Git state remain on disk. This can reduce reclaimed space. - No database migration, recovery-retention change, public API, or fleet-default change is included. ## Model Used OpenAI Codex, GPT-6 family, with tool use, code execution, and an independent agent review. The runtime does not expose a more specific model identifier. ## 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> |
||
|
|
e6dcc6b095 |
Connect personal Muse through secure native execution and Vault OAuth (#16448)
Add company-scoped Muse native control, OAuth, wake receiver and recovery. Recheck current authority after waits and before effects or receipt replay. Preserve task-read scope, assignment expiry, independent holds, nonblocking reassignment and truthful cleanup provenance. Retain source trust on progress comments and verify current Muse V8 authority through real signed-JWT HTTP requests. Preserve the upstream trimmed ordinary authentication lookup. Refs #16448. Preserve captured canonical queue recovery and concurrent environment preparation while retaining the scoped Muse V8 exclusion. Normal migration 0354 and existing Muse SQL remain unchanged. Fresh current-head Greptile review is 5/5 with the project-write finding addressed. Required CI and independent technical review gate the merge; maintainer override is reserved for formal approval rules. Recheck current Muse project-write authority after all receipt/task/run/admission waits, before creation or replay. Real PostgreSQL regressions reproduce four late effects/replays on the old route; the repaired three-file treatment passes 354 cases with no skips, and the scoped server typecheck passes. Ordinary/Dot behavior is preserved. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
63fbb714e6 |
fix(server): release idle tracking after aborted static UI files (#16685)
## Thinking Path > - Paperclip runs work for AI agents. > - Hosts must prove that accepted work has finished before idle sleep. > - HTTP request tracking keeps unfinished writes active after a client leaves. > - Static file middleware has no returned completion promise. > - An aborted UI download can leave its request active forever. > - This PR completes only a matched file response and keeps other work tracked. ## Linked Issues or Issue Description Refs #15522. Found while qualifying #16679. A search found no duplicate static-download idle fix. **What happened?** Closing a client during a static UI download leaves one tracked request active. The response has closed, but the file middleware never calls the wrapped response end method. The instance cannot report idle after that request. **Expected behavior** A closed, matched static file response must not leave a permanent work hold. Unfinished application writes must remain tracked. A missing file must keep the normal fallback and error paths. **Steps to reproduce** 1. Serve a large local file through the static UI middleware with idle admission enabled. 2. Start the download over HTTP. 3. Disconnect the client after its first data chunk. 4. Observe that the tracked request remains active with the original middleware. **Paperclip version or commit** Reproduced on the behavior in `d30648dee89720358271c276b9fc28cf83f18be7`. This branch starts at `cfa9dce295970a85b3d8ee14cab0eccf50bc72e2`. ## What Changed - Mark the completion of a known read-only response without dropping pending middleware promises. - Wrap static UI file serving. A successful file match is required before a closed response can complete its tracking. A late match rechecks an already closed response. Missing files keep the normal fallback. - Use the wrapper for hashed assets, other static UI files, and public development files. Preserve caller headers and cache options. - Test both HTTP abort timings, nested routers, conservative mounted-application holds, parent writes, mutating GET fallbacks, and callback-only work. - Update the idle contract and its verification map. Correct the paused-message recipe from hosted qualification: an explicit Pause cancels older queued work, so test new accepted input after the pause and await the normal resume lifecycle. ## Verification - The original two real stream-abort regressions fail with the original Express static behavior. - Three review regressions fail on `e260f4694afab8447b0cb203f439cb3ccad254e8`: a client closing before file lookup, an unfinished parent in a mounted application, and an unfinished parent in a root without installed handler tracking. Fixed sources were restored byte for byte after the comparison. - Two focused suites: 16 passed. They cover nested routers, both abort timings, hidden parent writes, late missing-file fallbacks, contents, HEAD, conditional responses, and caller headers. - Module and map checks pass. Map checks are structural only. - `pnpm -r typecheck` and `pnpm build`: passed on `f242ee739344484995d3addf81635512370778c8`. - Full CI matrix: 54 successful checks and 2 intentional Storybook skips. - Apex: 5/5 on the exact current head, with zero unresolved threads. - Full local maintained test groups are still running before final handoff. - The initial local broad run was stopped before changing source for the P1 review findings. Two file-mode fixture failures in that run came from the scratch runner's inherited `0077` mask; the same suite passes with the normal child test mask `0022`, without source or host configuration changes. The replacement run uses `0022` for test children and command-scoped `init.defaultBranch=master` for existing Git fixture assumptions. - This PR has not been deployed to a hosted environment. ## Risks Only a matched file served by the admitted application with installed handler tracking can complete this way. Routers share that scope. Mounted Express applications and roots without handler tracking keep the existing conservative response hold; this change does not claim their hidden writes are tracked. An unfinished tracked parent promise still blocks sleep after a file client disconnects. Redirects, missing files, application callbacks, and other GET requests retain their guards. No authentication, company scope, provider cleanup, or scheduling gate is removed. No schema or API response changes. ## Model Used OpenAI GPT-6 through Codex, with reasoning, source editing, and shell tools. The session does not expose a more specific serving model ID or its 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> |
||
|
|
1f27427ffd |
perf(server): batch retained workspace reader identities and policies (#16683)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Task startup checks who can read each physical workspace. > - A shared root retains the identities of earlier runs. > - The service reloads the same agents, tasks, projects and run policies for each reader. > - Database round trips grow with the retained run history and hold the company provenance lock. > - This pull request batches these reads within each guarded operation. Each run keeps its own identity and policy. > - The benefit is less task preparation time while current access checks remain in place. ## Linked Issues or Issue Description Refs #16424. **What existing behavior does this improve?** Workspace admission, repository publication and batched read authorization. **Current behavior** A synthetic shared workspace with 64 retained readers makes 680 SQL calls during a publication check. The same principals are loaded repeatedly. **Proposed behavior** Load retained identities and saved policies in batches of at most 500 IDs. Load project settings once per guarded operation. Reload records and permission grants on the next operation. **Reason and benefit** The local service benchmark with an injected 4 ms loopback round trip changed from about 7.0 seconds to 0.5 seconds and from 680 SQL calls to 47. This measures synthetic PostgreSQL data, not hosted response latency. ## What Changed - Extract retained-reader identity loading and acquisition trust checks into a focused service module. Select only the identity and trust fields used by these checks. - Batch company-scoped run, agent and task lookups. Keep each run's task binding, responsible user and policy checks. - Batch saved run-policy reads in read authorization. Keep company and agent identity checks and ordinary lookup behavior for noncanonical IDs. - Reuse project settings within one root authorization operation. - Add query budgets, identity failures, batch-boundary coverage, policy comparisons and grant-revocation tests. - Document snapshot lifetime and query scope. ## Verification - PASS: 197 focused workspace and authorization tests. - PASS: `pnpm -r typecheck`. - PASS: `pnpm build`. - PASS: all current-head hosted CI test groups, Runner checks, E2E shards, security checks and builds (55 successful checks; two unrelated Storybook jobs skipped). The local monolithic `pnpm test:run` was stopped after all equivalent hosted CI groups passed. It has no complete local result; the hosted matrix supplies the full-suite proof. - Synthetic real-PostgreSQL benchmark: 383 workspaces and 64 retained readers; 4 ms simulated loopback round trip. Publication check: 680 -> 47 SQL calls; 7.0-7.1 s -> 0.48-0.51 s. Three concurrent checks: 20.0-23.1 s -> 1.52-2.12 s. Setup and provider execution are excluded. Live reply timing remains unverified. - Regression coverage compares complete batched and ordinary authorization decisions. It checks distinct saved policies for the same principals, missing identities, company mismatch, task mismatch, responsible-user mismatch, revoked project grants and changes after the first operation. - No new schema, API or UI contract. ## Risks - A batch must not combine different runs' identities or policies. Each lookup and policy decision retains its run, company and agent checks. - Snapshots last for one guarded operation. Later admissions and publications reload data. No authorization cache survives the operation. - Restricted project trust checks keep their existing per-run validation path. Hosted latency remains an acceptance gate. ## Model Used OpenAI `gpt-6.1-sol` through Codex, with xhigh reasoning, code execution and tool use. The runtime does not expose the configured 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> |
||
|
|
e30550ef39 |
refactor: remove code comments added by recent PRs (#16681)
CONTRIBUTING.md says PRs add no code comments, but #16485, #16586, #16621 and #16672 added some. This removes the 215 comment-only lines git blame on master attributes to those merge commits, across 12 code files, plus one blank line the removal left doubled. Rewritten (not added) comments in scripts/assert-cloud-image-sentry.mjs and comments in .github workflows are left alone. No code changes. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
bebeb389f1 |
perf(server): do not watch bundled plugins for file changes (#16677)
Bundled sandbox-provider plugins are installed from local paths inside the image, so production started a chokidar dev watcher for each of them over files that never change. createPluginDevWatcher now takes unwatchedRoots (compared in resolved and real-path form), and the app passes the bundled plugin catalog root; plugins installed elsewhere are watched as before, and a plugin moving into an unwatched root closes its old watcher and cancels any pending restart. Co-Authored-By: Paperclip <noreply@paperclip.ing> |