mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-09 16:02:36 +01:00
795ad16c1f74bb5feb67d75ffd5f960f9a9a9ebe
753
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
464e6e16e0 |
fix(native): resume copyback after a restart kills its same-host owner; one board action otherwise (#19717)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Native runs save the agent's workspace files after the provider turn finishes (copyback) > - One controller owns copyback at a time. The run records that owner in `runnerProfileJson.nativeWorkspaceFinalizationOwner` (host, PID, token) > - A control-plane restart can kill the controller during copyback. The dead controller can never confirm its own stop > - Recovery then waited for a board confirmation. No surface offered that confirmation, so the run stayed `running` and the task stayed `in_progress` with no visible action > - This pull request lets the next controller on the same host prove the stop by itself. It also gives the board one clear action when that proof is not possible > - The benefit is that a restart during copyback resumes by itself, and a task never waits silently for a person ## Linked Issues or Issue Description **What happened?** In a Daytona restart-chaos wave, a kill during workspace copyback left the run `running` and its task `in_progress`. Recovery reported `native_workspace_finalization_owner_unverified`. The run was still `running` when the wave timed out. **Steps to reproduce** 1. Start a native remote (sandbox) run. 2. Kill the control-plane process (SIGKILL) after the provider result is accepted, during copyback. 3. Restart the control plane on the same host. **Expected behavior** If the previous controller and its copyback children are proven stopped on this host, recovery resumes copyback without a new agent turn. Otherwise, the task shows one board action to confirm that the previous server stopped. **Actual behavior** The recorded owner was cleared only by `resumeNativeWorkspaceAfterOwnerStop`. Same-host recovery also required a completed-copyback barrier, which an interrupted copyback never has. The task presentation showed `working`, and the UI had no control for the confirmation. Refs #19578 (boot-ID fencing for unstarted runs; same proof style). ## What Changed - Root cause: `server/src/services/native-runtime/native-workspace-finalization-ownership.ts` sent a dead same-host owner to `requireStopVerification` when no `workspace_finalize` operation had succeeded. That case is exactly a restart during copyback. - New `native-workspace-owner-stop-proof.ts`. The owner receipt now records the controller's process group (`processGroupId`). Copyback children (tar, Git) are not detached, so they keep that group. A successor on the same host releases the receipt only when the receipt names another controller boot, the PID is dead or recycled (process start time), and the group is empty or has no member outside the successor's own process tree that started after the old controller. Age alone never proves a stop. - A still-live group member returns `local_stop_pending`. The finalization worker rechecks it on its existing ownership recheck interval. The board action stays visible meanwhile. - A successful local proof writes `issue.workspace_owner_stop_verified` with the proof and marks the recovery `resuming`, like the existing platform proof. - A receipt from another host, a receipt without a process group, or a host without `ps` keeps the fence. The task interruption is now `waiting_for_user` with `userAction: "confirm_owner_stop"` (new shared enum value), not `working`. - UI: the task chat shows one **Confirm the previous server stopped** action. It asks for stop evidence and calls the existing `resume-workspace-finalization` API. It is shown only to roles that hold `runtime:confirm_owner_stop` (company owner or administrator, local board, instance administrator). The inbox names the same action. - The copyback advisory lock, the coordinator finalization lease, and remote save fencing are unchanged. - Docs: `doc/native-workspace-finalization-recovery.md`. ## Verification - Red then green on embedded Postgres (`server/src/services/native-runtime/native-workspace-finalizer.test.ts`): - same-host controller killed with SIGKILL, its process group empty: before `owner_unverified`, after `acquired` with the proof logged and no agent wake - a non-detached orphan child of the dead controller still runs: `local_stop_pending`, no copyback; after the child exits, `acquired` - a receipt without a process group: still `owner_unverified` - a foreign-host owner: the task presentation was `working` (red), now `waiting_for_user` / `confirm_owner_stop`; after the board confirmation it is `working` again - The existing orphan test (a detached child) and all other finalizer tests pass: `npx vitest run src/services/native-runtime/native-workspace-finalizer.test.ts src/__tests__/native-workspace-finalization-work.test.ts src/services/task-interruption-presentation.test.ts` (135 passed). - UI: `npx vitest run src/components/WorkspaceExportRecovery` (34 passed), including the action call body and the non-administrator case. - `pnpm check:token-gates` clean. Server and UI typecheck clean for the changed files. - Live Daytona restart-chaos wave: results are added in a comment below. ## Risks - A process-table check that reports a member wrongly as live only keeps the existing fence. The board action is still available. - A subreaper that adopts orphans does not change their process group, so the proof does not depend on the parent PID. - A child that a future change spawns with `detached: true` would leave the group. Copyback paths do not do that today. The existing detached-orphan test still fails closed, because a receipt without a process group is not released. - Old receipts have no process group. They keep the board action. ## Model Used - Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, used through Claude Code with tool use (shell, file edits, test runs). ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
f5fb8ada3b | Restore chat contacts, agent pins, and scrollable recent navigation (#19685) | ||
|
|
752cb8d3da |
fix(ui): contain patch previews and highlight diff source (#19478)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Tasks show documents and file attachments in cards and file views. > - Patch source needs clear added and removed lines in each view. > - Long patch lines can exceed the width of an inline preview. > - This pull request keeps the preview inside the card and adds patch colors. > - Users can read a compact patch preview and open the full source. ## Linked Issues or Issue Description **What happened?** Patch text can exceed the inline document box. Patch files and patch code blocks show plain text in the document view. **Expected behavior** Keep source inside its preview. Show added lines in green and removed lines in red. Keep headers, source markers, copy controls, line numbers, and downloads. **Steps to reproduce** 1. Open a document card with a diff code block that has long unbroken lines. 2. Open a `.patch` or `.diff` attachment in a task tab. 3. Open the same patch in the workspace file view. **Paperclip version or commit** Source checkout based on `e82210386f1e`. **Deployment mode** Built from source. The browser checks use Storybook fixtures. Related work: #19269 adds inline diffs for file edits. This change uses its line classifier for document and file source views. ## What Changed - Share the unified diff line classifier with file and document views. Track hunk lengths so later file headers keep their metadata style. - Add safe patch source rendering for patch files and `diff` or `patch` code blocks. - Clip long lines with an ellipsis in compact cards. Wrap the full source in file views. - Add a Preview patch action for small `.patch` and `.diff` attachments, including generic binary MIME types. Opening a large artifact list does not fetch patch source. Bound the actual response bytes. Reject remote preview URLs and redirects. Keep download and retry fallbacks. - Add patch text colors with sufficient contrast in both themes. Keep source-line selection visible over patch row colors. Copy the original patch text without layout line breaks. - Add five production component stories and browser checks at two widths in both themes. - Document the focused Storybook browser command. ## Verification - Final base qualification at `a120e0ada3f1eee9746f47a10384b5aa95f79824`: normally integrated the already-merged #19610 model-fixture repair (`8621bcf53ee2e4bbefb7d193add42dd544ca06e8`), preserving the reviewed patch preview changes. Official preflight passes (1.8s); all 129 focused tests pass again (23.67s), with UI typecheck and token gates passing. Current revision CI and reviews are pending; prior-head review receipts below are not current-head approval. - Conflict qualification at `befc954a6116f7292506200b96623b673f9385b5`: normally merged current master `c66b4a55efdc5675b5a5146197078b94de6407da`, resolving the append-only `ui/src/index.css` conflict by retaining both the patch rules and all current agent identity rules. No feature behavior was changed during resolution. Official isolated preflight passes. The seven focused component/parser suites pass 129 tests; UI typecheck and token gates pass. Fresh head CI and reviews are pending. - Qualification setup limits: the first focused command used the repository root instead of the UI working directory, so setup failed before any test ran. It was corrected to the UI directory and actual attachment-test path. The first UI typecheck found the unbuilt local plugin SDK; building that checkout’s SDK and repeating typecheck passes. These setup attempts are not test/typecheck passes. - Focused Vitest run: 139 tests passed in eight files. This includes source preservation, HTML escaping, large patches, tabs, Markdown wrapping, line numbers, and transcript diff parsing. A 200-card check confirms no patch fetch occurs before a preview request. CRLF regressions cover no-newline markers and added lines that start with `+++`. - `pnpm --filter @paperclipai/ui typecheck`: passed after the plugin SDK build prerequisite. - `pnpm check:token-gates`: passed. - Storybook catalog check and 30 map/catalog tests: passed. - `STORYBOOK_TEST_BASE_URL=http://localhost:6006 pnpm exec playwright test patch-preview.spec.ts --config=tests/storybook-visual/playwright.config.ts --project=stories --workers=2 --retries=0`: 20 passed on Linux Chromium. The checks include accessibility, theme colors, overflow, opening a document, wrapping source, exact clipboard contents, and the selected source line. Screenshots were inspected and saved to the task. - The first browser runs found contrast failures in diff text and source gutters. Patch text tokens and patch gutter opacity now fix those failures. The final run passes without retries. - `pnpm verify`: exit 2. The new browser spec is a global CI input. Required CI must supply broad coverage. - The local full Storybook build was killed with exit 137. This is not a build pass. External screenshot baselines are not published, so no baseline comparison was run. - Reviews found selected-row background precedence, file headers in unified patches without git separators, eager patch loading across a collection, and CRLF no-newline markers. Each finding has a focused fix and regression checks. The Storybook hunk count now matches its source lines. - Prior feature commit `b3cb9d6d3c0423315540514b1ad68325a64c1cc2`: [CI typecheck, build, tests, runner checks, and E2E passed](https://github.com/paperclipai/paperclip/actions/runs/42247974154). [Security scan passed](https://github.com/paperclipai/paperclip/runs/127995160859). [Greptile is 5/5](https://github.com/paperclipai/paperclip/pull/19478#issuecomment-6688482753), and [Paperclip Review is 5/5](https://github.com/paperclipai/paperclip/runs/127998788846). All six inline review threads are resolved. ## Risks - Compact previews omit the end of long lines. The full document and downloads keep the source. - Patch colors apply to unified diff syntax. Other patch formats keep literal text and do not have full format parsing. - The shared classifier keeps the existing task chat behavior. Regression tests cover that consumer. - No database, API, or access rules change. ## Model Used - OpenAI Codex, GPT-6, with reasoning, tool use, and code execution. The runtime did 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 - [ ] 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> |
||
|
|
07a548073a |
fix(ui): keep inline document links in the text line; plain-text request previews (#19639)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents talk to people in task chat. Their messages render as
markdown.
> - In an onboarding walk, two chat papercuts made agent text hard to
read.
> - First: a document link inside a sentence ("Your [plan is saved],
approved, ...") rendered as a padded card. The card is taller than the
text line, so it overlaps the lines around it.
> - Second: the one-line row above a pending review card showed the
agent's raw markdown summary (backticks, "- ", "**").
> - This pull request renders document links in running text as an
inline chip, and flattens the collapsed preview to plain text.
> - The benefit is that agent messages and pending-request rows read
cleanly.
## Linked Issues or Issue Description
**What happened?**
1. In task chat, an agent wrote: "Yes—we completed the onboarding
interview here in chat. Your [plan is saved](#document-plan), approved,
and handed off to execution task PIX-3." The "plan is saved" link
rendered as a 42px-tall bordered card in a 20px text line. It overlapped
the text above and below and left the text baseline.
2. The collapsed row above a "Review the creative brief (v1)" card read:
"The `creative-brief` document is saved on this task. It covers: -
**Brand voice and audience:** ..." with literal markdown syntax.
**Steps to reproduce**
1. Open a coordinator task chat where an agent message has a
`#document-...` link inside a sentence. Or open the Storybook story
`coordinator-conversation--inline-document-link`.
2. Open a task with a pending request whose summary contains markdown.
Or open
`composer-interaction-above-composer--pending-request-markdown-summary`.
**Expected behavior**
1. The document link sits in the text line like other inline links.
2. The collapsed preview shows the words as plain text.
## What Changed
- `SidebarDocumentLink` gets a `variant` prop. `card` (default) is
unchanged and is still used by the standalone plan preview card.
`inline` is a text-flow chip: `display: inline`, horizontal padding
only, a small muted background, and a 14px icon aligned to the text
bottom. Token classes only.
- `MarkdownBody` uses the `inline` variant for both document-link paths
(coordinator issue document links and `#document-...` hash links). The
label no longer uses `truncate` (nowrap), so long labels wrap with the
sentence.
- New `ui/src/lib/markdown-plain-text.ts` (`markdownToPlainText`): drops
code ticks, emphasis/strikethrough markers, list/heading/quote/task-box
prefixes, fences, rules, link/image targets and inline HTML tags, keeps
snake_case intact, and collapses whitespace. Unit tests included.
- `TaskChatInteractionCard` flattens the collapsed pending-request
summary and the unanswered-question prompt with `markdownToPlainText`.
- Stories: `Coordinator conversation / Inline document link` (+ dark)
with a play check that the link is no taller than the line and starts
inside the paragraph; `Interaction above composer / Pending request
markdown summary` with a play check that the row has no markdown syntax.
## Verification
Red on master (`e482f0f632`), then green with the fix:
```
# Red (master + new tests)
× renders a document link inside a sentence as inline text, not a padded card
AssertionError: expected 'inline-flex max-w-full items-center gap-2 rounded-lg border border-border bg-muted/25 px-3 py-2.5 ...' not to match /(^|\s)(inline-flex|flex|block|py-\S+|p-\S+)(\s|$)/
× shows the collapsed pending-request preview as plain text, not raw markdown
AssertionError: expected 'Review the creative brief (v1)The `cr…' to contain 'The creative-brief document is saved …'
Tests 2 failed
# Green (fix)
Tests 7 passed (the 2 above + 5 markdownToPlainText unit tests)
```
Browser geometry check (Playwright against Storybook, story
`coordinator-conversation--inline-document-link`, light and dark). It
measures the link box against the paragraph line-height and the text
node before the link:
```
# Before
light: FAIL lineHeight=20 chipHeight=42.0 chipTop=61.7 chipBottom=103.7 textTop=76.7 textBottom=93.7
dark: FAIL lineHeight=20 chipHeight=42.0 chipTop=61.7 chipBottom=103.7 textTop=76.7 textBottom=93.7
# After
light: PASS lineHeight=20 chipHeight=17.0 chipTop=62.7 chipBottom=79.7 textTop=62.7 textBottom=79.7
dark: PASS lineHeight=20 chipHeight=17.0 chipTop=62.7 chipBottom=79.7 textTop=62.7 textBottom=79.7
```
The story's own play function also failed on master in the browser:
`AssertionError: expected 42 to be less than or equal to 20`.
Inline document link, before / after (dark, then light):




Collapsed pending-request preview, before / after:




Neighbouring suites: `npx vitest run src/components/MarkdownBody
src/components/task-chat src/lib/markdown-plain-text.test.ts
src/components/MarkdownDocumentCardStyles.test.ts
src/components/MarkdownExternalLink.test.tsx` → 67 files, 1001 tests
passed.
Also run: `pnpm check:token-gates` (clean), UI `tsc -b` (no errors in
changed files; the only errors were an unbuilt local
`@paperclipai/plugin-sdk`), `node scripts/storybook-catalog.mjs`. `pnpm
verify` exited 2 (story file is a broad input), so broad coverage comes
from required CI.
## Risks
- Low risk. UI-only styling and text change.
- Document links in markdown now look like inline links with a small
icon instead of a card. A link that sits alone in its own paragraph also
renders inline. The standalone plan preview card keeps the card style.
- `markdownToPlainText` is a regex flattener for one-line previews, not
a full markdown parser. An unusual construct can keep a stray marker. It
does not change stored data.
## Model Used
- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, via Claude Code with
tool use (shell, file edits, Playwright browser checks).
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] 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>
|
||
|
|
411eecdccd |
fix(ui): store = as typed, without the highlight exporter's escapes (#19540)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - People write task requests and chat messages in the Markdown editor, and the stored text becomes the agent's prompt > - MDXEditor supports `==highlight==` marks, and its exporter escapes every `=` in prose to protect that syntax > - The editor therefore stores `a=b` as `a\=b` and `x=>y` as `x\=>y` > - A command or code snippet in a chat message then reaches the agent as invalid code > - This pull request removes the `=` escape when the escape cannot change how the text parses, as #19350 did for intraword underscores > - The benefit is that commands, assignments and arrows reach agents exactly as the person typed them ## Linked Issues or Issue Description Refs #19350 **What happened?** A chat evaluation sent a `node -e` command through the chat composer. The stored comment contained `const fs\=require(...)` and `()\=>`. Every `=` had a backslash. The agent received invalid JavaScript, and an exact-text check on the stored message failed. **Expected behavior** Text the person types is stored as typed. A `=` that cannot start or end a highlight needs no escape. **Steps to reproduce** 1. Type `a=b` or `x => y` in any Markdown editor field, such as the chat composer. 2. Read the stored value through the API. 3. Before this change it is `a\=b` or `x \=> y`. ## What Changed - New `ui/src/lib/equals-markdown.ts`: `unescapeEqualsSigns` removes `\=` escapes from prose only when they cannot change the parse: - any run of escaped `=` whose length is not exactly two (a highlight sequence is exactly two `=`); - a run of exactly two with whitespace or the text edge on both sides (such a run can neither open nor close a highlight). - Other two-runs, such as `a\=\=b` or `\=\=text\=\=`, stay escaped. Escaped backslashes (`\\=`) stay as they are. - `ui/src/lib/underscore-markdown.ts`: the code-range walk is now the shared `rewriteMarkdownProse` helper. Code spans, code blocks and raw HTML stay byte-identical for both rewrites. Underscore behavior does not change. - `MarkdownEditor.tsx`: `toStoredMarkdown` applies the new step after the underscore step, on the exporter's exact text. - Tests: unit cases for commands, `===`, spaced `==`, quotes and lists, highlight-capable runs, code spans and blocks, raw HTML and escaped backslashes. One editor test for a pasted command with a code block. ## Verification - `npx vitest run src/components/MarkdownEditor.test.tsx src/lib src/components/task-chat` in `ui/`: 280 files, 3388 tests passed. - Negative control: with the new step removed from `toStoredMarkdown`, the new editor test fails. - Parser check: I parsed the unescaped forms with `micromark-extension-highlight-mark` 1.2.0, the version MDXEditor uses. `a=b and c=d`, `x === y`, `a == b == c`, `()=>x` and `x!==y` produce zero highlight nodes. The controls `==a==`, `a ==b== c` and `say ==this== now` produce one highlight node each. - `tsc -p ui/tsconfig.json`: no errors in the changed files. The remaining errors are in files this change does not touch. ## Risks - Low risk. The step only removes an escape when the highlight tokenizer cannot use that `=`. Text the parser cannot place is returned unchanged. - Some `==` in code-like prose (for example `x!==y`) stays escaped. This is intentional: such a run can open a highlight. > 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 Opus 5.5 (`claude-opus-5-5`), Anthropic, with tool use and code execution in Claude Code. ## 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> |
||
|
|
6148fbd31f |
feat(ui): distinguish GitHub resources in inline Markdown links (#19476)
## Thinking Path > - Paperclip helps people manage AI agents and their work. > - Task conversations and documents use the shared Markdown renderer. > - GitHub repository, pull request, and issue links currently use the same icon. > - Long pasted URLs make these references hard to scan in a conversation. > - This change identifies each resource from its URL and shows a compact label with a distinct icon. > - The exact destination and custom link text stay intact. Connected status data keeps its existing behavior. ## Linked Issues or Issue Description **What existing behavior does this improve?** Inline GitHub links in rendered Markdown. **Current behavior** Repositories, pull requests, and issues all use the GitHub mark. Pasted resource links show the full URL. **Proposed behavior** Pull requests use the pull request icon. Issues use the issue icon. Repositories and other GitHub pages keep the brand mark. Pasted resource URLs show `owner/repository#number` or `owner/repository`. Custom labels keep their text and formatting. **Reason and benefit** Readers can identify GitHub resource types and scan references in a narrow conversation. Full URLs, query strings, and comment anchors stay available through the link destination. Link rendering makes no remote metadata requests. **Breaking changes** The visible text of a bare GitHub resource URL becomes compact. The destination does not change. No API, database, or connection changes are required. Searches found no duplicate work for GitHub inline resource presentation. Related work: [same-origin Markdown routing](https://github.com/paperclipai/paperclip/pull/17864). This change preserves that route handling. ## What Changed - Add a pure GitHub URL classifier with exact host checks and resource labels. - Move ordinary URL presentation into `MarkdownUrlLink`. Keep internal references, workspace links, custom resolvers, and connected metadata in their existing order. - Add separate icons and accessible resource names. Preserve authored Markdown titles and formatted labels. - Add Playground, Narrow, and Streaming Storybook examples that mount `MarkdownBody`. - Add parser and renderer tests, eight Chromium browser cases, and the browser command in the development guide. - Consider Open Graph loading. Use the existing connected metadata path for remote status and titles. Add no arbitrary page fetches. ## Verification - Focused Vitest coverage: 129 passing tests across nine files for GitHub parsing, Markdown rendering, connected metadata, document rendering, and workspace-file rendering. - `pnpm check:token-gates`. - `pnpm --filter @paperclipai/ui typecheck`. - `pnpm --filter @paperclipai/ui build`. - `pnpm build-storybook`. - Storybook catalog generation/check and 30 catalog/map tests. - Site-route regression: Stars, Education, and enterprise pages keep general GitHub branding and their full URL text. Three parser cases failed before the fix; parser and renderer cases now pass. - Streaming regression: three resource cases failed before the fix and pass after it. The fix preserves the generated word span and custom formatted labels. - Chromium: `STORYBOOK_TEST_BASE_URL=http://localhost:6106 pnpm exec playwright test inline-links.spec.ts --config=tests/storybook-visual/playwright.config.ts --project=stories`. - Browser scope: eight passing cases for ordinary/streaming modes, dark/light at desktop and 390px mobile, completed play assertions, exact comment destinations, safe external attributes, keyboard focus, wrapping, and no GitHub requests. Screenshots are saved as task artifacts; no review images are committed. - The first browser attempt in the resumed environment could not launch Chromium because its executable was missing. The browser was installed, and all eight cases then passed. - The browser cases use synthetic text and one connected metadata fixture. They do not prove provider authentication or server persistence. No visual baseline comparison is claimed; the repository baseline manifest is unpublished. - Initial typecheck found two unsupported story assertion options and an unbuilt SDK dependency in the fresh checkout. The options were removed and the SDK was built before the successful retry. - `pnpm verify` returned 2 because the new browser spec requires broad CI coverage. Focused tests and the browser suite supply local evidence. Required CI supplies broad coverage. ## Risks - Compact labels hide URL detail from the visible line. The exact href and default tooltip preserve that detail. - GitHub site routes can change. Unknown paths retain the general GitHub treatment. Lookalike hosts and credential-bearing URLs do not get GitHub resource treatment. - Connected external-object status and title rendering keeps priority over URL-derived presentation. ## Model Used OpenAI Codex, GPT-6 (`gpt-6` family), with reasoning, tool use, browser checks, and code execution. The exact deployment ID and context window are not exposed in this run. ## 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> |
||
|
|
c650f36007 |
fix(ui): refine agent profiles, identity editing, and list actions (#19535)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent pages expose identity files, reporting relationships, and
runtime settings.
> - Several controls had inconsistent spacing, weak navigation, or
misleading save feedback.
> - Empty task-row detail slots also reduced the title width before
truncation.
> - This pull request fixes those behaviors and aligns the reviewed UI
details.
> - The result is clearer agent editing and more readable task and agent
lists.
## Linked Issues or Issue Description
**What happened?**
Agent headers and file controls had inconsistent layout. The Identity
footer appeared without edits and did not provide clear save
confirmation. File names could wrap or omit the Markdown suffix. Task
titles truncated while empty detail slots occupied the row.
**Expected behavior**
Keep headers and actions aligned. Reveal the Identity footer only for
changes or save feedback. Use valid Markdown file names and actual file
dates. Let titles use available space.
**Steps to reproduce**
1. Open an agent overview, then its Identity tab.
2. Edit, undo, save, copy, and add an instruction file.
3. Resize the file panel and inspect file names and date labels.
4. Hover an agent row and inspect the Chat action and tooltip.
5. Open a task list with no recovery or external details and inspect
title width.
Related: #18716 is the prior UI bundle. #16934 and #14483 concern role
editing; this change does not add a role picker.
## What Changed
- Refine the character header, inline title and name editing, crown
position, runtime shortcut, and Chat/New task actions.
- Align profile metadata and manager selection; hide empty direct
reports.
- Refine Identity panels, Markdown filename validation, file-row hover,
truncation, Paper Mono typography, and copy feedback.
- Add a viewport-bound save footer with dirty, saving, and saved states.
Keep undo/discard separate from successful saves.
- Return recorded creation or modification dates for instruction files.
Reuse the active file transaction for metadata reads to avoid exhausting
the small connection pool.
- Reveal the agent-row Chat icon and label on hover, with a standard
delayed tooltip.
- Collapse empty task-row details so titles can use the available width.
## Verification
- Browser checks covered the local overview and Identity flows, narrow
file panels, successful file creation/update, undo/discard, header
navigation, row hover, tooltip delayed-open state, and full task titles.
- Focused instruction, save-footer, date, font-asset, and task-row tests
passed during development. After review, 55 file/instruction tests
passed, including cold restoration with recorded and unknown dates;
server typecheck and 18 immediate-save response tests also passed.
- Full `pnpm -r typecheck` and `pnpm build` passed after rebase onto
current master. The complete `pnpm test:run` attempt hit a 15-second
timeout in the existing chat Retry HTTP integration test; that case
passed in isolation (1 test passed). A second full attempt hit timeouts
in two other chat integration cases (GitHub webhook draining and
delivery retry budget); both passed in isolation without increasing
timeouts. All 55 remote checks passed on
|
||
|
|
fd4b197f83 |
fix(ui): hide runner selection during agent setup (#19517)
## Thinking Path > - Paperclip lets people manage AI agents for work. > - Agent setup connects a harness, model, account, and computer. > - The system already selects a qualified runner for a new agent. > - Setup still asks users to select that internal runner. > - The runner dropdown can be the only field in Advanced. > - This PR removes the dropdown and hides an empty Advanced section. > - Users keep their saved execution settings and see fewer setup controls. ## Linked Issues or Issue Description **What existing behavior does this improve?** Agent creation, onboarding, built-in agent setup, company import, and agent configuration. **Subsystem affected** The UI, setup error messages, tests, and Storybook fixtures. **Current behavior** Users can select a runner from a dropdown. Some setup screens place only that dropdown in Advanced. Errors can direct users to that control. **Proposed behavior** Remove runner dropdowns from setup and configuration. Use the existing automatic selection for new agents. Retain saved runner settings. Show Advanced only when other fields remain. **Reason and benefit** Users can configure agents without an extra internal execution choice. Setup also avoids an empty Advanced section. **Breaking changes** Users can no longer select a runner through these UI dropdowns. The API and CLI retain their runner options. Existing agents keep their saved execution settings. **Additional context** Related: [Default new agents to the qualified runner for their harness](https://github.com/paperclipai/paperclip/pull/15422). This PR changes the existing setup UI. It adds no harness or runtime default. The master merge retains the custom gateway placement from [#19510](https://github.com/paperclipai/paperclip/pull/19510). ## What Changed - Remove the shared runner dropdown and its setup/configuration callers. - Hide Advanced when it has no remaining fields. Keep command and argument settings where supported. Preserve custom gateway setup under Advanced on the Claude and OpenAI API key paths. - Keep setup failures visible and keep the retry action outside the removed control. - Update errors and documentation that referred to the removed dropdown. - Update component tests and Storybook fixtures for the new UI states. - Make Legacy first-task evals resume an API-configured setup record. Record that path separately from fresh automatic onboarding. ## Verification - Latest master integration (`187c0f6d6e5`): 276 onboarding/provider-connection tests passed across six files. UI typecheck and build passed. Token gates, query-error rendering checks, and the Storybook catalog check passed. The conflict resolution retains master's bounded connection tests and cancellation while removing the obsolete runner instruction. The first test command used the wrong working directory and failed before collecting tests; the corrected invocation from `ui/` passed. - Earlier branch verification passed: full workspace build and typecheck, 1,037 focused UI/service tests, 49 heartbeat provider contract tests, eval typecheck, and 30 map/catalog tests. - The full local `pnpm test:run` run passed all six chat integration shards (1,931 tests). It was stopped for the master merge before the complete suite finished. The [complete CI run](https://github.com/paperclipai/paperclip/actions/runs/42264662642) passed on the previous head `72e1699`. - Current head `a097c8369d079c839e78661a2206cfa62c5210e0`: [full CI](https://github.com/paperclipai/paperclip/actions/runs/42273168268) passed. PR checks total 55 passed and 3 skipped, with none failed or pending. Greptile reviewed this head at 5/5 with no actionable findings or unresolved review threads. - Live browser/provider evals have not run. The Legacy eval change has no live qualification claim. ## Risks - Removing the dropdown changes the setup UI. Existing API and CLI runner choices remain available. - Conditional Advanced sections must retain valid command and argument fields. - Legacy first-task evals now prove setup resumption. They do not prove the fresh-agent automatic default. - No schema change or data migration is included. ## Model Used OpenAI `gpt-6.1-sol`, through Codex in T3 Code. Reasoning effort: `xhigh`. The model used file editing, shell commands, and test tools. The harness does not expose the context window size. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
e3d8f42e19 |
fix(ui): recover stalled onboarding connection checks (#19505)
Bound the complete onboarding connection check to two minutes, abort its requests on timeout, and ignore late results. Keep the saved account available for retry and resume its matching unfinished setup after refresh. Verified 242 focused tests, workspace typecheck and build, and the complete hosted CI check set. Greptile is 5/5 with no unresolved review comments. Local full-UI timing failure and interrupted CI runner attempts remain documented in the PR evidence. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
1485d3de1b |
fix(ui): hold announcements until the onboarding first task is finished (#19514)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - A new user's first session is the onboarding first task. The agent asks its onboarding questions in that task thread. > - The app also shows an optional in-app announcement. The live feed now serves "Introducing Connectors" (`2026-09-14-connectors`). > - The announcement well only waits while the onboarding wizard dialog is open. It shows 3 seconds after the user lands on the first task. > - In the Nov 5 cloud onboarding test (Claude API path), the tester said: "Don't show the connectors upsell until the second session. It's blocking the user flyout and potentially the onboarding questions." > - This pull request holds announcements until the company's onboarding first task is done or cancelled. > - The benefit is that a new user sees the onboarding questions and the account menu without an upsell on top of them. ## Linked Issues or Issue Description Refs #19511 (places the card in the desktop sidebar, above the account menu. That PR keeps the card off the account menu after onboarding. This PR adds the first-session gate that #19511 leaves open.) **What happened?** On a new company's onboarding first task, the "Introducing Connectors" card shows 3 seconds after the page loads. At 1440x900 the card (352x346 px, bottom-left, z-40) covers the sidebar account menu trigger and the left edge of the task composer. **Expected behavior** Optional announcements do not show in the first session, while the onboarding first task is open. **Steps to reproduce** 1. Create a new company through onboarding. The wizard creates the onboarding first task. 2. Open the first task at 1440x900 and wait 3 seconds. 3. See the announcement card on top of the account menu and the composer. **Paperclip version or commit** `master` at |
||
|
|
21a1e78852 |
feat(environments): add managed plugin environment rows (#19490)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - A managed instance gets its instance-level environments from the `PAPERCLIP_MANAGED_CONFIG` document > - That document cannot declare a plugin environment yet, so a managed instance cannot get a plugin-provided environment without manual setup > - The full change is split into three pull requests. This first one adds the plugin environment rows and their write floor, and nothing calls them yet > - The second pull request lets the managed config declare plugin entries and provisions them at boot. The third sets the instance default once and advertises the new managed-config capability > - The benefit is a smaller review for each step, and no instance changes behavior until the last step lands ## Linked Issues or Issue Description **Subsystem affected** Server environments (managed-config environment provisioning, environment routes) and the board UI's adapter Test target. **Problem or motivation** A managed instance cannot get a plugin environment from its managed config. Company settings cannot create one either. So each managed instance that needs one requires manual setup. **Proposed solution** Over three pull requests, let an `environments` entry in the managed config declare `driver: "plugin"`. Boot then provisions one locked row for each plugin entry, and makes one of them the instance default once on new instances. This pull request adds only the row layer: create or adopt a marked row, archive it, find it, and keep tenants from editing it. **Alternatives considered** Manual setup on each instance, and a new control-plane endpoint. Both need a step outside the deploy. The managed config already delivers the sandbox entry. **Roadmap alignment** This extends the existing managed-config `environments` section, which already provisions the managed sandbox. It adds no new product surface. ## What Changed - New `server/src/services/managed-plugin-environments.ts`, used through new `environmentService` methods (`ensureManagedPluginEnvironment`, `archiveManagedPluginEnvironment`, `findManagedPluginEnvironment`): - The ensure validates the driver config through `normalizeEnvironmentConfig` and `validatePluginEnvironmentDriverConfig`, the same path an operator-created plugin environment takes. - It marks the row `managedByPaperclip: true` and `managedPluginEnvironment: "<pluginKey>:<driverKey>"`. - It adopts an existing unmarked row for the same plugin and driver instead of adding a second one, so a hand-made row keeps its agents. - A row that already matches gets no write. Changes write activity log entries. - Archive sets an active marked row to `archived`. The next ensure reactivates it. - Migration `0437`: unique index `environments_managed_plugin_environment_idx` on `metadata ->> 'managedPluginEnvironment'`. This is the only schema change of the three pull requests. Snapshot `0432` is pruned to keep the five newest. - `server/src/routes/environments.ts`: `isPlatformProvisionedEnvironment` also covers the new marker (write floor and redaction). `managedPluginEnvironment` is a reserved marker key, so a client cannot stamp it on its own row. Nothing provisions marked rows yet, so the marker-clear escape hatch stays open for them. The next pull request refuses it while the managed config declares the row's entry. - `ui/src/lib/adapter-test-environment.ts`: `resolveManagedSandboxEnvironmentId` requires `driver === "sandbox"`. The plugin row also carries `managedByPaperclip`, so the old "not local" check could take it for the managed sandbox. ## Verification - `cd server && npx vitest run src/__tests__/managed-plugin-environments.test.ts` (embedded Postgres): - The ensure creates the marked row through the plugin validator. A second ensure writes nothing and logs nothing. - A hand-made row for the same plugin and driver is adopted. It keeps its id and its agents. - Archive, then ensure, reactivates the row. - The ensure refuses while the plugin has no running worker, and refuses a name that another environment holds. - The unique index allows one row per marker. - `npx vitest run src/__tests__/environment-routes.test.ts`: on a cloud-managed instance, edit, env-var edit, status change and delete of a marked plugin row are refused, including for instance admins. The marker alone keeps the floor. A client cannot stamp the marker. The marker clear is allowed. - `npx vitest run src/__tests__/environment-service.test.ts`: passes. - `cd ui && npx vitest run src/lib/adapter-test-environment.test.ts`: the plugin row is never taken for the managed sandbox. Under managed-sandbox-only, an agent on the sandbox tests in the sandbox, and an agent on the plugin environment tests there. - `pnpm --filter @paperclipai/server typecheck`, `pnpm --filter @paperclipai/ui typecheck` and `pnpm --filter @paperclipai/db check:migrations` pass. - I did not run the full `pnpm test:run`, `pnpm -r typecheck` or `pnpm build`. CI covers them. `pnpm verify` asks for broader verification because of the migration. ## Risks - Migration: one new partial unique index on a small table. No row carries the marker before this change, so the index cannot fail on existing data. - No caller uses the new ensure yet, so no instance changes behavior. - The UI change affects only lists that hold a non-sandbox row with `managedByPaperclip`. Today that is only the local row, which the old check already excluded. > 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 Opus 5.5 (`claude-opus-5-5`), Anthropic, through Claude Code with tool use (file edits, shell, test runs). ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
0b8578055a |
fix: restore trailing spaces in queued steering messages (#19456)
## Thinking Path > - Paperclip lets people manage AI agents and give them more instructions during work. > - The task composer sends those instructions through the shared Markdown editor. > - The editor writes a final text space as the HTML entity ` `. > - The composer trims spaces before it submits a message. An entity survives this step. > - Queued messages can therefore contain extra text that the person did not type. > - This pull request restores final prose spaces at the editor output boundary. > - The queue and the agent receive clean message text. Code and escaped examples keep their source. ## Linked Issues or Issue Description **What happened?** A message that ends with a space can contain a final ` ` when it enters the steering queue. The shared editor exports this entity, and normal message trimming does not remove it. **Expected behavior** The editor must return final prose spaces as spaces. Code samples and escaped literal entities must keep their exact text. **Steps to reproduce** 1. Open a task while its agent works. 2. Type a steering message with a space at the end. 3. Submit the message to the queue. 4. Inspect its stored Markdown. Before this fix, it can end with ` `. **Paperclip version or commit** Reproduced from `70d23612dd` with the installed Markdown serializer. The serializer writes `Steer the current turn ` as `Steer the current turn ` plus a newline. Searches for related trailing-space and steering-entity PRs found no duplicate. ## What Changed - Restore trailing space entities only in the final Markdown text node. - Apply this step before the editor removes its other transport escapes. - Keep code, raw HTML, escaped entities, links, internal entities, and hard breaks unchanged. - Limit the fix to an entity at the end of the message. Keep entities before internal newlines or closing emphasis markers. Replacing those entities with spaces can create hard breaks or remove bold and italic formatting. Add tests for these limits. - Add editor regression cases and focused Markdown cases. Keep the fix in the shared editor; no queue API change is needed. ## Verification - TDD: the new editor test failed in 3 cases before the fix. It received literal entities instead of spaces. All 6 cases pass after the fix. - All 353 focused editor, Markdown, composer, and queue tests pass. This includes 10 new cases for internal newlines, emphasis, and a final space after these cases. - `pnpm check:token-gates` and `git diff --check` pass. - UI typecheck and UI production build pass. - Repository typecheck and build could not complete locally because Cargo is not installed. The full test command was started, then stopped after confirming its native Runner cases also need Cargo. No complete local full-suite verdict is claimed. Current-head [CI](https://github.com/paperclipai/paperclip/actions/runs/42229743296) passes for `350af775850664226d6630072cb8e08732e2a218`. This includes typecheck, build, tests, and E2E checks. - [Greptile](https://github.com/paperclipai/paperclip/pull/19456#issuecomment-6686109030) and [Paperclip review](https://github.com/paperclipai/paperclip/pull/19456#issuecomment-6686063906) each score the current commit 5/5. No review threads remain open. - Checked the design-review dependency claim against the current commit. [ui/package.json already declares the parser](https://github.com/paperclipai/paperclip/blob/350af775850664226d6630072cb8e08732e2a218/ui/package.json#L71). The existing underscore helper uses the same parser. Six direct checks also pass for GFM strikethrough, task lists, URLs, and tables. - No visual style changed. No database or API contract changed. The helper comment documents the storage rule. ## Risks - Low risk. The change only restores encoded spaces at the end of the document. Internal line endings and spaces inside emphasis are out of scope. The tests keep these entities unchanged to preserve Markdown formatting. Parser source positions protect code and HTML. Escape pairs protect literal entity examples. - Existing stored messages are not rewritten. They use the corrected output after an editor change. ## Model Used - OpenAI Codex, GPT-6. GPT-6.1 Sol (`gpt-6.1-sol`) assisted with the review follow-up. The runtime does not expose the context-window size. Used reasoning, repository tools, code execution, 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> |
||
|
|
4696ff4990 |
fix: reserve agent In Progress display for active runs (#19453)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Task status must tell operators whether an agent is working or waiting. > - A task can retain its in-progress lifecycle status after its run stops. > - The shared read projection only handled scheduled monitoring waits. > - The UI also ignored other projected statuses for in-progress tasks. > - This pull request requires an active task run for the In Progress display. > - Operators can see waits without changing execution or recovery authority. ## Linked Issues or Issue Description **What happened?** An agent task still showed In Progress after its run ended with an access failure and left a pending connection request. Stale execution locks and saved lifecycle state could show the same false activity. **Expected behavior** An agent task shows In Progress only with a task-linked queued or running run. Otherwise, it shows Blocked for recovery, In Review for a pending response or review, Monitoring for a scheduled check, or Todo for remaining work. Human ownership keeps its selected status. **Steps to reproduce** 1. Create an agent-owned task with an in-progress lifecycle status. 2. End its run and retain a pending human request. 3. Read the task, its summary, and search results. Before this change, they still show In Progress. ## What Changed - Derive visible activity from company-scoped, task-linked runs in the existing shared SQL projection. - Project inactive tasks to existing waiting or todo states. Preserve lifecycle status, locks, admission, and recovery. - Make the shared UI resolver use the projection while preserving explicit and optimistic status changes. - Cover stopped runs, stale locks, human waits, company isolation, monitoring, filters, counts, search, and UI labels. - Document the presentation rule in the product and execution contracts. ## Verification - Red before the server fix: 7 new regression cases failed because they returned in_progress. The 10 existing cases passed. - Green after the server fix: 20 cases passed in issue-display-status.test.ts, using embedded Postgres and real task APIs/search. Seven nearby active-question cases also passed. - Review regression: dismissed requests, historical questions, and returned review work each failed before the follow-up fix. All three now pass using the existing active-interaction rule and pending review state. - Red before the UI fix: 4 label cases failed. Five additional safety cases caught stale projections hiding explicit transitions. - Green after the UI fix: 43 tests passed across task-status-presentation, issue-filters, and issue-detail-subissues. - pnpm -r typecheck passed. All UI token gates and synchronization checks passed. - pnpm build passed. Server typecheck and build passed again after the review fixes. - Full CI passed on |
||
|
|
e9999071f3 |
fix(ui): store intraword underscores as typed, without the editor's escapes (#19350)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - People write task requests in the Markdown editor, and the stored
text becomes the agent's prompt
> - MDXEditor exports every literal underscore as `\_`, even inside
words such as `E2E_ASK_12` or `snake_case`
> - Agents then see backslashes the person never typed, and sometimes
repeat them in their answers
> - This pull request removes only the intraword escape when the editor
hands text back, as is already done for `\>` and `\<`
> - The benefit is that identifiers, filenames and exact strings reach
agents exactly as typed
## Linked Issues or Issue Description
**What happened?**
In QA staging smoke (launch 3108, task QA-671), a person created a task
through the UI that asked for the exact reply
`E2E_ASK_12_journey_1793913565974_507b01b8`. The stored description, and
the agent's prompt, contained `E2E\_ASK\_12\_journey\_…`. The agent's
`paperclip_finish` summary was unescaped, but its final answer copied
the escaped form. The posted reply therefore did not equal the requested
text, though the rendered Markdown looks the same. Earlier attempts
passed only when the model happened to unescape.
**Expected behavior**
Text the person typed is stored as typed. An underscore inside a word
never needs an escape, because CommonMark never treats it as emphasis.
**Steps to reproduce**
1. Type `snake_case` in any Markdown editor field, such as a new task
description or the chat composer.
2. Read the stored value through the API.
3. Before this change it is `snake\_case`.
**Paperclip version or commit**
master at
|
||
|
|
f8cb4957dc |
fix(ui): default Tasks to All tasks with a neutral sort header (#19393)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The Tasks page helps people inspect work across their company. > - A new viewer currently starts in Mine and can miss other company tasks. > - The task table also shows an active sort header before the viewer selects a sort. > - This pull request starts new viewers in All tasks and keeps the default sort header neutral. > - People see company work in newest-update order and keep their saved view choices. ## Linked Issues or Issue Description **What existing behavior does this improve?** The initial task view and the task table's default sort state. **Subsystem affected** ui/ — React board UI. **Current behavior** Tasks opens Mine when the viewer has no saved view. The table highlights Last updated even when the viewer has not selected a column sort. **Proposed behavior** Tasks opens All tasks when no saved view exists. The table keeps newest-updated tasks first without an active header or arrow. A column selection or an explicit sort URL activates the selected header. **Reason and benefit** New viewers can inspect company work immediately. The header distinguishes default ordering from an explicit sort choice. **Breaking changes** The first-visit view changes from Mine to All tasks. Saved views and explicit view URLs keep priority. Existing Inbox and Needs attention preferences retain their meaning. The change does not alter task access or database contracts. **Additional context** Refs #19363. This change builds on the grouped task menu from that merged pull request. It uses the existing menu and design tokens. ## What Changed - Default the Coordinator and combined task surfaces to All tasks. - Preserve saved personal views and migrate previous picker choices. - Keep implicit Last updated descending order separate from active header state. - Test default ordering, explicit sorting, reset behavior, view selection, and preference migration. - Update the product and implementation docs. ## Verification - Passed 118 focused tests across task routing, table sorting, views, and collection preferences. - Passed `pnpm check:token-gates`, `pnpm -r typecheck`, and `pnpm build`. - Full `pnpm test:run` is running. Its result will be updated here. - Greptile passed the current head with 5/5 and no findings or open review threads. - Browser check: All tasks uses the grouped My work and Organization menu. Last updated has no active highlight by default. Selecting the header adds the sort URL and active direction. Removing the explicit sort restores the neutral header. - Manual check: Open Tasks with no saved task view. Confirm All tasks opens. Select Mine, leave Tasks, and return. Confirm Mine remains selected. ## Risks - The new default shows more accessible company tasks on the first visit. Saved view choices remain intact. - Task tables share the sort-state change. Explicit sort links and column clicks retain active styling. Default row order stays newest-updated first. - No schema, API, permission, or execution changes. ## Model Used OpenAI Codex, GPT-6 family. This session does not expose the exact model ID or context-window size. Used reasoning, code editing, terminal commands, and browser verification. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Scott Tong <scott@scottsmbpm5max.lan> Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
434d224c3a |
fix(ui): retry stale chunk reloads while a deploy settles (#19361)
## 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. After a deploy, an
open tab can ask for a chunk from its old build.
> - #17349 added a recovery: the app reloads the page one time when a
chunk fails to load. A loop guard permits only one reload in five
minutes.
> - Staging error monitoring still reports `Failed to fetch dynamically
imported module` from builds that include #17349. The events come 1–10
seconds after page load, and 1–10 minutes after page load.
> - During a deploy, the old server and the new server can both answer
for some seconds. The reloaded page can then miss a chunk again. Also, a
second deploy can occur inside the five-minute window. In both cases the
guard stops the recovery, and the user sees the error page. One more
reload a few seconds later would recover.
> - #18518 keeps old chunks available after a deploy, but only on
deployments that enable shared UI assets. Other deployments still depend
on the reload recovery.
> - This pull request permits up to three reloads in the guard window.
The reloads wait 0 s, 2 s and 5 s, so that the deploy can settle. After
the last reload, the error page shows and reports as before.
> - The benefit is that a stale tab recovers through a normal deploy
without an error page and without error-monitoring noise. A chunk that
stays broken still shows the error after a small, fixed number of
reloads.
## Linked Issues or Issue Description
Refs #17349
Refs #18518
**What happened?**
A browser tab stayed open during a staging deploy. A lazy page chunk
failed to load with `TypeError: Failed to fetch dynamically imported
module`. The route error boundary showed "This page hit an error" and
reported the error. The release included the one-time reload from
#17349. The reload did not occur because the loop guard had already used
its single reload in the last five minutes.
**Expected behavior**
The app reloads again after a short wait while the deploy settles, and
the page loads. The error page shows only when the chunk stays broken.
**Steps to reproduce**
1. Open a board page on a deployment without shared UI assets.
2. Deploy a new build. While the old and new servers both answer, go to
a page that was not loaded yet.
3. The chunk fails, and the page reloads one time.
4. The reloaded page gets its HTML from one server and a chunk request
goes to the other server. The chunk fails again.
5. The guard stops the recovery, and the route error page shows.
**Paperclip version or commit**
`master` at
|
||
|
|
4550253dc9 |
feat(ui): rename Needs you to Inbox and move Mine into Tasks (#19363)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Coordinator gives people navigation for conversations, tasks, and decisions. > - The decision entry is called Needs you, while a separate Inbox remains under More. > - Coordinator's personal task filter does not retain the full behavior of the original Mine view. > - This pull request names the decision entry Inbox and hosts the original personal work views inside Tasks. > - People keep their triage tools and saved choices without moving between two task destinations. ## Linked Issues or Issue Description **What existing behavior does this improve?** Coordinator navigation and the personal Mine view in Tasks. **Subsystem affected** UI navigation, task view routing, task collection preferences, and browser coverage. **Current behavior** Needs you opens the decision feed. More contains another Inbox destination. The default Coordinator task filter matches task creators and assignees. It does not use the full personal participation rules, archive behavior, shortcuts, grouping, or saved columns of the original Mine view. The organization task table also resets its column choices on reload. **Proposed behavior** Inbox opens the same decision feed with the inbox icon. Tasks defaults to Mine and remembers a person's selected view per company. Mine uses the existing personal Inbox implementation and preferences. It retains read/unread title weights, keyboard navigation, read/unread shortcuts, archive and undo, mobile swipe-to-archive, grouping, and saved columns. Old Inbox links open the matching task view. The organization task table saves its columns and order per person and company. **Reason and benefit** People get Chat, Tasks, and Inbox as distinct navigation entries. Personal work remains a view within Tasks without losing the existing triage behavior. **Breaking changes** Coordinator no longer offers the previous Inbox destination under More. Old Inbox URLs redirect into Tasks and retain query parameters and fragments. The Needs you label becomes Inbox; its decision feed, count, history, and resolution paths stay in place. Classic retains its separate optional combined-list setting. **Additional context** Refs: #19360, the workspace-defaults PR now integrated from master. Refs: #10620, related Inbox attention ordering. Duplicate searches found no open PR for this navigation and Mine integration. Roadmap review found no separate new execution feature in this scope. ## What Changed - Rename Coordinator's desktop and mobile decision entry and page to Inbox. Use the inbox icon. Remove the old Inbox item under More. Clarify that the combined-list experiment applies only to Classic. - Add one Coordinator task-view router. Host Mine, Unread, Recent, Blocked, and Everything through the existing Inbox owner. Keep organization views in the task table and board. Normalize legacy filtered URLs before mounting a collection so clearing the last filter preserves the current layout and local filters. - Reuse the existing Mine API, participation, read state, archive cache, undo, keyboard, mobile gesture, grouping, and preference paths. Existing personal column choices carry over. - Save organization task-table columns and order per person and company. Keep controls usable if browser storage fails. - Update navigation tests, routing and persistence regressions, exact-run retry browser coverage for each workspace variant, product documentation, and the affected Storybook notes. Keep existing story IDs. ## Verification - Preference, routing, navigation, task table, and inherited Inbox regression tests pass in focused runs. After integrating master and addressing the review finding, all 187 focused tests, UI typecheck, and token gates pass. - Full build and repository typecheck pass after integrating master. The full UI suite previously passed: 894 files, 11,169 tests passed, and one skipped. All 14 desktop/mobile triage and exact-run retry browser cases, including a fresh production UI build, pass after integrating master. - The full repository test suite was not run locally for this UI-only change; full PR CI is running. - Browser checks use a fresh isolated local instance and a deterministic process agent for real run-attributed unread activity. They exercise legacy URLs, title weights, saved grouping and columns, read/unread shortcuts, archive/undo, and a real mobile touch gesture. - Earlier browser fixtures were corrected: own activity is read, agent comments need valid run attribution, and undo uses `u` after the archive refresh completes. The Inbox content heading is scoped separately from the layout heading. - The final settings wording correction passes all 63 settings tests. - The [next CI browser run](https://github.com/paperclipai/paperclip/actions/runs/42137377960/job/127629100535) caught an old URL assertion for denied run retries. The test now pins each workspace variant and covers Coordinator Tasks explicitly. The old expectation fails deterministically for Coordinator; all 12 retry cases pass with the corrected destination, preserving exact run identity and truthful queued, deferred, and denied feedback. - Token gates, map checks, and Storybook catalog checks pass. All 30 map/catalog script tests pass. Storybook play tests were not run. - Greptile reviewed [the final commit](https://github.com/paperclipai/paperclip/commit/5f2f3789b83af259f694f379afb769465688fb72) at **5/5** with no new actionable findings. Its sort-only link finding is fixed and resolved: three cases fail before the fix and pass after it. `sortField` and `sortDir` keep organization links on the organization table. [Current-head CI](https://github.com/paperclipai/paperclip/actions/runs/42139668774) is running. - [CI exposed a routing race](https://github.com/paperclipai/paperclip/actions/runs/42135293421/job/127621981587) when removing the last label from a legacy Everything link. Four deterministic regressions failed before the fix and now pass: collections only mount after URL normalization. The existing end-to-end component cases confirm local filters, board layout, fragments, and history survive the change. - The [initial server shard 4 run](https://github.com/paperclipai/paperclip/actions/runs/42131163087/job/127608751620) failed an unchanged monitor-drain idleness assertion: two active operations remained instead of zero. The complete scheduling suite passes locally (54 tests). One isolated CI retry passed, including its dependent verification gate. The original timing failure's root cause is not established. ## Risks - Mine includes the existing tasks, approvals, failed runs, and join requests, preserving the original personal participation and attention rules. - Shared URLs with organization filters or table sort parameters still open the organization task collection. Task back-links retain their original fragments. - Saved preferences are browser-local. Mine keeps its existing storage keys; the organization table and selected Coordinator view use person/company scopes. - No database or server API contract changes are included. Existing company access, personal participation, and decision permissions retain their owners. ## Model Used OpenAI Codex, based on GPT-6, with reasoning, repository tools, code execution, and browser automation. The exact serving revision 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: Scott Tong <scott@scottsmbpm5max.lan> Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
f2593b7905 |
feat: make Coordinator and Agent Chat standard and speed up navigation (#19360)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - People enter that work through the workspace, agent conversations, and tasks. > - Coordinator and Agent Chat still require experimental enrollment. > - Task link prefetches do not warm the compact queries used by the default task view. Chat also waits for a request when its navigation list already holds the conversation. > - This pull request makes Coordinator and Agent Chat standard and reuses the reads needed for navigation. > - People can choose Classic workspace in Experimental settings. Cached work can appear while fresh data loads. ## Linked Issues or Issue Description **What existing behavior does this improve?** Workspace selection, Agent Chat availability, and navigation between Chat, Tasks, and task details. **Subsystem affected** Cross-cutting: UI, workspace preferences, instance settings, and the database migration. **Current behavior** People must enable Coordinator and Agent Chat in Experimental settings. Opening a task can repeat requests because prefetch warms the full detail and comment queries, while the default view reads compact task data and a recent comment window. Opening Chat waits for a detail request even when the current person's conversation list contains it. **Proposed behavior** Coordinator is the standard workspace for everyone. Experimental settings offer Classic workspace, off by default. Old Coordinator experiment values do not select Classic. Agent Chat is available to everyone, including instances with an old saved or managed off value. Task link intent warms the queries used by the mounted view. Chat can use the current person's company-scoped conversation list during refresh. **Reason and benefit** People can use the standard workspace without setup. Repeat navigation can show cached content while the server refreshes it. **Breaking changes** Existing Coordinator experiment and Agent Chat off values no longer disable these surfaces. Classic requires an explicit new opt-in. The workspace API keeps its existing response shape and audit checks. The migration retains legacy values and adds a separate Classic preference. Execution permissions, company access, and chat privacy checks still apply. **Additional context** Roadmap check: this graduates existing surfaces and improves their navigation. It does not add a new agent execution capability. Duplicate searches found no open Coordinator workspace PR. Related server cache work, Refs: #17828, addresses compact issue-list invalidation; this PR addresses client navigation queries. ## What Changed - Add a default-off Classic workspace preference. Derive the existing workspace API response from that choice. Keep personal persistence, account isolation, and audited writes in the workspace preference service. - Replace the Coordinator experiment control with Classic workspace. Use Coordinator while preferences load. Update the existing settings examples and navigation recipe. - Retire the Agent Chat experiment control. Ignore old stored and managed off values. Retain the compatibility key and the existing execution and access checks. - Reuse account- and company-scoped chat list data with its original freshness timestamp. - Share compact task and recent-comment query options between prefetch and the task view. Keep full-history prefetch for Classic tasks and expanded history. - Add upgrade, replay, cache, account isolation, and browser switching regressions. Update product, database, development, and roadmap documentation. ## Verification - Targeted preference, settings, migration, cache, and UI regression tests passed during implementation. The cache tests hold refresh requests pending and check that content still renders. They also check account isolation and stale refresh behavior. - A real browser test verified fresh Coordinator defaults, Classic opt-in persistence, and return to Coordinator. It used an isolated source checkout with fresh data on macOS. - Token, migration numbering and safety, map, and Storybook catalog checks pass after the rebase. - Repository typecheck and build pass. Typecheck and token gates also pass after review repairs. The broad local run passed all six chat integration shards (1,931 tests). It then found the host-CLI-dependent recovery fixture described below. Its remaining duplicate work was stopped after the full current-head CI matrix passed; this is not a claim that the broad local command completed green. - Review repairs passed 419 UI/migration fixture tests, 19 Coordinator navigation tests, and all 214 tests in the five affected server suites. The 24 Chat/workspace browser tests pass, including standard Coordinator switching and explicit Classic persistence. - The broader browser repair run passed 85 tests. It retained two failed assertions and skipped five later serial cases. The affected files then passed all 11 tests after the fixes: reopen the desktop panel after reload and open More for Audit and Connectors. This includes the five serial cases that had not run. - The broad local suite exposed a recovery fixture that executed the host Codex CLI during a simulated remote probe. On a host with Codex 0.154.0, model fallback broke its fixed-model assertion. The fake sandbox now reports Codex 0.160.0. All 20 selected recovery/provider compatibility cases pass after the repair. - A CLI company import/export suite timed out during server startup in the second CI run. The port fallback is intentional in that fixture. No root cause was established. That suite passes on the final commit in CI. This records recovery, not a claimed product fix for the earlier timeout. - The first CI run exposed remaining assumptions about the retired flags and Classic UI. The repair commit updates those fixtures and navigation steps. It also restores the missing enabled Cases destination in Coordinator. Earlier local recovery attempts used the wrong fixture notification and advanced fake time during live execution; the corrected tests use the subscribed recovery queue and wall time during execution. - Greptile reviewed commit `98972b030d4505d838427a2fca6b196b8cad6d47` at **5/5** with no new comments. The original finding is resolved. - Current-head CI is green: **56 successful checks**, with three checks skipped by workflow filters. This includes typecheck, build, the complete Vitest matrix, all eight browser shards, Runner verification, release checks, and security checks. [Final CI run](https://github.com/paperclipai/paperclip/actions/runs/42132651414). - Typecheck caught missing `pid` and `startedAt` fields in the simulated command result. The fixture now returns the complete process contract, and the server test-layer typecheck passes. - Storybook catalog alignment was checked. Storybook play tests were not run. Hosted latency and cold bundle loading were not measured. ## Risks - The new default changes the workspace for people who previously left the Coordinator experiment off. They can opt into Classic in Experimental settings. - The additive migration must run before the new server code. It is safe to replay and preserves explicit Classic choices. - Cached content can be stale during background refresh. Existing query invalidation and source timestamps still control freshness. - These changes reduce avoidable loading waits. They do not establish a measured improvement in hosted request latency or initial bundle download time. ## Model Used OpenAI Codex, based on GPT-6, with reasoning, repository tools, code execution, and browser automation. The exact serving revision 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: Scott Tong <scott@scottsmbpm5max.lan> Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
bf10bc695a |
feat(task): show the agent's context window in task properties (#19273)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agents run through a harness (Codex app-server, or Claude through ACPX), and the runner turns harness events into Paperclip events > - Both harnesses report how full the model's context window is. Codex sends `modelContextWindow` with its token usage. Claude sends `used` and `size` in ACP `usage_update` > - Paperclip dropped both values. The task view could not show how close an agent is to compaction, and a compaction left no visible mark in the task chat > - This pull request carries the context-window occupancy through the runner, stores it with the existing usage events, and shows it as a "Context" row in the task Properties panel > - It also shows a "Context compacted · 230k → 38k tokens" divider in the task chat when the agent compacts its context > - The benefit is that operators can see when a long task is near its context limit and when the agent lost detail to a compaction ## Linked Issues or Issue Description Refs #19252 (same pattern: a canonical harness event turned into task-chat UI). Refs #19267 (status notices; it turns Claude's compaction banner into a notice, and this PR reads that notice too). **What existing behavior does this improve?** The task view shows no context-window information, and a compaction is invisible in the task chat. **Subsystem affected** Runner usage normalization (Rust and TypeScript transport), the PRP usage schema, a read-only issue API, the task Properties panel and the task-chat transcript. **Current behavior** Codex `modelContextWindow` and ACP `used`/`size` are dropped in the runner. `context.compacted` always has null sizes, Claude compactions emit no `context.compacted` event at all, and the live runner turn hides every marker except "interrupted". **Proposed behavior** `usage.reported` carries an optional `context {usedTokens, windowTokens}`. The task Properties panel shows a Context row ("10% of 258k") with a hover breakdown (tokens used, input and cached input, output, cost, compactions). The transcript shows a compaction divider, with sizes from the usage before and after the compaction. **Reason and benefit** Operators can see when a long task is close to its context limit, and they can see where the agent's earlier context was summarized. **Breaking changes** None. The new schema field is optional, and the new endpoint is read-only. ## What Changed - PRP `usage.schema.json`: add an optional `context {usedTokens, windowTokens}` object. Regenerate the schema bundle and the protocol manifest. - Rust `provider_events.rs`: add `codex_context_usage` (last request `totalTokens` and `modelContextWindow`) and `acpx_context_usage` (ACP `used`/`size`). ACPX `usage_update` now sets `context`. - Rust `provider_backend.rs`: Codex `thread/tokenUsage/updated` sets `context` on live (non-historical) usage. - Rust `provider_events.rs`: emit `context.compacted` for the completed `context_compaction` provider notice that #19267 produces from Claude's compaction banner. Only this path marks a Claude compaction, so the server counts each compaction once. - `runnerd-codex-transport.ts`: `rehydrateRunnerdUsageNotification` keeps a valid `context` on `tokenUsage`, so it reaches the stored `item.completed` usage item. - Server: new `GET /api/issues/:id/context-usage` (issue read access is required) and `issueContextUsage` service. It reads only the assignee's current session (the session of its newest usage report), and returns that session's latest context reading, non-zero totals, cost, and the count of compactions across all of the session's runs. Added to OpenAPI. Shared type `IssueContextUsage`. - DB: migration 0432 adds two partial indexes on `heartbeat_run_events`, built concurrently. One indexes usage items by run and time. The other indexes `context.compacted` events by company and session. `EXPLAIN` shows that both lookups use them. - UI: new `ContextUsageMeter` (bar, percentage, hover card) and `IssueContextUsageRow` in the Execution section of Properties. The row refreshes every 8 s while a run is active, and once more when the run ends. - UI transcript: `native-run-events.ts` maps `context.compacted` to a `context` activity entry with pre/post sizes from neighbouring usage items. `transcript-adapter.ts` turns it into a new `context_compacted` marker variant. The live runner turn keeps that marker as its own timeline row. - Storybook: `task-context-window.stories.tsx` (Properties panel in a task, all states, hover breakdowns, divider). ## Verification - `cargo test -p paperclip-runner-core --lib provider_events` (new tests: ACPX context, Codex context, banner compaction, notice compaction) - `pnpm --filter @paperclipai/paperclip-runner exec vitest run src/live/runnerd-codex-transport.test.ts` - `cd ui && npx vitest run src/components/ContextUsageMeter.test.tsx src/components/transcript src/components/task-chat src/components/issue-properties` - `cd server && npx vitest run src/__tests__/issue-context-usage.test.ts` (embedded Postgres) - `node scripts/typecheck-low-memory.mjs`, `pnpm check:token-gates`, `pnpm --filter @paperclipai/paperclip-runner run check:protocol-types` - Live check on a local worktree instance through the runnerd path: - A Codex `gpt-5.5` task showed "10% of 258k" (27k of 258k, input 77k with 49k cached, output 1.1k). - A Claude Sonnet 4.6 task showed "17% of 200k" (34k of 200k). - Storybook: Tasks and conversations / … / Task chat / Context window. - Not verified live: a real compaction. The divider is covered by unit tests through the same projector path the task chat uses. ## Risks - The schema field is optional, and older runners omit it. The UI renders nothing until a harness reports a window. - Migration 0432 builds two partial indexes concurrently on `heartbeat_run_events`, which is a large table. The indexes cover only usage items and compaction events, so they stay small. They add a little write overhead to those events. - Claude in-progress usage rows still record zero tokens with `requests: 1`. The final turn usage is correct. This PR does not change accounting. - A "Compact now" action is out of scope. It needs a compaction-only run that does not produce a run result. It will come in a follow-up. ## Model Used - Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, used through Claude Code with tool use (shell, file edits, in-app browser for Storybook and the live instance). ## 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> |
||
|
|
c3550cfb38 |
fix(daytona): send archive chunks in bounded windows (#19339)
## Thinking Path > - Paperclip manages agents and saves their work when execution stops. > - The Daytona plugin saves an archive through a terminal when disk capacity prevents the normal archive or download copy. > - That fallback sent one 40 KiB chunk and waited for its host write acknowledgement. > - Network delay then applied to every small chunk. A large archive could exceed the recovery deadline even while bytes were moving safely. > - This pull request sends a bounded window of chunks and still acknowledges every completed host write. > - The benefit is faster recovery over delayed connections, with bounded memory and the existing size, space and completion checks. ## Linked Issues or Issue Description Refs #19034, which added the capacity fallback. **What happened?** The archive fallback waits for one network round trip after each 40 KiB chunk. A saved workspace archive can be much larger than that chunk. Repeating a timed-out transfer does not remove this throughput limit. **Expected behavior** Allow a small amount of data to travel before waiting for acknowledgements. Keep memory bounded, write bytes in order, and stop after any write or protocol failure. **Steps to reproduce** 1. Run the real Bash archive sender against a host that delays each acknowledgement by 400 ms. 2. Transfer 1 MiB plus a partial final chunk with a four-second deadline. 3. The original implementation times out. The bounded-window implementation completes and preserves the exact source bytes. **Paperclip version or commit** The failing regression uses the original implementation from `6a66c09f7f7`. ## What Changed - Send at most sixteen 40 KiB chunks before collecting their acknowledgements. Drain the final partial window before the completion receipt. - Serialize host writes and reject more than sixteen pending frames. Stop queued writes on the first failure. - Keep per-frame size checks, total archive limits, the 1 GiB host space reserve, the transfer deadline and bounded teardown. - Add a real Bash regression with delayed acknowledgements, plus overflow and failed-write coverage. Update the plugin documentation. - Update the agent-creator test fixture for the required directory membership role introduced by #15183, which otherwise breaks merged CI typechecking. ## Verification - Failing first: the final real-Bash regression fails against the original source with `Daytona archive stream timed out`. It passes with the change. The empty-stream case passes too. - Standalone Daytona package `pnpm test`: 578 passed, 8 skipped. The skips are the existing opt-in live tests. - Standalone package `pnpm typecheck` and `pnpm build`: passed. - `pnpm test src/file-sync-capacity.live.test.ts` with a staging Daytona key: 2 passed on isolated test sandboxes. This covers actual terminal transport, stop/start, archive and file-copy capacity failures, exact saved hashes, safe links, cleanup and a second export. The tests removed their own sandboxes. - The production dependency assumption is bounded: at most 640 KiB of decoded payloads can wait for host writes. The parser also has a bounded encoded buffer. No background work or idle timer is added. - Initial hosted CI failed with TS2741 in `ui/src/lib/agent-creator.test.ts` after #15183 made `membershipRole` required. Rebased onto that change and added the nullable field to the fixture. UI `pnpm typecheck`, all 4 existing creator-label tests, and `pnpm check:token-gates` now pass locally. Hosted CI subsequently passed on the updated head. - `git diff --check` and a local secret and PII scan: passed. - Full repository checks were not repeated locally for this standalone plugin change. Hosted verification at `bf6b3cb6a622a9523c72b86fdfe616555c8f3ef8`: all 53 check runs passed, with the 2 opt-in Storybook checks skipped; both required gates (`ci / verify`, `ci / e2e`) passed. Greptile is 5/5 at this exact head, with no review threads or merge conflicts. The separate non-required `security/snyk (cryppadotta)` status remains pending; it is not claimed as passed. ## Risks - A burst can queue up to sixteen chunks instead of one. The receiver enforces this bound and acknowledges a chunk only after its ordered host write. - The timeout budget is unchanged. A connection that cannot finish within that budget can still fail. This change does not retry a provider turn or change file-recovery authority. - Source confinement, archive validation, successful producer completion and publication rules are unchanged. No schema migration. ## Model Used - OpenAI `gpt-6.1-sol` with xhigh reasoning, in Codex through T3 Code. Tool use included source edits, real Bash and filesystem tests, and isolated Daytona tests. The runtime does not expose its context window. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
22281d4b3a |
feat(task-chat): approve harness-proposed plans (Codex plan mode, Claude ExitPlanMode) (#19291)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agents run through the native runner. Codex and Claude Code each have their own plan mode, and each produces a proposed-plan document. > - Paperclip already has a planning work mode, an issue `plan` document, and a `request_confirmation` approval gate for plans. > - These parts were not connected. The Codex proposed-plan item was transcript text only. The server path never put Codex into plan mode. Claude was never put into plan mode, and its ExitPlanMode plan was dropped. A planning run could close its task as done with no approval. > - This pull request turns a harness's own proposed plan into the issue's Plan document and the existing approval gate, for Codex and Claude. > - The benefit is that users approve or send back the agent's real plan from the task chat. Approve resumes the agent. Request changes sends the reason back to the agent. ## Linked Issues or Issue Description Refs #19252 **Subsystem affected** Native runner provider events (Codex and ACPX Claude), the runner Codex provider (Rust), server native plan synchronization, and the task chat UI. **Problem or motivation** Codex and Claude both produce a proposed-plan document in their native plan mode. Paperclip did not use it. In live tests on the server path, a Codex planning run was not in Codex plan mode, saved its own `implementation-plan` document, and marked the task done without approval. Claude planning runs were not in Claude plan mode, and the ExitPlanMode plan text never reached Paperclip. **Proposed solution** Add a canonical `plan.proposed` event for a harness's proposed plan. Put Codex and Claude into their native plan mode for planning runs. Save a completed proposal as the issue `plan` document with the existing `request_confirmation` gate. Agents can also propose a plan on a standard task; the work mode stays standard. **Alternatives considered** Reuse `plan.updated`. Its schema is the within-turn checklist and is not the durable Plan document, so a separate event keeps the two clear. Stronger prompt text without native plan mode. Live tests showed that the model kept its own document workflow. **Roadmap alignment** This reuses the issue plan document, planning work mode and approval gate that already exist. It adds one canonical provider event. ## What Changed - `packages/paperclip-runner/protocol/schemas/*`: add the `plan.proposed` event (`paperclip.plan.proposed.v1`: `proposalId`, `status`, `markdown` up to 60k characters, `source`). Regenerate the schema bundle, validators and manifest. - `packages/paperclip-runner/src/provider-events.ts`: map the Codex `plan` item and a `<proposed_plan>` block in a completed Codex message to `plan.proposed`. Add `claudePlanProposalEvent`. - `packages/paperclip-runner/runner/crates/runner-core/src/codex_provider.rs`: send Codex's native `collaborationMode: plan` on `turn/start` for a read-only (planning) Codex run. Before this change the server path never sent it. - `runner-core/src/acpx_event_payload.rs`: admit `plan.proposed` as ACPX rich display activity. - `drivers/acpx/codex-runtime-adapter.ts`: set Claude Code to native plan mode for a read-only run. Capture Claude's ExitPlanMode plan from its permission request, record it, and decline the native "Ready to code?" prompt. - `drivers/acpx/codex-acpx-driver.ts`, `cli/acpx-runtime-sidecar.ts`: emit the captured proposal as a rich event. Complete that turn instead of reporting it as cancelled. - `backends/codex-native-backend.ts`: per-harness plan-mode instructions, and a short opt-in hint for Claude on standard tasks. - `server/src/services/native-runtime/native-session-executor.ts`: synchronize a completed `plan.proposed` into the `plan` document and a `request_confirmation` in planning and standard mode. Do not change the issue status during the run (that revoked the run's lease). The run finalizer turns the pending confirmation into the review wait. - `server/src/services/heartbeat-run-summary.ts`: keep a `<proposed_plan>` block out of the posted reply. - UI: new `plan_proposal` provider family. The task chat shows a live "Writing plan" card while a proposal streams and a one-line record when it completes. Resolved plan reviews keep a receipt ("Approved Plan v1", "Requested changes to Plan v1: reason"). Plan previews skip section headings. - Storybook: `Tasks and conversations/.../Task chat/Proposed plan approval` shows the journey. - `doc/SPEC-implementation.md`: describe harness-proposed plan approval. ## Verification - `cargo test -p paperclip-runner-core --lib` (new: `read_only_codex_turns_use_native_plan_collaboration_mode`) - `cd packages/paperclip-runner && npx vitest run src/provider-events.test.ts src/drivers/acpx/codex-runtime-adapter.test.ts` - `cd server && npx vitest run src/__tests__/native-plan-proposal-sync.test.ts src/__tests__/heartbeat-run-summary.test.ts` - `cd ui && npx vitest run src/components/transcript/native-run-events.test.ts src/components/task-chat` - Live test on a local worktree instance with real harnesses: - Codex (`gpt-5.6-sol`), planning task: Codex asked one question, then produced a native plan item. The task showed Plan v1 with Approve plan / Request changes and moved to in review. Approve changed the work mode to standard. Codex then implemented the plan and its tests passed. - Codex, Request changes with a reason: Codex woke in planning mode and produced Plan v2 that includes the change. - Claude (`claude-opus-5-5`), planning task: Claude was in plan mode. ExitPlanMode became Plan v1 and the turn completed. Approve resumed Claude in standard mode, and Claude implemented the plan. - Claude, standard task that asks for a plan first: Claude stopped before code changes and asked for plan approval. The work mode stayed standard. - Storybook: open `Proposed plan approval` and check each stage. ## Risks - Codex planning runs now really use Codex plan mode on the server path. Codex can ask a clarifying question before it proposes. This matches Codex plan mode. - Claude planning runs now use Claude plan mode. A declined ExitPlanMode ends the Claude turn; the runner reports it as completed. Claude's tool row for that request records a rejection from Claude's side. - Codex does not stream the proposed plan on the server path yet, so the live card shows a placeholder until the plan completes. - A `<proposed_plan>` block in any completed Codex message on a standard task now asks for approval. This is the documented opt-in path. > 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`), via Claude Code with tool use (shell, file edits, browser). Long context. No extended thinking mode was used. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [ ] 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> |
||
|
|
1b0f78100d |
fix(access): return membershipRole in the company user directory (#15183)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents often check a human approval. The check must confirm the role
of the approving user in the company.
> - An agent can read the company user directory. The directory removes
the membership role from the server record.
> - The admin member list requires `users:manage_permissions`. An
approval check must not need that permission.
> - This pull request returns `membershipRole` in the existing user
directory and keeps all access limits.
> - The benefit is that agents can verify an approver's role without
admin permissions.
## Linked Issues or Issue Description
**What happened?**
`GET /api/companies/{companyId}/user-directory` returns active users
without `membershipRole`. An agent that checks the authority of an
approving user cannot tell an `owner` from other roles. `/members`
requires `users:manage_permissions`.
**Expected behavior**
The directory returns the exact `membershipRole` from
`companyMemberships`. A missing role stays `null`. Reading this field
does not require admin permissions. Member management keeps its current
limits.
**Steps to reproduce**
1. Use a company with an active `owner` user and an active user without
a role.
2. Call `/user-directory` with an agent key.
3. Before this change, neither record has `membershipRole`. After this
change, the field is `owner` and `null`.
4. The same agent still cannot read `/members` or change a member.
## What Changed
- Add `membershipRole` to the select and result of
`loadCompanyUserDirectory`.
- Test the exact `owner`/`null` values, agent read access, denied admin
read and change, denied other company, and denied unauthenticated
request.
- Keep the existing `assertCompanyAccess` and the company, user type,
and active filters.
- The client type includes a nullable `membershipRole`. The management
test rejects only `users:manage_permissions` and checks the exact calls.
The first review findings are fixed in
|
||
|
|
d807887534 |
fix(ui): use one status glyph mapping for every task view (#19329)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Task status is the main signal on every task surface: sidebar rows, the task header, the status menu, lists, the inbox, pills and chat cards. > - One task state rendered different status icons in different views. A blocked task that waits on an active sub-task showed the blue "in queue" glyph in the task header. The status menu, the chat chip and the sidebar rows showed the red "Blocked" glyph for the same task. > - The cause: each view passed its own subset of the presentation fields to `StatusIcon`. Many views dropped `blockerAttention` and some dropped `externalConversationState`. The status menu rendered its current row from the bare status. The summaries API did not return `blockerAttention`, so the recent-task sidebar could not know the state. > - This pull request puts the state-to-glyph/label mapping in one resolver and makes every task view pass all of its fields. > - The benefit is that the same state uses the same icon and label everywhere. ## Linked Issues or Issue Description No public issue. Found in a hands-on onboarding test on a staging cloud workspace. **What happened?** The sidebar and the task pane/status menu showed different status icons for the same state. On the test task (blocked, waiting on an active sub-task), the task header and the status button showed the blue "in queue" glyph. The selected "Blocked" row in the status menu showed the red blocked glyph. The coordinator sidebar "Recents" and project rows also showed the red blocked glyph, and the chat "Subtask created" chip showed a red "Blocked" chip. **Expected behavior** The same underlying state uses the same icon and label everywhere. **Steps to reproduce** 1. Create a task with a sub-task. Block the parent on the sub-task, and let the sub-task's agent run (the parent is "blocked, covered"). 2. Open the parent task. The header shows the blue "in queue" glyph. 3. Open the status menu. The current "Blocked" row shows the red glyph. 4. With the coordinator sidebar on, look at the task in Recents or in its expanded project. It shows the red glyph. **Paperclip version or commit** `master` at |
||
|
|
088f85c5fe |
fix: rename the managed environment to Paperclip Sandbox (#19296)
## Thinking Path > - Paperclip manages AI agents and their execution environments. > - Managed installations supply a default sandbox through managed configuration. > - Most selectors show the configured environment name. > - A fallback label, two errors, and examples still use Paperclip Computer. > - This pull request changes that stock copy to Paperclip Sandbox. > - Existing and custom environment names continue to come from the stored row. ## Linked Issues or Issue Description **What existing behavior does this improve?** The managed environment label in agent settings and the errors shown when the managed sandbox is unavailable. **Subsystem affected** The agent configuration UI, runner selection, and environment reconciliation tests. **Current behavior** Fallback copy and current examples call the managed sandbox Paperclip Computer. The actual environment name is already configurable. **Proposed behavior** Use Paperclip Sandbox for stock copy and current examples. Keep configured names unchanged in selectors, including legacy names and custom names. **Reason and benefit** The name identifies this environment as a managed sandbox and removes ambiguity. **Breaking changes** The displayed fallback and error text change. Error codes, execution behavior, and environment identity remain the same. No migration is needed. **Additional context** No duplicate rename issue or pull request was found. This is a copy update, with no new roadmap feature. ## What Changed - Update the managed fallback label and two unavailable-sandbox error messages. - Update current test and Storybook fixtures without changing story IDs or behavior. - Test configured names, fallback copy, and the unavailable-sandbox message. - Add a PostgreSQL regression test for a rename that retains the environment ID, instance default, agent binding, environment variables, and lease. ## Verification - `pnpm -r typecheck` passed. - `pnpm build` passed. - Focused coverage: 956 cases across nine changed suites. The new fixture initially tried to insert an existing singleton; its corrected upsert passed with all 52 environment-service cases. The updated runner suite also passed all 243 cases. - The two UI suites passed all 189 cases, including configured legacy/custom names and the missing-default fallback. - `pnpm check:token-gates` passed. - `node scripts/storybook-catalog.mjs --check` passed. The catalog is structural evidence only. - `node --test scripts/check-maps.test.mjs scripts/storybook-catalog.test.mjs scripts/storybook-feature-index.test.mjs` passed. - Full `pnpm test:run` is in progress. No live provider or browser journey is claimed by these tests. - CI passed on the current head after one server-shard rerun. The first attempt hit a 10 ms deadline assertion in the unchanged status-card timing test; its isolated local run and the complete rerun shard passed. The original failure and rerun are retained in the PR comment. - Reviewed the diff for secrets, personal data, and run artifacts. ## Risks Low risk: runtime edits change three display strings. Managed reconciliation is unchanged. The regression test exercises the existing rename against PostgreSQL. The configured name still controls normal display, so this code change alone does not rename existing database rows. A managed configuration update uses the existing reconciliation path. Roll back the copy by reverting this commit. ## Model Used OpenAI GPT-6.1 Sol (`gpt-6.1-sol`) through Codex in T3 Code, xhigh reasoning, with repository tools and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used, version, and capabilities - [x] I have checked ROADMAP.md; this copy update does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs - [x] I have described the issue in the PR with the enhancement template fields - [x] No internal or instance-local issue references - [x] The branch name describes the change and contains no internal ticket ID - [x] Focused tests pass locally - [x] Relevant tests were added or updated - [x] Relevant copy and examples were updated; no API or schema documentation changed - [x] Risks are documented - [x] All CI gates passed on the current head, including the server 11/12 rerun and aggregate verify - [ ] Full local test suite completed (still running; six chat shards passed) - [x] Greptile is 5/5 on the current head with no unresolved findings - [x] I will address all reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
b0fa2ef9bf |
feat(task-chat): show web searches, model switches, waits and verification checks as dedicated rows (#19262)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agents run through the native runner. The runner turns harness activity into typed canonical events such as `research.*`, `model.route.changed`, `wait.*` and the run's own verification checks. > - The task chat flattened these events into generic tool rows. A web search showed as "Ran Research eventType: research.started, summary: …". The run's verification checks were dropped completely. > - Live tests found a second break: the Rust runner core forwarded Codex `webSearch` items without their query, action or results. The canonical `research.*` events therefore had `query: null`. > - This pull request keeps the full payload for these families (as #19252 did for plans), adds small dedicated rows, and keeps the web-search fields through the durable runner. > - The benefit is that users see what the agent searched for, which model actually ran, how long a wait lasts, and whether each check passed, without opening the run log. ## Linked Issues or Issue Description Refs #19252 (same pattern for the plan card) **Subsystem affected** Task chat activity rows (UI), the native run-event transcript mapping, and the Rust runner core Codex normalizer. **Problem or motivation** Provider activity that the runner already maps to canonical events reaches the task chat as unreadable generic rows. Verification checks never appear. For Codex, the web-search query and action are lost before they reach the canonical event. **Proposed solution** Keep `research`, `model_identity`, `artifact`, `review` and `wait` events as `provider_activity` entries with their full payload. Project the runner's `verification` items as a new `verification` family. Render dedicated rows: a web search with its quoted query and source-domain chips, a model switch as `from → to · reason`, a wait with a live countdown, and green/red check lines. Keep bounded web-search and sleep fields in the Rust normalizer. **Alternatives considered** A separate "Checks" block beside the final answer. We kept the checks in the activity group, because the group summary already leads with "Check failed" when a check fails. ## What Changed - `ui/src/components/transcript/native-run-events.ts`: keep research, model, artifact, review and wait events as `provider_activity` with the full payload. Map `item.completed` items of kind `verification` to the new `verification` family. Context, hook, safety and delegation stay on the generic path, because other work items own them. - `packages/adapter-utils/src/types.ts`, `ui/src/components/task-chat/task-chat-model.ts`, `ui/src/lib/issue-chat-messages.ts`: add the `verification` provider-activity family. - `ui/src/components/task-chat/task-chat-activity-presentation.ts`: add labels: "Searched the web “query”", "Opened a web page host/path", "Switched models a → b · reason", "Waiting 30s" / "Waited 30s", and "Check passed" / "Check failed" / "Check not run". - `ui/src/components/task-chat/TaskChatRunnerActivityGroup.tsx` and `TaskChatProtocolActivityRow.tsx`: show up to three source-domain chips under a finished search, a live countdown for a running wait, and a check line with a tinted icon and its detail. - `ui/src/components/task-chat/completed-activity-summary.ts`: the group summary leads with "Check failed" when a check fails, and says "Switched models" for a reroute. - `ui/src/components/task-chat/transcript-adapter.ts`: verification detail keys, and a `startedAt` timestamp that stays across lifecycle merges (used by the countdown). - `packages/paperclip-runner/runner/crates/runner-core/src/provider_events.rs`: keep bounded `query`, `action` and http(s) `results` for Codex `webSearch` items, and `durationMs` for `sleep` items. Other item types do not change. - `ui/storybook/stories/tasks/task-chat-provider-activity.stories.tsx`: new story. Its fixtures are persisted run events that go through the production transcript path. ## Verification - `pnpm --filter @paperclipai/ui exec vitest run src/components/transcript src/components/task-chat src/components/TaskChatThread.test.tsx src/adapters/paperclip-runner src/lib`: 275 files and 3669 tests pass. - `cargo test -p paperclip-runner-core`: all tests pass, including the new `keeps_bounded_web_search_and_sleep_identity`. - UI typecheck is clean. `pnpm check:token-gates` is clean. `cargo fmt --check` is clean. - Storybook: open "Tasks and conversations / … / Task chat / Provider activity". It shows a settled run, a live search, a live wait countdown and a narrow layout. - Live test on a local worktree instance with a real Codex agent (gpt-5.6-sol, Codex app-server 0.160). The task asked for a web search, a parser with tests, a pause, and two checks. The task chat showed "Searched the web “ISO 8601 week date first week Thursday conversion calendar date”" and two green check rows ("node --test week-date.test.js · 8 tests passed; 0 failed.", "node --check week-date.js"). The group summary read "Ran checks". Before the runner fix, the same search had `query: null`. Not verified live: - The source-domain chips. Codex 0.160 sends `results: null`, because it keeps search results on the server. The chips appear only when a provider reports sources. Unit tests and the story cover them. - The wait countdown and the model-switch row. In the live run Codex paused with a shell `sleep`, not a native `sleep` item, and no reroute occurred. Unit tests and the story cover both. - Claude. Its WebSearch and WebFetch calls arrive as generic tool executions, because ACPX drops the tool metadata. They show as tool rows, as before. The ACPX `_meta` work is separate. ## Risks - Low risk. The change only affects how canonical events display. The generic path stays for the families that this PR does not change. - The Rust normalizer now persists the web-search query and the source URLs/titles in the run events. This data was already intended for the canonical `research.v1` event, and it is bounded (4,000 characters per text field, 64 results, http(s) URLs only). - A search that Codex reports with `action: other` and no query shows as "Searched the web" with no subject. > 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 Opus 5.5 (`claude-opus-5-5`) in Claude Code, with tool use (shell, file edit, browser automation) and extended reasoning. ## 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> |
||
|
|
56517dda6c |
fix(ui): bundle connector, toolbar, empty-state and agent roster fixes (#18716)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Operators use connector setup, collection headers, empty states, and agent lists to manage that work. > - Provider redirects replace the setup page, and collection controls use different sizes. > - Agent selection inserts a bar above the list. The row link highlights only part of the row. > - This pull request keeps sign-in in a separate window and applies the Tasks control sizes to collection and audit headers. > - It also reuses artifact artwork for empty collections and gives agent selection a fixed action card. > - These changes preserve the operator's place and keep controls and rows stable. ## Linked Issues or Issue Description **What happened?** Connector sign-in replaced the current page. Inline collection controls had different heights. Projects and Artifacts used small placeholder empty states. Agent selection moved the list, hover covered only the identity cell, and chat/status shared that cell without matching headings. **Expected behavior** Provider sign-in opens in a new tab or window. Collection controls match Tasks. Empty collections use the large artifact graphics. Agent actions float above the page while rows remain aligned. **Steps to reproduce** Start connector sign-in from a page or dialog. Compare collection and Audit headers. Open an empty Projects or Artifacts collection. Select an agent, then hover across its row. Related public work: #13584 covers an earlier connector new-tab implementation, including same-page fallbacks that this bundle does not use. #8528 covers Tasks toggle sizing. #17742 covers scoped agent Audit sections. This bundle does not change server callback or audit authorization contracts. ## What Changed - Reserve a separate authorization window during the click. Use validated sign-in URLs, retain a new-tab fallback, and close blank windows after failed requests. Store Cloud reauthentication state in the destination window. - Use the Tasks 44px control foundation for shared collection headers and Audit, Costs, Timeline, Secrets, Teams, Gateways, and agent skill controls. - Use a large artifact stack with an off-white Paperclip image with a dark icon for Projects and artifact Tasks empty states. Use one matching artifact for other types. Set 20px gaps and use the label “Create project”. Action hover and keyboard focus animate the artwork. - Portal agent bulk actions to a fixed card 48px above the bottom safe area. Use quintic entry/exit motion and respect reduced motion. Retain card contents during exit. - Give chat and status separate cells, add a Status heading, use the MessagesSquare chat action with a hover tooltip, and highlight the entire row. - Add linked agent chips and a manager picker to the agent profile. Block self and descendant manager choices. Keep the name crown and custom title inline during edits. - Update design guidance, the connection maps, regression tests, and empty-state Storybook fixtures. ## Verification - Final commit `a41a6c6494a839deaaec1ef7cc50c90078ab6381`: all 55 checks passed, three skipped. [Canonical CI run](https://github.com/paperclipai/paperclip/actions/runs/41999792769) includes all eight browser shards and all server/runner/workspace groups. Greptile: 5/5, zero unresolved review findings. - Workspace typecheck/build passed. Local UI suite passed 11,006 tests in 880 files, plus 542 CLI tests. Subsequent connector callback changes passed all 245 AppsConnect tests, UI typecheck, token gates, and query-error policy checks. Manager cache/error regressions passed four tests. Map checks passed. - Local connector browser suite: 20 passed. All six chat integration shards: 1,931 passed. Workspace B groups passed; database tests passed 313 cases across 72 files with one worker. - Browser preview verified agent manager changes, overview links, inline name/title geometry, empty-state colors, row actions and the chat tooltip. Live provider consent and post-deployment feature verification remain separate from these fixtures. - Preserved failures: ten bulk-roster tests initially missed the portaled action card; their selectors were fixed and all twelve roster tests passed. A nested fixture selected pnpm 11 and removed local dependencies; the local shim now pins pnpm 9. Embedded PostgreSQL native links were restored. A Python 3.9 fixture failure passed all 19 tests with the current runtime. Concurrent local database startup failures passed on the one-worker rerun. - The broad local serialized server run passed 3,791 tests with one scheduling assertion failure, which passed in isolation. The local general-server run reproduced a native recovery provider/model fixture failure and has not completed. These server sources are unchanged by this bundle; all final canonical CI server shards passed. This is not a claim that every broad local run passed. - [Earlier CI run](https://github.com/paperclipai/paperclip/actions/runs/41995119880) failed a browser test during cleanup when heartbeat-run cancellation hit a PostgreSQL lock timeout. All final browser shards passed without weakening that test. - Review follow-ups cover Slack popup/fallback recovery, a single artwork hover transform, shared manager error rendering, detached standalone OAuth windows, and verified task-bound callbacks in both hosts. ## Risks - Browser popup policy and provider callback behavior can affect sign-in completion. The original setup page stays open; blocked windows have an explicit recovery path. - Shared toolbar styles affect several surfaces. Menu content remains in its existing portals; canonical label tabs and search clear buttons retain their own geometry. - No schema, server, API authorization, or migration change. - Required CI and review are complete. Deployment provenance and hosted feature verification are checked separately after merge. ## Model Used OpenAI Codex, GPT-6 family, with reasoning, repository tools, test execution, and browser inspection. The exact model ID and context-window size were not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run relevant tests locally and they pass (broader local exceptions are recorded above) - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
2ccc7d37ef |
feat(ui): retain approved reads across outage reloads (#18825)
## Thinking Path > - Paperclip lets people manage agent work through the board. > - The board already retains loaded reads during a temporary server failure. > - Reloading the page removes that in-memory data. > - A deploy can then leave a returning user without the shell or recent tasks. > - This pull request saves an explicit, limited set of reads in the browser. > - Cached identity supports display while fresh session checks protect writes. ## Linked Issues or Issue Description **What happened?** A reload during an API outage loses the board's loaded reads. An automatic worker update can also reload a hidden tab while a write is pending. **Expected behavior** Show the cached shell and recent tasks during a temporary outage. Limit saved content by user, company, age and build. Clear it on sign-out. Wait for a fresh session before sending account-bound writes. Defer automatic reloads while work is pending. **Steps to reproduce** Open a task and settings while online. Return 503 from the API and reload. Restore the API. Sign out and confirm that saved query records are gone. Discover a worker update while offline or during an autosave and confirm that it waits. Stacked on Refs #18822. Related durable-write foundation: Refs #17960. The outage browser suite follows in a separate test PR. ## What Changed - Persist an exact read allowlist through TanStack Query dehydration and hydration. Save shell preferences, company/sidebar data, agent/project lists, plugin UI metadata, the first inbox page, and 20 recent tasks. Task UUID and identifier reads share one recent-task slot. - Namespace records by user and company. Retain eligible reads across normal memory garbage collection, expire each read after 24 hours, and discard them after a build change. Unstamped builds disable hydration and persistence while retaining sign-out cleanup. Use the existing instance-wide plugin contribution query in the user's root record. - Exclude session credentials and bootstrap data, embedded plan documents, comments, preview work products, provider credentials and environment values, browser capabilities, pairing data, other queries, and mutations. Restore only display identity from session data. Preserve safe agent provider/model display fields and configuration object shapes. Apply the projection on save and restore. - Clear saved reads on sign-out, cross-tab account changes, and definitive session denial. Keep revocation working on plain HTTP without crypto.randomUUID. Use per-user revocation revisions to reject delayed writes and stale records. Preserve a newer account. Remove every UUID/identifier projection and nested inbox copy of a denied task. - Detach shared GETs when the account changes or signs out. Load complete, freshly authorized agents before opening bulk settings from a display-only roster. Retire a pending bulk-editor result or error when row, select-all or clear changes the selection, including a clear/reselect of the same agent. - Require a fresh server lookup before account-bound writes, pending task creation, or mounted autosaves resume. This includes automatic task read receipts, inbox archives, workspace preferences and primary-agent choices, with optimistic archive changes gated too. Cancel the old write scope when the verified user changes. Release completed archives through account-independent cleanup without restoring old cached rows; an old operation cannot clear a newer hide flag. Retry unconfirmed read receipts after a fresh session succeeds for the original account, and remember confirmed receipts across refreshes. Track pending reads per task so opening another task sends its receipt immediately; revisiting reuses an outstanding receipt and its original account scope. - Defer a hidden-tab worker reload until connectivity, mutations, durable sends, and autosaves are safe. Synchronously count each unresolved operation across online rate-limit retries. Release a cancelled target’s unused dirty token when an editor changes tasks; keep stored drafts, admitted saves and queued retries. Cover autosave debounce, newer edits, navigation and undo. ## Verification - Current head `fe4f682c879` is merge-ready: all 54 check runs completed (52 successful, one skipped, one neutral), the legacy Snyk status is successful, and both `ci / verify` and `ci / e2e` pass in run `41752927822`. Greptile Apex reviewed this exact head at 5/5 with zero unresolved threads; the branch has no merge conflicts. All three PRs now meet the merge-ready bar; the stack remains unmerged pending operator approval. - Greptile Apex reviewed exact current head `fe4f682c879` at 5/5 with no actionable findings and zero unresolved threads (summary updated 2026-11-04 at 01:24:40 UTC). Both settings-account and pending-selection findings are fixed, replied to and resolved. The branch has no merge conflicts. Current-head CI now passes in run `41752927822`. - Seventeen new cases cover settings restored from actual saved query records, matching/changed/signed-out identities, denied verification, late crown responses without overwriting newer reads, and bulk-selection changes during successful/failed reads. Sixteen fail the preceding source and one preserves denial compatibility. Both settings paths reuse the existing account-bound mutation guard; its optional explicit QueryClient supports the workspace hook’s existing detached-host mode. Primary-agent optimistic updates begin only after verification and cleanup checks ownership and the cache revision. - Earlier CI run `41749456480` on prior head `2cf7516f18c` has one real server test failure: the owned-runtime case in `idle-completed-history.test.ts` could not reach its HTTP child on port 34757 within 10 seconds (99 refused probes). Its other 1,829 cases pass and three skip; the only other unsuccessful job is the downstream `verify` gate. The exact selected case passes locally, and the entire 75-case file passes in 72.19 seconds on the exact `2cf7516f18c` source tree with isolated PostgreSQL and a real child process on macOS arm64/Node 25.6.1. The Linux CI startup cause remains unknown; these local results are not a fix or CI acceptance. One failed-jobs retry with debug logging was accepted on that unchanged head, then superseded by the later settings fixes. Current-head CI remains required; no source change was made for this failure. - Current cache head `fe4f682c879`, based on read head `09d1db29dea` and master `683fa4725e9`, passes all 1,198 focused tests across twenty-eight files, UI typecheck, token gates and the enforcing query-error guard. Dependent browser head `228c1b68d30` contains this exact application source and passes standalone strict checking of all three browser specs. Current-head CI now passes in run `41752927822`. - Three new navigation regressions fail the preceding application source and pass with the fix. They open three cached tasks before any receipt resolves, leave the page before success or failure, revisit an outstanding read without duplicating it, and recover an older failed receipt after a fresh session succeeds while a later task remains pending. - The fixture repair passes all seven deadline integration cases and the complete server typecheck, including the server test layer. The old assertion deterministically fails at 23:59:06.888 UTC; its one-second-old run also fails the first-second-of-day probe. The corrected fixture passes noon and both midnight probes. The permanent three-case coverage uses seeded 2099 clocks. - Nine new cases cover archive success/failure after sign-out and another account takes over, both mounted and unmounted; cleanup ownership when a newer archive uses the same task; session-check 429 exhaustion followed by matching, changed or signed-out identity; and a failed read receipt followed by a new session read. They verify no old-cache restoration, toast or navigation, retained newer hide flags, no failed-check loop and no duplicate confirmed receipt. Seven fail the previous implementation; two compatibility cases retain account-change suppression. Initial test error-constructor and query-notification timing assumptions were corrected before the passing checks. - The inherited skills/app error-priority fix passes all 60 affected tests and UI typecheck on both application branches. Its twelve new regression cases fail the preceding read implementation. The persisted-cache suite includes 48 cases. - Six new regressions fail against the preceding application source and pass with the fix. Actual worker-update and mutation-cache listeners cannot reload a hidden tab between online 429 retries; the original create key survives, and the update reloads once after a receipt. Real self-hosted and Cloud sign-out work without crypto.randomUUID, with stamped and unstamped builds. Saved reads are removed and account write scopes are invalidated. An initial test-fixture type annotation error was corrected before the passing typecheck. - The 48 cache tests cover actual five-minute memory GC, the 20-task bound across saved and live reads, original 24-hour expiry, denial before session verification, unstamped cleanup, cross-tab revocation and delayed flushes. Private GETs cannot cross account transitions. Bulk edits require complete current agent data. Undo releases the update blocker while preserving the Saved indicator. - All 23 built-UI outage/write/loading cases pass in 4.5 minutes on exact integrated head `228c1b68d30`, containing current cache revision `fe4f682c879`: ten outage, six durable-write and seven loading cases. The run uses bundled Chromium, the built UI, a fresh local-trusted server and isolated embedded PostgreSQL on macOS arm64/Node 25.6.1. All three specs pass standalone strict TypeScript checking. Owned temporary server and database stopped. - Earlier browser runs exposed and fixed cached-header, native Storage cleanup and replay/session defects. A prior run passed 21/22 because real WebSockets contradicted the simulated HTTP outage; the fixture now closes existing socket pairs and holds new sockets through the same outage deadline. An older CI run exposed a disposed response in the Inbox route callback; pre-navigation snapshots remove that lifetime, and the current full run includes that repair. Earlier failures and their diagnosis remain in the discussion. The current full run passes. Broader historical workspace failures remain documented in Refs #18822; this does not claim a clean full workspace suite. - Current-head CI passes on `fe4f682c879`. Controlled local outages do not complete hosted authentication or a real Cloud restart/deploy acceptance. Commands for the current cache change and inherited read fix (the current focused run also includes src/lib/inboxArchiveCache.test.ts and src/pages/Inbox.test.ts): ```sh pnpm --filter @paperclipai/ui exec vitest run src/pages/CompanySkills.test.tsx src/pages/apps/AppNotConnected.test.tsx pnpm --filter @paperclipai/ui exec vitest run src/hooks/useDurableSubmit.test.tsx src/hooks/useDurableAutosave.test.tsx src/hooks/useSignOut.test.tsx src/lib/persisted-query-cache.test.ts src/lib/service-worker-updates.test.ts src/lib/service-worker-cache-policy.test.ts src/lib/pending-send.test.ts src/lib/issue-execution-policy.test.ts src/components/InlineEditor.test.tsx src/components/MarkdownEditor.test.tsx src/components/NewIssueDialog.test.tsx pnpm --filter @paperclipai/ui exec vitest run src/components/agents/AgentBulkRoster.test.tsx src/components/agents/AgentBulkSettingsSheet.test.tsx src/hooks/useAccountBoundMutation.test.tsx src/pages/IssueDetail.test.tsx src/components/TaskChatThread.test.tsx src/components/TaskChatThread.task-creation-order.test.tsx src/api/client.test.ts src/api/agents.test.ts pnpm --filter @paperclipai/ui exec vitest run src/hooks/useCoordinatorWorkspaceEnabled.test.tsx src/context/PrimaryAgentProvider.test.tsx src/components/CoordinatorWorkspaceSetting.test.tsx src/components/primary-agent/PrimaryAgentPresentation.test.tsx src/components/MobileBottomNav.coordinator.test.tsx src/components/CoordinatorSidebar.test.tsx src/pages/Issues.coordinator-routing.test.tsx pnpm --filter @paperclipai/ui typecheck pnpm check:token-gates node scripts/check-query-error-rendering.mjs --enforce --summary ``` ## Risks This deliberately saves task content on the local browser for up to 24 hours. The allowlist excludes credentials and ephemeral capabilities. Local storage can be disabled or full; persistence then fails without blocking the app. Restored data can be stale and never grants server access. A user or access change clears cached account reads and invalidates pending writes. The browser outage suite and real hosted deploy acceptance remain release requirements. There are no migrations or new dependencies. ## Model Used OpenAI `gpt-6.1-sol` through Codex, with xhigh reasoning effort, tool use, and code execution. The context window size is 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 - [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 bug report 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] The focused local tests for this change pass - [x] I have added tests and updated relevant documentation - [x] I have considered and documented 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: Paperclip <noreply@paperclip.ing> Co-authored-by: Bender (Fable) <bender@agents.paperclip.ing> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
a3313f6944 |
fix(ui): complete read recovery and enforce query error rendering (#18822)
## Thinking Path > - Paperclip lets people manage agent work through the board. > - The board reads task, agent, settings, plugin, and run data from the server. > - A deploy can interrupt those reads after content is already visible. > - Local error branches can replace that content with an error or show raw codes. > - This pull request moves the remaining reads to the shared recovery behavior. > - The query-error guard prevents new local error patterns from returning. ## Linked Issues or Issue Description **What happened?** Loaded lists, settings, task panels, and manual reads could clear their content or show errors during a server restart. Some reads also disabled the shared retry policy. **Expected behavior** Keep loaded content during a temporary failure. Show the shared connection banner. Retry reads after recovery. Replace content after a real access denial or missing resource, with readable copy. **Steps to reproduce** Open a task, settings page, or run log. Return 503 with `tenant_app_unavailable` from the API. Restore the API and check that content refreshes. Repeat with 403 and 404 to check the failure state. Related merged work: Refs #15754, Refs #15772, Refs #17960. This change covers remaining reads and enforcement. Browser persistence and the outage browser suite follow separately. ## What Changed - Repair an existing PostgreSQL deadline fixture at UTC boundaries. A daily cap defers a heartbeat until both its original interval and the next UTC day allow it. Keep the counted run in its seeded day and cover noon, just before midnight and the first second after midnight with explicit clocks and real PostgreSQL. Production scheduling is unchanged. - Integrate the saved list, settings, shell, task, and manual-read recovery changes against current master. Preserve the current task, Inbox, and run-log structure. - Add `useResilientFetch` for component-local reads. Preserve loaded data, cancel stale requests, and retry through the shared connectivity policy. Keep browser and pairing capabilities in memory. - Retain run log chunks across stream changes and catch up after recovery without duplicate chunks or stalled requests. - Keep genuine authorization and missing-resource failures visible. Translate known single-word codes such as `forbidden`. Show known skills and disconnected-app failures before sibling loading states. Keep Retry bound to its failed request. - Make the query-error guard enforce by default and run it in the CI policy job. Document the narrow exceptions and the read recovery contract. - Invalidate pending OAuth discovery when the operator leaves setup or its context changes. Keep reserved-popup cleanup bound to the current attempt. ## Verification - Current read head `09d1db29dea` is merge-ready: all 59 check runs are completed (54 successful, three skipped, two neutral), the legacy Snyk status is successful, and both required `ci / verify` and `ci / e2e` gates pass. Greptile Apex reviewed this exact head at 5/5 with no unresolved threads; the branch has no merge conflicts. The current CI run is `41748339602`. - Current read head `09d1db29dea` includes master `683fa4725e9`. The latest change touches only the existing server deadline test fixture. Application source remains the previously verified `86376fa751e` revision: all 60 affected skills/disconnected-app tests and both application UI typechecks passed, along with token gates and the enforcing query-error guard. Those UI suites were not repeated for this test-only repair. - The fixture repair passes all seven deadline integration cases and the complete server typecheck, including the server test layer. The old assertion deterministically fails at 23:59:06.888 UTC; its one-second-old run also fails the first-second-of-day probe. The corrected fixture passes noon and both midnight probes. The permanent three-case coverage uses seeded 2099 clocks. - Twelve new regressions fail against the previous implementation. Both skills variants and disconnected-app pages show either request's 403 or 429 while the sibling pauses or remains fetching. Permission failures stay visible. Retry stays usable for its failed request and recovers independently. An initial test-fixture query-key typo was corrected before the passing run. The finding is replied to and resolved. Greptile reviewed prior application revision `86376fa751e` at 5/5 with no new actionable findings or unresolved threads. The current test-only head has now received its own Apex 5/5 review with no unresolved threads, and its CI is successful as recorded above. - The preceding OAuth fix passed all 237 setup tests on both application branches. Its ten regressions prove that Back, Cancel, unmount, or context changes retire initial discovery without creating a connection, caching old identities, navigating an abandoned popup, or closing a newer attempt. - Earlier master integration `e992f770339` passed all 309 tests across eight affected Slack, recovery, retry, submission and task files, plus UI typecheck, token gates, enforcing query-error scan and seven guard tests. The integration preserves Slack workspace reconnect and shared recovery, readable execution errors, source-inspection company scoping, and current submission behavior. Newly inherited retained-file recovery controls keep cached data through transient failures and hide it after definitive denial. - The preceding cache head `97c0bc3966f` passed 1,038 focused cache/write/editor/account/task/API tests. All 22 built-UI outage/write/loading cases passed in 4.7 minutes on exact browser head `b7deaaee5da`, with strict checking of all three specs. The latest skills/app rendering fix is covered by its affected component suites; those broader cases were not repeated for this separate read path. - Historical broader UI, CLI and build results and unresolved aggregate server/DB/adapter failures remain in the PR discussion. Interrupted CI runs were audited and recorded separately; they are not counted as passes. Controlled local outages do not prove hosted authentication or a real Cloud restart/deploy. Real hosted acceptance remains required after merge and deployment. Commands for the latest fix: ```sh pnpm --filter @paperclipai/ui exec vitest run src/pages/CompanySkills.test.tsx src/pages/apps/AppNotConnected.test.tsx pnpm --filter @paperclipai/ui typecheck pnpm check:token-gates node scripts/check-query-error-rendering.mjs --enforce --summary ``` ## Risks This migration touches many read surfaces. The main risks are initial loading, request cancellation, retained authorization state, and run-log paging. The tests cover those states. There are no server, schema, dependency, or API contract changes. The follow-up browser suite and hosted deploy acceptance are required before release acceptance. Recovered commits retain their original authors. If squash-merging, preserve `Co-Authored-By: Bender (Fable) <bender@agents.paperclip.ing>` and the Paperclip trailer. ## Model Used OpenAI `gpt-6.1-sol` through Codex, with xhigh reasoning effort, tool use, and code execution. The context window size is not exposed. Saved source commits keep their original authorship. ## 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 bug report 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] The affected local tests pass; broader limitations are recorded above - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented 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: Paperclip <noreply@paperclip.ing> Co-authored-by: Bender (Fable) <bender@agents.paperclip.ing> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
c6cb7e2a2d |
fix(ui): accept file drops across task and new-task views (#18849)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - People add images and files through task message composers. > - A file drop requires a small target inside the composer. > - A screen-wide target makes this action easier. > - Task pages and new-task dialogs use the same composer. > - This pull request adds one shared file-drop target. > - The open dialog receives the drop when it covers a task page. ## Linked Issues or Issue Description Refs #13206. This improves the task composer drop area. Related PRs: #18689 adds image previews. #15964 adds direct uploads in the Artifacts panel. **What existing behavior does this improve?** Image and file drops in the task composer and new-task dialog. **Current behavior** People must drop a file into the composer area. **Proposed behavior** People can drop a file anywhere on the screen when an available composer is present. A full-screen overlay shows the destination. **Reason and benefit** People can add an image without aiming at the text field. **Subsystem affected** React board UI. **Breaking changes** The available composer captures file drops across the screen. Text and link drags retain their current behavior. Upload rules and APIs stay the same. **Additional context** ROADMAP.md lists task discussion and attachments as existing features. This change improves their input area. ## What Changed - Add a shared screen-wide drop target to the task composer. - Give an open task dialog exclusive ownership of file drops. Keep file drops available while a model or assignee picker is open. - Give explicit editor, task attachment, and Artifacts drop areas priority over the screen-wide composer target. Share one marker for these areas. - Keep image and file uploads in description, question, and protocol editors. Read-only editors and editors that delegate uploads to a parent keep the composer fallback. - Prevent browser navigation from file drops while the active composer is read-only. - Use the existing file staging and upload callbacks. - Disable drops during pause, queued message edits, uncertain sends, submission, and read-only states. - Exclude hidden and inert composers. - Clear the overlay after drop, drag exit, cancellation, window blur, and unmount. - Add component tests and two Storybook drag-over examples. ## Verification - 316 tests passed across the drop target, real MarkdownEditor, task composer, new-task dialog, and Artifacts tab. Tests cover image and text-file drops in a real editor, overlay reset, parent and read-only editors, and task attachments. - Two new cases failed before the editor and attachment fixes. Both passed after the fixes. - An earlier expanded run had three new-task upload assertion failures. The five affected cases passed on the unchanged implementation in isolation. The expanded run then passed all 316 tests. The cause of the earlier failures remains unverified. - UI typecheck and UI production build passed. The first typecheck attempt lacked plugin SDK declarations. Building the SDK restored these declarations; typecheck then passed. - Design-token gates, Storybook catalog generation, and whitespace checks passed. - Chromium checks from the design review confirmed one image per screen drop in each view. The editor stayed empty and the overlay cleared. These checks used local Storybook fixtures. - The requested screenshots were accepted before this PR was opened. - Full repository typecheck and build were attempted. Both stopped in the native Runner package because this environment has no cargo executable. - The full repository test run was attempted. It was stopped during the first chat integration shard before a full-suite verdict. The focused UI suite passed. - The first CI attempt did not complete. Typecheck and build logs report runner shutdown signals. Most browser shards were cancelled; their logs could not be retrieved. No complete CI verdict is available. The new commit starts a fresh CI run. - Review findings about Artifacts drops, portaled pickers, read-only drop navigation, and editor drop ownership are fixed. Current-head CI and review are pending. - The previous CI run passed build, typecheck, general tests, and six browser shards. Browser shards 5/8 and 8/8 failed. Their logs returned BlobNotFound; the causes remain unverified. The new commit starts a fresh CI run. Manual check: open a task, drag a PNG over the page header, and drop it. Confirm one image preview. Open a new-task dialog over the task and repeat. Confirm the file appears only in the new task. Cancel the drag and confirm the overlay clears. Open the description editor. Drop an image and then a text file into it. Confirm each upload stays with the description and does not enter the chat draft. ## Risks - Screen-wide file capture changes which surface receives file drops. - Dialog ownership and disabled-state tests limit unintended uploads. - No server, API, database, or migration changes are required. - Full repository acceptance still requires the native Rust toolchain and CI results. ## Model Used OpenAI GPT-6 through Codex. The exact runtime snapshot ID and context-window size were not exposed. Capabilities used: repository inspection, code editing, shell commands, and browser 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 - [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 |
||
|
|
c99bcd89fe |
fix: preserve Product TestOps evidence and CI readiness (#19000)
## Thinking Path > - Paperclip manages agent work through governed product workflows. > - Product E2E tests check those workflows through the app and Runner. > - A trusted reporter sends retained results to TestOps. > - Free-form metadata and a short upload observer can lose safe, valid evidence. > - UUID navigation can also discard task metadata before the canonical query returns. > - Hermetic CI files start child processes that need CPU capacity within their readiness limits. > - This change closes the reporting contract, retains authenticated core aliases, and reserves CI CPU capacity. > - Original case identities, conditions, assertions, verdicts and deadlines remain intact. ## Linked Issues or Issue Description Refs #18983. This addresses its late [metadata disclosure finding](https://github.com/paperclipai/paperclip/pull/18983#discussion_r4470789114) and [upload readiness finding](https://github.com/paperclipai/paperclip/pull/18983#discussion_r4470790366). **What happened?** The reporter accepted model IDs and matcher names through syntax filters. A secret-shaped string could pass those filters. First-task results also use their top-level model field for an observed alias. Treating it as configured metadata can reject valid retained evidence. The upload observer stopped after 22 seconds of waits. [Required CI on the earlier head](https://github.com/paperclipai/paperclip/actions/runs/41886885193) also found two real browser title failures and five native package readiness failures. A deterministic control reproduced metadata loss during UUID-to-identifier navigation. A separate fixed-resource control reproduced startup deadline failures with four concurrent hermetic fixtures, while one and two fixtures passed. **Expected behavior** Reject unknown transmitted metadata before creating upload files. Preserve every original matcher verdict and attempt receipt. Observe server processing without rerunning the product. Keep authenticated task metadata visible through canonical navigation. Reserve capacity for hermetic child processes without changing the original readiness deadlines. **Steps to reproduce** Use a secret-shaped model ID or cleanup state in retained evidence, return an observed first-task model alias, or let upload processing settle after 40 seconds of virtual time. Hold the canonical core query pending after an authenticated UUID read. For the CPU control, run the same providerless startup/recovery fixture alone, four times concurrently, and twice concurrently under a fixed 4-vCPU quota and its original 8-second readiness limit. ## What Changed - Bind configured model receipts to each exact declared case model. Four first-task cases use captured agent configuration; their observed aliases and fallback text remain digest-only. A missing capture stays null / Not recorded. The other 16 cells use their configured profile model. Reject wrong or unknown configuration before any upload file exists. - Keep the existing model distribution: 18 Codex cells on `gpt-5.6-sol`, configured-repository case 9 on its existing `gpt-6.1-sol` override, and task-workspaces case 54 on `openrouter/deepseek/deepseek-v4-flash-0731`. The repository override exists at the [original canary source](https://github.com/paperclipai/paperclip/blob/86814c6550f52e99ede150a883bdc773cbb540e3/tests/runner-e2e/catalog.ts#L1148). No model configuration changes. - Allow only existing Matcher kinds, closed failure classes, and cleanup states `passed`, `failed`, or `not_started`. Publish each matcher's kind, ordinal, original boolean verdict and SHA256 path receipt. Full conditions remain in the linked original workflow artifact; raw dynamic path bytes do not enter TestOps. - Observe the same upload for at most 55 seconds of poll waits. Product scenarios, provider retries and scenario deadlines do not change. - Retain task core data under only the authenticated response's own UUID and identifier core keys. Preserve existing canonical data. Keep arbitrary references and full-detail keys empty until their own reads. - Retain a first-failure trace for the existing Cloud recovery test. Keep its assertions, timeout, retries, mock data and artifact policy unchanged. This adds diagnosis evidence; it does not claim to fix that separate Cloud title timeout. - Reserve half the available CPUs for Runner package CI workers, with the existing upper cap of four. A 4-vCPU host uses two workers; an 8-vCPU host still uses four. Local defaults and test selection do not change. ## Verification - Reporting controls first reproduced the two original gaps. All 14 Node contract tests now pass. Unknown configuration creates neither a result directory nor an export summary. A model valid for a different selected case is also rejected. Original functional failures and earlier accounting receipts survive. - The catalog compatibility test passes for all 20 selected cells, exact model tuples, real pure grader outputs and actual `projectFirstTaskResult` shapes. It covers observed aliases, fallback text, absent evidence and wrong or secret-shaped configured metadata. These are contract controls, not live journey passes. - Virtual-clock controls accept a correct result that settles at 40 seconds and reject a persistently wrong verdict after 55 seconds. They make no product or provider calls. - Two new core-cache controls failed before repair. The query/cache suites now pass all 8 tests. They hold canonical refresh pending and verify title/company retention, newer canonical data, full-detail enrichment and unrelated keys. UI typecheck and token gates pass. - The unchanged exact UUID cross-company link/upload browser test passed once after repair: 5.8-second scenario, 32.0-second complete command. The unchanged exact Cloud task-entry diagnostic passed once: 5.4-second scenario, 23.3-second complete command. Its original canonical-only timeout remains unexplained. All five Cloud tests still collect after the trace setting. - The providerless Linux control used the retained Runner and compiled controller from source `3a2249dd`, with a fixed 4-vCPU quota and original 8-second readiness limit. Solo passed 1/1; four concurrent fixtures failed 4/4; two concurrent fixtures passed 2/2. At each failure, Rust had accepted command 2 but startup was still pending; checkpoint and published status agreed, one connection was authenticated, no replay backlog existed, and the sidecar had not launched. Passing controls preserved the expected startup failure through controller replacement. No network or credentials were available. - That control uses Linux amd64 emulation and Node 24.21; hosted CI used Node 24.22.1. It supports the worker-cap change, but does not prove that the original `m5n.xlarge` host caused every CI failure. The original red attempts remain recorded. - Actual config-load controls verify 1 CPU → 1 worker, 2 → 1, 4 → 2, 8 → 4 and 16 → 4, with no local, timeout or retry override. The isolated policy change preserves the same 297 test-file inventory; integration of current master `89703c3ff7` retains all 298 current native package files. The original PR package/native command plans remain unchanged. - Final head `877e28da32f2d2f0d12906c89aff085e2c6ea943` passes both required checks, `ci / verify` and `ci / e2e`, in [CI run 41897677652, attempt 2](https://github.com/paperclipai/paperclip/actions/runs/41897677652/attempts/2). The native package passes 4,950 tests with 10 existing skips. All eight browser shards pass; the Cloud shard passes all 41 tests, including all four unchanged recovery cases. - Attempt 1 preserved 46 successful jobs but its one-file heartbeat recovery shard hit the original 20-minute job limit without a named assertion or completion verdict. Its cause remains unidentified. One explicitly bounded debug replay retained those 46 successes and ran only that leaf and its dependent rollup. The unchanged file passed all 412 tests (346.91-second file, 371.34-second Vitest command, 7m11s job). Source, cases and deadlines did not change. This establishes intermittency, not a causal repair. The original timeout and debug pass both remain recorded. - Fresh [Greptile 5/5](https://github.com/paperclipai/paperclip/pull/19000#issuecomment-6637604918) and [Ponytail 5/5](https://github.com/paperclipai/paperclip/pull/19000#issuecomment-6637489454) reviews name exact head `877e28`. The single review thread is resolved. Live TestOps bootstrap and complete 20-case acceptance remain held until reviewed delivery. CI and focused controls do not count as product plan passes. ## Risks - Future model or Matcher kind changes require a reviewed reporting-contract update. - TestOps shows a closed Matcher kind and ordinal. The path digest binds the original condition in retained evidence. - Core alias data retains the existing authenticated query-client and server company boundaries. It never becomes full-detail evidence. - Fewer CI workers can increase one job's duration. The full suite must verify the final policy. The paid evaluation matrix and its parallelism do not change. - The original Cloud title timeout and the first-attempt heartbeat CI hang do not have proven causes. Current unchanged assertions pass, but this does not establish repeatability. The Cloud test now retains its first-failure trace. A successful upload or focused control alone cannot establish a complete product pass. ## Model Used OpenAI Codex with reasoning, tool use and code execution. The host does not expose the exact model ID or context window to this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` 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> |
||
|
|
5996f25122 |
fix(ui): replace selected text on ordinary paste (#18796)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - People edit task documents and comments in the Markdown editor. > - Its link validator accepts safe text that is not a URL. > - Lexical uses that validator to turn pasted text into a link around the selection. > - Pasting JSON or prose can keep the old text and put the new text in its link destination. > - This pull request handles plain selected-text replacement in the existing paste plugin. > - The benefit is standard text replacement with existing manual link controls intact. ## Linked Issues or Issue Description Fixes #2930. Related: #8506 by `joegalbert-ai` identifies the same validator cause. Thanks for that analysis. This change adds current Lexical command coverage and preserves the separate manual and decorator link paths. The contributor PR remains unchanged. Reproduce by selecting an existing paragraph and pasting `{"status":"ready"}`. The old code keeps the previous paragraph as a link label and uses the JSON as its destination. The expected result is the pasted JSON as text. ## What Changed - Replace a selected text range, including soft line breaks, when the clipboard text is not an unambiguous link target. - Keep selected-label link wrapping for valid scheme, network, web and email targets, including international addresses. Treat ambiguous relative paths and fragments as ordinary pasted text. - Leave the manual link validator unchanged. Keep manual relative, internal, fragment, email and decorator links, with existing executable-scheme guards. - Use the same native Lexical rich-paste insertion API for selected HTML payloads. Preserve HTML formatting and the paste undo boundary. Keep files, Markdown, code and other selection types with their existing handlers. - Declare the clipboard API and test rich-text API at the existing Lexical 0.48.0 version. The scheduled repository bot owns the lockfile refresh; this PR has no lockfile delta. - Add real Lexical paste and link-command regressions through the production editor policy and paste plugin. This restores expected editing behavior; it adds no setting, endpoint or new feature-map entry. ## Verification - Before the fix, real selected-text paste tests fail for JSON, prose and multiline text. They retain the old label and create a link with the replacement as its URL. The valid-URL control passes. - A test-only experiment with the exact recognition predicate from #8506 fails four current decorator relative/fragment cases. The chosen paste-handler fix keeps the manual validator intact. The experiment was removed after preserving its result. - `pnpm --filter @paperclipai/ui exec vitest run src/components/MarkdownEditor.test.tsx src/lib/markdownPaste.test.ts src/lib/normalize-markdown.test.ts src/lib/mention-aware-link-node.test.ts src/lib/mention-deletion.test.ts`: 119 editor-focused tests passed. After the baseline update, the same editor suites plus App and ShellConfigurationGate passed 146 tests. - The React MDXEditor shell is mocked. The configured production predicate, actual paste-normalization plugin, native rich-text paste handler and real Lexical paste/link commands are not mocked. Tests cover URL wrapping, plain replacement, manual/decorator links, executable-scheme handling and paste-owner handoff. - UI typecheck and production build pass. UI token gates, module boundaries and diff checks pass. Initial test event-type errors were fixed. Greptile found that JSON with an email still formed a link. Its real-command regression failed before narrowing whole-address recognition and passes after the fix. An isolated frozen install and SDK build resolved local workspace prerequisite errors. - No live task edit or deployed replay was run. Full repository checks run in current-head CI. The initial quality gate rejected generated lockfile edits; the policy correction removes them without changing tested source. The earlier current-head workspaces-a CI failure was the independently fixed invitation-access fixture in App.test.tsx. Merge #18799 supplied that baseline fixture fix. Its local regression and the editor suites now pass together; all final-head CI checks now pass. Final head `5156085b83c908e1439927bbebf25ab0aa42f81b` has 60 terminal contexts: 56 success, three skipped, and the neutral Paperclip review at 5/5. Greptile is 5/5 with no unresolved findings. - Review regressions also failed before repair for a selected soft line break, formatted HTML with JSON, and international email addresses. These cases now pass. The HTML test checks that bold formatting survives. ## Risks - URL recognition must not turn ordinary text into a link. Ambiguous relative paths use text replacement on paste; the manual link controls still accept them. - The selected HTML path must preserve formatting. It delegates insertion to the native rich-paste API with the original clipboard. File payloads and non-simple selection types still yield. - Existing Markdown normalization still applies. Script/data scheme checks and rendered-link sanitization remain unchanged. - No visual tokens, schema, public API, provider or deployment configuration changes are required. No additional user documentation is needed for this expected editing behavior. ## Model Used OpenAI Codex, `gpt-6.1-sol`, Extra High reasoning, with source inspection, code execution and regression testing. Context-window capacity 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 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> |
||
|
|
652cd76026 |
fix(ui): expose Stop for failed native retries (#18899)
## Thinking Path > - Paperclip manages agents and their tasks. > - A native run can fail while it still owns a same-run retry. > - The server supports Stop for that pending execution. > - Run details show Cancel only for queued or running records. > - A failed pending retry therefore has no ordinary cleanup control. > - This pull request exposes the existing Stop eligibility and uses the existing cancellation endpoint. ## Linked Issues or Issue Description Refs #14743 and #14733 for correlated native Stop. Those changes cover backend cancellation and protocol qualification. They do not add the failed-run control to run details. Searches of current master and open PRs found no matching UI repair. **What happened?** A native run can show failed while its coordinator still owns a retryable failure with no accepted result. The backend can cancel that retry. Both run-detail implementations hide the cancellation button because the record is terminal. **Expected behavior** The selected run offers Stop when the server confirms that pending native retry. Unknown, legacy, terminal and accepted-result states do not gain this control. Existing queued and running cancellation stays available. **Steps to reproduce** Render either run-detail implementation for a failed native run with an eligible retry. The original UI has no Stop button. The original batched execution projection has no eligibility field. The regression tests exercise both real components and the actual PostgreSQL projection query. **Paperclip version or commit** The missing control and projection field were reproduced on |
||
|
|
523775f78f |
fix(ui): skip keyless document rows instead of crashing the task panel (#18870)
Keep issue-document rows without a string key out of the task panel list and the document caches, so one malformed row cannot crash the page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
11ac90e31f |
fix(build): typecheck server/src/__tests__ and fix every type error (#18739)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The server has about 1,100 test and helper files in `server/src/__tests__` > - `server/tsconfig.json` excludes that directory, Vitest does not check types, and no script runs the tsconfig in that directory > - So a test can call a function with the wrong arguments and still pass, and no tool reports it > - This gap hid 2,168 real type errors, and some of them hid tests that did not test what they claim > - This pull request fixes all of these errors and adds the directory to the server layers from paperclipai/paperclip#18737 > - The benefit is that a type error in a server test now fails the typecheck, with no baseline and no backlog ## Linked Issues or Issue Description Refs paperclipai/paperclip#18737, which is merged and added the server layers. Refs paperclipai/paperclip#18738, which is merged and checks the test projects outside `pnpm -r`, so it is not a duplicate. Refs paperclipai/paperclip#18137, which records that this directory has no check. **What happened?** No tool checked the types of 1,074 of the 1,101 files in `server/src/__tests__`. I searched `package.json`, the workflows, and all tsconfig files. 27 files are in the program of another tsconfig, and these 27 have 0 errors. 11 of the 27 are in `helpers/maintenance/tsconfig.json`. No script ran that project when I measured this. paperclipai/paperclip#18738 now runs it. **Expected behavior** The server typecheck checks these files, and a type error fails the check. **Steps to reproduce** 1. On the base commit, run `tsc -p server/src/__tests__/tsconfig.json --noEmit`. It reports 6,536 errors and needs 12.3 GiB. 2. Add a type error to any file in `server/src/__tests__`. 3. Run `pnpm --filter @paperclipai/server typecheck`. It passes. **Paperclip version or commit** I measured the error breakdown below on commit `8dfd632452`, with TypeScript 7.0.2. The branch now includes master up to paperclipai/paperclip#18865. **Deployment mode** Not applicable. This issue applies to development and CI. No production source file in the server changes. ### Error breakdown Each row adds one change to the row above. | Step | Total errors | Change | Cause | | --- | --- | --- | --- | | Config as committed | 6,536 | | | | Add `src/types/*.d.ts` | 4,447 | -2,089 | Config. The Express request types were missing. | | Set `rootDir` to the repository root | 2,436 | -2,011 | Config. | | Set `allowImportingTsExtensions` | 2,181 | -255 | Config. Vitest accepts `.ts` imports. | | Add `ES2024.Promise` to `lib` | 2,138 | -43 | Config. Node 24 has `Promise.withResolvers`. | | Set `allowJs` for `.mjs` imports | 2,148 | +10 | Config. It removes 8 `TS7016` errors and shows new real errors. | | Set `declaration` to false | 2,142 | -6 | Config. Tests emit nothing. | | Count only files in `server/src` | 2,058 | -84 | Other packages: 53 Daytona, 29 Runner test, 2 UI. | So 4,478 of the 6,536 errors (69%) came from config or scope, and 2,058 are real type errors in 314 files. The 29 Runner test errors are also real, which gives 2,087 errors. Tests that master added after this measurement had 81 more errors, so this pull request fixes 2,168 errors. This table classifies the first 2,058 errors. | Kind of real error | Errors | | --- | --- | | Wrong argument or assignment type | 1,023 | | Stale or partial fixture objects | 525 | | Property that the type does not have | 317 | | Missing narrowing of null or unknown | 101 | | Implicit any | 60 | | Missing name or module | 16 | | Other | 16 | ### What the type errors hid Most errors were stale fixtures and loose mocks. These errors hid real test problems, and this pull request fixes them: - **A test that never ran.** `instrumentation.test.ts` required `sdk-trace-base`, which is not installed. So 3 span tests were skipped. They now run and pass. - **Assertions that could not fail.** - `issue-thread-interactions-service` used a company ID as an issue ID. - `status-card-evaluation-work` compared `[]` with `[]` in a rollback check. - `slack-conversation-lifecycle` read `item.issueId`, which does not exist. - `email-channels` used a permission key that does not exist. - `heartbeat-project-env` imported `LOW_TRUST_REVIEW_PRESET`, which is not exported. The value was undefined. - **Postgres processes that did not stop.** 11 test files called `stop` on the test database helper. That method does not exist, and the helper method is `cleanup`. - **Arguments that the service ignored.** - `methodKey` is now `connectionMethodKey` in the Daytona, Unikraft, 1Password, and Railway tests. - 108 calls passed `"owner-user"` to a parameter that expects an options object. - 9 chat wizard fixtures passed `managementContext` as `source`, so they ran `existing_app` and not `manifest`. - 2 tests passed a `{ userId }` actor that the function ignores. - Inserts into `environments` passed a `companyId` column that the table does not have. - **Problems in tests that master added during this work.** - `sandbox-creation-operations` read `database.connectionString` when an external test database was set. In that mode `database` is undefined, so the fixture would stop with a TypeError. It now uses the external URL. - `idle-completed-history` set a Dot operation to `dispatched`. That is a Muse status, and the Dot type does not have it. The fixture now uses `admitted`, which is a real in-flight Dot status. ### Possible product problems, not changed These may be real problems in production code or types. I did not change them, because this pull request does not change production behavior: - `decisions-service` `service.create` does not validate the lenient `cancel_issue_tree` input. - `createConnection` ignores `input.connectionPurpose`. - The `createConnection` route schema default stores `{}` for `transportConfig`. - `prepareManagedAiRuntime` accepted the invalid value `mode: "connection"`. - `createBinding` accepts invalid `projectionClass` strings outside class 3. - `ensureManagedProjectWorkspace` forwards an untyped `repoRef` by spread. - `routineVariableSchema.label` is optional, but `RoutineVariable.label` is required. - `ToolRunContext.projectId` may be too strict. - `withdrawInteraction` reads `issue.status`, which its type omits. - `issueService.list` and `reconcileNativeFinalizations` omit fields that they return at runtime. - `createGitHubExternalObjectProvider` handles `tokenProvider: null`, but its type forbids this value. ## What Changed - Fixed the 2,168 type errors. The diff changes 322 test and helper files. - Corrected `server/src/__tests__/tsconfig.json`. Editors and the typecheck now read the same options and report the same errors. - Added three `test-tree` layers to `server/scripts/typecheck-layers.mjs`. They read the server layers as declarations, and any error fails them. A hash of the path selects the shard, so a new file does not move other files. - Added `server/scripts/typecheck-stubs/daytona-sdk.d.ts`. Server tests reach Daytona plugin source, and the root install does not have `@daytonaio/sdk`. - Changed two imports in `ui/src/lib/issue-execution-policy.ts` to use `.js` extensions, because server tests import this file. - Made `declarationsConfig` and `--declarations-only` skip the `test-tree` layers, because these layers emit nothing. Other projects read only the source layers. Added a test for this. - Updated `doc/DEVELOPING.md`. ## Verification Run these commands: ```sh pnpm --filter @paperclipai/server typecheck pnpm exec vitest run server/scripts/typecheck-layers.test.mjs ``` Results on macOS (arm64), Node 24, 16 cores. Each check ran after the merge of paperclipai/paperclip#18738 unless the row says otherwise: | Check | Commit | Result | | --- | --- | --- | | Server typecheck, `PAPERCLIP_TYPECHECK_LOW_MEMORY=1`, all 7 layers | `6e45a08573` | Exit 0, 0 errors, 62 seconds, peak 3.52 GiB | | `node scripts/typecheck-test-projects.mjs --low-memory` | `a3306bd13e` | Exit 0, 0 errors, 42 seconds, peak 3.25 GiB | | The same script with `--reuse-declarations` | `1b878aabc0` | Exit 0, 0 errors | | `typecheck-layers.test.mjs` and `live-recovery-work.test.ts` | `01db5634e4` | 90 passed. These include real compiler runs for a pass, a type error, and an invalid tsconfig. | | `tsconfig.declarations.json` after a full server typecheck | `0fb1e4fb0a` | It references only `below`, `cycle`, and `above`. No generated config names a `tsconfig.layers.json` file. | | Owned runtime test in `idle-completed-history` | `e8f2f448ac` | Passed, with the fix that master later replaced | | `idle-incoming-wake`, `plugin-idle-manager`, and the changed `chat-channels` test | `6e45a08573` | 30 passed | | Runner `native-execution.test.ts` | `eab4dcc1f4` | 114 passed | | The 19 server test files that changed since `eab4dcc1f4`, and `typecheck-layers.test.mjs` | `259737b700` | 4,275 of 4,277 passed. The 2 failures are in `chat-channels` and are in the list of 7 below. | The peak is the largest single process, from `/usr/bin/time -l`. Peaks for the server typecheck were between 3.42 GiB and 3.56 GiB across 8 runs. Peaks for the test projects were 3.25 GiB and 3.37 GiB across 2 runs. I did not measure a cgroup. **Runtime check of the fixes.** Types do not prove that a test still works. So I ran all 309 changed server test files, 11,929 tests, before the rebase onto paperclipai/paperclip#18737: | Result | Tests | Detail | | --- | --- | --- | | Passed | 11,913 | Includes the 2 tests and the 54 `dot-runner` tests that passed in a later run, as described below. | | Failed | 7 | The same 7 tests also fail on the commit before the fixes. | | Skipped | 9 | These tests have their own skip conditions: `sentry` 5, and 1 each in `bundled-plugin-registration`, `customer-success-cloud`, `onepassword-connection`, and `workspace-runtime-https-live-exercise`. | The 7 tests that fail with and without this change, on my machine: - 3 tests in `chat-channels` and `email-channels` stop with `ENOENT` on a `SKILL.md` file. The path is in the parent checkout, above the git worktree that I used, so I expect that the worktree is the cause. I did not prove this. - `workspace-instance-cleanup` compares `/private/var/...` with `/var/...`. This is a macOS symlink difference. - 2 tests in `git-reproducible-managed-checkouts` get `unknown_base_git_files` and expect `unpushed_managed_checkout`. I did not find the cause. - 1 more test in `chat-channels`, `materializes direct external-chat finals once`, gets `undefined`. I did not find the cause. CI is the check for these 7 tests. `ci / verify` passed on `eab4dcc1f4`. Failures during this work: - My fix to `agent-runtime-connector-access` changed an invalid permission key in the setup, but not in the assertion. The runtime check found this. I corrected the assertion, and the file passes. - `heartbeat-plugin-environment` failed one wait in the full run. It passed three times alone, so I think that load caused the failure. It can fail again under load. - `dot-runner` skipped all 54 tests in the full run because `cargo` was not on my `PATH`. It then passed 54 of 54 with the toolchain on the `PATH`. - My first `lib` value removed the default DOM types, and the error count went up by 375. I added the DOM libraries. - My Daytona stub with bare `any` left 48 errors, because generic helpers then inferred `unknown`. I added shapes that return promises. - One fix to `agent-secrets-routes` used `class_3_static_lease`, and the test failed. That class allows only specific paths. I reverted to `unclassified`. - `ci / General tests (server (8/12))` failed on `259737b700` because of the flaky port in `idle-completed-history`. paperclipai/paperclip#18853 fixed this test on master, so this pull request keeps that fix. **Audit of the diff.** I counted these patterns in added and removed lines, to find fixes that only hide an error: | Pattern | Added | Removed | | --- | --- | --- | | `@ts-ignore` | 0 | 0 | | `@ts-expect-error` | 0 | 1 | | `.skip` | 0 | 0 | | `as any` | 9 | 9 | | `: any` | 11 | 2 | | `as never` | 8 | 2 | | `as unknown as` | 35 | 4 | | `Promise<unknown>` | 16 | 5 | | `expect(` | 128 | 113 | No hunk removes more `expect(` calls than it adds. Three removals of test content were intentional, and I checked each one: - `muse-control` removed `signalToken`. Line 1012 already asserts that it is absent. - `merged-pr-confirmation-sweep` removed legacy aliases. Other tests cover them. - `heartbeat-workspace-branch-containment` removed a `finalize` branch that no test row can reach. Some partial fixtures stay unchecked through `as unknown as` and `Promise<unknown>`, mostly in `issue-agent-mutation-ownership-routes` and `issue-comment-reopen-routes`. **Accuracy of the check.** One program over the tree and the three shards reported the same errors at the same positions. Memory, as the peak of the largest process on one thread, was 3.93 GiB for one program and 2.43 GiB for the largest shard. I measured these two values before the fixes. Not run or not proven: - I did not run the full `pnpm test:run`, or a root `pnpm build`. I expect CI to run the full suites. - I did not run the 4 GiB container check, or the full `scripts/typecheck-low-memory.mjs`. The peaks above come from macOS, so they are not a Linux cgroup measurement. - I did not run the UI typecheck after the merges. - `workspace-runtime-https-live-exercise` is skipped, so its `cleanup` fix did not run. ## Risks - **A large diff in test files.** 328 files change. A pull request that edits the same tests can get merge conflicts. New tests on master can also add type errors before this merges. Any such error fails this check and needs a fix here. - **A higher cost for changes to source types.** A change to a type can add errors in test files that the author did not touch. The author must then fix them. This is the purpose of the check, but it is new work. - **Changed test behavior.** Some tests now run paths that they did not run before, such as the 9 chat wizard fixtures and the 3 span tests. They pass here, but they can be more sensitive to timing or to the environment. - **The Daytona stub can go stale.** The stub is written by hand. If the plugin uses a new SDK member, the typecheck reports an error until someone updates the stub. - **The release path.** `release-verify.yml` and `scripts/release.sh` run `pnpm -r typecheck`, so they now run this check. - **The tsconfig change.** The test transform reads `server/src/__tests__/tsconfig.json`. The options that I changed are for type checks, and the runs above passed. - **A gap that remains.** Tsconfigs in `packages/paperclip-runner` and in most sandbox provider plugins exclude `*.test.ts`. This check does not read most of those test files, so they can still drift. That work is separate from this pull request. > 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`) through Claude Code, with reasoning, tool use, code execution, and subagents. The runtime does not show 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 - [ ] I have run tests locally and they pass (7 tests fail locally, with and without this change. See Verification.) - [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> |
||
|
|
51d1d4ce07 |
fix(ui): refine coordinator navigation and task list defaults (#18831)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The Coordinator workspace puts chat, tasks, and human decisions in one navigation. > - Its task menu exposed only two views and always opened All tasks. > - Its sidebar hid search under More and showed an empty Recents section. > - This pull request restores the four task views and saves each user's last selection. > - It also groups the main navigation and makes the task list use the page background. > - Users can return to their preferred task view and find search from the sidebar. ## Linked Issues or Issue Description **What existing behavior does this improve?** The Coordinator sidebar and task collection. **Subsystem affected** ui/ — React and Vite board UI. **Current behavior** Coordinator opens All tasks and offers only All tasks and Needs attention. Search lives under More. Empty Recents content takes sidebar space. The task list inherits a darker root background. **Proposed behavior** Tasks starts in Inbox for new users. The menu contains Inbox, Unread, Needs attention, and All tasks. The selected view persists per user in browser storage. The sidebar groups Chat, Tasks, and Needs you between New task and More. Search sits beside the organization menu. Recents appears only when entries exist. The list surface and edge fades match the local page background. **Reason and benefit** The page starts with personal work and restores the user's last choice. Navigation gives search a fixed location and removes empty content. **Breaking changes** Unread task-view links now stay on Coordinator Tasks. Retired merged-Inbox views keep their existing Inbox routes. Organization-filter links without an explicit view still open All tasks. Needs attention keeps the existing pending-decision feed. The initial Inbox rule applies to Coordinator. Task lists now default to newest updates, including task-detail subtask lists. Saved and URL sort choices stay intact. **Additional context** Related merged work: Refs #18703, Refs #17983, Refs #18323, Refs #18492. The GitHub search found no duplicate open PR for these changes. This is focused UI polish within the existing workspace and does not add a roadmap feature. ## What Changed - Default task lists to Last updated descending and show that active header. Keep descendants with their parents while nesting is on; use a flat newest-first order when nesting is off. Task-detail subtask lists use this default and retain checklist controls. Saved and URL sort choices keep precedence. - Add space after New task and before More. Add header search with the existing command palette action. - Use “Needs you” in desktop navigation, mobile navigation, and the decision page. - Hide Recents when no entries exist. - Restore the shared four-view task menu. Default Coordinator to Inbox and save the last view per user. - Read unread tasks through the server's viewer read filter. Preserve task hierarchy and existing filtered links. - Use the resolved local-board identity for Inbox. Keep Inbox and Unread selected when a status filter changes. Load accessible read ancestors as context for unread subtasks. - Resolve task-list and edge-fade surfaces against the Coordinator background token. - Update view, routing, navigation tests, and DESIGN.md. ## Verification - Passed for the sorting update: 344 tests across the task-list, classic and streamlined nesting, Coordinator task page, and task-detail suites. - Passed for the sorting update: 30 Storybook catalog and map checks, token gates, UI typecheck, and UI production build. - Browser check: a task-list URL without sort parameters shows Last updated descending as the active sort. - Passed: `pnpm -r typecheck` after rebase onto master. - Passed after review fixes: 91 tests across seven affected task-view, routing, identity, navigation, and decision-page suites. - Passed after review fixes: UI typecheck and UI production build. - Passed: `pnpm check:token-gates` and `git diff --check`. - Browser checks: Inbox opens on the first task visit. The menu shows all four views. Unread survives leaving Tasks and returning, and survives reload. Header search opens the command palette. Empty Recents is absent. - Browser style check: the page, task-list section, row groups, and edge-fade token resolve to the same local background. - Passed: `pnpm build` after rebase onto master. - Local full-suite run: all six chat integration shards passed (1,834 tests). Stopped the remaining local run after all latest-head CI test gates passed. The local full suite did not finish. - Greptile: 5/5 on current commit `5fc50d616c`, with all three earlier review findings fixed and all threads resolved. The sorting update added no new review findings. - Initial CI failed in [browser shard 1/8](https://github.com/paperclipai/paperclip/actions/runs/41702707260/job/126156263776). The cross-organization UUID task-link test reached its 5-second heading assertion timeout. The failure screenshot and page snapshot show the correct task heading. The precise cause of the timeout remains unknown. - Passed during CI diagnosis: six focused Chrome browser runs, then all 35 tests from the same shard on the unchanged branch. Task links resolved to the target organization and attachment uploads completed. - Passed on the single unchanged-head CI retry: [all 35 tests in browser shard 1/8](https://github.com/paperclipai/paperclip/actions/runs/41702707260/job/126184223560), including the original UUID task-link case. This establishes recovery; it does not establish the original timeout cause. - Passed: [all CI gates for commit `5fc50d616c`](https://github.com/paperclipai/paperclip/actions/runs/41702707260). The final aggregate gate passed. No check is pending or failing. Three checks are skipped as expected, and the optional Superagent scan is neutral. - Review: confirm the sidebar order, four task views, saved view after navigation, and matching list background. ## Risks - Task-list defaults change from Task ID order to newest updates. Task-detail subtask lists use the same default instead of workflow order. Existing saved and explicit sort choices remain available. - Low risk. New Coordinator users start in Inbox instead of All tasks. - The view preference stays in this browser and does not sync across devices. - The task collection keeps its existing paging behavior. - Unread URLs now select the native Coordinator task view. ## Model Used OpenAI Codex, GPT-6 family. The session did not expose a more specific runtime model ID or context-window size. Used code editing, terminal tools, and browser verification. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Scott Tong <scott@scottsmbpm5max.lan> Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
519b345d69 |
fix(ui): expose governed retained-file recovery (#18848)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The control plane must preserve saved work before it admits another attempt. > - Retained-file recovery already has an authorized API and a bounded worker. > - The task UI hid that operation when workspace repair blocked execution. > - The run inspector could check source identity but could not request preservation. > - This pull request exposes that existing operation with its exact source binding. > - The worker still owns file verification, stop receipts, and execution release. ## Linked Issues or Issue Description Refs #18678 and #18803 for the existing retained-source and continuation contracts. **What happened?** A failed native run could leave an active, system-owned export recovery action. The task showed a generic Retry control. Its workspace repair gate correctly refused another provider turn. The run inspector offered only read-only source inspection. The authorized file-preservation API had no production UI caller. **Expected behavior** An authorized board operator can request preservation of the exact retained files. The UI keeps the repair hold until the server records verified preservation. A lost response must keep the same request identity. **Steps to reproduce** 1. Use an active retained-export action whose workspace recovery is blocked and retryable. 2. Open its source task while `workspaceRepairRequired` is true. 3. Open the exact failed run and inspect recovery. 4. Before this change, neither surface can request the existing file-preservation operation. **Paperclip version or commit** The focused regression fails on master `1f55073f96b2485f49f98ee8c261aa14ec2f79ac` before the production UI edits. I checked the roadmap and searched open public PRs for this UI repair. No duplicate was found. This is a repair to the existing recovery capability. ## What Changed - Add Recover saved files to the existing task recovery area and exact-run inspector. Reuse the current board task-mutation access check and the existing `recoverWorkspace` API. - Read the exact action, run, company, task, and source observation again before sending. Refuse changed, retired, foreign, unverified, or non-retryable sources. - Save one account-scoped request before POST. Keep its key through a lost response and reload. Reconcile with GET before an explicit resend. Use a new key only after an explicit click and a fresh, confirmed exhausted attempt; do not resend automatically. - Show queued, recovering, blocked, and verified receipt states separately. A request acknowledgement does not mark files saved or resolve the task hold. Hide generic Retry for native export holds. Keep the existing Retry path for legacy restoration. - Cover both mounted surfaces and negative access, source, account, persistence, duplicate-click, and lost-response cases. Update the existing design guidance and correct the affected run-detail recipe only. ## Verification - RED: the new component regression fails with `missing Recover saved files` before production changes. The original failure is retained. - GREEN: 265 tests pass across `WorkspaceExportRecovery.control.test.tsx`, `WorkspaceExportRecovery.test.tsx`, `RunWorkspaceRecoverySurface.test.tsx`, and the full `IssueDetail.test.tsx` suite. - Review RED/GREEN: the prior UI reused the failed key after a confirmed exhausted attempt. A focused regression now proves a different key for an explicit new attempt, while the lost-response controls still prove key reuse. Mounted task controls prove that verified native preservation stays available, unverified or stale native sources never offer generic Retry, and viewers cannot mutate. A separate RED against the exact prior UI proves the lost legacy control. Its GREEN clicks the existing legacy Retry API while the workspace hold remains active. - Full UI TypeScript check passes: `node scripts/run-tsc.mjs -p ui/tsconfig.json --noEmit`. - `node scripts/check-token-gates.mjs`, `node scripts/check-maps.mjs`, and `git diff --check` pass. The map check proves structure only. - One early legacy test probe used an unsigned fixture and a readonly array; those setup failures are retained. The corrected same-user fixture proves the source RED and GREEN. The first test command used an unnamed project filter and stopped before loading tests. The corrected package configuration produced the recorded RED. One initial storage fault probe did not intercept jsdom's storage method; the corrected prototype fault proves that unavailable storage sends no POST. - Dependencies use Node 24.22.2 and a frozen pnpm 9.15.4 install with scripts disabled. The maintained shared and SDK prerequisite builds pass on this base. No dependency or lockfile changes are included. - A later Paperclip Review follow-up found the plain-HTTP UUID gap. Its focused regression fails before POST with the prior direct call, then passes with the existing UUID helper. The same storage, lost-response, retry and source controls remain green. - Original full CI `41715060582` fails two Cloud-auth task-entry browser checks at their existing heading assertion. The retained original artifacts show a late task pane (one already contains the heading; one still shows Loading conversation). The cause remains unproven. No auth, fixture, timeout or assertion change is included. Fresh Greptile is 5/5 with zero open threads and Paperclip Review passes on the UUID fix head. Current full CI `41720068249` attempt 1 failed. Three workers were terminated by AWS Spot capacity loss. The CLI startup and dense-ZIP checks also timed out at their unchanged deadlines. The CLI/shared input trees match a previous passing CI job, and the dense-ZIP case passes one focused local check. The CLI timeout cause remains unknown. The coordinator requested one bounded recheck. Attempt 2 succeeds on the same source, with all current checks green. No source, fixture, timeout or assertion changed for that recheck. The worker issued no retry. This pass does not establish the original CLI timeout cause. - Full recursive typecheck, repository tests, and application build were not run locally under the bounded UI verification scope. Full CI is requested. - No live preservation request, provider turn, deployment, or sandbox cleanup was performed for this repair. Original saved-file recovery remains unverified until rollout and real acceptance. ## Risks The client access check is a display guard. The existing server authorization and physical source, ownership, stop, and snapshot checks remain authoritative. Unavailable browser storage blocks the request before POST. A failed acknowledgement retains the request for its owner. The UI never calls task Retry, recovery resolution, reconstruction, provider execution, or destructive cleanup. The existing worker retains its bounded recovery policy and may finish the saved result after real preservation. ## Model Used OpenAI Codex, GPT-6 family, with repository inspection, code editing, and test execution. The exact runtime model ID and context-window size are not exposed to this agent. ## 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> |
||
|
|
1f55073f96 |
fix(cursor-cloud): support API-only controllers on managed stacks (#18310)
## Thinking Path > - Paperclip helps people manage AI agents at work. > - Cursor Cloud hosts execution behind its API. > - Product setup still expected a Paperclip Computer. > - Managed-only tenants therefore rejected valid setup. > - This admits the validated API-owned controller. > - Authority, Stop proof, budgets and cleanup remain enforced. ## Linked Issues or Issue Description Refs #18068 and #18069; both dependencies have merged. **What happened?** Managed-only setup still requested a Computer. Live tests exposed missing Cursor Stop proof and duplicate replay. **Expected behavior** Use Cursor’s API controller. Verify provider/controller termination and replay each log identity once. **Steps to reproduce** Enable native Runner/managed-only. Configure Cursor model/repository/key without a Computer, then Test, finish setup, run and Stop. ## What Changed - Derive API-only placement from validated native Cursor configuration; reject placement/command/workspace/home overrides and keep Kubernetes-only execution closed. - Skip Computers/checkout/workspace realization. Keep scoped tools, completion, private staging, budgets, leases and recovery. Persist placement; reject contradictions. - Align Cloud cards, Test, Save and Finish setup; hold unready drafts. Legacy keeps its Computer, credential and policy checks. - Verify Stop from exact API ownership, audited intent, provider-terminal proof, no Computer/process ownership and controller retirement. Recheck immediate/deferred retirement; wake existing recovery on durable evidence. - Clear warnings when the actual stopped target later has authoritative confirmation. Keep missing/other-run negatives and the existing predicate. - Publish safe status refresh after full-proof ACK. Retain bounded native/physical cancellation history; add no poller or weaker proof path. ## Verification Core merged as `3910352c923a`; Product merged as `27d35314be8e`. Public branch `5f86eb66b081` has tree `67344151d303`. Its exact-head Greptile summary is 5/5; the fresh audit found zero unresolved threads and complete pagination. The controlled workspace retry and required summary passed. All 59 current-head contexts are terminal and clean. Prior green-36 evidence keeps its identity. [Current CI](https://github.com/paperclipai/paperclip/actions/runs/41680511731) first failed workspaces-a 1/2: the CLI company-import/export beforeAll 30-second runtime-info/child-PID/HTTP readiness wait expired. All 431 UI files/4,714 tests and 285 other CLI tests passed (one skip). The cause remains UNKNOWN. Child output records startup recovery complete, but buffered CI prefixes do not establish its relation to the waiter deadline; runtime-file/PID/last-health state was not captured. Both unchanged local probes were RED. The second observed dependency preflight still pending at the deadline; observer overhead was not quantified. Neither proves the CI cause. After all functional jobs finished, only the queued metadata summary was cancelled; the other 48 records stayed unchanged. Attempt 1 retains 46 successes, the original failure, one skip and the cancelled summary. One same-head debug retry was admitted at 18:42 UTC on November 3. Its workspace job passed at 19:23 UTC on the same checkout: UI 431 files/4,714 tests and CLI 33 files/286 tests, including company import/export. Test caching was disabled. The new `ci / verify` summary passed; workflow attempt 2 completed SUCCESS. Required `ci / e2e` also passed. The final check at 19:53 UTC on November 3 found all 59 current-head contexts terminal and clean: zero pending and zero failing. The 47 inherited completed/skipped rows are not new executions. No code, assertion or timeout changed; success does not explain the original failure or erase the local REDs. CI checkout is `1ea9d8608ced`/tree `78cb1ec13d59` (parents `2e37c73c05fe`, 5f86); both workflows use 2e37. Its 20 extra paths add low-memory build/Rust task-memory. Scripts cohere; later matrix changes only labels, with no newer debug-cache steps. Static audit found no blocker. Supported API arguments omit the memory flag: no default monitor/instruction changes. Flagged external launchers can change Cursor instructions/digests and remain unqualified. The merge added 41 master-identical paths, retained the green-36 inbox hunk and found UI fixtures matching upstream. Startup/backup, recovery projection, sleep diagnostics and binary backup change production. Static audit found eight Stop/ACK owner blobs and 37 sleep-work SQL templates unchanged, with sleep fences/single-flight accounting intact. Exact precommit tree: 416/416 across eight server files, binary backup 1/1, server types PASS; repeated scopes are not summed. The deferred-retirement P1 reproduced three real-DB/owned-process failures; missing proof stayed unverified. Recovery passed 47 process cases/33 proof negatives. Warning repair binds actual targets to same-run proof. Validation passed 729 scoped UI cases, a separate 359-case thread run, 111 backend cases (84 CAS, 6 assembled, 21 activity/privacy), types/tokens. Proof validators/predicate are unchanged; no new poller or increased timeout. The d8d3 attempt stays FAILED: 45 passes, two workspaces-a failures, derived verify failure and one skip. Both shards shared three failures: two successful mocks omitted the account guard’s required userId. The two-line fixture repair changed no guard, assertion or timeout. Three failures reproduced; 54 access/auth tests then passed, including account-change/denial negatives, plus UI types/tokens. The 69285 attempt stays FAILED: 49 jobs, 46 passed, serialized shard 9 failed, its verify aggregate failed and one selection job skipped. The shard passed 575/576 cases. Its aborted-snapshot case expected nine computes but saw eight: a final HTTP 200 coalesced while seven ordinary reads had not proved the aborted compute settled. Earlier CI and the unmodified local baseline passed with a miss; no local RED is claimed. The repair awaits the snapshot, allows exactly one extra GET if coalesced, then requires a miss and retains nine computes/all HTTP429 assertions. No production code, hook, loop, sleep or timeout changed. Six inbox and seven cache/admission cases passed locally, plus server types; 30 unrelated cases were filtered. Green 36 passed 576/576 without taking the extra-GET branch; local runs also missed that schedule. Current CI event merge 1ea9 now passed 576/576 and naturally exercised the former failure: coalesced (count 2, 1ms), then exactly one fresh miss (count 1, 16ms), with strict nine-compute/HTTP429 assertions intact. No instrumentation or retry was added. Earlier compatibility passed scoped remote/inbox, routine, API-placement and UI tests, plus types/migrations/snapshots/maps/tokens. The 89-path adoption restored fleet routing without workflow overrides or added skips. Each result retains its source identity. Live qualification remains actual `9af1a5de42a2`: unchanged Artifact grader PASSED 17/17 and active-Stop grader PASSED 21/21. All three provider test resources were deleted canonically with GET404; post-delete download returned the exact 27 bytes. Histories stayed stable (Artifact 121 and Stop 67 canonical identities), with 21 company runs, zero active work and no accounting/cancellation/reservation debt or integrity findings. Saved settings reopened; no-prompt Test/Linux admission passed with `claude-sonnet-4-5`. No new Save is claimed. The first Stop sampling case stays FAILED on a 10.373-second gap. Unchanged retry kept all 24 samples: 35.076 seconds quiet, maximum gap 4.584 seconds, plus a separate CANCELLED/artifact-absent read after 180 seconds. Initial grading rejected locator spelling before functional checks; metadata changed only after same-file/inode/byte proof, with raw evidence/oracles unchanged. Original Question/Plan/reconnect and historical deleted-artifact results keep their identities. Git trees verified 11 history-only conflicts and six earlier mainline paths. Hosted 9af to the public BRANCH differs in 222 paths; 13,500 other mode/blob leaves match. Runner runtime implementations and six observer/driver pins match 9af on that branch only; inherited `drivers/acpx/runtime-host.test.ts` differs. No all-Runner/src, CI/latest-master runtime or image equality is claimed. Later static audits through `8ab89f41e499` found no concrete API-only blocker. That base adds completed-history sleep proofs and an MCP cleanup migration; protected Stop/ACK owners are unchanged. These later changes are outside this CI and have no live qualification here. Host duplicate-card and later recovery/UI repairs retain separate proof, not deployed 9af identity. Direct-key coverage requires absent aiConnection; API-only placement skips inherited remote-workspace disk-full paths, and config-read gates match their parent. Other retained failures: stale fixture 132/133; E8 48/135 with 87 reset-hook failures; Mac 17 SQL failures/skips; title/startup/custody/Stop/deletion unknown causes and bounded recoveries; superseded warning/50 duplicate identities; pre-repair ACK/Core CI failures. Fixture RED/GREEN passed 7/7 browser and 121/121 shutdown tests with a failing broken-unsubscribe control; stable WSP wrapper passed 128 after physical teardown failure. No full local-suite pass is inferred. All paid attempts remain recorded; vendor dollar cost is UNKNOWN. ## Risks Experimental: Cursor independently acknowledges neither the effective model nor instruction digest before the first prompt. Explicit values are submitted and behavior checked live; unpriced provider dollar cost stays UNKNOWN. The placement exception applies only to validated native Cursor API execution. Other local work remains denied under managed-only policy. Missing/stale Stop or cleanup proof stays pending; damaged archives remain failed. Explicit Legacy keeps its existing policy owners. ## Model Used OpenAI Codex/GPT-6 family: tools, execution, browser checks, delegated review. API ID/context window unavailable. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used and the limits of available model metadata - [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 linked public issues or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch describes the change and contains no internal ticket ID - [x] I have run the scoped local tests reported above; retained failures are stated separately - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation - [x] I have considered and documented the risks - [x] All required CI gates pass on the current head - [x] Fresh Greptile is 5/5 with no unresolved findings on the current head - [x] I will address all reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
b40e6edaea |
perf(inbox): combine startup reads and reduce refetch pressure (#18790)
## Thinking Path > - Paperclip helps people manage AI agents and their work. > - Mine shows the work and failures that need the viewing user's attention. > - A reload waits for account access, task rows, parent captions and failure state. > - Those reads form several browser request stages before useful rows appear. > - Live invalidations can also restart the same task-list request more than once. > - This change supplies startup data together and removes redundant refresh work. > - It preserves current authority, failure presentation, archive state and row stability. ## Linked Issues or Issue Description Refs #18645. Related: #18642. This change implements the read-receipt behavior independently on current master. It does not use that PR's branch or patch. **What happened?** Mine starts its primary request after the session, company and board-access reads. It then requests parent captions and rich failure context. Four observed loads spent another 0.45–0.70 seconds after the primary rows arrived. One slower load waited 1.71 seconds for parent context. The same run observed two HTTP 429 responses. These timings identify request waits; they do not attribute the delay to SQL or Node CPU. Read receipts also invalidate general task collections and dashboards. Overlapping parent and child invalidations can start two requests and abort the first. **Expected behavior** The initial page should use one account-safe startup projection and one complete Mine response. A read receipt should refresh the affected viewer's inbox state. Each invalidation batch should refresh a covered query once. Required captions and current failure state must be ready before first reveal. Existing rows should remain usable during a transient refresh error. **Steps to reproduce** 1. Open a populated Mine inbox with parent tasks outside the visible index and a current failed run. 2. Reload with browser HTTP cache retained and application query state empty. 3. Inspect the session, company, board access, task-index and context request sequence. 4. Open or mark a task read and inspect the unrelated collection refetches. **Paperclip version or commit** Baseline: `44a9a043b80c18314d8dd89556f444dae696d3d6`. **Deployment mode** Authenticated board UI. Local proof uses the real APIs and database with a synthetic session resolver. No hosted candidate deployment is claimed. ## What Changed - Add optional, same-user `boardBootstrap` data to the existing session response. Seed account-keyed company and board-access reads from it. Keep ordinary endpoint reads for fallback, retry and live reconciliation. A returning account cannot reuse revoked cached access. Cache collection and later real refetches remain effective. - Add the board-only Mine snapshot endpoint. Reuse the canonical issue selector, private-task filtering, run-read decisions, secret redaction and interruption/recovery presentation. Assemble the fixed 100-task page, parent captions and bounded 200-run failure window on the server. Start independent reads together. Optional source errors keep successful task rows usable. - Keep array-shaped source caches for archive and undo. Key Mine source, context and reveal state by account. Validate the response's user stamp before committing it. Remove array-only cross-tab Mine broadcasts, which cannot carry its paired failure context. The server retains authenticated in-flight coalescing. - Scope read-receipt invalidation to the affected viewer's inbox, badges and chat unread state. Keep company and task audit views fresh. Preserve genuine task mutations, run updates and subscription-gap reconciliation. - Remove covered scalar-prefix invalidations within a batch. Preserve predicates, exact matches and different query/refetch constraints. A later event can still refresh again. - Retire Mine in-flight reuse after local company activity or run lifecycle changes. A post-archive read starts fresh. Old work keeps its admission slot until it settles, even if every HTTP client aborts. The eight-compute limit stays in place. - Add API, component and browser regressions. Extend the production timing harness with matching API/UI artifact receipts, retained-cache reloads, request status counts, layout checks and optional controlled network latency. Update API and verification documentation. ## Verification - Full `pnpm -r typecheck` passes. - Full `pnpm build` passes. - Token gates, map checks and diff whitespace checks pass. - 72 Inbox component tests pass. Startup-specific checks pass, including account switching, revoked cached access, malformed/absent bootstrap data and cache collection. The canonical authenticated bootstrap route also passes against real PostgreSQL. - Six real PostgreSQL Mine route cases pass, including full equivalence with legacy authorized projections, privacy, fixed bounds, membership revocation, coalescing, archive freshness and aborted-client admission. Four focused legacy coordinator controls pass. Six assembly tests pass. - Refetch and invalidation regressions pass. Meaningful pre-fix tests observed two request starts and one abort for overlapping invalidations; the fix produces one start and no abort. The archive race test observed the post-archive GET joining the old body before the fix. - All 11 existing startup browser checks pass, including Tasks/Mine code loading, desktop/mobile bounds, non-streamlined Coordinator, task navigation, failed preloading and Back position. The nine focused startup, fallback, partial-source error, rate-limit recovery, archive/undo and geometry cases also pass. The 429 cases use the inherited retry window. Archive and keyboard undo are corroborated through the real API and reload. Authentication and failure fault injection in these cases are explicitly simulated. - Matched production before/after timings are complete. Full aggregate Vitest coverage is left to CI. At 15:15 UTC, the final-head runner gate and `review` workflow pass. The 45 build/test/policy jobs are queued; the Build job has no `ubuntu-latest` runner assigned and has executed no steps, so remote aggregate results remain unverified. Paperclip Review and Superagent Security Scan are in progress. Superseded runs for this PR were cancelled. No current-head check has reported a failure; the CI checklist remains open. The remaining step is runner allocation and completion of those external checks; persistent queueing needs the repository CI owner's attention. - Greptile completed on final head `ecde295565309275c4f2fae903caf6892f1eaafd` at 5/5. The map-scope finding is fixed and resolved; there are no open review threads. ### Matched browser timings Five alternating baseline/candidate pairs per network scenario, measured serially in headful Chrome 156.0.8078.80 on Apple silicon with Node 24.22.2 and a 1440×900 viewport. Both production UIs use their matching real API revision against one fixed disposable PostgreSQL fixture: 34 tasks, 31 visible task rows, one paused agent and one terminal failure. No active agent/provider work. HTTP cache is retained; each initial sample reloads the document and clears application query state. Warm navigation and Back retain query state. CPU and throughput are native. The 100ms scenario uses CDP minimum request-to-response-header latency without request interception. It is a controlled request-dependency experiment, not a staging reproduction. Values are median milliseconds with min–max in parentheses. Paired saving is baseline minus candidate for each alternating pair; its median differs from the difference of arm medians. Positive saving favors the candidate. | Network / journey | Baseline | Candidate | Median paired saving | | --- | ---: | ---: | ---: | | Native / initial rows | 187.6 (128.9–208.5) | 191.7 (130.3–210.9) | −23.3 | | Native / Recent → Mine | 100.17 (99.90–101.87) | 100.07 (99.88–101.37) | −0.16 | | Native / task → Back | 70.45 (56.63–72.02) | 66.64 (56.52–67.71) | +4.94 | | 100ms / initial rows | 930.3 (914.1–1015.7) | 799.0 (697.1–826.0) | +211.8 | | 100ms / Recent → Mine | 100.09 (97.73–100.16) | 100.18 (96.65–100.98) | −0.02 | | 100ms / task → Back | 74.97 (62.77–75.82) | 75.47 (61.51–76.19) | +0.35 | The controlled-latency initial pairs all improve, saving 108.3–217.0ms. Native initial pairs have mixed signs (−67.5 to +78.1ms), so they establish no reliable native page-speed improvement. Warm and Back timings are effectively unchanged. Median primary-request start is 110.4→135.2ms natively and 497.8→480.9ms with 100ms latency; these runs do not establish a large startup-only timing gain. API requests through the two-second post-reveal window fall from median 32 (32–37) to 27 (25–28) natively, and 37 (33–38) to 30 (25–32) with 100ms latency. All 20 samples preserve the same ordered 31 task links, first-row DOM identity and geometry. All recorded API responses are HTTP 200; zero unfinished requests, 429s or JavaScript errors. Lower 429 incidence on staging remains unproven. Measured source: baseline `44a9a043b80c18314d8dd89556f444dae696d3d6`, candidate `4c12b2ef0ecf0754676e99bd6b9399e84408646c`. Final head `ecde295565309275c4f2fae903caf6892f1eaafd` changes only two feature-map files and existing browser test expectations since that measured candidate; production executable inputs are identical to the measured candidate. Asset hashes, API health revision receipts and every raw sample were retained. These results do not claim hosted-page improvement or deployment of this PR. ## Risks - Startup enrichment adds work to the session read. Failure of this optional projection falls back to the ordinary company and access endpoints. It does not invalidate a valid session or replace per-request server authorization. - Account changes, stale cache entries and same-company navigation can expose old presentation data. Account keys, principal stamps, reveal scopes and canonical bootstrap replacement have dedicated negative cases. Permission failures hide cached task rows; transient network, 429 and 5xx failures preserve them. - Current failure state can differ from the historical failed run. The snapshot uses the existing canonical rich projection and verified missing-ID coverage. Partial context failures retain an explicit retry path. - Mutation retirement follows events delivered to the current server process. This adds no cross-replica invalidation protocol or distributed read-after-write guarantee. - New UI assets require the matching API. Older UI/session consumers retain their existing response and endpoint behavior. There is no database migration, provider call or deployment change. ## Model Used OpenAI Codex, based on GPT-6, with reasoning, code execution, browser automation and delegated source review. The exact runtime model 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 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> |
||
|
|
27d35314be |
feat: connect experimental Cursor Cloud to native Runner (#18069)
## Thinking Path > - Paperclip helps people manage AI agents at work. > - Native Runner owns execution and task authority. > - Operators need an explicit native Cursor Cloud choice. > - Tools/files need company, task, session and run scope. > - This connects setup and lifecycle to Runner Core. > - Legacy agents retain their selected runtime/history. ## Linked Issues or Issue Description Depends on #18068. Managed-only API placement and API-owned Stop containment are in #18310. Refs #5664, #11803, #17299, and #17471. No duplicate native integration was found. ## What Changed - Add explicit native setup, Test, saved settings and dispatch with no-prompt account/catalog/callback checks. - Scope MCP to company, agent, task, session and run through authenticated HTTPS. Register verified artifacts/work products; preserve unpriced accounting, completion and budgets. - Connect Question/Plan continuation, cold handoff and admitted fresh sessions; recheck waiting admission under the task lock. - Present audited Stop intent while preserving physical containment proof; bound typed Stop metadata. Preserve title edits through preference/navigation readiness. - Select one live/history representation per run to prevent duplicate settled cards. Integrate upstream task/read-state/retry/schema contracts and repair two test fixtures. ## Verification Core #18068 merged normally as `3910352c923a`. Product head `5a60f541c982` has passing repository CI/build/browser checks, including required `ci / verify` and `ci / e2e`, plus a fresh exact-head Greptile 5/5 review with zero unresolved threads. Two non-required external app checks remain pending: Paperclip Review is queued waiting for its assigned agent; Superagent Security Scan is reviewing the diff. These are not claimed completed. The normal merge endpoint enforces the repository rules; no policy or status override is used. The dependent Top PR is addressing its fresh deferred-Stop review finding. Product `5a60f541c982` passed 270 UI and 20 selected Cloud/native/disk-full tests, UI/server typechecks, tokens and maps. Top’s clean normal merge passed tokens/maps/diff checks; its matrix is pending. Earlier receipts retain Core’s 47 Rust, 4 compiled-native retirement and 19 settlement controls, normal Runner build, and runtime 9af build/recursive typecheck. Reproduced loading/shutdown CI fixture failures passed 7/7 browser and 121/121 unit tests, including a broken-unsubscribe negative control. No timeout/oracle was relaxed. The actual-parent restack adopts 75 mainline paths, including schema/permission and generic runtime changes, beyond the prior two fixture repairs and client projection fix. The full difference from hosted `9af1a5de42a2` is therefore larger than four files; backend source also differs. The merged config-read checks match Core391, and the Cursor placement/runtime/relay/selection modules match frozen9af; selected affected regressions pass. Paid proof keeps its actual 9af source/image identity. The separately tested live/history card fix is not claimed deployed on that host. On 9af, original saved settings survived reopening and fresh no-prompt Test authenticated catalog/model/binding; no new Save is claimed. Fresh Linux admission passed. With `claude-sonnet-4-5`, Artifact downloaded exact 27 bytes and matched 121 canonical identities in complete S3-served history. First Stop’s strict quiet FAILED on a 10.373-second gap despite independent cancellation/no late artifact. One targeted unchanged-sampler retry retained all 24 samples: 35.076 seconds quiet / maximum gap 4.584 seconds, 67 ordered canonical identities, and separate CANCELLED/artifact-absent status after the original 180-second deadline. The pre-reload duplicate settled card is disclosed. Exact-ID cleanup for the three new provider agents is awaiting authorization, so full grades and the fresh Artifact’s post-cleanup download remain blocked. A historical deleted-provider artifact was newly downloaded on 9af; original F226 Question/Plan/reconnect and cleanup proof keep their identities. Retained failures: stale fixture 132/133; E8 48/135 with 87 reset-hook failures; Mac 17 SQL failures/skips; earlier title/startup/custody/Stop/deletion failures with unknown causes/bounded recoveries; `dea023` Stop’s warning/50 duplicate identities; pre-repair ACK and original Core CI failures. WSP’s 251-assertion, 7/8-suite attempt failed physical PostgreSQL teardown; the unchanged wrapper rerun passed 128. Retry alone establishes no cause or full local-suite pass. All paid attempts remain recorded; vendor dollar cost is UNKNOWN. ## Risks Experimental: Cursor independently acknowledges neither the effective model nor instruction digest before the first prompt. Explicit values are submitted and checked through behavior; unpriced provider dollar cost stays UNKNOWN. Callbacks need authenticated reachable HTTPS. Scope, revocation, budgets, completion and cleanup remain authoritative. Operator Stop intent is separate from physical containment. Saved legacy agents retain their selected runtime. Prior shared title-save/deletion failures remain disclosed. ## Model Used OpenAI Codex, GPT-6 family, assisted with reasoning, repository tools, code execution, browser verification, and delegated code review. The serving model’s exact API ID and context window are not exposed. No value is inferred from the model catalog. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used and the limits of available model metadata - [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 linked public issues or described the issue in this PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch describes the change and contains no internal ticket ID - [x] I have run the scoped local tests reported above; pending gates are stated separately - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation - [x] I have considered and documented the risks - [x] All required CI gates pass on the current head - [x] Fresh Greptile is 5/5 with no unresolved findings on the current head - [x] I will address all reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
4814d1ab69 |
fix(ui): show composer images as rounded thumbnails (#18689)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - People use the new-task and thread composers to send text and files. > - Images currently enter the text editor or appear with other files. > - Large images interrupt text entry and make the two composers inconsistent. > - This pull request puts image previews above the text in both composers. > - People can check and remove images while they continue to edit the text. ## Linked Issues or Issue Description Refs: #13206. Related shared-composer work: #15091. **What existing behavior does this improve?** Image selection, paste, and drop in the new-task and thread composers. **Current behavior** Thread images enter the editor at the text cursor. New-task images can appear inline or with file attachments. Images do not have one preview size. **Proposed behavior** Show images above the text as 80 by 80 previews with rounded corners. Use the existing spacing and radius tokens. Keep file attachments in their current row. Add image references when the thread message is sent. **Reason and benefit** People can review images without moving or deleting message text. One shared image row keeps both composers consistent. **Breaking changes** New image uploads stay outside the editor until send. Old inline-image drafts remain readable. No server API or database changes are required. ## What Changed - Add `ComposerImageAttachments` for local previews, removal, upload status, and retry. - Let `TaskChatComposer` own the image row and all image input paths. Keep attachment IDs in the existing send flow. - Let `NewIssueDialog` stage images and upload retained files after task creation. Save file bytes in browser IndexedDB by account and company. Restore them after reload. Clear them after creation. Show storage errors. Merge saved file changes in one IndexedDB transaction. Delete only the files removed by that draft. This keeps files saved by other open tabs. - Keep rich editing for old image Markdown. Use the same MIME and filename checks for image previews in both composers. - Save optional MIME data with thread draft attachments. Existing draft records remain valid. - Add desktop and mobile Storybook examples. Update the task feature map and component tests. ## Verification - `pnpm exec playwright test --config tests/e2e/playwright.config.ts tests/e2e/board-attachment-receipts.spec.ts`: all 14 Chromium tests pass against the real local Board, API, storage, and disposable database. The suite proves image recovery in two open tabs after saves and task creation, new-task image recovery after reload, byte-for-byte upload content, cleanup after creation, rich editing of old image drafts, upload receipt recovery, and removal during pending uploads. - The first local browser attempt could not start because Chromium was absent. Chromium was installed. A later run passed 12 tests but the new legacy-draft fixture restored an empty body. That fixture wrote storage while an empty composer was mounted. It now seeds before React startup and uses a real uploaded image. The complete 13-test rerun passes. Early component runs also exposed the new restore timing. Submit and file controls now wait for restoration. The test helper now waits for React effects. - 316 focused tests pass across `TaskChatComposer`, `NewIssueDialog`, `MarkdownEditor`, `composer-draft`, and `useStagedIssueFiles`. The tests cover explicit file removal, file recovery, account and company changes, storage failures, MIME-empty images, upload retries, and removal. - The two-tab browser test failed on the previous commit: the second save erased the first image. The fix merges files in one read/write transaction and records explicit removals. The first fixed run reached the final create step but had no text request after the other tab cleared the shared text draft. The test now enters a fresh request before that step. The full 14-test rerun passes. - `pnpm check:token-gates`, `node scripts/check-maps.mjs`, `node scripts/storybook-catalog.mjs`, and `git diff --check` pass. - `pnpm --filter @paperclipai/ui typecheck` and `pnpm --filter @paperclipai/ui build` pass after building the local plugin SDK dependency. Repository typecheck and build stop because this workspace has no `cargo`. Full CI must pass before merge. The first CI run passed typecheck, build, and all unit-test shards. Its browser failure expected the old inline upload label. The assertion now uses the thumbnail upload status. - The prior browser review used the production components with simulated upload and submit calls. Desktop, mobile, and dark-theme captures were accepted before this PR. Browser checks confirmed equal-size rounded previews above the editor, no inline image nodes, no horizontal overflow, and removal that preserves text. These checks do not prove live backend persistence. - Earlier repository typecheck and build attempts also stopped without `cargo`. An earlier full test run was killed with a recorded out-of-memory event during a server integration shard. It had no full-suite verdict. One document-recovery test timed out during that concurrent run. Its isolated rerun and later complete focused runs passed; the initial timeout cause was not established. - An initial catalog command in this workspace ran before dependency installation finished. It could not load Storybook. The command passed after installation. The first UI typecheck could not find plugin SDK declarations while that package was still building. The UI typecheck passed after `pnpm --filter @paperclipai/plugin-sdk build`. To inspect the layout, open `composer-new-task--images`, `composer-new-task--mobile-images`, `composer-add-menu--images`, and `composer-add-menu--mobile-images` in Storybook. Select images with different aspect ratios. Check removal, mixed files, failed upload and retry, and draft restoration. - Greptile reports 5/5 for commit `9b9e93beeed80371f667ad2e1a9573e82332c05c`. There are no open review threads. [CI](https://github.com/paperclipai/paperclip/actions/runs/41544180330) passed on this commit. All 58 checks finished: 54 passed, one review is neutral, and three optional checks were skipped. The legacy Snyk status passed. Paperclip also reports 5/5. No review threads are open. ## Risks - Open tabs share the account and company draft. Atomic file writes keep changes from other tabs. A reload can restore those saved files. - Attachment state now controls when image references enter a thread message. Tests cover pending uploads, failures, retry, removed images, and retained upload IDs. - New-task images use the existing staged-file upload flow after task creation. A failed upload follows that flow's existing error behavior. Browser storage can be unavailable or full. The composer keeps the files in memory and shows a recovery message. - Legacy inline-image drafts retain their original text. No migration is required. ## Model Used OpenAI GPT-6 through Codex, with reasoning, tool use, and shell execution. The exact runtime snapshot ID and context-window size are not exposed in this session. The earlier implementation's model snapshot is not recorded in the handoff. ## 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 available in this session) - [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 references) - [x] My remote branch name describes the change and contains no internal Paperclip ticket ID - [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> |
||
|
|
58308a3e63 |
perf(apps): scope sidebar review counts to one connection (#18688)
## Thinking Path > - Paperclip helps people manage AI agents and their governed app access. > - The Apps sidebar displays a Review badge for one connection. > - It polls the full company attention service every 30 seconds to get two counts. > - That service also loads every profile, rule and active catalog entry. > - This pull request adds an authorized connection read for only those counts. > - The same badge now avoids unrelated profile evaluation and database result decoding. ## Linked Issues or Issue Description **Current behavior** The contextual sidebar polls company-wide attention. It needs only one connection's signed pending action count and whether any catalog entries are quarantined. **Proposed behavior** Both sidebar variants poll a connection-scoped count endpoint with existing connection read authority. The full attention API stays unchanged. **Reason and benefit** The retained 200-profile fixture performs seven service queries and returns 80,115 rows for this badge. The new reader performs one query and returns one row. This reduces local service CPU and avoids unnecessary decoded profile/rule data. Related merged evaluator fixes are already in the baseline: Refs #18673, Refs #18681. A search found no existing PR for this scoped count reader. ROADMAP.md contains no duplicate planned work. ## What Changed - Add the narrow shared DTO, typed client, guarded REST/OpenAPI route and catalog-owned reader. - Count independent aggregates with both company boundaries and exact signed-argument semantics. Keep archived counts at zero. - Update both contextual sidebar variants. Keep the exact badge, 30 second interval and existing attention-prefix invalidation. - Add PostgreSQL differential tests, authenticated HTTP tests, sidebar tests, a repeatable benchmark and access documentation. ## Verification - Baseline: `3f8ebfff8aa9febd0733c6f65b07485dcadfd0e2`, including both merged evaluator fixes. Service treatment: `0827f7d0b3`; route/fixture refinement: `230c42ee15`; final local existence gate: `390a218254`. - Passed: focused PostgreSQL differential test; assembled HTTP test with board session and agent JWT; 14 sidebar component tests; token gates; map checks; diff check. - Fixture: 200 profiles, 76,000 rules, 1,900 active tools, 695 removed references, 12 agents, a sibling connection and 2,000 unrelated historical invocations. Complete normalized two-count results are equal on both paths. - Quiet local measurement: seven alternating warm pairs after two warmup pairs, Node 24.22.2, macOS, real disposable PostgreSQL. Legacy/new service CPU median: 213.891/1.680 ms; ranges: 209.329–228.552/0.515–6.137 ms. Wall median: 156.867/1.248 ms; ranges: 151.739–162.289/1.115–1.386 ms. Queries: 7/1. Returned rows: 80,115/1. - Run `cd server && node --expose-gc --import ./node_modules/tsx/dist/loader.mjs scripts/benchmark-connection-review-counts.ts`. See `doc/connection-review-counts.md` for scope and failure history. Byte-volume accounting runs outside timing; no HTTP payload reduction is claimed. - Initial raw scalar SQL failed with ambiguous columns. Typed subqueries fixed it and passed real PostgreSQL equality. Initial fixture agents lacked permissions and correctly received 403. The final fixture grants explicit authority and tests revocation. An initial benchmark included byte serialization in timing; the reported run excludes it. - Passed required local `pnpm -r typecheck` and `pnpm build`. The initial sandbox typecheck could not open the tsx IPC socket; the escalated rerun passed. Full monolithic `pnpm test:run` was not run locally: repeating a 15–25 minute suite serially across both performance PRs adds no distinct evidence. Broad suite acceptance uses final-head CI, which runs the same general/serialized test partitions and the native Runner lane. Final-head CI is in progress. - Passed built-static Chromium journey on an owned local-trusted server and disposable PostgreSQL: Review 3 appears, only scoped counts are requested by this sidebar, resolving requests/clearing quarantines then reloading removes the badge, and archived counts are zero. The first ad hoc launcher omitted required decision-service options and failed at startup; using the normal no-op wake callback fixed that harness. - Greptile identified an invalid resolved-request fixture label. Corrected `denied` to the declared `rejected`, then reran the real PostgreSQL differential test. The count SQL and non-pending exclusion are unchanged. - The first final-head CI failed the static cross-tenant existence-oracle guard because the new explicit resource company assertion had no nearby `hasCompanyAccess` gate. Existing management admission already rejects foreign resources with 404. The route now also follows the standard local two-step gate. The unchanged guard plus authenticated HTTP negative cases passed (3 tests). No allowlist or test was weakened. - These local service measurements do not prove hosted performance. No deployment is included. ## Risks Low risk. New read admission reuses existing current-authority checks. The old attention API is unchanged. Counts still require database work over relevant pending/catalog rows. No cache, schema migration or telemetry is added. Roll back this PR if the badge differs or scoped reads deny previously permitted users. ## Model Used OpenAI `gpt-6.1-sol` (Sol 6.1), with reasoning, tool use and code execution. The host does not expose the configured context-window size. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] 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> |
||
|
|
554a770c6f |
perf(apps): scope connection profile configuration reads (#18687)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The Apps Permissions page reads saved access profiles for one connection. > - The page fetched every company profile, rule, and binding. > - It used only the app profile and eligible task-granted profiles for that connection. > - This pull request adds a saved configuration read owned by the profile service. > - The route keeps current connection and per-profile management checks. > - The benefit is fewer database rows, less Node work, and a smaller response for the same displayed configuration. ## Linked Issues or Issue Description **Subsystem affected** Server profile configuration reads and the Apps Permissions and Review data caller. **Problem or motivation** One connection page loaded and serialized unrelated company profiles. In the local fixture, this produced a 32.35 MB response with 76,001 rule rows. **Proposed solution** Select the displayed connection's app profile and exact eligible connection-intent profiles before loading their entries and bindings. Return an explicit configuration DTO with complete selected arrays. Keep summary and pending-review work on the existing full API. **Alternatives considered** Filtering the full response in the browser retains the database and Node cost. Truncating the full API would break other clients. Filtering entries to the connection would lose selectors and bindings needed by saves. **Roadmap alignment** This improves the existing governed Apps capability. It does not add a new access policy. Related merged work: #18673 and #18681. Related harness cleanup: #18683. Public PR searches found no duplicate connection configuration projection. ## What Changed - Add `ToolProfileConfiguration` and `GET /api/tool-connections/{connectionId}/profile-configuration`. - Select `app:<connectionId>` at any status and exact active, correctly bound `connection_intent` profiles. Run the existing per-profile visibility filter before configuration queries. - Preserve complete ordered entries and bindings. Keep all save behavior, empty-binding install fallback, and the existing full profile API. - Switch AppDetail and AgentConnectionAccess to the configuration DTO. Use a distinct cache key below the existing profiles prefix so mutation and reconnect invalidations still refresh it. - Add real PostgreSQL differential and authenticated HTTP tests, UI caller coverage, a reproducible benchmark, and access-map documentation. ## Verification Baseline: `3f8ebfff8aa9febd0733c6f65b07485dcadfd0e2`, after both #18673 and #18681. Final head: `b40c1ed7c0833d403e20ee8a5ff9d09f1bad6d22`. Current implementation and reproduction details are in [the performance note](https://github.com/paperclipai/paperclip/blob/b40c1ed7c0833d403e20ee8a5ff9d09f1bad6d22/doc/performance/2026-11-02-connection-profile-configuration.md). - AppDetail: 79 tests passed. Existing access/action saves, install fallback, grant removal, errors, and refresh cases use the new caller. - Real PostgreSQL differential: passed. Full ordered selected configuration equals the old full-list selection. Cases cover extra bindings, sibling selectors, wrong source/key/status/binding, null and non-string agent metadata, fresh mutations, empty app bindings, visibility filtering, and company scope. - Production HTTP authentication: API key and run JWT cases passed. Hidden personal accounts omit spanning profiles. Private connection reads fail. Restored ownership restores visibility. Revoked management grants deny fresh calls. Final UID canonicalization and foreign-company 404 assertions passed on the current head. - Map structural check, token gate, and `git diff --check`: passed. - Required local `pnpm -r typecheck` and `pnpm build`: passed on the current head. `pnpm test:run` was started once. Its first chat shard passed (337 tests, 151.87 seconds); the second shard was intentionally interrupted after the complete final-head CI suite passed. This partial local attempt is not a full local test pass. The same stable-runner general and serialized partitions and Runner lanes passed in [final-head CI](https://github.com/paperclipai/paperclip/actions/runs/41538805231), including aggregate `ci / verify`. No local assertion failures were observed before interruption. - Final-head focused acceptance: four files, 85 tests passed. Full token gates, maps, and module boundaries passed. - Actual browser acceptance passed on the current checkout with isolated real PostgreSQL and a local trusted board. An action saved as Off persisted after reload. Both app agent bindings stayed intact. Removing an agent-only task grant persisted after reload. Requests used only the narrow profile endpoint. No browser exceptions occurred. No responses were mocked. No provider calls or hosted changes were made. The helper stopped the owned runtime and database after the check. - Final exact-head checks: 54 success, one clean neutral Paperclip Review, three skipped, zero pending or failures. Legacy Snyk status: success. No inline review comments. - Greptile reviewed exact head `b40c1ed7c0833d403e20ee8a5ff9d09f1bad6d22`: 5/5, no findings, completed successful check. Five alternating unprofiled pairs ran with real PostgreSQL on macOS/arm64, Node v24.22.2, and forced GC. The fixture has 210 profiles (200 heavy profiles plus ten eligibility cases), 76,001 rules, 1,900 active tools, 695 removed tools, and 12 agents. The selected configuration has two profiles and 1,391 rules. Each pair asserts complete ordered selected DTO equality. | Measurement | Full list | Configuration read | | --- | --- | --- | | Service wall ms, median [min, max] | 200.927 [193.319, 213.390] | 6.414 [5.508, 6.973] | | Node CPU ms, median [min, max] | 262.751 [246.727, 271.573] | 27.525 [22.576, 29.308] | | Select queries / returned rows | 7 / 78,139 | 3 / 1,397 | | Actual response JSON bytes | 32,353,534 | 592,233 | | Serialization wall ms, median [min, max] | 90.714 [88.715, 99.304] | 1.644 [1.637, 1.745] | | Serialization CPU ms, median [min, max] | 90.644 [88.569, 96.778] | 1.654 [1.637, 1.807] | Reproduce: `node --expose-gc --import ./server/node_modules/tsx/dist/loader.mjs server/scripts/benchmark-connection-profile-configuration.ts 5`. The benchmark measures the service and actual response JSON separately. It excludes HTTP and authorization work through an identity visibility callback. Node CPU does not include PostgreSQL CPU. No hosted or foreground-under-load improvement is claimed. Preserved failures: offline install lacked a locked tarball; frozen online install passed. Sandbox localhost and tsx IPC restrictions blocked initial DB/typecheck attempts; permitted retries use the same checks. The first HTTP suite needed the unbuilt plugin SDK; its owning build helper fixed setup. Shared typecheck caught a missing barrel export, now fixed. A broad typecheck inherited the host's unpinned nested pnpm executable; the owned stalled process was stopped and restarted with pinned pnpm 9. The complete current-head CI suite and aggregate verify passed. The separate Paperclip agent review published 5/5 with no findings at this head and completed with a clean neutral conclusion. An added foreign-company assertion expected 403; the existing guard correctly returned 404. Only the test expectation changed. The first real browser attempt saved and reloaded the action correctly, but grant deletion returned 422: the stress fixture had a company binding, which makes that profile the company default. The UI showed the existing deletion error. The second browser seed used the production agent-only intent shape and passed removal and reload. This does not change the stress fixture or product deletion gates. Initial external browser script attempts also needed an ESM extension and the correct dependency path. Logs, first-failure screenshots, traces, and result files are retained in the local evidence directory. ## Risks - SQL selection must stay aligned with connection-intent eligibility. Differential fixtures cover the exact current predicate. - A selected connection can still have many rules. This change preserves all selected configuration. - Per-profile authorization still reads current selected resources and can add work. Connection visibility does not bypass that check. - No migration, default-allow, effective-access, policy-review, provider, or deployment behavior changes. The old endpoint remains available. Rollback restores the old AppDetail caller and removes the additive endpoint. ## Model Used OpenAI Codex, `gpt-6.1-sol`, with code execution and repository tools. The host does not expose the context-window size. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
946735d03a |
Persist task sorting in URLs and show newest routine tasks first
Save task sort choices in URLs across task views. Open routine tasks by creation time, newest first, with stable sorting before pagination. Co-Authored-By: Paperclip <Paperclip-Paperclip@users.noreply.github.com> |
||
|
|
40b8075916 |
feat(ui): show scheduled task waits as Monitoring (#18624)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task indicators tell an operator whether work is active, waiting, or
complete.
> - An agent can yield until a saved monitor checks CI or another
external result.
> - The task currently keeps the In Progress icon between those runs.
> - Changing the stored status would affect monitor admission and
recovery.
> - This pull request adds a read-only Monitoring display state with a
blue clock.
> - Operators can see and filter scheduled waits while execution keeps
its existing rules.
## Linked Issues or Issue Description
**What existing behavior does this improve?**
Task status indicators, task collection filters, board columns, and
search facets.
**Current behavior**
A task that waits for a scheduled monitor shows the same In Progress
icon as active work.
**Proposed behavior**
Show Monitoring with a static blue clock when an agent-owned task has a
saved ordinary monitor and no active run, execution lock, review
participant, or active recovery action. Return to the normal task
indicator when the check starts. Preserve review, blocked, terminal, and
quota-recovery states.
**Reason and benefit**
Operators can distinguish scheduled waits from current agent work
without reading the task history.
**Breaking changes**
None to stored task statuses or execution rules. Task reads gain
optional displayStatus. Collections and search gain a separate read
filter. Existing status filters keep their lifecycle meaning.
Related historical work: #4396 covered a monitoring label exemption.
This change uses the saved monitor and a read projection.
## What Changed
- Add one SQL projection for task detail, compact lists, summaries,
relations, search results, and display-status counts.
- Show the blue clock in shared task icons and chips, task detail and
breadcrumbs, properties, references, list rows, recent navigation, and
agent task cards.
- Add Monitoring to task filtering, grouping, sorting, board columns,
and search facets. Prevent a drag from creating this derived state.
- Keep stored lifecycle statuses, monitor scheduling, checkout,
recovery, permissions, and agent status filters unchanged.
- Add database and UI regression coverage, full-page Storybook examples,
and product and access-map documentation.
## Verification
- Passed `pnpm -r typecheck`.
- Passed `pnpm build`.
- Passed `pnpm check:token-gates` and the map/catalog structural checks.
- Ran the new database suite on a disposable PostgreSQL 17 database. It
covers read surfaces, filter pagination/counts, queued/running checks,
rescheduling, completion, retained monitors, review, and recovery holds.
- Ran existing search, list, board, sidebar, task status, and filter
tests. Corrected board queries use displayStatus and eight columns.
- The full local `pnpm test:run` stopped in a chat integration shard: 12
failures (four timeouts and eight FIFO publication assertions). That run
spanned a rebase. A focused rerun on the current source passed all 21
selected cases without assertion or timeout changes. The original cause
is not established; this does not claim the full local suite passed.
Final-head required CI passed (ci / verify and ci / e2e, run
41488267209).
- Passed 82 tests for task API summaries, recovery precedence, search,
and optimistic updates; 54 tests for status cards, database reads, and
board moves; and 27 tests for blocker relations and recent-task cache
updates. One intermediate database setup hit its 20-second hook timeout;
the serial rerun passed.
- Greptile is 5/5 on
|
||
|
|
d38cdf261a |
perf(ui): speed up Tasks and Inbox startup (#18492)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Tasks and Inbox are the main entry points for that work. > - Earlier changes made their data reads and row counts smaller. > - Those changes remain, but shared controls now pull in the whole task-detail bundle. > - A cold open can also read a remembered organization before selecting the one in the URL. > - This pull request separates collection code and selects the addressed organization first. > - It warms task code after collection paint, so the next task open stays fast. ## Linked Issues or Issue Description Refs #17756, #18323, #16849, #17041, #17983, #17960, #18461. **What happened?** Tasks and Inbox still use their optimized index reads and row budgets. However, small shared controls and hooks were placed in the task-detail chunk. A collection had to download that whole chunk. The HTML also preloaded it on every route. The original production profile loaded about 6.5 MB of decoded JavaScript before useful rows, or 1.9 MB transferred with compression. Company bootstrap could select a different remembered organization before Layout selected the URL's organization. This started unnecessary company reads. A retained multi-company browser fixture reproduced two attention-count requests for different companies. **Expected behavior** Show correctly scoped, stable collection rows without waiting for task-detail code. Keep compact reads, bounded rendering, direct task preloading, immediate New Task input, and fast follow-on navigation. **Steps to reproduce** 1. Use a production UI build with Coordinator enabled and two active organizations. 2. Remember one organization, then cold-open Tasks or Mine in the other. 3. Inspect startup script and company requests before the first useful row. The baseline UI revision is `91fdf02e95`. This is a UI change. It has no API, schema, migration, or authorization changes. ## What Changed - Group the static collection dependency trees above the task-detail group. Keep the existing startup and task grouping strategy. - Preload task detail and its static dependency closure early on direct task and agent-chat URLs. Keep collection aliases out of that preload. - Fetch the immutable task chunk at low priority after a collection paints, or on a same-origin task-link hint. After a successful immutable response is fully read, module-preload the cached chunk so it can compile without executing. A failed HTTP probe skips module preload. - Prefer an addressed active organization during bootstrap. Preserve manual selection, archived-company handling, and account-scoped company lists. - Preserve a task reading anchor when a programmatic scroll event reports an unchanged offset during restore reflow. Strengthen the Back journey to wait for a completed collection navigation. - Add production-browser checks for delayed indexes, correct company scope, stable row geometry, failed speculation, and early direct-task preload. Update collection verification notes and the feature map. ## Verification Final source: `e402ab7fc6`; baseline UI: `91fdf02e95`. - All **234 focused unit cases** and **44 production-browser journeys** passed on the final source: 33 task journeys and 11 collection journeys. Coverage includes compact history, saved cards, draft persistence, avatar continuity, failed-probe recovery, delayed data, pagination, deep links, desktop/mobile and reading-position restoration through Back. Desktop and mobile screenshots were inspected. - Workspace typecheck, full production build, map checks, token gates and diff checks passed. The default local `pnpm test:run` still stops before executing tests because the existing chat-test line selector reports `No test found` (1,816 skipped). This is not a passed full local test suite. Focused tests and remote CI remain separate evidence. - Greptile reviewed the exact final commit at **5/5**, with zero open review threads. Final code CI passed. The complete check inventory is **55 successful, 3 skipped, 1 neutral**. The neutral result is the separate Paperclip Review: its agent finished without completing an assessment, so it is not a passing review score. Five alternating baseline/candidate pairs per scenario, Chromium 151.0.7922.34, 1440×900, 4× CPU, 50ms latency, approximately 9Mbps down / 1.5Mbps up. Cold cases use fresh browser contexts with normal cache writes enabled; warm cases use the same context and normal application query cache. Both previews use the server's immutable hashed-asset cache policy and uncached HTML, with real local feature settings and no request interception. All task-owned builds and suites were stopped during timing; other host activity was uncontrolled. Readiness requires useful rows and editable search, or the readable task thread and editable composer, followed by two animation frames. | Journey | Baseline median (range) | PR median (range) | Median paired saving | | --- | --- | --- | --- | | Cold Tasks | 3239 ms (3189–3333) | 2545 ms (2441–2682) | +752 ms | | Cold Inbox | 3207 ms (3203–3268) | 2679 ms (2502–3062) | +541 ms | | Warm Inbox | 717 ms (701–917) | 760 ms (745–768) | -47 ms | | Warm Tasks | 1150 ms (1126–1207) | 1136 ms (1119–1174) | +18 ms | | First task click | 943 ms (932–1008) | 1007 ms (976–1098) | -74 ms | | Back to Tasks | 584 ms (568–617) | 566 ms (559–575) | +10 ms | | Cold direct task control | 3389 ms (3377–3402) | 3415 ms (3395–3896) | -13 ms | All five pairs improved for each cold collection. The signed saving is baseline minus candidate for each pair; it is distinct from the difference of medians. Warm navigation is broadly similar. First task click was 74ms slower by median paired difference. Direct-task median paired difference was 13ms slower, with one slower 3.90s candidate sample retained in the range; this is not a claimed direct-task speedup. Completed script transfers by collection readiness fell from about **1.91MB to 1.14MB** (Tasks), and **1.90MB to 1.14MB** (Inbox). Task code warms after rows paint. At the test bandwidth, the removed 0.77MB critical transfer represents roughly 0.65s of download time; CPU and network overlap, so their savings are not added. Unthrottled loopback API control medians stayed about 17–18ms in both variants. All 30 cold samples had zero browser errors. Rejected experiments remain separate: automatic splitting produced over 200 startup requests; disabling recursive grouping slowed direct tasks; HTTP-only warming improved collection startup but slowed first task opens. The final correction preloads direct dependencies and compiles successfully cached code after paint. Routing disables HTTP caching, so intercepted runs were kept as diagnostic evidence rather than used for warm-cache acceptance; see [Playwright's cache behavior](https://playwright.dev/docs/api/class-page#page-route). Vite preview's default asset `no-cache` policy was also corrected to match the shipped server before final measurement. ## Risks - Bundle placement affects shared consumers. Browser checks cover collections and task navigation; the full PR checks also cover other routes. - Code warming still transfers the task chunk if the user stays on a populated collection. It moves that download past first paint and does not execute it. This is a startup latency improvement, not a claim that all eventual bytes disappear. - A direct click before warming finishes still loads code on demand. Direct task and chat URLs retain early module preload. - Local browser evidence does not establish a deployed staging speedup. This PR does not merge or deploy itself. ## Model Used OpenAI GPT-6 (Codex), with reasoning, tool use and local code execution. The context-window size is not exposed in this environment. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run the relevant tests locally and they pass (234 unit cases and 44 browser journeys; the full-command limitation is documented above) - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All code CI gates are green (the separate Paperclip Review is neutral because its agent did not complete an assessment) - [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> |
||
|
|
f2db909393 |
fix(ui): retain startup autosave through session recovery (#18412)
Reviewed and verified at
|
||
|
|
322fa6b65c |
fix(ui): restore task document authoring and add persistence journey (#18356)
## Thinking Path > - Paperclip helps people manage AI agents and their work. > - Task documents keep versioned work beside each conversation. > - The default chat interface could read general documents but hid their editor. > - People also need unfinished edits to survive a tab switch or reload. > - This pull request restores the shared editor in Artifacts. > - A portable browser journey checks exact saved content and revision history. > - The benefit is a usable document flow with independent deployment checks. ## Linked Issues or Issue Description **What happened?** A person using the default task interface could read a general task document but could not create or edit one. The existing editor was available in Classic mode. A pending create could also leave newer text as a new form after its editor unmounted, causing a conflict against the person's own successful creation. **Expected behavior** A person can create and edit general documents through Artifacts. Titles, bodies and revision history persist after reopening and reloading the task. Unfinished text survives tab switches. A successful create makes retained newer text an edit of that confirmed revision. Later writes from another actor still cause a conflict. **Steps to reproduce** 1. Open an ordinary task in the default chat interface, then open Artifacts. 2. Try to create a general document. The previous interface has no authoring control. 3. With authoring restored, submit a new document, keep typing, and switch to Properties before the request finishes. 4. Reopen Artifacts. The previous draft path restores a new form despite the successful create. Related public work: #17598 adds document copy/download and #18157 adds image galleries. The selected actual merged parent is `f1d780838218f975064f38333946805e0ec103a5` from #18427. It includes the stable profile-entry ordering repair and the exact recovery-fixture prerequisite. The resulting PR diff contains 32 document and reporting files. ## What Changed - Reuse `IssueDocumentsSection` for general documents in default-chat Artifacts. Keep Classic authoring in its existing task body. Ordinary tasks, conversations and Coordinator mode share the same editor options and signed-in permission wrapper. - Preserve Plans, file-review documents, attachments, uploads and work products. Hide duplicate general-document cards. Use the same general-document key rules for visible rows, validation and refused writes. - Forward image uploads, mentions, references, author maps and feedback to both editor mounts. Keep empty mention/project values stable while queries load. - Back up unfinished forms within their signed-in account, task and editor scope. Preserve text entered before its key. Record a successful create on its matching retained newer buffer, including after unmount or an early reopen. Preserve newer title/body edits, real remote conflicts and matching cancellation cleanup. - Add the model-free `task-document-persistence` journey. Setup creates only an owned empty backlog task. The browser creates and edits the document; normal APIs independently check company, task, actor, exact content and both revision records. - Reopen the owned task through the explicit Backlog view, then reload it. Require exact UI readback and zero native runs. Add only the Doc registration, definition-hash inputs, report mapping and four closed checks to the shared harness. - Count explicit zero-run browser receipts after private journey metadata is removed for publication. Preserve missing billing evidence, positive usage and native/protocol accounting. - Update browser assertions for the restored inline editor while retaining exact download bytes, revision collisions, paused-state and no-run checks. Update the feature map, usage docs and shared editor stories. ## Verification - Latest focused checks use official Node 24.22.2: 568 journey, catalog, report, billing and attempt-accounting tests across 25 suites pass. All four admitted journeys remain registered. The seven relevant UI suites pass 529 tests, including the task-page container after the parent merge. Maps, token gates, the PR-scope diff check and the owned credential-pattern scan pass. The normal QA import preflight also passes with an empty environment and network access blocked. - Billing regression: before the repair, the explicit empty public receipt counted one run, and two positive-usage receipts were discarded by browser metadata. Those three cases fail before and pass after the repair. Two additional red regressions cover aggregate usage beside an empty run list. That ambiguous shape now keeps an unavailable receipt and a minimum count of one. Missing receipts retain unavailable billing, and native/protocol one-or-more run totals retain their measurements. - The previous fresh CI run failed its unchanged snapshot-only recovery fixture: one global sweep did not call its callback. The original failure remains recorded. An isolated PGlite probe with all canonical migrations exercises the real reconciler: it processes two earlier sources, then reaches the owned third source on the next sweep. It preserves source evidence, files and run IDs. This proves bounded pagination, not full native snapshot repair. - Local native recovery tests could not start PostgreSQL because the host semaphore limit was reached. That run executed zero cases. Canonical Linux CI later passed all 143 fixture cases, including the original snapshot-only case and the new competing-candidate control. The exact fixture repair is now inherited from #18427 and is absent from this PR diff. - The portable oracle rejects 19 stale, missing, foreign or incorrect outcomes. Result validation also rejects model/provider metadata and native runs for this case. - Five real Artifacts-to-Properties unmount regressions fail before the repair and pass after it. They cover both editor modes, reopening before and after completion, later typing, and a foreign revision that must still conflict. The edit-storage failure case also checks that Cancel clears the promoted fallback copy. - UI coverage includes default chat, Classic, conversations, Coordinator, Plan rendering, document-card deduplication, reserved keys, pending-query stability, permissions and rich editor options. - Earlier real browser checks passed five upload cases and two artifact-arrival cases. They retain exact CSV bytes, original/revised content, collision, paused-state and no-run assertions. Current-head normal CI runs the updated browser suites again. - The branch merges only the selected actual parent `f1d780838218f975064f38333946805e0ec103a5`. The merge has no conflicts or manual resolution. The SQL service and recovery fixture match that parent exactly. The own document editor, persistence flow, saved-state oracle and billing repair retain their previously qualified source blobs. Follow-up, clarification, question/resumption, screenshot helpers and the Steering map are byte-identical to the merged parent. Existing project/search/question/follow-up registrations remain present. - Required document source blobs remain exact: Doc UI `22e80663b053363e5f75e1432dd9043dc0e70243`, its unmount tests `16f3f4ed0dc9b11aaff129e06e6cf2bbf4522713`, readiness helper `800a747284db19b8484650b6759e8bd1f356839d`, and budget service `3a15d489f0aa55c22e8f7fe6a6bc6a0e14e5914e`. - Local typing is limited by borrowed declarations from another checkout. They omit current `skill_test` and sandbox creation-operation fields. No dependency declarations or repository config were changed. The authoritative clean CI Typecheck + Release Registry gate passes on exact head `2ffce29827ae170420d740940c1c069c7225a74c`. - Full monorepo typecheck, tests and build were not run locally. Borrowed build declarations from another checkout limit local typing. Authoritative [clean CI](https://github.com/paperclipai/paperclip/actions/runs/41171717008) passes on exact head `82d15946c5844d3ae41c6ade62fa224053f20a9a`: 55 successful checks, 3 skipped and 1 neutral, with zero pending or failed checks. Typecheck, build, Runner, server and browser lanes pass. Greptile gives that same head a fresh 5/5. All 15 review threads are resolved, with no further thread page. The PR is mergeable and clean. - Failure history remains recorded. The earlier recovery failure was repaired with a bounded, owned-source fixture. A later CI worker shut down after 2,375 Runner unit tests passed. Its one authorized narrow retry passed those tests and all five native integration suites. The separate AgentConfig browser failure was reproduced and fixed by the merged #18427 parent. These earlier passes do not replace current-head CI. - Final-source live qualification passed on exact harness and served application `82d15946c5844d3ae41c6ade62fa224053f20a9a`. QA run `41177696858` completed all four closed checks and all five phases with zero native runs. Cleanup passed; the durable manifest is complete with no pending evidence. The coordinator verified the original grade and manifest. - The [public qualification report](https://pages.paperclip.ing/evals-qa-smoke-41177696858-1/) records zero agent runs, empty run IDs and empty run usage. Pricing remains unavailable and billing remains incomplete; the report does not claim measured zero cost. - The earlier harness `36c8d9ddd76d0b7ddb28a9a6c674d9e538f6df88` pass against application `2ffce29827ae170420d740940c1c069c7225a74c` remains historical evidence. It is separate from the final-source measurement above. - The selected parent brings profile-entry ordering, proactive chat, a database migration, Runner updates, and task-page chat/read behavior. Its new task-page container is included in the final application measurement. The coordinator retains the original evidence and owns the primary merge and daily-plan admission. ## Risks Artifacts now mounts the existing shared editor. Its autosave, conflict, revision, annotation and server access contracts remain in place. Tests cover both interface modes, shared scopes, later remote writes and unavailable edit storage. Plans and generated file-review documents keep their existing flows. The PR adds no database schema or API change. The shared billing repair requires explicit captured empty run IDs and an unambiguous usage object containing only an empty run list for public browser-only receipts. Other fields beside an empty list keep conservative unavailable billing. Missing measurements remain unavailable. Contradicting positive usage remains counted. The inherited recovery fixture keeps the production sweep limit and its source, readback and no-agent-work assertions. The live journey must fail when authoring controls or saved outcomes are absent. It must not create the expected document through setup APIs or switch to another interface to pass. Final deployment verification must retain the actual app and harness revisions separately. ## Model Used OpenAI Codex, based on GPT-6, with tool use and code execution. The exact runtime 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> |
||
|
|
0e15c92073 |
feat(skills): make managed content independent of web-server disk (#18334)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agents use installed skills and exact version pins during execution. > - Managed skills still depended on mutable directories on the web server. > - A replacement server could lose acknowledged edits or remove an unassigned skill whose directory was absent. > - This pull request makes immutable versions the authority for managed content and installed repository reads. > - The server can rebuild delivery files from durable content after replacement. > - This establishes skills readiness for ephemeral web servers. General server draining and workspace recovery remain separate work. ## Linked Issues or Issue Description **Subsystem affected** Skills services, shared contracts, database receipts, Skill Studio, and runtime delivery. **Problem or motivation** A fresh web server must discover, read, edit, and deliver protected installed skills using the same database, object storage, secrets, and supported application artifacts. It must not need its predecessor's files or process memory. **Proposed solution** Use `managed` ownership with a null source locator. Read installed content by immutable version. Prepare packages before a short publication transaction. Persist execution selections before materialization. Recover exact pinned runtime assets and reject deletion while active or recovering pins exist. **Alternatives considered** Reconstructing a mutable installed directory preserves the old source-of-truth ambiguity. Permanent dual writes create two competing authorities. This change uses one managed model after a bounded legacy conversion. **Roadmap alignment** This improves the existing Skills Manager, Studio, version history, and Cloud execution capabilities. The maintainer supplied the implementation contract. This does not add a separate skills product or deploy fleet changes. Related work: #18082 supplies immutable package storage. #17273 addresses edits outside the API for linked local skills; this PR keeps that source category separate. #2648 is a closed earlier ephemeral-filesystem proposal. ## What Changed - Add managed ownership and focused content publication and execution materialization modules. Keep the archive format and package storage tables. - Publish managed create, save, delete, fork, rename, restore, and catalog content with version checks. Add durable create receipts. Preserve file-save receipt responses. - Return file version identities. Keep Studio drafts after a conflict and provide an explicit reload action. A delayed reload cannot overwrite newer typing or navigation. - Persist exact runtime selections, including empty selections. Rebuild pinned assets and verify their admitted digests on a replacement server. - Preserve source access on forks and disconnected copies. Keep the existing workspace policy category for managed skills. - Add bounded conversion, eligibility, and independent verification phases. Load persisted Cloud configuration in the standalone CLI without seeding or changing it. Reject partial current versions against installed inventories; recover only complete saved content or the exact source. Document storage migration blockers and the compatible rollback floor. - Add separate-process PostgreSQL/S3 qualification and update domain, retention, policy, and UI regressions. - Pass the plugin worker manager into Studio execution, admit restricted `skill_test` mode through native Runner contracts, and preserve admitted scope across native and REST tools. Native tests cannot create ordinary tasks, browse company data, or use external tools. - Select the exact durable Studio revision even when unassigned or Beta skills is off. Persist Studio output and audit atomically with native task completion, preserving the result on replay. ## Verification - Final revision `13e8af480b88ba6fea5737bac4bd81104d604792` passed full CI: all 49 workflow jobs completed successfully ([run 41127396098](https://github.com/paperclipai/paperclip/actions/runs/41127396098)). This includes typecheck, test suites, Runner checks, browser checks and build. Greptile review 15 is 5/5 on that same revision, with zero unresolved threads. The PR is ready for review. - Local workspace typecheck and build passed after integrating master. Focused checks passed: 33 execution/completion cases, 52 Runner HTTP cases, 16 managed-content cases, 17 Studio cases, the new real-process CLI regression, map checks and UI token gates. The CLI regression proves inspection does not seed missing Cloud configuration. Server typecheck passed after that fix. - The independent-process PostgreSQL/S3 matrix passed through normal HTTP skill routes. It covers A → B → C replacement, lost commit responses, upload crashes, concurrent saves, binary contents and executable delivery. Metadata listing and warm selected delivery retain zero object downloads. Local timing measurements are recorded; they do not establish hosted latency. - Hosted A → B → C passed on the owned disposable test tenant with external Postgres, S3 and a real remote Paperclip Computer. Predecessor temporary homes were absent. C read and executed B's acknowledged managed save. New runs used repository v1 while v2 was installed. Hashes matched an independently checked exact upstream commit. - Compatible image rollback to `6518b323` passed. Studio retained the unassigned fork's C save. A fresh remote run executed the newer managed content and historical repository pin. The actual shell event confirmed expected hashes, stdout, exit 0 and mode 0555. - Runtime candidate `9200e3fcb4` deployed successfully ([Cloud run 41124147876](https://github.com/paperclipai/paperclip-cloud/actions/runs/41124147876)). The final Studio test delivered only the unassigned fork's exact v3, executed its script and persisted a successful output snapshot. Independent command-event inspection confirmed all three hashes, stdout, exit 0 and mode 0555. All 14 installations were version-backed. Independent verification checked all 25 versions: 23 remote objects, two bundled database snapshots, zero blockers. - The deployed image is `9200e3fcb4`. Later master integration, the client-only delayed-reload draft guard and the CLI bootstrap have separate automated proof. The CLI bootstrap was also exercised against the tenant's stored configuration and storage through the same read-only services. This PR does not claim that the deployed image is the final PR revision. - Live Studio checks exposed worker wiring, admission, access scope, exact selection and completion-publication gaps. They are fixed. Failed attempts remain in the evidence. The full local suite exceeded 80 minutes under host contention and was stopped. Later combined/isolated local attempts also timed out; they are not counted as passes. Full CI covers the integrated suites. Earlier CI found an obsolete restart-scope fixture, which was corrected and passed all 52 HTTP cases. - Reproduction and migration: [`doc/skill-ephemeral-web-servers.md`](doc/skill-ephemeral-web-servers.md). Source revisions, deployments, versions, run IDs, hashes and failure history: [`doc/plans/2026-10-30-ephemeral-web-skills.md`](doc/plans/2026-10-30-ephemeral-web-skills.md). ## Risks - Legacy conversion requires stopped admission and retired filesystem-authoritative writers. Pre-conversion binaries are not supported rollback targets afterward. - Cloud readiness requires remote object storage. Local provider receipts and provider mismatches remain blockers until objects are copied and verified. - Linked local sources retain filesystem semantics and are outside the cloud guarantee. - Cold reads still fetch the existing archive format. Warm runtime preparation retains the verified-cache path. - Bundled reconciliation preserves an installed head. Existing release snapshots remain selectable. An older server must not replace a newer head with its shipped files. - No production volumes, fleet defaults, or general deployment coordination change in this PR. ## Model Used OpenAI Codex, GPT-6 family, with reasoning, repository tools, code execution, and browser use. The exact backend model ID and context-window size are not exposed in this session. No subagents were used. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
f53db0c70f |
perf(server): overlap OpenCode setup and trace reply recovery (#18367)
Overlap eligible OpenCode GitHub and assigned MCP preparation. Trace deferred reply discovery and recovery, and forward the native GitHub transport recorder. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
6dcf4160dd |
perf(chat): load recent messages and page history on scroll (#18358)
## Thinking Path > - Paperclip lets people manage work done by agents. > - A standing agent chat can hold months of conversation. > - The chat route forced full-history mode, bypassing compact task loading. > - A cold visit fetched lifetime run summaries and hydrated historical transcripts. > - This PR starts with 20 recent messages and loads earlier pages on upward scroll. > - It preserves the reader's position, current questions, and draft while history grows. ## Linked Issues or Issue Description **What happened?** Standing agent chats forced full-history loading. A long conversation fetched full activity and run history before it became readable. Earlier comments also used an explicit load control. **Expected behavior** Open a small recent conversation quickly. Load older messages when the reader scrolls upward. Show an inline loading state. Keep the visible message and composer mounted through paging, live updates, and Back navigation. **Steps to reproduce** 1. Open a standing agent chat with hundreds of messages and completed runs. 2. Use a fresh browser query cache. 3. Observe full activity and run reads plus transcript requests for historical runs. 4. Compare the recent window and upward paging after this change. Related work: #18312 and #18323 restored compact task and collection loading. #14848 added reopening of visited agent chats. A GitHub search found no open PR for this chat-history optimization. ## What Changed - Return 20 contiguous recent comments for standing chats, with a stable oldest cursor. Keep the existing compact task exchange contract. Use the existing company/issue/time index for cursor reads. - Keep chats compact even if their task view previously expanded history. Retain observed messages through live catch-up and cache-backed return visits. - Keep fetched history pages, acknowledged sends, and the observed recent cursor separate. Reconcile live replies without losing history after a send or deleted cursor. - Hydrate metadata only for newly revealed message/run IDs; preserve prior batches while paging. Slow-send recovery refreshes the recent window. Receipts failures have an independent retry. - Hydrate run summaries only for loaded messages and the latest turn. Validate batches of at most 100 run IDs and keep the existing issue/company access rules. - Reuse hydrated terminal native streams when only history membership changes. Preserve retry, resume, mode changes, reconnect recovery, and interrupted recovery reads. - Load older messages, decision receipts, and task handoffs through upward scrolling. Support wheel, touch, and keyboard input. Keep pending questions visible. - Reserve a status slot while loading. Preserve a logical message anchor and the mounted composer. Pause failed page reads until an inline Retry. - Add database, route, controller, and scroll regressions, plus an opt-in production-build browser rig for long chats on desktop and mobile. Update design and feature/access documentation. ## Verification - The real PostgreSQL cold-open suite passes all 12 tests, including contiguous pages with equal timestamps, complete history, company denial, and scoped run IDs. - Activity route and OpenAPI suites pass 53 tests. The route run allowed local cold-import overhead; CI retains the repository's normal timeouts. - Three new paging regressions fail against the unchanged source. The candidate's focused paging/window suite passes 26 tests. Broader UI verification is recorded below when complete. - Desktop and mobile browser acceptance covers recent-only startup, per-frame reveal geometry, delayed and failed older pages, stable reading anchors and drafts, Back, older comment links, and one persisted live reply. - Full workspace typecheck and build passed locally. The final UI source also passes its typecheck and production build. - Affected UI suites pass: 212 controller/history/paging tests, 352 thread/scroller tests, 26 native-stream tests, plus metadata batching and live-cache hydration coverage. The issue mutation/access route suite passes 179 tests. - All 22 final desktop/mobile browser journeys pass, including delayed image growth. The isolated second-page request proof also passes six repeated desktop/mobile runs. A separate 6,000-message, 3,000-run fixture passes cold-open and delayed-paging checks on both screen sizes, still opening 20 messages and loading one 50-message page. - Final matched production timings use baseline `aa58fa1073` (`index-BaRiMbxd.js`) and candidate UI source `f9a26b9783` (`index-DPWTbsFF.js`, identical application source at final head `bf71ffd5af`). Chromium 151.0.7922.34, 1440×900, 4× CPU throttle, no added network latency, browser HTTP cache disabled, fresh application cache for each cold visit. Both variants block service workers and use the same warm local API server and immutable 600-message/300-run fixture. Only document HTML is intercepted for both variants; API requests are real. The common API revision is `109981f8c1`; subsequent commits change only UI and tests. | Usable conversation | Baseline median (range) | Candidate median (range) | | --- | --- | --- | | Cold direct URL | 6.57 s (5.69–7.45) | 3.07 s (2.50–3.28) | | Warm in-app return | 3.76 s (3.54–4.76) | 0.67 s (0.58–1.46) | | Back return | 2.53 s (2.12–4.20) | 0.51 s (0.47–1.18) | Five pairs alternate order. Every paired difference favors the candidate for all three journeys. Readiness requires a revealed, fully visible latest reply above the composer and an editable composer. Return timing starts after the Tasks route renders. Cold API requests fall from 953–954 to 71; API wire bytes fall from 517–559 KB to about 49 KB. Separate CPU profiles and request waterfalls confirm the removal of lifetime event hydration and are excluded from the five timing pairs. Both variants have the same expected missing optional plan document (404) and no browser exceptions. Control recent-window API reads have medians of 37 ms / 32 ms, with shared-host outliers up to 376 ms. The 6,000-message recent-window SQL uses `issue_comments_company_issue_created_at_idx` (22 index rows read for a 21-row probe). Geometry assertions retain a 2-pixel tolerance for the reading anchor and first-reveal layout. These are local synthetic measurements, not deployed staging latency. Earlier timing probes are excluded because they did not isolate service workers or composer clearance. Final head `bf71ffd5afb5684ba9105a3127f617e7adf5139c` has 55 successful checks, three optional skips and one neutral result, with no failures or pending checks. Greptile is 5/5 with no open review findings. ### Failure record Early local attempts exposed an unconditional scroller wrapper that changed the old task layout, and automatic retries on chat page failures. Both were corrected. The original task scroller structure stays in place. Metadata request assertions wait for initial connection recovery to settle, then verify only the new page’s reads; retry/resume/reconnect revalidation remains intentional. The initial review caught a send-before-scroll cache defect; its controller regression failed before the fix. Later rapid-paging checks caught scroll readiness being gated by metadata after the first reveal; readiness now stays enabled once revealed. Live replies use the separate acknowledged-message cache, then catch up from the server cursor. Visual review exposed a pagination wrapper bypassing existing composer clearance. The body is again a direct scroller child; cold-open browser checks require the full latest reply above the composer. A resize-observer regression failed before the fix and now passes. Controlled delayed inline images prove both pinned following and a stable reading anchor on desktop/mobile. The first performance fixture lacked valid native event envelopes and caused missing-log fallbacks. It is excluded from latency claims. The final fixture uses saved native assistant events and conversation session generations. The live test uses a temporary fixture-agent key, attributes the reply to an existing synthetic run, and revokes the key. It starts no model or agent process. Local database attempts failed during a Docker shutdown. The retained disposable database was restored and its suite passed. Early fixture errors included a missing conversation identity field and session generation. Mobile test setup also selected an offscreen sidebar link and reused queued human input. Optional announcements could intercept input; the fixture now dismisses them before the journeys. The scroll observer now waits for the delivered wheel event and settled animation frames, including when the viewport is already at the top. A concurrently running live test briefly changed another probe’s row count; the final acceptance and timing runs were sequential on separate fixtures. The final rig uses the visible mobile navigation and a saved agent reply. Anchor observation waits for the user's scroll to settle before measuring the effect of live updates. The full local `pnpm test:run` attempt hit repeated embedded PostgreSQL initialization failures and failures in untouched native-session executor suites; it was stopped after the repeated environment failures. The targeted real-PostgreSQL suite passed, and final-head CI is required before handoff. The first CI run also caught an exact mock expectation missing the added company scope; the expectation is updated and its 179-test suite passes. The final-head first CI attempt also stalled an assigned child task in the existing plan-approval scenario, then hit a heartbeat-run row lock timeout during fixture cleanup. The failed shard and aggregate check passed on an unchanged rerun of the same commit. Scenario assertions and timeouts were unchanged. The failure and rerun are retained in [CI run 41116120430](https://github.com/paperclipai/paperclip/actions/runs/41116120430). ## Risks - Historical transcript diagnostics no longer load on a cold chat open. Saved messages and conversation events remain available; diagnostic run views keep their full records. - Cursor paging must not omit comments with equal timestamps. Database tests cover timestamp/UUID ordering and the complete set. - Prepended or late content can move the reader. Browser checks cover retained row identity, viewport offsets, mounted drafts, and Back. Previously loaded pages stay in the query cache for its existing lifetime. - Local synthetic evidence does not establish deployed staging latency. This PR does not merge or deploy the change. ## Model Used OpenAI Codex, GPT-6 family, with reasoning, tool use, and code execution. The exact backend deployment 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 (affected checks; limits are recorded above) - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |