Packages
@argus/ado
Implementations of the AdoClient contract from @argus/shared — the one
gateway to Azure DevOps. It exists so ADO's REST surface, auth modes, and
retry behaviour are dealt with in exactly one place, and so every other
package can run against an in-memory ADO instead.
Place in the system
Consumed by the ingress (re-fetching PRs/threads for actionability), the
worker (reads and writes), @argus/mcp-ado (tool execution), and the eval
harness (FakeAdoClient as the target evals post to). Depends only on
@argus/shared, @azure/identity, and the official azure-devops-node-api
SDK — a thin adapter, not hand-rolled REST.
The two implementations
| Implementation | Notes |
|---|---|
RestAdoClient |
ADO REST 7.1 via the official SDK's WebApi/GitApi, with retry/backoff and typed errors (AdoAuthError, AdoNotFoundError, AdoRateLimitError, …). Auth comes from authFromEnv(): Entra ID primary (DefaultAzureCredential against ADO_ENTRA_SCOPE, the standard AZURE_* vars or managed identity) with PAT fallback (ADO_AUTH_MODE=pat). Credentials are host-side only — they never enter model context (PRD §9.3). |
FakeAdoClient |
In-memory, seeded with a demo PR (FakePrSeed), behaviourally faithful (threads, replies, resolution, iterations). This is a shipped feature, not a test file: MOCK_ADO=1 selects it in real wiring, and evals depend on it so a live eval can never post to real ADO. |
Key exports
RestAdoClient,FakeAdoClient,FAKE_ARGUS_IDENTITY.authFromEnv(),entraAdoAuth(),patAuth(),ADO_ENTRA_SCOPE.parseMentions()(wire.ts) — mention detection from the comment's mentioned-identity data, never by string-matching names in prose.- The typed error hierarchy under
AdoError. - Re-exports of the contract types (
AdoClient,PrMetadata,AdoThread, …) so callers import implementation and contract together.
How it's tested
rest.test.ts drives RestAdoClient against a scripted GitApiSurface
(retry, error mapping, thread wiring); entraAuth.test.ts covers the
Entra/PAT selection; fake.test.ts pins FakeAdoClient's behaviour to the
contract so fakes and reality cannot drift apart silently.
