mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-08-31 02:06:21 +00:00
feat(review): back pr-context on Aone Code targets (#9621)
* feat(review): back pr-context on Aone Code targets pr-context was the one read subcommand still gh-direct, so every Aone run was forced context-unavailable: the verdict capped at COMMENT (the wired a1 approval could never fire), Agent 0 skipped, and the machine ledger never recovered from posted summaries. Route it through the platform reader with a normalized context bundle; Aone serves it from mr view + the flat comment list (thread comments carry the ledger), GitHub's implementation is an extraction of the existing calls — its output stays byte-identical. The forced cap leaves the Aone write path for parity with GitHub's state-claim handling, and the refetch commands a context file emits bake --pr on Aone, where comment bodies are addressed per-MR. * fix(review): keep Aone ledger carriers out of the blocker re-check (#9621) On Aone this pipeline's own round summaries are path-less comments, so they ride pr-context's issue channel, where their visible **[Critical]** lines self-promoted every prior Critical-bearing summary into "Blockers to re-check" — rendering each prior Critical three times (beside the ledger section and the inline roots that own the same findings) and spending the section budget on the pipeline's own prose until genuine human blockers degraded to snippets. Exclude bodies carrying the ledger marker from issue-channel promotion and the stdout count, strip the marker out of the settled snippet, and switch the pr_number guard to the canonical isPositivePrNumber so 0x10/5. spellings cannot fragment side-file continuity. Pin the witnesses the round's findings name: the guard, args.host forwarding, the issue-kind --pr refetch branch, the account-first author keying, and the GitHub test suites' independence from the cwd-origin probe. * fix(review): refuse pr_number spellings that do not round-trip (#9621) isPositivePrNumber alone admits two spellings whose Number() value does not round-trip to the raw string: leading zeros (007 fetches 7 but the raw string labels the heading and the prev-ledger side file, so a later 7 run reads a different side file and the round counter restarts) and digit strings above Number.MAX_SAFE_INTEGER (Number() silently rounds them, fetching a different PR than the labels announce). Add the safe-integer and no-leading-zero conjuncts — matching fetch-pr's [1-9]\d* rule — so every admitted input satisfies String(Number(x)) === x. Also pin the witnesses the round-2 review names: the commit_id round-trip through the GitHub reader and toRawReview into the persisted side file (both spreads were unwitnessed), the stale force-applies comment in submit-aone.test.ts the cap removal outdates, and the setup batch's Aone carve-out for the unbacked comment-status call. * docs(review): align Aone docs with the landed no-ancestry anchor rule and comment-status skips D6 described the AGit-Flow anchor as inert until the incremental rule landed, but that rule (#9630) merged while this branch was in flight — anchors now delta-scope Aone re-reviews. SKILL.md's comment-status section and Step 6's report-existence guard now name the Aone skip the setup batch already carries, so no path sends an Aone run at the unbacked command or at a report that was never written. * docs(review): annotate #9616 as landed and define the report-less re-check rule The out-of-scope list still read self-PR detection as open work although #9629 shipped it into this branch's merge base — annotate it like the sibling #9618 entry. Step 6's report-existence guard pointed report-less runs at a re-derivation the skill never defines; replace it with the explicit rule: no per-thread status routing, no hand-derived substitute, rule from the code at the reviewed commit, cannot-tell over a guess. * fix(review): route the context head through aoneHeadSha and close the round-5 findings getReviewContext read sourceBranch raw while every other head read trims — a padded server value diverged the context file from the rest of the run (phantom-drift shape). getCurrentUser now honors the seam contract on the anomalous whoami shapes instead of leaking untagged throws and non-string accounts. Step 6's report-less rule no longer contradicts the comment-status failure contract: runs where the command ran and failed keep the "re-derive if needed" fallback. The Aone paragraph names comment-body among the backed reads, and witness tests pin the identity gate's carriers key and the head normalization. * fix(review): shape-check the Aone comment listing in getReviewContext a1 can answer repo mr comment list with an exit-0 a1.error/v1 error object (backend auth failure or client timeout — measured by cleanup's a1CommentList on the identical payload). Without a guard the object survives the ?? [] coalesce and .filter throws an untagged TypeError, losing the envelope's actionable message at exactly the recoverable moment. Guard as the provider family already does and surface the cause; witness tests pin both envelope shapes (mutant-checked). * test(review): pin getCommentBody's body-field fallback (mutant-checked) * fix(review): union resolved comments into the Aone context bundle The default comment list excludes resolved comments (measured by the cleanup audit) while GitHub's REST fetches include them, so a resolved blocker/marker root never reached the re-check walk or the fail-closed identity gate. Union the default and --resolved listings as the audit does, dedupe by id, fail closed on either listing's error envelope, and disclose the residual that resolved replies stay invisible; witness tests mutant-checked. * fix(review): serve resolved comments and guard the envelope in getCommentBody getCommentBody queried only the default comment list while the context bundle it serves refetches for unions in resolved comments — a resolved id named by a truncation note threw "not found" every time, and an exit-0 a1.error/v1 envelope threw an untagged TypeError that lost the actionable message. Extract the shape-checked default+resolved union helper and read both sites through it; witness tests mutant-checked. * ci: correct qwen-autofix.yml size baseline to its actual post-migration size #9677 shrank qwen-autofix.yml from 431526 to 397656 bytes (prose moved to the design record) but recorded the baseline at 392111, 5545 below the file's own post-change size, so the first PR to run the ratchet tripped it. This branch introduces zero growth to the file (byte-identical to main); the bump aligns the baseline with reality. No workflow content changes. --------- Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com>
This commit is contained in:
parent
6b729f91d6
commit
ec8a8a1a97
13 changed files with 1719 additions and 137 deletions
|
|
@ -493,6 +493,23 @@ Enterprise paragraph.
|
|||
dedup backing for Aone, cleanup audit, the ai_comment marking flag
|
||||
(a1-side), the render-adjudication carve-out.
|
||||
|
||||
- **Phase 3b — Aone `pr-context` backing (this change).** The reader gains
|
||||
`getReviewContext` + `getCurrentUser` (D1's `getContext` + `self`,
|
||||
synchronous). `pr-context` routes through the platform reader; the
|
||||
normalized bundle keeps ALL rendering and security logic platform-neutral.
|
||||
GitHub's implementation EXTRACTS pr-context's existing gh calls
|
||||
unchanged — the existing suite passing unmodified is the no-regression
|
||||
evidence. On Aone: metadata from `mr view` (stats degrade), one flat
|
||||
comment list split by `path`, no verdicts, ledger carriers = the
|
||||
thread-level comments (the posted summaries); refetch commands bake
|
||||
`--pr` (Aone addresses every comment body per-MR) and bake only an
|
||||
explicit `--host` (never the ambient GH_HOST). The forced
|
||||
context-unavailable cap leaves submit (the reads are backed now), so an
|
||||
Aone run that read its context can APPROVE and the wired
|
||||
`a1 repo mr approve` fires. Agent 0 becomes runnable on Aone (its gate
|
||||
is pr-context success; its welded `issue-context` command is already
|
||||
backed). Design: `2026-08-21-review-aone-pr-context.md`. Still open: the
|
||||
Phase-3 open items above, unchanged.
|
||||
- **Phase 4 — semantic gaps.** Incremental-cache ancestry fallback, build-test
|
||||
repo-config escape hatch, publish-assets gating polish, generic-GitLab
|
||||
(glab) evaluation.
|
||||
|
|
|
|||
280
docs/design/2026-08-21-review-aone-pr-context.md
Normal file
280
docs/design/2026-08-21-review-aone-pr-context.md
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
# Phase 3b: Aone Code `pr-context` backing for /review
|
||||
|
||||
> Status: draft. Scope: back `qwen review pr-context` on Aone Code through the
|
||||
> platform reader, lifting the forced context-unavailable cap on Aone runs.
|
||||
> Parent: `2026-08-13-review-platform-provider-abstraction.md` (Phase 3,
|
||||
> "still open: context reads"). Continues `2026-08-15-review-aone-provider.md`.
|
||||
|
||||
## Context
|
||||
|
||||
The Aone read path (Phase 2, #9226) and the Aone write path (Phase 3 `submit`
|
||||
slice, #9491) are landed. But `pr-context` — the subcommand that fetches a
|
||||
target's metadata and existing discussion into the context file every agent
|
||||
reads — is still GitHub-direct. On an Aone target it is SKIPPED, and the skip
|
||||
cascade defines the current Aone experience:
|
||||
|
||||
- every Aone run is context-unavailable; `submit` FORCES the cap for Aone
|
||||
writes, so the verdict can never rise past COMMENT;
|
||||
- the wired `a1 repo mr approve` never fires (the cap precedes it);
|
||||
- Agent 0 (issue fidelity) is skipped — it is gated on `pr-context` success,
|
||||
even though `issue-context` (its evidence command) is already Aone-backed;
|
||||
- the machine ledger is never recovered from the MR, so every round re-opens
|
||||
as round 1 even though the posted summary comment carries the marker.
|
||||
|
||||
Backing `pr-context` is the single change that lifts all four: the cap is a
|
||||
consequence of the skip, Agent 0's gate is `pr-context` success, and the
|
||||
ledger lives in the posted comments this subcommand would now read.
|
||||
|
||||
Out of scope (tracked): comment-status/presubmit backing and cross-round
|
||||
dedup (#9613), AI-comment marking (#9614), removed-line anchors (#9615),
|
||||
self-PR detection (#9616 — landed via #9629 and merged into this branch
|
||||
while it was in flight), cleanup audit (#9617), incremental cache under
|
||||
AGit-Flow (#9618 — landed via #9630 and merged into this branch while it was
|
||||
in flight; see D6), test-plan routing / composeUrl / a1 version floor (#9619).
|
||||
|
||||
## Verified platform facts
|
||||
|
||||
The Phase-2 facts table (probed 2026-08-13 against maxcompute/odps_src with
|
||||
a1 v0.1.90) already covers everything this phase reads, plus the a1 command
|
||||
surface re-checked 2026-08-21 via help (no auth needed):
|
||||
|
||||
| Need | a1 surface | Notes |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
||||
| MR metadata | `a1 repo mr view <id> -f json` → `title, description, state, sourceBranch (head SHA under AGit-Flow), targetBranch, author, detailUrl` | no additions/deletions stats — the context header degrades |
|
||||
| All comments | `a1 repo mr comment list --mr <id> -f json [--sort asc]` → `id, note, author, closed, outdated, path, line, side, parentNoteId, isAiComment, isDraft` | one flat collection; `path` present ⇔ inline; NO pagination flags (full list returned); default sort `desc` |
|
||||
| Reviews / verdicts | none — no review object exists on Aone | approvals surface only through `mr status` checks |
|
||||
| Current user | `a1 auth whoami -f json` → `account` | |
|
||||
|
||||
Probe-pending shapes RESOLVED 2026-08-21 against live MRs once a1 auth was
|
||||
restored:
|
||||
|
||||
- `author` is an object `{id, name, username}` — `username` is the identity
|
||||
space `a1 auth whoami`'s `account` answers in (verified both on one MR).
|
||||
The tolerant reader tries `account` first, then `username`.
|
||||
- `createdAt` is present (ISO-8601 with offset); `closed` is a NUMBER,
|
||||
`outdated`/`isAiComment`/`isAiSummary`/`isDraft` are booleans — the draft
|
||||
skip is live, not hypothetical.
|
||||
- The comment envelope also carries `updatedAt`, `adopted`, `labels` —
|
||||
unread.
|
||||
|
||||
One NEW gap surfaced by the same E2E (filed as #9620, pre-existing, out of
|
||||
this phase's scope): `mr view` carries NO head-SHA field, and
|
||||
`sourceBranch` is a branch NAME on branch-based (non-AGit-Flow) MRs — the
|
||||
provider's sourceBranch-as-SHA assumption (facts table, submit's drift gate,
|
||||
`meta`'s headSha) only holds under AGit-Flow.
|
||||
|
||||
## Design decisions
|
||||
|
||||
### D1 — One new reader operation, `getReviewContext`, plus `getCurrentUser`
|
||||
|
||||
`pr-context` is the single consumer, so the reader gains exactly two members:
|
||||
|
||||
- `getReviewContext(prNumber, ownerRepo): ReviewContext` — the normalized
|
||||
bundle: metadata, the flat comment list split into inline/thread channels,
|
||||
and the platform's review-level verdicts.
|
||||
- `getCurrentUser(): string` — the authenticated account ('' on the
|
||||
empty-output shape; throws on lookup failure).
|
||||
|
||||
The end-state interface in the parent doc named this `getContext(req)` —
|
||||
"description, comments, verdicts, self"; `self` stays a separate operation
|
||||
because pr-context's identity policy is deliberately NOT "always fetch": the
|
||||
lookup runs only when comments exist, and its failure semantics (fail closed
|
||||
iff a posted root carries a critical marker) are pr-context's security
|
||||
logic, not the platform's. Keeping that logic in one place, platform-neutral,
|
||||
is the point.
|
||||
|
||||
```ts
|
||||
interface ReviewContextComment {
|
||||
id: number;
|
||||
author: string; // login/account, '' when absent
|
||||
body: string;
|
||||
createdAt: string; // ISO; '' when the platform gives none
|
||||
path?: string; // present ⇔ inline comment
|
||||
line?: number;
|
||||
parentId?: number; // GitHub in_reply_to_id / Aone parentNoteId
|
||||
}
|
||||
|
||||
interface ReviewContextVerdict {
|
||||
id: number;
|
||||
author: string;
|
||||
body: string;
|
||||
state: string; // APPROVED | CHANGES_REQUESTED | COMMENTED | …
|
||||
submittedAt: string;
|
||||
commitId?: string; // GitHub: the head the review was submitted against
|
||||
}
|
||||
|
||||
interface ReviewContext {
|
||||
title: string;
|
||||
body: string;
|
||||
authorLogin: string;
|
||||
state: string;
|
||||
baseRefName: string;
|
||||
headRefName: string; // branch name (GitHub); Aone: sourceBranch — a bare SHA under AGit-Flow
|
||||
headRefOid: string;
|
||||
additions?: number; // absent where the platform reports no stats
|
||||
deletions?: number;
|
||||
changedFiles?: number;
|
||||
comments: ReviewContextComment[];
|
||||
verdicts: ReviewContextVerdict[];
|
||||
/** Where this platform's machine-ledger markers live, shaped as verdicts
|
||||
* ready for `recoverLedger`: GitHub — the review bodies; Aone — the
|
||||
* thread-level comments (the posted summaries). */
|
||||
ledgerCarriers: ReviewContextVerdict[];
|
||||
}
|
||||
```
|
||||
|
||||
`github.ts`'s implementation EXTRACTS pr-context's existing calls (one
|
||||
`gh pr view` + the three paginated `ghApiAll` fetches; `ledgerCarriers` =
|
||||
`verdicts`). The transport seam stays `lib/gh.js`, so pr-context's existing
|
||||
test suite — which mocks that module — pins the extraction unchanged. That
|
||||
suite passing unmodified is the no-regression evidence.
|
||||
|
||||
### D2 — Aone channel mapping
|
||||
|
||||
One flat comment collection serves three GitHub channels:
|
||||
|
||||
- `path` present → inline comment; `parentNoteId` → `in_reply_to_id`, so
|
||||
`classifyInlineThreads`/`findRootId` walk Aone threads unchanged.
|
||||
- `path` absent → issue-level ("general MR thread") comment — blocker
|
||||
promotion and the "Already discussed" channel, exactly the treatment
|
||||
GitHub's issue comments get.
|
||||
- ledger carriers = the path-ABSENT comments, mapped into the verdict shape
|
||||
(`state: 'COMMENTED'`, no `commitId`): the qwen summary lands there, and
|
||||
`recoverLedger` walks carriers — own/foreign split, round-first selection,
|
||||
headroom, the merge-over-own union — with zero Aone-specific code. Aone
|
||||
comments carry no `commit_id`, so a recovered Aone ledger has no age
|
||||
reference — the convergence posture already skips its age rule on that
|
||||
shape ("skip the age rule, not the review").
|
||||
- `isDraft` comments are skipped (the PENDING-review analogue: a draft is
|
||||
not a posted round and not settled discussion).
|
||||
- Resolved comments are INCLUDED: the default `comment list` excludes them
|
||||
(measured: the MR's `comments` minus `closedComments`), while GitHub's
|
||||
REST fetches include resolved-thread comments — so `getReviewContext`
|
||||
unions the default and `--resolved` listings, deduped by id, the same
|
||||
union `cleanup`'s audit applies. The `closed`/`outdated` FLAGS are still
|
||||
ignored this phase (their consumer is comment-status, #9613); the union
|
||||
is about which comments ARRIVE, not how their state is rendered.
|
||||
Disclosed residual: resolved REPLIES stay invisible — the `--resolved`
|
||||
listing returns resolved ROOT inline comments only, so a resolved thread
|
||||
renders its root without its reply chain (the re-check walk is unaffected
|
||||
— a reply alone never retires a blocker).
|
||||
- `verdicts` is empty: Aone has no review object. The "Review summaries"
|
||||
section therefore renders nothing on Aone; human overall comments are
|
||||
thread comments and render in the thread channels like GitHub issue
|
||||
comments. Approvals are visible only through `mr status` and join with the
|
||||
dedup/presubmit phase.
|
||||
|
||||
### D3 — Metadata mapping
|
||||
|
||||
From `mr view`: `title`, `description` → body, `author` → authorLogin,
|
||||
`state` passthrough, `targetBranch` → baseRefName, `sourceBranch` →
|
||||
headRefOid (it IS the head SHA under AGit-Flow). `headRefName` =
|
||||
`sourceBranch` as well: under AGit-Flow that string is the head SHA, and
|
||||
rendering `master ← <sha>` in the context header is truthful and
|
||||
informative; a non-AGit-Flow MR's real branch name renders the same way
|
||||
GitHub's does. Diff stats have no Aone source: the header line degrades to
|
||||
"not reported by the platform" instead of printing zeros (zeros would assert
|
||||
an empty diff). pr-context does not compute them locally — the worktree
|
||||
belongs to fetch-pr, and duplicating its merge-base arithmetic here would be
|
||||
a second copy of logic that has a home.
|
||||
|
||||
### D4 — Refetch commands bake `--pr` on Aone; only an explicit `--host` bakes
|
||||
|
||||
pr-context's truncation notes emit `comment-body` commands. On GitHub,
|
||||
inline and issue comment ids are global, so only `--kind review` carries
|
||||
`--pr`; on Aone every comment body is addressed per-MR (comment-body already
|
||||
refuses a pr-less Aone call). The emitted command builder learns the
|
||||
platform: on Aone, every emitted refetch carries `--pr <id>`. A refetch a
|
||||
reader cannot run is a truncation nobody can complete, which the fail-closed
|
||||
"partial read is `cannot tell`" rule then turns into a stalled re-check.
|
||||
|
||||
The host half of the contract: on Aone only an EXPLICIT `--host` flag bakes
|
||||
into the emitted refetches. An ambient `GH_HOST` never does — it is a
|
||||
different platform's host, and baking it would silently retarget every
|
||||
refetch at a GitHub host, re-opening the exact cross-platform leak the
|
||||
`--pr` rule closes. A flagless Aone run's refetches rely on the cwd clone's
|
||||
origin — the same detection the run itself used. (GitHub keeps its existing
|
||||
policy: the explicit `--host` else an operator-exported `GH_HOST` bakes.)
|
||||
|
||||
### D5 — The forced context-unavailable cap leaves the Aone write path
|
||||
|
||||
`submit` forces `contextUnavailable: true` for Aone writes because "this
|
||||
phase has no Aone backing for pr-context" — the premise this change removes.
|
||||
The force goes away; the Aone path takes the state's claim exactly as GitHub
|
||||
does (handed through raw, a malformed value refused by compose-review). The
|
||||
forgery class the force closed — a forged/omitted field composing an APPROVE
|
||||
— reopens to exactly the level GitHub runs at, where the reads are backed
|
||||
and the claim stands. comment-status/presubmit remain unbacked, but they
|
||||
feed the `presubmit` downgrade fields, never `contextUnavailable` (whose
|
||||
meaning is "pr-context failed or was skipped", per Step 1). Consequence: an
|
||||
Aone run that read its context can now compose APPROVE, and the wired
|
||||
`a1 repo mr approve` fires for the first time.
|
||||
|
||||
### D6 — Ledger anchors under AGit-Flow: carried, live via the no-ancestry rule
|
||||
|
||||
A recovered own-ledger's `sha` rides into the side file and the section's
|
||||
anchor ruling as on GitHub. Under AGit-Flow the anchored head is amended
|
||||
(orphaned) on every update, so the ancestry test GitHub's incremental path
|
||||
relies on would fail for EVERY update; `fetch-pr --since` therefore
|
||||
resolves Aone anchors with the no-ancestry rule (the parent doc's D7,
|
||||
shipped by #9630 while this branch was in flight): the anchor-behind-head
|
||||
test and the merge-base clamp are both skipped, and a recovered anchor
|
||||
delta-scopes the round to the files the update touched — rebase drift
|
||||
staying within them keeps the scope, anything wider falls back to
|
||||
full-range, and no drift byte enters the published scope. The anchor is
|
||||
LIVE on Aone, not inert: the draft's "inert until #9618" text predates that
|
||||
landing and was wrong from the merge on.
|
||||
|
||||
### D7 — Skill and doc surface
|
||||
|
||||
SKILL.md's Aone paragraph: every Aone run is NO LONGER context-unavailable;
|
||||
`pr-context` runs like GitHub (same failure handling — warn, continue,
|
||||
context-unavailable state); Agent 0 runs (its welded `issue-context` command
|
||||
is Aone-backed); `plan-diff` gets `--pr`/`--repo` when the fetch succeeds.
|
||||
The skip list shrinks to what is still unbacked: `comment-status`,
|
||||
`presubmit`, `test-plan`, the Step 9 bypass audit, and `publish-assets`.
|
||||
The repeat-round caveats shrink to the two that remain true (no dedup
|
||||
backing; no self-PR detection). The "approve does not fire this phase" text
|
||||
goes. `docs/users/features/code-review.md`'s Aone paragraph and the parent
|
||||
doc's phase tracker update with it. (Post-write merges shrink the list
|
||||
again: #9629 lands presubmit's self-PR/drift backing and #9633 the Aone
|
||||
bypass audit — the merged SKILL.md and user doc carry the live state; this
|
||||
paragraph records the phase-3b scope as written.)
|
||||
|
||||
## Files affected
|
||||
|
||||
- `lib/platform/types.ts` — `ReviewContext` types; the two reader members.
|
||||
- `lib/platform/github.ts` — implementation (extraction of pr-context's
|
||||
current calls; `currentUser` passthrough).
|
||||
- `lib/platform/aone.ts` — implementation over `mr view` + `comment list`;
|
||||
whoami mapping.
|
||||
- `pr-context.ts` — routes through `getPlatformReader({host})`; keeps ALL
|
||||
rendering and security logic (blocker promotion, ledger recovery,
|
||||
fail-closed identity, truncation discipline) platform-neutral over the
|
||||
normalized bundle; PrMetadata's stats become optional; refetch commands
|
||||
gain `--pr` on Aone.
|
||||
- `submit.ts` — the forced cap removed (D5), its comment rewritten.
|
||||
- `SKILL.md`, `docs/users/features/code-review.md`,
|
||||
`docs/design/2026-08-13-review-platform-provider-abstraction.md`
|
||||
(phase tracker).
|
||||
|
||||
Tests: pr-context's suite passes unmodified (transport seam unchanged);
|
||||
new tests in `lib/platform/aone.test.ts` for the mapping (channel split,
|
||||
draft skip, carrier shaping, author fallbacks, stats absence), in
|
||||
`pr-context.test.ts` for the Aone routing (emitted `--pr` refetches,
|
||||
degraded diff line, ledger recovery from comments), and the `submit` suites'
|
||||
forced-cap pins flip to parity pins.
|
||||
|
||||
## Open questions
|
||||
|
||||
1. ~~The probe-pending shapes above (author field, createdAt, isDraft
|
||||
visibility).~~ RESOLVED — see the facts table addendum; the mapping tests
|
||||
are pinned to the live shapes.
|
||||
2. Comment volume: a long-lived odps_src CR's comment list arrives in one
|
||||
un-paginated JSON payload; the 64 MiB aone-client bound covers it, but a
|
||||
monster thread's context file crosses the read_file threshold — the
|
||||
existing size warning + paging guidance already handles that shape.
|
||||
3. Branch-based (non-AGit-Flow) MRs carry a branch NAME in `sourceBranch`
|
||||
and `mr view` exposes no head-SHA field — the provider's
|
||||
sourceBranch-as-SHA assumption breaks on them (submit's drift gate then
|
||||
refuses every post). Pre-existing, filed as #9620, out of this phase.
|
||||
|
|
@ -382,7 +382,7 @@ The deterministic halves of the pipeline — argument parsing (`qwen review pars
|
|||
|
||||
**GitHub Enterprise:** reviewing a PR URL on a non-`github.com` host routes every GitHub call at that host — the review subcommands (`match-remote`, `meta`, `fetch-pr`, `pr-context`, `comment-status`, `issue-context`, `fetch-diff`, `comment-body`, `plan-diff`, `test-plan`, `presubmit`, `compose-review`, `submit`, `publish-assets`) accept `--host` and set it in code, so a forgotten host cannot silently retarget the review at `github.com`.
|
||||
|
||||
**Aone Code:** for a clone whose origin is on `gitlab.alibaba-inc.com`, run `/review` from inside that clone — the platform is detected from the remote and the subcommands work, backed by the `a1` CLI (at least 0.1.90 — an older install is refused at authentication time with an upgrade message) — the target number is the global MR id. `fetch-pr` fetches `refs/merge-requests/<id>/head` and builds the worktree + diff, so the agent review of the worktree is unchanged, and `test-plan` works too — it reads the MR description through the same reader. Every Aone run is context-unavailable and several flows are skipped (rather than hitting github.com's same-named repo): `pr-context`/`comment-status` have no Aone backing (the context-unavailable cap keeps an Approve verdict at Comment), `presubmit` is backed only for self-PR detection (the `a1 auth whoami` account vs the MR author) and head drift — its CI and existing-comment checks come back neutral — Agent 0 is skipped, and the `publish-assets` write is skipped. `--comment` **posts** the review through the `a1` CLI: one comment per inline finding, then the summary comment. Aone has no native request-changes state — on that verdict the summary comment carries a blocking header, and any inline Criticals that were actually posted block the merge through the discussion gate while their discussions stay unresolved (when no inline Critical posted, the header is advisory and nothing mechanically blocks the merge). The posted comments carry no AI-comment flag — `a1` cannot set one — so a repo's dedicated `ai_comment` merge gate does not track them. The native `a1 repo mr approve` is wired for an Approve verdict but does not fire this phase: the context-unavailable cap keeps an Approve verdict at Comment (a Request-changes verdict still posts its blocking summary). Incremental re-review follows the AGit-Flow update model: an update AMENDS the single CR commit in place, orphaning the head the previous round reviewed — so the cached anchor is ruled WITHOUT ancestry (the anchor-behind-head test would fail for every update), and the re-review scopes the PR's own diff to the files the update touched instead of falling back to a full review; an update that also rebased onto newer master keeps that scope only while the rebase's drift stays within the CR's files — drift touching any other file falls back to the full review, and no drift byte enters the published scope either way. One caveat for repeat rounds: there is no dedup backing yet, so a second `--comment` round re-posts every still-valid finding as a new comment (self-PR detection IS backed: reviewing your own MR gets the same verdict downgrade as on GitHub). See `docs/design/2026-08-15-review-aone-provider.md`.
|
||||
**Aone Code:** for a clone whose origin is on `gitlab.alibaba-inc.com`, run `/review` from inside that clone — the platform is detected from the remote and the subcommands work, backed by the `a1` CLI (at least 0.1.90 — an older install is refused at authentication time with an upgrade message) — the target number is the global MR id. `fetch-pr` fetches `refs/merge-requests/<id>/head` and builds the worktree + diff, so the agent review of the worktree is unchanged, and `test-plan` works too — it reads the MR description through the same reader. `pr-context` is backed too: it reads the MR's metadata, discussion threads, and previously posted qwen summaries (the machine ledger recovers from them), so an Aone run sees the MR's existing discussion exactly as a GitHub run sees a PR's. Several flows are still skipped or reduced (rather than hitting github.com's same-named repo): `comment-status` has no Aone backing, `presubmit` is backed only for self-PR detection (the `a1 auth whoami` account vs the MR author) and head drift — its CI and existing-comment checks come back neutral — and the `publish-assets` write is skipped. `--comment` **posts** the review through the `a1` CLI: one comment per inline finding, then the summary comment. Aone has no native request-changes state — on that verdict the summary comment carries a blocking header, and any inline Criticals that were actually posted block the merge through the discussion gate while their discussions stay unresolved (when no inline Critical posted, the header is advisory and nothing mechanically blocks the merge). The posted comments carry no AI-comment flag — `a1` cannot set one — so a repo's dedicated `ai_comment` merge gate does not track them. The native `a1 repo mr approve` fires for an Approve verdict when the run read the MR's context (the same gate as GitHub; a context-unavailable run stays capped at Comment). Incremental re-review follows the AGit-Flow update model: an update AMENDS the single CR commit in place, orphaning the head the previous round reviewed — so the cached anchor is ruled WITHOUT ancestry (the anchor-behind-head test would fail for every update), and the re-review scopes the PR's own diff to the files the update touched instead of falling back to a full review; an update that also rebased onto newer master keeps that scope only while the rebase's drift stays within the CR's files — drift touching any other file falls back to the full review, and no drift byte enters the published scope either way. One caveat for repeat rounds: there is no dedup backing yet, so a second `--comment` round re-posts every still-valid finding as a new comment (self-PR detection IS backed: reviewing your own MR gets the same verdict downgrade as on GitHub). See `docs/design/2026-08-15-review-aone-provider.md`.
|
||||
|
||||
Every run ends with one machine-readable line (`Review complete: <target> — <disposition>`), so scripts and CI wrappers can detect completion and outcome with a single `^Review complete: ` match.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue