Skip to content

Commit 01373b8

Browse files
ADO Lens 0.9.2
Fixes and additions from testing 0.9 on a real project. - `ado_create`: fields with a default of the process (Value Area, Severity, Triage…) and fields Azure DevOps fills itself (Area ID, Iteration ID, State, Work Item Type) are no longer asked for - the rule check of 0.9.0 took the system rules of the process for fields to give. A rule "required while State was empty" is checked as "on create" instead of ending in a 400 from Azure DevOps. - `ado_fields type=<type>`: fields required by rules are named as REQUIRED, and fields that are required but filled by Azure DevOps say so. - `ado_trace` much faster on items with many pull requests: the files of a PR come from its last iteration instead of a diff of its merge commit, merge commits of linked PRs are not read twice, a completed PR into a branch answers "is it there" without asking, and only the newest change of each source -> target pair is checked. Reading the changes gets half of the time, so builds and deployments are still read. - `ado_trace` with no code linked looks for configuration words in every text field of the item and its tasks. - `ado_sprint`: a "Done" state that the process puts in the Resolved category counts as done. - `ado_work_item`: names of up to 40 linked releases (was 10); a release deleted by retention or not readable says so. - Numbered lists keep their numbering (`<ol start="3">`). - `ado_pr_update`: `update` adds reviewers, `requiredReviewers` (on create and update) makes them required, `autocomplete` (merge strategy, delete source branch, text = merge message) and `cancel_autocomplete`. - A parameter a tool does not have is reported with the tool's parameters instead of being dropped (a conversation started before an update still sees the old tool descriptions).
1 parent f7ddde8 commit 01373b8

16 files changed

Lines changed: 230 additions & 45 deletions

‎CHANGELOG.md‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
11
# Changelog
22

3+
## 0.9.2 — 2026-10-19
4+
5+
Fixes and additions from testing 0.9 on a real project.
6+
7+
- `ado_create`: fields with a default of the process (Value Area, Severity, Triage…) and fields Azure DevOps fills
8+
itself (Area ID, Iteration ID, State, Work Item Type) are no longer asked for - the rule check of 0.9.0 took the
9+
system rules of the process for fields to give. A rule "required while State was empty" is checked as "on create"
10+
instead of ending in a 400 from Azure DevOps.
11+
- `ado_fields type=<type>`: fields required by rules are named as REQUIRED, and fields that are required but filled by
12+
Azure DevOps say so.
13+
- `ado_trace` much faster on items with many pull requests: the files of a PR come from its last iteration instead of
14+
a diff of its merge commit, merge commits of linked PRs are not read twice, a completed PR into a branch answers
15+
"is it there" without asking, and only the newest change of each source -> target pair is checked. Reading the
16+
changes gets half of the time, so builds and deployments are still read.
17+
- `ado_trace` with no code linked looks for configuration words in every text field of the item and its tasks.
18+
- `ado_sprint`: a "Done" state that the process puts in the Resolved category counts as done.
19+
- `ado_work_item`: names of up to 40 linked releases (was 10); a release deleted by retention or not readable says so.
20+
- Numbered lists keep their numbering (`<ol start="3">`).
21+
- `ado_pr_update`: `update` adds reviewers, `requiredReviewers` (on create and update) makes them required,
22+
`autocomplete` (merge strategy, delete source branch, text = merge message) and `cancel_autocomplete`.
23+
- A parameter a tool does not have is reported with the tool's parameters instead of being dropped (a conversation
24+
started before an update still sees the old tool descriptions).
25+
326
## 0.9.1 — 2026-10-19
427

528
- `ado_trace` always answers: on an item with many links (pull requests, commits, builds, releases) the slow parts

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ What each MCP tool answers, when Claude should reach for it, and the CLI command
218218
| `ado_trace` | was it done as asked, and where is it: the acceptance criteria (from the parent for a task) and whether they changed after coding started; changesets, commits and pull requests linked to the item and its tasks with the X++ objects they touch; builds (also those deleted by retention); every release stage of the code's branches with **YES / NOT YET**, labelled by the environment map (`staging` → UAT); for Git, whether the change is merged into each mapped branch; tests, tasks and warning signals | "did they do what I asked", "is it on UAT yet" | `adolens trace 123` |
219219
| `ado_changes` | the files of a changeset (`523`), pull request (`PR 482`) or commit (sha + `repo`) with X++ objects and their added / changed / removed methods; `file` gives the diff of one file — for AOT XML per method plus the metadata (fields, controls, properties) without raw XML noise | reading what exactly changed | `adolens changes 523`, `adolens changes 523 --file AxClass/SalesTable_Extension.xml` |
220220
| `ado_pr` | without id: pull requests waiting for my review and mine (`list=active`: all); `merged=<branch>`: those completed into a branch (`since`, `top`, `repo`) with their work items; with id: status, reviewers and votes, checks (build, work item linking, reviewers), linked work items, open comment threads written by people (not system notes) | code review, "what is blocking my PR" | `adolens pr`, `adolens pr 482` |
221-
| `ado_pr_update` | `create` (repo, source, target, title, markdown text, work items, reviewers, draft, tags), `update` (title, description, link work items - for branch policies), `comment` (general or on a file and line), `reply`, `resolve`, `vote`, `tag`, `publish`, `complete`, `abandon`; `@[name]` notifies | reviewing, opening and finishing PRs | — |
221+
| `ado_pr_update` | `create` (repo, source, target, title, markdown text, work items, reviewers, draft, tags), `update` (title, description, reviewers, link work items - for branch policies), `autocomplete` / `cancel_autocomplete` (merge strategy, delete the source branch, merge message), reviewers optional or required, `comment` (general or on a file and line), `reply`, `resolve`, `vote`, `tag`, `publish`, `complete`, `abandon`; `@[name]` notifies | reviewing, opening and finishing PRs | — |
222222
| `ado_pipeline` | recent builds (of a pipeline, a branch); with `build`: the failed stage, job and steps, their errors, and the lines of the log that report errors (MSBuild noise cut); `artifacts=true` lists the build's artifacts, `artifact=<name>` the files in one (`part=` reads a file), `save=true` saves it to disk | "why is the build red", getting a package or a log | `adolens pipeline 900`, `adolens pipeline 900 --artifact drop --save` |
223223
| `ado_pipeline_run` | queues a pipeline by name or id, optionally on a branch, with variables | re-running a build | — |
224224
| `ado_wiki` | the project wiki: page tree (`depth`), one page as markdown with its version and subpages, or search across the project's wikis with snippets; long pages are cut unless `detail=full` | "how does X work", finding documentation | `adolens wiki`, `adolens wiki "Team/Setup"`, `adolens wiki --search "dual write"` |

‎README.pl.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ Na co odpowiada każde narzędzie MCP, kiedy Claude powinien po nie sięgnąć i
219219
| `ado_trace` | czy zrobiono to, o co proszono, i gdzie to jest: kryteria akceptacji (dla zadania — z elementu nadrzędnego) i to, czy zmieniły się po rozpoczęciu prac; changesety, commity i pull requesty podpięte pod element i jego zadania, z obiektami X++, których dotyczą; buildy (także usunięte przez retencję); każdy etap release'u gałęzi tego kodu z **TAK / JESZCZE NIE** i etykietą z mapy środowisk (`staging` → UAT); dla Gita — czy zmiana jest scalona do każdej zmapowanej gałęzi; testy, zadania i sygnały ostrzegawcze | „czy zrobili to, o co prosiłem”, „czy to już jest na UAT” | `adolens trace 123` |
220220
| `ado_changes` | pliki changesetu (`523`), pull requesta (`PR 482`) albo commita (sha + `repo`) z obiektami X++ i ich dodanymi / zmienionymi / usuniętymi metodami; `file` daje diff jednego pliku — dla AOT XML per metoda plus metadane (pola, kontrolki, właściwości) bez szumu surowego XML-a | czytanie, co dokładnie się zmieniło | `adolens changes 523`, `adolens changes 523 --file AxClass/SalesTable_Extension.xml` |
221221
| `ado_pr` | `merged=<gałąź>`: pull requesty scalone do gałęzi (`since`, `top`, `repo`) z ich work itemami; bez id: pull requesty czekające na mój przegląd i moje (`list=active`: wszystkie); z id: stan, recenzenci i głosy, kontrole (build, podpięty work item, recenzenci), podpięte work itemy, otwarte wątki pisane przez ludzi (bez wpisów systemowych) | code review, „co blokuje mój PR” | `adolens pr`, `adolens pr 482` |
222-
| `ado_pr_update` | `create` (repo, źródło, cel, tytuł, opis w markdownie, work itemy, recenzenci, szkic, tagi), `update` (tytuł, opis, podpięcie work itemów - pod polityki gałęzi), `comment` (ogólny albo na pliku i linii), `reply`, `resolve`, `vote`, `tag`, `publish`, `complete`, `abandon`; `@[imię]` wysyła powiadomienie | przegląd, zakładanie i kończenie PR-ów | — |
222+
| `ado_pr_update` | `create` (repo, źródło, cel, tytuł, opis w markdownie, work itemy, recenzenci, szkic, tagi), `update` (tytuł, opis, recenzenci, podpięcie work itemów - pod polityki gałęzi), `autocomplete` / `cancel_autocomplete` (strategia scalenia, usunięcie gałęzi źródłowej, komunikat), recenzenci opcjonalni albo wymagani, `comment` (ogólny albo na pliku i linii), `reply`, `resolve`, `vote`, `tag`, `publish`, `complete`, `abandon`; `@[imię]` wysyła powiadomienie | przegląd, zakładanie i kończenie PR-ów | — |
223223
| `ado_pipeline` | ostatnie buildy (pipeline'u, gałęzi); z `build`: nieudany etap, zadanie i kroki, ich błędy i linie logu zgłaszające błędy (bez szumu MSBuild); `artifacts=true` lista artefaktów buildu, `artifact=<nazwa>` pliki w nim (`part=` czyta plik), `save=true` zapisuje go na dysk | „czemu build jest czerwony”, pobranie paczki lub logu | `adolens pipeline 900`, `adolens pipeline 900 --artifact drop --save` |
224224
| `ado_pipeline_run` | uruchamia pipeline po nazwie albo id, opcjonalnie na gałęzi, ze zmiennymi | ponowne puszczenie buildu | — |
225225
| `ado_wiki` | wiki projektu: drzewo stron (`depth`), strona jako markdown z wersją i podstronami albo wyszukiwanie we wszystkich wiki projektu z fragmentami; długie strony są ucinane, chyba że `detail=full` | „jak działa X”, szukanie dokumentacji | `adolens wiki`, `adolens wiki "Team/Setup"`, `adolens wiki --search "dual write"` |

‎src/AdoLens/AdoLens.csproj‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
<AssemblyTitle>ADO Lens for Azure DevOps</AssemblyTitle>
2424
<Description>Azure DevOps (work items, boards, wiki, Git and TFVC, pipelines) served to AI assistants over MCP</Description>
2525
<Copyright>Copyright © 2026 WillowDev</Copyright>
26-
<Version>0.9.1</Version>
26+
<Version>0.9.2</Version>
2727
</PropertyGroup>
2828

2929
<ItemGroup>

‎src/AdoLens/Boards.cs‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,10 @@ static string Category(Snapshot s, JsonElement wi)
194194
{
195195
var type = s.FindType(WorkItems.Field(wi, "System.WorkItemType") ?? "");
196196
var state = WorkItems.Field(wi, "System.State");
197-
return type?.States.FirstOrDefault(x => x.Name.Equals(state, StringComparison.OrdinalIgnoreCase))?.Category
197+
var category = type?.States.FirstOrDefault(x => x.Name.Equals(state, StringComparison.OrdinalIgnoreCase))?.Category;
198+
// Some processes put "Done" in the Resolved category (waiting for a check); for the people it is done.
199+
if (category == "Resolved" && GuessCategory(state) == "Completed") return "Completed";
200+
return category
198201
// A type or state this project does not know (an item of another project in the sprint): any type with that state.
199202
?? s.Types.SelectMany(t => t.States).FirstOrDefault(x => x.Name.Equals(state, StringComparison.OrdinalIgnoreCase))?.Category
200203
?? GuessCategory(state);

‎src/AdoLens/Formatting.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ static string FieldLine(Snapshot s, TypeField f)
8686
{
8787
var def = s.Fields.GetValueOrDefault(f.Ref);
8888
var parts = new List<string> { $"{f.Name} ({f.Ref})", TypeName(def) };
89-
if (f.Required) parts.Add("required");
89+
if (f.Required) parts.Add(WorkItems.FilledByAzureDevOps(f.Ref) ? "required, filled by Azure DevOps" : "required");
9090
if (def?.ReadOnly == true) parts.Add("read-only");
9191
if (!string.IsNullOrEmpty(f.Default)) parts.Add($"default {f.Default}");
9292
var line = string.Join(", ", parts);

‎src/AdoLens/Html.cs‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ public static partial class Html
3232
private static partial Regex BlankLines();
3333

3434
/// <summary>HTML → markdown: headings, lists, bold, links, code, tables as "a | b"; images become "[image]".</summary>
35+
[GeneratedRegex(@"\bstart\s*=\s*[""']?(\d+)", RegexOptions.IgnoreCase)]
36+
private static partial Regex OlStart();
37+
3538
public static string ToMarkdown(string? html)
3639
{
3740
if (string.IsNullOrWhiteSpace(html)) return "";
@@ -59,7 +62,13 @@ public static string ToMarkdown(string? html)
5962
case "ul" or "ol":
6063
// Only the outermost list is separated from the text; nested ones continue under their item.
6164
if (closing) { if (lists.Count > 0) lists.Pop(); if (lists.Count == 0) sb.Append('\n'); }
62-
else { if (lists.Count == 0) sb.Append('\n'); lists.Push((name == "ol", 0)); }
65+
else
66+
{
67+
if (lists.Count == 0) sb.Append('\n');
68+
// <ol start="4"> continues a numbering broken by text in between.
69+
var first = name == "ol" && OlStart().Match(attrs) is { Success: true } st && int.TryParse(st.Groups[1].Value, out var n) ? n - 1 : 0;
70+
lists.Push((name == "ol", first));
71+
}
6372
break;
6473
case "li" when !closing:
6574
var depth = Math.Max(0, lists.Count - 1);

‎src/AdoLens/McpTools.cs‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ public static Task<string> Pr(Lens lens,
366366
public static class PrTools
367367
{
368368
[McpServerTool(Name = "ado_pr_update")]
369-
[Description("Pull request actions: create (repo, source, target, title, text, workItems, reviewers, draft), update (title, text, workItems: links them), comment (text, file, line), reply (thread, text), resolve (thread, status), vote (approve|suggestions|wait|reject|reset), tag, publish, complete, abandon. @[name] notifies.")]
369+
[Description("Pull request actions: create (repo, source, target, title, text, workItems, reviewers, draft), update (title, text, workItems, reviewers), comment (text, file, line), reply (thread, text), resolve (thread, status), vote (approve|suggestions|wait|reject|reset), tag, publish, autocomplete (mergeStrategy, deleteSourceBranch, text = merge message), cancel_autocomplete, complete, abandon. @[name] notifies.")]
370370
public static Task<string> PrUpdate(Lens lens,
371371
string action,
372372
int? id = null,
@@ -382,17 +382,18 @@ public static Task<string> PrUpdate(Lens lens,
382382
string? title = null,
383383
[Description("Work item ids: 123;456.")] string? workItems = null,
384384
[Description("Names or e-mails separated by ';'.")] string? reviewers = null,
385+
[Description("Reviewers who must approve.")] string? requiredReviewers = null,
385386
bool draft = false,
386387
[Description("'a; b' adds, '-c' removes.")] string? tags = null,
387388
bool deleteSourceBranch = false,
388389
[Description("noFastForward | squash | rebase | rebaseMerge.")] string? mergeStrategy = null,
389390
string? connection = null,
390391
CancellationToken ct = default)
391-
=> McpTools.Run("ado_pr_update", new { action, id, repo, thread, file, line, vote, status, source, target, title, workItems, reviewers, draft, tags, deleteSourceBranch, mergeStrategy, connection },
392+
=> McpTools.Run("ado_pr_update", new { action, id, repo, thread, file, line, vote, status, source, target, title, workItems, reviewers, requiredReviewers, draft, tags, deleteSourceBranch, mergeStrategy, connection },
392393
() => PullRequestQueries.ActAsync(lens, connection, new PullRequestQueries.PrAction
393394
{
394395
Action = action, Id = id, Repo = repo, Text = text, Thread = thread, File = file, Line = line, Vote = vote, Status = status,
395-
Source = source, Target = target, Title = title, WorkItems = workItems, Reviewers = reviewers, Draft = draft,
396+
Source = source, Target = target, Title = title, WorkItems = workItems, Reviewers = reviewers, RequiredReviewers = requiredReviewers, Draft = draft,
396397
DeleteSourceBranch = deleteSourceBranch, MergeStrategy = mergeStrategy, Tags = tags,
397398
}, ct));
398399
}

0 commit comments

Comments
 (0)