## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - Operators use task filters to keep a useful view of their work.
> - Coordinator saves status and assignee filters in the task-list URL.
> - A selected label stayed only in React state, so reload removed it
and showed unrelated rows.
> - This change saves and restores selected labels through the same
page-owned URL path.
> - Operators can reload and share that filtered collection without
selecting its labels again.
## Linked Issues or Issue Description
**What happened?**
In Coordinator All tasks, select a status, assignee, and label. Sort by
Task ID and reload. Status, assignee, and sort remain selected, but the
label is cleared and rows without that label appear.
**Expected behavior**
Reload and history navigation retain the selected labels with the other
URL filters. Clear filters removes the selected labels.
**Steps to reproduce**
1. Open Coordinator All tasks with labeled and unlabeled tasks for the
same assignee and status.
2. Select that status, assignee, and a label.
3. Change Task ID sorting and reload the page.
4. Check both the selected label and the displayed tasks.
**Paperclip version or commit**
Source regression reproduced at master
47027e7ba5.
**Deployment mode**
Local rendered component test with the production filter panel, page,
and collection hook. API data is mocked. Live staging acceptance of this
repair remains pending.
Related prior work: #18831 preserves Coordinator views and filtered
links. Bounded searches found no matching label reload repair.
## What Changed
- Save selected labels as repeated `label` URL parameters in
CoordinatorTasks.
- Restore labels on mount and synchronize them on history navigation.
- Remove label parameters when clearing filters. Keep unrelated URL
values.
- Open label-only links in All tasks when no view is specified.
Canonicalize legacy Inbox-view links with labels to All tasks before
mounting the collection, so removing the last label retains local
filters and layout.
- Preserve the URL hash when filters change or clear.
- Add rendered checkbox, remount, repeated-label, history,
unknown-label, and legacy-view routing regressions through the real page
and collection.
- Document this URL behavior in PRODUCT.md.
## Verification
- First observed red: a production label checkbox restricted rows before
remount; after remount an unlabeled row appeared. The failure was
captured before production edits.
- Focused component suites: 90 tests pass across CoordinatorTasks,
Issues coordinator routing, useTaskListCollection, and issue-filters.
- UI typecheck and production build pass after generating the existing
plugin-sdk declarations locally.
- Token gates, map checks, and `git diff --check` pass. A review
correction restored the map to its unchanged base version. A native
review then found that the parent route omitted label scope. Four
settled routing cases failed before the one-entry route fix and pass
after it; the original label regressions still pass. A follow-up review
found a last-label redirect from the legacy URL; real
parent-plus-collection tests reproduced it. The route now canonicalizes
that entry before mount, and the tests preserve local priority and board
layout through label changes and history.
- The first treatment attempt exposed asynchronous test router timing.
The test now waits for a route update before the next interaction.
Initial failures remain in the private evidence record.
- Local checks above cover the UI and the affected component suites
only. `pnpm -r typecheck`, `pnpm test:run`, and `pnpm build` were not
run across the full workspace on this candidate. No whole-repository
local pass is claimed.
- Fresh hosted checks completed on exact head
`11586cc4e1bc4951b1fdde403ff229f760db721b`: 54 success, 3 skipped, 1
neutral; no failures or pending checks. Snyk status passed. Greptile and
native review both gave 5/5. Both actionable review threads are
resolved. Native review noted one optional redundant scope entry; no
blocking finding remains.
- Fixed-revision live browser acceptance remains pending. No deployed
repair or recovery is claimed.
## Risks
Low scope. The change affects Coordinator task-list presentation only.
Unknown label IDs remain restrictive until cleared; missing label
metadata does not silently widen results. Multiple labels keep the
existing OR filtering behavior. Other task interfaces keep their
existing persistence path. URL label values use company-local IDs and do
not grant access. Label filtering remains over loaded records; this
change does not add server pagination filtering.
## Model Used
OpenAI `gpt-6.1-sol` through Codex, with reasoning, source inspection,
code execution, and local tests. The runtime did not expose context
window size. The parent agent owns delivery coordination.
## 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>
@paperclipai/ui
Published static assets for the Paperclip board UI.
What gets published
The npm package contains the production build under dist/. It does not ship the UI source tree or workspace-only dependencies.
Storybook
Storybook config, stories, and fixtures live under ui/storybook/.
pnpm --filter @paperclipai/ui storybook
pnpm --filter @paperclipai/ui build-storybook
Typical use
Install the package, then serve or copy the built files from node_modules/@paperclipai/ui/dist.
Editor dependency identity
Keep the root and workspace overrides for @codemirror/state,
@codemirror/view, and @lezer/common aligned. CodeMirror requires shared
extension identity, while Lezer parsers and syntax highlighters require shared
NodeProp IDs. Multiple Lezer copies can crash code-block highlighting with
tags is not iterable. src/lib/codemirror-single-instance.test.ts checks the
installed dependency graph and highlights sample code through the editor's real
language dependencies. GitHub Actions owns regeneration of pnpm-lock.yaml.