Repository navigation
DevOps Studio v0.22.0
Added
- DevOps Studio now works across several repositories at once. The app used to point at exactly one source folder, so a feature whose code spans repositories was analyzed against a fragment of itself — silently, with nothing to tell you coverage had been lost. Settings now holds a list of source repos, and every surface that reads code reads all of them: the generator, Suite Chat, Commit Review, confidence evaluation, the code viewer and the terminal. Your existing source folder migrates by itself into a one-repo workspace, and at one repo the app looks and behaves exactly as it did.
- A Source repos block in Settings — add a folder, rename it, remove it, or point "Scan a folder…" at a parent directory and pick up every repo cloned inside it in one go. Each row shows the repo's current branch and which Azure DevOps repository it's bound to. This also closes the dead end where opening a commit review with nothing configured sent you to a Settings tab that had no source-directory control at all.
- The status bar shows and switches the branch of every repo. Past one repo the folder segment reads "N repos" and the branch segment summarises where they are — the shared branch when they agree, "N branches" when they don't — opening a list you drill into per repo. Repos move independently: a switch running in one can't cancel or steal the toast of one running in another, and the dirty-tree prompt asks about one repo at a time and names it.
- Commit Review spans the whole workspace. The commit picker merges every repo's history into one timeline, so a change that touches three repositories can finally be reviewed as one change. Every repo is guaranteed a share of the list, so a repo nobody has touched in months stays reachable instead of being crowded out by the busy ones. Which repos the reviewer may read is a separate control from which commits are under review — a commit in one repo often can't be judged without reading another that has no commit in the selection at all.
- Runs can be narrowed to the repos you care about. The generator, Suite Chat and Commit Review each carry a Repos chip row (shown past one repo): every repo is on by default, and unticking one keeps that run out of it. The generator persists the choice into its checkpoint, so a resumed run keeps the scope it started with instead of quietly widening back to everything.
- Published code links now deep-link into the right Azure DevOps repository. Each source repo binds to its ADO repo and project, matched from the repo's own
originremote against your organisation's repository list — normalised URL first, then the project and repo parsed out of either URL shape (SSH and legacyvisualstudio.comremotes never string-matched the HTTPS one), then a folder-name match that must be unique across the organisation, so a name two projects share is left unbound rather than bound to the wrong one. Every link into a repository living outside the connection's project was previously dead. Settings' repo row is the manual override, with a repository picker grouped by project and a "Detect from remote" action. - "Get source code…" is reachable once you already have a repo. It used to hang off the status-bar segment that only appears when no repo is configured, so it vanished the moment a tester had one. It's now in the repo list footer, in the Settings source-repos block, and still in the empty state.
- The custom-provider Test button now performs a real model call. It fired a bare reachability ping that discarded the response, sent no authorization header, and reported "Reachable — server responded" for any reply at all — so a wrong key, a 404 and a 500 all read as success, and the model ID was never exercised. Test now runs the same one-token generation a real run would, against the base URL, key and model you've drafted, and reports what actually came back. The Model ID field also suggests the models your endpoint lists, while still accepting anything you type.
- The AI's read-only git access is considerably wider — 31 subcommands instead of 19, so it can answer questions with
for-each-ref,show-branch,check-ignore,check-attrand the diff plumbing rather than working around their absence. Write forms remain blocked outright, andls-remotestays out because it reaches the network, where a credential prompt can hang the call.
Fixed
- The AI's read gate could be escaped three ways, and each is now closed. A symlink or junction inside a repo (
vendor/cachepointing at your home directory) made every file on the machine readable through a path that looked entirely repo-local — the gate checked the literal path and the read followed the link. It now runs on the resolved path, and the read uses that same resolved form so it can't land on a different file than the one just cleared. Separately, files the app refuses to open by name were still readable through the command runner (cat .env,git show HEAD:.env,git log -p credentials.pem), and the source-code exemption that keepsCredentials.csreadable also let.env.tsand.npmrc.jsthrough. Finally,git --git-dir=C:\…\other-repo\.git logpointed the whole command at a different repository, because the guard checking for escapes never looked at a path glued to a flag. - Every Azure DevOps deep link built from a published source link was dead. Publishing escaped each
/in a path or branch name and nothing ever unescaped it, so the links read back mangled. Two more defects in the same block: unticking "Tag with source branch" — or generating from a non-git or detached-HEAD folder — published links the app itself then refused to read back, and the commit stamp was written empty even though publish had already captured it. - Code links were stamped with the wrong repo's branch. A case citing two repositories recorded both links against whichever repo happened to be first. Each link now carries the branch and commit of the repo it actually names, read from that repo's working directory at publish time, and one unreadable folder only costs its own links their stamp.
- Confidence verdicts read as permanently stale, and every bulk run re-scored the whole suite. A verdict was compared against a single repo's HEAD regardless of what it had read, so past one repo the "skip verdicts that are still fresh" gate never fired — on the app's most expensive path. A verdict now records the repos its own evidence cites and goes stale only when one of those moves. Re-checking that also used to cost a git call per repo per case; a bulk run resolves it once.
- A suggested fix could be written into the wrong repository. Commit Review's Apply button resolved the patch path against whatever the status bar pointed at rather than the review's own repos.
- Reopening a saved review bound it to whatever repo was current instead of the repos it was actually run against.
- A terminal's Quick Prompts injected another repo's base branch into its templates, because the strip read the global source folder rather than the shell's own working directory.
- Assignee pickers kept offering the previous project's people after a connection change. The roster is per project and was cached for the whole session, so the names on offer weren't assignable on the work items being created.
- Azure DevOps errors lost the detail that explains them. A rate-limited request reached you as "retry in undefineds" and a server error dropped the excerpt saying what ADO had actually rejected — the error fields were serialized in the wrong case for the frontend reading them.
- The AI wasted steps on programs that aren't there. Six of the tools its prompts advertised don't exist on a stock Windows PATH, and
findandtreeresolve to unrelated Microsoft binaries of the same name, sofind . -name "*.ts"failed as "FIND: Parameter format not correct". Each attempt burned a step against the run's budget and stayed in the transcript to be re-sent on every later one. The prompts now lead with git and the app's own read tools, and a missing program points at the tool that replaces it. This worked in development and failed in the shipped app, which is why it survived so long. - A generated case could be dropped silently when the model followed the new path convention, leaving a run that produced nothing and no explanation.
- A repo-scope chip could re-include repos you had deselected, when the registry had changed underneath it.
- Code search hid whole repositories. Search results were concatenated per repo before being truncated, so one repo's eighty matches could bury another's entirely; they're now interleaved.
- The settings file was rewritten and broadcast on every launch, because the saved repos and the freshly-normalised ones were compared as text and their keys came back in a different order.
- The empty state mounted two copies of the Get source code wizard, so a request from the Settings window opened one while a click opened the other.
- The branch picker hid any saved-but-unlisted branch whose name appeared inside its "current branch" sentinel value — a real branch called
currentvanished from the list rather than being added to it.
Changed
- Files are addressed as
<repo>/<path within repo>throughout — in prompts, in the model's answers, in code links, in the code viewer's header and in tab titles. Tab titles only pick up the prefix when two open viewers collide on the same filename. - A bare filename opens the copy in the repo that owns it. The code viewer searches every configured repo instead of silently opening the first one's.
- There is no fixed tracking-branch option any more. Code links always track the live branch of the repo each link names; a repo with no branch (detached HEAD, or not a git repo) publishes without one rather than claiming a
mainyou never generated from. The per-run "Tag with source branch" switch still controls whether any provenance is stamped at all. - The status bar's folder segment opens Settings past one repo, since picking a directory there would collapse the workspace to that single folder.
- Every repo-git reader shares one poll instead of running its own timer over the same folders.
- A run interrupted by an older version can't be resumed after updating to this one — the saved checkpoint format changed. Interrupted runs started on 0.22.0 onwards resume as normal.
macOS users: the .dmg / .app bundles are unsigned. See docs/install-macos.md for how to bypass Gatekeeper on first launch.