feat(workflows): Phase 5 ADO MG-PR verbs wired (replaces human-gate stub)#118
Merged
Conversation
…tub) Replaces the `mg_pr_human_gate_ado` stub in `implement-mg.yaml` with the real `pr open-mg-ado` + `pr merge-mg-ado` verbs (shipped in PR #106 but previously unwired because the workflow chain didn't thread the ADO connection inputs). ## What changed ### `polyphony-implement.yaml` (1.1.0 → 1.2.0) - New optional inputs: `organization`, `project`, `repository` (all default `""`). Required only when `platform=ado`; ignored otherwise. - Threaded down to `implement-mg.yaml` alongside the existing `platform` input. ### `implement-mg.yaml` (1.0.0 → 1.1.0) - New optional inputs: `organization`, `project`, `repository`. - `pr_platform_router` now also computes `ado_inputs_ready` + `missing` so the workflow can fail early and clearly when platform=ado but the connection inputs are blank — without burning an ADO API call that would just return `error_code: invalid_argument`. - Replaced `mg_pr_human_gate_ado` (operator-managed PR) with: - `mg_pr_open_ado` — script invoking `polyphony pr open-mg-ado` with `--organization/--project/--repository`. Idempotent (reuses an existing OPEN PR for the same head/base pair). - `mg_pr_merge_ado` — script invoking `polyphony pr merge-mg-ado`. Hardcoded merge-commit per the ADR (nested MGs depend on git ancestry; squash and rebase would break the chain). Idempotent (recognises an already-merged PR). - `mg_pr_failed_gate_ado` — human gate fired when either ADO verb returns a non-empty `error_code` (or merge returns merged=false). Retry routes back to `mg_pr_open_ado` (safe — both verbs are idempotent); abort routes to `$end` without invoking `scope_closer`. - `mg_pr_inputs_missing_gate` — human gate fired when platform=ado but one or more of `organization/project/repository` is blank. Surfaces the missing field list from the router so the operator can re-invoke with the correct inputs. - `output.pr_url` and `output.pr_number` now prefer `mg_pr_open_ado` when defined, falling back to `mg_pr_open` (per M3 + M7). - All routes use explicit `error_code is defined and != ''` / `merged == true` conditions plus a catch-all to the failure gate (per M4). ### `index.yaml` - Added missing `implement-mg` entry (was previously absent). - Bumped `polyphony-implement` versions list to include 1.1.0 + 1.2.0 (1.1.0 was already on disk but not tracked in the index — historical drift fixed in passing). ## Scope decision (per rubber-duck pass) This PR DOES NOT touch `polyphony-full.yaml`. Promoting `platform` to the apex creates a misleading semantic where a full run with `platform=ado` would still create GitHub plan PRs (because `plan-level.yaml` is GitHub-only today). Operators wanting ADO MG support should invoke `polyphony-implement.yaml` directly with `platform=ado` + the three connection inputs, OR pre-author the plan and start from `ready_for_implementation`. Apex-level platform threading is deferred until plan-level + feature-pr ADO support land. ## Validation - All 16 lint scripts (8 ps1 + 8 Pester suites) pass. - `conductor validate` passes for both touched workflows. - 2400/2400 .NET tests pass. - Verb signatures verified against the ADO MG verb help output and result schemas (`PrOpenMgAdoResult`, `PrMergeMgAdoResult`). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced May 6, 2026
PolyphonyRequiem
added a commit
that referenced
this pull request
May 7, 2026
… (Phase 5) (#121) Replaces the human-gate stub of `ado-pr.yaml` with a real platform-native PR lifecycle and makes `feature-pr.yaml`'s creator step platform-aware. Mirrors the shape of `implement-mg.yaml` from PR #118 (the canonical template for github/ado dual-leg workflows). ## ado-pr.yaml — full rewrite (1.0.1 → 2.0.0) Was a 138-LOC stub that emitted ADO_PR_NOT_IMPLEMENTED and surfaced a single human gate. Now a real ~600-LOC lifecycle: - `ado_inputs_validator` (entry) — fail-fast on missing organization/ project/repository inputs before burning an API call. - `ado_pr_status_check` — calls `polyphony pr poll-status-ado`, routes 6 ways on `state`: merged → already-merged emitter; approved + merge_allowed → merger; approved + blocked → blocked-gate; changes_requested / pending / closed / error → respective human gates. - `ado_pr_merger` — calls `polyphony pr merge-feature-ado`, passes `--match-head-commit {{ status_check.head_sha }}` as a stale-head guard. On `error_code == 'stale_head'` routes back to `ado_pr_status_check` (re-poll with new SHA, then re-attempt merge). - Terminal emitters: `ado_pr_already_merged_emitter` (idempotent merged case), `ado_pr_treat_as_merged_emitter` (operator override — emits `override=true`/`reason='operator_manually_verified_merge'` for log traceability). - 7 human gates total: `ado_pr_blocked_gate` (approved-but-not-mergeable with `policy.blocking_reasons` surfaced), `ado_pr_changes_requested_gate`, `ado_pr_pending_gate`, `ado_pr_closed_gate`, `ado_pr_error_gate`, `ado_pr_merge_failed_gate`, `ado_inputs_missing_gate`. - Gate option labels renamed: "Treat as merged" → "I manually verified merge" (per rubber-duck — old phrasing concealed that polyphony hadn't actually verified anything). NO LLM reviewer in this revision: humans review natively in ADO; polyphony just polls and merges. LLM-advisory mode for ADO is a future enhancement that needs a `pr post-comment-ado` verb (doesn't exist yet). ## feature-pr.yaml — restructure (1.0.1 → 1.1.0) - New optional inputs `organization`/`project`/`repository` for ADO. - `entry_point` flips from `feature_pr_creator` → `pr_platform_router` (router upstream of creator, mirrors implement-mg.yaml shape). - `pr_platform_router` computes `{ platform, ado_inputs_ready, missing }`. GitHub → `feature_pr_creator_github`; ADO + ready → `feature_pr_creator_ado`; ADO + missing → `feature_pr_inputs_missing_gate`. - Creator split: `feature_pr_creator` → `feature_pr_creator_github` (calls `pr create-feature-pr`) + `feature_pr_creator_ado` (calls `pr create-feature-ado`). - New `feature_pr_creator_failed_gate_ado` for ADO creator errors (retry is idempotent — reuses existing OPEN PR). - `pr_lifecycle_ado` now threads `organization`/`project`/`repository` + `pr_number` from the ADO creator into ado-pr.yaml v2. - ADO leg short-circuits remediation: on `pr_lifecycle_ado.merged == false`, routes to new `ado_remediation_not_supported_emitter` (emits merged=false with `reason='ado_remediation_not_supported'`). The remediation chain (`remediation_planner`/`remediation_implementer`/`feature_pr_updater`) is GitHub-only — uses `gh` directly; cannot run on ADO without `pr post-comment-ado`/`pr request-review-ado` verbs that don't exist yet. Operator must remediate manually in ADO and re-invoke the workflow. - All `feature_pr_creator.output.pr_number` references in remediation prompts renamed to `feature_pr_creator_github.output.pr_number` — safe because the remediation chain is now GitHub-only by construction. - Output map updated: `pr_url` and new `pr_number` use `is defined` guards to prefer ADO when defined, fall back to GitHub (M3 / StrictUndefined-safe). ## Lint script update `lint-ado-pr.ps1` was written for the stub and required two now-obsolete shapes: the `ADO_PR_NOT_IMPLEMENTED` sentinel string and a `merged` gate option value. Both are gone in v2 (real lifecycle has no sentinel; gate options are semantic — `repoll`, `verified_merge`, `retry`, `trigger_remediation`, `abort` — not literal `merged`/`aborted`). Lint now requires only `abort` from human gates (universal exit-path rule per P6) and is documented in the comment block. `lint-ado-pr.Tests.ps1` updated accordingly: dropped two stub-era tests; added one focused test for the `abort`-required check. ## Validation - All 8 lint scripts pass (`lint-ado-pr.ps1` PASS). - All 16 lint Pester suites pass (101/101 tests). - `dotnet build` clean, `dotnet test` 2475/2475 (no code changes — pure YAML + PowerShell lint update). ## Rubber-duck blockers addressed 1. **Approved ≠ mergeable.** Routes split for `approved + merge_allowed` (→ merger) vs `approved + blocked` (→ `ado_pr_blocked_gate`). Merger passes `--match-head-commit` for stale-head safety; on `stale_head` error_code routes back to status_check. 2. **"Treat as merged" can lie.** Renamed to "I manually verified merge" across all 5 gates that present it. Emitter records `override=true` and `reason='operator_manually_verified_merge'` for log traceability. 3. **ADO remediation is GitHub-only.** Short-circuited at `pr_lifecycle_ado` instead of bleeding into the GitHub-shaped `remediation_planner` chain. Honest "not supported" exit beats a silent failure inside the wrong toolchain. ## Deferred - LLM advisory reviewer for ADO (needs `pr post-comment-ado`). - ADO remediation chain (needs `pr post-comment-ado` + `pr request-review-ado`). - Plan-level ADO wiring (next workflow PR; same pattern, deeper workflow). Co-authored-by: Daniel Green <dangreen@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat(workflows): Phase 5 ADO MG-PR verbs wired (replaces human-gate stub)
Replaces the
mg_pr_human_gate_adostub inimplement-mg.yamlwith thereal
pr open-mg-ado+pr merge-mg-adoverbs (shipped in PR #106 butpreviously unwired because the workflow chain didn't thread the ADO
connection inputs).
What changed
polyphony-implement.yaml(1.1.0 → 1.2.0)organization,project,repository(alldefault
""). Required only whenplatform=ado; ignored otherwise.implement-mg.yamlalongside the existingplatforminput.
implement-mg.yaml(1.0.0 → 1.1.0)organization,project,repository.pr_platform_routernow also computesado_inputs_ready+missingso the workflow can fail early and clearly when platform=ado but the
connection inputs are blank — without burning an ADO API call that
would just return
error_code: invalid_argument.mg_pr_human_gate_ado(operator-managed PR) with:mg_pr_open_ado— script invokingpolyphony pr open-mg-adowith--organization/--project/--repository. Idempotent (reuses anexisting OPEN PR for the same head/base pair).
mg_pr_merge_ado— script invokingpolyphony pr merge-mg-ado.Hardcoded merge-commit per the ADR (nested MGs depend on git
ancestry; squash and rebase would break the chain). Idempotent
(recognises an already-merged PR).
mg_pr_failed_gate_ado— human gate fired when either ADO verbreturns a non-empty
error_code(or merge returns merged=false).Retry routes back to
mg_pr_open_ado(safe — both verbs areidempotent); abort routes to
$endwithout invokingscope_closer.mg_pr_inputs_missing_gate— human gate fired when platform=adobut one or more of
organization/project/repositoryis blank.Surfaces the missing field list from the router so the operator can
re-invoke with the correct inputs.
output.pr_urlandoutput.pr_numbernow prefermg_pr_open_adowhendefined, falling back to
mg_pr_open(per M3 + M7).error_code is defined and != ''/merged == trueconditions plus a catch-all to the failure gate(per M4).
index.yamlimplement-mgentry (was previously absent).polyphony-implementversions list to include 1.1.0 + 1.2.0(1.1.0 was already on disk but not tracked in the index — historical
drift fixed in passing).
Scope decision (per rubber-duck pass)
This PR DOES NOT touch
polyphony-full.yaml. Promotingplatformtothe apex creates a misleading semantic where a full run with
platform=adowould still create GitHub plan PRs (becauseplan-level.yamlis GitHub-only today). Operators wanting ADO MGsupport should invoke
polyphony-implement.yamldirectly withplatform=ado+ the three connection inputs, OR pre-author the planand start from
ready_for_implementation. Apex-level platform threadingis deferred until plan-level + feature-pr ADO support land.
Validation
conductor validatepasses for both touched workflows.result schemas (
PrOpenMgAdoResult,PrMergeMgAdoResult).Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com