mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-28 20:21:50 +01:00
5bf0142d4599fce968dcb0fdb3e7dddd7007a972
2263
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
39279aa34f |
feat(ui): shared error, connectivity and query foundation for disconnects (#15754)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The board reads API data and keeps the current task on screen. > - A restart or temporary network failure can interrupt those reads. > - Separate page error handlers can hide cached data or expose raw server codes. > - The app needs one connection state, readable error copy and a consistent read policy. > - This change provides that foundation and moves affected read surfaces onto it. > - The dependent write layer in #17960 preserves edits and submissions across the same failures. ## Linked Issues or Issue Description **What happened?** Temporary API failures could replace loaded content with errors. Different surfaces handled the same outage differently. Some showed raw server codes. A successful query to an unrelated service could also falsely report that Paperclip had recovered. **Expected behavior** Keep cached content visible. Show one connection banner during sustained trouble. Confirm recovery through the Paperclip health probe or its WebSocket. Retry transient reads and show readable errors for permanent failures. **Steps to reproduce** 1. Open a populated task or workspace page. 2. Interrupt API requests with a 503 or a dropped connection. 3. Keep an unrelated external request in flight. 4. Confirm that cached content remains and that the external result cannot clear the outage. 5. Restore the API and check that reads refresh. The write layer first merged into this feature branch in #15769 now has its own dependent PR, #17960. This PR contains the shared foundation and read changes. Merge this PR first. ## What Changed - Classify API errors and provide readable error copy, including non-JSON proxy responses and Retry-After handling. - Use one connection store and health probe with bounded backoff. Confirm recovery from the server health probe or live-updates WebSocket. - Pause reads while disconnected, retry transient errors, and refresh active reads after recovery. - Keep cached data visible through shared query views and affected page, panel and plugin read surfaces. - Add one app-level connection banner and support the pending-write count consumed by the dependent write layer. - Add a query-error rendering guard. Call it directly from the existing CI step. Update development documentation. ## Verification - Historical-chat lookup now follows the same ready/stale roster state as rendering. Three regressions fail before the fix; the six new cases pass after it, including working Retry, fresh data, no-cache error, permanent 403 and company isolation. All six focused query/recovery suites pass 200 tests. Final-commit CI passes and Apex is 5/5 with no unresolved findings. Canary Dry Run initially refused a preview version that was already on npm. It passed after one rerun with fresh registry metadata; no check was disabled. - Integrated current master and retained both transcript interest registration and connectivity reporting on socket open. The seven focused recovery/query suites pass 288 tests, and UI typecheck and production build pass. All 9,451 UI tests across 799 files pass on the merge commit. Final-commit CI passes and Apex is 5/5 with no unresolved findings. - Current head `70d9335d732219352ef0f98414439766bbcb33df`: all hosted CI checks pass. Apex is **5/5** on that head with no unresolved findings. The branch has no merge conflict. GitHub still requires code-owner approval. - The foundation passes 9,430 UI tests in 804 files. After integrating current master page paths, 190 focused page tests pass. - Two unrelated-success regressions fail before the latest fix. With the fix, 62 focused UI tests, all six guard tests and UI TypeScript pass. - The composed foundation and write layer pass **9,505 UI tests in 808 files**, UI TypeScript, a production UI build, and query-error, token and map guards. - A real Chromium journey on the composed source injects a 503 during title save. The loaded task stays visible; one reconnect banner appears; the edit saves after recovery; another task stays unchanged; the saved title survives reload. - Full recursive local checks were not repeated because Runner compilation exhausted local disk during another repair. Hosted checks must pass before merge. No new staging deployment is claimed. - Latest review follow-up: a cached CaseDetail now survives a failed HTTP 429 refresh. Its page regression fails before the fix and passes after it. Eighty focused foundation tests, UI TypeScript, build and guards pass after that change. - Earlier CI evidence is retained: several foundation jobs received a runner shutdown signal together. The write-layer head also failed an unchanged Runner descriptor close test with `provider_transport_failed`. The same Runner source passed that suite in the foundation run. New CI runs cover the updated heads; no check or assertion was weakened. ## Risks - Shared retry defaults change the time before transient read errors appear. Permanent errors still fail promptly. - ApiError.message now contains readable copy. Callers that compare raw codes must use ApiError.code. - Cache success can come from another service or local data. It must not confirm Paperclip recovery. - Durable writes are reviewed separately in #17960. This PR does not change database or mutation contracts. ## Model Used Anthropic Claude Opus 5.5 (`claude-opus-5-5`) produced the original work with tool use. OpenAI Codex, GPT-6 family, assisted with restoration, integration, tests and review fixes. The Codex session does not expose its exact serving model ID or context window size. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Paperclip <noreply@paperclip.ing> Co-authored-by: Amy (Opus) <claude@users.noreply.github.com> |
||
|
|
70c8646337 |
fix(ui): drop top margin and border on first contextual sidebar section (#17412)
The first section in the contextual sidebar rendered a leading top margin and divider with nothing above it. Use first: variants so only sections that follow another section get the spacing and border. <!-- Write all pull request text in Simplified Technical English (ASD-STE100): short sentences, one instruction per sentence, simple approved vocabulary, and the active voice. --> ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The board UI has contextual sidebars, such as Skills, Apps, and Agent > - These sidebars share one set of style constants in `contextual-sidebar-styles.ts` > - Each section in the sidebar has a top margin and a top border to separate it from the section above > - The first section has no section above it, but it still shows the margin and the border > - This pull request adds `first:` variants to the section style > - The first section now sits flush at the top, and the other sections keep their divider ## Linked Issues or Issue Description **What existing behavior does this improve?** The section style in the contextual sidebar. It adds a top margin and a top border to every section. **Subsystem affected** UI (`ui/src/components/contextual-sidebar-styles.ts`) **Current behavior** The first section in the sidebar shows a top margin and a divider line. Nothing is above it, so the divider looks wrong and wastes space. **Proposed behavior** The first section has no top margin and no top border. Each later section keeps its margin and divider. **Reason and benefit** The sidebar looks cleaner at the top. The change is small and uses only existing design tokens. **Breaking changes** None. ## What Changed - Added `first:mt-0 first:border-t-0` to `contextualSidebarStyles.section` in `ui/src/components/contextual-sidebar-styles.ts`. Before: <img width="585" height="410" alt="Screenshot 2026-10-24 at 10 14 36 AM" src="https://github.com/user-attachments/assets/12c35f5f-7993-4fdb-89b2-df3394859bf8" /> After: <img width="560" height="377" alt="Screenshot 2026-10-24 at 10 14 24 AM" src="https://github.com/user-attachments/assets/92e1f7ab-f4c0-48ac-832a-a3726770deac" /> ## Verification - Run `pnpm check:token-gates`. It passes. - Open a page that uses a contextual sidebar, such as Skills or Apps. - Check that the first section has no top gap and no divider. - Check that the later sections still show their divider. ## Risks - Low risk. The change affects only the spacing and the top border of the first sectio - Several sidebars share this style, so check each one: Apps, Skills, Agent, and Chat detail. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - Provider: Anthropic - Model: Claude Opus 5.5 (`claude-opus-5-5`) made the commit. Claude Sonnet 5.5 (`claude-sonnet-5-5`) helped review the change afterward. - Capabilities: tool use and code execution in Claude Code (CLI). - The one-line style change is human-authored. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only puub.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
c9213d1be4 |
fix: send saved queued messages after Stop (#17959)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - People can save follow-up messages while an agent runs. > - Stop preserves those messages and stops the active execution. > - The queue removed its delivery controls when that execution ended. > - Native admission also refused an explicit resend of older queued input. > - This change adds Send for a stopped queue and records fresh board intent. > - The saved message can continue through normal cleanup and admission checks. ## Linked Issues or Issue Description **What happened?** A person queued a message with a screenshot while an agent was starting. Steering was not yet available. They stopped the run. The message remained visible, but no control could send it. Native queue delivery also rejected this transition. **Expected behavior** A stopped queue offers Send. The click preserves message IDs, content, attachments and original authors. It starts at most one eligible continuation. Stop remains effective until the person gives new direction. **Steps to reproduce** 1. Start a native task and queue a second message. 2. Stop the active run before it consumes that message. 3. Open the task after cleanup. Observe the saved message with no send control. Refs #16965 for the queue-control change and #15015 for stopped conversation recovery. No open repair for this exact transition was found. ## What Changed - Show Send for a saved deferred queue with no active run. - Accept the existing board queue action for a stopped native target. Keep live native interruption restricted. - Use the server-recorded click time to authorize older native messages. Reject stale, malformed and wrong-actor intents. - Reuse normal queue dispatch, revision checks, cleanup proofs and execution admission, including a failed native predecessor after a verified Send. - Ignore a fully committed, successful recovered export when admitting a fresh message, while retaining the wait for results still committing. - Honor an applied `/new` conversation boundary while retaining native execution holds until the existing stop and cleanup checks verify them. Workspace holds also survive reset. Check the newest failed or cancelled native execution even when older recovery actions exist. - Keep native automatic delivery separate from the explicit Send action. Update execution and access documentation. ## Verification - Meaningful regressions failed before the fixes: stopped queues lacked Send, native admission refused fresh intent, cleanup and dispatch receipts were missing, deferred rows disappeared, live plan Interrupt rejected its own receipt, and Agent Chat `/new` inherited an old non-workspace execution hold. - Six assembled-wakeup cases fail before the reset cleanup fix. All 11 reset/history cases pass after it: live processes, missing identity, quarantined cleanup, remote leases and live controllers remain held; verified cleanup proceeds and retires the hold. Two more cases fail before the fallback fix and pass after it: Send verifies a stopped or live native predecessor despite a later reset receipt and no recovery record. - **525 server tests pass** across seven queue admission, route, dispatch, envelope, provenance, blocker and conversation files. **343 queue/thread UI tests** also pass. Server/UI TypeScript, token and map guards pass. The final scoped server typecheck also builds native Runner successfully. - The latest regressions prove that completed recovered exports permit fresh input, and clearing conversation history still requires old native stop and cleanup verification; an unsafe workspace still blocks after `/new`; failed native Send reaches actual continuation dispatch with the original queued comment. A result still being committed remains deferred. History plus a newer Stop cannot hide a missing process/controller/lease receipt. - The real Chromium Stop/Send journey passes on current head `75fa5e7222c59f43ff7ac326e81093bc9da28330`: queue a follow-up, Stop, reload, explicitly Send, then verify exactly one useful response and no live run. Earlier browser journeys cover legacy Interrupt, interruption during a write and Stop followed by a new direction. These use an isolated app/database and controlled ACP fixture, not an external AI account or a staging deployment. - Negative cases retain actor, company, issue, assignee, queue and cancellation-receipt bindings; cleanup/process/workspace/controller holds; approvals; pause and budget gates. Typed responses keep their original resolver and immutable result. - Full local recursive typecheck stopped in unchanged Rust Runner compilation with ENOSPC, so the chained full tests/build did not run. All hosted CI gates pass on final commit `75fa5e7222c59f43ff7ac326e81093bc9da28330`, including typecheck, tests, build and E2E. Apex review on that commit is 5/5, with no unresolved findings. Earlier unrelated CI failures involved PostgreSQL fixture-cleanup deadlock and an unchanged decision-expiry deadline assertion; the latter's 20 cases pass locally without source changes. No assertions or limits were weakened. Local resource cleanup was limited to this task's verified completed test processes and rebuildable npm caches. ## Risks - Send can authorize a new turn for a saved message after Stop. A Send click must be newer than the stopped execution; a live plan Interrupt is bound to the cancellation receipt produced by that same click. It does not imply that cleanup finished or that an external action is safe to replay. - The existing endpoint and intent format are reused. No schema or credential change is required. Live native steering and legacy interruption keep their existing paths. ## Model Used OpenAI Codex, GPT-6 family, with reasoning, repository inspection, tool use and code execution. The session does not expose the exact serving model ID or context window size. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
6cc765bd81 |
feat(live): deliver recoverable transcripts to interested views (#17456)
## Thinking Path > - Paperclip should show live agent output without repeating presentation work for every view. > - Execution, acknowledgements and durable checkpoints must remain independent of browser interest. > - The server already owns authorization and redaction at delivery. > - A shared browser connection can declare which visible runs need full transcripts. > - Catch-up must handle subscription races, disconnects, terminal output and slow consumers. > - This PR delivers the backend and UI contract together without a database migration. ## Linked Issues or Issue Description **What existing behavior does this improve?** Visible transcript consumers receive recoverable output through one shared browser connection. **Current behavior** Independent views can create duplicate connections, presentation work and recurring history reads. A subscription race or filtered native history can lose the saved tail. **Proposed behavior** Negotiate run interests, subscribe before catch-up and retain independent canonical recovery cursors. Keep lightweight lifecycle and attention events available without full transcript delivery. PR 4 of #17097 → #17439 → #17455 → #17456. The runtime feature is independent of hot-upgrade recovery; the stack order is for review convenience. ## What Changed - Add additive WebSocket capability negotiation, replacement interests, revision acknowledgement and resynchronization notices. - Reference-count visible consumer interests on one company-scoped browser connection. Preserve older-client/server behavior. - Reuse canonical structural/current-user/registered-secret redaction for plugin run notifications through the same bounded delivery queue. Keep producer and uninterested streams free of recipient lookups. - Refresh application queries after the matching recovery acknowledgement, including one follow-up after an older in-flight read. Ordinary interest acknowledgements add no refresh. - Keep authorization and redaction at delivery. Browser interest cannot change harness execution, PRP ACKs, checkpoints, accounting or canonical logs. - Deduplicate by sequence and log identity. Catch up terminal output and saved tails without recurring reads during healthy negotiated streaming. - Bound delivery to 1,000 items and 1 MiB. Overflow requires resynchronization; persistent congestion closes the connection. - Preserve compact-history expansion from current master across paginated catch-up. Snapshot the original read window before React can defer its update. ## Verification On current source `f6710f0b3c`, Linux [job 122604880503](https://github.com/paperclipai/paperclip/actions/runs/40624101891/job/122604880503) executes all five run-read permission cases successfully (2.574 seconds), including grant and revocation on the same connection. Its shard passes all 2,430 cases. Current [server-shard job 122604880416](https://github.com/paperclipai/paperclip/actions/runs/40624101891/job/122604880416) has 1,513 passes, one failure and three skips: an unchanged nested-clone expiration/restore test exceeds its 15-second deadline. The preceding `5efc6c48bf` source has identical non-document bytes; [its corresponding job 122601359272](https://github.com/paperclipai/paperclip/actions/runs/40623017917/job/122601359272) passes all 21 nested-clone cases, including that case in 9.505 seconds. The exact timing cause is unproven. The single diagnostic [retry job 122609332597](https://github.com/paperclipai/paperclip/actions/runs/40624101891/job/122609332597) passes all 21 nested-clone cases (61.316 seconds), including the formerly timed-out case in 7.003 seconds, and all 1,514 shard cases (three skips). The failure remains recorded; no timeout or assertion was changed. After the server squash merge and qualification retarget, all 50 focused server cases and all 91 focused UI cases pass again, with both typechecks and token gates. Runner vendor preparation rebuilds current master inputs before those tests. This source needs fresh CI and reviews; prior CI and browser receipts do not qualify it by inference. Current candidate `f6710f0b3c` now targets master `6987c2f20b`, after merged #17097, #17439 and #17455. Its diff contains only transcript delivery and its documentation. It adds no database migration. Retargeting changes only the evidence document; all production and test code is byte-identical to `5efc6c48bf`. On the eighth integration, all 50 focused server delivery cases and all 91 focused UI cases pass, with both typechecks and token gates. The following 35-case receipt belongs to the earlier delivery correction. Four low-queue authorization/decoration stall variants and the late-rejection case fail before correction. They now verify the five-second read deadline, old and negotiated clients, revisions that cannot reset the deadline, unaffected sibling connections, rejected late results, and timer cleanup. The first combined toast run has four loopback EPERM failures and 31 passes; its permitted repeat passes all 35. Earlier 28-case evidence excluded the toast file. The permission correction requires the current HTTP company-scope transcript permission, plus task access, for both native events and legacy logs. Prior Linux source `49a8783e9b`, job 122549913643, executes all five run-read cases, including grant/revocation on the same connection, successfully. That source placed this file in server shard 11; later shard assignments can differ and must be checked against their actual inventories. The older `405bedd189` receipt retains a separate scheduled-retry teardown race and inherited fixture collision; neither is waived. The new head must pass again in Linux CI. The seven extracted stream-recovery tests preserve their assertions. All 39 related legacy/native cases, UI typecheck and token gates pass after restoring the initially missed fixture helper. Earlier full workspace build/typecheck and Chrome journeys at `445a76563c` cover two views, company switches, reconnect, terminal catch-up, reload and zero recurring healthy transcript reads. Those browser receipts are historical source evidence and do not qualify this new head by inference. The [qualification record](https://github.com/paperclipai/paperclip/blob/f6710f0b3c84c6fdb2021df67206261b446dfc97/doc/plans/2026-10-22-hot-upgrade-qualification.md) retains exact earlier UI/history, source-boundary and cleanup failures with their fixes and limits. The workload-cost test preserves bounds and authorization callback counts for zero interests, one viewer, multiple browsers and a slow viewer. Its socket congestion is simulated. It measures neither SQL nor network costs. Current permission checks and the final hosted active-agent/viewer matrix remain unmeasured; no production savings are claimed. Fresh exact-head CI, legacy status, completed Greptile 5/5, resolved feedback and ordinary merge eligibility remain required. The earlier recipient corrections pass all 47 registry/plugin/delivery/WebSocket/toast cases and all 174 UI provider/recovery/interest cases, both typechecks and token gates on source `b202e59a25`. A real bus/host-service test registers a synthetic run secret through the production registry and reproduces its raw notification before the fix; native/legacy/final notifications now redact it, disposal prevents late worker notification. A later P1 review reproduces lost final notifications on settings-read and secret-resolution failure. Both cases fail before correction. Any delivery failure or subscription timeout now sends one content-free stream error and removes the plugin subscription. It never changes the agent execution or run status. Later events start no new redaction reads. The final integrated six-file server lane passes all 50 cases, with server typecheck and token gates. Existing browser delivery behavior is unchanged. Storage and secret-provider seams are scripted. Two real React Query/provider regressions first miss a run during resync; both now refresh after the valid replacement ACK, including pending-read and stale-scope cases. The prerequisite qualification batch passes all 118 cases and E2E typecheck after master integration. Fresh CI, security scan and reviews remain pending on this head. The contribution-rule review correction removes 104 explanatory comments introduced by this slice and keeps the ordering, deadline and plugin-delivery explanations in the delivery document. Existing comments and functional test/lint directives remain. All edited source files have identical parsed non-comment tokens before and after the change. All 50 server delivery cases and all 91 cases in six affected UI suites pass, along with token gates. The new head requires fresh CI, security and review. ## Risks A slow or disconnected viewer must resynchronize from authorized canonical history. It may see a display gap until catch-up completes. Company changes and revoked access must remove delivery interests. This slice adds no database migration and cannot change execution or recovery authority. Full transcript delivery evaluates current company-scope permission per delivery. Active plugin recipients also perform canonical redaction reads; viewer-load database costs on this final source remain unmeasured. ## Model Used OpenAI GPT-6 through Codex, with reasoning, repository tools and code execution. The runtime does not expose a more specific model ID or context-window size. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
f52da40f08 |
fix: resume queued turns after maintenance (#17967)
Keep an accepted turn's starting input in task history, show its admission wait, and resume existing queued runs promptly when maintenance ends or expires. Verified with behavioral red/green regressions, real PostgreSQL and process execution, browser/native Runner acceptance with a deterministic provider, workspace typecheck, production build, and current-head CI/review. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
7a8df30953 |
fix(runner): admit Grok effort through native session metadata (#17942)
## Thinking Path
> - Paperclip lets people manage AI agents for work.
> - Paperclip Runner must preserve each agent's model and thinking
effort.
> - The Grok migration in #17922 passes explicit effort to native
Runner.
> - The pinned Grok 1.0.13 CLI reports native session metadata instead
of standard ACP config options.
> - The standard effort guard rejects that valid session before the
first prompt.
> - This pull request binds model and effort on Grok session open and
verifies the native reply.
> - Restored sessions keep the selected effort instead of reverting to
Grok's default.
## Linked Issues or Issue Description
Related: https://github.com/paperclipai/paperclip/pull/17922
**What happened?**
A migrated Grok 4.7 agent with High effort fails at native session.open
before it can run a tool. Grok 1.0.13 has no standard configOptions
response and rejects session/set_config_option. Its native session
metadata supports the requested model and effort. A cold load also
resets effort to High unless the request supplies it again. The upgrade
banner also calls Grok “Codex”.
**Expected behavior**
The native session must acknowledge the selected model and effort before
a prompt. A cold restore must preserve both values. The upgrade banner
must describe the selected harness accurately.
**Steps to reproduce**
1. Upgrade a Grok agent to Paperclip Runner with explicit High effort.
2. Assign a bounded shell task. The pre-fix native session fails during
admission.
3. For the restore case, create a Low native session, close the process,
and load it without effort metadata. The pinned CLI reports High.
**Paperclip version or commit**
Observed at
|
||
|
|
3f8149066c |
Fix connection controls for inherited hiring environments (#17944)
<!-- entire-trail-link-start --> https://entire.com/gh/paperclipai/-/trails/106/changes/paperclip/106 <!-- entire-trail-link-end --> ## Thinking Path > - Paperclip lets people hire agents and select execution environments. > - The name and adapter dialog saves an inactive draft before model connection. > - That draft can inherit its environment through a null defaultEnvironmentId. > - Managed-only and forced Kubernetes policy resolve that inheritance to an environment ID. > - The readiness gate compared the stored null with that ID and treated the selection as unsaved. > - This change accepts unchanged inheritance and keeps preparation and save-failure gates. > - People can select auth, open Advanced, and test a saved account before finishing setup. ## Linked Issues or Issue Description **What happened?** The Connect a model screen disabled all auth controls for a draft from the name and adapter dialog under managed-only or forced Kubernetes policy. Reloading did not recover it. The draft had no explicit environment, which is a valid inherited selection. **Expected behavior** Keep connection controls usable once the draft and environment are ready. Test the saved agent against its resolved environment before hiring finishes. Continue to block tests during preparation or an unsaved environment change. **Steps to reproduce** 1. Enable managed-only execution with a valid instance default, or force Kubernetes. 2. Open New agent, enter a name, and choose Claude or Codex. 3. Reach Connect a model with the saved draft's defaultEnvironmentId still null. 4. Try the saved subscription, API-key tile, or Advanced gateway. This follows #17761. The roadmap and related PR search found no existing fix for this readiness regression. ## What Changed - Accept the inherited selection when neither the draft nor the user specifies an environment. - Retain the existing preparation, loading, selection-save, and connection-test gates. - Cover Claude and Codex under managed plugin, managed sandbox, and forced Kubernetes policy. - Extend preparation coverage to both explicit and inherited environments. - Add the inherited-draft journey to the feature map. ## Verification - Hosted reproduction on Core |
||
|
|
f60ac29cf1 |
fix(runner): migrate Grok Build with native reasoning effort (#17922)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Harness selection maps supported agents to Paperclip Runner. > - The native Runner already supports Grok Build, but its migration mapping excludes Grok. > - Grok agents also have a thinking-effort setting that the native execution contract does not carry. > - This pull request adds the migration path and preserves explicit Grok effort through startup and resume. > - Operators can upgrade an existing Grok agent without silently losing its model, account, or effort. ## Linked Issues or Issue Description **What happened?** Existing Grok Build agents have no Runner selector or upgrade action. Adding only the mapping would route conversion through the Codex fallback and lose Grok execution semantics. Native execution also ignores the legacy reasoning-effort field. **Expected behavior** A qualified Grok agent can explicitly upgrade. The saved model, account, instructions, history, and supported effort remain intact. Unsupported legacy settings fail before saving. The provider must acknowledge the selected effort before inference. **Steps to reproduce** 1. Open the runtime page of an existing Grok Build agent on a qualified Linux x64 or macOS ARM64 computer. 2. Observe that the Runner selector and upgrade action are absent. 3. Compare the native execution input with the saved legacy reasoning-effort setting. Related work: #13882 introduced native Grok Build. #15422 covers the earlier default-runner work. This change extends the current shared selection contract. ## What Changed - Add the Grok harness mapping, qualified platform limits, upgrade action, and company-scoped computer qualification. - Translate Grok settings to ACPX without changing the selected account or explicit model. Resolve the legacy default model to the native default. Preserve the effective legacy search policy. Reject incompatible command, argument, permission, and turn-limit settings. - Add native execution input v10 for explicit Grok effort and search policy. Preserve historical schemas. Enforce disabled search through Grok requirements and bind it across startup and recovery. - Apply and verify ACP `reasoning_effort` before prompting. Bind the value to provider descriptors, checkpoints, runtime identity, and resume checks. - Use the Grok catalog and effort choices in the task composer. Apply task model and effort overrides while retaining the agent account and search policy. Update runtime controls, portability/default handling, documentation, and capability maps. - Advance Pi and Copilot source attestations for changed shared transport and recovery code. Keep historical identities intact and update all Rust integration fixtures. ## Verification - Migration and review regressions were reproduced before the fixes. Coverage includes the Grok mapping, default model, explicit effort, implicit search policy, task overrides, and incompatible legacy settings. The broad migration, route, immutable-input, and composer check passed 478 tests. The final catalog and task-input check passed 135 tests. - Runner startup, recovery, search policy, and profile checks passed 361 tests, with one platform skip. The final source-identity, search-admission, and transport event-pump check passed 89 tests. - All 757 Rust workspace tests passed for the broad implementation. After the final source attestation update, all 55 ACPX profile/session tests passed. - `pnpm -r typecheck` and `pnpm build` passed for the implementation. Server and Runner typecheck passed after the final production change. Server `tsc --noEmit` passed after the final test-fixture change. Docker context integrity, token gates, maps, generated protocol data, and replay goldens passed. - The v10 startup fixture initially used an ambient local Grok login and failed on CI. An explicitly empty credential home reproduced all four failures. The fixture now supplies a synthetic key and a private empty home. A separate case checks that missing credentials fail closed. All seven selected Grok v10 and Claude v9 startup cases pass without host credentials. - The full local suite could not complete because embedded PostgreSQL failed before database-backed fixture setup. The broad executor-suite attempt hit the same limit and was stopped. Neither attempt is counted as passing. Current-head CI must verify those paths before merge. - Earlier CI found missing Rust input fields, stale source attestations and exact fixture pins, a missing Docker context entry, and an outdated import expectation. Those failures were fixed and checked locally. The CI logs retain the original failures. - Different earlier CI runs also failed unchanged cleanup pagination, device-login timeout, and chat lost-response recovery cases. Later attempts passed the cleanup and login cases without changes to those implementations. Their causes remain unproven. The original evidence remains in [the first run](https://github.com/paperclipai/paperclip/actions/runs/40563402840), [the login run](https://github.com/paperclipai/paperclip/actions/runs/40571128328), and [the chat run](https://github.com/paperclipai/paperclip/actions/runs/40573072163). A passing retry does not establish a root-cause fix. - Both reviews rate current head `16fba9b4cdf12bc7945e6628912e79da42959f35` 5/5. All current-head CI gates pass in [run 40576580699](https://github.com/paperclipai/paperclip/actions/runs/40576580699). All 60 check runs completed cleanly, including the four intentional skips and the neutral 5/5 Paperclip review. The legacy security status is successful. No review threads remain unresolved. - Staging migration and a real shell task are pending deployment. This PR does not claim full Grok provider qualification. Reviewers can verify the operator path by upgrading a qualified Grok agent, checking its saved model and effort, and running a shell task through native execution. ## Risks - Explicit effort and search policy require the matching Runner and sidecar build. Older immutable execution inputs keep their existing schemas. - Providers that omit or reject the selected effort fail before a prompt. Unsupported effort does not fall back silently. - Existing agents retain their saved runner until an explicit change. New Grok agents use native execution only on qualified platforms. - Grok token and cost reporting remain unverified, as before. ## Model Used OpenAI Codex, GPT-6 family. The exact serving model ID and context-window capacity are not exposed in this session. Used reasoning, source editing, shell execution, and browser inspection. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes: #` / `Refs: #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and the focused suites pass; the full local suite has the environment limitation recorded above - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
6e5b9794d6 |
perf(github): avoid duplicate webhook body reads (#17894)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - GitHub webhooks enter a durable action queue before the worker processes them. > - A worker must check retry eligibility and win an atomic claim before it replays a delivery. > - The current eligibility read returns the complete webhook body, and the successful claim returns it again. > - This pull request reads small eligibility fields first and returns the body only to the successful claimant. > - The worker keeps its retry, ownership, runtime, credential, and recovery checks. > - The benefit is less database transfer without removing durable replay data. ## Linked Issues or Issue Description Refs: #17666, #15981. Those changes own the existing recovery scheduler and ingress module. This PR changes the result projections and validation order within that module. It has no dependency on another open PR. A public issue and PR search found no duplicate change. **What existing behavior does this improve?** The durable GitHub webhook worker reads action eligibility and replays claimed deliveries. **Current behavior** The first read returns all action columns and the complete webhook body. A successful claim returns them again. An active claim or future retry also downloads a body that this worker cannot process. **Proposed behavior** Read only ID, status, result, and update time for eligibility. Return ID, endpoint ID, and payload from the successful atomic claim. Validate that claimed payload before replay. **Reason and benefit** A synthetic 131,105-byte webhook body produces about 263 KB of response values before this change. The changed service returns about 132 KB for successful processing and fewer than 150 bytes for skipped work. This removes duplicate body transfer. **Breaking changes** There is no public API or schema change. Malformed active or delayed rows now remain under their current claim or retry deadline. The eligible claimant validates and fails them later. A worker that does not own the claim can no longer clear their payload. ## What Changed - Use a small projection for initial action eligibility. - Return the replay body only from a successful claim. Keep the existing status, stale-time, and previous-attempt guards. - Validate the row returned by the claim. Fence invalid-payload settlement by kind, processing status, and the claimed attempt. - Add 19 real PostgreSQL regressions for complete replay bodies, skipped work, retries, stale-claim recovery, contention, corrupt bodies, claim loss, replacement bodies, and payload retention. - Wait for the saved chat authentication link in one existing async UI test. Keep its exact destination and all other assertions. This repairs a second independent CI test failure without changing product UI. - Accept the two precise invalid-repository diagnostics from Git 2.55 and 2.56 in one existing test. This repairs an independent CI compatibility failure. It changes no Git expiration service behavior. - Add a reproducible benchmark that loads the real baseline service from an explicit commit. It captures generated SQL and parameters, query plans, response-value estimates, timings, and complete valid-work behavior comparisons. ## Verification - Baseline: `663fe667d66d3863d0919a8724f1d99500feef0b`. - PostgreSQL 17.11, Node 24.22.1. The fixture uses synthetic random body content. No hosted database or provider was changed. - `pnpm exec vitest run server/src/services/chat-channels/github/webhook-ingress.test.ts`: 19 passed with a dedicated disposable PostgreSQL database. - Existing assembled GitHub tests: recovery from pre-ingress failure, scheduler retry and restart, exact terminal redelivery, runtime pause/resume, recovery tombstones, and credential rotation passed. - `node scripts/check-module-boundaries.mjs` and `git diff --check`: passed. - Benchmark: `node --import ./server/node_modules/tsx/dist/loader.mjs scripts/benchmark-github-webhook-ingress.ts --baseline-ref=663fe667d66d3863d0919a8724f1d99500feef0b`. The default uses disposable embedded PostgreSQL. `PAPERCLIP_TEST_DATABASE_URL` can select a dedicated migrated test database with a name that ends in `_test`. - Ten timed samples after two warmups, with alternating baseline/treatment order. The main acceptance criterion is response size, rather than a timing threshold. The 0.51 ratio bound is deterministic for this fixed synthetic fixture; it is not a promise for arbitrary webhook bodies or result metadata sizes. Focused tests measure the body transfer reduction directly. Actual wire savings require post-rollout measurement. | Scenario | Baseline response-value bytes | Changed response-value bytes | | --- | ---: | ---: | | Received | 263,276 | 131,547 | | Due retry | 263,342 | 131,613 | | Stale processing | 263,291 | 131,563 | | Future retry | 131,692 | 136 | | Active processing | 131,642 | 86 | | Processed | 131,659 | 103 | The benchmark compares response status/body, all stable durable action fields, and the replay body, signature, delivery ID, and provider routing. All six valid scenarios match. It excludes generated row IDs and timestamps. The final measurement records treatment commit `f1ad8ce838700237b56f895cc61a9c6ed0850cd6`, an empty initial worktree status, and the SHA-256 of the actual source. It ran from the server directory to verify that Git paths resolve from the repository root. Local timing ranges overlap and vary with host load. An earlier loaded repeat had a due-retry median of 19.61 ms before and 22.58 ms after, so no consistent latency gain is claimed. The byte reduction is the verified result. Response-value estimates exclude PostgreSQL protocol/TLS overhead and JSONB whitespace. These are local measurements, not a claim about deployed latency or a monthly bill. `pnpm -r typecheck` and `pnpm build` passed on production-change commit `6f4f36bff525494dadda30b49ea6a9a33976e1ab`. Greptile completed with 5/5 and no review threads on that commit. Commit `2abf9b1e50c568b632e7568398a5826a6122e456` changes only the Git test matcher. Commit `f1ad8ce838700237b56f895cc61a9c6ed0850cd6` fixes benchmark provenance after automated review. Commit `ee2a96dad549c72da3132d2b93fd11eb1c45bc31` repairs an existing async UI test. Final commit `994d398d12be65f595b305d1c2f8a61b9d587ff9` extends real PostgreSQL contention coverage after review. Full CI completed successfully on that final head: [workflow run 40537698349](https://github.com/paperclipai/paperclip/actions/runs/40537698349). All 55 successful checks, one neutral review, and two optional skipped checks are terminal; none are pending or failing. Fresh Greptile and Paperclip reviews are both 5/5, with zero unresolved review threads. The production source SHA-256 remains `402f9c66cd030c9ded9f39a3bc72d26c56627752c0950b102adcab15c4512df3`, so the production proof is unchanged. The full local `pnpm test:run` was not completed because this host exhausted embedded PostgreSQL semaphore resources; the focused real PostgreSQL tests used a private disposable container. Current-head remote CI passed the full suite. A direct server typecheck before runner preparation reported missing runner build outputs; supported preparation and the full typecheck then passed. The first complete build found a partial local Copilot closure from the dependency cache. The complete pinned closure was restored and verified, then the complete build passed. The first local test run also found a fixture teardown order error; the teardown was corrected, then all 17 tests passed. Frozen dependency installation failed on the existing master patch metadata. Independent cached dependency directories were cloned, their workspace links were checked, and no dependency manifest or lockfile was changed. The first CI server4 shard failed one existing Git expiration test: Git 2.56 reported `gitfile does not point to a valid repository`, while the test expected the Git 2.55 phrase `not a git repository`. The service returned the correct `inspection_failed` result and preserved the workspace. Separate test-only commit `2abf9b1e50c568b632e7568398a5826a9c6ed0850cd6` accepts either precise diagnostic. The affected assembled test passed locally with real PostgreSQL 17.11 and Git 2.55; the captured CI diagnostic also matches, and unrelated permission errors do not. This was a compatibility failure, not a transient failure or an unchanged rerun. Paperclip Review found that the benchmark recorded its own scratch directory as an uncommitted change. The final benchmark-only repair captures repository status before scratch creation, runs Git commands from the repository root, records the source hash before measurement, and rejects source edits during measurement. A full benchmark run from the server directory then reported clean provenance and passed all six byte/behavior comparisons. The review thread was marked addressed after this proof. The next full CI run found a separate unchanged UI test failure in `ConnectionIntentInteractionBody.test.tsx`: the saved authentication link was still absent after one fixed flush. The same failure reproduced locally: one failed and 50 passed. Separate test-only commit `ee2a96dad549c72da3132d2b93fd11eb1c45bc31` uses the existing bounded `waitForAssertion` helper around the identical destination assertion. The whole file then passed all 51 tests, and UI token gates passed. The no-extra-setup and no-automatic-completion assertions remain. No UI runtime or timeout changed. Paperclip Review also asked for parallel claims from stale-processing and due-failed rows. The contention test now covers those states and received rows. Each case holds the claims until all 12 workers have read the same eligible attempt, then uses real PostgreSQL to assert one replay and exactly one attempt increment. The whole focused suite passed all 19 tests. This coverage change does not modify production code or the measured queries. The review thread was marked addressed after this proof. ## Risks - Payload validation now follows claim commit. If the process stops there, the existing stale-claim recovery path retains the body and retries it. Tests cover fresh and stale processing rows. - A malformed future retry now fails when due instead of being cleared by an unrelated early worker. The claimed-attempt guard prevents invalid settlement from overwriting a later claim. Terminal invalid-payload settlement intentionally retains the baseline result shape (`code` and `retryable: false`, without `attempts`). Changing that result contract is outside this byte reduction; the non-retryable row cannot become due again. - Existing runtime-generation, credential, recovery-source, replay-barrier, redaction, and retry checks remain in place. Existing assembled tests cover these boundaries. - There is no migration, startup job, dependency change, or deployment in this PR. ## Model Used - OpenAI GPT-6 through Codex. The exact runtime model ID and context window are not exposed by this environment. Capabilities used: source analysis, code editing, shell tools, PostgreSQL experiments, and automated tests. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [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 (The public contract is unchanged; benchmark usage and evidence are documented above.) - [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> |
||
|
|
eda2a03bfe |
fix(ui): keep responder avatars visible through comment acknowledgement (#17885)
## Thinking Path > - Paperclip gives people a shared place to manage and talk with agents. > - Task chat and Agent Chat show the responding agent as soon as a person sends a message. > - Comment storage and run discovery finish in separate requests. > - Both chat surfaces removed the startup identity when comment storage finished. > - A slow run lookup therefore made the avatar disappear and appear again. > - This pull request keeps startup feedback until the run appears or a newer execution outcome ends admission. > - The agent stays visible while the response starts. ## Linked Issues or Issue Description **What happened?** The responding agent's avatar appeared after Send, disappeared when the human comment was saved, and appeared again when the run loaded. Existing conversations made the flash easy to see. **Expected behavior** Keep the agent identity visible across comment storage, queued admission, and runtime startup. Clear temporary startup feedback on failure, backoff, task completion, or a completed run. **Steps to reproduce** 1. Open an existing agent conversation. 2. Send another message. 3. Let the comment POST finish before the task and live-run reads finish. 4. Observe the responder identity disappear during that gap. **Paperclip version** Source baseline: `db70c5acd92f50fa37fb4f0dea3da0e7685089a2`. **Deployment mode** Local trusted mode with an isolated database. The browser test used the real app, APIs, and native runner with a deterministic Codex provider. It held read responses to expose the acknowledgement gap. It did not call a live model provider. Related: #4485 addressed human-comment alignment during session loading. This change addresses agent-response startup. ## What Changed - Share submission-to-run state between the task and classic chat surfaces. - Keep the identity mounted after comment acknowledgement. End startup on a visible run or a newer admission outcome. - Keep old execution projections and older loaded history from acknowledging a new response. Retain slow-start refresh and uncertain-save handling. - Extend the startup tests through the missing acknowledgement interval on desktop and mobile. Add existing-thread, paused-agent, fast-completion, and clock-skew cases for both surfaces. - Match completed runs to the saved comment and its server time. Use the shared status rules and server-reported reporting-chain health for known agent blockers and confirmed task pauses. Keep submitted feedback visible through pause-state read errors. No browser/server clock comparison is used. - Clarify the identity continuity rule in `DESIGN.md`. ## Verification - Red: the actual Send tests fail against the original components in eight cases. - Green: both chat suites pass, 420 tests total. Extra red/green cases cover paused or ineligible agents, missing/terminated managers, reporting cycles, browser clocks five minutes ahead or behind, and pause-state read failures. - Chromium on an existing conversation: the original avatar appeared at 58 ms and disappeared at 326 ms. On final commit `f9602e3e48`, the avatar appeared at 68 ms and stayed visible through the same held-read interval. Frame sampling found no disappearance after it appeared. - Native fixture turns succeeded and stored their final provider replies. Repeated the existing-thread turn and normal navigation/reload on final commit `f9602e3e48`: both runs succeeded, both replies were stored, and the conversation returned to its waiting state. - `pnpm -r typecheck`, `pnpm build`, `pnpm check:token-gates`, and the final UI typecheck passed. - `pnpm test:run` was attempted. The host exhausted PostgreSQL semaphores. The supported external test database let some suites run, but other suites still attempted embedded clusters and failed or skipped setup. The run was stopped after repeated setup failures. - The broader UI run passed 9,251 tests and failed one existing connection-authentication test. The same test fails on an untouched copy of the base commit. This PR does not change that component or test. Full-suite CI remains the complete-suite check. - Final-head CI attempt 1 lost seven workers to shutdown or lost communication and hit one timing assertion in an unchanged scheduler test. Retried only failed jobs once on the same commit; the scheduler test and interrupted jobs recovered. All retried jobs and both aggregate gates passed. Final CI is green on `f9602e3e48c75580935465eb0b4713fc7a4bcc56`. ## Risks Low scope: this changes client startup feedback only. There are no API, data, auth, or token changes. If run discovery is slow, the existing slow-start message remains visible until current execution evidence arrives. Completed runs are matched to the submitted comment by consumption identity or server timestamps, so loading old history and browser clock differences cannot end its feedback incorrectly. ## Model Used OpenAI Codex, GPT-6 family. This session does not expose the exact deployment ID or context-window limit. It used reasoning, code editing, command execution, and Chromium automation. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass (420 relevant chat tests; the full-suite setup limit is recorded above) - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
e71a23c01c |
fix(ui): animate late task sidebar loading (#17880)
<!-- entire-trail-link-start --> https://entire.com/gh/paperclipai/-/trails/61/changes/paperclip/61 <!-- entire-trail-link-end --> ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Task pages load the conversation and related sidebar data separately. > - The sidebar host did not exist until its content arrived. > - Its first appearance skipped the width transition and moved the thread at once. > - This pull request keeps an empty host at zero width until content is available. > - The sidebar and thread now move together, with immediate changes for reduced motion. ## Linked Issues or Issue Description **What happened?** A cold task load showed a wide skeleton. The right sidebar then appeared at full width and shifted the thread at once. **Expected behavior** The sidebar should enter smoothly. The task thread should move with it. Unknown or hidden sidebars should take no space. **Steps to reproduce** 1. Open a populated task in a fresh browser context. 2. Delay the task metadata response. 3. Watch the skeleton and thread as the right sidebar becomes available. Related work: [task cold-open reads](https://github.com/paperclipai/paperclip/pull/17756). ## What Changed - Keep the shared sidebar host mounted at zero width while its content is unknown. Make hidden hosts inert and hide them from assistive technology. - Use shared motion tokens for width and opacity. Disable motion for reduced-motion preferences and keep pointer resizing immediate. - Clamp late content to the current viewport without overwriting the saved width. Keep the motion catalog aligned with the reveal tokens. - Clip the panel body during reveal. Keep the resize handle inside the viewport during the first frame. - Clear empty panes immediately when content is removed. Release maximized geometry on that render. Remove the unused width/opacity token. - Add four replayable Storybook scenarios using the production skeleton and panel components. Add browser checks for both arrival orders, absent and hidden sidebars, reduced motion, resizing, and maximize/restore. - Document the shared sidebar loading behavior in DESIGN.md. - Load the comment-route test modules in suite setup. This prevents a slow module load from timing out the first test and affecting the next test. This test-only change fixes a reproducible CI failure; route behavior and assertions stay the same. ## Verification - 201 focused task-detail, properties-panel, and motion-catalog tests passed. New host-continuity regressions failed against the original component in both task interfaces. - Eight focused Storybook browser checks passed without retries after the review fix. They measure intermediate widths and matching thread widths, check overflow, exercise resize and maximize controls, and confirm immediate removal of docked and maximized content. - The first removal checks sampled before replay cleanup committed. Sampling now starts after the host becomes inert. All three removal checks fail against the prior commit. Restoring the source during that comparison left a stale Storybook module in the preview. After a preview restart, all eight cases passed without retries on the fixed source. - Verified a real populated local task in a fresh browser context with delayed real API responses. Recorded a screencast for visual review. The captured reveal had 20 intermediate widths, no horizontal overflow, and no browser errors. - Repository typecheck, full build, Storybook build, token gates, map checks, and 30 catalog/map tests passed. Full typecheck, full build, focused UI tests, and UI typecheck were repeated after the upstream rebase. - Full `pnpm test:run` was attempted and stopped after repeated embedded PostgreSQL initialization failures. The host has exhausted its semaphore pool. The local app test used a disposable container database instead. - Replay `tasks-sidebar-loading--sidebar-during-skeleton` in Storybook. Run the focused browser suite with `STORYBOOK_TEST_BASE_URL` set to that Storybook server. - CI serialized shard 6/9 failed when the first comment-route test hit its 15-second timeout. Its work then affected the next test's mock count. Both failures reproduced locally on Node 24. After moving module loading to suite setup, all 103 tests and server typecheck passed with the same test timeout. A first local attempt could not bind the Supertest listener inside the sandbox; it was repeated with local network access. ## Risks - The shared host also serves other properties panels. Hidden preferences, default widths, pointer resizing, maximize/restore, and both task interfaces have focused coverage. - Width animation can reflow text while the panel enters. Reduced motion removes the transition. Navigation removes empty panes immediately. - Visual approval is complete. The full CI suite must pass before merge. No schema or API contracts change. ## Model Used - OpenAI GPT-6 through Codex, with reasoning, code execution, and browser tools. The exact deployed model ID and context-window size are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
bd382eee53 |
fix(recovery): explain retained source verification failures (#17773)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Workspace recovery must prove the identity of retained work before it uses an allocation. > - The verifier rejects several different contracts with the same `source_binding_invalid` code. > - A saved Retry can therefore stop before file preservation without enough evidence for a safe repair. > - Operators need a bounded observation of the selected source without another attempt or weaker guards. > - This pull request records closed failure reasons and adds an explicit read-only inspection on the run page. > - The benefit is a precise next diagnostic step while the saved work, intent, and ownership fences remain intact. ## Linked Issues or Issue Description Refs: #17741, #17053. This is a diagnostic follow-up. It does not change recovery admission or the retained-source acceptance policy. **What happened?** A retained-source recovery exhausted in `verify_execution` with only `source_binding_invalid`. Run and task diagnostics could not distinguish an invalid reference, lease policy, source binding, or reopened allocation. The normal recovery-actions read can also revalidate recovery state, so it was not a safe substitute for a current read-only inspection. **Expected behavior** Record an allowlisted reason at the rejected guard. Allow a reader to inspect one exact task/run/action without changing its attempts, saved input, receipts, or ownership. Clearly separate the recorded failure from current identity observations. **Steps to reproduce** 1. Prepare a terminal native run with a retained-source action and a lease policy of `reuse_by_environment`. 2. Attempt source verification. The guard must still reject that policy. 3. Open the failed run and choose Inspect recovery, then Inspect current source. The diagnostic should name `lease_policy_not_retained` and the allowlisted policy. ## What Changed - Split existing source-binding guards into closed reason codes. Keep each acceptance predicate and physical recovery action unchanged. - Persist validated, path-free reason/policy detail with future system recovery failures. Keep historical generic records compatible. - Add an explicit query on the existing task recovery-actions GET. Exact company/task/run/action selection bypasses read revalidation. Run selection lists at most 20 actions; inspection stops before per-lease lookup when a record has more than eight sources. - Add a manual inspection control on native export-failure run pages. Keep resolved retained actions inspectable. Show recorded failure and current recorded-source identity separately. - Update execution semantics and feature/access recipes. The shared type is the normalized server/UI contract; it contains no provider payload or secret. ## Verification - RED: the prior verifier failed both reason assertions for rejected warm policy and foreign-run lease binding. GREEN: the final focused source/HTTP, system-state, and UI suites pass 23 tests. The UI follow-up passes 8 tests after the review fixes. - HTTP tests prove exact selection, cross-company denial, resolved-action access, reused-allocation rejection, redaction, and unchanged actions, runs, leases, tasks, wakeup receipts, workspace operations, and activity. A nine-source case proves bounded inspection while the existing worker verifier still accepts all nine valid sources. - Review follow-up: show allowlisted saved detail beside a changed current observation, preserve all listed actions, and follow exact-action selection in verified/limited/error tests. The prior component fails the saved/current drift regression in an in-memory RED control; the current component passes. UI typecheck/build pass again. - `pnpm -r typecheck` and `pnpm build` pass. Token gates, maps, module boundaries, and `git diff --check` pass. - Rebased onto master `46de15ff4b` without conflicts. Range-diff proves both diagnostic commits are unchanged. On new head `a7e2bc87fcea75e76b6b736304d1287257f71174`, all 23 focused tests, full typecheck/build, token gates, maps, and module checks pass again. Both fresh reviews are 5/5 with zero unresolved threads. Final exact-head GitHub status is CLEAN: 55 success, 2 skipped, 1 neutral, no pending checks or failures. The [ci / verify aggregate](https://github.com/paperclipai/paperclip/actions/runs/40387002325/job/121802415824) passed in eight seconds. All test/build/typecheck/E2E lanes passed. - Existing full workspace recovery suite: 56/56 pass (103.5 seconds) before the byte-equivalent rebase. `pnpm test:run` hit repeated embedded PostgreSQL initialization failure before database-suite assertions and was stopped. No full local suite pass is claimed. The owned external `_test` database provided the focused HTTP/source verification. The prior browser attempt also stalled at Network.enable before its click; that attempt did not establish browser acceptance. - Current-head local browser acceptance passes through the actual run page: Inspect recovery lists the exact action, Inspect current source shows recorded generic failure separately from the current rejected policy, and reload resets inspection to the explicit control. Explicit selection works again after reload. The app used isolated data, an empty inherited environment, a paused synthetic agent, and no provider credentials. Final state remains failed/exhausted with zero attempts, zero wakeup receipts, zero workspace operations, and unchanged original generic failure. The local app and temporary tab were stopped. This proves the diagnostic journey, not the deployed source's actual lease policy or its recovery. - Final merge verification at `a7e2bc87fcea75e76b6b736304d1287257f71174`: GitHub reports CLEAN and mergeable. Both repository-required checks, `ci / verify` and `ci / e2e`, pass, as does the exact-head Greptile check (5/5, zero unresolved threads). The separate [Entire trail](https://entire.com/gh/paperclipai/paperclip/trails/7) has no recorded reviewer approval; no such approval is claimed. It is not a configured GitHub merge gate. - Initial local setup failures were distinct from product assertions: localhost sandbox EPERM required scoped local access; a browser harness import path was corrected. A test UUID type inference error and historical native-export UI selection gap were corrected before the green run. The live task remains blocked; this diagnostic does not claim it recovered. ## Risks - This change improves evidence. It does not prove provider termination, local descriptor integrity, or successful file preservation, and it does not repair the original source. - Current inspection spans multiple database reads. It is an observation, not a historical cause or execution authority. It performs no provider/filesystem calls and starts no retry or executor. - The optional persisted detail is backward compatible. Unknown values and extra fields are excluded. Oversized source lists remain uninspected through this explicit diagnostic path; physical recovery rules do not change. ## Model Used OpenAI Codex based on GPT-6, with code execution and browser tools. The exact serving model ID and context window were not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
0c9d10d695 |
feat(connections): complete saved setup guidance and coverage maps (#17739)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Product and agent access maps describe the same capability IDs. > - Agent connection management changes the callable operations and permission boundaries. > - Reviewers need an operation inventory that distinguishes API access, human handoffs, and fixture evidence. > - This pull request adds saved setup screens and updates the maps for #17737. > - The benefit is that users and contributors can inspect the coverage and remaining boundaries. ## Linked Issues or Issue Description **Subsystem affected** Product and permission documentation, saved authentication setup UI and consent metadata, and product/agent access maps. **Problem or motivation** The current maps describe board-only management paths. They need to match delegated connection management and distinguish administration from ordinary tool execution. **Proposed solution** Record route operations, required grants, responsible-user limits, transport, saved authentication handoffs, provider-fixture evidence, and explicit local-operator boundaries for every connection family. **Roadmap alignment** This is the documentation companion to #17737. It covers existing Connected Apps, governed MCP gateways, chat channels, and personal/shared AI accounts. It uses existing server setup operations and adds their saved handoffs to the existing UI. ## What Changed - Show saved AI sign-in and connection setup handoffs in the existing UI. - Open GitHub import and rotation links at the required human step. Resume a committed rotation after reload without asking for another secret. - Restore saved Google service choices for the addressed user while preserving newer consent. Successful direct/cloud consent records its own timestamp, independently of refresh or lease writes; existing refresh paths preserve it. - Update product, implementation, and permission-default documentation. - Reconcile app permissions, connection setup, chat channels, profiles/gateways, and model account coverage. - Use matching capability IDs in the product and agent access maps. - Label source-reviewed operations separately from fixture-tested operations and live provider setup. - Preserve catalog creator attribution under the responsible user, with the actual agent still recorded. This follow-up moved from the implementation to keep both reviews below 100 files. This companion now changes 38 files, including the preserved Vercel personal-credential and OAuth callback attribution follow-ups alongside consent and catalog ownership. - Name the addressed-human browser-session and consent step for Slack managed authorization and installation. Preserve source-only evidence for those individual operations. ## Verification - Current companion head: `04d40cdd605452d91cf4931476eb292a210825af`, including implementation `2ecd6451d0` and master `ea727dc3c2`, 38 files. All intended companion files survive: 35 are byte-identical to the previous companion; two chat maps and qualification add current evidence. Exact-head Superagent passed and Paperclip Review supplied an actual neutral5/5 assessment with no findings and explicit no-independent-runtime/live/current-CI verification limits. Exact-head Greptile also completed at5/5 with no findings; both formerly failed shards and their verification aggregate passed on attempt2; full exact-head Linux CI workflow40446969603 completed SUCCESS. All current checks and statuses are terminal clean, with no unresolved findings. This PR remains dependent on #17737 and needs fresh checks after its required post-squash replay. The preceding 605 head’s reviews are historical after this update. Older b0ea Linux workflow success after its single rerun also remains historical. - Earlier preserved-stack verification passed **2,165 tests**: 70 assembled-server actual-auth scenarios, 27 OpenAPI contracts, 2,022 native API tests and 46 saved GitHub wizard cases in fresh PostgreSQL. The parent also passed **141 existing gateway/policy tests**. Workspace typecheck/build, maps and token gates passed. The initial typecheck IPC denial and all material intermediate regressions remain in the qualification record; no full local sweep or live provider setup is claimed. - Operation maps now cover issuer/target gateway policy intersection and post-approval revocation, bounded activity pagination through private-only windows, and native local-login encrypted receipts. The companion preserves the Vercel OAuth callback ownership change with its existing credential ownership follow-up. - Parent CI has one retained connection-intent e2e failure from a periodic-recovery timing race. GitHub refused the first job-rerun attempt while its workflow was nonterminal. Once completed, the single failed-job rerun was accepted as attempt 2 and passed, including the full parent Linux workflow. - Companion Linux server shard 4/12 retained a cleanup-idleness timeout in `login-cleanup-work.test.ts` (active work was still 1 after its five-second wait). The same unchanged cleanup suite passed all 16 cases in the parent Linux job 121950185096 and all 16 cases locally against a fresh disposable PostgreSQL database. Relevant cleanup/reaper/scheduling runtime code is unchanged. The single unchanged-code failed-job rerun was accepted as **attempt 2** on the previous `b0ea3c940f` head (workflow 40431671705). The failed shard and complete Linux workflow passed on attempt 2; no additional unchanged-code rerun was used for this failure. The first local attempt failed the existing dedicated `_test` database-name guard before running tests; the correctly named fixture passed without weakening the guard. - **Earlier 82 GitHub UI tests passed**. All three new replacement cases were red before the fix. A confirmed unchanged generation preserves the earlier copy; a changed or unreadable generation blocks copying and reconnecting. An explicit status check can restore the copy when it is still current. All earlier import, rotation, verification, and retry states remain covered. - The complete stack passed **82 API/OpenAPI tests** in fresh PostgreSQL, including 55 scenarios with real agent keys, run JWTs, human sessions, production defaults, persistence, and deterministic providers. The parent also passed **60 Copilot installation tests**, preserving published v62 and binding combined guidance as v63. - **Earlier 10 focused Google/OAuth tests passed**: eight picker cases and two local-HTTP protocol cases proving consent metadata survives concurrent token refresh. The refresh and legacy UI cases were red before the fix. These protocol fixtures use the existing injected board actor and do not count as agent-authenticated proof. - Workspace typecheck/build passed after the consent change; normal migration generation reported no SQL changes for the additive JSON metadata. The parent's latest caller-authorization correction passed server typecheck/build. Map validation and token gates passed. Maps cover 35 areas and 192 capability IDs. The specification names migration `0380_broken_aqueduct.sql`. - The test-call operation maps now record the full caller/target tool access decision (profiles, policies, and explicit grants), credential identity for every auth label, approval, and rate checks. The profile-only precondition was removed after the new permitted-access cases failed; those cases and the no-auth identity regression now pass. Saved test status requires its originating principal and current linked-task access; actual key/JWT privacy-denial evidence is recorded. - Tool-connection activity is now operation-verified: 100 events over two tasks require two capability decisions and at most two run captures (previously 100/102), preserve private-event filtering, and deny the next request after audit revocation. The regression was red before the fix. - Cloud enrollment creation and callback entries now name instance-administrator and company/principal checks. The callback is a browser return with HTML or a 303 redirect. Status reads retain their separate board-actor rule. - Operation maps identify the API, transport, authorization, evidence, and human/operator boundaries. Structural checks do not establish live provider behavior. Earlier failures and fixture corrections remain in `doc/plans/2026-10-13-connection-api-parity.md`. - An earlier companion head (`26edbe17`) received an actual Paperclip Review assessment of 5/5 with no actionable findings, published with neutral status. That review did not run tests or confirm CI, and it is historical for this new head. The prior incomplete execution result is not counted as a passed assessment. Fresh review remains pending. The duplicate enrollment findings have explanatory replies and are resolved. - The latest implementation correction passed all 55 actual-auth scenarios and 27 OpenAPI contracts (separate commands). It repairs unavailable old credential material, preserves fresh import versus configured reconnect links, and distinguishes credential field sets/completion modes in handoff keys. The new fresh-link and collision cases were red before the fix. All 41 GitHub wizard tests now pass, including filling the fresh saved handoff and asserting App import rather than reconnect; UI typecheck, maps and token gates also pass. Qualification retains the earlier failures and an incorrect OpenAPI filename that selected only the integration module before the correct separate contract run. - Configured GitHub credential-entry links carry canonical requested fields and all/any mode. The form displays and submits those values through human reconnect while retaining other saved credentials. Two webhook/client-secret cases were red before the fix; combined all/any and legacy-link cases also pass. The current UI fixes the old |
||
|
|
3edba11576 |
fix(github): stop counting suspended installations as repository access (#17343)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents get GitHub access through a managed GitHub App connection.
**Refresh access** reads the installations and repositories that the
user token can reach.
> - GitHub keeps listing a suspended App installation and all of its
repositories for the user token. But the token then loses write access
and cannot read private repositories.
> - `loadGitHubGrantMetadata` did not read `suspended_at`. It counted a
suspended installation as live access ("all repos") and set the
connection to healthy.
> - So the board showed "connected, all repositories" while agents got a
403 on `git push` and a 404 on private repositories. The suspend webhook
marks the connection unhealthy, but the next refresh or reconnect
reverted that.
> - This pull request skips suspended installations. When all
installations are suspended, Refresh access fails with a clear error and
a link to the installation settings page, where an owner can click
**Unsuspend**.
> - The benefit is that the board shows the real access state, and
operators get a direct path to fix it.
## Linked Issues or Issue Description
**What happened?**
A GitHub App installation on an organization was suspended. The
Paperclip GitHub connection still showed "connected" with access to all
repositories after **Refresh access**. Agents that used the managed
token got `Permission to <org>/<repo>.git denied` (403) on push,
`Resource not accessible by integration` on branch creation, and 404 on
private repositories.
**Expected behavior**
Refresh access must not count a suspended installation as repository
access. When every installation is suspended, Refresh access must fail
with a message that says the installation is suspended, and the page
must link to the installation settings page.
**Steps to reproduce**
1. Connect GitHub to Paperclip through the GitHub App, with an
installation on an organization.
2. On GitHub, suspend that installation (Organization settings → GitHub
Apps → Configure → Suspend).
3. In Paperclip, click **Refresh access** on the GitHub connection.
4. See that the connection stays healthy and reports all repositories,
while agent pushes fail with 403.
**Paperclip version or commit**
`master` at
|
||
|
|
3e7c3ee9a9 |
fix(ui): fall back to the icon face when an Artifacts V1 preview fails to load (#17260)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agents produce artifacts: documents, files, pictures, video and links. The Artifacts V1 presentation (`enableArtifactsV1`, #17228) shows them as prints, sheets and rows on the Artifacts page, in the panel's Artifacts tab and in the task thread > - A picture is printed from its attachment's content path. When that content cannot be loaded (on staging, image work products whose attachment returns 404), the browser draws its broken-picture glyph inside the bordered print and inside the 40px row thumbnail > - The presentation already has a face for a file with nothing to show: the icon sheet (the faint glyph and the type label) and the row's document icon. A picture that cannot be loaded should take that face, not a browser glyph > - This pull request listens for the element's own `error` event in the V1 primitives and falls back to the icon face on all three surfaces: the stack front and the single tile on the Artifacts page, and the panel and thread rows > - The benefit is that a missing or unreadable file reads as a file of its type everywhere, with no fetch to find out, and nothing changes for a picture that loads ## Linked Issues or Issue Description No public issue exists. This section follows the bug report template. **What happened?** With Artifacts V1 on, an image work product whose attachment content returns 404 ("Attachment not found") shows the browser's broken-image glyph inside the bordered print on the Artifacts page (the stack front and the single tile) and inside the 40px thumbnail in the panel and thread rows. **What did you expect to happen?** The artifact shows the icon face a file without a preview gets: the icon sheet with the faint glyph and the type label on the Artifacts page, and the document icon with the type label in the rows. **Steps to reproduce** 1. Turn on Settings > Experimental > Artifacts V1. 2. Register an image work product whose attachment content returns 404, or delete the attachment behind one. 3. Open the Artifacts page, the task's Artifacts tab and the task thread. **Relevant subsystem** The web UI (`ui/src/components/artifacts/v1/`). ## What Changed - `ArtifactPrint`: a new `usePreviewFailure(source)` hook beside `useImageAspect`, and an `onMediaError` prop wired to the `error` event of the print's `<img>` and `<video>`. The hook remembers the source that failed rather than a flag, so a front that moves on to another picture (a stack's newest artifact) gets a fresh chance. - `ArtifactFront`: owns the failure state for its subject and renders the icon sheet (`IconSheet`, the `icon` treatment) once the print reports an error; it passes the error on through its own `onMediaError`. - `ArtifactStack`: on an error it stops fitting a print and stands the icon sheet where a sheet stands in the media stack (the portrait anchor, where audio stands), keeping the media backing. - `ArtifactRow`: the thumbnail listens for `error` on its `<img>` / `<video>` and gives way to `ArtifactRowIcon`, the document icon with the type label. - Until the picture loads the print stays the 4:3 placeholder, and a picture that loads behaves as before. No fetch is made to detect a failure. - A failed video takes the plain icon sheet with no play disc, since the stream it would promise cannot play; a video with no URL at all keeps the existing media-fallback treatment with the disc. - `index.ts` exports `usePreviewFailure`; the plan doc `doc/plans/2026-10-22-artifacts-mvp-v1.md` records the fallback. - Tests: `ArtifactTile.test.tsx` covers the single tile (4:3 placeholder, then the icon sheet after `error`), the picture stack (the sheet stands where the audio stack's sheet stands, on the media backing) and a video whose stream fails (icon sheet, no play disc). `ArtifactRow.test.tsx` covers the thumbnail and the video thumbnail giving way to the document icon, and a new source getting its own chance. ## Verification - `cd ui && npx vitest run src/components/artifacts/v1` — 6 files, 33 tests pass (5 new). - `pnpm run check:token-gates` — exits 0: all four token gates clean, palette tokens and the ClipLab character in sync. (The bare `pnpm check:token-gates` form reports "Command not found" under pnpm 9.15.4 in this worktree; `pnpm run` works.) - `cd ui && pnpm typecheck` — exits 0 with no errors. - Browser proof on a throwaway backend-free vite page (not committed) rendering the primitives with a 404 picture, a 404 video, a picture that loads and audio: on the Artifacts page the 404 picture's stack front is the PNG icon sheet at the same position as the audio stack's sheet (left 37.89px, top 13.34px) on the media backing; the single tiles show the PNG and WEBM icon sheets with no play disc while the loading picture keeps its fitted 240×160 print; the rows show the PNG and WEBM document icons with no `<img>`/`<video>` left, while the loading picture's row keeps its thumbnail. Not run: the browser suites (`pnpm test:e2e`, `pnpm test:release-smoke`) and a live staging check. States enumerated: loading (4:3 placeholder print, unchanged), loaded (fitted print, unchanged), failed picture (icon sheet / document icon), failed poster-less video (icon sheet without play disc / document icon), source changed after a failure (print again). ## Risks - Low risk. The change is behind `enableArtifactsV1` and only acts on the element's `error` event, which fires for a 404, a network failure, or content that is not decodable as a picture; nothing is fetched to find out. - `ArtifactFront` and `ArtifactStack` each keep the failure state for their subject (as both already keep the loaded aspect), set from the same event in one render; a consumer that renders `ArtifactFront` with a print size but ignores `onMediaError` still gets the icon face, only at the print's position. - A picture that fails once and later becomes readable at the same URL keeps the icon face until the surface remounts or the subject moves on to another source; the data does not change under a mounted tile in practice. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - Claude (Anthropic), model ID `claude-fable-5-1`, extended thinking, running in Claude Code (desktop app) with tool use: file editing, shell, Vitest, and the built-in browser for the proof page. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
b46d1ab77b |
feat(ui): request a standalone window so the app can be installed (#13461)
## Thinking Path > - The Paperclip board is used from phones, and `ui/public/site.webmanifest` is what a browser reads when someone adds the board to a home screen. > - That manifest asks for `display: "browser"`. Chrome installs a web app only when `display` is `fullscreen`, `standalone` or `minimal-ui`; with `browser` it answers `manifest-display-not-supported` and adds a shortcut rather than an app, so every launch keeps the address bar. > - The user interface already implements the no-browser-chrome case. `StandaloneBrowserControls` renders Refresh, Share and Open in Browser, and it is rendered only when `mobile && isChromelessDisplayMode()`. `ui/src/lib/pwa-display-mode.ts` exists for no other purpose than to detect `standalone`, `fullscreen` and `window-controls-overlay`. > - None of those modes can occur on a mobile launch while the manifest says `browser`, so that component and its fallback controls are unreachable in practice. > - That makes the manifest value look like the outlier rather than the intent, so the change is one manifest field plus the test that pins it. ## Linked Issues or Issue Description Refs #2139 — "enh: Officially support Install as Progressive Web App", which asks for a supported home-screen install. This pull request is the installability half of that request; it does not touch notifications. **Subsystem affected** The web app manifest and the unit test that guards it: `ui/public/site.webmanifest` and `ui/src/lib/pwa-install-mode.test.ts`. No server, plugin, or database code. **Problem or motivation** Chrome's installability criteria require `display` to be one of `fullscreen`, `standalone` or `minimal-ui`. With `display: "browser"` Chrome reports `manifest-display-not-supported`, offers only a shortcut, and the launch keeps browser controls, so the board never behaves like an installed application even though the manifest, service worker, and icons all exist. The same value also makes existing code unreachable: the in-app replacement controls for a chromeless launch (`StandaloneBrowserControls`, gated on `mobile && isChromelessDisplayMode()`) cannot be triggered from a mobile home-screen launch, so the app carries a fallback that nothing can exercise. **Proposed solution** - Set `display: "standalone"` in `ui/public/site.webmanifest`. - Update `ui/src/lib/pwa-install-mode.test.ts`, which asserted `display === "browser"`. The assertion now pins `standalone` and a comment records why, so the next reader does not have to reconstruct this reasoning. The assertions that keep the legacy `mobile-web-app-capable` and the Apple metas out of `index.html` are unchanged. `standalone` rather than `fullscreen` for two reasons. It keeps the Android status bar showing the clock and battery, and it avoids a known Android behaviour of `fullscreen` launches: opening the soft keyboard triggers a fullscreen transition and a visible flicker ([Google issue 392925620](https://issuetracker.google.com/issues/392925620), [Stack Overflow 71606355](https://stackoverflow.com/questions/71606355/pwa-does-not-resize-window-when-virtual-keyboard-is-active-on-fullscreen-display)), which `standalone` does not do. **Alternatives considered** - `fullscreen`. Also installable, and it additionally hides the Android status bar. Rejected as the default for that reason; it is a one-word change if preferred. - Adding the legacy `mobile-web-app-capable` meta. Rejected: Chrome reads the manifest, so the meta is redundant. - Adding the Apple `apple-mobile-web-app-capable` metas for iOS. Rejected for this change: it is iOS-specific, and iOS is not the platform whose installability check this fixes. - Changing `orientation`, which #5564 reports. Rejected as out of scope; this pull request stays on `display` only. **Roadmap alignment** `ROADMAP.md` does not plan this work. Its only mention of install is the skills store. **Additional context** - #7792 attempted a standalone PWA earlier and was closed during triage. It bundled a deploy-pipeline change and a heartbeat change with the manifest change, and its title carried an internal ticket id. This pull request is deliberately the manifest change alone. - #5564 reports that the manifest's `orientation: any` ignores the Android rotation lock. Related, not addressed here. - The keyboard flicker above was reported against a board installed with `fullscreen`, which is one of the two reasons this pull request asks for `standalone` instead of the more immersive mode. ## What Changed - `ui/public/site.webmanifest`: `display` is now `"standalone"` instead of `"browser"`. - `ui/src/lib/pwa-install-mode.test.ts`: the expectation that pinned `browser` now pins `standalone`, with the reasoning in a comment; the meta assertions are unchanged. No runtime code, no dependency, and no data change. The icons the installability check also requires (`android-chrome-192x192.png`, `android-chrome-512x512.png`) are already present and unchanged. ## Verification - `vitest run src/lib/pwa-install-mode.test.ts src/lib/pwa-display-mode.test.ts` in `ui`: 2 files, 7 tests passed (the same 2 + 5 the sibling plugin-event change reports). - The manifest parses as JSON, keeps `display: "standalone"`, and keeps 192 and 512 pixel icons. - The only place in the repository that asserts the manifest's `display` value is the test updated here; the other references to `site.webmanifest` are request routing and HTTP log policy and are unaffected. - CI on the previous head of this branch had two failures unrelated to this change: an e2e hover-opacity assertion on a sidebar star button (`Star Zeta`: expected `1`, received `0`) and `TypeError: Cannot read properties of undefined (reading 'logicalEffectCount')` in the runner verify job. Both are in subsystems this change cannot reach; CI is re-running on this commit. ## Risks - Low. One manifest field and one test expectation; no runtime code changes. - The value applies to new installations. An app already installed with the previous value keeps its installed configuration until it is reinstalled, so nobody loses a working install. - iOS launches are unchanged: Safari does not take `display` from the manifest for home-screen launches, and this change does not add the Apple metas. - Nobody depends on the address bar being present in an installed launch; the in-app controls that replace it (`StandaloneBrowserControls`) are already implemented and become reachable. ## Model Used - Provider: DeepSeek. Model ID: `deepseek-v4-flash`. The model ran as a tool-using coding agent (shell, file edits, headless browser automation) inside a coding harness. The harness did not report a context-window size or a reasoning mode. ## 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 issues and linked them above (#2139, #7792, #5564) - [x] I have either (a) linked existing issues with `Fixes:` / `Closes` / `Refs #` OR (b) described the issue in-PR following the relevant issue template — both, see above - [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 ticket id or instance-derived details - [x] I have run the affected tests locally and they pass (2 files, 7 tests) - [x] I have added or updated tests where applicable — the guard test is updated, and it is the only test that pins this value - [x] I have updated relevant documentation to reflect my changes — no user-facing document describes the manifest; the updated test now records the reasoning in place - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green — CI is re-running on this commit after the unrelated failures described under Verification - [ ] Greptile is 5/5 — awaiting the review run on this commit - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
208a093d19 |
fix(chat): preserve resumed review waits and retry newer saved input (#17725)
<!-- entire-trail-link-start --> https://entire.com/gh/paperclipai/-/trails/36/changes/paperclip/36 <!-- entire-trail-link-end --> ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - GitHub review agents publish findings and wait for an authorized reply or head change. > - Review tools could retain the requester after resume while completion lost that same wait proof. > - A yielded report could then queue its own continuation or repeat a missing-wait error. > - Ordinary Retry could also select an older failed turn while a newer saved request had no admission. > - This change shares the existing authority proofs and canonical admission owners. > - Current access, publication, execution and budget gates remain required. ## Linked Issues or Issue Description Refs #17318. Builds on the canonical saved-input retry owner in #17733. Related #16550 covers deferred legacy comments after ownership waits. The separate recovery repair in #17724 owns the cleanup-to-saved-input handoff; this PR does not add a second admission owner. A resumed review could publish an assessment, then turn its `response_wake` into an immediate `issue_status_changed` wake. A provider that omitted its continuation could instead repeat a completion error. A newer linked-human message saved during a budget hold could also remain unstarted because Retry selected the older failed source. ## What Changed - Resolve passive review waits through the accepted requester ledger used by GitHub tools. Require the latest reviewed head, exact company, task, agent, repository and processed publication under current access. - Fill omitted/null yielded continuation from that server proof. Permit an inherited normal tree resume only through its accepted parent identity. Permit an ordinary follow-up only after this run has a processed useful reply linked to its exact inbound message. Reject acknowledgements, partial assessments, pending or uncertain writes as that reply proof. - Recheck the same run/review/head/source proof during feedback, finalization and final status commit. Preserve explicit malformed-input rejection and Done policy. Add no monitor permission or publication grant. - Keep heartbeat and publication projections narrow. Preserve both published Copilot v62 identities and generate source-bound v63 from the pinned merged base. No v63 live qualification is claimed. - Certify the structured isolated-directory binding failure only at its pre-allocation boundary and only through canonical task Retry. Other workspace validation reasons and unknown effects remain denied. - Route Retry to eligible newer saved input through the existing canonical owner. Preserve the old result and skipped receipt. Require current principal, source, App, runtime fence, budget, native ownership and exact cleanup proof. - Recover absent historical App metadata only through an earlier trusted processed response receipt and an immutable non-null endpoint claim. Explicit malformed or conflicting metadata stays denied. - Revalidate execution through the exact claimed wake, coalesced task Retry and resolved user-continuation receipt after admission. A second normal Retry can recover the exact never-started authorization failure with unchanged saved input. Require empty execution evidence, exact diagnostics and no allocated or active executor. - Explain when a recorded result prevents exact replay. Ordinary board Retry directs a new task message to continue from saved work. Inherited requester identity alone never grants replay. - Keep accepted board-message preparation failures with the canonical task Retry owner. Certify the exact unchanged comment, original user wake, accepted same-user identity and absence of provider execution. Pin that source, recheck it at admission, and bind identity initialization to the coalesced intent and exact claimed successor receipt. Uncertifiable sources retain an actionable fresh-message refusal. - Return safe named authority categories for board Retry refusals. Update execution documentation and capability maps. Add no schema or polling loop. ## Verification - A fresh external review request exposed a separate isolated-directory preparation failure before allocation. Its first normal Retry saved an intent but admitted no successor. This follow-up certifies only that exact structured preparation boundary through the existing canonical Retry owner, with trusted failed settlement and no executor, lease, result or output. A real HTTP/queue regression reproduces the missing successor before the repair. Twenty-three current-source safety cases and the final 98-case Retry/HTTP group pass, including a fresh click after a denied intent, source revocation, accepted results and the older direct API remaining denied. The warning case uses actual configuration preparation and production event append; unknown warning shape or provider provenance stays denied. Full workspace typecheck, build, maps and diff checks pass. Renewed hosted normal Retry now succeeds on the final combined source: it preserves the exact saved request and linked requester, starts one native successor in a fresh attempt workspace, publishes the current-head 2/5 assessment and commits In review with passive response wake. - A later hosted normal Retry published a low-score assessment but lost its accepted source identity because the previous attempt failed before identity initialization. It repeated continuation errors, then submitted Done. This is failed acceptance, not a successful qualification. The initializer now retains the exact source only after execution-time failed-chat Retry authorization; generic Retry and Done policy are unchanged. A real queue/initializer regression fails with a null source on the previous code and passes with the newer saved source. Two real database completion cases verify that source yields the authoritative wait and commits In review. Renewed hosted normal Retry now retains the accepted source and exposes the authoritative current-review wait. It completed after two semantic feedback corrections (wrong contract revision, then wrong criterion IDs); the correct contract was present in emitted input. The third finish was accepted and committed In review, with no missing-wait loop or Done escalation. - Repeated board-message preparation failures now walk their canonical intent, failed dispatch and accepted parent identity, rechecking each contained predecessor. A production queue regression fails the second ordinary HTTP Retry before the repair and passes afterward. Changed source, contradictory execution evidence and cyclic receipts remain denied; traversal stops after twenty links. - New inherited omission cases failed before the repair. The final full PostgreSQL 18 wait/status suite passes **252 tests** under Node 24.22. It covers omitted/null input, malformed-first recovery, same-head resume, exact-source replies, changed heads, revoked access, pending/uncertain/mixed publications, final commit revalidation, no duplicate review and no self-wake. - **15 existing publication tests passed before the pinned merge** on a separate fresh database. They retain default partial-delivery and failure-fallback behavior. Context reads remain below the unchanged 16 KiB heartbeat and publication response limits with large saved output present. - Saved-input tests cover a real signed PR webhook, production accounting-budget refusal, normal policy recovery and canonical Retry. Historical producer-shaped tests prove the missing-App case red, then check trusted prior receipts and malformed, late, revoked or mismatched proof. A broader order-coupled test was reproduced on the prior source; its global fault injector now targets its own authorization query. The 43-case sequence passes without changing production behavior or its safety assertions. - New signed-ingress and real heartbeat execution tests reproduced the admitted-successor failure, then the next normal Retry failure. The final pinned merged source passes 249 full GitHub review/publication and Retry cases on a fresh database, including all 49 saved-input cases. A separate 74-case Retry/HTTP run also passes. Exact dispatch negatives cover source, company, agent, task, successor, receipt, pause, assignment, accepted success, controller and cleanup proof. Bootstrap contradictions remain denied. The canonical Retry suite passes 16 cases through its supported external PostgreSQL test connection. - The normal board HTTP route reproduced the unusable inherited-result refusal. It now returns actionable guidance without starting a successor. The actual UI Retry hook and banner tests pass 12 cases. - A production-shaped accepted board comment followed by a pre-provider qualification failure reproduced HTTP 409 before the repair. The final real HTTP/queue test certifies one canonical successor and preserves the accepted identity. It rejects changed source, actor, task, agent, result, controller, process, profile, allocation and receipt evidence. A post-acceptance source change keeps the same intent pending. Execution revalidation rejects removed or mismatched proof. The probe stops deliberately after production identity initialization; it does not claim provider execution. The final source passes the 75-case Retry group, the focused two-case board/inherited-policy group and 19 canonical Retry cases. Full workspace typecheck, build and map checks pass. - Full workspace `pnpm -r typecheck` and `pnpm build` pass. Map, module-boundary and diff checks pass. Full local `pnpm test:run` remains unverified. The 256-case explicit-native suite cannot initialize its packaged PostgreSQL because libzstd is absent; an existing command-scoped fallback did not resolve it. Current-head remote full-suite checks are required. Merged-source full GitHub+Retry (249), separate Retry/HTTP (74), full wait/status (252), profile/history and completion (75), and visible Retry hook/banner (12) checks pass. The fresh owned PostgreSQL 18 databases applied all 377 migrations. - Actual Rust Runner, OpenCode 1.18.34 and exact DeepSeek used unchanged production-generated synthetic contexts. Resume finished with an explicit server wait. The author-reply trial omitted continuation twice: its first report failed the existing empty-criteria check; the corrected second report still omitted continuation and received the exact server wait. It completed once with no missing-wait loop or Done escalation. Controller acknowledgments were synthetic; these probes do not establish hosted publication or board state. - Hosted combined testing proved automatic admission of the exact saved author reply, a useful GitHub answer and committed passive wait. It required two malformed-continuation rejections before a nullish fallback succeeded. A later normal Pause/Resume completed in one finish with explicit response_wake and no new review/comment. The admitted normal Retry then exposed the execution guard gap repaired here. Those remain checkpoint results. On the final combined source, renewed normal Retry completed actual native provider work and GitHub publication, committed the passive wait, released ownership and cleaned up its environment. A subsequent ordinary unmentioned author reply woke once, made no GitHub tool calls or new assessment, and completed its first finish with an explicit response wake. Both exact leases expired with successful cleanup and the queue was empty. However, final destination inspection found a separate automatic fallback overwrote the existing summary with a generic no-final-response message. External summary preservation therefore remains failed acceptance; the separate publication repair in #17726 owns that producer. Full combined publication preservation has not passed. These hosted runs include the pinned-base native additions; they do not qualify Copilot v63. - Current-head automated review is 5/5 with zero unresolved threads. All current-head CI gates passed (54 successful checks/contexts, four skipped, none pending). The earlier login-cleanup idle-work assertion also reproduced locally while its controlled baseline passed; its cause remains unknown, but the exact assertion passed in the fresh current-head CI shard. No timeout, assertion or production workaround was added. This PR is ready for review within its source, authority, native finalization, state, wake and cleanup scope. The independent automatic fallback publication regression is tracked by #17726; no complete combined workflow pass is claimed. ## Risks - The latest saved review defines the durable head boundary. Ingress must record a new head before admission. A reply receipt proves delivery only for its exact saved source; a shared GitHub comment ID alone cannot authorize this wait. - Historical App recovery cannot infer identity without direct proof or an earlier valid server response receipt. It never replays that response. - This does not infer review-score policy from instructions or override Done. No deployment, merge or repair of historical tasks is claimed by the PR. ## Model Used OpenAI `gpt-6.1-sol`, with reasoning, repository inspection, code editing and test execution. The context-window size is not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass (focused database and native suites; full local suite limitation described 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 (verified on immutable latest head) - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups (verified on the latest head) - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
f0877a9c7c |
fix: recover native work and requalify saved computers (#17724)
<!-- entire-trail-link-start --> https://entire.com/gh/paperclipai/-/trails/32/changes/paperclip/32 <!-- entire-trail-link-end --> ## Thinking Path > - Paperclip manages AI agents and preserves their work after an interruption. > - Native Stop must confirm termination and save the workspace. > - Task and run views must show the current recovery receipt. > - A new external reply can arrive while that cleanup is pending. > - The reply must return to its original chat owner after cleanup. > - A successful fresh retry also becomes the task’s bound workspace for its next ordinary turn. > - Managed computer updates can invalidate a saved snapshot qualification. > - This pull request fixes those instructions, acknowledgements, handoffs and the existing native-agent Test path. > - The operator can continue with new input while the stopped turn remains preserved. ## Linked Issues or Issue Description **What happened?** Stopped native runs could keep the initial workspace-repair instruction after files were recovered. Native Stop could also leave the shared cancellation state at requested after remote termination was confirmed. A new GitHub reply saved during cleanup could then remain queued because cleanup did not ask its original inbound owner to reconsider the receipt. After a managed snapshot update, an existing native agent could also need qualification while the generic environment Test required instance-admin access. **Expected behavior** Show the current saved-work state. Acknowledge Stop only after exact termination proof. Let an authorized operator use the existing saved-agent Run test to qualify its current computer. After cleanup, recheck the saved reply's current authority and admit it once as new input. Preserve the stopped run and uncertain external effects. **Steps to reproduce** 1. Stop an active native turn before it returns a semantic result. 2. Send a new authorized external reply while cleanup is pending. 3. Let workspace recovery and provider cleanup finish. Inspect the run instruction, Stop acknowledgement and queued reply. Related work: #17594 preserves native processes through controller outages. #17401 addresses a separate bootstrap failure. This pull request does not replace those fixes. ## What Changed - Use the exact run's workspace recovery receipt for task and run guidance, including the Activity ledger. - Retire an obsolete exact-session notice through the existing bounded reconciler. Preserve the separate no-replay hold. - Write the shared native Stop acknowledgement only after the audited Stop intent and every exact remote lease receipt match. - Delegate saved external input to the live inbound owner. Recheck its source, actor, endpoint, principal and conversation generation. Promote the same receipt in the transaction that creates its new run. - Use that owner from the cleanup callback and existing stranded-queue catch-up after a lost callback or restart. A denied source cannot abort other items. - Reuse the current private task directory after a successful fresh retry. Re-read the company/task/workspace binding and validate the canonical stable or attempt namespace without recreating missing files; keep a later fresh retry separate. - Extend the existing agent-scoped qualification owner to native agents. The clean saved-agent Test qualifies its exact computer before runtime testing. Reuse a current proof; require a real probe and verified cleanup for a stale proof. Preserve draft tests and metadata-only external/pool previews. - Update execution semantics, capability maps and the recovery verification recipe. Add a production-page Storybook interaction for the normal native Test. ## Verification - **Red:** persisted recovery states returned stale instructions; an exact terminated native lease left shared Stop requested; the real GitHub subscribed-message fixture left zero successors after cleanup. The controlled baseline restored the previous production source, reproduced the failure, then restored the fixed bytes with matching SHA-256 hashes. - **Green:** 382 durable-chat, native-continuation, Stop and recovery tests pass. The real GitHub/PostgreSQL handoff matrix passes 12/12. It covers callback, application restart, callback/sweep race, valid input behind a deleted source, and denial for unknown stop, wrong allocation, paused endpoint, revoked principal, deleted or changed source, changed conversation generation and foreign scope. Repeated callbacks preserve one receipt, its actor, one successor and the unchanged stopped predecessor. - **Workspace continuation red/green:** the real PostgreSQL preparation flow created a fresh attempt and saved a marker, then rejected the next ordinary turn with the same binding mismatch observed in deployed use. The repaired preparation and filesystem suites pass 86/86: stable and attempt-root reuse, saved-marker preservation, a later clean sibling, changed current bindings, foreign company/task, closed workspace, traversal, missing path and symlink refusal. No task row reset or old-turn replay is used. - **Qualification red/green:** a native saved-agent qualification returned 422, and its normal Test skipped qualification. The repaired path passes 224 qualification/immutable-snapshot/environment tests and 176 UI/upgrade tests. It covers revoked authority, foreign or changed computer, current-proof reuse, failed/missing proof, draft settings, settings changed during the probe, and external/pool previews. On exact current source, the real local Harness / Runtime UI also qualified a newly saved disposable Computer with missing proof through actual Daytona, then completed the actual OpenCode/OpenRouter hello probe using `openrouter/deepseek/deepseek-v4.1-flash-1017`. Supported availability changed from Legacy-only to Paperclip Runner after proof persistence. Qualification and runtime leases both completed normal release/cleanup. The five prior task run IDs were unchanged; no task wake was created. This is macOS source-server/UI with real Linux Daytona and provider services, not a hosted UI claim. Test probes are archived by the existing inspection contract; release does not claim physical deletion. - Full workspace `pnpm -r typecheck`, `pnpm build`, token, map and diff checks pass at `f6450f4739fc8141815b8b7c35fde22a655c5f90`. The broad local `pnpm test:run` passed 24,899 tests and reported one existing nested-clone test timeout at 15 seconds. The complete failing file then passed 21/21 with the normal timeout; the exact case also passed on the pinned earlier baseline. The broad runner stopped before its later groups. No timeout or production workaround was added. Prior head `f6450f4` has 53 successful checks, two conditional Storybook skips and Greptile 5/5 with no inline threads. New workspace-reuse head `fcb13399ec70f92f71bd8250081251dca3f48962` passes workspace typecheck, full build, 86 scoped tests, maps and diff checks; Current-head CI has 53 successful checks and two conditional Storybook skips; Greptile is 5/5 with no inline findings. Deployed ordinary-turn reuse acceptance passed as described below. - **Hosted Stop proof:** the real GitHub issue-mention path used native OpenCode, `openrouter/deepseek/deepseek-v4.1-flash-1017`, Daytona and an exact low-trust task boundary. Normal UI Stop interrupted an active Bash call. Native and shared acknowledgements matched the exact lease. Automatic recovery saved exactly `STARTED\n` (8 bytes), with no finish marker. Reload showed Stopped and saved work recovered. Only the original cancelled run remained. Normal five-minute cleanup completed its exact provider-destruction transition. - **Limits:** the provider buffered command output, so the marker was read after recovery. The approved local provider credential could not inspect the hosted sandbox; its 404 is not deletion proof. Cleanup success comes from the exact lease's platform destruction transition. An earlier hosted stale instruction disappeared after rollout with unchanged raw run/action data; that historical cause remains unexplained. Original incident holds and publication receipts were untouched. - **Hosted handoff proof:** after QA deployed the combined candidate containing `46b2e99`, startup admitted the previously saved GitHub author reply without another comment, Retry or manual action. The new native run used the exact original wake receipt and saved comment. It completed once, committed an external-response wait, preserved the stopped predecessor, emptied the queue and left the task In review. The answer appeared in the original GitHub conversation. Workspace finalization and the exact lease's normal destruction transition succeeded. - **Hosted workspace proof:** on the combined candidate containing `fcb13399`, normal Retry preserved the original authenticated GitHub request and completed a fresh native attempt. One later ordinary same-head author reply then completed in the exact same workspace ID and attempt directory, with no Retry/fresh directive. Its input tree digest matched the Retry's finalized digest; final copyback preserved that digest. The persisted assessment row and all five prior run records were unchanged, exactly one new reply run completed, and the task returned to In review with an empty queue and no live run. Both exact leases completed normal verified destruction. This used real native OpenCode, the exact DeepSeek/OpenRouter model and Daytona, without workspace-row repair or a new remote marker. - **Publication limit:** the workspace audit compares the persisted assessment and run history. The ordinary reply exposed a separate destination-summary fallback that changed the visible GitHub summary despite the preserved assessment row. The publication track is repairing that behavior; this proof does not claim the visible summary was preserved. - **Deployment boundary:** current-head CI/review and hosted same-source Retry/ordinary-workspace reuse acceptance passed. The separate visible-summary publication failure remains owned by the publication track. Combined hosted UI confirmation of the native-agent Test path is coordinated separately. Actual missing-proof UI/provider qualification has passed in the isolated local instance above; prior hosted Stop and same-input handoff proof remains separate. No merge or deployment is performed by this pull request. ## Risks Recovery state and termination receipts must match the exact source run and allocation. Missing or foreign proof keeps the hold. The chat owner must retain the original receipt and actor and recheck current authority. Cleanup cannot grant authority or replay the stopped turn. Existing native ownership, Stop, budget, permission and uncertain-effect guards remain in place. ## Model Used OpenAI GPT-6.1 Sol (`gpt-6.1-sol`) through Codex, with reasoning, repository tools, source editing and test execution. The context-window size is not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass (affected suites and isolated failing file pass; broad timeout retained above) - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green (current fcb has 53 successful checks/two conditional Storybook skips) - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
baec3abd67 | Authorize background project Git with explicit Connector consent (#17798) | ||
|
|
cfed739f81 |
fix(external-objects): stop reporting GitHub rate limits as unreachable (#17792)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/11/changes/paperclip/11
<!-- entire-trail-link-end -->
## Thinking Path
> - Paperclip is the open source app that people use to manage AI agents
for work.
> - Paperclip shows the status of external objects, such as GitHub pull
requests and issues.
> - A background sweep refreshes these objects and resolves a GitHub
credential.
> - The sweep read a credential only from a company secret with a
well-known name.
> - An instance without that secret made anonymous GitHub API calls.
Anonymous calls are limited to 60 per hour.
> - When the limit was reached, the sweep showed "unreachable" for
objects that it could not refresh.
> - A server environment token is instance-wide, so it must not expose a
private repository that a company cannot see.
> - This pull request reads a server token for public repositories,
reports a rate limit as its own state, and shows a warning on the pill.
> - The benefit is an accurate status, fewer misleading failures, and no
cross-company private data.
## Linked Issues or Issue Description
No public GitHub issue exists. The sections below describe the bug.
**What happened?**
The board showed "unreachable" for many GitHub links, even after a
related fix was deployed.
**Expected behavior**
The board should show "unreachable" only for real network failures. It
should show a rate limit as its own state and retry later.
**Steps to reproduce**
1. Use an instance with no GitHub token company secret and no server
token.
2. Let the external-object sweep make more than 60 anonymous GitHub
requests in one hour.
3. Open a task with GitHub links.
**Paperclip version or commit**
master (commit
|
||
|
|
835966dec8 |
Prepare agent-owned environments during hiring (#17761)
<!-- entire-trail-link-start --> https://entire.com/gh/paperclipai/-/trails/1/changes/paperclip/1 <!-- entire-trail-link-end --> ## Thinking Path > - Paperclip manages agents and their execution environments. > - New agent setup saves an inactive agent before model connection tests. > - Some plugins need that agent to prepare its execution resource. > - The wizard tested without the agent ID, while the setup hold prevented preparation. > - Environment changes also discarded the selected model account. > - This change prepares the saved draft during setup and keeps normal execution held. > - Users can test the prepared resource before they finish hiring. ## Linked Issues or Issue Description **What happened?** An agent-owned plugin environment could not acquire a test lease during hiring. Changing environments also returned the user to Connect and cleared the selected account. **Expected behavior** Keep the selected account, invalidate its test, and prepare the saved agent resource in the background. Test that same agent before finishing setup. **Steps to reproduce** 1. Start a new Claude or Codex agent and select a saved account. 2. Change to an agent-owned plugin environment. 3. Try to finish setup or reconnect the account. Related: #17750 defers probes until after hire submission. This change implements preparation during the wizard instead. The related PR search and ROADMAP review found no other implementation of this setup preparation path. ## What Changed - Add the optional `requiresAgent` driver declaration. Require agent lifecycle participation when it is set. - Prepare saved drafts on creation or environment changes. Keep the setup hold and wait in `verifying` without background verification scans. - Bind tests to the saved agent. Return a warning without allocating a lease when the required agent is absent or still preparing. - Preserve the account and configuration step when the environment changes. Save the selection and invalidate the old test. - Show active preparation and support authorized retries. Keep approval, company, budget, and normal task admission controls. - Document the contract and cover lifecycle, lease, manifest, and wizard behavior. ## Verification - Server and UI TypeScript checks passed. - 112 wizard and setup helper tests passed. The shared manifest suite passed. - 123 lifecycle, policy, lease, and environment-test API cases passed after the approval-gate fix. The diagnostic and driver suites and all 80 agent adapter route tests also passed. - Token gates, module boundaries, map validation, and whitespace checks passed. - All 66 lifecycle/policy cases passed after the stopping-draft permission fix. The new real-DB route case verifies creator success, other-creator denial, and refusal to complete a hire while stopping. - Full workspace typecheck and build were attempted. Both stop at the unchanged Rust Runner step because Cargo is not installed on this host. - CI on |
||
|
|
c7c12dbc79 |
Support plugin panels in task sidebars (#17796)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task side panels keep live work beside the conversation.
> - Plugins can already provide agent detail tabs.
> - Those tabs have no generic way to appear beside the task that is
using the agent.
> - This pull request adds an optional task-side-panel declaration to
agent detail tabs.
> - The plugin owns the label, component and availability. Core supplies
the task's running agent.
## Linked Issues or Issue Description
**What existing behavior does this improve?**
Access to plugin-contributed live views from task chat.
**Subsystem affected**
Plugin manifest validation, slot discovery, and task side-panel
UI/state.
**Current behavior**
Agent detail-tab contributions appear on agent pages. A task cannot
offer the same view through a plugin-owned availability decision.
**Proposed behavior**
An agent detail tab can declare `taskSidePanel: { availabilityPath }`.
Core substitutes the running agent into the plugin-local path. A
declared board GET route scoped to that agent returns `{ available:
boolean }`. Available contributions appear in desktop and mobile task
side panels.
**Reason and benefit**
Keep the task and its live plugin views together. Preserve plugin
ownership of provider protocols and product behavior. Core contains no
concrete plugin identifiers, routes, labels or readiness rules.
**Breaking changes**
None. The field is optional. Existing contributions remain unchanged.
Missing, disabled or unavailable plugins add no panel.
**Additional context**
Related: #17111 established the agent detail-tab and scoped API
extension surfaces. Roadmap and related PR searches found no duplicate
of this extension.
## What Changed
- Extend the manifest with optional task-panel metadata. Validate safe
plugin-local paths and require a declared board GET route with
agent-scoped authorization.
- Discover and load only opted-in agent contributions. Poll their
generic availability responses and mount the existing components with
agent context.
- Add generic panel tabs, launcher entries, dismissal and inactive-view
removal in desktop/mobile task chat.
- Reuse the existing live-run polling guard so idle tasks with a healthy
live connection stop polling.
- Add provider-neutral fixtures, schema/authorization tests, task tests
and SDK/feature documentation.
## Verification
- PASS: 301 focused tests including the full task-detail file, generic
panel discovery, persistence, slot loading and manifest validation.
Regressions cover POST-before-GET route order, mobile drawer dismissal,
recovery without focus and the absence of the hidden desktop task panel
on mobile.
- PASS: UI and shared-package typechecks; production UI build; token
gates, feature-map and module-boundary checks; diff and secrets/PII
review.
- PASS on final head: all 795 UI files / 9,186 tests, and all 95
shared-package files / 1,038 tests. Commands: `node
node_modules/vitest/vitest.mjs run --project @paperclipai/ui
--maxWorkers 3` and the corresponding `--project @paperclipai/shared`
command with local socket access.
- On the final head, server shards 7/12 and 10/12 and workspace shard
a-1/2 were interrupted by runner shutdown/communication loss. GitHub
reported infrastructure failures; no assertion failure was surfaced in
the available diagnostics. The queued summary was cancelled, then `gh
run rerun --failed` successfully requested retries for only those three
jobs. They are currently queued for CI runners; the 50 successful checks
remain passing. Interrupted attempts are not counted as passing.
[Final-head CI and
retry](https://github.com/paperclipai/paperclip/actions/runs/40396870920).
- Earlier verification exposed an empty-panel rerender loop, which was
fixed. The sandboxed combined run also failed five shared port-registry
tests because it could not bind loopback listeners; the full shared
rerun with socket access passed. These earlier failures are retained
here rather than reported as passing runs.
- Full workspace typecheck/build were attempted with pinned pnpm 9 after
resolving the initial local package-manager setup. Both stop at the
unchanged Runner Rust step because `cargo` is not installed. Full local
workspace checks are not reported as passing; final CI must provide
those broader checks.
- No live provider or plugin-specific transport acceptance is claimed by
Core's synthetic fixtures.
## Risks
- Availability is polled every three seconds only while an authorized
running agent exists. Plugins own the side effects and meaning of that
read.
- A view uses the running agent's context. It is not a separate per-task
resource.
- Optional metadata adds no backend endpoint or permission bypass. The
host requires existing board and agent authorization.
- Reverting the optional contract and UI integration removes task panels
without a data migration.
## Model Used
OpenAI Codex (GPT-6), with reasoning, repository tools and code
execution. The exact backend snapshot ID and context window size are not
exposed by this session.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have described the issue in-PR following the relevant issue
template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal
ticket id
- [x] I have run focused tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
|
||
|
|
507dc70be2 |
fix(evals): bind hosted controller admission to the first attempt (#17523)
Bind hosted controller admission to the repository, GitHub run, first attempt, workflow revision and selected execution before credential reads or provider launch. Keep offline evidence replay independent of the current worker environment. Preserve the single-project boundary editor and refresh project-access data with agent-detail updates.
Verified head:
|
||
|
|
5061ab7b35 |
perf(ui): speed up task and inbox cold opens (#17756)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Task lists and inboxes are the main entry points to that work. > - Cold opens fetch overlapping task lists, task descriptions, and run details before useful rows settle. > - Independent responses can insert rows above content that a person has started to read. > - This pull request loads a small task index first and adds details only for visible rows. > - It keeps row order and geometry stable while those details arrive. ## Linked Issues or Issue Description **What existing behavior does this improve?** Cold opens of Tasks and Inbox, including the shared navigation badge. **Subsystem affected** Server list reads, shared response contracts, and the React UI. **Current behavior** The badge fetches full task bodies. Mine fetches several overlapping lists. Historical diagnostics and row metadata add work before the first useful list. A fast failed-run response can appear before task rows, then move down when tasks arrive. **Proposed behavior** Load the selected inbox source and its required context together. Use an index without task descriptions or recovery diagnostics. Fetch diagnostic details for up to 50 visible rows. Keep skeletons, recovery indicators, external status, and live metadata in fixed space. **Reason and benefit** Reduce work on a cold open and prevent loading-induced row movement. On the same 100 local fixture tasks, the compact response was 262,441 decoded bytes and the index was 110,909 bytes. This comparison excludes compression and is not a page latency benchmark. **Breaking changes** Existing full and compact responses remain available. New index/row projections are opt-in and marked as partial data. Mine keeps its existing most-recent-100 display limit, now selected on the server. Existing filters and group preferences remain in the client. No database migration. **Additional context** Refs: #17593. Related: #13095, #17428, #13803. This change addresses collection overfetch and layout stability. It does not replace the blocked-inbox query work or the database activity-index work. ## What Changed - Add authorized index and row projections, with bounded task and parent ID batches. - Replace badge list downloads with unread IDs and aggregate counts. Preserve actor privacy, dismissals, and local archive behavior. - Load only the selected inbox source, plus bounded parent and failed-run context. Return only relevant failures from the bounded run window. - Batch hierarchy reads, including at most one authorized child per collapsed parent in one request. Collapsed markers do not consume the expanded row budget, and partial descendant counts are not shown as totals. Enrich visible rows without replacing membership, ordering, titles, or read state. - Reserve row geometry on desktop and mobile. Reveal the initial inbox only after its sources settle. Preserve legacy task-list reads. - Start collection module downloads during access checks. Keep partial rows out of the task-detail cache. - Keep ETags and concurrent request sharing for the new projections, but skip the short server response TTL so archive undo sees fresh state. ## Verification - On final head `ef6afb2a56`, the full CI workflow passed, including build, typecheck, server/workspace/runner suites, and all eight browser shards. A server shard reported **1,489 passing tests** before runner shutdown canceled the job; its single infrastructure retry passed. Both Greptile and Paperclip Review are **5/5**, with zero unresolved review threads. - The optional external **Entire Gates** check remains `unassessed` because it has no active assessed Change for this comparison. Entire is not set up in this checkout. The repository ruleset requires `ci / verify` and `ci / e2e`; both passed. No gate configuration was changed. - Passed workspace typecheck after the final API batching change. The full production build also passed on the final commit; the exact-retry E2E run built the shipped UI. - Passed token gates and map validation. The final batch-preview pass has 91 passing route/hierarchy/component tests, including privacy, request bounds, 30 collapsed parents in one read, and a 120-child parent alongside a sibling. - Passed the 166-test focused UI/inbox/badge run, 47 additional UI regression tests, and 34 issue-list route tests. The latest regressions cover low-trust agent badge IDs, cold company selection, 30 description-only Mine matches with archive actions, retrying optional row details, and collapsed/expanded siblings. - The full local `pnpm test:run` spanned the rebase and reported failures in five suites before it was stopped; it is not claimed as a complete pass. A fresh serial rerun of all five suites passed **452/452** tests (tool gateway, native resume, project repositories, workspace recovery, and runner selection). Full current-commit coverage is checked by CI. - Real browser: delayed index and row-detail responses on Tasks and Mine. The first placeholder and first row had the same origin and 44-pixel height. Twelve rows on each page had zero position, height, or title-width change after recovery details arrived. - Real browser: reviewed long titles and recovery status at a 390 by 844 viewport. Task text stays on one line and recovery uses a compact indicator. - Three fresh document loads per page on final commit `260893bf92`, with HTTP cache retained on a warm local development server: Tasks 1.031–1.190 seconds; Mine 0.999–1.193 seconds. Browser-control overhead is included. These values must not be compared directly with staging latency or the earlier local samples taken during a full test run. - The browser archive test exposed stale results after Undo. The new projections now bypass the server TTL; immediate-mutation regression tests pass. The final browser retry passed: Archive followed by Undo restored exactly one row and the badge count. - CI exposed a hook-order crash when company selection resolved after the first inbox render. The hook now runs before the empty-company return. All seven affected exact-retry and legacy-continuation browser scenarios pass locally after the fix. - Real browser review regressions: 97 description-only source matches retained Archive actions; deliberately failed optional row reads displayed a retry notice while all 12 observed row positions and heights stayed unchanged. Retry restored the recovery indicator. Network fault injection was removed. - The final production build and workspace typecheck passed. Final focused verification passed 153 UI/helper tests and 26 heartbeat privacy route tests. Final review regressions cover newer diagnostics arriving during the index read, reloading diagnostics when the same task ID changes version, optional source failure/retry without hiding available rows, and required external-status filter failure. The latest-failures route test verifies bounded selection, agent filtering, success suppressing an older failure, and private-run redaction. - Real browser: deliberately failed the run source, then retried it. Twelve available task rows kept the same position and 44-pixel height before, during, and after retry. No loading skeleton replaced them. Fault injection was removed. - Hierarchy review decision: the cold-open barrier stays because inserting ancestors or expanded children after revealing index rows would cause layout shifts. Existing hierarchy context now survives subsequent requests, with a regression proving a new ancestor read does not blank the list. The bounded recursive tree read can still add latency for unusually deep expanded trees. - Tasks now handles a failed external-status filter with an explicit error and Retry, suppressing a false empty state. All 52 Tasks component tests pass, including failure-to-success retry. One existing large-tree test timed out while workspace typechecking ran concurrently; the whole component suite passed when rerun without that competing work. Workspace typecheck, the full production build, and token gates passed for this fix. ## Risks - Saved filters and grouping still operate on the existing bounded collection. This is not a new global server pagination model. - Fixed row slots reduce available title width. Long titles remain accessible through task navigation. - Recovery and related diagnostics arrive after core rows. Their responses cannot replace ordering fields, and stale versions are rejected. - Index/row requests now revalidate against current data instead of a short server TTL. They still share concurrent reads and use ETags. - This has not been deployed by this pull request. Staging latency must be measured after deployment under comparable conditions. ## Model Used OpenAI Codex, GPT-6 family. The exact runtime model ID and context-window size are not exposed in this session. Used code editing, terminal execution, and real-browser diagnostics. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
a67a18c171 |
fix(tasks): hide empty message history disclosure (#17751)
## Thinking Path > - Paperclip helps people manage AI agents and their work. > - Each task page shows the instruction and saved conversation. > - Cold opens show recent content before older history. > - The page used any linked run as evidence of older messages. > - A task's first run therefore showed an empty More messages control. > - This PR shows the control only when the preview omits comments or runs. > - Fresh tasks stay clear, and older task history remains available. ## Linked Issues or Issue Description Refs: #17593. **What happened?** A fresh task with only its first run displayed More messages, even though there was no earlier history to load. **Expected behavior** Show More messages only when older comments or runs are omitted. Runs observed while the page stays open must not create a false disclosure. The output control also uses actual skipped bytes, so a growing run does not gain an empty output control. **Steps to reproduce** 1. Create a task and let its first run start or finish. 2. Open that task with a fresh application cache. 3. Observe the empty More messages control below its instruction. ## What Changed - Keep omitted-run evidence with the cached recent run window. - Use omitted comments or runs to decide whether to show More messages. - Preserve run retention, reconnect reconciliation, and expansion of real history. - Offer More run output when a single legacy log exceeds the compact byte window. - Keep first-run native diagnostics accessible through More task actions → Show task activity. - Add regression coverage and update the task feature map. ## Verification - Passed the existing 9,168-test UI suite across 794 files, then all 504 focused task-detail, history-window, real thread, and log-transport tests after adding the activity-menu regression. - Passed workspace build, workspace typechecks, token gates, and map checks. - Reproduced the bug in the earlier UI using a disposable local task. The corrected UI hides the control with zero runs or only the first run. - In the local browser, expanded a long task to all 80 comments. The latest answer appeared once and the disclosure disappeared. No console warnings or errors occurred in that journey. - Expanded a saved 111 KB legacy log through More run output and opened its earlier activity in the local browser. - On a single saved native run, verified no More messages control. Used Show task activity to reveal its earlier tool output; the latest answer remained visible exactly once, with no console warnings or errors. - The first broad local run stopped because the fresh dependency install lacked PostgreSQL library symlinks. The normal package setup repaired that environment issue. - The next broad run hit one workspace-runtime timeout. Its focused rerun passed with unchanged server source; the original failure remains recorded. Stopped the already-failed broad runner after the previous revision passed full PR CI. All final-head build, typecheck, test, and policy CI jobs passed. Both automated reviewers scored the final head 5/5, with no unresolved threads. The separate Entire Gates check is pending because the PR has no active assessed Change for its current comparison. The installed Entire CLI reports no linked project trail and exposes no Change-assessment command; no gate or repository settings were altered. Browser verification used this branch's UI with the existing disposable test-drive API. No agent execution was started. ## Risks Low risk. This changes the recent run cache shape and the disclosure condition. The full run cache remains an array. Tests cover first-run states, observed new runs, omitted older runs, expansion, and reconnect reconciliation. No schema or API changes. A separate run-output control preserves access to a single truncated legacy log. The task menu preserves first-run native activity access without implying older messages exist. ## Model Used OpenAI GPT-6 through Codex, with code execution and browser tools. A more specific model ID and context-window size are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
df5a78cf91 |
fix(ui): keep iPhone task chat stable while typing and streaming (#17232)
## Thinking Path > - Paperclip keeps human-agent conversations attached to tasks. > - People need to read and reply comfortably from a phone. > - The mobile task page scrolled the document and positioned its composer with a sticky navigation offset. > - Safari's keyboard resize and later focus pan could move that document again, causing overlap, gaps, and jumps while editing. > - This change gives mobile and desktop the same message scroller and a normal flex footer. > - CSS owns the layout. A small VisualViewport adapter handles the visible height and Safari's stale document focus scroll. > - Streaming no longer measures every historical row while following the bottom. ## Linked Issues or Issue Description Fixes https://github.com/paperclipai/paperclip/issues/16497 Related: https://github.com/paperclipai/paperclip/pull/15245 also addresses keyboard positioning. This change additionally removes mobile document auto-follow and reduces historical-row measurement work. ## What Changed ### One scroll owner and a natural-flow composer Before: ```text Document scroll + mobile auto-follow └─ Conversation + sticky composer + animated navigation offset ``` After: ```text Height-constrained conversation shell ├─ Header ├─ Message scroller — owns follow/reading position └─ Composer — normal flex footer Navigation stays at the layout viewport bottom, behind the keyboard ``` - Reuse TaskMessageScroller on mobile. Delete the separate 136-line useWindowAutoFollow implementation and its superseded tests. - Keep the composer in normal flex flow. Remove its sticky bottom positioning and navigation-offset animation. - Constrain the mobile conversation with CSS. Classic tasks and other pages retain their existing layout. - Add a 47-line useMobileVisualViewport hook. It changes shell height on resize, not on typing or incoming messages. It never translates the shell or hides navigation. - Reject Safari's stale document focus pan only for an unzoomed, keyboard-open conversation. Inner message and editor scrolling stay native. - Keep a saved reading anchor when reading older messages. Skip historical-row measurements while following the bottom. - Update tests and the existing mobile streaming fixture. Keep only two layout-contract sentences in DESIGN.md. **Scope:** 19 files, +367 / -482 lines: 115 fewer lines overall. Production UI/CSS alone is +158 / -190 lines. No API, database, or dependency changes. ## Verification Bottom-follow is also saved explicitly for Back navigation. A new regression covers returning after rotation changes message wrapping, without restoring historical-row scans. ### Physical iPhone acceptance Tested on an iPhone 15 Pro running iOS 26.7.1. The reporter confirmed: - Opening the keyboard positions the composer correctly immediately, before any typing. - The installed web app works. - Long drafts, insertion, deletion, and sending are acceptable. The reporter described long drafts as not perfect but good enough. - Reading older messages during incoming output preserves position; returning to the bottom resumes following. - Rotation, keyboard close/reopen, and attachment/picker transitions work. Remote inspection corroborated the corrected open-keyboard state: visible height 358px, composer bottom 358px, document scrollY 0. Navigation remained display:block at y=631px, behind the keyboard. Earlier candidates failed device testing. The decisive trace showed a correct viewport resize followed about one frame later by a stale 337px native document focus pan. Typing caused Safari to correct it. Tests now cover that event ordering, the reverse ordering, and zoom panning. ### Performance evidence The existing TaskChatPerfHarness supplied 200 historical responses, 4,000 collapsed tools, and 30 updates at 100ms intervals. | Measurement | Before | After | | --- | ---: | ---: | | Historical row geometry reads | 6,000 | 0 | | Renderer main-thread work | 331.2ms | 273.5ms | | Largest task | 27.1ms | 12.3ms | This is one instrumented Chromium development run on the Mac, not a phone benchmark or a statistical speedup claim. The zero-row-measurement result also has a regression test that failed with 6,000 reads before the change. To reproduce, serve ui/tests/task-chat-perf.html with the UI Vite server. Record 30 streaming updates at the bottom. Inspect TaskMessageScroller and row getBoundingClientRect calls. Existing historical-render tests also confirm that unchanged Markdown does not reparse on live-tail updates. ### Automated and full-app checks - [Current-head CI](https://github.com/paperclipai/paperclip/actions/runs/39862524031) is green: 54 successful checks and 2 skipped checks. Greptile rates the current head 5/5, confirms the Back-navigation fix, and has no unresolved findings. - **601 focused tests pass** across the task page, layout, composer, scroller, viewport adapter, and historical-render coverage. - UI typecheck and production build pass. - Token gates, Storybook catalog checks, and catalog/map structural tests pass. - Independent review of the final source tree passed with no findings. - The full source app ran on macOS with an isolated database and saved conversation history. A reply sent through the real UI persisted after reload. Provider execution was not part of this layout test. - **Full local repository checks did not pass.** Build/typecheck stop at missing Rust cargo. The full test run reported 142 failed server tests and 3 failed suites; missing cargo is confirmed in those three suites. The other server failures were not diagnosed in this UI task. Current-head CI now supplies the repository-wide evidence; these local failures remain disclosed. ## Risks - Mobile conversations now share the desktop scroll owner. Navigation, loading, history restoration, and reading-position tests cover that change. - The keyboard-state threshold is a 120px viewport reduction. Accessory-only keyboards retain the normal navigation spacing. - The document-scroll fallback is scoped to rendered conversations with an open keyboard at scale 1. It does not handle inner scrolling or prevent zoom panning. - Long-draft behavior is accepted, with minor polish still possible. - The UI change is reversible and requires no data migration. ## Model Used OpenAI GPT-6 Astra, exact model ID gpt-6-astra, through OpenCode. Capabilities used: reasoning, code editing, tests, Chromium performance tracing, and Safari remote inspection. The harness does not expose the context-window size. An independent general-purpose subagent reviewed the final tree; its serving model ID was not exposed. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with Fixes / Closes / Refs OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal Paperclip ticket id or instance-derived details - [x] I have run focused tests locally and they pass; repository-wide failures are disclosed above - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
d64cb7be52 |
fix(ui): identify accounts in AI connection choices (#17738)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agent settings select an authorized AI account independently of the harness and model. > - Multiple accounts can have the same provider name. > - The account picker and legacy adoption dialog showed only that name. > - Operators could not distinguish a personal API key from a shared subscription during credential repair. > - This pull request shows the existing sign-in method, sharing scope, and available account identity before selection and adoption. > - Operators can select the intended account while the existing access and validation checks remain effective. ## Linked Issues or Issue Description Refs #14970 for the shared account selection control. No duplicate account-identity repair was found. **What happened?** Two authorized OpenAI accounts appeared as identical `OpenAI` choices. The adoption dialog repeated that ambiguous name. The list response already contained the account method, scope, and identity, but the UI omitted them. **Expected behavior** An operator can distinguish a personal API key from a company-shared subscription and confirm the selected account before saving. **Steps to reproduce** 1. Make a personal OpenAI API-key account and a shared OpenAI subscription available to an agent. Give both the name `OpenAI`. 2. Open Harness / Runtime and choose a managed connection for a legacy agent. 3. Inspect the two choices and the adoption confirmation. **Paperclip version or commit** Reproduced on master `a1f77821b9cd5c9c846fdf7a0fa5cc620ad2b6bb`. **Deployment mode** Hosted staging and the source UI regression. ## What Changed - Show the sign-in method, personal/shared scope, and available account or owner identity in connection labels. - Use the same label in the selected value and legacy adoption confirmation. Match the confirmation to both the connection and grant. Wrap dropdown choices so narrow screens retain the account identity, and expose the full selected label in the trigger title. - Add a behavioral regression with duplicate provider names, exact grant selection, and disabled unavailable accounts. - Update affected Storybook interaction selectors, the account guide, and the agent verification recipe. ## Verification - Before the fix, the new regression fails because duplicate accounts have no distinguishing metadata. The other 13 field tests pass. - After the fix, all 67 tests in `ui/src/components/ai-connections` pass. The regression selects the exact personal grant and keeps the unavailable option disabled. - `pnpm -r typecheck` and `pnpm build` pass locally. The full `pnpm test:run` command was stopped after embedded PostgreSQL failed to initialize after five attempts in an unrelated native-runtime suite. Its log is retained. Current-head CI partitions must establish full test coverage. - Token gates, map checks, Storybook catalog checks, and all 30 map/catalog contract tests pass. - In local Chrome, the existing production-component Storybook dropdown shows method and scope. Its nine interaction steps pass, as do all 19 steps in the new-agent connection-modes story. At a 320-pixel preview width, two shared OpenAI subscriptions show their distinct account identities in full, including during keyboard selection. These fixtures do not establish provider authentication. - Separately, the staging credential-repair workflow validated an existing authorized shared OpenAI connection, persisted the agent binding across reload, and resumed the original task into real provider/tool execution. This configuration recovery does not deploy this UI patch or establish task completion. - All CI completes on final head `a283bda2ad2f026f4f3c0fee03bf2962b0ad6e02`: 55 successful checks, the neutral Paperclip review, and two intentionally skipped Storybook checks; no pending or failed checks. This includes the partitioned tests, typecheck, build, runner suites, canary, and eight browser shards. Greptile and Paperclip review both rate this exact head 5/5 with no unresolved findings. [CI run](https://github.com/paperclipai/paperclip/actions/runs/40338613167). - The review's selected-trigger truncation finding is fixed in the final head. Its title assertion failed before the fix, and all 67 account-selection tests, UI typecheck, and token gates pass afterward. ## Risks - Labels are longer and can truncate in narrow selected-value controls; the trigger title exposes the complete label. Dropdown choices wrap, and the adoption dialog uses the complete label. - The UI uses existing authorized account metadata. It adds no credential reads, access grants, provider fallback, or account selection policy. ## Model Used OpenAI Codex (GPT-6). The exact serving model identifier and context window are not exposed in this session. The agent used code editing, terminal tests, and browser tools. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
a1f77821b9 |
perf(tasks): show recent conversation before historical activity (#17593)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - A task page must show the instruction and current conversation
quickly.
> - The current page waits for related task data and historical run
transcripts.
> - These reads grow with task history, even when the reader only needs
the latest answer.
> - This pull request gives cold opens a small initial view and loads
older history on demand.
> - Messages and runs observed while the page stays open remain visible.
> - The benefit is a readable task before historical diagnostics finish
loading.
## Linked Issues or Issue Description
Related: #14667 and #16229. The first changes the reveal gate and scroll
anchors. The second adds general history pagination. This PR adds a core
task read and a folded recent-conversation view. It preserves the
default full-read API contracts. The shared files will need coordination
if either related PR lands first.
**What existing behavior does this improve?**
Cold opening an ordinary task with a long conversation or large run
logs.
**Current behavior**
Task enrichment and historical transcripts delay the readable
conversation. A cold open can fetch several megabytes of tool activity
before revealing saved messages.
**Proposed behavior**
Show the task instruction, recent saved replies, latest human input, and
the latest run's conversation data first. Fetch older messages and full
run activity when the reader chooses **More messages**. Retain new
messages while the page stays open.
## What Changed
- Add an authorized core issue view that skips related enrichment. Keep
enrichment on the existing detail read. Share task mutation, rollback
and invalidation updates with the core cache.
- Add a bounded recent-comment read. Preserve the first human
instruction when no description exists, including legacy rows with a
NULL author type. Keep company and task access checks and comment
redaction.
- Add optional recent activity and run-summary views. Fetch original
input receipts for visible comments separately so delivered messages
stay out of the queue. Reconcile watched unfinished runs after a
reconnect beyond the preview window, removing deleted runs after
reconciliation.
- Filter the latest native run's initial events to assistant messages,
request lifecycles and terminal results. Full event reads remain
available on expansion. Legacy fallback reads use a small tail extended
to the first complete record. HTTP cancellation aborts the storage read.
- Retain observed messages across cursor catch-up and new runs. Apply
local cancellation and deletion to both caches and their task aliases.
Refetch locally seeded history pages on expansion. Preserve expansion
across identifier and UUID links. Keep deep links, classic tasks and
Agent Chat on their existing full-history path.
- Update API documentation, design guidance, capability maps and
regression coverage.
## Verification
- Final acceptance on `9ea0b15ae44d9f6d2c9a9f824b4835f299f92979`: all CI
gates passed, including server/UI tests, all eight browser shards,
runner checks, full typecheck and build. [Final CI
run](https://github.com/paperclipai/paperclip/actions/runs/40326990328).
GitHub reports 55 successful checks, two intentionally skipped checks,
and one neutral Paperclip Review check described below. No checks are
pending or failed; Greptile is 5/5 and no review threads remain open.
- October 26 merge update: merged current `master`. The only conflict
was in task-page imports; both the compact-history hook and the new
live-update hooks remain. All CI tests and build jobs passed on
`044fd6733d`. Fresh review found canceled-comment cache drift, legacy
human-comment filtering, send-then-expand truncation, and partial legacy
log records. These defects were fixed in `af3d66a5bd`.
- Review-fix verification: 470 tests pass across ten affected suites,
including all six PostgreSQL cold-open tests without a helper override.
Cancellation/delete and send-then-expand regression tests failed before
the fixes and pass afterward. Coverage includes task identifier/UUID
reopen, stale in-flight reads, legacy NULL author types, local-file and
object-storage tails cut inside UTF-8 text, route forwarding, and
request cancellation. Full workspace typecheck and production build,
token gates, map validation and diff checks pass.
- Follow-up review found that a failed expanded legacy read lost its
record-alignment state on retry. `9ea0b15ae4` commits the expanded
window only after a successful read. The new regression fails before the
fix and passes afterward; all 19 transcript tests, UI typecheck, UI
build and token gates pass. Greptile reviewed this commit at 5/5 with no
actionable findings, and all review threads are resolved.
- The final Paperclip Review check ended neutral because its execution
did not complete; no passing Paperclip assessment is claimed. Its
earlier four concrete findings were fixed and regression-tested.
Greptile and the security scans completed successfully on the final
commit.
- The preceding `af3d66a5bd` CI run was canceled when superseded by the
retry fix. Its server shard 11 check briefly reported failure, but the
job API records cancellation and its test step passed all 1,750 tests.
This superseded run is not used as final CI acceptance.
- 549 focused tests pass on the final implementation across nine task
UI, activity-route, OpenAPI and PostgreSQL suites. These cover pending
history, desktop/mobile visibility, expansion, retained runs, message
bursts, cancellation recovery and queued-comment removal in both views.
- Legacy expansion keeps the latest answer visible while fetching and
deduplicating older output.
- Five PostgreSQL tests pass for core access denial, recent comments,
missing-description instructions, event paging and bounded activity/run
reads. macOS could not start another PostgreSQL cluster because it
exhausted its semaphore limit. These tests used a separate disposable
database on an existing local server through a temporary test setup
override. The helper was restored afterward.
- Full workspace typecheck and build pass with the final state fixes, as
do token gates and capability-map validation.
- Token gates, capability-map validation and `git diff --check` pass.
- Browser proof used a disposable task with 80 comments and six large
run histories. The cold view showed the instruction and recent exchange.
**More messages** revealed older comments. Navigation away and back
preserved expansion.
- Local HTTP sample: core 50 ms, recent comments 24 ms, recent run
summaries 17 ms. The latest native conversation response was 839 JSON
characters / 8 ms; its full event response was 1,099,005 / 86 ms.
Browser content paint was 1.34 seconds with development assets cached.
These are local observations, not staging latency claims.
- The first CI run passed every job except four board-send browser cases
and the review threshold. Those browser fixtures only mocked the old
comments endpoint; they now serve both recent and full reads, retaining
all message and attachment assertions. Both initial review findings were
fixed with regression tests. The next CI run passed every job. The
deeper review identified core-cache mutation, older delivery receipt and
retained run-status gaps; those are now fixed with regression coverage.
Final review is 5/5 with zero unresolved findings. Final-head CI
initially failed one unchanged runner shutdown test
(`runnerd-codex-transport.test.ts`, timeout-attachment case) with
`NativeSessionCloseUnrecoverableError`; all other CI jobs passed. The
same runner code passed on
|
||
|
|
5d2515e520 |
Simplify agent harness configuration choices (#17722)
## Thinking Path
> - Paperclip manages AI agents and their work.
> - Users choose a harness in agent setup and configuration.
> - Supported harnesses already determine their native Runner profile.
> - A second ACP agent selector lets users make a conflicting choice.
> - The harness list also shows unavailable options marked Coming soon.
> - This PR removes these extra choices and keeps each harness's
settings.
## Linked Issues or Issue Description
Refs #17142 and #17120. Related runner defaults work: #15422.
**What existing behavior does this improve?**
The Harness dropdown and native agent configuration form.
**Current behavior**
A Pi or Claude agent shows an ACP agent selector below Harness. Users
can select a different agent in that second control. The Harness list
also includes disabled Coming soon entries.
**Proposed behavior**
Use Harness as the only agent choice when it determines the Runner
profile. Hide unavailable entries from its list. Keep the generic
advanced Runner selector available where no parent harness determines
the profile.
**Reason and benefit**
Users choose the harness once. The form no longer offers a conflicting
ACP agent choice or an option they cannot use.
**Breaking changes**
No API or stored configuration changes. Unavailable harnesses are
omitted from the list; existing saved values still display.
## What Changed
- Hide the ACP agent selector when the parent Harness control determines
the Runner profile.
- Remove Coming soon options and their unused disabled-state rendering
from the Harness dropdown.
- Preserve saved Process and HTTP selections during unrelated edits
while omitting them from new choices.
- Document the field visibility contract.
- Cover new and saved Claude, Pi, Codex, and OpenCode forms. Check that
Pi thinking controls remain and an unrelated name edit does not rewrite
Runner configuration.
## Verification
- Passed after rebasing onto master: 199 tests across
AgentConfigForm.render, codex-local/config-fields, and adapter config
sections.
- Passed: UI TypeScript check, UI production build, token gates, and git
diff --check.
- Live browser verification passed for the Pi configuration page before
and after rebase. Harness remains Pi, ACP agent is absent, and the
original model and thinking level remain. The open Harness list contains
no Coming soon, Process, or HTTP entries.
- Dropdown regression cases open Harness, check the supported options,
exclude Coming soon/Process/HTTP options, and preserve saved Process and
HTTP configuration through a name-only save.
- Passed on final commit
|
||
|
|
5cea9c7c0e |
fix(ui): show eligible wake targets when resuming tasks (#17521)
## Thinking Path > - Paperclip manages agents and their assigned tasks. > - A task pause controls execution without changing task status. > - Resume can remove that pause and request work from eligible assignees. > - The preview counted blocked tasks and former executors as wake targets. > - The release route correctly skipped those targets, so the dialog promised work that did not start. > - Resume also trusted stale pause snapshots after tasks were reopened. > - This PR aligns preview with execution eligibility and rechecks current task state when releasing a pause. ## Linked Issues or Issue Description **What happened?** Pause an assigned blocked task, then open Resume. The dialog says that one task will resume and offers to wake one agent. Applying it only removes the pause. The route skips blocked and backlog tasks. A former executor can also inflate the wake count after reassignment. **Expected behavior** The dialog must distinguish removing a pause from starting work. Its wake count must use the current assignees and statuses accepted by the release route. Blocked work must stay blocked. **Steps to reproduce** 1. Open an assigned blocked task. 2. Choose Pause work, then Resume task. 3. Inspect the wake count and apply Resume work. Related runtime recovery work is tracked separately in #17097 and #17439. This PR does not change remote execution recovery. ## What Changed - Share the resume status list between preview and release. Count only current assignees on todo, in-progress, and in-review tasks for resume wakes. - Explain that Resume removes the pause. Show the existing preview warnings, including tasks that remain idle. - Disable and uncheck the wake option when no agents qualify. Send the same choice to the server. - Reevaluate previously skipped pause members after reopening or releasing another hold. Retain active-pause and unsafe-execution guards. - Add real PostgreSQL and HTTP-route regressions plus browser coverage for both task interfaces. Keep draft, ancestor-pause, and Stop/reconciliation coverage. - Update the task coordination maps. Add an opt-in dedicated test database URL for hosts where embedded PostgreSQL cannot start. ## Verification - Final head `9548eb16736f632cc111a5c13a9a994ec1d95a13`: all 55 completed checks pass, with two optional Storybook checks skipped. [CI 40188094904](https://github.com/paperclipai/paperclip/actions/runs/40188094904) passes, including typecheck, build, all general/serialized suites, and all eight E2E shards. Greptile is 5/5 on this commit; the reopened-task finding is fixed and resolved. - Red: the real PostgreSQL regression receives three agents instead of the one eligible current assignee on the original code. - Green: all 27 tree-control service, route, and unit tests pass. They cover current assignees, blocked/backlog exclusions, reopened tasks, company boundaries, remaining pause holds, and execution blockers. - The reopened-task route regression fails on the previous implementation: skipped members never reach preflight/wake, and an unsafe replay releases the hold instead of returning 409. All cases pass with the fix. - Browser: all five applicable cases pass together (90 seconds): blocked-work resume in both interfaces, draft/ancestor-pause cases in both interfaces, and the process Stop/pause/reconciliation/restart/cancel lifecycle. The optional native-runner fixture is skipped locally because its fixture binary is not configured. - All 157 task-page component tests pass on the prior commit; subsequent changes affect the server route and Stop fixture only. - `pnpm -r typecheck` and `pnpm build` pass before rebase, and CI typecheck/build passed on the previous PR commit. Server typecheck passes again after the route fix. The final-head CI run also passes these full checks. - `node scripts/check-maps.mjs`, `node scripts/check-token-gates.mjs`, and `git diff --check` pass. - Full `pnpm test:run` was attempted but did not complete: this host cannot initialize embedded PostgreSQL, and unrelated workspace-runtime tests timed out. The focused database tests and E2E suite use disposable PostgreSQL 18 instead. All general-test and serialized-test CI shards passed on the previous PR commit; the final-head CI run also passes every test shard. - The first CI run caught the existing Stop test trying to check a disabled wake option for blocked legacy work. It now asserts zero wake targets and retains the no-execution-before-reconciliation checks. - Earlier E2E attempts exposed fixture problems: assignment started the fixture before it was paused, and the classic interface had two matching editor nodes. The fixture now enables dispatch after the hold exists and scopes the final assertion to the task composer. No product assertion was removed. ## Risks Resume preview is a snapshot. The release route still checks current status, assignment, and execution blockers. It does not bypass approval, budget, or recovery gates. Pause, cancel, and restore keep their existing affected-agent semantics. The test database override only accepts a dedicated database name ending in `_test`; it runs migrations before the suite and closes its clients afterward. ## Model Used OpenAI GPT-6 through Codex, with reasoning, repository tools, browser control, and code execution. The runtime does not expose a more specific model ID or context-window size. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
e335265568 |
fix(ui): stop idle task run polling with live updates (#17608)
Stop successful empty assigned-task run queries from polling only while the matching company and session connection is open. Preserve active, pending, failed, and disconnected cadence. Share one lifecycle refresh owner between the task and chat views, discover reviewer events without task identity, and refresh after older in-flight reads settle. All 175 focused tests, 9,079 UI tests, build, typecheck, exact-head Greptile 5/5, and required CI pass. Regression mutations catch reviewer discovery, duplicate reads, readiness, failure state, missing refreshes, and scope cleanup. Earlier E2E cleanup deadlock and server cleanup timeout remain documented; failed-only reruns passed on their same commits. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
6aa711f6c6 |
fix(ui): avoid broad task refreshes after known run progress (#17602)
Use the existing live-status cache patch result to skip redundant task and history reads. Keep unknown-run discovery, lifecycle, activity, visibility, and reconnect recovery. Verified with full build and typecheck, 9,047 UI tests, final context tests and counterfactual broad-refetch and missing-fallback failures, complete exact-head CI, and Greptile 5/5 Medium with no unresolved comments. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
d0c8f0b090 |
fix: explain project access denials and add an authorized repair path (#17509)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Low-trust agents may read only the projects in their allowed scope. > - Workspace setup correctly stops a task outside that scope. > - The task previously showed a generic failure, and agent settings did not offer an additive repair. > - This pull request explains the denial and lets authorized operators add projects while preserving other restrictions. > - The saved task then offers an explicit retry. Saving access does not start work. ## Linked Issues or Issue Description **What happened?** A project access denial appeared as an ordinary failed attempt. Operators could not add a second allowed project from agent settings. **Expected behavior** The task should explain the denied access and link to a working permission editor. The editor should preserve existing scope and restrictions, enforce operator authority, and retain drafts after a failed save. **Steps to reproduce** 1. Assign a low-trust agent to a task whose project is outside its allowed projects. 2. Let workspace setup deny project access. 3. Open the task, follow Manage project access, add the project, save, reload, and return to the task. 4. Confirm that the saved message remains and Retry task is a separate action. ## What Changed - Record a typed, non-retryable project denial before provider dispatch. Project denials do not enter automatic continuation or provider comment policy. - Project current and historical setup denials into a safe task notice. Keep unrelated failures, prior assignees, and approval/pause/budget gates separate. Recheck current project authority, including standard trust and root-issue grants. Accepted retries keep their working state. - Add board-only project-access reads and additive saves under the agent row lock. Enforce company scope, agent-management authority, pending-approval restrictions, and an audit record for new additions. - Add the production notice and searchable multi-project editor, including read-only, saving, cancellation, and failed-save states. Preserve the return-to-task query through canonical agent redirects. - Register board-only project-access routes in OpenAPI with a strict request schema. - Add production Storybook examples and API/persistence/concurrency regressions. Retain the approved design snapshot and update the behavior maps and implementation contract. ## Verification - Passed: `pnpm -r typecheck`, `pnpm build`, `pnpm build-storybook`, `pnpm check:token-gates`, `node scripts/check-maps.mjs`, and `node scripts/storybook-catalog.mjs`. - Passed: 11 permission/projection tests and 30 run-completion tests against an isolated PostgreSQL database. These cover historical failures, concurrent additions, idempotent audit, preserved restrictions, foreign projects, read-only users, agent self-grants, and no automatic wakeup. - Passed: all 27 OpenAPI route tests, including route coverage and the new board-only request/response contract. - Browser: the real app displayed a historical denial; Manage project access opened the editor; saving retained the original project and survived reload; Return to task showed the ready notice. Saving created one audit event and zero runs. Explicit Retry returned 202 and reached the separate sandbox requirement, which remained enforced. No external provider was used. - All five production Storybook interaction checks pass: blocked task, save, cancellation, failed-save recovery, and read-only settings. These use fixture callbacks; durable authorization is covered separately above. - `pnpm test:run` was attempted locally but stopped after repeated embedded PostgreSQL startup failures caused by macOS semaphore exhaustion. Full-suite CI is required before merge. The separate UI suite passed all 9,095 tests. The 41 focused server regressions also passed after rebasing onto the latest master. A further 26 recovery-classification tests pass, including a red-to-green regression for automatic continuation after a project denial. ## Risks - No schema migration. The new endpoint only adds same-company project IDs and preserves the rest of the stored policy. - The historical notice recognizes one exact setup denial message. It does not display arbitrary run errors or disclose a different source project's identity. - The retry still passes all current admission and isolation checks. The notice does not promise that other execution requirements are satisfied. - Related open work: #13309 covers inherited secret restrictions; #11234 covers the broader repository catalog. This change does not replace either policy surface. ## Model Used OpenAI Codex (GPT-6), with code execution and browser tools. The precise runtime model ID and context-window size were not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass (focused server and full UI suites; full-suite infrastructure limit above) - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
0eb2c964a7 |
fix(agents): allow runner qualification with agent configuration permission (#17448)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agent owners configure the harness and computer used for that work. > - A legacy runner upgrade must first qualify an unverified sandbox. > - The upgrade called an instance-admin probe, so a company owner with agent configuration permission received HTTP 403. > - This pull request qualifies the saved computer through the agent's existing configuration authorization. > - Company owners can complete the upgrade while general instance environment management stays restricted. ## Linked Issues or Issue Description Refs #17361. Related: #17122. **What happened?** Upgrade runner displayed for an existing Claude agent on a Daytona Paperclip Computer. Clicking it returned “Instance admin access required” for a cloud company owner. The agent remained on the legacy runner. **Expected behavior** A caller permitted to update the agent can qualify that agent's saved computer and upgrade. Instance-admin access is not required for this agent-scoped operation. **Steps to reproduce** 1. Sign in as a cloud company owner with `agents:configure` and no instance-admin role. 2. Open an existing legacy Claude agent on an unqualified Daytona snapshot. 3. Select Upgrade runner. ## What Changed - Add `POST /api/agents/{id}/qualify-runner` with the existing `agent_config:update` guard. - Reuse the server's effective environment resolver. The submitted environment ID only detects stale state; it cannot select a different computer. - Preserve company binding checks, check binding again at lease acquisition, and record agent-scoped audit activity. - Return qualification status and the lease receipt without instance-level provider metadata or raw provider errors. - Use the new endpoint for the existing-agent upgrade. Keep the generic environment probe restricted to instance admins. - Disable Upgrade runner when an unsaved computer change resolves to a different target, with a save-first explanation. Other draft settings still accompany an upgrade. - Add real-database authorization regression tests and update the API contract and access maps. ## Verification - Red: the existing UI called the instance-wide probe and failed the new agent-scoped call assertions in eight upgrade cases. - Green: 349 related route, provider qualification, runner selection, and UI tests passed. - Green: 12 authorization cases passed with real PostgreSQL, real HTTP routes, real saved role grants, and a simulated provider boot. They cover the cloud owner, removed grants, foreign agent/computer, inherited targets, stale target, invalid body, archived/local target, redacted failure, audit scope, and unchanged agent settings. - Review regression: two cases first reproduced the enabled upgrade button after an unsaved computer change; both now pass, along with all 168 related UI tests. Qualified/unqualified computers and restoring the saved selection are covered. - All 26 OpenAPI cases passed; the 12 real-database authorization cases also passed after rebase. - The host exhausted PostgreSQL semaphores. For the 12 cases, a temporary local-only setup used disposable PostgreSQL 18 in Docker instead of the embedded database launcher. The committed tests use the normal embedded database helper. No authorization decisions were mocked. - `pnpm -r typecheck`, `pnpm build`, `pnpm check:token-gates`, map validation, module-boundary validation, and `git diff --check` passed. - `pnpm test:run` was attempted but did not establish a full local pass: the host could not start embedded PostgreSQL clusters. All current-head CI gates passed, including the full suite in CI. The commitperclip review workflow timed out before reporting any executed steps on its first attempt and passed on one retry. - Fresh staging acceptance remains pending deployment. Verify persisted native configuration and a successful runtime test on the existing Daytona computer after merge. Earlier live Daytona proof from #17361 is separate evidence. ## Risks - Qualification can start a fresh, temporary sandbox. It uses the existing probe lifecycle and cleanup contract. - The new path must remain scoped to the saved agent and its company. Denial and redaction tests cover that boundary. General instance probe authorization is unchanged. - No migration, role change, credential change, or automatic agent upgrade is included. ## Model Used - OpenAI GPT-6 through Codex, with reasoning, code execution, and browser tools. The exact deployed model variant and context-window size were not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
f66d590899 |
fix(ui): open the new-task form immediately (#17041)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - People use New task to send work to an agent. > - The board currently downloads the task dialog code after the first click. > - This shows a loading window before people can enter their request. > - The form already loads agent and project choices after it opens. > - This pull request loads the task dialog code with the board. > - People can start writing immediately and keep their text as choices arrive. ## Linked Issues or Issue Description Related change: #16849. Commit `fa50cab5685b9cdbb26ad9c610cc5b6c373d3ff4` added the deferred dialog and its loading window on October 19, 2026. **What happened?** The first New task click shows “Loading new task…” while the browser downloads the dialog code. **Expected behavior** The form opens on click. Agent and project choices load in place. Text entered during those requests stays in the form. **Steps to reproduce** 1. Open the board in a fresh browser session. 2. Select New task before its code is cached. 3. Observe the loading window before the form appears. **Paperclip version or commit** Source baseline: `8b4ab65b1c3d863d282752e83307943720a5c85c`. **Deployment mode** The browser code applies to local and hosted boards. Verification used a source checkout. ## What Changed - Import NewIssueDialog with the board. Keep the existing mount and draft lifecycle. - Add a first-open test that fails if the form waits for an asynchronous render. - Cover text entry during delayed agent and project requests and defaults that arrive later. - Document the behavior and its verification recipe. ## Verification - Regression proof: the first-open test failed before the import change and passed after it. - All 125 tests in BoardDialogs, DeferredOverlay, NewIssueDialog and Layout passed. - The production UI build and UI TypeScript check passed. The typecheck passed with `NODE_OPTIONS=--max-old-space-size=2400` after the competing test process was stopped. - Token gates, map validation and Git diff checks passed. - The first UI typecheck could not resolve the unbuilt local plugin SDK. The SDK was then built. - Full typecheck and build attempts hit the sandbox's 4 GB memory limit when run with the full test suite. Two later UI typecheck attempts also hit that limit during other validation. The cgroup recorded four OOM kills in total. The full repository test attempt and a broader UI test attempt were stopped. No complete suite result is claimed. Serial repository typecheck reached the missing Rust `cargo` executable. Full CI passed on head `9dde4bc`; local limits remain recorded here. - First CI run at `e5a99b8`: typecheck, build, all unit-test shards and seven browser shards passed. Browser shard 2 failed at `chat-adapters-ui-providers.spec.ts:185`, waiting for Slack setup Success after reload. The saved page showed the working connection and Continue button. The cause is not confirmed; this failure is retained for follow-up. [Failed job](https://github.com/paperclipai/paperclip/actions/runs/39522214527/job/118968542923). - Removed the added import comment after Greptile review. Head `9dde4bc` changes only that comment. The review thread is resolved. Fresh CI passed on head `9dde4bc`. Greptile reviewed that exact head at 5/5 with no open findings. All eight browser shards passed, including the earlier Slack failure. The earlier failure remains unexplained; the only intervening code change removed a source comment. A passing retry establishes recovery, not its cause. - Component tests use mocked directory requests. No deployed latency or browser persistence claim is made. Latest CI: [run 39523376437](https://github.com/paperclipai/paperclip/actions/runs/39523376437). Reviewed head: `9dde4bc0caa3556e315a2fc197268b7c9879efa4`. ## Risks - Task dialog code is part of board startup again. This adds its dependencies to the initial code graph. No startup latency benchmark is claimed. - Other creation dialogs retain their existing lazy imports and loading behavior. ## Model Used OpenAI Codex, GPT-6, with reasoning, repository tools and code execution. The runtime does not expose a more precise model ID or context-window size. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
87bf89756e |
fix: support Daytona runner upgrades and ignore obsolete Claude options (#17361)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Existing Claude and Codex agents can upgrade to Paperclip Runner. > - A Daytona computer needs platform qualification before Runner becomes its default. > - The upgrade notice required that default, so it hid the action that could start qualification. > - Saved Claude turn limits also caused conversion to fail even though Runner can run without them. > - This pull request verifies the computer on click and ignores obsolete Claude options with a warning. > - Agents retain their model, account, environment, instructions, and permission policy. ## Linked Issues or Issue Description Related: #17122. **What happened?** A legacy Claude agent on a Daytona snapshot had no upgrade button until its environment had platform qualification. A saved `maxTurnsPerRun: 1000` then caused conversion to return HTTP 422. **Expected behavior** The upgrade action verifies a supported Daytona computer and converts the agent. Unsupported tuning options produce a visible warning and do not block execution. **Steps to reproduce** 1. Create a legacy Claude agent with `maxTurnsPerRun: 1000` on an active Daytona snapshot. 2. Open Runtime before the environment has platform qualification. 3. Try to upgrade to Paperclip Runner. **Paperclip version or commit** After #17122, reproduced against `9c442cf48e`. ## What Changed - Offer upgrade on probe-capable Daytona snapshots and immutable sandbox images. Perform the public environment probe only after a click. Save after fresh adapter discovery confirms support. - Resolve the actual computer for explicit, instance-default, and hidden managed environments. Preserve pending edits and reject stale probe results. - Ignore Claude `maxTurnsPerRun`, `chrome`, `warmHandleIdleMs`, and `acpWarmHandleIdleMs`. Return structured warnings from create, hire, and update. Show warnings in Runtime and after a save. - Keep validation for commands, credentials, filesystem, network, and permission settings. - Retain the legacy turn limit in the existing live conversion fixture. Update regression tests, upgrade stories, and capability maps. ## Verification - Red: the old route returns HTTP 422 for the saved turn limit; the old form hides the Daytona upgrade notice. - Green: 417 focused server and form tests pass. A further 188 tests pass after the review fixes. Qualification coverage includes failed probes, unsupported targets, changed settings, managed defaults, unsaved environment variables, and forced Kubernetes targets. - `pnpm -r typecheck` and `pnpm build` pass. Token gates, map checks, map tests, and Storybook catalog checks pass. - Real local Claude Opus 5.5 conversion and task pass, with the downloaded artifact checked against seeded source bytes, SHA-256, and Git commit. - Real browser upgrade and full Claude Opus 5.5 task on a disposable named Daytona snapshot pass at `b81cec7d8c`. The saved agent retains its model, high effort, credentials, timeout, and grace settings while dropping the turn limit with a visible warning. Exactly one successful run completed the task. The downloaded artifact matched independently seeded source bytes, SHA-256, and Git commit; the source was unchanged, no interactions remained pending, and the delivery link survived a browser reload. The snapshot used current runtime assets built from public source. The supplied Daytona account could not access the original staging snapshot, so this verifies an equivalent local fixture rather than that exact snapshot. Disposable test resources were cleaned up. - Earlier live attempts remain recorded: an image-based sandbox creation failed, and the first named-snapshot probe returned failure with unresolved provisional cleanup identity. Later named-snapshot probing and the task succeeded; the initial creation failures are not attributed to this PR or declared resolved. A separate attempt using the Oct 18 cached runtime failed the current provider-pack compatibility check; rebuilding the runtime from matching public source removed that mismatch. Owned resources were identified and cleaned up, with diagnostic databases retained. - 54 checks passed at `b81cec7d8c`, with no failed checks; Greptile and Paperclip Review both scored 5/5, with both review threads resolved. Master advanced during the live proof, so the branch was rebased with both sides of additive import/test conflicts retained. On the rebased head `2b74222b94`, 472 focused tests, UI typecheck, and UI build pass. All required CI gates pass; Greptile and Paperclip Review both score 5/5 on this head, with no unresolved review threads. The PR is mergeable. The serial local `pnpm test:run` was stopped after the CI test lanes passed; that local run is not claimed as a pass. ## Risks - An explicit upgrade can allocate a temporary probe sandbox and take several minutes. Probe failures leave the agent on its existing runner. - Ignored options no longer enforce a turn cap, Chrome integration, or legacy idle-time tuning. The UI warns about each active ignored option. - Unsafe or ambiguous execution settings still fail validation. This change does not weaken environment qualification or runtime artifact checks. ## Model Used OpenAI Codex, GPT-6, with reasoning, code execution, and browser tools. The exact deployment model ID and context-window size are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
e0d90339bf |
fix(runner): make task-capable plugin environments Runner-only (#17380)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - An environment plugin can run Paperclip Runner tasks through a `driver: "plugin"` environment. > - Core lets only the `paperclip_runner` adapter use a plugin environment. > - A Claude agent cannot get onto the Runner there. Runner selection needs a reported platform for Claude, and a plugin target reports none. > - The adapter Test route also checks the driver against the requested harness before it resolves the runner. > - This pull request makes task-capable plugin environments Runner-only and checks the Test driver after runner selection. > - The benefit is that Claude and Codex agents can use a Runner task environment, and the UI cannot produce a legacy agent there. ## Linked Issues or Issue Description Refs #17029. Refs #16978. **What happened?** A Claude Code agent with a plugin environment that runs Runner tasks fails the connection test. The error is: `Environment driver "plugin" is not allowed here. Allowed drivers: local, ssh, sandbox`. The Runner selector in Advanced shows Paperclip Runner as unavailable, so the user cannot fix the agent in the form. **Expected behavior** A Claude or Codex agent on that environment uses Paperclip Runner. The connection test passes the driver check. Legacy is not offered, because a legacy adapter cannot run on a plugin environment. **Steps to reproduce** 1. Install an environment plugin whose driver declares `supportsTasks: true`. 2. Create a plugin environment for that driver. 3. Open an agent with the Claude Code harness and select that environment. 4. Click Test. The test fails with the driver error above. **Agent adapter(s) involved** Claude Code, Codex (through Paperclip Runner). **Additional context** Two gates caused the failure: - `agentRunnerAvailability` requires a platform for `claude_local`. A plugin target is `{ driver: "plugin" }`, so Claude resolves to Legacy. - The Test route ran `assertAdapterTestEnvironmentForCompany` with the URL adapter type before `resolveNewAgentRunnerForCompany`. The plugin driver is allowed only for `paperclip_runner`, so the check failed before selection could change the adapter. ## What Changed - Runner target resolution marks a plugin environment as `runnerTasks` when its plugin manifest declares `supportsTasks` for the driver key and has the `environment.drivers.register` capability. The check reads the manifest only. Run admission still verifies a ready plugin and a live worker. - `agentRunnerAvailability` returns Paperclip Runner as the only runner for a `runnerTasks` target. It skips the platform check, because the plugin provisions the host and launches its own pinned Runner. Harnesses that the Runner does not support keep the Legacy result. - The adapter Test route runs the company-binding check first, as before. It runs the driver check after runner selection, with the resolved adapter type. The driver check still runs before secret resolution, leases, and the adapter probe. - A saved adapter that cannot run on the requested environment no longer keeps its saved execution in the Test route. It re-resolves its runner. - `assertAdapterTestEnvironmentBinding` is a new helper that holds the binding half of the guard. `assertAdapterTestEnvironmentForCompany` keeps its behavior and calls it. - The agent form switches a Legacy runner choice to Paperclip Runner when the selected environment offers no Legacy runner. The test and the save then send the Runner choice. - `docs/specs/agent-config-ui.md` records the Runner-only rule and the Run test order. ## Verification - `pnpm --filter @paperclipai/server exec tsc --noEmit` passes. - `pnpm --filter @paperclipai/ui exec tsc -b` passes. - Server suites pass: `agent-runner-selection.test.ts`, `agent-test-environment-routes.test.ts`, `agent-permissions-routes.test.ts`, `environment-selection-route-guards.test.ts`, `agent-harness-verification.test.ts`, `plugin-runner-task.integration.test.ts`, `adapter-routes.test.ts`, `adapter-auth-signal-routes.test.ts`, `agent-adapter-validation-routes.test.ts`, `agent-hire-ai-connections.test.ts`. - UI suites pass: `AgentConfigForm.render.test.tsx` and `NewAgent.test.tsx`. - New tests cover these cases: - A task-capable plugin target offers only Paperclip Runner for Codex and Claude. - Claude saves as `paperclip_runner` with ACPX on that target. - A driver without `supportsTasks`, a different driver key, a missing capability, an unknown plugin, or a malformed config keeps the existing plugin target. - The Test route checks the driver against the resolved adapter. - The Test route still rejects a plugin environment for a legacy adapter, before any secret resolution. - A saved adapter re-resolves only when it cannot run on the requested environment. - The form switches a saved or new Legacy choice to Paperclip Runner on a Runner-only environment. - I ran the new route and form tests against the old code. They fail without the change. - The full server `typecheck` script did not complete locally. Its Runner vendor step needs `cargo`, which this machine does not have. CI runs the full script. - I did not run a live plugin environment end to end. ## Risks - Behavior change: Codex on a task-capable plugin environment now offers only Paperclip Runner. Before, the selector also showed Legacy, but Core rejected a legacy save on that environment. No working setup loses an option. - The `runnerTasks` decision reads the plugin manifest. If the plugin is down, the agent still selects the Runner, and the run fails at admission with the existing plugin error. - The adapter auth-signal route still checks the driver with the requested harness. This PR does not change that route. - An explicit Legacy save through the API on a Runner-only environment still fails with the existing driver error. The UI no longer offers that choice. ## Model Used - Claude Opus 5.5 (`claude-opus-5-5`) wrote the change and the tests in Claude Code, with shell, file editing, and local test runs. - Claude Fable 5.1 (`claude-fable-5-1`) did the earlier diagnosis in the same session. - The session does not expose the context window size. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Paperclip <noreply@paperclip.ing> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
4d90634f74 |
feat(connections): add 1Password service-account connector (#17249)
## Thinking Path > - Paperclip lets people manage AI agents and govern their access to outside services. > - Apps connections keep provider credentials in the instance vault and mediate every action through grants, policies, and audit. > - Agents currently have no Apps connection for reading or managing 1Password items with an operator-supplied service-account token. > - 1Password supports this through its official SDK; its documentation MCP server does not expose vault operations. > - This pull request adds a one-field service-account connection and registers eight reviewed SDK actions through the existing native-provider catalog. > - Operators can select vault permissions in 1Password and agent/action access in Paperclip without installing a CLI or handing durable credentials to agents. ## Linked Issues or Issue Description Related: #16144 adds 1Password as Paperclip's secret-storage backend. This PR adds the separate Apps/tool-access flow with a per-connection credential; it does not change secret providers or use a server-wide ambient token. **Subsystem affected** Apps catalog, native tool-provider registry, and shared connection setup. **Problem or motivation** People need to paste their own `OP_SERVICE_ACCOUNT_TOKEN`, find official service-account setup instructions, and authorize agents to use the selected vaults through ordinary Paperclip governance. **Proposed solution** Add `1password/service-account`, with a password field labeled **Paste your 1Password Service Account token** and a link to [1Password's creation instructions](https://www.1password.dev/service-accounts/get-started#create-a-service-account). Use the pinned official `@1password/sdk` 0.5.0 for vault/item listing, item and secret-reference reads, and item create/update/archive/delete. **Alternatives considered** A remote MCP card would not provide vault access. A local CLI or a third-party MCP package adds installation and credential surfaces that the official SDK avoids. ## What Changed - Added the source and generated catalog definition, permission review, official light/dark artwork, documentation, and capability-map references. - Added a provider-owned SDK bridge with strict schemas, account-domain validation, contract hashes, fixed errors, bounded output, and disposable workers with cancellation/deadlines. - Registered the provider through master's native-provider catalog; existing setup, health, discovery, gateway, policy, and audit owners remain in place. - Labeled the single password field **Paste your 1Password Service Account token**. The shared formatter preserves explicit credential prompts; ordinary key labels retain their existing presentation. - Added credential-ownership, gateway read/write, policy/revocation, worker, setup UI, and interactive Storybook coverage. ## Verification - Final review follow-up: added two deterministic worker-entry tests for nested exact-token redaction and oversized-output rejection. Removing each guard caused exactly its regression test to fail. The focused provider suite passed **15 tests**, and the official server typecheck passed after rebuilding stale workspace SDK artifacts. Current head `569cb7f9bd57db791fb13a6034ce69bf50878cb1` passed the full [CI run](https://github.com/paperclipai/paperclip/actions/runs/40016166260), including typecheck, build, unit/integration tests, and all eight browser shards. The required `ci / verify` and `ci / e2e` gates passed. [Greptile](https://github.com/paperclipai/paperclip/pull/17249#issuecomment-6353731805) and [Paperclip Review](https://github.com/paperclipai/paperclip/pull/17249#issuecomment-6372165895) each rated this exact head **5/5**, with no open findings. Paperclip Review completed with a neutral check because its scoped reviewer could not inspect CI; the full CI result was verified separately. Other neutral checks and intentionally skipped Storybook jobs contain no actionable findings. - CI recovery on the same commit: the first attempt lost six jobs. Five logged simultaneous runner shutdowns at 18:49 UTC on 2026-10-23; the sixth stopped logging before a test result and its root cause was not established. No assertion failure appeared in the retrieved logs. All six jobs and the aggregate gates passed one failed-job retry. [CI run](https://github.com/paperclipai/paperclip/actions/runs/40005754936). - Copy follow-up: the catalog, provider, and setup UI suites passed **275 tests**. The governed gateway lifecycle passed **3 tests** (one live-only test skipped), including create, update, archive, and delete. UI token gates and map checks passed. The branch was rebased onto `9c442cf48e` to resolve additive catalog conflicts while retaining the Vercel and Supabase entries. The existing live write proof below remains applicable; this follow-up changes presentation only. - Five affected suites, including the existing Daytona consumer, passed **290 tests** (one opt-in live test skipped in fixture mode). Full `pnpm -r typecheck` and `pnpm build` passed. The local broad-suite attempt could not complete because PostgreSQL semaphore exhaustion prevented a competing integration suite from starting; the complete affected-file retry passed after disposable-process cleanup. The prior commit `f208a8aff6dc28859cc3f343497e18d85f124579` passed the complete CI matrix. All CI build, typecheck, test, and browser gates also passed on the earlier commit `9e2f3d3140368a08da43b004b2e8d3a0f4c0fa4d`. The separate Paperclip Review reported a worker-result regression-test gap on that head; the follow-up above addresses it. Its review thread is resolved, and both fresh current-head reviews are clean as recorded above. - Token gates, module boundaries, brand validation, map checks, and Storybook catalog checks passed. - Direct SDK create/archive/delete and rejected-call coverage passed (13 provider tests); the Storybook Permissions/Test play completed successfully in Chromium. Server and UI typechecks passed after those fixes. Greptile passed prior commit `9e2f3d3140368a08da43b004b2e8d3a0f4c0fa4d` at **5/5**. Both reviewers also passed the worker-test follow-up at **5/5** as recorded above. - Live 1Password proof on 2026-10-22: connect, eight-action discovery, vault listing through an actual run-scoped gateway, refresh, reconnect preserving identity, another read, removal, and denial through the retained session passed. Credential absence was asserted in responses/audit; an exact-token scan of inspected logs and changed files passed. - Real browser: Connectors → 1Password → token entry → personal access limited to one disposable agent → completion → Permissions → Test `onepassword_list_vaults` succeeded. The disposable connection was removed afterward. - Compiled-worker smoke initially exposed inherited Node launch flags. Workers now use explicit empty `execArgv`; the compiled worker then authenticated successfully and listed one vault. - Live write proof on **2026-10-23**: the replacement Keychain token passed all eight actions through the actual run-scoped gateway for both personal and shared credentials. The test created, listed, read, updated, resolved a secret from, archived, and deleted two synthetic items. Both were absent from subsequent item lists. Refresh/reconnect, identity preservation, removal, retained-session denial, and credential absence passed. The live suite passed **3 tests** (one fixture-only test skipped) in 116.65 seconds. The expanded fixture suite passed **3 tests** (one live-only test skipped); the 13 provider tests and server typecheck passed. An exact-token scan passed over 64 source/log files. - Failure history: the original token denied creation on 2026-10-22 and created no item. The first 2026-10-23 attempt stopped before provider calls because host PostgreSQL semaphore limits prevented test-database startup. A temporary ten-connection test profile allowed the complete retry to pass without changing shared services or host limits. A new delete-result assertion also exposed an outdated fixture response (`success` instead of `deleted`); the fixture was corrected and the complete fixture suite passed. Official contract sources: [service accounts](https://www.1password.dev/service-accounts/get-started), [SDKs](https://www.1password.dev/sdks), [item management](https://www.1password.dev/sdks/manage-items), [official JavaScript SDK](https://github.com/1Password/onepassword-sdk-js). ## Risks - Authorized item/secret reads intentionally return secret values to the agent and ordinary tool-result history. Select trusted agents and use restricted service-account vaults; the connection token itself is redacted. - New connections retain existing Paperclip action defaults, including Allowed writes/destructive actions for selected agents. 1Password still enforces the token's permissions. - Service-account access cannot be changed in place. Create a replacement account and reconnect to change vault permissions; read-only keys can connect but cannot write. - SDK authentication happens per action in a disposable worker. Calls have a 30-second maximum; cancellation stops local work, while a mutation already accepted by 1Password can still finish. Writes are never automatically retried. - Additive dependency and catalog change; no database migration. Disable/remove the connection to withdraw access, or remove the provider from catalog visibility for rollback. ## Model Used OpenAI Codex, based on GPT-6, with code editing, shell/browser tools, and live provider verification. A more specific runtime model ID and context-window limit were not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
73526559b5 |
fix(ui): reload once when a lazy chunk or its CSS fails to load (#17349)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - The board UI loads each page as a lazy chunk. Vite adds a preload
step that also loads the CSS of the chunk.
> - Staging error monitoring reported `Unable to preload CSS for
…/assets/issue-detail-CIbQo9zW.css`. The same file name comes from the
current build, so the CSS did not change. One request for the file
failed for a short time.
> - Vite rejects only the first import that asks for a failed file.
Later imports skip that file. On a task page, the first import is the
task-page prefetch, which ignores errors. The page then shows without
its CSS. On other pages that share the CSS, such as Agents, the lazy
route rejects and the route error boundary shows the error.
> - Neither case recovers without a manual reload. This is a routine
retry that the app can do safely, so the app must do it.
> - This pull request reloads the page one time when a chunk or its CSS
fails to load. A loop guard limits this to one reload in five minutes.
> - The benefit is that a stale tab after a deploy, or one failed asset
request, recovers without an error page, without missing styles, and
without error-monitoring noise. An asset that stays broken still shows
the error and still sends a report.
## Linked Issues or Issue Description
**What happened?**
A board page showed "This page hit an error" with `Unable to preload CSS
for <origin>/assets/issue-detail-<hash>.css`. On a task page, the same
failure gave no error message, but the page showed without its
stylesheet.
**Steps to reproduce**
1. Build the UI and start the server.
2. Make the first request for `/assets/issue-detail-*.css` fail. The new
Playwright spec does this with `page.route(...).abort("failed")`.
3. Open `/<prefix>/agents`. The route error boundary shows "Unable to
preload CSS".
4. Open `/<prefix>/issues/<id>`. The task shows, but the browser does
not request the task CSS again. The page has no task-page CSS.
**Expected behavior**
The app recovers from a chunk or CSS load failure without user action.
If the failure continues, the app shows the error one time, with no
reload loop.
**Environment**
Hosted staging browser. The local build of current `master` reproduces
it.
I searched open and closed PRs for `preload`, `preloadError`, and `stale
chunk`. I found no related PR.
## What Changed
- `ui/src/lib/chunk-load-recovery.ts` (new): `isChunkLoadError` matches
the Vite CSS preload error and the dynamic import errors from Chromium,
Firefox, and WebKit. `reloadForChunkLoadError` reloads one time. A
`sessionStorage` marker blocks a second reload for five minutes. After
the first reload, later chunk errors in the same document are part of
that reload, so they return "reloading" and do not show an error.
Without `sessionStorage`, the function does not reload, because it
cannot guard against a loop. `startChunkLoadRecovery` listens for
`vite:preloadError`. It does not cancel the event, so the import still
rejects as before.
- `ui/src/main.tsx`: Starts the listener before the first render. The
listener covers every import, including the task-page prefetch that
ignores errors.
- `RouteErrorBoundary` and `AppErrorBoundary`: While a recovery reload
runs, they show a loading state. They do not show the error page and do
not report to Sentry. Other errors work as before.
- Tests: Vitest unit tests for the helper and both boundaries. A new
Playwright spec, `tests/e2e/chunk-load-recovery.spec.ts`, runs against
the real server and the built UI.
## Verification
- `pnpm --filter @paperclipai/ui exec vitest run
src/lib/chunk-load-recovery.test.ts
src/components/RouteErrorBoundary.test.tsx
src/components/AppErrorBoundary.test.tsx`: 21 tests pass.
- Full UI Vitest suite: 793 files, 9,075 tests pass.
- `pnpm --filter @paperclipai/ui typecheck` passes. `node
scripts/check-token-gates.mjs` is clean. `node scripts/check-maps.mjs`
passes.
- `npx playwright test --config tests/e2e/playwright.config.ts
chunk-load-recovery.spec.ts`: 3 tests pass.
- Task page with one failed CSS request: one reload, the CSS loads, and
the task shows.
- Agents page with one failed CSS request: one reload, the CSS loads,
and the page shows with no error page.
- CSS that always fails: one reload, then the error page shows. There is
no second reload.
- Red proof: I ran the same spec with the `ui/src` changes removed
(current `master` UI code). Both recovery tests fail. On Agents, the
route error boundary shows `Unable to preload CSS for
http://127.0.0.1:3199/assets/issue-detail-CIbQo9zW.css`. On the task
page, the CSS is never requested again.
- A failure I found and fixed during the work: my first version changed
only the error boundaries. The task-page e2e case failed with that
version, because the prefetch received the error and the boundary never
saw it. The `vite:preloadError` listener fixes that case. All results
above are from the final commit.
- The spec blocks service workers, because Playwright page routes cannot
see requests that a service worker sends. With a worker, a failed
network request for an asset that is not cached also gives
`Response.error()`. Thus the preload error is the same.
## Risks
- A page can reload while a user is on it. This occurs only after a
chunk or CSS load failure, and at most one time in five minutes per tab
session. Without this change, that page already shows an error or shows
without styles. Composer drafts use browser storage, so a reload keeps
them.
- A failure that recovers no longer sends a Sentry event. A failure that
continues after the reload still sends one, so a broken deploy stays
visible.
- The error patterns match browser and Vite message prefixes. If a
browser changes its message, that browser goes back to the current
behavior: the error page and a report.
- No API, schema, or server changes.
## Model Used
- Claude Opus 5.5 (`claude-opus-5-5`) by Anthropic, run as a Paperclip
agent through Claude Code with tool use (shell, file edits, Playwright,
and Vitest).
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com>
|
||
|
|
9c442cf48e |
feat(connections): deploy and configure Supabase and Vercel (#17217)
Add governed Supabase and Vercel deployment/configuration connectors with vaulted credentials, agent access policies, approvals, audit, and bounded provider operations. Deliver reviewed REST actions to native agents and guard Vercel preview intent on empty projects. Preserve secret-safe request identity and durable retry behavior. Verified by current-head CI, fresh Greptile 5/5 review, and real-agent deployment/configuration walkthroughs on disposable provider resources. Test resources and temporary provider tokens were removed after verification. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
93d26eb84e |
feat(ui): link routine-created tasks back to their source routine (#16471)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Routines create tasks on a schedule. Each task records its source in `originKind = "routine_execution"` and `originId = <routine id>`. > - The issue Properties card shows Relationships such as Parent. It does not show the routine that created the task. > - An operator who reads a routine-created task cannot go to the routine from the task. They must find the routine by hand. > - This pull request adds a "Routine" row under Relationships, below Parent. The row links to the source routine. > - The benefit is a direct path from a routine-created task to the routine that made it. ## Linked Issues or Issue Description Refs #9727. That PR adds a general provenance model and an "Origin" chip. It also links routine executions to the routine. It is much larger (DB migration, server, plugin SDK). It has merge conflicts and no updates since August. This PR is a small UI-only change with no schema or API change. If #9727 merges later, the two rows can be merged into one. **Is your feature request related to a problem?** A task that a routine creates has no visible link back to that routine in the Properties card. **Describe the solution you'd like** Show a "Routine" row under Relationships for routine-created tasks. The row shows the routine title and links to `/routines/:id`. **Describe alternatives you've considered** A generic "Origin" row for all origin kinds (the #9727 approach). That needs new server data for most kinds. A routine link needs only data that the issue already has. ## What Changed - Add `ui/src/components/issue-properties/routine-origin-row.tsx` (`RoutineOriginRow`). It reads the routine with the same `queryKeys.routines.detail` query as the routine page, so the cache is shared. - Show the row in `IssueProperties.tsx` after Parent, only when `originKind === "routine_execution"` and `originId` is set (+5 lines). The new component is in its own file because `IssueProperties.tsx` already has more than 3,000 lines. - States: - Routine found: an outline chip with the repeat icon and the routine title. The chip links to the routine page. - Routine still loading, routine deleted (404), or any other lookup error: no row. The card never shows an empty Routine field. - Task not created by a routine: no row. No routine request is sent. - Add 4 tests in `IssueProperties.test.tsx`: routine found, routine loading, routine deleted, and task not created by a routine. ## Verification - `pnpm --filter @paperclipai/ui exec vitest run src/components/IssueProperties.test.tsx`: 94/94 pass. - `vitest run src/pages/IssueDetail.test.tsx src/components/TaskSidePanel.test.tsx` (other surfaces that render the panel): 195/195 pass. - `node scripts/check-token-gates.mjs`: all gates clean. - `tsc --noEmit` in `ui`: no errors in the changed files. Other errors came from workspace packages that were not built locally (`@paperclipai/plugin-sdk/ui`, generated storybook catalog JSON). This change does not touch them. - Manual check: open a task that a routine created. Find the "Routine" row under Parent. Click it. The routine page opens. - Not run locally: full `pnpm -r typecheck`, `pnpm test:run`, `pnpm build`, and a browser check. CI runs these. ## Risks - Low risk. The change is UI-only and additive. It has no schema, API, or contract change. - Each routine-created task view sends one extra `GET /routines/:id` request. The routine page uses the same cache key, so the response is often cached already. - The row appears only after the routine request finishes. On a cold cache, it shows up a moment after the rest of the card. - If the routine is deleted or the user cannot read it, the task shows no Routine row. The task still records `originKind`/`originId`. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - Anthropic Claude Opus 5.5 (`claude-opus-5-5`) in Claude Code, with tool use (shell, file edit, test execution). Standard context window. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Devin Foley <139239+devinfoley@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
3bd709df8b |
Operationalize Product E2E accounting, tracing, and scheduling (#17009)
## Thinking Path > - Paperclip manages agents and the work they perform. > - Product E2E tests exercise real agents, tools, setup and cleanup. > - Repeated runs need retained costs and traces, including failed attempts. > - A passing retry must not hide earlier spending or feedback. > - Recurring work also needs admission limits, private reports and failure detection. > - This change supplies those controls while keeping paid activation behind existing gates. ## Linked Issues or Issue Description Refs #16996 and #17158. This is the consolidated landing of the reviewed eval operations stack: #17019, #17024, #17025, #17027, #17030, #17033, #17035, #17038, #17043, #17044, #17048, #17050, #17051, #17092, #17096, #17100, #17107, #17109, #17112, #17115, #17117, #17121, #17123, #17127, #17130, #17133, #17134, #17137, #17140, #17143, #17154. The repository permits squash merges only. A local rehearsal showed that squashing each slice into master causes repeated conflicts in dependent slices. This PR preserves their commits and lands their combined implementation in one reviewed integration. Superseded slices will close after this merge. ## What Changed - Retain every attempt's cost receipt, including setup, failures, interruptions and retries. Separate reported amounts, estimates, missing costs and reserved capacity in reports and dashboards. - Add bounded request admission, exact model pricecards, gateway error accounting, cache policy and reconciliation evidence. Refuse unsupported routes and requests that cannot fit the allowance. - Integrate Braintrust gateway traces and OTLP correlation, with secret filtering and experiment imports. Record phase timing, including setup, feedback capture and cleanup. - Collect complaint and suggestion evidence after each attempt, including recovery after failures. Retain explicit review dispositions independently from the product grade. - Add gated daily and weekly selections, measured forecasts, setup/readiness checks, wall-time limits and retained monitor notifications. Include declared non-model overhead in admission while reporting the existing subscription separately. - Keep recurring history private, bound uploads and retention, and use isolated archive environments. Keep public publication an explicit operation. Report and publication jobs install only the committed lockfile, with scripts disabled and isolated stores; stale pins fail closed. - Integrate current master, preserve its Product E2E journey billing and privacy checks, and test that shared setup receipts do not double-count estimated agent usage. Preserve upstream fixture repairs. ## Verification - Complete integration baseline `0649a5ce7544ab20825c2183d2f421157db49f24` includes master `a3e1d915a7110a4e115b46396a3f79e6dfb4d05e` and every original stack head as ancestors. - On that integration baseline, `pnpm test:e2e:runner:unit`: 4,012 Vitest tests passed, two skipped, across 193 files; all 137 Node source-contract tests passed. - Focused billing and Product E2E journey contract checks: 24 tests passed. They cover estimates, unknown receipts, single-owner setup costs, browser-only execution and private publication guards. - Monitor and workflow wiring: all 96 Node tests passed. `node scripts/check-token-gates.mjs`: all gates clean. - `pnpm test:e2e:runner:typecheck` passes after the standard Runner TypeScript build refreshed local declarations. The first attempt rejected the new master `runner_prepared_launch` union member because this checkout retained an older generated declaration; the source union already contained that member. - Current head `492b0708a1c531a023d9ac10f0f3dc6383cc1754` removes dependency re-resolution from archive-authorized reporting jobs after the security scan flagged it. All 15 workflow-security tests pass after updating the old two-install assertion. - Hosted [CI run 39965460180](https://github.com/paperclipai/paperclip/actions/runs/39965460180) passes on the current repaired head, including typecheck, build, general tests, Runner checks, browser shards and canary dry run. Greptile is 5/5 on this exact head with no unresolved threads. The security scan passes after the fixed lockfile-resolution thread was resolved. - Paperclip Review returned a terminal neutral check but an incomplete 0-file assessment on the repaired head: its platform blocked both diff responses as prompt-injection content. This is not a successful code review. No bypass or fabricated pass was attempted; current-head Greptile, security and hosted CI are independent gates. - No paid test, reservation release or recurring-run activation accompanies this landing. Live route qualification and invoice reconciliation remain separate evidence. <details> <summary>Retained earlier validation failures</summary> Earlier broad local runs had two 15-second test timeouts (CLI poll cadence and Retry validation), one embedded-database setup timeout, and later PostgreSQL semaphore exhaustion. The exact timed-out tests passed separately without larger timeouts; the broad-run causes were not established. Those local failures remain distinct from subsequent hosted CI results. The independent #17158 fix records its Muse fixture collision, its UUID correction and hosted verification. Local Muse execution was also blocked by macOS embedded-PostgreSQL startup. No historical failure is treated as a successful paid qualification. </details> ## Risks - Admission is a local control, not a provider invoice cap. Missing provider receipts or resource charges retain unknown amounts and holds; estimates do not become billed dollars. - The bounded path admits only documented local suites and provider routes. Ordinary legacy or separate Runner protocol campaigns have different controls. Merging this code does not qualify additional routes. - Recurrence still needs the existing enable gates and current qualification/allowance evidence. Archive permissions and resources must match the documented private-environment contract. - Legacy reports may lack complete attempt or phase evidence. Reports preserve that limitation and do not infer zero usage from missing data. ## Model Used OpenAI GPT-6 through Codex, with reasoning, repository tools and code execution. The exact deployment variant and context-window size are not exposed by this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass (targeted checks; full-suite host limitation disclosed above) - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
fbaf3c6ed2 |
feat(onboarding): connect a custom AI gateway (#17253)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - A person must connect an AI account when they set up the first agent. > - The existing connection form supports custom Responses and Messages gateways. > - First-agent onboarding does not expose that form or its saved model list. > - A person who uses a custom gateway cannot complete this setup through the normal controls. > - This pull request adds the existing gateway form to onboarding and requires a model before Connect. > - The person can save the account first, then choose Connect to test the environment and hire the agent. ## Linked Issues or Issue Description Refs #14104. This addresses the missing custom endpoint option during first-agent onboarding. Refs #15103. That issue also covers other adapters and the separate New Agent wizard. Related source review: - Refs #15884. That proposal adds a Local LLM source, changes private-network HTTP validation, and uses OpenCode. This change uses existing gateway routing and preserves the explicit environment test before hire. - Refs #14006. That proposal adds new providers and connection methods. This change uses the existing OpenAI and Anthropic managed connection contracts. **What existing behavior does this improve?** The API-key step of first-agent onboarding for Codex and Claude. **Current behavior** The wizard accepts a direct provider key but does not expose custom gateway setup or the saved gateway model list. **Proposed behavior** Choose Use a custom gateway. Save its URL, key, and models through the existing connection form. Select a saved model. Choose Connect to run the normal environment test and hire the agent with the managed connection binding. **Reason and benefit** People can complete onboarding with an existing custom gateway. They can save the connection before any agent test starts. **Breaking changes** No API, database, or routing schema changes. The new path applies to Codex and Claude API-key setup. Existing direct-key setup remains available. ## What Changed - Add a small onboarding dialog that reuses `AiProviderSetup` for Responses or Messages gateway connections. - Let the shared setup form use Save connection as its submit label in this dialog. - Bind the saved account to the current company and adapter. Clear its selection when the person changes companies or chooses another API key. - Load the saved connection's models. Require a model before Connect can test the environment and hire the agent. - Show a loading state, a visible error, and Retry loading connection when the saved connection lookup fails. Reuse the shared lookup cache and preserve the model hook contract for existing consumers. - Cover saving, model selection, delegated account use, secret exclusion from drafts and hire payloads, and Cmd+Enter in the gateway dialog. ## Verification - Focused UI verification: `pnpm --filter @paperclipai/ui exec vitest run src/components/OnboardingWizard.test.tsx src/components/ai-connections/AiProviderSetup.test.tsx` — 187 tests passed across two files. - The first focused attempt had one test-only failure because its fixture lacked `TooltipProvider`. The fixture now supplies that provider. The complete focused run then passed all 187 tests. - The new test confirms that saving the connection and pressing Cmd+Enter in its dialog do not call the adapter test or hire API. Connect remains disabled until model selection. Connect then uses the selected model and managed connection for both test and hire. - Rebased onto `origin/master` at `042051904d368f5514e287e5ca8e404dc8f78a0d`. The two focused UI files passed all 187 tests again on the rebased tree. - UI typecheck passed on the rebased tree. The first attempt found missing generated Plugin SDK declarations in the fresh worktree. `node scripts/ensure-plugin-build-deps.mjs` built the local shared and SDK artifacts. The Storybook catalog check and `tsc -b` then passed. - Reused installed third-party packages from the unchanged lockfile. Worktree-local workspace links pointed at the rebased source. No older workspace source was substituted. - The full token gate checks and `git diff --check` passed in this isolated worktree. - An earlier wider local repository run failed in a chat-channel test. That failure was not investigated in this isolated UI follow-up and remains part of the verification history. The complete CI suite for this PR later passed on the reviewed commit. Deployed gateway acceptance has not been run. - Review follow-up: reproduced the failed saved-connection refresh before the fix. The new test failed because the page did not show the lookup error. The page now shows the error and Retry loading connection. Connect stays disabled until lookup and model selection succeed. - The new failure-and-retry test uses separate response objects so cache mutation cannot hide a failed refresh. It also proves that save and retry do not probe or hire an agent. - The expanded regression initially needed a corrected mock return type. After that correction, all 199 tests passed across OnboardingWizard, AiProviderSetup, and useConnectionModels. UI typecheck, all token gate commands, and `git diff --check` passed. - The review fix is pushed at `12b4e9cb8528ba44af377315ba39fe3fbccae7bd`. All 53 active CI and security checks passed on that exact head. Two Storybook checks were skipped. Greptile completed with 5/5, and there are no unresolved review threads. The earlier local chat-channel failure remains recorded above. - No live Cloud gateway campaign or candidate deployment has been completed for this product change. ## Risks - Gateway setup adds a nested dialog inside onboarding. Its key events must not submit the parent wizard. The Cmd+Enter regression test covers this boundary. - A saved connection can offer no model list. That state permits an explicit model ID and still requires selection before Connect. - Saving a connection proves that it was stored. The normal Connect action remains responsible for runtime validation. A successful mocked UI test does not prove gateway reachability from a deployed runtime. - `ROADMAP.md` already includes personal and shared AI accounts and multi-model teams. This is a scoped extension of those capabilities. It does not add a provider, a protocol, or wider URL access. ## Model Used OpenAI Codex, GPT-6 family. The exact deployment model ID and context window are not exposed in this session. The agent used reasoning, tool use, code editing, and local test execution. No unverified model ID or context size is claimed. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
c5ca29dbef |
fix(claude): prepare compatible sandbox runtimes during onboarding (#17259)
## Thinking Path > - Paperclip connects agent accounts and prepares their execution environments. > - A managed sandbox image can outlive the model defaults shipped by the app. > - Claude setup skipped installation whenever a CLI was already on PATH. > - The selected model then failed its minimum-version check after sign-in succeeded. > - This pull request prepares a compatible private CLI before testing or running it. > - Cloud onboarding also stops asking customers to run inaccessible shell commands. ## Linked Issues or Issue Description **What happened?** A new managed Cloud stack completed Claude subscription sign-in. Its environment test then failed because the snapshot contained Claude Code 2.1.263, while the selected `claude-opus-5-5` model requires 2.1.280. The screen displayed Manual debug commands that a hosted customer cannot run. **Expected behavior** Paperclip prepares its managed runtime before testing the selected account. A stale image CLI does not require the customer to upgrade a server package. Failed preparation still blocks hiring. Cloud does not display manual shell debugging. **Steps to reproduce** 1. Start a managed sandbox with Claude Code 2.1.263 on PATH. 2. Connect a Claude subscription and select `claude-opus-5-5` on the CLI lane. 3. Connect the agent. Installation is skipped because the command exists, then the version gate blocks the hello test. **Paperclip version or commit** Source baseline: `6204239cfc8c3be79fc185cf3f468ebaa0ab1e3e`. **Deployment mode** Authenticated managed Cloud with a Daytona named snapshot. The correction also applies to the default CLI in other managed sandbox transports. Related work: Refs #14993 sets model/runtime requirements; Refs #15993 changes native defaults on qualified targets. Neither prepares an outdated default sandbox CLI on this path. Searches found no open duplicate. ## What Changed - Check the actual default CLI against the selected model's existing minimum version. - When a sandbox's default command is outdated, install the exact required npm package into a private versioned workspace prefix. Reuse a compatible private installation. Keep the image's global CLI intact. - Verify the private executable and use that same command for the account hello test and normal CLI runs, with matching command metadata. Probe effort support after preparing that executable so the chosen effort is retained. Keep the model, account, engine and permissions unchanged. - Return safe preparation checks to environment tests and normal run logs, distinguishing installation failure causes without returning raw installer output or credential-bearing URLs. - Exclude provider and Paperclip credentials from the installer environment. Preserve the existing failing version gate if installation or verification cannot succeed. Local, SSH and explicit custom commands remain operator-managed. - Hide Manual debug and legacy operator check hints on Cloud and while deployment metadata is unknown; preserve check messages and details. Retain self-hosted help and the detailed failed checks. Cloud copy asks for a retry instead of asking the customer to repair the environment. - Add subprocess-backed runtime controls, an account-probe regression and mounted Cloud/self-hosted wizard controls. Update development guidance and the affected capability maps. ## Verification - Passed all Claude source suites and the server Claude execution suite on head `c941ae44c22d8dafec0df033a129e39ce4ebd966`: **412 passed**, one existing opt-in test skipped. These include the new command/effort ordering, safe installer diagnostics, environment forwarding and run-log regressions. - On final head `0ecae0e9304f495a57524158b3700b8e9bc21cb8`, passed **208 tests** across all 174 mounted onboarding wizard tests and 34 Claude execution tests. The failure fixture includes the real command-bearing hint, and execution asserts both metadata command fields agree. - Passed `pnpm -r typecheck`, `pnpm build`, `pnpm check:token-gates`, `node scripts/check-maps.mjs` and `git diff --check`. Full typecheck and build were repeated successfully on final head `0ecae0e9304f495a57524158b3700b8e9bc21cb8`. [Latest-head CI](https://github.com/paperclipai/paperclip/actions/runs/39879208694) is green: 54 checks passed and two skipped, including browser E2E and serialized database suites. - The new runtime controls execute real subprocesses with a controlled installer. They cover an old CLI, an already compatible CLI, failed or ineffective installation, local/custom commands, and an unknown version. The probe regression asserts that the hello call uses the private executable. - A separate non-root local subprocess check installed the real npm `@anthropic-ai/claude-code@2.1.280` package. Its private command reported 2.1.280, the simulated image CLI remained 2.1.263, and a second preparation reused the private copy. This ran on macOS ARM64. It did not use a provider account, send a model prompt, or prove live Daytona behavior. - Attempted `pnpm test:run`. Embedded PostgreSQL initialization failed after five attempts on this Mac with `Postgres init script exited with code null`. The unchanged native-session database cases then failed. Stopped only that full-suite process tree after recording the repeated startup failure. No full local-suite pass is claimed; Linux CI must cover those tests. - The first new subprocess fixture had a quoting syntax error. It was corrected before the passing focused runs. The one-off real-package script first required an ESM extension correction, then passed. Logs retain both attempts. A new execution assertion initially inspected the final sandbox cleanup shell instead of the launched command; it now checks execution metadata. A broader directory selection also picked up generated `dist` tests whose Markdown fixtures are not copied by the build (two ENOENT failures). The explicit source-suite run above passes; no generated-test pass is claimed. - Apex review: **5/5**, reviewed final head `0ecae0e9304f495a57524158b3700b8e9bc21cb8`, all five earlier findings addressed and resolved, no new findings. - Merge, deployment and a fresh live Cloud subscription test are still required. No customer account or production runtime was changed by this branch. ## Risks - An outdated sandbox needs npm registry access and up to 120 seconds for one bounded installation attempt. A failed or unverified install continues to block execution. - The versioned package uses sandbox workspace storage. Compatible cached copies avoid repeat installation within that workspace. Existing runtime cleanup and sandbox lifecycle still apply. - The compatible version comes from the adapter's existing model-version contract. This does not add a model fallback or change the selected execution engine. - No schema, credential, permission, workflow or lockfile change. ## Model Used OpenAI Codex, based on GPT-6, assisted with implementation and verification. The exact serving model ID and context-window limit are not exposed in this session. Capabilities used: code editing, shell execution, API inspection and test execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
6204239cfc |
Support installed default project workspace providers (#17247)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Storage plugins already own project storage and task checkout preparation. > - Core only selected these plugins through an explicit project policy. > - Installation could therefore leave new and existing projects on incompatible Core preparation. > - This pull request adds one generic manifest declaration and one shared effective-policy resolver. > - Project configuration shows inheritance while durable workspace bindings retain their owners. ## Linked Issues or Issue Description **Subsystem affected** Plugin contracts, project configuration, and execution workspace preparation. **Problem or motivation** An installed storage provider cannot become the company default. Projects without an explicit provider keep Core preparation, even when their execution environment cannot use a Core Git checkout. **Proposed solution** A provider declares supported `workspaceProvider.defaultForProjects` mode and strategy. Company-enabled installations supply inherited defaults. Explicit plugin selections and explicit Core/local (`storageProviderPluginId: null`) win. Conflicting defaults require an operator choice. The declaration and implementation contain no provider-specific identifiers. **Alternatives considered** Rewriting every project would lose the distinction between inheritance and overrides. Selecting by worker health would silently change storage on an outage. **Roadmap alignment** Extends the existing workspace and sandbox provider contracts. The roadmap has no duplicate default-provider implementation. Related public work includes #17243, which covers prepared execution directories rather than provider selection. ## What Changed - Add a validated generic default-provider declaration and document it in the SDK. - Resolve provider selection and Git defaults consistently in project responses, source selection, heartbeat source resolution, reservation, and preparation. - Keep stored policy separate from effective configuration. Add the normal project configuration selector for inheritance, explicit plugins, and Core/local. - Preserve existing local and plugin workspace ownership. Pin selection through preparation and keep provider failures visible. - Add database, API, manifest, heartbeat, and UI regressions. Update the verification maps. ## Verification - Targeted Vitest runs cover manifest validation, project defaults and API access, explicit overrides, existing ownership, new/imported task inheritance, heartbeat routing, source-free tasks, selection pinning during setup, and UI configuration. - Combined policy, provider integration, and heartbeat run: 58 tests pass; 60 unrelated cases excluded. After the final shared-provider fallback fix, all 47 policy tests pass, including shared and operator-mode regressions. - Server and UI TypeScript checks, SDK build, verification-map validation, credential-pattern scan, added-comment scan, and `git diff --check` pass. - A downstream integration uses this Core resolver and preparation service with a real storage hook and mocked remote infrastructure. A new Git project reaches the hook without a stored provider ID. - Standard Greptile and Apex both scored 5/5 on |
||
|
|
9bf7dc0c8f |
feat(agents): bulk edit connections and default models (#17215)
Add harness-scoped bulk connection and default-model edits to the agent roster, with compatible choices, change previews, per-agent save results, and retries. Use an icon-based harness filter, keep agent rows readable, remove the status selector and selection hint, and redirect legacy status URLs to the full roster. Preserve authorization, audit history, unrelated settings, and optimistic concurrency checks through the existing agent update route. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
46760cc588 |
fix(chat): honor dismissal for all composer requests (#17218)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Task conversations show requests in the feed and above the message composer. > - Earlier fixes kept dismissed questions in history, but excluded completion reviews and other request kinds. > - Closing those forms left a pending badge, and the server could still demand a response. > - This pull request saves human dismissal and removes the request from composer reminders and ordinary completion gates. > - People can continue the conversation and reopen the request from history. ## Linked Issues or Issue Description Related work: #15229 and #15392. **What happened?** Dismissing a completion review closed its form but left it counted as pending. It could return after reload, block a retry, or cause the agent to demand another response. Raw runtime requests could also lose their only usable control when dismissed. **Expected behavior** Dismissal leaves an accessible request in the feed and clears the composer form and pending count. It persists after reload. It does not submit an answer, approve an action, or wake the agent. **Steps to reproduce** 1. Open a task with a pending completion review or another composer request. 2. Dismiss the request, then reload the task. 3. Check that the composer stays clear and the feed entry can reopen the request. ## What Changed - Add nullable dismissal fields and a human-only dismissal endpoint with company, private-task access, resolver, and locked review-policy checks. - Persist saved-request dismissal on the server. Keep browser persistence for raw runtime requests and existing question dismissals. - Keep confirmations, choices, item verdicts, suggested tasks, and runtime requests accessible in the feed. - Exclude dismissed ordinary requests from completion and retry gates. Tell agents not to repeat deferred requests. - Preserve tool, secret, connection, plan, company-policy, and configured review authorization gates. Expire deferred non-question requests when their task completes. - Preserve the selected form when another dismissal finishes saving. Keep reopened reviews visible through delayed comment refreshes. - Add a completion-review Storybook test drive and update design, API, database, and capability documentation. ## Verification - `pnpm -r typecheck`: passed. The final UI changes also passed the UI typecheck. - `pnpm build`: passed. The final UI changes also passed the UI production build. - Focused UI and transcript tests: 550 passed across nine files after merging the current base branch. - Focused database, completion, and prompt tests: 105 passed across three files, including two review-policy regressions that failed before the fix. The tests reject a review requester excluded by current policy, preserve the pending gate on denial, and permit an independent reviewer to defer the request. - Route regression suite: 81 passed, including denial before reading or mutating a private-task request. - `pnpm check:token-gates`: passed. - Map and Storybook structural checks: passed; 30 map/catalog script tests passed. - Browser: used the production task-thread components in the completion-review fixture. Dismissed, reloaded, reopened from the feed, and dismissed again. No pending badge or composer takeover remained. Story callbacks simulate API saves; separate server tests cover persistence and permissions. - `pnpm test:run`: stopped after the general-server group reported one failure in `workspace-runtime.test.ts`: "returns a bounded structured conflict and exposes only same-company workspace references". The same test passed in isolation (1 passed, 178 skipped). The cause of the full-suite failure is not established. The full PR CI suite subsequently passed on e243cbb001; its two authorization review findings are fixed in |
||
|
|
341b622604 |
feat(ui): Artifacts V1 behind an experimental setting — Artifacts page, panel tab and task thread (#17228)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agents produce artifacts: documents, files, pictures, video and links. The app shows them on the Artifacts page, in the right panel's Artifacts tab and in the task thread > - The artifact directions lab (#17213) settled a presentation for those surfaces, MVP V1, drawn from the PCLP-Core mocks. It is a reference, not product code > - Shipping it means product components on product data, token-only, behind a switch, one surface at a time, so the current presentation stays the default until the new one has been used > - This pull request adds the switch (Settings > Experimental > Artifacts V1), the `--artifact-*` tokens, the V1 primitives as product components, and the V1 presentation on all three surfaces behind the switch: the Artifacts page, the panel's Artifacts tab and the task thread > - The benefit is the redesign in the product, reversible by one setting, with every existing behaviour of those surfaces kept ## Linked Issues or Issue Description No public issue exists. This section follows the feature request template; the plan is `doc/plans/2026-10-22-artifacts-mvp-v1.md`. **Subsystem affected** The web UI (`ui/`): the Artifacts page, the right panel's Artifacts tab and the task thread. The experimental settings contract in `packages/shared` and `server` gains one boolean. **Problem or motivation** The three artifact surfaces grew separately and their artifact presentation is dated and inconsistent. The lab produced a measured direction; nothing in the product uses it yet. **Proposed solution** An experimental setting, `enableArtifactsV1`, default off, with the same plumbing as the other experimental settings. Product primitives under `ui/src/components/artifacts/v1` (kind helpers and adapters, the sheet and print artwork, the stack, the page tiles with the Paper Mono pill, the row the panel and thread will share), driven by `--artifact-*` tokens in `index.css` with light and dark values. With the setting on: the Artifacts page shows one row of views (Tasks, All files, Images, Videos, Documents, Text, Files) and the V1 tiles, a task with several artifacts as a stack whose newest artifact is the first page, everything else as single tiles; the panel's Artifacts tab is one flat list of V1 rows, newest first, with the expandable rows (Markdown review surface, document annotations, deep links) keeping their behaviour behind the row as their face; the thread shows a message's files as rows under its footer and registered deliverables and documents as one row each. The hover movement respects reduced motion. **Alternatives considered** Replacing the current cards outright: no fallback and three surfaces to land at once. Mounting the lab's components: they are typed on lab fixtures and keep lab-local tokens, which the token gates reject. The primitives were ported instead and the lab stays a reference. **Roadmap alignment** Supports the "Artifacts & Work Products" theme in `ROADMAP.md`. Presentation only; no data model change. **Additional context** No new API fields: the tiles show title, identifier, count and "Updated …"; rows take sizes from the work-product and attachment payloads; a picture's aspect ratio comes from the loaded image, 4:3 until it loads. The plan records what each surface keeps and what it drops (run sections in the panel; the "Images · N / Files · N" labels and the four-up grid in the thread). ## What Changed - Add the `enableArtifactsV1` experimental setting: shared type, validator and feature catalog, server defaults and managed keys, the `useArtifactsV1Enabled` hook, and the Settings > Experimental toggle (in its alphabetical place). - Add the `--artifact-*` tokens and the Artifacts V1 component rules to `ui/src/index.css`: light values on `:root`, dark overrides, and the hover movement under `prefers-reduced-motion: no-preference`. - Add `ui/src/components/artifacts/v1/`: `kinds.ts` (kind treatment, labels, glyphs, the server's media-kind rule, adapters from `CompanyArtifact`), `geometry.ts` (the measured constants), `when.ts`, `ArtifactSheet`, `ArtifactPrint`, `ArtifactStack`, `ArtifactFront`, `ArtifactTile` (stack and single tiles, caption, grid), `ArtifactRow` (the row and its inline group), `ArtifactsV1Filters`, with the mock's SVG assets. - Wire the Artifacts page: with the setting on, the toolbar's filter row becomes the V1 views and the grid renders V1 tiles; the toolbar takes an optional `filters` row for this. The old cards and kind filters stay the default. - Wire the panel's Artifacts tab (`IssuePropertiesArtifactsTab`): with the setting on, one flat list of V1 rows, newest first; `DocumentRow` and `MarkdownWorkProductRow` take a `face` render prop so the V1 row fronts their unchanged expansion, review and deep-link behaviour; `PanelFileRow` opens attachments and attachment-backed work products the way the shipped card does (gallery, text tab, new tab) with open and download beside the name; other work products are a link row with their status. - Wire the task thread: `TaskChatBubble` hangs a message's files under its footer as V1 rows inline (pictures and video to the gallery, text to a text tab, files to a new tab) in place of the media grid and file chips; `TaskChatProtocolCard`'s resource rows render deliverables, documents and attachments as one V1 row each, opening where the card did. - `ArtifactRow` keeps trailing controls beside its own control (no nested interactive elements) and can be a link, an in-app anchor, a new-tab anchor or a button; adapters read work products, documents, attachments and message references. - Add a catalogued Storybook story, `Components/Artifact V1 primitives`, under `documents-artifacts`, on fixtures. - Add tests: the primitives (kinds, dates, print fitting, tiles, rows), the hook, the Artifacts page, the panel's Artifacts tab, the task-chat bubble and the protocol card, each with the setting on and off; the settings page and server tests list the new key. - Add `doc/plans/2026-10-22-artifacts-mvp-v1.md`. ## Verification - Run `cd ui && pnpm typecheck`: the Storybook catalog accepts the new story, and `tsc -b` is clean apart from the five pre-existing `PluginOrganizationSwitcher` errors. - Run `pnpm check:token-gates` and `node scripts/check-maps.mjs`: clean. - Run `cd ui && npx vitest run src/components/artifacts src/components/issue-properties src/components/task-chat/TaskChatBubble.test.tsx src/components/task-chat/TaskChatBubble.artifactsV1.test.tsx src/components/task-chat/TaskChatProtocolCard.test.tsx src/components/task-chat/TaskChatProtocolCard.artifactsV1.test.tsx src/pages/Artifacts.test.tsx src/hooks/useArtifactsV1Enabled.test.ts src/pages/InstanceExperimentalSettings.test.tsx`: the suites pass (151 tests in the last run). - Run `cd packages/shared && npx vitest run src/feature-catalog.test.ts` and `cd server && npx vitest run src/__tests__/instance-settings-service.test.ts`: pass. - Manual: open Settings > Experimental, turn on Artifacts V1. On the Artifacts page the view row reads Tasks, All files, Images, Videos, Documents, Text, Files; tasks with several artifacts show as stacks, hovering fans the pages and lifts the artwork (not under reduced motion); Images shows single tiles with bordered prints. Open a task's Artifacts tab: one list of rows, newest first; a Markdown work product still expands into its review surface, a document still opens in its tab. In the thread, a message's files sit under its footer as rows. Turn the setting off: everything returns to the current presentation. - Storybook: `Tasks and conversations / Documents, attachments, and work products / Components / Artifact V1 primitives`. - Not run: the full `pnpm test:run` and `pnpm build` (CI runs them), and a browser pass against a dev instance with real artifacts on the three surfaces; that pass is the remaining step before this leaves draft. ## Risks - Off by default; with the setting off, the only changes on a product path are an optional `filters` prop on the toolbar, an optional `face` prop on two panel rows, a read of the setting in the bubble and the protocol card, and the new token declarations. - With the setting on, the Artifacts page's view tabs set two URL parameters (`groupBy`, `kind`) at once; the group-by menu and search are unchanged. - A picture with unknown dimensions renders at 4:3 until it loads, then the print refits once; the frame's height is fixed so nothing below it moves. - About thirty new `--artifact-*` tokens, namespaced and documented in place. ## Model Used - Claude Fable 5.1 by Anthropic, model ID `claude-fable-5-1`, used through Claude Code in the desktop app. Extended reasoning was on. Capabilities used: tool use (shell, file edits, a headless Playwright browser for the lab's measurements, the Figma MCP server for the mocks during the lab work) and image input. The context window is the Claude Code session's; its exact size is not surfaced to the session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above (#17213 is the lab this builds on) - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass (the suites listed above; CI runs the full set) - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes (the plan document; no command or product behaviour changes outside the setting) - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
059ae49cab |
feat(connections): add Unikraft Cloud connection (#17139)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Apps connections give agents governed access to external services through vault credentials, grants, action policies, the tool gateway, and audit. > - Unikraft Cloud runs unikernel micro-VMs, services, and volumes across regional metros, and it offers a sandbox plugin for commands and files. > - Unikraft is not in the catalog. It has no hosted MCP server, so the generic "Connect your own MCP server" flow cannot reach it. > - Daytona (#16483) added a native REST pattern for this case: a catalog generated from the provider's published OpenAPI specifications and executed through the gateway. > - This pull request adds Unikraft on that pattern and moves the shared native-provider code into one registry, so the shared connection code does not name each provider. > - The benefit is governed agent access to all published Unikraft actions, with the token kept in the vault and sent only to published Unikraft hosts. ## Linked Issues or Issue Description Refs #16483 **Problem or motivation** Teams that run workloads on Unikraft Cloud want their agents to list instances, read logs, deploy and scale services, and run commands in sandboxes. Unikraft is not in the Apps catalog. Unikraft has no hosted MCP server, so operators cannot connect it through the remote MCP flow. **Proposed solution** Add a native Unikraft connection. Generate its actions from Unikraft's official OpenAPI specifications for the platform API and the sandbox plugin. Pin the specifications to a reviewed commit. The operator connects an API token. The token stays in the vault and goes only to the five published metro hosts. Every action takes an optional metro. Actions without a metro use the connection's default metro, which the operator can change under Advanced. **Alternatives considered** A catalog-only AppDefinition was not possible because no hosted MCP endpoint exists. Wrapping the `unikraft` CLI was rejected because it would expose host filesystem behavior and CLI login state. A second copy of the Daytona bridge was rejected; the shared transport and catalog contract are now one module with a provider registry. **Roadmap alignment** This extends the existing Apps and Connections provider coverage. It uses the existing credential, grant, policy, gateway, and audit model. It does not overlap planned core work. ## What Changed - Added `scripts/generate-unikraft-tools.mjs` and its tests. The generator reads the platform and sandbox plugin specifications at commit `5dd107ea1cd8716b83cb86a83ed2a6ee46f99b5b`, resolves shared parameters, records source SHA-256 hashes, and writes `server/src/services/unikraft/operations.generated.json`. - The catalog has 105 actions: 89 platform operations and 16 sandbox plugin operations. The server-sent audit event stream is recorded in the inventory and is not advertised as an action. - Classification: GET operations and sandbox reads and waits are reads. Delete, stop, suspend, detach, unpin, and sandbox command execution, signals, and stdin are destructive. All other operations are writes. - Added `server/src/services/connectors/unikraft/client.ts` and its generated catalog. It validates arguments against the generated schemas, accepts only published metros, rejects path traversal, sends JSON bodies on GET and DELETE as the specification requires, and verifies the token with `GET /v1/users/quotas`. A sandbox wait that times out (documented HTTP 408) returns a still-running result instead of a failure. - Moved the bounded, credential-redacting HTTP sender and the catalog contract helpers from `daytona.ts` to `native-rest-client.ts`. Added `native-provider-catalogs.ts`. `tool-access.ts`, the `tool-access/catalog` and `token-broker` modules, `connectors/tool-policy.ts`, and `tool-gateway.ts` now use this registry instead of Daytona-specific checks. Daytona behavior does not change. - Added the Unikraft definition source, the generated definition, the brand mark and manifest entry, and the permission review (`liveProof: not-run`). - Added `doc/connections/UNIKRAFT.md` with a sequence diagram, endpoints, setup, actions, and limits. Updated the connections README, the permission audit, and both capability maps. - Tests: definition shape, database-backed gateway reads, writes, deletes, and sandbox commands for personal and shared grants, default and per-call metros, rejection of unpublished metros and traversal, Off policies, revocation, stale-contract blocking, credential export denial, schema validation for all actions, pinned-transport tests for GET and DELETE bodies, and a browser setup check. ## Verification - `pnpm exec vitest run packages/shared/src server/src/__tests__/unikraft-connection.test.ts server/src/__tests__/unikraft-http-boundary.test.ts server/src/__tests__/daytona-connection.test.ts server/src/__tests__/daytona-http-boundary.test.ts server/src/__tests__/tool-access-service.test.ts server/src/__tests__/tool-gateway-service.test.ts server/src/__tests__/tool-gateway.test.ts ui/src/pages/apps/AppsConnect.test.tsx ui/src/pages/apps/Browse.test.tsx ui/src/lib/app-brand-assets.test.ts` plus `connector-tool-policy` and `tool-catalog-publication`: all passed after the rebase onto the split tool-access modules. - `node --test scripts/generate-unikraft-tools.test.mjs scripts/generate-daytona-tools.test.mjs scripts/app-brand-validation.test.mjs`: 20 passed. - `node scripts/check-app-brand-assets.mjs`, `node scripts/check-maps.mjs`, and `git diff --check`: passed. - `pnpm --filter @paperclipai/shared typecheck`, `pnpm --filter @paperclipai/server typecheck`, and `pnpm --filter @paperclipai/ui typecheck`: clean. - `npx playwright test --config tests/e2e/playwright.config.ts tests/e2e/unikraft-connector.spec.ts tests/e2e/daytona-connector.spec.ts`: 2 passed. - `node scripts/generate-unikraft-tools.mjs` regenerates the committed catalog with the recorded hashes. - Manual: on a local instance, open Connectors, search for Unikraft, and select **Add key**. Confirm the icon, the password field, the key guidance, and the default metro select under **Change**. - Not verified: a real Unikraft account. Live provider read and write proof is pending. ## Risks - A Unikraft token acts for the whole organization in every metro. Unikraft offers no narrower token permissions. Assign only trusted agents and review action permissions. - Sandbox actions run arbitrary commands inside the selected instance. They are classified as destructive. - A timed-out write can still complete at the provider. The bridge does not retry writes automatically. - New metros fail closed until the specification is regenerated and reviewed. Legacy `*.kraft.cloud` hosts are not reachable. - The Daytona refactor moves code without behavior changes. All Daytona tests pass without edits. - The generated JSON snapshot is large because it holds the provider input contracts. No migration or lockfile change is required. ## Model Used - Claude Opus 5.5 (Anthropic), model ID `claude-opus-5-5`, 1M context window, used through Claude Code with tool use (shell, file editing, web research, browser tests). ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [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 |
||
|
|
def4726bea |
feat(ui): add the artifact directions lab with the MVP V1 kit (#17213)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agents produce artifacts: documents, files, pictures, video and links. The app shows them in the task thread, in the right panel's Artifacts tab and on the Artifacts page > - The three surfaces grew one at a time. Their artifact presentation is dated and does not match > - A redesign needs a side-by-side comparison of several directions on the real chrome, in both themes, with hover states, before any product code changes > - This pull request adds a backend-free design lab under `ui/src/artifact-directions`: the shipped presentation as the baseline, four exploratory directions, and the MVP V1 kit drawn from the PCLP-Core mocks > - The benefit is a shareable, capturable reference for the artifact redesign that touches no product code path ## Linked Issues or Issue Description No public issue exists. This section follows the feature request template. **Subsystem affected** The web UI (`ui/`): the task thread, the right panel's Artifacts tab and the Artifacts page. The change is a design lab beside the app, not a change to those surfaces. **Problem or motivation** The three artifact surfaces are being redesigned. Designers must compare candidate directions on the real chrome, in dark and light, with hover states, and share a link. No harness for that exists. Figma mocks do not show the real chrome or the themes. **Proposed solution** A separate Vite entry (`ui/artifact-directions.html`) renders static mocks of the three surfaces. A "kit" supplies the artifact components for each surface. Kits: Today (the shipped components fed with fixtures), four directions (1.Solid, 2.Tint, 3.Tactile, 4.Hybrid) and 5.MVP V1 built from the Figma mocks. A toolbar switches kit, surface, theme and hover animation. The state lives in the URL, so any view can be linked and captured. **Alternatives considered** Figma mocks only: no real chrome, no themes, no hover. Storybook stories only: no page-level composition and no shareable static build. The lab keeps two Storybook stories as a secondary view. **Roadmap alignment** The lab supports the "Artifacts & Work Products" theme in `ROADMAP.md`. It is a design reference. It is not a product feature and it does not ship in the app bundle. **Additional context** The lab builds with its own config (`ui/vite.artifact-directions.config.mjs`). The app's `vite build` does not include it. A build of this branch is live at https://paperclip-artifact-directions.vercel.app. That preview also carries two surfaces that are not in this pull request (a media preview overlay and a panel closeup); they are parked on a separate branch. ## What Changed - Add the lab entry, its Vite config and the shell: `ui/artifact-directions.html`, `ui/vite.artifact-directions.config.mjs`, `ui/src/artifact-directions/` (static frames for the thread, the panel and the Artifacts page, a `fetch` stub for the lab's own page, fixtures, the kit contract, URL state, a sticky two-row toolbar). - Add the Today kit: the shipped artifact components, fed with the lab's fixtures. - Add four directions, each with its own `tokens.css` scoped to `[data-direction]`: 1.Solid, 2.Tint, 3.Tactile, 4.Hybrid. - Add the 5.MVP V1 kit from the PCLP-Core mocks: Artifacts page stacks and single tiles, the right panel's row list, thread rows grouped inline when one message produced several, a hover animation (the backing pages turn 5°, the artwork rises 6px), light-mode values, Paper Mono for the task pill. - Set Paper Mono for every monospace run in the lab (`lab.css`), from the face and `--font-paper-mono` that `index.css` declares. - Add two Storybook stories under `design-proposals` (`artifact-directions-compare`, `artifact-directions-hybrid`), annotated for the Storybook catalog as proposed prototypes on fixtures, and a capture script (`shot.cjs`). - Add two `.claude/launch.json` entries: the lab's dev server and its static preview. - Add Vitest coverage for the lab's logic: URL state, the API stub, the kit's kind treatment, type labels and media kinds, its date labels, print fitting and the thread's inline grouping (six files). ## Verification - Run `cd ui && npx vitest run src/artifact-directions`. The six lab test files pass (31 tests). - Run `cd ui && npx tsc -p tsconfig.json --noEmit`. The output is clean apart from the five pre-existing `PluginOrganizationSwitcher` errors. - Run `node scripts/check-token-gates.mjs`, `node scripts/sync-agent-palette-tokens.mjs --check` and `node scripts/sync-cliplab-character.mjs --check`. All gates are clean. The lab directory is outside the token-gated paths; its tokens are lab-local. - Start the lab: `cd ui && npx vite --config vite.artifact-directions.config.mjs --port 5180`. Open `http://localhost:5180/`. The page lands on 5.MVP V1's Overview in dark mode with animation on. Switch kit, surface and theme in the toolbar; the URL follows. - Open `http://localhost:5180/?d=d5-v1-mvp&s=gallery` and hover a stack: the two backing pages turn and the first page rises. Open `?s=thread` and `?s=panel` for the rows. - Build the lab: `cd ui && ARTIFACT_DIRECTIONS_OUT_DIR=/tmp/artifact-lab npx vite build --config vite.artifact-directions.config.mjs`. - Headless checks ran against the dev server during the work: toolbar labels, defaults and keys; thread and panel row geometry (58px rows, 8px and 12px gaps); the hover animation (5° turn, 6px rise, one easing curve); pill fills per theme; Paper Mono resolution on every monospace run. The measured values are in the kit's doc comments. - Run `node scripts/storybook-catalog.mjs --check` (the check `ui typecheck` runs first): the catalog accepts both stories. - Not run: the repo-wide `pnpm -r typecheck` (it needs the Rust toolchain for `paperclip-runner`) and `pnpm build`. The change adds files under `ui/src/artifact-directions` and `ui/storybook/stories/design-proposals` and edits `.claude/launch.json`; it changes no shipped module. CI runs the full Vitest suite. ## Risks - Low risk for the product. The app bundle does not include the lab. The lab's `fetch` stub installs only on the lab's own page. - Storybook gains two stories; the Storybook build includes them. ## Model Used - Claude Fable 5.1 by Anthropic, model ID `claude-fable-5-1`, used through Claude Code in the desktop app. Extended reasoning was on. Capabilities used: tool use (shell, file edits, a headless Playwright browser for measurements and captures, the Figma MCP server to read the mocks) and image input for mock screenshots. The context window is the Claude Code session's; its exact size is not surfaced to the session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above (none found for "artifact directions lab", "artifacts redesign", "artifacts tab design") - [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 lab's Vitest files, the UI typecheck and the token gates; CI runs the full suite) - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes (no product behaviour or command changed; the lab documents itself in `kit.ts` and the frames) - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |