Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3899de0
feat(review): add status-aware file staging and stream tabs
yusing Sep 5, 2026
adb8043
feat(review): stage and unstage the active diff hunk
yusing Sep 5, 2026
f3a2dba
feat(review): discard and stash only the selected file
yusing Sep 5, 2026
e5fabaf
feat(review): open the editor at the selected changed line
yusing Sep 5, 2026
39172f2
feat(ui): show Git-style file status colors
yusing Sep 5, 2026
a148e8c
fix(ui): scope file quick actions to the focused sidebar
yusing Sep 5, 2026
9d29139
fix(ui): resolve shortcut ownership across review focus and menus
yusing Sep 6, 2026
3810379
feat(ui): indicate focused pane and scope keyboard actions to it
yusing Sep 6, 2026
9d6aac8
feat(ui): make files-pane folders actionable
yusing Sep 6, 2026
6faffe6
feat(ui): keep working-tree folder actions and line stats on both tabs
yusing Sep 6, 2026
f2808c1
feat(ui): add Enter/escape pane focus commands
yusing Sep 6, 2026
4677cd1
fix: reconcile rebased staging and sidebar integrations
yusing Sep 7, 2026
6acd5ad
feat(review): support opening source lines in micro
yusing Sep 7, 2026
c950f0e
fix(ui): window diff rows before viewport measurement
yusing Sep 7, 2026
17c14fc
test(broker): create private runtime fixture regardless of umask
yusing Sep 7, 2026
a1f3c02
test(git): expect custom executable for working-tree inventory
yusing Sep 7, 2026
b3df1e7
test(cli): preserve Git ISO timezone in history expectations
yusing Sep 7, 2026
1f6e282
test(vcs): allow isolated compiler startup under contention
yusing Sep 7, 2026
c79baf0
fix(jj): include repository context in source failure diagnostics
yusing Sep 7, 2026
807f713
test(pty): wait for a painted frame when measuring key scroll
yusing Sep 7, 2026
c40b2e1
test(pty): wait for multi-row selection backgrounds to paint
yusing Sep 7, 2026
373826a
fix(extensions): accept the latest dialog answer in an input burst
yusing Sep 7, 2026
27e9432
fix(ui): preserve newer note hover during deferred scroll reads
yusing Sep 7, 2026
1efb9a6
fix(ui): keep file-action focus and targets fresh within input bursts
yusing Sep 7, 2026
182a484
fix(ui): settle native note edits before consuming drafts
yusing Sep 7, 2026
501a54a
fix(ui): preserve working-tree action targets and write exclusion
yusing Sep 7, 2026
c4a0785
fix: reconcile upstream extension contracts after rebase
yusing Sep 7, 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
5 changes: 5 additions & 0 deletions .changeset/active-hunk-staging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": minor
---

Stage or unstage the active diff hunk with Space or a code-line double-click, preserving other hunks and worktree content.
2 changes: 2 additions & 0 deletions .changeset/calm-bikes-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
5 changes: 5 additions & 0 deletions .changeset/complete-note-input.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": patch
---

Preserve the final characters of a note when save follows immediately, and let queued edits settle before cancellation.
5 changes: 5 additions & 0 deletions .changeset/enter-esc-pane-focus.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": patch
---

Use Enter to focus the selected file’s review from the files pane and Escape to return to the files pane on the current file.
5 changes: 5 additions & 0 deletions .changeset/exact-line-editor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": minor
---

Open the external editor at the selected source line or the active hunk’s first change, mapping staged lines through later unstaged edits and refusing text-converted coordinates or unknown editor line syntax.
5 changes: 5 additions & 0 deletions .changeset/fast-dialog-answers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": patch
---

Preserve the latest extension dialog input and selection when Enter follows immediately.
5 changes: 5 additions & 0 deletions .changeset/fast-discard-targets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": patch
---

Honor file navigation immediately before discard or stash shortcuts while preserving the exact selected target.
5 changes: 5 additions & 0 deletions .changeset/focused-pane-indication.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": patch
---

Highlight the focused pane with a brighter border, and move ↑/↓ and j/k through the file list while the files pane is focused.
5 changes: 5 additions & 0 deletions .changeset/folder-file-pane-actions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": minor
---

Make files-pane folders selectable so staging, discard, and stash apply to their nested files in tree view or their group’s files in the compact list.
5 changes: 5 additions & 0 deletions .changeset/folder-select-keeps-stats.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": patch
---

Keep files-pane line counts visible on both working-tree tabs and keep folder selection on the current tab when any nested file belongs there.
5 changes: 5 additions & 0 deletions .changeset/git-status-file-colors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": patch
---

Show Git-style colored status columns in the file panel, with red untracked markers, green staged additions, and a full-width selected-row highlight.
2 changes: 2 additions & 0 deletions .changeset/hot-comics-battle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
5 changes: 5 additions & 0 deletions .changeset/initial-row-window.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": patch
---

Keep large unwrapped diffs responsive from the first frame by windowing rows before the terminal viewport is measured.
2 changes: 2 additions & 0 deletions .changeset/little-clouds-rush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
5 changes: 5 additions & 0 deletions .changeset/live-staging-targets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": patch
---

Apply staging to the latest file, folder, or hunk selected in an input burst and prevent extension writes from overlapping Git mutations.
5 changes: 5 additions & 0 deletions .changeset/micro-editor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": patch
---

Support opening the selected source line in micro with the e shortcut when EDITOR is set to micro.
5 changes: 5 additions & 0 deletions .changeset/newer-note-hover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": patch
---

Keep add-note controls visible when a mouse move follows navigation before the viewport update settles.
2 changes: 2 additions & 0 deletions .changeset/open-donuts-allow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
2 changes: 2 additions & 0 deletions .changeset/pty-frame-probes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
5 changes: 5 additions & 0 deletions .changeset/quiet-file-quick-actions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": patch
---

Keep stash and discard shortcuts scoped to the visible, focused file panel so they do not override built-in review shortcuts elsewhere.
5 changes: 5 additions & 0 deletions .changeset/quiet-jj-diagnostics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": patch
---

Include the repository path when Jujutsu source reads fail to start or collect output.
2 changes: 2 additions & 0 deletions .changeset/rebase-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
5 changes: 5 additions & 0 deletions .changeset/review-chord-conflicts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": patch
---

Stop help and menus from advertising keys that a working-tree command currently owns, leave file quick actions after review-stream clicks, and keep Space on the file action when hunk staging is not available.
5 changes: 5 additions & 0 deletions .changeset/selected-file-discard-stash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": minor
---

Discard selected-file changes with a scoped confirmation, or stash only the selected file with a message while preserving its partial staging and unrelated work.
2 changes: 2 additions & 0 deletions .changeset/smooth-comics-fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
5 changes: 5 additions & 0 deletions .changeset/status-aware-staging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hunkdiff": minor
---

Add status-aware working-tree navigation with staged/unstaged stream tabs and file staging through Space or double-click.
2 changes: 2 additions & 0 deletions .changeset/sunny-worlds-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
2 changes: 2 additions & 0 deletions .changeset/upstream-working-tree-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
21 changes: 20 additions & 1 deletion docs/extension-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ key runs it, so the mouse surfaces read from it rather than restating it: the
dropdown menus (`packages/hunk/src/ui/lib/appMenus.ts`) declare items as command ids plus
menu-specific wording and checkbox state, and the controls help dialog
(`packages/hunk/src/ui/lib/helpContent.ts`) declares curated rows the same way — both render
their key text from resolved `keyLabels` and run entries through
their key text from the chords first-match dispatch still delivers and run entries through
`executeAppCommand`. A few commands ship with `defaultKeys: []` because they
exist for a menu item; they never match a key but remain bindable by id.

Expand All @@ -337,6 +337,25 @@ none — which is why the visible menu list is derived from the menus record

## VCS adapters

Plain working-tree reviews additionally carry an optional provider-owned status inventory beside
the active diff changeset. `packages/hunk-git/src/workingTree.ts` derives both
index/worktree status and attestations, and implements the public file-staging methods.
`packages/hunk-git/src/hunkStaging.ts` selects attested raw Git hunks for
index-only writes; sanitized render text is never applied. The conversion boundary preserves these
optional methods and normalizes their errors. `packages/hunk/src/ui/hooks/useWorkingTreeActions.ts`
binds status paths to the existing review navigation and AppHost's tracked mutation/serialized
refresh lifecycle, excluding extension writes while a Git action is active. The bundled sidebar consumes `ExtensionPaneProps.workingTree` through the public
pane contract; inactive-side files never become fabricated review-document entries. Stream tabs
replace the active canonical diff, not the sidebar inventory. Browser/session exports remain
read-only with respect to Git state. The same leased mutation controller owns exact-file
discard/stash prompts; keyboard routing remains in the App keyboard hook and mouse choices reuse
ConfirmDialog. Git builds file-only stash trees through an isolated index and publishes a normal
stash before cleaning the selected live paths. Cleanup failure retains that stash and reports
partial completion. The terminal cursor adapter distinguishes deliberate source selection from
automatic viewport rows; editor fallback consumes the shared first-change target. Git's optional
read-only line resolver validates source coordinates and maps staged addresses through later
worktree edits, while App retains editor launch and refresh ownership.

`packages/hunk/src/core/vcs/index.ts` owns provider-neutral catalog ordering, lookup,
detection, and operation dispatch. `packages/hunk/src/app/vcsCatalog.ts` composes bundled
registrations, while `packages/hunk/src/app/sessionBootstrap.ts` extends that catalog with
Expand Down
58 changes: 56 additions & 2 deletions docs/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,60 @@ reuses one is skipped with a notice.
map off entirely — produces a clear "not supported" error for that command
instead of a crash.

Plain working-tree `load` results may return `workingTreeFiles`, an ordered inventory covering both
staged and unstaged files, independent of `input.staged`. Each entry supplies `path`, optional
`previousPath`, `staged`, `unstaged`, `untracked`, `conflicted`, an opaque `version` attestation, and
optionally an `unavailableReason`. Do not return this inventory for revision comparisons.

API v25 adds optional `statusCode`, a two-character Git-style index/worktree status (`??` for
untracked files). The sidebar colors these columns independently and retains `S`/`U` indicators
for providers that omit the code. This display field does not replace mutation attestations.

API v25 adds optional inventory `stats` (`additions` / `deletions`) covering that path's staged
and unstaged line counts. The files pane uses these when the current Unstaged/Staged stream does
not include the file, so +/- counts stay visible on both tabs.

The working-tree operation may implement `stageFile(input, file, ctx)` and
`unstageFile(input, file, ctx)`. Revalidate the supplied attestation and exact path before writing;
unstaging must leave worktree contents unchanged. Throw `HunkExtensionUserError` on refusal or
failure. Hunk tracks started mutations through shutdown, blocks repeated actions until refresh,
and reloads authoritative state even after a failed mutation; extension workspace writes are refused while that Git action is active.

API v25 also adds optional `stageHunk(input, file, hunk, ctx)` and
`unstageHunk(input, file, hunk, ctx)`. `hunk` is the existing `ExtensionDiffHunk` summary.
Validate its numbered identity against the canonical provider patch after checking the file
attestation, including its comparison base. Apply original patch bytes, never decoded or
text-converted source. Preserve all other hunks and worktree content; reject unsupported textual changes.
Hunk actions use the currently reviewed side rather than the file's combined staged status.

API v25 adds optional `discardFile(input, file, scope, ctx)` and
`stashFile(input, file, message, ctx)`. Discard scope is `"all"` or `"unstaged"`;
the host obtains exact-file confirmation before calling either operation. Unstaged-only discard
preserves the index and is offered when both status sides have changes. Stash receives the entered
message (possibly empty) and must preserve the selected file's partial staging in the stash while
excluding unrelated changes from every stash tree and from live cleanup. Revalidate the attestation
before writes, retain a published stash if cleanup fails, and report partial completion explicitly.
These optional operations remain absent for read-only providers and revision comparisons.

API v25 adds optional `stashFiles(input, files, message, ctx)` for one stash covering several
attested paths. The host confirms a selected folder before calling it. Preserve each file's partial
staging and exclude unrelated changes, the same way `stashFile` does for one path.

API v25 adds optional `resolveWorkingTreeLine(input, file, line, ctx): Promise<number>`.
This read-only operation validates a new-side source line and maps staged addresses into the actual
worktree before an external editor is launched. Validate the reviewed file's source attestation, account for later
unstaged edits, and refuse unmappable source transforms rather than guessing. Hunk drops a result
when its review lease has expired. This capability does not launch an editor or grant remote writes.

Mounted panes receive optional `props.workingTree` with this inventory, `selectedPath`,
`selectedEntryId`, `staged`, `busy`, `selectFile(path)`, `selectEntry(id)`, `toggleStaged(path)`,
and `toggleEntry(id)`. These controls expire on review reload.
Selecting an inactive-side file switches stream tabs without reducing the review to one file.
File toggling stages remaining unstaged changes first, otherwise unstages the file. Folder rows use
`selectEntry` / `toggleEntry` and apply to the files shown under that row. Existing
`props.files` and review navigation still describe only the active diff stream. These host-only
actions are not exposed through browser/session commands or `ctx.commands`.

API version 19 adds the optional, read-only `history` capability used by the built-in `hunk log` surface:

```ts
Expand Down Expand Up @@ -1878,7 +1932,7 @@ path.

`canWriteDocument` checks the review and file policy without prompting or
inspecting the filesystem. A later `writeDocument` can still refuse if the file
has moved or become unsafe.
has moved or become unsafe, or a Git mutation owns the host write boundary.

`writeDocument` verifies the target, asks for consent through the attributed
`ctx.dialogs` queue, then verifies it again before writing. The second check
Expand All @@ -1890,7 +1944,7 @@ reconciliation of the review then active, and the write promise may settle
before that reload finishes.

A declined prompt returns `cancelled`, an ineligible or unsafe target returns
`unavailable`, and an attempted write failure returns `failed` with a
`unavailable` (also returned while a Git action is active or Hunk is shutting down), and an attempted write failure returns `failed` with a
displayable `detail`. Malformed requests reject the promise.

### `hunk.transformChangeset(fn)`
Expand Down
Loading