Skip to content

fix(server): keep forks separate from their upstream repository in project grouping - #11011

Closed
Project516 wants to merge 2 commits into
pingdotgg:mainfrom
Project516:fix/fork-project-grouping
Closed

Project516 wants to merge 2 commits into
pingdotgg:mainfrom
Project516:fix/fork-project-grouping

Conversation

@Project516

@Project516 Project516 commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

What Changed

A checkout with an upstream remote keeps its canonical repository identity from upstream, so pull request features still target the repository a fork tracks. The identity now also carries the checkout's own origin remote, as an optional origin field, when it names a different repository than the canonical one.

Clients group and label by that field. A fork and a checkout of the original no longer collapse into one group, and the fork shows under its own name (owner/fork) in the sidebar, the draft project picker, and the mobile machine switcher. Checkouts of the same fork, including its worktrees, still group together.

Files:

  • packages/contracts: RepositoryOrigin schema, optional origin on RepositoryIdentity, and two small helpers that pick the grouping key and label.
  • apps/server: the resolver emits origin when it differs from the primary remote.
  • packages/client-runtime: project grouping keys and labels use the helpers.
  • apps/mobile: the environment matching in the new task flow uses the same key.
  • Docs: one sentence in the internals remote page.

Why

Fixes #4880. With repository grouping on, a renamed fork and the original repository showed up as a single project named after upstream, so users could not tell which one they were working in. The workaround was turning grouping off.

The earlier attempt in #7686 swapped the origin and upstream precedence for every consumer of the identity. That was closed because a sidebar label should not redefine canonical identity. This change leaves canonicalKey, locator, owner, name, and provider untouched, so pull request lookup and linking behave exactly as before. Only grouping and labels read the new field, and only when a fork is involved. Checkouts without an upstream remote produce the same identity as today.

UI Changes

The only visible change is text: a fork's group label and picker entry read owner/fork instead of the upstream name, and the fork is listed as its own project. No layout, motion, or styling changes. Before-state screenshots are in the issue thread from the September 5 check.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes (text-only label change, see above)
  • I included a video for animation/interaction changes (no motion changes)

Claude Fable 5.1 via Claude Code.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Sep 9, 2026
Comment thread packages/contracts/src/environment.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — This is a focused bug fix that keeps fork grouping separate while preserving canonical upstream identity, with targeted resolver and grouping tests and backward-compatible metadata. An unresolved Medium finding identifies a missing fallback for fork labels when origin display metadata is absent.

Not approved because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
🧰 Additional context used
📚 Code guidelines (1)
AGENTS.md — auto-discovered

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: pingdotgg/t3code/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 22d6a1bf-26de-49af-84fd-a3e3b14c8ab0

📥 Commits

Reviewing files that changed from the base of the PR and between 4510018 and 46ccd58.

📒 Files selected for processing (4)
  • apps/mobile/src/features/threads/new-task-flow-provider.tsx
  • apps/server/src/project/RepositoryIdentityResolver.test.ts
  • apps/server/src/project/RepositoryIdentityResolver.ts
  • packages/contracts/src/environment.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

Repository identities now include metadata for a distinct fork origin. Repository grouping, labels, and mobile task selection use origin-aware helpers. Tests and documentation cover fork separation from upstream repositories.

Changes

Fork identity grouping

Layer / File(s) Summary
Identity contract and resolution
packages/contracts/src/environment.ts, apps/server/src/project/RepositoryIdentityResolver.ts, apps/server/src/project/RepositoryIdentityResolver.test.ts
Repository identities support optional origin metadata. Resolution records the origin remote when it differs from the primary identity.
Grouping and mobile project selection
packages/client-runtime/src/state/projectGrouping.ts, packages/client-runtime/src/state/projectGrouping.test.ts, apps/mobile/src/features/threads/*, docs/internals/remote.md, docs/user/project-settings.md
Grouping keys, labels, and mobile repository matching use origin-aware helpers. Tests cover separate fork groups and fallback labels. Existing basename and title fallback behavior remains unchanged. Documentation describes fork naming and grouping when a fork tracks an upstream repository.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: t3dotgg, juliusmarminge, maria-rcks

Merge Risk: ⚪ Minimal · up to 46ccd

Forks use their own origin for grouping and labels while retaining upstream identity for pull-request behavior. No actionable merge-blocking issue is established; the change is mergeable subject to normal checks.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 46ccd

The change separates fork grouping from canonical repository identity without a demonstrated expansion of access or privileges. Task destinations remain explicit. Compatibility across older and newer repository metadata, and end-to-end access enforcement, remain unconfirmed.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — Control of a checkout's origin configuration now influences its grouping key, label, and matching against loaded projects on saved environments. This influence can affect draft destination selection, but the traced paths do not turn origin metadata into credentials, canonical PR identity, or additional execution authority.

Trust Boundaries and Controls

  • observed — Known unequal repository keys are rejected by the environment-list predicate and cannot match through basename/title in the target-project helper. However, that helper still returns the first target project when no match succeeds. This terminal fallback predates the PR and means repository matching is a selection aid, not a complete access or destination-enforcement boundary.

Resilience and Maintainability Implications

  • inferred — Within the inspected pending-task recovery flow, later grouping-key changes do not recompute the queued task's destination: recovery restores the recorded environmentId and projectId. This bounds identity drift at the provider handoff, but downstream execution and authorization were not independently verified.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the problem and the implementation, but it does not use the required Problem, Change, Scope and approval, and Verification sections. It also omits focused test results and doe… Add the required sections. State the problem and reproduction context under Problem, implementation details under Change, the linked issue or maintainer approval under Scope and approval, and the tests run with observed results under Verifi…
Docstring Coverage ⚠️ Warning Docstring coverage is 30.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 7 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main fix: keeping fork repositories separate from their upstream repositories during project grouping. It uses a concise conventional-commit format.
Linked Issues check ✅ Passed Issue #4880 requires the fork and upstream repository to display with different names. The PR adds origin metadata to repository identity, uses the origin for grouping and display labels, and preserve…
Out of Scope Changes check ✅ Passed The changes remain within issue #4880. Contract updates, server resolution, client and mobile grouping changes, automated tests, and documentation support separate fork identity and grouping. No unrel…
Full details: Description check

Explanation

The description explains the problem and the implementation, but it does not use the required Problem, Change, Scope and approval, and Verification sections. It also omits focused test results and does not embed or link the required before-and-after UI screenshots.

Resolution

Add the required sections. State the problem and reproduction context under Problem, implementation details under Change, the linked issue or maintainer approval under Scope and approval, and the tests run with observed results under Verification. Embed or link before-and-after screenshots for the UI label changes.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

@Project516
Project516 force-pushed the fix/fork-project-grouping branch from 8637e33 to b2d9e76 Compare September 12, 2026 17:22
@cursor

cursor Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@Project516

Copy link
Copy Markdown
Contributor Author

claude-opus-5 responding on behalf of project516

Rebased onto main to clear the conflict.

The only conflict was in docs/user/project-settings.md. This branch added one sentence to the "Project grouping has a client-wide default..." paragraph, and main has since rewritten that section, so the paragraph the sentence attached to no longer exists.

I dropped the sentence rather than relocating it. docs/user/welcome-wizard.md already tells users that "Clones with the same remote share one group", which is exactly the behavior this fix restores for forks: before it, a fork and the original collapsed into one group despite having different remotes, contradicting that line. The fix makes the existing text true, so it needs no new text. The internals note in docs/internals/remote.md is unchanged, since it records why canonical identity and grouping key differ, which the code cannot carry on its own.

No code changes in the rebase. RepositoryIdentityResolver.ts has not been touched on main since this branch was cut, and buildRepositoryIdentity still has a single call site. Verified locally after the rebase: RepositoryIdentityResolver.test.ts 11/11 and projectGrouping.test.ts 14/14.

Also corrected the file list above, which still claimed a user-doc sentence.

@Project516
Project516 force-pushed the fix/fork-project-grouping branch from b2d9e76 to 4510018 Compare September 23, 2026 17:23
@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Sep 23, 2026
…oject grouping

A checkout with an upstream remote takes its canonical identity from upstream so
pull request features target the repository it forked. Project grouping used
that same key, so a fork and a checkout of the original collapsed into one group
with the upstream name.

The identity now also carries the checkout's own origin remote when it differs
from the canonical repository. Clients group and label by origin, so a fork
stays its own project under its own name while the canonical identity is
unchanged.

Fixes pingdotgg#4880
@Project516
Project516 force-pushed the fix/fork-project-grouping branch from 4510018 to 46ccd58 Compare October 1, 2026 13:44

Copy link
Copy Markdown
Member

Note

This comment is posted by Julius' dot

Closing for missing UI verification. This changes visible fork grouping and labels, but the PR leaves the before/after requirement unchecked and points to the September 5 reproduction rather than captures of this fix. The reported resolver and grouping tests are useful. Please attach before/after screenshots showing the corrected fork grouping and labels, then request reconsideration.

@Project516

Copy link
Copy Markdown
Contributor Author

Claude Opus 5.5 responding on behalf of project516

Thanks for the review. I opened #14639 as the replacement, rebased on current main. It has before/after screenshots of this fix in the web client, taken with disposable fork fixtures, showing the fork as its own picker entry and the draft header named after the fork. Its verification section also lists the focused tests and what I could not check.

@Project516
Project516 deleted the fix/fork-project-grouping branch October 9, 2026 21:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: the name of forks are the same title as the upstream repo

2 participants