Commit Graph
6 Commits
Author SHA1 Message Date
Yichen Jiang 6e882cd6e3 fix(forge): confine review writes to the bound pull request and reconcile unknown submissions
A write to a thread or comment now reads, in the head check, the pull
request that holds it and is refused without a mutation when that is
another pull request. Submitting the pending review keeps the
submission to reconcile, so an unknown outcome blocks a second review.
GraphQL errors count as refusals only when every type names one, so a
GitHub timeout reports an unknown outcome. Pending reviews are found
by viewerDidAuthor among up to 100, without the unused commit field. A
resolved thread stays open while the reader writes in it, unsupported
writes no longer poll, and the docs state the partial two-step write.
2026-11-09 14:08:22 +08:00
Yichen Jiang 9f875cf44d Merge remote-tracking branch 'origin/feat/forge-review-threads' into feat/forge-review-writes
# Conflicts:
#	apps/web/tests/forge-panel.e2e.ts
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/subsystems/forge.i18n.yaml
#	docs/subsystems/forge.md
#	docs/subsystems/forge.zh.md
#	packages/experimental/client-ui-forge/README.i18n.yaml
#	packages/experimental/client-ui-forge/README.md
#	packages/experimental/client-ui-forge/README.zh.md
#	packages/experimental/client-ui-forge/src/client/ChangesTab.tsx
#	packages/experimental/client-ui-forge/src/client/mount.ts
#	packages/experimental/client-ui-forge/src/client/thread-state.ts
#	packages/experimental/client-ui-forge/src/index.ts
#	packages/experimental/client-ui-forge/tests/changes-tab.client.spec.tsx
#	packages/experimental/client-ui-forge/tests/mount.client.spec.ts
#	packages/experimental/client-ui-forge/tests/review-cache.host.spec.ts
#	packages/experimental/client-ui-forge/tests/review.host.spec.ts
#	packages/experimental/forge-github/README.i18n.yaml
#	packages/experimental/forge-github/src/threads.ts
#	packages/experimental/forge-github/tests/threads.spec.ts
#	packages/experimental/forge/src/types.ts
#	packages/experimental/forge/tests/registry.spec.ts
#	packages/extensions/tool-cordis/src/api-catalog.ts
2026-11-09 13:03:22 +08:00
Yichen Jiang 1ba5977691 fix(forge-panel): address the review thread findings
- A jump to a thread centered its card on every later jump to the same file, since the jump target outlived the jump.
  The scroll target now carries the card to center and is cleared when the jump ends; unfolding still follows the
  latest thread jump.
- In a commit range view, a thread on a file the chosen commits do not change opened on the host instead of choosing
  all commits; a thread the chosen commits do not hold now always chooses all commits first.
- A quote of an old-side thread named the head as the commit its lines number. It now says the lines number the file
  before the change and names the head only as where the diff ends, and ForgeAnchor documents the same.
- Refresh reads review threads from the host past the panel's cache (`changeRequestReview` takes `fresh`), so a thread
  resolved since shows without waiting for `reviewRefreshMs`; `maxCachedReviewBytes` defaults to 16 MiB, at least
  one read under forge-github's default `maxOutputBytes`.
- Picking a thread from a list that covers the files moves the focus to the thread's card.
- `ForgeReviewData.viewer`, its GraphQL field, `ThreadActions.viewer`, and `ThreadReadState.unsupported` had no
  consumer and are removed.
- A quoted outdated thread is named by the lines it was written on; a missing pull request or repository makes a
  review read `not-found`; a truncated read that kept no thread still offers the thread list.
2026-11-09 12:50:33 +08:00
Yichen Jiang b02529e520 feat(forge): write review threads and the pending review through the provider
ForgeProvider gains an optional writeReview for replies, resolution,
comment edits and deletions, and the viewer's pending review, which
review reads now report with the viewer's permissions. The GitHub
provider checks the head and the pending review in one query, then
sends one GraphQL mutation on stdin and never retries it; a reply at
once is refused while a pending review exists, since GitHub adds it
to that review. The forge panel Remote changeRequestReviewWrite drops
the kept threads after every write, because resolving a thread does
not move a pull request's updatedAt.
2026-11-09 11:21:00 +08:00
Yichen Jiang d6208abfca docs(forge-github): state how review reads bound the first page and which pages re-check the head
A first review thread page whose output alone passes maxOutputBytes fails the read as too-large through gh's output
limit, rather than ending it as truncated as the README and the ReviewLimits documentation said; only a later page
that would pass the limit truncates the read. Thread pages after the first re-check the head, while a thread's comment
pages do not. A test pins the first-page failure.
2026-11-07 18:21:08 +08:00
Yichen Jiang 256e1ae370 feat(forge): read pull request review threads at the displayed head
ForgeProvider gains the optional readReview(ref, headSha, signal), which
returns ForgeReviewData only when the read names headSha as the head and
a stale failure otherwise. Each thread carries a current position on the
head and the original position it was written at; ForgeFailure gains the
unsupported code that ctx.forge.readReview returns for a provider
without review reads.

forge-github reads the threads, the head, and the viewer in one GraphQL
query, pages threads up to maxReviewThreads and comments to their end,
re-checks the head on every following thread page, and bounds all pages
by maxOutputBytes. A thread is placed at the head only when GitHub keeps
it current and its first comment is on the head commit.

The forge panel adds the changeRequestReview Remote, cached per change
request by head and update time and read again after reviewRefreshMs,
since resolving a thread does not change a pull request's updatedAt.
2026-11-07 14:28:39 +08:00