Skip to content

feat(pull-requests): support native Gitea lifecycle actions - #8

Merged
kalvenschraut merged 3 commits into
gitea/ssh-hostsfrom
gitea/lifecycle
Sep 8, 2026
Merged

kalvenschraut merged 3 commits into
gitea/ssh-hostsfrom
gitea/lifecycle

Conversation

@kalvenschraut

@kalvenschraut kalvenschraut commented Sep 5, 2026 •

Copy link
Copy Markdown
Member

Gitea pull requests need reversible draft/ready actions and visible auto-merge state. Map drafts to the configured native title prefixes, verify each transition, and read Gitea’s durable timeline for scheduled/cancelled auto-merges. Enable native scheduling/cancellation, author permissions, and base comparison.

Validation: 41 focused tests passed. Live Gitea 1.27.3 tests verified draft/ready, scheduling with a pending required check, cancellation, and cleanup without merging the PR. The stock API does not expose the armed merge method; a separate Gitea API PR will add it. The final integrated server typecheck passes.

Final stack validation at 256fd6fe5: 228 focused tests passed, followed by 61 API/workflow cases and the final team-recovery regression; server typecheck and targeted lint passed. The live settle-on-merge E2E previously passed with fixture cleanup. Companion Gitea backend and focused integration tests passed, including native revert across all five merge styles.

Model: GPT-5.6 Sol (high), integration review GPT-6 Astra. Harness: Codex.

@kalvenschraut

Copy link
Copy Markdown
Member Author

@coderabbitai review

Please evaluate correctness, regressions, security boundaries, and test coverage against the existing source-control and pull-request integrations. For this fork, main is the clean upstream mirror and rtvision is the integration branch. Review the changes in this PR against its current base; report actionable findings with file references.

@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Repository and branches =='
git remote -v
git status --short
git branch --show-current
git branch -a --no-color | sed -n '1,160p'

echo '== Pull request metadata =='
gh pr view 8 --repo RTVision/t3code --json number,title,baseRefName,baseRefOid,headRefName,headRefOid,changedFiles,additions,deletions,mergeable,state,url

echo '== Merge bases and commit ranges =='
for base in rtvision main; do
  if git rev-parse --verify --quiet "origin/$base" >/dev/null; then
    printf '%s: ' "$base"
    git merge-base HEAD "origin/$base"
  fi
done
git log --oneline --decorate --no-merges "$(git merge-base HEAD origin/rtvision)..HEAD" 2>/dev/null || true

echo '== Changed files against integration base =='
git diff --name-status "$(git merge-base HEAD origin/rtvision)"...HEAD
echo '== Diff stat =='
git diff --stat "$(git merge-base HEAD origin/rtvision)"...HEAD

echo '== Changed source/test outlines =='
git diff --name-only "$(git merge-base HEAD origin/rtvision)"...HEAD \
  | grep -E '\.(ts|tsx|js|jsx|py|go|rs)$' \
  | while IFS= read -r file; do
      [ -f "$file" ] || continue
      echo "--- $file"
      ast-grep outline "$file" --items all 2>/dev/null || true
    done

Length of output: 2558


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='20841bcbd84e2e1348124e25385a9c25b3059fde'
head='582011ec14da9ea9d08e224889bc9870b0fdafbf'

echo '== Verify base and merge base =='
git cat-file -t "$base" || true
git merge-base "$base" "$head" || true

echo '== Changed files =='
git diff --name-status "$base...$head"
git diff --stat "$base...$head"

echo '== Complete pull request patch =='
git diff --find-renames --find-copies --unified=80 "$base...$head"

echo '== Nearby integration modules =='
fd . . --type f \
  | grep -Ei '(gitea|github|gitlab|pull.?request|source.?control)' \
  | sed -n '1,260p'

echo '== Structural map of changed TypeScript files =='
git diff --name-only "$base...$head" \
  | grep -E '\.tsx?$' \
  | while IFS= read -r file; do
      echo "--- $file"
      ast-grep outline "$file" --items all 2>/dev/null || true
    done

Length of output: 84524


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Gitea HTTP request boundary and URL construction =='
ast-grep outline apps/server/src/sourceControl/GiteaApi.ts --items all
sed -n '1,300p' apps/server/src/sourceControl/GiteaApi.ts

echo '== Gitea API focused implementations =='
sed -n '193,352p' apps/server/src/pullRequest/GiteaPullRequestApi.ts
sed -n '565,760p' apps/server/src/pullRequest/GiteaPullRequestApi.ts
sed -n '1100,1300p' apps/server/src/pullRequest/GiteaPullRequestApi.ts
sed -n '1,300p' apps/server/src/pullRequest/GiteaPullRequestProvider.ts

echo '== Contract action and detail semantics =='
rg -n -C 8 'PullRequestAction|autoMergeEnabled|baseComparison|PullRequestViewerPermissions' packages/contracts/src/pullRequest.ts

echo '== Comparable auto-merge and permissions implementations =='
rg -n -C 12 'autoMergeEnabled|getAutoMerge|enable-auto-merge|disable-auto-merge|viewerPermissions|baseComparison' \
  apps/server/src/pullRequest/GitHubPullRequestProvider.ts \
  apps/server/src/pullRequest/GitLabPullRequestProvider.ts \
  apps/server/src/pullRequest/BitbucketPullRequestProvider.ts \
  apps/server/src/pullRequest/AzureDevOpsPullRequestProvider.ts \
  apps/server/src/pullRequest/GitHubPullRequestCli.ts \
  apps/server/src/pullRequest/GitLabPullRequestCli.ts || true

echo '== Existing Gitea pagination call sites =='
rg -n -C 8 'nextPagePath|readUnknownSlice|Link|x-total-count' \
  apps/server/src/pullRequest/GiteaPullRequestApi.ts \
  apps/server/src/pullRequest/GiteaPullRequestApi.test.ts

Length of output: 110756


🤖 web_search executed:

Gitea 1.27.3 API GET /repos/{owner}/{repo}/issues/{index}/timeline pagination order pull_scheduled_merge pull_cancel_scheduled_merge

Length of output: 11158


@kalvenschraut Review complete against PR #8 base gitea/ssh-hosts.

Findings

  1. High — Auto-merge state is incorrect after a full timeline page
    apps/server/src/pullRequest/GiteaPullRequestApi.ts, Line 1206

    getAutoMergeEnabled passes x-total-count to nextPagePath. Gitea 1.27 sets this header to the number of items in the current timeline page, not the total number of timeline items. Therefore, if page 1 contains 50 ordinary events, the response has x-total-count: 50. The code sees rowsSeen === total and stops. It never reads page 2 or later.

    This can report autoMergeEnabled: false when the latest schedule or cancellation event is outside the first page. It can also retain a stale result when a later cancellation event is outside page 1.

    Do not use x-total-count for this timeline endpoint. Continue when pageEvents.length === PAGE_SIZE, or use an endpoint-specific pagination rule that Gitea documents as a true total. Add a test with:

    • A first page of 50 non-lifecycle events.
    • x-total-count: "50".
    • A second page with pull_scheduled_merge or pull_cancel_scheduled_merge.

    Gitea’s 1.27 timeline handler sets the header from the returned page length: https://github.com/go-gitea/gitea/blob/v1.27.2/routers/api/v1/repo/issue_comment.go.

  2. Medium — The Gitea support documentation contradicts the new feature
    docs/user/source-control.md, Line 112

    The new Gitea section documents draft/ready actions and auto-merge controls. The later “Review and merge” section still says that “draft/ready changes” and “auto-merge controls” are unavailable.

    Update the later capability list. Keep only the features that remain unavailable, such as reactions, comment editing, workflow approval, and revert pull requests.

Security boundary

The timeline Link handling does not create a new credential-forwarding boundary. GiteaApi.request rejects URLs outside the configured /api/v1/ root and does not follow redirects.

You are interacting with an AI system.

@kalvenschraut
kalvenschraut marked this pull request as ready for review September 5, 2026 05:57
@kalvenschraut

Copy link
Copy Markdown
Member Author

@coderabbitai review

Please review this PR at its exact current head in stack pingdotgg#6. Verify correctness, regressions, security boundaries, and focused coverage against its current base, and report any actionable findings with file references.

@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='RTVision/t3code'
pr='8'

echo '== Current pull request metadata =='
gh pr view "$pr" --repo "$repo" \
  --json number,title,state,url,baseRefName,baseRefOid,headRefName,headRefOid,changedFiles,additions,deletions

echo '== Local HEAD and branch =='
git status --short
git branch --show-current
git rev-parse HEAD

echo '== Current base and merge base =='
base_ref="$(gh pr view "$pr" --repo "$repo" --json baseRefName --jq .baseRefName)"
head_ref="$(gh pr view "$pr" --repo "$repo" --json headRefName --jq .headRefName)"
git fetch --quiet origin "$base_ref" "$head_ref" || true
base_oid="$(git rev-parse "origin/$base_ref")"
head_oid="$(git rev-parse HEAD)"
merge_base="$(git merge-base "$base_oid" "$head_oid")"
printf 'base_ref=%s\nbase_oid=%s\nhead_ref=%s\nhead_oid=%s\nmerge_base=%s\n' \
  "$base_ref" "$base_oid" "$head_ref" "$head_oid" "$merge_base"

echo '== Commits in current PR range =='
git log --oneline --decorate --no-merges "$merge_base..$head_oid"

echo '== Files in current PR range =='
git diff --name-status --find-renames "$merge_base...$head_oid"
git diff --stat "$merge_base...$head_oid"

echo '== Changed TypeScript file structure =='
git diff --name-only "$merge_base...$head_oid" \
  | grep -E '\.(ts|tsx)$' \
  | while IFS= read -r file; do
      test -f "$file" || continue
      echo "--- $file"
      ast-grep outline "$file" --items all 2>/dev/null || true
    done

echo '== Patch =='
git diff --find-renames --unified=45 "$merge_base...$head_oid"

Length of output: 2539


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='0b6bf7c20edb07f47180fd9385a2ac3375e73a2c'
head='39a28c350b81b130f9bb4eda3e41172fd69f17d3'

echo '== Verify immutable review endpoints =='
git cat-file -t "$base"
git cat-file -t "$head"
printf 'merge_base=%s\n' "$(git merge-base "$base" "$head")"

echo '== Current PR commits =='
git log --oneline --decorate --no-merges "$base..$head"

echo '== Current PR files and stats =='
git diff --name-status --find-renames "$base...$head"
git diff --stat "$base...$head"

echo '== Changed source and test structure =='
git diff --name-only "$base...$head" \
  | grep -E '\.(ts|tsx)$' \
  | while IFS= read -r file; do
      test -f "$file" || continue
      echo "--- $file"
      ast-grep outline "$file" --items all 2>/dev/null || true
    done

echo '== Current PR patch =='
git diff --find-renames --unified=45 "$base...$head"

Length of output: 61686


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Pagination and Gitea API request boundary =='
sed -n '300,420p' apps/server/src/pullRequest/GiteaPullRequestApi.ts
ast-grep outline apps/server/src/sourceControl/GiteaApi.ts --items all
sed -n '1,310p' apps/server/src/sourceControl/GiteaApi.ts

echo '== Changed action and detail implementation =='
sed -n '565,710p' apps/server/src/pullRequest/GiteaPullRequestApi.ts
sed -n '1280,1470p' apps/server/src/pullRequest/GiteaPullRequestApi.ts
sed -n '100,205p' apps/server/src/pullRequest/GiteaPullRequestProvider.ts
sed -n '1,180p' apps/server/src/pullRequest/GiteaLifecycle.ts

echo '== Pull-request detail contract and other provider behavior =='
rg -n -C 8 'autoMergeEnabled|baseComparison|PullRequestViewerPermissions|enable-auto-merge|disable-auto-merge' \
  packages/contracts apps/server/src/pullRequest \
  -g '*.ts' \
  -g '!apps/server/src/pullRequest/GiteaPullRequestApi.ts' \
  -g '!apps/server/src/pullRequest/GiteaPullRequestProvider.ts' \
  -g '!apps/server/src/pullRequest/GiteaPullRequestApi.test.ts' \
  -g '!apps/server/src/pullRequest/GiteaPullRequestProvider.test.ts' \
  -g '!apps/server/src/pullRequest/GiteaLifecycle.ts' \
  -g '!apps/server/src/pullRequest/GiteaLifecycle.test.ts' \
  | sed -n '1,1000p'

echo '== Gitea test setup and full changed test portions =='
sed -n '1,130p' apps/server/src/pullRequest/GiteaPullRequestApi.test.ts
sed -n '850,1120p' apps/server/src/pullRequest/GiteaPullRequestApi.test.ts
sed -n '1,160p' apps/server/src/pullRequest/GiteaPullRequestProvider.test.ts

echo '== References to the timeline endpoint and pagination helper =='
rg -n -C 5 'issues/.*/timeline|nextPagePath\(' apps/server/src \
  -g '*.ts'

Length of output: 153682


🤖 web_search executed:

In the Gitea v1.27.3 source, how does GET /api/v1/repos/{owner}/{repo}/issues/{index}/timeline set the X-Total-Count response header? Does it contain the count of the current page or the total matching timeline events? Cite the relevant source file and lines.

Length of output: 11260


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Remaining Gitea provider methods =='
sed -n '180,300p' apps/server/src/pullRequest/GiteaPullRequestProvider.ts

echo '== Permission refresh in action service =='
sed -n '1180,1285p' apps/server/src/pullRequest/PullRequestService.ts

echo '== Exact changed line ranges =='
nl -ba apps/server/src/pullRequest/GiteaPullRequestApi.ts | sed -n '360,415p;1178,1230p;1285,1455p'
nl -ba apps/server/src/pullRequest/GiteaPullRequestProvider.ts | sed -n '1,115p;145,205p'
nl -ba docs/user/source-control.md | sed -n '65,125p'

echo '== Provider construction test coverage =='
rg -n -C 6 'GiteaPullRequestProvider\.layer|GiteaPullRequestProvider\.make|getChangeRequest\(' \
  apps/server/src/pullRequest \
  -g '*Gitea*test.ts' \
  -g '*.test.ts'

Length of output: 10078


🏁 Script executed:

#!/bin/bash
set -euo pipefail

numbered() {
  awk -v start="$2" -v end="$3" 'NR >= start && NR <= end { printf "%6d  %s\n", NR, $0 }' "$1"
}

echo '== Auto-merge pagination implementation =='
numbered apps/server/src/pullRequest/GiteaPullRequestApi.ts 386 405
numbered apps/server/src/pullRequest/GiteaPullRequestApi.ts 1184 1225

echo '== Auto-merge pagination tests =='
numbered apps/server/src/pullRequest/GiteaPullRequestApi.test.ts 990 1045

echo '== Current Gitea capability documentation =='
numbered docs/user/source-control.md 72 125

echo '== Current provider detail tests that exercise timeline state =='
rg -n -C 4 'getAutoMergeEnabled|autoMergeEnabled|timeline' \
  apps/server/src/pullRequest/GiteaPullRequestProvider.test.ts \
  apps/server/src/pullRequest/GiteaPullRequestApi.test.ts

Length of output: 14030


@kalvenschraut Review complete at current head 39a28c35, against base 0b6bf7c2.

Findings

  1. High — The timeline reader still stops after the first full page.
    apps/server/src/pullRequest/GiteaPullRequestApi.ts, Line 1206

    getAutoMergeEnabled uses nextPagePath. That helper treats X-Total-Count as the total number of timeline events at Lines 396-399.

    Gitea 1.27 sets this header to len(apiComments) for the timeline endpoint. The header is the count of the returned page, not the total count. Therefore, if page 1 contains 50 events, Gitea returns X-Total-Count: 50. The code sees rowsSeen === total and does not request page 2.

    This can report autoMergeEnabled: false when the latest schedule event is on a later page. It can also retain an outdated state when a later cancellation event is on a later page.

    Do not use X-Total-Count for this endpoint. Continue while pageEvents.length === PAGE_SIZE, unless Gitea supplies a valid Link: rel="next" value. Add a regression test where:

    • Page 1 contains 50 non-lifecycle events.
    • Page 1 has X-Total-Count: "50".
    • Page 2 contains pull_scheduled_merge or pull_cancel_scheduled_merge.

    Gitea v1.27 sets the timeline header from len(apiComments): https://github.com/go-gitea/gitea/blob/v1.27.2/routers/api/v1/repo/issue_comment.go.

  2. Medium — The Gitea capability documentation is internally inconsistent.
    docs/user/source-control.md, Line 116

    Lines 73-76 state that T3 supports verified draft/ready transitions and native auto-merge scheduling. Lines 116-119 still state that draft/ready changes and auto-merge controls are unavailable.

    Update the “Review and merge” Gitea capability list. Keep only the unsupported features, such as reactions, comment editing, workflow approval, and revert pull requests.

Security boundary

I found no additional credential-forwarding issue in timeline pagination. GiteaApi.request rejects pagination URLs outside the configured /api/v1/ root and does not follow redirects.

You are interacting with an AI system.

@kalvenschraut

Copy link
Copy Markdown
Member Author

Addressed both findings in 3c866b6f6.

  • Timeline pagination now ignores this route's page-length X-Total-Count, follows Link: rel="next" when present, and otherwise continues after a full 50-row page. The regression covers X-Total-Count: 50 with the schedule event on page 2, plus a linked page-2 cancellation.
  • The Gitea capability paragraph now lists draft/ready transitions and auto-merge controls as supported.

Focused lifecycle/API tests: 35 passed. Targeted lint passed.

@kalvenschraut

Copy link
Copy Markdown
Member Author

@coderabbitai review

Please review this PR at its exact current head in stack pingdotgg#6. Verify correctness, regressions, security boundaries, and focused coverage against its current base, and report any actionable findings with file references.

@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='RTVision/t3code'
pr='8'

echo '== Pull request metadata =='
gh pr view "$pr" --repo "$repo" \
  --json number,title,state,url,baseRefName,baseRefOid,headRefName,headRefOid,changedFiles,additions,deletions

base_ref="$(gh pr view "$pr" --repo "$repo" --json baseRefName --jq .baseRefName)"
head_ref="$(gh pr view "$pr" --repo "$repo" --json headRefName --jq .headRefName)"
git fetch --quiet origin "$base_ref" "$head_ref"

base_oid="$(git rev-parse "origin/$base_ref")"
head_oid="$(git rev-parse HEAD)"
merge_base="$(git merge-base "$base_oid" "$head_oid")"
printf '\n== Exact review range ==\nbase_ref=%s\nbase_oid=%s\nhead_ref=%s\nhead_oid=%s\nmerge_base=%s\n' \
  "$base_ref" "$base_oid" "$head_ref" "$head_oid" "$merge_base"

echo '== Commits =='
git log --oneline --decorate --no-merges "$merge_base..$head_oid"

echo '== Changed files =='
git diff --name-status --find-renames "$merge_base...$head_oid"
git diff --stat "$merge_base...$head_oid"

echo '== Changed TypeScript outlines =='
git diff --name-only "$merge_base...$head_oid" \
  | grep -E '\.(ts|tsx)$' \
  | while IFS= read -r file; do
      test -f "$file" || continue
      echo "--- $file"
      ast-grep outline "$file" --items all 2>/dev/null || true
    done

echo '== Patch =='
git diff --find-renames --unified=55 "$merge_base...$head_oid"

Length of output: 2262


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='RTVision/t3code'
base='0b6bf7c20edb07f47180fd9385a2ac3375e73a2c'
head='3c866b6f6b26ebfc9f044ab8ba31c634dc4b516b'

ensure_commit() {
  local oid="$1"
  if ! git cat-file -e "${oid}^{commit}" 2>/dev/null; then
    git fetch --quiet "https://github.com/${repo}.git" "$oid"
  fi
}

ensure_commit "$base"
ensure_commit "$head"

echo '== Immutable review range =='
printf 'local_head=%s\n' "$(git rev-parse HEAD)"
printf 'base=%s\nhead=%s\nmerge_base=%s\n' \
  "$base" "$head" "$(git merge-base "$base" "$head")"
git show -s --format='base: %H %s%nhead: %H %s' "$base" "$head"

echo '== Files and patch =='
git diff --name-status --find-renames "$base...$head"
git diff --stat "$base...$head"
git diff --find-renames --unified=45 "$base...$head"

echo '== Changed TypeScript outlines =='
git diff --name-only "$base...$head" | grep -E '\.tsx?$' | while IFS= read -r file; do
  echo "--- $file"
  git show "$head:$file" > "/tmp/$(basename "$file")"
  ast-grep outline "/tmp/$(basename "$file")" --items all 2>/dev/null || true
done

echo '== Relevant current source with line numbers =='
git show "$head:apps/server/src/pullRequest/GiteaPullRequestApi.ts" \
  | nl -ba | sed -n '350,435p;555,725p;1140,1260p;1260,1500p'
git show "$head:apps/server/src/pullRequest/GiteaPullRequestProvider.ts" \
  | nl -ba | sed -n '1,280p'
git show "$head:apps/server/src/pullRequest/GiteaLifecycle.ts" \
  | nl -ba | sed -n '1,260p'

Length of output: 63756


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head='3c866b6f6b26ebfc9f044ab8ba31c634dc4b516b'

show_range() {
  local file="$1" start="$2" end="$3"
  echo "--- $file:$start-$end"
  git show "$head:$file" | sed -n "${start},${end}p" | awk -v n="$start" '{printf "%6d  %s\n", n++, $0}'
}

echo '== Gitea pagination and request boundary =='
show_range apps/server/src/pullRequest/GiteaPullRequestApi.ts 300 410
show_range apps/server/src/pullRequest/GiteaPullRequestApi.ts 565 660
show_range apps/server/src/pullRequest/GiteaPullRequestApi.ts 1170 1290
show_range apps/server/src/pullRequest/GiteaPullRequestApi.ts 1390 1465
show_range apps/server/src/sourceControl/GiteaApi.ts 1 330

echo '== Provider and lifecycle code =='
show_range apps/server/src/pullRequest/GiteaLifecycle.ts 1 140
show_range apps/server/src/pullRequest/GiteaPullRequestProvider.ts 1 260

echo '== Contract and action authorization paths =='
git show "$head:packages/contracts/src/pullRequest.ts" \
  | grep -n -E -C 8 'PullRequestAction|autoMergeEnabled|baseComparison|PullRequestViewerPermissions'
git show "$head:apps/server/src/pullRequest/PullRequestService.ts" \
  | grep -n -E -C 12 'viewerPermissions|enable-auto-merge|disable-auto-merge|runAction'

echo '== Comparable provider detail loading and permissions =='
for file in \
  apps/server/src/pullRequest/GitHubPullRequestProvider.ts \
  apps/server/src/pullRequest/GitLabPullRequestProvider.ts \
  apps/server/src/pullRequest/BitbucketPullRequestProvider.ts \
  apps/server/src/pullRequest/AzureDevOpsPullRequestProvider.ts; do
  git cat-file -e "$head:$file" 2>/dev/null || continue
  echo "--- $file"
  git show "$head:$file" | grep -n -E -C 8 'getAutoMergeEnabled|autoMergeEnabled|baseComparison|viewerPermissions|enable-auto-merge|disable-auto-merge'
done

echo '== Gitea provider/API test references and test setup =='
git show "$head:apps/server/src/pullRequest/GiteaPullRequestApi.test.ts" \
  | grep -n -E -C 10 'getAutoMergeEnabled|timeline|draft|ready|enable-auto-merge|disable-auto-merge|layer'
git show "$head:apps/server/src/pullRequest/GiteaPullRequestProvider.test.ts" \
  | sed -n '1,220p' | awk '{printf "%6d  %s\n", NR, $0}'

Length of output: 101167


🤖 web_search executed:

Gitea v1.27.3 source API resolve pull request review comment permission author without repository write access endpoint

Length of output: 20739


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head='3c866b6f6b26ebfc9f044ab8ba31c634dc4b516b'

echo '== Optional auto-merge field consumers =='
git grep -n -E 'autoMergeEnabled|autoMergeMethod' "$head" -- \
  'apps/**' 'packages/**' | sed -n '1,320p'

echo '== Detail and provider test construction =='
git grep -n -E -C 10 'getChangeRequest:|getAutoMergeEnabled|autoMergeEnabled|GiteaPullRequestProvider\.layer|GiteaPullRequestProvider\.make' \
  "$head" -- 'apps/server/src/pullRequest' \
  | sed -n '1,900p'

echo '== Optional enrichment patterns in all providers =='
git grep -n -E -C 8 'Effect\.orElseSucceed|autoMergeEnabled|Effect\.all' \
  "$head" -- 'apps/server/src/pullRequest/*Provider.ts' \
  | sed -n '1,1000p'

Length of output: 179626


🤖 web_search executed:

site:github.com/go-gitea/gitea/blob/v1.27.2 "func CanMarkConversation" Gitea

Length of output: 20126


@kalvenschraut Review complete at head 3c866b6f6, against base 0b6bf7c2.

Finding

  1. Medium — A timeline-read failure now prevents the pull request detail from loading
    apps/server/src/pullRequest/GiteaPullRequestProvider.ts, Line 160

    getChangeRequest includes api.getAutoMergeEnabled(input) in the required Effect.all. If the timeline endpoint returns an error, times out, returns malformed data, or reaches the pagination bound, the complete detail request fails.

    autoMergeEnabled is optional in ProviderChangeRequestDetail. The existing provider behavior degrades unavailable enrichment data. For example, Line 171 degrades a failed checks read to []. The contract also distinguishes an absent auto-merge value from false.

    Make the timeline read degrade to undefined on failure. Preserve the detail response and omit autoMergeEnabled when Gitea cannot provide a trustworthy state. Add a provider-level regression test that fails getAutoMergeEnabled while the pull request, repository access, and viewer reads succeed.

Verified

  • The timeline reader now ignores the route-specific page-length X-Total-Count.
  • The reader follows Link: rel="next" and otherwise continues after a full page.
  • The new tests cover both corrected pagination paths.
  • Pagination links remain within the configured Gitea API root. GiteaApi.request rejects external URLs and does not follow redirects.

You are interacting with an AI system.

@kalvenschraut

Copy link
Copy Markdown
Member Author

Fixed the latest review finding in 9276180. Pull-request detail now treats the Gitea timeline lookup as optional enrichment: a failed timeline read omits autoMergeEnabled while preserving the core detail and checks. Added a provider-level regression through the real Gitea adapter layer. Validation: 42 focused Gitea provider/API/lifecycle tests passed; targeted lint passed.

@kalvenschraut

Copy link
Copy Markdown
Member Author

Merge verdict: NO-GO (review gates incomplete).

Head: 92761803ad9ee6d548af49b2965323ae28806018.

  • Codex: NO-GO for merging under the requested two-reviewer gate. Merge readiness and review history were checked; the full dual code review is incomplete, and this comment is not a code approval.
  • Fable 5.1 / Claude CLI: BLOCKED. The requested claude-fable-5-1 review was attempted, but the CLI reached its session limit before returning a completed verdict. Its reported reset is midnight America/Chicago. There is no fresh Fable GO from this pass.
  • CodeRabbit: No formal APPROVED review. The successful CodeRabbit status check does not satisfy the requested approval gate. This branch has not enabled reviews.request_changes_workflow; the existing CodeRabbit replies on this series identify that configuration as preventing formal approvals.
  • GitHub merge state: MERGEABLE / CLEAN against gitea/ssh-hosts.
  • Checks: the current rollup contains a successful CodeRabbit status only; it contains no build/test check result. No new tests or browser verification are claimed by this audit.

No merge performed. Resume the independent code reviews when Fable is available, obtain the missing/current CodeRabbit approval where applicable, and recheck the exact head and base before merging.

@kalvenschraut

Copy link
Copy Markdown
Member Author

@coderabbitai approve

The maintainer requests formal approval for the remaining PRs. Please assess the exact current head 92761803ad9ee6d548af49b2965323ae28806018 and submit APPROVED only if your review has no remaining blockers. If there is a blocker, leave its concrete reason and the fix required instead. A successful status check alone does not meet this merge gate.

If branch configuration prevents formal approval, please state that explicitly. Independent Codex/Fable code verdicts are being refreshed separately; this request does not authorize merging or bypassing their findings.

@coderabbitai

coderabbitai Bot commented Sep 7, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='RTVision/t3code'
pr='8'
requested_head='92761803ad9ee6d548af49b2965323ae28806018'

echo '== Pull request metadata =='
gh pr view "$pr" --repo "$repo" \
  --json number,state,url,baseRefName,baseRefOid,headRefName,headRefOid,mergeable,reviewDecision,statusCheckRollup

base_ref="$(gh pr view "$pr" --repo "$repo" --json baseRefName --jq .baseRefName)"
base_oid="$(gh pr view "$pr" --repo "$repo" --json baseRefOid --jq .baseRefOid)"
head_oid="$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq .headRefOid)"

printf '\n== Requested and current endpoints ==\nrequested_head=%s\nbase_ref=%s\nbase_oid=%s\nhead_oid=%s\n' \
  "$requested_head" "$base_ref" "$base_oid" "$head_oid"

for oid in "$base_oid" "$requested_head"; do
  if ! git cat-file -e "${oid}^{commit}" 2>/dev/null; then
    git fetch --quiet "https://github.com/${repo}.git" "$oid"
  fi
done

test "$head_oid" = "$requested_head"
merge_base="$(git merge-base "$base_oid" "$requested_head")"
printf 'merge_base=%s\n' "$merge_base"
git show -s --format='base: %H%n  %s%nhead: %H%n  %s' "$base_oid" "$requested_head"

echo '== Commits and changed files =='
git log --oneline --no-merges "$merge_base..$requested_head"
git diff --name-status --find-renames "$merge_base...$requested_head"
git diff --stat "$merge_base...$requested_head"

echo '== Changed code structure =='
git diff --name-only "$merge_base...$requested_head" \
  | grep -E '\.(ts|tsx|js|jsx)$' \
  | while IFS= read -r file; do
      echo "--- $file"
      git show "$requested_head:$file" > "/tmp/$(basename "$file")"
      ast-grep outline "/tmp/$(basename "$file")" --items all 2>/dev/null || true
    done

echo '== Complete final patch =='
git diff --find-renames --unified=55 "$merge_base...$requested_head"

echo '== Key implementation and tests =='
for spec in \
  'apps/server/src/pullRequest/GiteaPullRequestApi.ts:350:430' \
  'apps/server/src/pullRequest/GiteaPullRequestApi.ts:560:730' \
  'apps/server/src/pullRequest/GiteaPullRequestApi.ts:1160:1285' \
  'apps/server/src/pullRequest/GiteaPullRequestApi.ts:1285:1485' \
  'apps/server/src/pullRequest/GiteaPullRequestProvider.ts:1:280' \
  'apps/server/src/pullRequest/GiteaLifecycle.ts:1:260' \
  'apps/server/src/sourceControl/GiteaApi.ts:1:340' \
  'apps/server/src/pullRequest/GiteaPullRequestApi.test.ts:900:1125' \
  'apps/server/src/pullRequest/GiteaPullRequestProvider.test.ts:1:300' \
  'packages/contracts/src/pullRequest.ts:1:400' \
  'docs/user/source-control.md:60:130'
do
  IFS=':' read -r file start end <<< "$spec"
  git cat-file -e "$requested_head:$file" 2>/dev/null || continue
  echo "--- $file (Lines $start-$end)"
  git show "$requested_head:$file" | sed -n "${start},${end}p" \
    | awk -v n="$start" '{printf "%6d  %s\n", n++, $0}'
done

echo '== Gitea action authorization and detail consumers =='
git grep -n -E -C 10 \
  'viewerPermissions|runAction|enable-auto-merge|disable-auto-merge|autoMergeEnabled|baseComparison' \
  "$requested_head" -- apps/server/src packages/contracts/src \
  | sed -n '1,1400p'

Length of output: 203572


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='RTVision/t3code'
pr='8'
head='92761803ad9ee6d548af49b2965323ae28806018'

echo '== Exact PR state =='
gh pr view "$pr" --repo "$repo" \
  --json state,baseRefName,baseRefOid,headRefName,headRefOid,mergeable,reviewDecision \
  --jq '{state, baseRefName, baseRefOid, headRefName, headRefOid, mergeable, reviewDecision}'
base="$(gh pr view "$pr" --repo "$repo" --json baseRefOid --jq .baseRefOid)"
test "$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq .headRefOid)" = "$head"
echo "merge_base=$(git merge-base "$base" "$head")"
echo '== Commit list and changed files =='
git log --oneline --no-merges "$base..$head"
git diff --name-status "$base...$head"

show () {
  local file="$1" start="$2" end="$3"
  echo "--- $file (Lines $start-$end)"
  git show "$head:$file" | sed -n "${start},${end}p" | nl -ba -v "$start"
}

echo '== Pagination helpers and lifecycle reader =='
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 300 430
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 1160 1225
show apps/server/src/pullRequest/GiteaLifecycle.ts 1 120
show apps/server/src/sourceControl/GiteaApi.ts 1 260

echo '== Permissions, actions, and base comparison =='
show apps/server/src/pullRequest/GiteaPullRequestProvider.ts 1 205
show apps/server/src/pullRequest/GiteaPullRequestProvider.ts 205 305
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 1218 1285
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 1390 1495

echo '== Focused test cases =='
rg -n -C 18 \
  'getAutoMergeEnabled|full.*page|X-Total-Count|rel="next"|timeline|omits.*autoMerge|autoMergeEnabled' \
  apps/server/src/pullRequest/GiteaPullRequestApi.test.ts \
  apps/server/src/pullRequest/GiteaPullRequestProvider.test.ts \
  apps/server/src/pullRequest/GiteaLifecycle.test.ts

echo '== Diff for final fix commit =='
git diff --find-renames --unified=45 '3c866b6f6b26ebfc9f044ab8ba31c634dc4b516b..92761803ad9ee6d548af49b2965323ae28806018'

echo '== API request-boundary tests =='
rg -n -C 12 'api root|outside|external|redirect|Link|nextLink|pagination' \
  apps/server/src/sourceControl/GiteaApi.test.ts \
  apps/server/src/pullRequest/GiteaPullRequestApi.test.ts

Length of output: 3678


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head='92761803ad9ee6d548af49b2965323ae28806018'

show () {
  local file="$1" start="$2" end="$3"
  echo "--- $file (Lines $start-$end)"
  git show "$head:$file" | sed -n "${start},${end}p" \
    | awk -v n="$start" '{printf "%6d  %s\n", n++, $0}'
}

echo '== Pagination helpers and lifecycle reader =='
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 300 430
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 1160 1225
show apps/server/src/pullRequest/GiteaLifecycle.ts 1 120
show apps/server/src/sourceControl/GiteaApi.ts 1 260

echo '== Permissions, actions, and base comparison =='
show apps/server/src/pullRequest/GiteaPullRequestProvider.ts 1 205
show apps/server/src/pullRequest/GiteaPullRequestProvider.ts 205 305
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 1218 1285
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 1390 1495

echo '== Focused test cases =='
rg -n -C 18 \
  'getAutoMergeEnabled|full.*page|X-Total-Count|rel="next"|timeline|omits.*autoMerge|autoMergeEnabled' \
  apps/server/src/pullRequest/GiteaPullRequestApi.test.ts \
  apps/server/src/pullRequest/GiteaPullRequestProvider.test.ts \
  apps/server/src/pullRequest/GiteaLifecycle.test.ts

echo '== Diff for final fix commit =='
git diff --find-renames --unified=45 \
  '3c866b6f6b26ebfc9f044ab8ba31c634dc4b516b..92761803ad9ee6d548af49b2965323ae28806018'

echo '== API request-boundary tests =='
rg -n -C 12 'api root|outside|external|redirect|Link|nextLink|pagination' \
  apps/server/src/sourceControl/GiteaApi.test.ts \
  apps/server/src/pullRequest/GiteaPullRequestApi.test.ts

Length of output: 95087


🤖 web_search executed:

In the Gitea v1.27.3 source code, for GET /api/v1/repos/{owner}/{repo}/issues/{index}/timeline, what exact format does the Link: rel="next" pagination header use? Provide the source file and the relevant code or lines. Confirm whether it is an absolute URL or an API-root-relative URL.

Length of output: 12469


@kalvenschraut Approved.

I reviewed exact head 92761803ad9ee6d548af49b2965323ae28806018 against base 0b6bf7c20edb07f47180fd9385a2ac3375e73a2c.

I found no remaining blocker.

The timeline reader now handles Gitea’s page-length X-Total-Count correctly. It follows valid pagination links and uses the full-page fallback that the Gitea 1.27 timeline endpoint requires. The API root and redirect controls preserve the credential boundary. The final provider fix correctly treats timeline state as optional enrichment. Focused regression coverage exercises the failure path through the Gitea adapter layer.

[approve]

You are interacting with an AI system.

@kalvenschraut

Copy link
Copy Markdown
Member Author

Merge verdict: NO-GO. This supersedes the earlier quota-only readiness comment.

Reviewed head: 92761803ad9ee6d548af49b2965323ae28806018; declared destination: gitea/ssh-hosts.

  • Codex: GO. Timeline continuation and optional-enrichment failure handling are present in this exact head. No blocking defect found in this change.
  • Fable 5.1 / Claude CLI: GO, completed independent review of 92761803ad9e.
  • CodeRabbit: No formal GitHub APPROVED review on this head. Approval was requested. Some bot replies say “Approved” or contain [approve], but the GitHub review records do not contain an approval; this does not pass the requested gate. The original branch configuration does not enable reviews.request_changes_workflow.

Validation: 339 focused integrated PR tests plus 502 cross-provider tests passed at integration head 6114cf39; the integrated server typecheck passed. These checks validate the integrated implementation, not every earlier PR snapshot. The original #12 compiler failure was reproduced separately.

No merge is authorized while any blocker or required approval is outstanding. Recheck the resulting head and current base after corrections or stack merges.

This PR also belongs to the native Gitea stack: merging it would merge lower open members, including blocked #4/#5. Those predecessor gates must pass too.

@kalvenschraut

Copy link
Copy Markdown
Member Author

GO on the individual change — merge blocked by stack

Reviewed commit: 92761803ad9ee6d548af49b2965323ae28806018.

Codex and Claude Fable 5.1 both approve the reviewed lifecycle head, including its timeline paging and tolerated timeline failure. Later branches were cut before some of these fixes, so preserve them when reconciling the stack.

GitHub native-stack merging includes preceding PRs, including blocked #5. Hold the merge until the required predecessor fixes are cleared.

Validation by Codex: the exact #36 integration head 6114cf39dac017bd665908effd538e5f4f8d5764 passed 1,002 tests across 39 affected files, scoped server/web/desktop typechecks, and targeted lint (warnings, no errors). These are integration results, not a claim that this standalone head passed those checks. Fable independently reviewed source and diffs via Claude CLI; it did not run the tests.

Reviewers: Codex and Claude Fable 5.1 (Claude CLI).

@kalvenschraut

Copy link
Copy Markdown
Member Author

@coderabbitai review

Please independently review the newly pushed fixes at c169fc23f476c5263045cff486985890d49e5860 and submit a formal GitHub approval on this head only if no blockers remain. Otherwise report the remaining actionable findings. The maintainer requested fresh CodeRabbit approval before merging; an older approval or a green skipped-review status does not satisfy that gate. Codex and Claude Fable 5.1 are separately re-reviewing the changes, including the prior no-go findings in this PR.

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='RTVision/t3code'
pr='8'
requested_head='c169fc23f476c5263045cff486985890d49e5860'

echo '== Pull request metadata =='
gh pr view "$pr" --repo "$repo" \
  --json number,state,url,baseRefName,baseRefOid,headRefName,headRefOid,mergeable,reviewDecision,statusCheckRollup

base_ref="$(gh pr view "$pr" --repo "$repo" --json baseRefName --jq .baseRefName)"
base_oid="$(gh pr view "$pr" --repo "$repo" --json baseRefOid --jq .baseRefOid)"
current_head="$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq .headRefOid)"

for oid in "$base_oid" "$requested_head"; do
  if ! git cat-file -e "${oid}^{commit}" 2>/dev/null; then
    git fetch --quiet "https://github.com/${repo}.git" "$oid"
  fi
done

printf '\n== Exact review range ==\nrequested_head=%s\ncurrent_head=%s\nbase_ref=%s\nbase_oid=%s\n' \
  "$requested_head" "$current_head" "$base_ref" "$base_oid"
test "$current_head" = "$requested_head"
merge_base="$(git merge-base "$base_oid" "$requested_head")"
printf 'merge_base=%s\n' "$merge_base"
git show -s --format='base: %H%n  %s%nhead: %H%n  %s' "$base_oid" "$requested_head"

echo '== Commits and changed files =='
git log --oneline --no-merges "$merge_base..$requested_head"
git diff --name-status --find-renames "$merge_base...$requested_head"
git diff --stat "$merge_base...$requested_head"

echo '== Changed code structure =='
git diff --name-only "$merge_base...$requested_head" \
  | grep -E '\.(ts|tsx|js|jsx)$' \
  | while IFS= read -r file; do
      echo "--- $file"
      git show "$requested_head:$file" > "/tmp/$(basename "$file")"
      ast-grep outline "/tmp/$(basename "$file")" --items all 2>/dev/null || true
    done

echo '== Complete patch =='
git diff --find-renames --unified=45 "$merge_base...$requested_head"

Length of output: 68431


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head='c169fc23f476c5263045cff486985890d49e5860'

show() {
  local file="$1" start="$2" end="$3"
  echo "--- $file (Lines $start-$end)"
  git show "$head:$file" | sed -n "${start},${end}p" | nl -ba -v "$start"
}

echo '== Lifecycle and pagination implementation =='
show apps/server/src/pullRequest/GiteaLifecycle.ts 1 140
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 300 430
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 565 700
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 1160 1280
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 1320 1465

echo '== Gitea request security boundary =='
show apps/server/src/sourceControl/GiteaApi.ts 1 330

echo '== Provider, action authorization, and contracts =='
show apps/server/src/pullRequest/GiteaPullRequestProvider.ts 1 300
git show "$head:apps/server/src/pullRequest/PullRequestService.ts" \
  | nl -ba \
  | grep -E -C 14 'viewerPermissions|runAction|enable-auto-merge|disable-auto-merge|action' \
  | sed -n '1,1100p'
git show "$head:packages/contracts/src/pullRequest.ts" \
  | nl -ba \
  | grep -E -C 10 'PullRequestAction|PullRequestViewerPermissions|ProviderChangeRequestDetail|autoMergeEnabled|baseComparison' \
  | sed -n '1,800p'

echo '== Focused current tests =='
show apps/server/src/pullRequest/GiteaLifecycle.test.ts 1 180
show apps/server/src/pullRequest/GiteaPullRequestApi.test.ts 1120 1410
show apps/server/src/pullRequest/GiteaPullRequestProvider.test.ts 1 260

echo '== Test and implementation references for Gitea actions =='
git grep -n -E -C 6 \
  'giteaViewerPermissions|setThreadResolution|resolve|titleForDraftAction|getAutoMergeEnabled|enable-auto-merge' \
  "$head" -- apps/server/src/pullRequest packages/contracts/src \
  | sed -n '1,1400p'

Length of output: 2242


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head='c169fc23f476c5263045cff486985890d49e5860'

show() {
  local file="$1" start="$2" end="$3"
  echo "--- $file (Lines $start-$end)"
  git show "$head:$file" | sed -n "${start},${end}p" \
    | awk -v n="$start" '{printf "%6d  %s\n", n++, $0}'
}

echo '== Lifecycle and pagination implementation =='
show apps/server/src/pullRequest/GiteaLifecycle.ts 1 140
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 300 430
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 565 700
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 1160 1280
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 1320 1465

echo '== Gitea request security boundary =='
show apps/server/src/sourceControl/GiteaApi.ts 1 330

echo '== Provider and contracts =='
show apps/server/src/pullRequest/GiteaPullRequestProvider.ts 1 300
git show "$head:apps/server/src/pullRequest/PullRequestService.ts" \
  | awk '{printf "%6d  %s\n", NR, $0}' \
  | grep -E -C 14 'viewerPermissions|runAction|enable-auto-merge|disable-auto-merge' \
  | sed -n '1,1100p'
git show "$head:packages/contracts/src/pullRequest.ts" \
  | awk '{printf "%6d  %s\n", NR, $0}' \
  | grep -E -C 10 'PullRequestAction|PullRequestViewerPermissions|autoMergeEnabled|baseComparison' \
  | sed -n '1,800p'

echo '== Focused current tests =='
show apps/server/src/pullRequest/GiteaLifecycle.test.ts 1 180
show apps/server/src/pullRequest/GiteaPullRequestApi.test.ts 1120 1410
show apps/server/src/pullRequest/GiteaPullRequestProvider.test.ts 1 260

echo '== Existing Gitea resolution and action call paths =='
git grep -n -E -C 6 \
  'setThreadResolution|giteaViewerPermissions|titleForDraftAction|getAutoMergeEnabled|enable-auto-merge' \
  "$head" -- apps/server/src/pullRequest packages/contracts/src \
  | sed -n '1,1400p'

Length of output: 241768


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head='c169fc23f476c5263045cff486985890d49e5860'
previous='92761803ad9ee6d548af49b2965323ae28806018'

show() {
  local file="$1" start="$2" end="$3"
  echo "--- $file (Lines $start-$end)"
  git show "$head:$file" | sed -n "${start},${end}p" \
    | awk -v n="$start" '{printf "%6d  %s\n", n++, $0}'
}

echo '== Final commit =='
git show --find-renames --stat --oneline "$head"
git diff --find-renames --unified=60 "$previous..$head"

echo '== Repository access and pull request mapping =='
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 240 310
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 700 800
show apps/server/src/pullRequest/GiteaPullRequestApi.ts 1640 1690

echo '== Request-boundary tests =='
fd -a '^GiteaApi\.test\.ts$' apps/server/src
git show "$head:apps/server/src/sourceControl/GiteaApi.test.ts" \
  | awk '{printf "%6d  %s\n", NR, $0}' \
  | grep -E -C 14 'API root|external|redirect|pagination|Link|baseUrl|Authorization' \
  | sed -n '1,1200p'

echo '== Changed code test locations and coverage names =='
git diff --name-only "$previous..$head"
git grep -n -E 'setThreadResolution|draft prefix|draft state|scheduled merge|merge_when_checks_succeed|timeline' \
  "$head" -- apps/server/src/pullRequest/GiteaPullRequestApi.test.ts \
                 apps/server/src/pullRequest/GiteaPullRequestProvider.test.ts \
                 apps/server/src/pullRequest/GiteaLifecycle.test.ts

Length of output: 78282


🤖 web_search executed:

For Gitea v1.27.3, verify from Gitea source or official API documentation: (1) how draft pull-request state is derived from WORK_IN_PROGRESS_PREFIXES; (2) the POST /repos/{owner}/{repo}/pulls/{index}/merge request body and behavior of merge_when_checks_succeed; (3) the DELETE merge endpoint for cancelling a scheduled merge; (4) whether a pull-request author without repository write access can resolve or unresolve a review conversation. Provide source URLs and relevant code references.

Length of output: 15556


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='RTVision/t3code'
pr='8'
head='c169fc23f476c5263045cff486985890d49e5860'

echo '== Current formal review state =='
gh pr view "$pr" --repo "$repo" --json headRefOid,reviewDecision,reviews \
  --jq '{headRefOid, reviewDecision, reviews: [.reviews[] | {author: .author.login, state, submittedAt, commit: .commit.oid}]}'

echo '== Current CodeRabbit approval configuration =='
git show "$head:.coderabbit.yaml" 2>/dev/null || true

echo '== Gitea v1.27 source: draft title implementation candidates =='
for url in \
  'https://raw.githubusercontent.com/go-gitea/gitea/v1.27.3/modules/setting/repository.go' \
  'https://raw.githubusercontent.com/go-gitea/gitea/v1.27.3/services/pull/pull.go' \
  'https://raw.githubusercontent.com/go-gitea/gitea/v1.27.3/services/pull/merge.go' \
  'https://raw.githubusercontent.com/go-gitea/gitea/v1.27.3/routers/web/repo/pull.go' \
  'https://raw.githubusercontent.com/go-gitea/gitea/v1.27.3/routers/api/v1/repo/pull.go'
do
  echo "--- $url"
  curl --fail --silent --show-error --location "$url" \
    | grep -n -E -C 8 'WORK_IN_PROGRESS_PREFIXES|WorkInProgress|IsWorkInProgress|ResolveConversation|resolve.*conversation|Can.*Conversation|Unresolve' \
    | sed -n '1,400p' || true
done

echo '== Gitea v1.27 source: route registration candidates =='
for url in \
  'https://raw.githubusercontent.com/go-gitea/gitea/v1.27.3/routers/api/v1/api.go' \
  'https://raw.githubusercontent.com/go-gitea/gitea/v1.27.3/routers/api/v1/repo/pull.go'
do
  echo "--- $url"
  curl --fail --silent --show-error --location "$url" \
    | grep -n -E -C 5 'resolve|unresolve|/merge|Cancel.*Auto|AutoMerge' \
    | sed -n '1,300p' || true
done

Length of output: 15291


🏁 Script executed:

#!/bin/bash
set -euo pipefail

tree_url='https://api.github.com/repos/go-gitea/gitea/git/trees/v1.27.3?recursive=1'
tree_file='/tmp/gitea-v1.27.3-tree.json'
curl --fail --silent --show-error --location "$tree_url" > "$tree_file"

echo '== Candidate Gitea v1.27.3 files =='
grep -Eo '"path":"[^"]+"' "$tree_file" \
  | grep -E '(^|/)(issue|pull).*\.go$|issues.*\.go$' \
  | grep -E 'model|service|router' \
  | sed -n '1,500p'

echo '== Source definitions for draft prefix and conversation authority =='
grep -Eo '"path":"[^"]+"' "$tree_file" \
  | sed -E 's/"path":"([^"]+)"/\1/' \
  | grep -E '(^|/)(issue|pull).*\.go$|issues.*\.go$' \
  | grep -E 'model|service|router' \
  | while IFS= read -r path; do
      content="$(curl --fail --silent --show-error --location \
        "https://raw.githubusercontent.com/go-gitea/gitea/v1.27.3/$path" || true)"
      if printf '%s' "$content" | grep -Eq 'func (CanMarkConversation|IsWorkInProgress|GetWorkInProgressPrefix|ResolvePullReviewComment|UnresolvePullReviewComment)'; then
        echo "--- $path"
        printf '%s\n' "$content" \
          | grep -n -E -C 16 'func (CanMarkConversation|IsWorkInProgress|GetWorkInProgressPrefix|ResolvePullReviewComment|UnresolvePullReviewComment)' \
          | sed -n '1,700p'
      fi
    done

Length of output: 1626


🤖 web_search executed:

site:github.com/go-gitea/gitea/blob/v1.27.3 "CanMarkConversation"

Length of output: 776


🤖 web_search executed:

site:github.com/go-gitea/gitea/blob/v1.27.3 "GetWorkInProgressPrefix" OR "IsWorkInProgress"

Length of output: 993


@kalvenschraut Approved.

I reviewed pull request #8 at exact head c169fc23f476c5263045cff486985890d49e5860 against current base 63cb01d96dccba6a09435e03d9384418993c02bc.

I found no remaining actionable blocker.

The lifecycle actions use Gitea’s native merge and cancellation routes. The draft prefix logic matches Gitea’s case-insensitive prefix behavior. The timeline reader handles both page-length X-Total-Count values and Link: rel="next" values. Timeline failures omit optional auto-merge state without failing core pull-request detail reads.

The service refreshes viewer permissions before actions. The author resolution permission matches Gitea 1.27 behavior. The API request boundary keeps pagination requests under the configured API root and prevents redirect-based credential forwarding.

Focused regression coverage includes the final provider detail path.

[approve]

You are interacting with an AI system.

@kalvenschraut

Copy link
Copy Markdown
Member Author

@coderabbitai approve

Your completed source review reports no remaining blockers at c169fc23f476c5263045cff486985890d49e5860. Please record that completed review as a formal GitHub approval on this exact head, as your reply instructed. If the head changed or you identify a remaining blocker, do not approve; explain the outstanding issue instead.

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Rate Limit Exceeded

@kalvenschraut have exceeded the limit for the number of chat messages per hour. Please wait 53 minutes and 33 seconds before sending another message.

@kalvenschraut

Copy link
Copy Markdown
Member Author

Re-review: GO on the change; NO-GO for merging the current stack

Reviewed head: c169fc23f476c5263045cff486985890d49e5860. This updates my earlier go/no-go comment for the newly pushed repairs.

Timeline pagination and tolerant auto-merge-state reads are present, including the provider-path regression. Codex, Fable, and CodeRabbit approve the lifecycle change.

Fable 5.1: GO on the individual change.

The native-stack prefix through this PR conflicts with rtvision in GiteaPullRequestApi.ts, its tests, and GiteaPullRequestProvider.test.ts. Resolve and re-review the integration before merging.

Validation by Codex: 308 focused tests across 9 files passed on integration head 73dd9c33ab15db71748beb6f0485ec212e6682f8; scoped server, web, and client-runtime typechecks passed, and targeted lint of 21 changed files passed with warnings. A separate single-worker reproduction exposed the native comment-reaction bug (100 reads and no reactions for a 50-reaction comment). These are integration results, not a claim that every standalone head passed the checks. Fable reviewed source and diffs through Claude CLI; it did not run tests.

The remaining native-stack merges must clear their predecessors and the actual target branch. CodeRabbit’s commit-specific comments are distinguished from formal GitHub review records; rate-limited requests are not approvals.

@kalvenschraut

kalvenschraut commented Sep 8, 2026 •

Copy link
Copy Markdown
Member Author

GO — merged after Codex, Fable 5.1, and CodeRabbit review.

Reviewed head: 41246dcadaf4a5d1e5f0d9548afbdd1dbf626d50. This supersedes my previous decision on the older head.

Lifecycle behavior is retained. The only net change from its current predecessor corrects a test workspace path.

CodeRabbit reviewed every exact head and cleared the combined integration. Its commit-specific approval is recorded in that comment; this is not a claim of a new formal GitHub APPROVED review on each PR. All three reviewers require #26 to land with #27 or later; they merged together in the dependency batch.

Validation by Codex: 490 focused tests across 13 files passed on integration head 2e156ad621fb32b241abd4614a367aea7943d12e, including the previously failing native comment-reaction reproduction. Scoped server, web, and client-runtime typechecks passed; targeted lint of 24 changed files passed with warnings. Checks ran sequentially with one test worker. These validate the integration, not separate test runs on every component head. Fable independently reviewed source and diffs via Claude CLI.

Merged: f787a611cffccbdf0fd5e593bba8f615c607f532 at 2026-09-08T04:42:46Z. This PR merged in the 17-member Gitea batch into rtvision; the six dependency PRs followed as one reviewed batch. Final rtvision commit is 20926b20ed4ea72618f7608f70b1d4cea8e40053; its tree 9a0e0253b515456f6a117be5ebccf2cd8e911b01 exactly matches tested integration head #36.

@kalvenschraut
kalvenschraut merged commit f787a61 into rtvision Sep 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant