Skip to content

fix(azure-devops): az repos pr create links the new pull request to the thread - #36292

Open
juliusmarminge wants to merge 1 commit into
mainfrom
factory/pr-31191-a1794597635
Open

juliusmarminge wants to merge 1 commit into
mainfrom
factory/pr-31191-a1794597635

Conversation

@juliusmarminge

Copy link
Copy Markdown
Member

Rebuilt from origin/main as one commit; the first attempt's branch was not used as a base, only its diff was read. Cause: the Azure DevOps definition set no changeRequestCreateCommand, and changeRequestsCreatedBy in PullRequestSyncReactor only reads a URL on a line of its own, while az repos pr create prints indented JSON whose url is the REST address. Fix: the definition now sets the create command and a new optional changeRequestCreateOutputUrls, which reads each top-level JSON object in the output and builds the web URL with the existing azureDevOpsPullRequestWebUrl (moved unchanged from server/ to shared/pullRequestUrls.ts so the definition can use it). The reviewers' open finding (az repos pr show --id "$PR_ID" && az repos pr create --title test --output none linking existing PR 42) is settled by a new optional changeRequestPrintCommand: Azure sets it to any az repos pr subcommand, az devops invoke or az rest, and when one runs beside the create nothing of that host is linked, since all of them print an existing pull request in the same JSON form. That is broader than the first attempt's list-only guard and is covered by a test row that fails without it. Printed URLs are also counted per host against that host's own create commands instead of against the total, so an Azure create cannot vouch for a second GitHub URL; that is a small tightening for mixed-host scripts that main did not have. Limit: an indented JSON pull request printed by a non-az command (for example cat saved.json) beside a create would still be read, the same class of gap GitHub has with cat urls.txt. docs/user/source-control.md now names az repos pr create among the commands that link automatically. No UI change.

Fixes #31166

Supersedes #31191. The change is @juliusmarminge's; their commits are kept.

Reproduction on main

In T3 Code, open a project backed by an Azure DevOps Services repository with an authenticated Azure CLI. Push a feature branch and ask an agent in a thread to run az repos pr create --source-branch feature --target-branch main --title "Linking reproduction", retaining default JSON output and without calling link_pull_request. Inspect the thread's linked pull requests: main leaves the new PR unlinked; this change should add it automatically. These steps were derived from the issue and diff, not executed.

Evidence

Being captured: before and after in the real app. This section is filled in before the pull request can merge.

Tests

vp test run src/orchestration-v2/PullRequestSyncReactor.test.ts -t "links what the command created" in apps/server: 22 passed, including 3 new table rows (Azure create after a push links PR 42; az repos pr show beside a silent create links nothing; an existing GitHub URL beside GitHub and Azure creates links nothing). Verified failing-first: with the source changes stashed the Azure create row fails; with only changeRequestPrintCommand disabled the show row fails. vp run check:changed: format, lint, knip, graphql, typecheck (19 packages) and tests (4 files, 110 tests) all pass. The pre-commit hook (fmt, lint, knip) passed.

Not in this change

  • No Azure-specific unit test for azureDevOpsPrintedPullRequestUrls in the package; the reactor table rows exercise it end to end at the one layer that failed on main.
  • Compact output (az repos pr create --output json piped through jq -c, --output tsv, --query) is not read, so those creates stay unlinked rather than guessed at.
  • The first attempt's rows for az repos pr list beside a create and for a GitHub create after an Azure list were not carried over; the show row covers the same guard, and the Azure list case is unchanged existing behaviour.

Who did the work

  • Written by Claude Fable 5.2, in Claude Code
  • Reviewed by GPT-6.1 Sol, in Codex, and by Claude Opus 5.5, each on its own
  • Proof captured by GPT-6.1 Sol and checked by Claude Opus 5.5

Run by the t3code factory in T3 Code.

…he thread

An agent that opened a pull request with `az repos pr create` left its thread
without a link: the Azure DevOps definition named no create command, and the
reactor only reads a URL on a line of its own, while `az` prints the pull
request as JSON with its REST address.

The definition now names the create command and reads the web URL out of that
JSON. Every `az repos pr` subcommand prints an existing pull request in the
same form, so one beside the create (`show`, `list`, `update`) leaves nothing
linked. Printed URLs are now counted against each host's own create commands,
so an Azure create cannot vouch for a second GitHub URL.

Fixes #31166

Co-Authored-By: Claude Fable 5.2 <[email protected]>
@github-actions github-actions Bot added vouch:trusted Author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Nov 13, 2026
@macroscopeapp

macroscopeapp Bot commented Nov 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at f36ea27

Macroscope's review found this PR approvable — Azure DevOps pull requests created by an agent are now linked to the conversation using parsed CLI output. The change reuses existing linking and refresh behavior, with guards against treating existing pull requests as newly created.

You can add or adjust custom eligibility rules. Learn more.

@github-actions

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 5.0 KiB 5.0 KiB 0 B (0.0%) 6.8 KiB ✅
Codex Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Codex Live turn WebSocket wire 1.2 KiB 1.2 KiB 0 B (0.0%) 2.0 KiB ✅
Codex Live turn WebSocket decoded 21.5 KiB 21.5 KiB 0 B (0.0%) 24.4 KiB ✅
Codex Live turn messages 1 1 0 (0.0%) 8 ✅
Claude Total thread wire 5.0 KiB 5.0 KiB 0 B (0.0%) 6.8 KiB ✅
Claude Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Claude Live turn WebSocket wire 1.2 KiB 1.2 KiB 0 B (0.0%) 2.0 KiB ✅
Claude Live turn WebSocket decoded 21.9 KiB 21.9 KiB 0 B (0.0%) 24.4 KiB ✅
Claude Live turn messages 1 1 0 (0.0%) 8 ✅

Other scenarios

All 64 scenario measurements match main.

All 64 scenario measurements
Provider Scenario Metric Main baseline This PR Impact PR ceiling
Codex short turn resume WebSocket decoded 10.5 KiB 10.5 KiB 0 B (0.0%) 12.7 KiB ✅
Codex short turn resume WebSocket messages 2 2 0 (0.0%) 2 ✅
Codex long turn running, cold open HTTP decoded 281.7 KiB 281.7 KiB 0 B (0.0%) 302.7 KiB ✅
Codex long turn running, cold open rows 75 75 0 (0.0%) 75 ✅
Codex long turn running, history page HTTP decoded 92.4 KiB 92.4 KiB 0 B (0.0%) 107.4 KiB ✅
Codex long turn running, history page rows 75 75 0 (0.0%) 75 ✅
Codex long turn finished, cold open HTTP decoded 381.5 KiB 381.5 KiB 0 B (0.0%) 410.2 KiB ✅
Codex long turn finished, cold open rows 151 151 0 (0.0%) 151 ✅
Codex long turn finished, socket cold open WebSocket decoded 381.6 KiB 381.6 KiB 0 B (0.0%) 410.2 KiB ✅
Codex long turn finished, socket cold open WebSocket messages 2 2 0 (0.0%) 2 ✅
Codex long turn finished, socket cold open rows 151 151 0 (0.0%) 151 ✅
Codex long turn finished, work page HTTP decoded 186.2 KiB 186.2 KiB 0 B (0.0%) 200.2 KiB ✅
Codex long turn finished, work page rows 150 150 0 (0.0%) 150 ✅
Codex idle thread resume WebSocket decoded 65 B 65 B 0 B (0.0%) 200 B ✅
Codex idle thread resume WebSocket messages 1 1 0 (0.0%) 1 ✅
Codex fleet shell snapshot HTTP decoded 42.4 KiB 42.4 KiB 0 B (0.0%) 53.7 KiB ✅
Codex fleet shell snapshot rows 27 27 0 (0.0%) 27 ✅
Codex fleet shell subscribe WebSocket decoded 65 B 65 B 0 B (0.0%) 200 B ✅
Codex fleet shell subscribe WebSocket messages 1 1 0 (0.0%) 1 ✅
Codex fleet shell resume check HTTP decoded 18 B 18 B 0 B (0.0%) 100 B ✅
Codex fleet shell resume check rows 0 0 0 0 ✅
Codex stale shell reload HTTP decoded 42.4 KiB 42.4 KiB 0 B (0.0%) 53.7 KiB ✅
Codex stale shell reload rows 27 27 0 (0.0%) 27 ✅
Codex stale shell resume WebSocket decoded 140 B 140 B 0 B (0.0%) 400 B ✅
Codex stale shell resume WebSocket messages 2 2 0 (0.0%) 2 ✅
Codex stale todo list cold open HTTP decoded 72.4 KiB 72.4 KiB 0 B (0.0%) 83.0 KiB ✅
Codex stale todo list cold open rows 75 75 0 (0.0%) 75 ✅
Codex stale todo list cold open nodes 2 2 0 (0.0%) 4 ✅
Codex stale todo list cold open subagents 2 2 0 (0.0%) 4 ✅
Codex stale todo list cold open plans 1 1 0 (0.0%) 2 ✅
Codex stale todo list cold open providerTurns 1 1 0 (0.0%) 2 ✅
Codex stale todo list cold open checkpoints 1 1 0 (0.0%) 2 ✅
Claude short turn resume WebSocket decoded 10.6 KiB 10.6 KiB 0 B (0.0%) 12.7 KiB ✅
Claude short turn resume WebSocket messages 2 2 0 (0.0%) 2 ✅
Claude long turn running, cold open HTTP decoded 283.3 KiB 283.3 KiB 0 B (0.0%) 302.7 KiB ✅
Claude long turn running, cold open rows 75 75 0 (0.0%) 75 ✅
Claude long turn running, history page HTTP decoded 93.4 KiB 93.4 KiB 0 B (0.0%) 107.4 KiB ✅
Claude long turn running, history page rows 75 75 0 (0.0%) 75 ✅
Claude long turn finished, cold open HTTP decoded 384.2 KiB 384.2 KiB 0 B (0.0%) 410.2 KiB ✅
Claude long turn finished, cold open rows 151 151 0 (0.0%) 151 ✅
Claude long turn finished, socket cold open WebSocket decoded 384.3 KiB 384.3 KiB 0 B (0.0%) 410.2 KiB ✅
Claude long turn finished, socket cold open WebSocket messages 2 2 0 (0.0%) 2 ✅
Claude long turn finished, socket cold open rows 151 151 0 (0.0%) 151 ✅
Claude long turn finished, work page HTTP decoded 188.1 KiB 188.1 KiB 0 B (0.0%) 200.2 KiB ✅
Claude long turn finished, work page rows 150 150 0 (0.0%) 150 ✅
Claude idle thread resume WebSocket decoded 66 B 66 B 0 B (0.0%) 200 B ✅
Claude idle thread resume WebSocket messages 1 1 0 (0.0%) 1 ✅
Claude fleet shell snapshot HTTP decoded 43.0 KiB 43.0 KiB 0 B (0.0%) 53.7 KiB ✅
Claude fleet shell snapshot rows 27 27 0 (0.0%) 27 ✅
Claude fleet shell subscribe WebSocket decoded 66 B 66 B 0 B (0.0%) 200 B ✅
Claude fleet shell subscribe WebSocket messages 1 1 0 (0.0%) 1 ✅
Claude fleet shell resume check HTTP decoded 18 B 18 B 0 B (0.0%) 100 B ✅
Claude fleet shell resume check rows 0 0 0 0 ✅
Claude stale shell reload HTTP decoded 43.0 KiB 43.0 KiB 0 B (0.0%) 53.7 KiB ✅
Claude stale shell reload rows 27 27 0 (0.0%) 27 ✅
Claude stale shell resume WebSocket decoded 140 B 140 B 0 B (0.0%) 400 B ✅
Claude stale shell resume WebSocket messages 2 2 0 (0.0%) 2 ✅
Claude stale todo list cold open HTTP decoded 73.4 KiB 73.4 KiB 0 B (0.0%) 83.0 KiB ✅
Claude stale todo list cold open rows 75 75 0 (0.0%) 75 ✅
Claude stale todo list cold open nodes 2 2 0 (0.0%) 4 ✅
Claude stale todo list cold open subagents 2 2 0 (0.0%) 4 ✅
Claude stale todo list cold open plans 1 1 0 (0.0%) 2 ✅
Claude stale todo list cold open providerTurns 1 1 0 (0.0%) 2 ✅
Claude stale todo list cold open checkpoints 1 1 0 (0.0%) 2 ✅

Baseline: 9efd960 · PR result: f36ea27 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@juliusmarminge

Copy link
Copy Markdown
Member Author

The automated pipeline stopped on this pull request and will not merge it:

the fix is written and reviewed, but proving it needs something no worker has:

  • Permanent blocker: the reproduction requires an authenticated Azure DevOps Services account and repository with permission to push a feature branch and create a pull request. No Azure credentials or configuration are available on this VM; Azure CLI is also absent. Neither the base failure nor the head success was observed.

It stays open for a person to finish or close.

@coderabbitai

coderabbitai Bot commented Nov 13, 2026

Copy link
Copy Markdown
Contributor

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

The change adds Azure DevOps pull-request URL extraction from CLI output and integrates it with thread linking. The sync reactor now processes create-command output separately for each source-control definition.

Changes: Azure DevOps pull-request linking

Layer / File(s) Summary
URL contract and extraction
packages/source-control-core/src/shared/definition.ts, packages/source-control-azure-devops/src/shared/pullRequestUrls.ts
SourceControlDefinition now supports extracting URLs from command output and matching commands that print existing requests. Azure DevOps helpers construct pull-request URLs and extract them from printed JSON objects.
Azure DevOps command wiring
packages/source-control-azure-devops/src/shared/definition.ts, packages/source-control-azure-devops/src/server/azureDevOpsPullRequests.ts, packages/source-control-azure-devops/src/server/azureDevOpsPullRequestJson.ts
The Azure DevOps definition recognizes az repos pr create and related print commands. Server modules use the shared URL-construction function.
Reactor linking and validation
apps/server/src/orchestration-v2/PullRequestSyncReactor.ts, apps/server/src/orchestration-v2/PullRequestSyncReactor.test.ts, docs/user/source-control.md
The reactor handles URLs per source-control definition and checks create-command counts. Tests cover Azure DevOps JSON output and existing pull requests. The documentation lists az repos pr create as a command that automatically links a created pull request.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant AzureCLI
  participant AzureDevOpsDefinition
  participant PullRequestSyncReactor
  AzureCLI->>AzureDevOpsDefinition: Print pull-request JSON
  AzureDevOpsDefinition->>PullRequestSyncReactor: Extract pull-request URL
  PullRequestSyncReactor->>PullRequestSyncReactor: Match URL to create command
Loading

Suggested reviewers: only21mil, t3dotgg, bil0000

Merge Risk: Minimal · up to f36ea

Running az repos pr create in a thread now links the created Azure DevOps pull request, and each host's create commands are checked only against that host's URLs. One contrived case remains, where unrelated command output could be linked as the created pull request. It is documented as accepted and is low impact, so the change is ready to merge.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title names the Azure DevOps fix and the main behavior: az repos pr create links the new pull request to the thread. It follows the conventional commit form and matches the linked issue and the ch…
Description check Passed The description follows the repository template. It has a clear Problem (Azure DevOps definition lacks a create command and JSON output is not read), a Change section explaining the fix and the helper…
Linked Issues check Passed Directly linked issue #31166 has one coding requirement: az repos pr create in an Azure DevOps thread must link the new pull request to the thread. The issue names two causes: the Azure DevOps defin…
Out of Scope Changes check Passed Each changed area connects to #31166 or to the PR objectives:
- definition.ts (Azure DevOps) adds the create command and printed-output handling. This is the core fix.
- pullRequestUrls.ts is new …
Full details: Title check

Explanation

The title names the Azure DevOps fix and the main behavior: az repos pr create links the new pull request to the thread. It follows the conventional commit form and matches the linked issue and the changeset. It is specific enough for a teammate scanning history.

Full details: Description check

Explanation

The description follows the repository template. It has a clear Problem (Azure DevOps definition lacks a create command and JSON output is not read), a Change section explaining the fix and the helper move, a Scope section linking issue #31166, and a Verification section with specific focused tests and results. It also names the model and harness used. The Evidence section is explicitly marked as pending, and the Scope section does not follow the template's guidance to state why a small fix needs no issue. Those gaps are minor, since the issue is linked. The Evidence placeholder is a known gap that the author states must be filled before merge.

Full details: Linked Issues check

Explanation

Directly linked issue #31166 has one coding requirement: az repos pr create in an Azure DevOps thread must link the new pull request to the thread. The issue names two causes: the Azure DevOps definition does not set changeRequestCreateCommand, and the reactor reads only standalone URL lines, while az repos pr create prints indented JSON with pullRequestId.

The change addresses both causes:

  • packages/source-control-azure-devops/src/shared/definition.ts sets a create-command matcher for az repos pr create.
  • changeRequestCreateOutputUrls (new optional definition field) runs azureDevOpsPrintedPullRequestUrls, which decodes top-level JSON pull-request objects and builds web URLs with azureDevOpsPullRequestWebUrl.
  • PullRequestSyncReactor.ts uses each definition's output extractor, so the Azure create output is read.

Tests: three new table rows in PullRequestSyncReactor.test.ts cover an Azure create after a push (links PR 42), a show beside a silent create (links nothing), and a GitHub URL beside GitHub and Azure creates (links nothing). The author reports a failing-first check for the create row.

Not required by the issue and not implemented: compact, TSV, and --query output. The issue's reproduction uses default JSON output, so these cases do not block the requirement. The Evidence section (real-app before/after) is pending. It is not a coding requirement.

The evidence used is the PR summary, the AI-generated change summary, and the PR description. No repository inspection was run to confirm the code. Behaviour rests on the reported test results.

Full details: Out of Scope Changes check

Explanation

Each changed area connects to #31166 or to the PR objectives:

  • definition.ts (Azure DevOps) adds the create command and printed-output handling. This is the core fix.
  • pullRequestUrls.ts is new shared code. It holds azureDevOpsPullRequestWebUrl, moved unchanged from azureDevOpsPullRequests.ts, and the new output parser. The move lets the definition use the URL builder without a server-only import. The two azureDevOpsPullRequest*.ts server files change only their imports and the removed function.
  • packages/source-control-core/src/shared/definition.ts adds the optional changeRequestCreateOutputUrls and changeRequestPrintCommand fields. The reactor needs these to read Azure output.
  • PullRequestSyncReactor.ts makes three changes: per-definition output extraction, a print-command guard, and per-host counting of URLs against that host's create commands. The print-command guard addresses a reviewer finding (a show command beside a create linking an existing PR). Per-host counting prevents an Azure create from vouching for a GitHub URL. This change goes beyond the issue text, but it is needed for the Azure create path to be correct in mixed-host scripts, so it is related work rather than unrelated work.
  • docs/user/source-control.md lists az repos pr create among automatic linking commands. This matches the new behaviour.
  • Tests cover the changed behaviour.

No unrelated file or feature change was found in the summary. No UI change is reported.

Finishing Touches

Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between 9efd960 and f36ea27.

Files selected for processing: 8

  • apps/server/src/orchestration-v2/PullRequestSyncReactor.test.ts
  • apps/server/src/orchestration-v2/PullRequestSyncReactor.ts
  • docs/user/source-control.md
  • packages/source-control-azure-devops/src/server/azureDevOpsPullRequestJson.ts
  • packages/source-control-azure-devops/src/server/azureDevOpsPullRequests.ts
  • packages/source-control-azure-devops/src/shared/definition.ts
  • packages/source-control-azure-devops/src/shared/pullRequestUrls.ts
  • packages/source-control-core/src/shared/definition.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:trusted Author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: az repos pr create does not link the new pull request to the thread

1 participant