Skip to content

fix(#2592): default to fork-based scaffold PR for non-owner users - #2594

Merged
waynesun09 merged 3 commits into
mainfrom
agent/2592-fork-scaffold-pr
Jun 29, 2026
Merged

fix(#2592): default to fork-based scaffold PR for non-owner users#2594
waynesun09 merged 3 commits into
mainfrom
agent/2592-fork-scaffold-pr

Conversation

@fullsend-ai-coder

@fullsend-ai-coder fullsend-ai-coder Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #2592fullsend github setup now defaults to fork-based PRs for non-owner contributors instead of pushing branches directly to the upstream repo.

Decision tree for scaffold PR creation

user == repo owner?
  yes → push branch directly, same-repo PR
  no  → check for existing fork
    found → reuse it (no prompt, no new fork)
    not found → interactive prompt:
      [f]ork (default) → create fork, poll until ready, push, cross-fork PR
      [u]pstream       → try direct push; if 403 → clear error suggesting fork
    non-interactive (e.g. sync-scaffold) → auto-fork without prompting

Key changes

  • internal/layers/commit.go — Refactored commitScaffoldViaPR with fork-first logic. Added io.Reader parameter for interactive prompts. New helpers: commitBranchAndPR, commitViaFork, forkAndCommit, waitForFork, promptForkChoice.
  • internal/forge/forge.go — Added ErrForbidden, IsForbidden(), FindExistingFork(), CreateFork() to the Client interface.
  • internal/forge/github/github.go — Implemented fork/forbidden methods on LiveClient. Scoped 403→ErrForbidden mapping to CreateBranch only.
  • internal/forge/fake.go — Extended FakeClient with fork simulation fields.
  • internal/cli/admin.go — Pass os.Stdin to CommitScaffoldFiles (interactive).
  • internal/layers/workflows.go — Pass nil to CommitScaffoldFiles (non-interactive, auto-fork).

Fork readiness

GitHub fork creation returns 202 Accepted and can take 30s+ for large repos. After CreateFork, the code polls GetRepo every 3s for up to 2 minutes until the fork is materialized.

Cross-fork PRs

When creating a PR from a fork, the PR head is set to "forkOwner:branchName" so GitHub correctly identifies the source branch across repositories.

Test plan

  • 16 new tests in commit_test.go covering the full decision tree
  • ~30 existing tests updated to set AuthenticatedUser for fork-detection compatibility
  • go vet ./... clean
  • go build ./... clean

@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown

E2E tests are running

Authorization passed for this commit. See the E2E Tests workflow for results.

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 7:51 AM UTC · Completed 8:06 AM UTC
Commit: e6aebb1 · View workflow run →

@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.71429% with 25 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/layers/commit.go 87.96% 10 Missing and 3 partials ⚠️
internal/forge/github/github.go 70.00% 6 Missing and 6 partials ⚠️

📢 Thoughts on this report? Let us know!

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review

Findings

Medium

  • [race-condition] internal/layers/commit.go:58 — After CreateFork returns (HTTP 202 Accepted, an async operation), the code immediately calls CreateBranch on the newly created fork. GitHub's fork creation is asynchronous, so the fork repository may not be ready yet when CreateBranch executes. This can cause CreateBranch to fail with a 404 (repo not found) or other transient error. The "existing fork" path does not have this problem because the fork is already materialized.
    Remediation: Wrap the CreateBranch call after CreateFork in a retry loop, reusing the retryOnRepoRace pattern already established in internal/forge/github/github.go for similar async-initialization races. Alternatively, surface the retry at the commit.go layer since CreateBranch is a forge.Client interface call.
Previous run

Review

Findings

Medium

  • [resource-leak] internal/forge/github/github.go:459 — In FindExistingFork, when c.do() returns a response with StatusNotFound, the code returns ("", nil) without closing resp.Body. Every other call site in this file that receives a response from do() closes the body. This leaks an HTTP response body on every call where the user does not already have a fork — the most common path.
    Remediation: Add defer resp.Body.Close() immediately after the nil-error check on c.do(), before the status code checks.

  • [logic-error] internal/forge/github/github.go:490CreateFork only extracts the fork owner login from the GitHub API response, but GitHub may create a fork with a different repo name if the user already has an unrelated repo with the same name (e.g., repo becomes repo-1). The caller in commit.go initializes branchRepo to the upstream repo name and never updates it, so all subsequent API calls (CreateBranch, CommitFilesToBranch) would target a non-existent repo and fail with 404. FindExistingFork has the same blind spot — it checks GET /repos/{user}/{repo} using the upstream name, so it would miss a renamed fork.
    Remediation: Have CreateFork return both the owner login and the actual repo name from the response (name field). Update the forge.Client interface signature and commitScaffoldViaPR to use the returned repo name for branchRepo.

  • [breaking-api] internal/forge/forge.go:207 — Adding FindExistingFork and CreateFork to the forge.Client interface is a breaking change for any out-of-tree implementations. Currently only FakeClient and github.LiveClient exist (both updated), but AGENTS.md documents planned GitLab/Forgejo support. The interface is in internal/, limiting the blast radius, but fork semantics differ across forges — document the cross-forge contract (whose fork, idempotency, naming) so future implementors have clear expectations.
    Remediation: Verify no in-progress forge implementations exist in related repos. Add doc comments on the new interface methods specifying the behavioral contract for all forge implementations.


Labels: PR modifies scaffold install flow in internal/layers/commit.go and forge abstraction in internal/forge/

Previous run (2)

Review

Findings

Medium

  • [logic-error] internal/forge/github/github.go:87 — Mapping all HTTP 403 responses to forge.ErrForbidden in APIError.Unwrap() is overly broad. GitHub returns 403 for secondary rate limits (when the retry budget is exhausted), SAML SSO enforcement, and other policy-based denials — not only permission failures. Any of these would incorrectly trigger the fork-and-push fallback path in commitScaffoldViaPR. The existing Unwrap() comment (lines 75–82) explicitly explains why ErrBranchProtected is NOT mapped globally because 422s are context-dependent — the same reasoning applies to 403.
    Remediation: Only map 403 to ErrForbidden at the call site (e.g., CreateBranch) rather than globally in Unwrap(), following the established ErrBranchProtected pattern. Alternatively, inspect the 403 response message to distinguish permission denials from rate limits or SAML enforcement.

  • [scope-creep] internal/forge/forge.go — The PR adds fork-based fallback triggered by 403, but issue fullsend github setup command create the PR from a branch in the main repository and not from my fork #2592 says "I expect that it should use my fork to create the PR rather than pushing the branch to the upstream repository." This could describe an expectation for fork usage by default (not just as a 403 fallback). The PR reasonably addresses the most likely interpretation, but a clarifying comment on the issue would confirm alignment.
    Remediation: Verify with the issue author whether the problem is (a) they lack push access and got a 403 error, or (b) they have push access but want fork-based PRs by default.

  • [fallback-pattern] internal/layers/commit.go — The fork fallback does not construct a context-aware PR body explaining why a fork was needed, unlike the existing commitScaffoldDirect fallback which adds: "The default branch has branch protection rules that prevent direct pushes." The fork-created PR should similarly explain that a fork was used because the user lacks push access.
    Remediation: Add a fork-specific PR body or append context explaining that a fork was used because the user lacks push access to the upstream repo.


Labels: PR modifies scaffold install flow in internal/layers/commit.go and forge abstraction in internal/forge/

Previous run (3)

Looks good to me

Previous run (4)

Review

Findings

Medium

  • [logic-error] internal/forge/github/github.go:87 — Mapping all HTTP 403 responses to forge.ErrForbidden in APIError.Unwrap() is overly broad. GitHub returns 403 for secondary rate limits (when the retry budget is exhausted), SAML SSO enforcement, and other policy-based denials — not only permission failures. Any of these would incorrectly trigger the fork-and-push fallback path in commitScaffoldViaPR. The existing Unwrap() comment (lines 75–82) explicitly explains why ErrBranchProtected is NOT mapped globally because 422s are context-dependent — the same reasoning applies to 403.
    Remediation: Only map 403 to ErrForbidden at the call site (e.g., CreateBranch) rather than globally in Unwrap(), following the established ErrBranchProtected pattern. Alternatively, inspect the 403 response message to distinguish permission denials from rate limits or SAML enforcement.

  • [scope-creep] internal/forge/forge.go — The PR adds fork-based fallback triggered by 403, but issue fullsend github setup command create the PR from a branch in the main repository and not from my fork #2592 says "I expect that it should use my fork to create the PR rather than pushing the branch to the upstream repository." This could describe an expectation for fork usage by default (not just as a 403 fallback). The PR reasonably addresses the most likely interpretation, but a clarifying comment on the issue would confirm alignment.
    Remediation: Verify with the issue author whether the problem is (a) they lack push access and got a 403 error, or (b) they have push access but want fork-based PRs by default.

  • [fallback-pattern] internal/layers/commit.go — The fork fallback does not construct a context-aware PR body explaining why a fork was needed, unlike the existing commitScaffoldDirect fallback which adds: "The default branch has branch protection rules that prevent direct pushes." The fork-created PR should similarly explain that a fork was used because the user lacks push access.
    Remediation: Add a fork-specific PR body or append context explaining that a fork was used because the user lacks push access to the upstream repo.


Labels: PR modifies scaffold install flow in internal/layers/commit.go and forge abstraction in internal/forge/

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

Comment thread internal/forge/github/github.go Outdated
if e.StatusCode == http.StatusNotFound {
return forge.ErrNotFound
}
if e.StatusCode == http.StatusForbidden {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] logic-error

Mapping all HTTP 403 responses to forge.ErrForbidden in APIError.Unwrap() is overly broad. GitHub returns 403 for secondary rate limits, SAML SSO enforcement, and other policy-based denials — not only permission failures. Any of these would incorrectly trigger the fork-and-push fallback path in commitScaffoldViaPR. The existing Unwrap() comment (lines 75-82) explicitly explains why ErrBranchProtected is NOT mapped globally because 422s are context-dependent — the same reasoning applies to 403.

Suggested fix: Only map 403 to ErrForbidden at the call site (e.g., CreateBranch) rather than globally in Unwrap(), following the established ErrBranchProtected pattern. Alternatively, inspect the 403 response message to distinguish permission denials from rate limits or SAML enforcement.

@fullsend-ai-review fullsend-ai-review Bot added requires-manual-review Review requires human judgment component/install CLI install and app setup labels Jun 24, 2026
@ifireball

Copy link
Copy Markdown
Member

/fs-fix need to find out if the user already has a fork and reuse that where possible

@fullsend-ai-coder

fullsend-ai-coder Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Finished Fix · ✅ Success · Started 8:38 AM UTC · Completed 8:50 AM UTC
Commit: 6bd5f3a · View workflow run →

fullsend-ai-coder Bot added a commit that referenced this pull request Jun 24, 2026
Add FindExistingFork to forge.Client interface so commitScaffoldViaPR
can check whether the user already has a fork before trying (and
failing) to push to upstream. When an existing fork is found, the
scaffold branch is created directly on the fork, skipping the
unnecessary 403 round-trip. The CreateFork fallback path remains for
users who don't yet have a fork.

Addresses review feedback on #2594
@fullsend-ai-coder

Copy link
Copy Markdown
Contributor Author

🔧 Fix agent — iteration 1 (human-triggered)

Added FindExistingFork to forge.Client so commitScaffoldViaPR detects existing forks and reuses them, skipping the unnecessary upstream push attempt that would fail with 403.

Fixed (1):

  1. detect and reuse existing fork where possible: Added FindExistingFork method to forge.Client interface with GitHub and FakeClient implementations. Updated commitScaffoldViaPR to check for existing forks before attempting upstream push, reusing them directly to avoid the 403 round-trip. Added test for the reuse-existing-fork path.

Tests: passed

Updated by fullsend fix agent

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 8:53 AM UTC · Completed 9:06 AM UTC
Commit: 769aff5 · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot added ready-for-merge All reviewers approved — ready to merge and removed requires-manual-review Review requires human judgment labels Jun 24, 2026
@ifireball

Copy link
Copy Markdown
Member

/fs-fix fix the logic error spotted by fullsend-ai-review as get the coverage for new code to or above 80%

@fullsend-ai-coder

fullsend-ai-coder Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Finished Fix · ✅ Success · Started 9:26 AM UTC · Completed 9:37 AM UTC
Commit: 6bd5f3a · View workflow run →

fullsend-ai-coder Bot added a commit that referenced this pull request Jun 24, 2026
The global APIError.Unwrap() mapping of HTTP 403 to forge.ErrForbidden was
overly broad — GitHub returns 403 for secondary rate limits, SAML SSO, and
other policy denials, not only permission failures. This follows the
established ErrBranchProtected pattern: the sentinel is wrapped at the call
site (CreateBranch) where the operation context disambiguates the cause.

Also adds tests for FindExistingFork, CreateFork, CreateBranch 403 wrapping,
FakeClient fork methods, IsForbidden helper, and commit.go edge cases to
bring patch coverage above the 80% threshold.

Addresses review feedback on #2594
@fullsend-ai-coder

Copy link
Copy Markdown
Contributor Author

🔧 Fix agent — iteration 2 (human-triggered)

Fixed the logic error by scoping the 403-to-ErrForbidden mapping from the global APIError.Unwrap() to the CreateBranch call site, following the established ErrBranchProtected pattern. Added comprehensive tests for all new code paths (FindExistingFork, CreateFork, CreateBranch 403, fake client methods, IsForbidden, commit.go edge cases) to bring patch coverage above 80%.

Fixed (2):

  1. global 403-to-ErrForbidden mapping in Unwrap() is overly broad (internal/forge/github/github.go): Removed the global HTTP 403 to forge.ErrForbidden mapping from APIError.Unwrap(). Added context-specific mapping in CreateBranch() that wraps 403 errors with forge.ErrForbidden, following the established ErrBranchProtected pattern. Updated the Unwrap() comment to explain why 403 is not mapped globally (rate limits, SAML SSO, etc.).
  2. patch coverage below 80% threshold (internal/forge/github/github_test.go): Added tests for FindExistingFork (fork exists, no fork, not a fork of target), CreateFork (success, API failure), and CreateBranch_Forbidden (403 wraps ErrForbidden). Also added fake client tests for FindExistingFork, CreateFork, CreateBranch per-repo errors, and IsForbidden helper. Added commit.go edge case tests for FindExistingFork error fallthrough and branch creation failures on fork.

Tests: passed

Decision points
  • Chose to wrap 403 at CreateBranch call site rather than inspecting the 403 response message (alternatives: Inspect 403 response message to distinguish permission denials from other 403s, Add a new method-specific error type; rationale: Follows the established ErrBranchProtected pattern in this codebase where context-dependent errors are wrapped at the call site. The isRetryable function already handles secondary rate limit 403s before they reach checkStatus, so any remaining 403 from CreateBranch's ref-creation POST reliably indicates a permission denial.)

Updated by fullsend fix agent

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 9:40 AM UTC · Completed 9:54 AM UTC
Commit: 9b29f14 · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

Comment thread internal/forge/github/github.go Outdated
func (c *LiveClient) FindExistingFork(ctx context.Context, owner, repo string) (string, error) {
user, err := c.GetAuthenticatedUser(ctx)
if err != nil {
return "", fmt.Errorf("find existing fork: %w", err)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] resource-leak

In FindExistingFork, when c.do() returns a response with StatusNotFound, the code returns ("", nil) without closing resp.Body. Every other call site in this file that receives a response from do() closes the body. This leaks an HTTP response body on every call where the user does not already have a fork.

Suggested fix: Add defer resp.Body.Close() immediately after the nil-error check on c.do(), before the status code checks.

}

// CreateFork creates a fork of owner/repo under the authenticated user's
// account. If a fork already exists, the GitHub API returns 202 with the

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] logic-error

CreateFork only extracts the fork owner login from the GitHub API response, but GitHub may create a fork with a different repo name if the user already has an unrelated repo with the same name (e.g., 'repo' becomes 'repo-1'). The caller in commit.go uses the original repo name for all subsequent API calls (CreateBranch, CommitFilesToBranch), which would 404 if the fork name differs.

Suggested fix: Have CreateFork return both the owner login and the actual repo name from the response. Update the forge.Client interface and commitScaffoldViaPR to use the returned repo name for branchRepo.

Comment thread internal/forge/forge.go Outdated
CreateRepo(ctx context.Context, org, name, description string, private bool) (*Repository, error)
DeleteRepo(ctx context.Context, owner, repo string) error

// FindExistingFork checks whether the authenticated user already

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] breaking-api

Adding FindExistingFork and CreateFork to the forge.Client interface is a breaking change for any out-of-tree implementations. Currently only FakeClient and github.LiveClient exist (both updated), but AGENTS.md documents planned GitLab/Forgejo support. Document the cross-forge contract so future implementors have clear expectations.

Suggested fix: Verify no in-progress forge implementations exist. Add doc comments specifying the behavioral contract for all forge implementations.

@fullsend-ai-review fullsend-ai-review Bot removed the ready-for-merge All reviewers approved — ready to merge label Jun 24, 2026
@ifireball

Copy link
Copy Markdown
Member

/fs-fix

@fullsend-ai-coder

fullsend-ai-coder Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Finished Fix · ✅ Success · Started 1:28 PM UTC · Completed 1:39 PM UTC
Commit: 68c8592 · View workflow run →

fullsend-ai-coder Bot added a commit that referenced this pull request Jun 24, 2026
…body

- FindExistingFork/CreateFork now return (forkOwner, forkRepo, err) so
  callers use the actual fork repo name instead of assuming it matches
  the upstream name (GitHub may rename forks to avoid collisions)
- Close resp.Body on the 404 early-return path in FindExistingFork
- Add cross-forge behavioral contract docs on new interface methods
- Add tests for renamed fork scenarios
- Update commitScaffoldViaPR to use returned forkRepo for branchRepo

Addresses review feedback on #2594
@fullsend-ai-coder

Copy link
Copy Markdown
Contributor Author

🔧 Fix agent — iteration 3 (human-triggered)

Addressed all 3 review findings: fixed resp.Body leak on 404 path in FindExistingFork, changed fork method signatures to return actual repo name (handling GitHub rename collisions), and added cross-forge behavioral contract documentation to interface methods. Added test cases for renamed fork scenarios.

Fixed (3):

  1. resource-leak: FindExistingFork leaks resp.Body on 404 path (internal/forge/github/github.go): Added resp.Body.Close() before returning on the 404 early-return path in FindExistingFork, matching the pattern used by all other response-handling code in the file
  2. logic-error: CreateFork/FindExistingFork don't return actual fork repo name (internal/forge/forge.go): Changed FindExistingFork and CreateFork signatures from (forkOwner string, err error) to (forkOwner, forkRepo string, err error). Both LiveClient and FakeClient implementations now extract and return the actual repo name from the API response. Updated commitScaffoldViaPR to use the returned forkRepo for branchRepo, fixing the case where GitHub renames a fork (e.g. repo to repo-1) due to naming collisions
  3. breaking-api: new interface methods lack cross-forge behavioral contract docs (internal/forge/forge.go): Added detailed cross-forge contract documentation to both FindExistingFork and CreateFork interface method comments, specifying: empty-string convention for missing forks, idempotency requirement, platform-specific fork semantics, and requirement to return actual repo name from API response

Tests: passed

Decision points
  • FindExistingFork still checks GET /repos/{user}/{repo} by upstream name so a renamed fork would be missed (alternatives: Use GET /repos/{owner}/{repo}/forks to list all forks and search for users fork, Keep current approach and rely on CreateFork idempotency; rationale: Kept current approach: if the fork is renamed FindExistingFork returns empty and the caller falls through to try upstream push then 403 then CreateFork which is idempotent and returns the correct fork metadata. The extra API call is acceptable for this rare edge case and avoids the complexity of paginating fork listings)

Updated by fullsend fix agent

@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown

Site preview

Preview: https://71e0b925-site.fullsend-ai.workers.dev

Commit: 60744d65c01b0ceb76a2ec492f01ecc661d94b1c

@ifireball

Copy link
Copy Markdown
Member

/fs-review

@rh-hemartin

Copy link
Copy Markdown
Member

I agree with Barak here, I think the sentiment that the users have is that they want to use their fork first. So I agree that the CLI needs to check if the user has a fork, then use it, even with push access to the original. If a fork is not detected we can ask users about if proceed by using the original repository, and if not tell them to create a fork. I don't think we need to create the fork from the CLI. But up to you.

@waynesun09 waynesun09 added the fullsend-no-fix Skip bot-triggered fix agent runs label Jun 26, 2026
@waynesun09
waynesun09 force-pushed the agent/2592-fork-scaffold-pr branch from 558949d to 7c60772 Compare June 26, 2026 14:33
@waynesun09 waynesun09 changed the title fix(#2592): use fork for scaffold PR when user lacks push access fix(#2592): default to fork-based scaffold PR for non-owner users Jun 26, 2026
@waynesun09

Copy link
Copy Markdown
Member

Thanks @rh-hemartin — this PR now implements fork-first as the default. Here's the decision tree:

  1. User == repo owner → push branch directly, same-repo PR (no fork needed)
  2. Existing fork found → reuse it automatically (no prompt)
  3. No fork, interactive → prompt: [f]ork (default) / [u]pstream — pressing Enter defaults to fork
  4. No fork, non-interactive (e.g. sync-scaffold) → auto-fork without prompting

On your point about not creating the fork from the CLI — I went with offering it as the default prompt option because fullsend github setup already requires admin access to set secrets/variables, so the user is actively running the CLI. Creating the fork in-band avoids sending them away to the GitHub UI and coming back. But the upstream option is always available if they prefer to push directly (with a clear 403 error + suggestion if that fails).

The fork creation also handles GitHub's async 202 response by polling GetRepo every 3s for up to 2 minutes until the fork is ready.

Add FindExistingFork and CreateFork to the forge.Client interface with
GitHub LiveClient and FakeClient implementations. Scope HTTP 403 to
ErrForbidden mapping to CreateBranch call site only, following the
established ErrBranchProtected pattern. Add comprehensive tests for
all new methods.

Assisted-by: Claude
Signed-off-by: Wayne Sun <gsun@redhat.com>
Refactor commitScaffoldViaPR to use a fork-first decision tree:
- Owner → push branch directly, same-repo PR
- Existing fork → reuse it (no prompt)
- No fork, interactive → prompt: [f]ork (default) / [u]pstream
- No fork, non-interactive → auto-fork
- Upstream 403 → clear error suggesting fork option

Fork creation polls GetRepo every 3s for up to 2min to handle
GitHub's async 202 Accepted response. Cross-fork PRs use the
"forkOwner:branchName" head format.

Add io.Reader parameter to CommitScaffoldFiles for interactive
prompts. Callers pass os.Stdin (interactive) or nil (auto-fork).

Fixes: #2592

Assisted-by: Claude (implementation)
Signed-off-by: Wayne Sun <gsun@redhat.com>
Update existing tests to set FakeClient.AuthenticatedUser matching
the test's repo owner so the new fork-detection logic correctly
identifies the user as the owner and takes the direct-push path.

Without this, tests hit the fork path and timeout waiting for a
non-existent fork to become ready.

Assisted-by: Claude (implementation)
Signed-off-by: Wayne Sun <gsun@redhat.com>
@waynesun09
waynesun09 force-pushed the agent/2592-fork-scaffold-pr branch from 7c60772 to 60744d6 Compare June 26, 2026 14:54
@waynesun09 waynesun09 added the ok-to-test Allow e2e CI to run after maintainer review (must be re-applied after each push) label Jun 26, 2026
@waynesun09
waynesun09 added this pull request to the merge queue Jun 29, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 29, 2026
@waynesun09
waynesun09 added this pull request to the merge queue Jun 29, 2026
Merged via the queue into main with commit 08e7c62 Jun 29, 2026
22 of 23 checks passed
@waynesun09
waynesun09 deleted the agent/2592-fork-scaffold-pr branch June 29, 2026 14:04
@fullsend-ai-retro

fullsend-ai-retro Bot commented Jun 29, 2026

Copy link
Copy Markdown

🤖 Finished Retro · ❌ Failure · Started 2:09 PM UTC · Completed 2:31 PM UTC
Commit: 60744d6 · View workflow run →

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

Labels

component/install CLI install and app setup fullsend-no-fix Skip bot-triggered fix agent runs ok-to-test Allow e2e CI to run after maintainer review (must be re-applied after each push) requires-manual-review Review requires human judgment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fullsend github setup command create the PR from a branch in the main repository and not from my fork

3 participants