guito 1.0.10 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,41 @@ All notable changes to Guito are documented in this file. The project follows [S
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.0.12] - 2026-10-15
8
+
9
+ ### Changed
10
+
11
+ - Azure DevOps is now detected from the repository's remotes instead of configured. Guito derives the project from `origin` (or the first other remote pointing to Azure DevOps) and creates pull requests against that remote; the settings dialog shows the detected project. The `guito.azureDevOpsUrl` VS Code setting and the Server URL field in the settings dialog are removed.
12
+
13
+ ### Added
14
+
15
+ - Pull request **Comments** tab now shows code context on inline threads: a focused snippet around the commented line with a **Show code context** loader and an expandable full-file diff, so reviewers see what a comment refers to without leaving the tab.
16
+ - Azure-generated comment activity now reads as plain language: vote entries like "changed status to 10" render as "approved" (with suggestions / waiting for author / rejected mapped the same way) and named status changes use friendly labels like Resolved, with the raw text kept as a tooltip. System entries in an inline thread's diff view render as a quiet one-line note instead of a comment with avatar and markdown, again with the raw text as a tooltip.
17
+ - Filter pull request comments by thread status (with counts), location (General vs Inline), and entry kind (comments vs activity), with a **Clear** reset and a distinct "No comments match these filters" empty state.
18
+ - Mark automated review findings as fixed from the PR dialog's **Review** tab with a per-finding **I fixed it** button. Fixed points move to **Already handled** with a green **Fixed** label and are never raised again by future reviews, like dismissed ones. A **Dim handled** toggle dims the handled section via opacity so pending points stand out; it is on by default and remembered per browser.
19
+ - Decline to review a pull request from the PR dialog's **Review** menu (**Decline to review** / **Resume review**). Reviewers who declined appear in their own **Declined** section of the dialog's reviewer list, and the side panel marks pull requests you declined with a **Declined** badge.
20
+
21
+ ### Fixed
22
+
23
+ - Right-clicking a branch badge in the commit history no longer offers the wrong actions for local branches whose names contain a slash (e.g. `feature/topic`). Badges are now resolved against the loaded branch list instead of guessing from the name, so **Checkout Branch...** opens the local switch dialog and **Delete Branch...** deletes the local branch instead of failing against a misread remote.
24
+ - Detached `HEAD` and symbolic `origin/HEAD` badges no longer offer **Rename**, **Delete** or **Pull** actions that Git would refuse, and **Unselect in Branches Dropdown** now removes only that branch from the history filter (instead of clearing the whole selection) and stays disabled when the branch is not selected.
25
+
26
+ ## [1.0.11] - 2026-10-12
27
+
28
+ ### Added
29
+
30
+ - Keyboard shortcuts for the commit history. **Ctrl+F** focuses the commit search box, **Ctrl+J** selects and scrolls to the current branch's commit (or the checked-out commit when HEAD is detached), and **Ctrl+G** opens a **Go to Commit** dialog. Type a row number to jump to that row of the list as currently shown, or a commit hash (at least 4 characters) to jump to that commit. History that isn't loaded yet is fetched as needed, and the dialog explains when a row is out of range, a hash is ambiguous or unknown, or the commit is hidden by the current branch or search filter. On macOS, Cmd works in place of Ctrl. The shortcuts do nothing while a dialog is open.
31
+ - **Code review of uncommitted changes.** A new **Code review** button sits after the stash buttons on the uncommitted changes panel. It has Claude Code review everything not yet committed: staged, unstaged and untracked files. While the review runs, the button turns into **Stop review**. When it finishes, the results open in a new tab: a VS Code editor tab inside the extension, or a browser tab in standalone Guito. Each finding shows its severity and comment and links to the file and line. Its **Auto fix** button has Claude Code fix that one problem in the working tree. Claude Code may only read and edit files; it cannot run commands or use git. The fix shows up as an ordinary uncommitted edit, and **Stop** cancels a running fix. Reviews and fixes use the configured review model, effort, instructions and timeout (`guito.aiReview.*`). The last review is kept per worktree in `.git/guito-working-review.json`.
32
+
33
+ ### Changed
34
+
35
+ - Ref pills in the commit history now match the graph. Each branch pill takes the color of its graph line; the current branch stays filled, now in its line color instead of a fixed blue. Local and remote branches and tags share one pill style. Remote branches get a cloud icon and tags keep the tag icon, and tags use a soft yellow that no graph line uses. To keep that yellow unique, the graph's two yellowish line colors were replaced with violet and silver. Prefer a quieter look? The new **Gray branch and tag pills** setting (`guito.grayRefBadges` in VS Code, off by default) draws every branch and tag pill in one neutral gray, with the current branch filled.
36
+ - The close buttons on the uncommitted changes panel, commit detail, settings, pull request, diff and merge conflict views, and the error banner's dismiss button now share one look and behavior, matching the commit panel's close button.
37
+
38
+ ### Removed
39
+
40
+ - Stashes no longer appear in the commit history. The "Show stashes" setting (`guito.showStashes` in VS Code) is gone, and the latest stash commit is no longer drawn in the graph; stashes are listed only in the repository panel.
41
+
7
42
  ## [1.0.10] - 2026-10-10
8
43
 
9
44
  ### Added
package/README.md CHANGED
@@ -97,9 +97,9 @@ The settings dialog also manages preferences that have no VS Code equivalent: th
97
97
  | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
98
98
  | `guito.autoReload` | Reload commits and the working tree automatically when the repository changes outside Guito, for example from a terminal. On by default. |
99
99
  | `guito.showGraph` | Show the Git graph beside the commit history. On by default. |
100
- | `guito.showStashes` | Show stash entries above the commit history. Off by default. |
101
100
  | `guito.showTags` | Show tag badges attached to commits. On by default. |
102
101
  | `guito.showRemoteBranches` | Show remote branches in the repository panel and the branch pills on commits. On by default. |
102
+ | `guito.grayRefBadges` | Show branch and tag pills in a single neutral gray instead of graph lane colors. Off by default. |
103
103
  | `guito.fileListView` | How changed-file lists are shown: `flat` (default) lists every file with its full path, `tree` groups them into collapsible folders. |
104
104
  | `guito.refListView` | How branches and tags are shown in the repository panel: `flat` (default) lists full names, `tree` groups them into collapsible namespace folders. |
105
105
  | `guito.sidePanelSectionsExpanded`| Open the repository panel with all sections expanded. On by default. |
@@ -111,9 +111,10 @@ The settings dialog also manages preferences that have no VS Code equivalent: th
111
111
 
112
112
  ### Azure DevOps
113
113
 
114
+ Guito detects Azure DevOps from the repository's remotes: when `origin` (or, failing that, any other remote) has a URL like `https://server/DefaultCollection/Project/_git/Repo`, pull request creation, the pull request panel, and the automated reviewer are enabled for that project. ssh remotes are reached over https on the same host. Requests authenticate with Windows integrated auth.
115
+
114
116
  | Setting | Description |
115
117
  | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
116
- | `guito.azureDevOpsUrl` | Base URL of your on-prem Azure DevOps Server, for example `https://server/DefaultCollection`. Enables pull request creation and the automated reviewer; requests authenticate with Windows integrated auth. |
117
118
  | `guito.prBranchNameTemplate` | Branch name template used when Guito creates a new branch for a pull request. Defaults to `pr/${randomstring}`. Variables: `${username}`, `${randomstring}`, `${branch}`, `${targetbranch}`, `${title}`, `${repository}`, `${date}` (UTC `YYYY-MM-DD`), `${time}` (UTC `HHmmss`), and `${timestamp}`. |
118
119
  | `guito.allowMerge` | Offer the "No fast-forward (merge commit)" and "Semi-linear merge" pull request completion strategies. On by default. |
119
120
 
package/bin/ai-review.js CHANGED
@@ -2,7 +2,7 @@ import { spawn } from 'node:child_process';
2
2
  import { createHash } from 'node:crypto';
3
3
  import { homedir } from 'node:os';
4
4
  import { join } from 'node:path';
5
- const SEVERITIES = ['blocker', 'concern', 'suggestion', 'nit'];
5
+ export const SEVERITIES = ['blocker', 'concern', 'suggestion', 'nit'];
6
6
  /** Effort levels Claude Code accepts for --effort; '' leaves it to Claude Code. */
7
7
  export const AI_REVIEW_EFFORTS = ['', 'low', 'medium', 'high', 'xhigh', 'max'];
8
8
  /** How much a drafted commit message says beyond its subject line. */
@@ -267,7 +267,7 @@ export function parseModelReview(raw) {
267
267
  };
268
268
  }
269
269
  /** Identity of a finding across re-reviews: same place, same point. */
270
- function fingerprint(file, title) {
270
+ export function fingerprint(file, title) {
271
271
  const normalized = title
272
272
  .toLowerCase()
273
273
  .replace(/[^a-z0-9]+/g, ' ')
@@ -275,7 +275,7 @@ function fingerprint(file, title) {
275
275
  return createHash('sha1').update(`${file}\u0000${normalized}`).digest('hex').slice(0, 16);
276
276
  }
277
277
  /** Renders one file's diff with the line numbers the model must cite. */
278
- function renderFileDiff(diff, budget) {
278
+ export function renderFileDiff(diff, budget) {
279
279
  const header = `--- FILE: ${diff.path}${diff.oldPath && diff.oldPath !== diff.path ? ` (renamed from ${diff.oldPath})` : ''} [${diff.status}] ---`;
280
280
  if (diff.binary)
281
281
  return `${header}\n(binary file, not reviewable)\n`;
@@ -320,7 +320,7 @@ function renderThreads(threads) {
320
320
  })
321
321
  .join('\n');
322
322
  }
323
- const REVIEW_CONTRACT = `Reply with one JSON object and nothing else:
323
+ export const REVIEW_CONTRACT = `Reply with one JSON object and nothing else:
324
324
  {"summary": "<one or two sentences on the change as a whole>",
325
325
  "findings": [
326
326
  {"file": "<path exactly as given in the diff header, or \\"\\" for the change as a whole>",
@@ -346,8 +346,9 @@ export function buildReviewPrompt(input) {
346
346
  const incremental = Boolean(sinceCommit);
347
347
  const perFile = Math.max(2000, Math.floor(input.maxDiffChars / Math.max(diffs.length, 1)));
348
348
  const body = diffs.map((diff) => renderFileDiff(diff, perFile)).join('\n');
349
- const raised = previous.filter((finding) => finding.status !== 'dismissed');
349
+ const raised = previous.filter((finding) => finding.status === 'pending' || finding.status === 'posted');
350
350
  const dismissed = previous.filter((finding) => finding.status === 'dismissed');
351
+ const fixed = previous.filter((finding) => finding.status === 'fixed');
351
352
  const sections = [
352
353
  'You are reviewing an Azure DevOps pull request as a careful senior engineer on this team.',
353
354
  '',
@@ -377,6 +378,13 @@ export function buildReviewPrompt(input) {
377
378
  .join('\n')
378
379
  : ' None.',
379
380
  '',
381
+ 'POINTS THE USER FIXED (never raise these again):',
382
+ fixed.length
383
+ ? fixed
384
+ .map((finding) => ` - ${finding.file || 'pull request'} — ${finding.title}`)
385
+ .join('\n')
386
+ : ' None.',
387
+ '',
380
388
  'EXISTING COMMENT THREADS ON THE PULL REQUEST:',
381
389
  renderThreads(threads),
382
390
  '',
@@ -755,6 +763,22 @@ export function createAiReviewer(deps, initialConfig = DEFAULT_AI_REVIEW_CONFIG,
755
763
  return next;
756
764
  });
757
765
  },
766
+ async fix(pullRequestId, findingIds) {
767
+ const wanted = new Set(findingIds);
768
+ return mutateStore((store) => {
769
+ const current = store.pullRequests[String(pullRequestId)];
770
+ if (!current)
771
+ throw new Error(`Pull request ${pullRequestId} has not been reviewed yet.`);
772
+ const next = {
773
+ ...current,
774
+ findings: current.findings.map((finding) => finding.status === 'pending' && wanted.has(finding.id)
775
+ ? { ...finding, status: 'fixed', resolvedAt: now().toISOString() }
776
+ : finding),
777
+ };
778
+ store.pullRequests[String(pullRequestId)] = next;
779
+ return next;
780
+ });
781
+ },
758
782
  async forget(pullRequestId) {
759
783
  await mutateStore((store) => {
760
784
  delete store.pullRequests[String(pullRequestId)];