From a27dd722a24a27c0f3bbdcb4c4d79192d757d8e1 Mon Sep 17 00:00:00 2001 From: Dotta <34892728+cryppadotta@users.noreply.github.com> Date: Fri, 11 Sep 2026 15:11:56 -0500 Subject: [PATCH] fix(ui): restore task page archive shortcut (#13253) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The task detail page gives operators keyboard shortcuts for fast task work. > - The `y` shortcut must archive the open task from the inbox and return the operator to the inbox. > - A streamlined UI gate limited this shortcut to tasks opened from a selected inbox row. > - Direct task pages no longer ran the shortcut. > - This pull request removes that gate and adds regression coverage. > - The benefit is consistent keyboard operation from every visible task page. ## Linked Issues or Issue Description **What happened?** The `y` keyboard shortcut did nothing on a task page opened outside the inbox. **Expected behavior** The `y` shortcut archives the open task from the inbox and returns the operator to `/inbox`. **Steps to reproduce** 1. Enable keyboard shortcuts. 2. Open a visible task from the Tasks page. 3. Press `y` while focus is outside an editor. 4. Observe that the task does not archive. **Paperclip version or commit** Current `master` before this pull request. **Deployment mode** Local development. ## What Changed - Enable the `y` archive shortcut on every visible task detail page when keyboard shortcuts are enabled. - Keep the existing input, dialog, modifier, hidden-task, and pending-request guards. - Verify that `y` archives the task and navigates to `/inbox` for a task opened from the Tasks page. ## Verification - `pnpm exec vitest run ui/src/pages/IssueDetail.test.tsx ui/src/lib/keyboardShortcuts.test.ts ui/src/lib/issueDetailBreadcrumb.test.ts` (139 tests passed) - `pnpm --filter @paperclipai/ui typecheck` - `pnpm check:token-gates` - `pnpm --filter @paperclipai/ui build` - The full workspace typecheck and build reached the Rust runner. This environment does not include `cargo`, so the Rust steps did not run. - The full test suite entered unrelated serialized external-chat integration tests. It was stopped after the affected UI suite passed. ## Risks - Low risk. The change restores the shortcut behavior that existed before the streamlined UI gate. - The shortcut still ignores text inputs, open dialogs, modifier keys, and hidden tasks. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex. The Paperclip runtime did not expose the exact model ID or context window. The model 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) - [ ] 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 --- ui/src/pages/IssueDetail.test.tsx | 7 +++++-- ui/src/pages/IssueDetail.tsx | 6 +----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/ui/src/pages/IssueDetail.test.tsx b/ui/src/pages/IssueDetail.test.tsx index 4a59314de6..439732e8bb 100644 --- a/ui/src/pages/IssueDetail.test.tsx +++ b/ui/src/pages/IssueDetail.test.tsx @@ -2643,7 +2643,7 @@ describe("IssueDetail", () => { }); }); - it("keeps inbox archive actions scoped to an inbox-origin task", async () => { + it("archives a task-page issue with y and returns to the inbox", async () => { mockLocation.state = createIssueDetailLocationState( "Tasks", "/issues/all", @@ -2679,7 +2679,10 @@ describe("IssueDetail", () => { document.dispatchEvent( new KeyboardEvent("keydown", { key: "y", bubbles: true }), ); - expect(mockIssuesApi.archiveFromInbox).not.toHaveBeenCalled(); + await waitForAssertion(() => { + expect(mockIssuesApi.archiveFromInbox).toHaveBeenCalledWith("issue-1"); + expect(mockNavigate).toHaveBeenCalledWith("/inbox", { replace: true }); + }); }); it("arms the inbox archive shortcut only for the selected inbox row", async () => { diff --git a/ui/src/pages/IssueDetail.tsx b/ui/src/pages/IssueDetail.tsx index b85b20b97d..eb1cbfca47 100644 --- a/ui/src/pages/IssueDetail.tsx +++ b/ui/src/pages/IssueDetail.tsx @@ -92,7 +92,6 @@ import { readIssueDetailHeaderSeed, withIssueDetailHeaderSeed, rememberIssueDetailLocationState, - shouldArmIssueDetailInboxQuickArchive, } from "../lib/issueDetailBreadcrumb"; import { resolveIssueActiveRun, @@ -5667,10 +5666,7 @@ export function IssueDetail({ tasksTab }: { tasksTab?: TaskSidePanelProps["tasks const goToInboxShortcutArmedRef = useRef(false); const goToInboxShortcutTimeoutRef = useRef(null); const canQuickArchiveFromInbox = - keyboardShortcutsEnabled && - (!streamlinedUiEnabled || - (isFromInbox && shouldArmIssueDetailInboxQuickArchive(location.state))) && - !issue?.hiddenAt; + keyboardShortcutsEnabled && !issue?.hiddenAt; useEffect(() => { if (!issue?.id || !canQuickArchiveFromInbox) return;