Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
9d5136b
docs(review): design the token hover card trigger settings and announ…
backnotprop Sep 3, 2026
94ec825
feat(review): token hover card trigger settings and first-run announc…
backnotprop Sep 3, 2026
5c93856
fix(review): hover card review findings, M1/M2 and minors
backnotprop Sep 3, 2026
d04cfce
fix(review): dialog footer names the real Settings tab (Editor, not R…
backnotprop Sep 3, 2026
406c2af
feat(review): jumbo hover card announcement, and rename the feature t…
backnotprop Sep 3, 2026
ab9b73a
feat(review): make the announcement example a live try-it on the real…
backnotprop Sep 3, 2026
17b8aae
fix(review): the try-it fixture names the token the prompt asks you t…
backnotprop Sep 3, 2026
51e85d5
feat(review): the hover card modifier gate is Cmd (Ctrl), not Alt
backnotprop Sep 3, 2026
eebab51
fix(review): pointer cursor wins over Pierre's I-beam on hovered and …
backnotprop Sep 3, 2026
50f8e22
fix(review): the intro dialog's demo token gets the pointer cursor too
backnotprop Sep 3, 2026
b553835
feat(review): hover delay default is 300ms matching VS Code; tiers re…
backnotprop Sep 3, 2026
6f74c04
test(review): restore the 700-delay test's summed advances
backnotprop Sep 3, 2026
2641c0c
fix(review): the hover gate's typing guard pierces the shadow root
backnotprop Sep 3, 2026
07256d9
feat(review): the modifier gate paints the navigable-target affordance
backnotprop Sep 3, 2026
50b32df
fix(review): hover card cleanups, and the design's delay tiers
backnotprop Sep 3, 2026
dc83c01
chore(core): re-pin the guide viewer build
backnotprop Sep 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ jobs:
packages/review-editor/hooks/useReviewSearch.test.tsx
packages/review-editor/hooks/useTokenHover.test.tsx
packages/review-editor/components/TokenHoverCard.test.tsx
packages/review-editor/components/TokenHoverAnnouncementDialog.test.tsx
packages/review-editor/utils/stitchTokenIdentifier.test.ts
packages/review-editor/hooks/useAutoViewed.test.tsx
packages/review-editor/hooks/useCallFlowAnalysis.test.tsx
Expand Down
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ The default code-review diff is **`since-base`** — a composite of `merge-base(

**Staging display invariant:** `useGitAdd`'s `stagedFiles` is the EFFECTIVE staged set (sections-sidecar snapshot + session stage/unstage overrides) and is the only source any surface may render staging state from. The sidecar entry's `staged` flag is a snapshot — ORing it back in makes files unstaged mid-session render as staged (and inverts the next toggle).

`since-base` is only offered when the base ref actually resolves — on a repo whose trunk isn't discoverable (`trunk`, no `origin/HEAD`) `getGitContext` omits it and the default falls through to `uncommitted`, so committed branch work is never silently hidden. The since-base patch/sections/fingerprint/file-content paths all degrade to `HEAD` together when merge-base fails for a resolvable-but-unrelated base. First-run shows `ReviewSetupDialog` (replaces the removed `DiffTypeSetupDialog`), which initializes an unseen reviewer's panel to Tree once while preserving the resolved diff default, and is reopenable from the review header menu. The one-time dialog chain is guide intro → look-and-feel → review setup → Edit Mode; none of the dialogs stack. Analysis layers no longer add a startup dialog: Semantic Changes retains its enabled default, while Call Flow remains disabled until the user explicitly enables it in Settings, which is also consent for its managed runtime installation.
`since-base` is only offered when the base ref actually resolves — on a repo whose trunk isn't discoverable (`trunk`, no `origin/HEAD`) `getGitContext` omits it and the default falls through to `uncommitted`, so committed branch work is never silently hidden. The since-base patch/sections/fingerprint/file-content paths all degrade to `HEAD` together when merge-base fails for a resolvable-but-unrelated base. First-run shows `ReviewSetupDialog` (replaces the removed `DiffTypeSetupDialog`), which initializes an unseen reviewer's panel to Tree once while preserving the resolved diff default, and is reopenable from the review header menu. The one-time dialog chain is guide intro → look-and-feel → review setup → Edit Mode → token hover cards; none of the dialogs stack. The token hover announcement is last and additionally skips a session where hover cards cannot run at all (no live workspace), WITHOUT consuming its cookie, and never shows to a reviewer whose trigger is already non-default (which after the boolean-to-trigger migration is exactly the early adopter who turned cards off). Analysis layers no longer add a startup dialog: Semantic Changes retains its enabled default, while Call Flow remains disabled until the user explicitly enables it in Settings, which is also consent for its managed runtime installation.

### GitButler review invariants

Expand Down Expand Up @@ -553,7 +553,7 @@ During normal plan review, an Archive sidebar tab provides the same browsing via
| `/api/guide/:jobId/output` | GET | Fetch a failed guide job's captured raw output for manual repair (404 if none captured) |
| `/api/guide/:jobId/submit` | POST | Manually submit corrected guide JSON for a failed job (body: `{ payload }`) |
| `/api/code-nav/resolve` | POST | Search for symbol definitions and references via ripgrep (body: `{ symbol, filePath, line, charStart, side, language? }`) |
| `/api/code-nav/hover` | POST | Token hover card resolution: the same body and the same guards as `/resolve`, over the same ripgrep search, returning one enriched definition (kind, approximate signature, heuristic doc comment, short preview), an optional runner-up candidate, and a five-reference sample. `backend: 'unavailable'` (rg missing) is a normal 200 and the client renders nothing. `source` is always `'search'` in Tier 0; the nullable `symbolKind` / `signature` / `doc` fields are what a later syntax- or index-backed tier would fill. |
| `/api/code-nav/hover` | POST | Token hover card resolution: the same body and the same guards as `/resolve`, over the same ripgrep search, returning one enriched definition (kind, approximate signature, heuristic doc comment, short preview), an optional runner-up candidate, and a five-reference sample. `backend: 'unavailable'` (rg missing) is a normal 200 and the client renders nothing. `source` is always `'search'` in Tier 0; the nullable `symbolKind` / `signature` / `doc` fields are what a later syntax- or index-backed tier would fill. Client-side the card is governed by two cookie-only settings (`packages/ui/config/settings.ts`, types in `@plannotator/core/token-hover`): `tokenHoverTrigger` (`hover` default / `modifier`, meaning the platform's primary modifier held, Cmd on macOS and Ctrl elsewhere via `isModKeyHeld` / `modEventKey` in `packages/ui/utils/platform.ts` / `off`, which withholds the handler props so the diff views wire no listeners at all) and `tokenHoverDelay` (150 / 300 default / 700 ms, the dwell before any request exists; 300 matches the VS Code hover delay). `tokenHoverTrigger` REPLACED the original `tokenHoverCards` boolean and re-reads its cookie as a migration on every load until the user touches the setting (`false` becomes `off`), never writing it back: a migrating read returns a value, so the registry's default-seeding write never fires, and resolution is pure and identical every time. Cmd rather than Alt because Alt is widely bound to push-to-talk dictation (an Alt gate would open cards while the user speaks) and because Cmd+hover is already VS Code's "tell me about this symbol" gesture; the navigable-target underline and the card under one held key is that composite gesture, not a collision, since `handleCodeNavRequest` dismisses the hover surface on every References invocation. Only the modifier ALONE arms: any other key while it is held (Cmd+C) disarms and closes, so a copy with the pointer parked on a token cannot pop a card. Both key branches read `composedPath()[0]`, not `event.target`, because a window-level listener sees the shadow HOST and Pierre's edit-session editor is a contenteditable inside that root; typing suppresses ARMING only, never disarming, and keyup carries no typing guard at all. The `pn-token-nav` affordance is the other half of the held-key gesture: the diff views paint it from the pointer enter event, and the hook additionally reports arm/disarm through `onModifierGate(armed, tokenElement)` so a key pressed over a parked pointer (and the release after it) paints and unpaints it too. `pn-token-hover` (underline plus a `cursor: pointer !important` that beats Pierre's I-beam) is painted by BOTH diff views, gated on a hover handler actually being wired, so `off` and the portable viewer get no affordance. Click behavior is untouched by the trigger setting, and the #1461 Alt+click References alias is unrelated. The stored value stays `modifier`: the setting names the shape of the gate, not which key fills it. |
| `/api/code-nav/file` | GET | Read file from working tree for code-nav preview (`?path=`) |

### Annotate Server (`packages/server/annotate.ts`)
Expand Down
Loading