Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
# Changelog

## 0.9.2 — 2026-10-19

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).

## 0.9.1 — 2026-10-19

- `ado_trace` always answers: on an item with many links (pull requests, commits, builds, releases) the slow parts
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ What each MCP tool answers, when Claude should reach for it, and the CLI command
| `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` |
| `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` |
| `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` |
| `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 | — |
| `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 | — |
| `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` |
| `ado_pipeline_run` | queues a pipeline by name or id, optionally on a branch, with variables | re-running a build | — |
| `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"` |
Expand Down
2 changes: 1 addition & 1 deletion README.pl.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ Na co odpowiada każde narzędzie MCP, kiedy Claude powinien po nie sięgnąć i
| `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` |
| `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` |
| `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` |
| `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 | — |
| `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 | — |
| `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` |
| `ado_pipeline_run` | uruchamia pipeline po nazwie albo id, opcjonalnie na gałęzi, ze zmiennymi | ponowne puszczenie buildu | — |
| `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"` |
Expand Down
2 changes: 1 addition & 1 deletion src/AdoLens/AdoLens.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<AssemblyTitle>ADO Lens for Azure DevOps</AssemblyTitle>
<Description>Azure DevOps (work items, boards, wiki, Git and TFVC, pipelines) served to AI assistants over MCP</Description>
<Copyright>Copyright © 2026 WillowDev</Copyright>
<Version>0.9.1</Version>
<Version>0.9.2</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
5 changes: 4 additions & 1 deletion src/AdoLens/Boards.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,10 @@ static string Category(Snapshot s, JsonElement wi)
{
var type = s.FindType(WorkItems.Field(wi, "System.WorkItemType") ?? "");
var state = WorkItems.Field(wi, "System.State");
return type?.States.FirstOrDefault(x => x.Name.Equals(state, StringComparison.OrdinalIgnoreCase))?.Category
var category = type?.States.FirstOrDefault(x => x.Name.Equals(state, StringComparison.OrdinalIgnoreCase))?.Category;
// Some processes put "Done" in the Resolved category (waiting for a check); for the people it is done.
if (category == "Resolved" && GuessCategory(state) == "Completed") return "Completed";
return category
// A type or state this project does not know (an item of another project in the sprint): any type with that state.
?? s.Types.SelectMany(t => t.States).FirstOrDefault(x => x.Name.Equals(state, StringComparison.OrdinalIgnoreCase))?.Category
?? GuessCategory(state);
Expand Down
2 changes: 1 addition & 1 deletion src/AdoLens/Formatting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ static string FieldLine(Snapshot s, TypeField f)
{
var def = s.Fields.GetValueOrDefault(f.Ref);
var parts = new List<string> { $"{f.Name} ({f.Ref})", TypeName(def) };
if (f.Required) parts.Add("required");
if (f.Required) parts.Add(WorkItems.FilledByAzureDevOps(f.Ref) ? "required, filled by Azure DevOps" : "required");
if (def?.ReadOnly == true) parts.Add("read-only");
if (!string.IsNullOrEmpty(f.Default)) parts.Add($"default {f.Default}");
var line = string.Join(", ", parts);
Expand Down
11 changes: 10 additions & 1 deletion src/AdoLens/Html.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public static partial class Html
private static partial Regex BlankLines();

/// <summary>HTML → markdown: headings, lists, bold, links, code, tables as "a | b"; images become "[image]".</summary>
[GeneratedRegex(@"\bstart\s*=\s*[""']?(\d+)", RegexOptions.IgnoreCase)]
private static partial Regex OlStart();

public static string ToMarkdown(string? html)
{
if (string.IsNullOrWhiteSpace(html)) return "";
Expand Down Expand Up @@ -59,7 +62,13 @@ public static string ToMarkdown(string? html)
case "ul" or "ol":
// Only the outermost list is separated from the text; nested ones continue under their item.
if (closing) { if (lists.Count > 0) lists.Pop(); if (lists.Count == 0) sb.Append('\n'); }
else { if (lists.Count == 0) sb.Append('\n'); lists.Push((name == "ol", 0)); }
else
{
if (lists.Count == 0) sb.Append('\n');
// <ol start="4"> continues a numbering broken by text in between.
var first = name == "ol" && OlStart().Match(attrs) is { Success: true } st && int.TryParse(st.Groups[1].Value, out var n) ? n - 1 : 0;
lists.Push((name == "ol", first));
}
break;
case "li" when !closing:
var depth = Math.Max(0, lists.Count - 1);
Expand Down
7 changes: 4 additions & 3 deletions src/AdoLens/McpTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ public static Task<string> Pr(Lens lens,
public static class PrTools
{
[McpServerTool(Name = "ado_pr_update")]
[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.")]
[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.")]
public static Task<string> PrUpdate(Lens lens,
string action,
int? id = null,
Expand All @@ -382,17 +382,18 @@ public static Task<string> PrUpdate(Lens lens,
string? title = null,
[Description("Work item ids: 123;456.")] string? workItems = null,
[Description("Names or e-mails separated by ';'.")] string? reviewers = null,
[Description("Reviewers who must approve.")] string? requiredReviewers = null,
bool draft = false,
[Description("'a; b' adds, '-c' removes.")] string? tags = null,
bool deleteSourceBranch = false,
[Description("noFastForward | squash | rebase | rebaseMerge.")] string? mergeStrategy = null,
string? connection = null,
CancellationToken ct = default)
=> McpTools.Run("ado_pr_update", new { action, id, repo, thread, file, line, vote, status, source, target, title, workItems, reviewers, draft, tags, deleteSourceBranch, mergeStrategy, connection },
=> 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 },
() => PullRequestQueries.ActAsync(lens, connection, new PullRequestQueries.PrAction
{
Action = action, Id = id, Repo = repo, Text = text, Thread = thread, File = file, Line = line, Vote = vote, Status = status,
Source = source, Target = target, Title = title, WorkItems = workItems, Reviewers = reviewers, Draft = draft,
Source = source, Target = target, Title = title, WorkItems = workItems, Reviewers = reviewers, RequiredReviewers = requiredReviewers, Draft = draft,
DeleteSourceBranch = deleteSourceBranch, MergeStrategy = mergeStrategy, Tags = tags,
}, ct));
}
Expand Down
Loading