diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-27 22:54:43 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-27 22:54:43 -0500 |
| commit | dcfecf3e4f46c920eb77ca9b3169d0719fa0b9fd (patch) | |
| tree | dc710dc4412152897aa7fa617c0cabc6bbc08caa /docs/issue-sources-spec.org | |
| parent | 15ce896744a8095c221bdeaf887f6311f9a94526 (diff) | |
| download | pearl-dcfecf3e4f46c920eb77ca9b3169d0719fa0b9fd.tar.gz pearl-dcfecf3e4f46c920eb77ca9b3169d0719fa0b9fd.zip | |
feat(sources): favorites, views, and filters via pick-source
Pearl now treats Linear sources (favorites, custom views, ad-hoc filters, saved queries) as one surface. `pearl-pick-source` is the unified picker: it lists every Linear favorite alongside every locally saved query, and dispatches by kind. View / project / cycle / label / user favorites resolve to runnable filter or view sources; issue / document / dashboard favorites open in the browser since they aren't lists.
The filter compiler grows id-based forms (`:label-id` and `:assignee-id`), so favorites that name a Linear entity (a user, a label) compile to rename-proof queries rather than fragile name matching. The ad-hoc builder gets a matching member-assignee option ("me / member / any"), so a one-off "what's a teammate working on?" doesn't require building a saved query first.
Two pre-existing builder bugs surfaced during verify and got fixed in the same pass. The builder previously passed display names straight to the compiler, but `:team` compiles to `team.key.eq` and `:project` to `project.id.eq`, so Linear rejected every builder run that pinned a team or project. Now the builder resolves the picked name to its key / id before assembling. And `pearl-list-issues-by-project` previously injected `:assignee :me` into the filter, hiding every teammate's work in the project. It now returns the whole project.
The save prompt on the builder was rewritten so the local-only nature is unambiguous, and the README grew a Sources section plus a keymap-table entry for `f s`.
Diffstat (limited to 'docs/issue-sources-spec.org')
| -rw-r--r-- | docs/issue-sources-spec.org | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/docs/issue-sources-spec.org b/docs/issue-sources-spec.org index 101e13a..a4374c3 100644 --- a/docs/issue-sources-spec.org +++ b/docs/issue-sources-spec.org @@ -37,7 +37,9 @@ Each =Favorite= node carries =type= (the dispatch key), =title= (a ready display : query { favorites { nodes { id type title url sortOrder : customView { id } project { id } cycle { id } -: label { id } user { id } issue { id identifier } team { id } } } } +: label { id } user { id } issue { id identifier } +: team { id } projectLabel { id } document { id } dashboard { id } } +: pageInfo { hasNextPage endCursor } } } Introspection of the =Favorite= type confirmed the favoritable entity fields: =issue=, =project=, =cycle=, =customView=, =label=, =projectLabel=, =user=, =team=, =document=, =initiative=, =dashboard=, =pullRequest=, =release=, =releaseNote=, =facet=, =predefinedViewType=, =projectTab=, =customer=, plus convenience fields =title=, =url=, =detail=, =color=, =icon=, =folderName=, =owner=, =sortOrder=. Craig's current 9 favorites span customView / project / issue; the schema supports the rest. @@ -49,12 +51,11 @@ Pagination: the =favorites= connection is paginated like other Linear connection | favorite =type= | required API fields | v1 action | persisted source | |----------------------+------------------------+--------------------+----------------------------------------------------| -| =customView= | =customView.id=, title | run the view | =(:type view :name T :view-id ID)= | +| =customView= | =customView.id=, title | run the view | =(:type view :name T :id ID :url URL)= | | =project= | =project.id=, title | filter | =(:type filter :name T :filter (:project ID :open t))= | | =cycle= | =cycle.id=, title | filter | =(:type filter :name T :filter (:cycle ID :open t))= | -| =label= / =projectLabel= | =label.id=, title | filter | =(:type filter :name T :filter (:label-id ID :open t))= | +| =label= | =label.id=, title | filter | =(:type filter :name T :filter (:label-id ID :open t))= | | =user= | =user.id=, title | filter | =(:type filter :name T :filter (:assignee-id ID :open t))= | -| =team= | =team.id=, title | filter | =(:type filter :name T :filter (:team ID :open t))= | | =issue= | =issue.identifier=, url | browser-only (HP2) | none — opens =url=, renders no source | | anything else | =url=, title | browser-only | none — opens =url= | |
