Skip to content

Add drag-and-drop project reordering to the sidebar - #185

Merged
juliusmarminge merged 7 commits into
mainfrom
t3code/reorder-projects-drag-drop
Mar 9, 2026
Merged

juliusmarminge merged 7 commits into
mainfrom
t3code/reorder-projects-drag-drop

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Mar 6, 2026 •

Copy link
Copy Markdown
Member
CleanShot.2026-03-09.at.14.15.02.mp4

Summary

  • add project drag-and-drop reordering in the sidebar using @dnd-kit (core, sortable, modifiers, utilities)
  • introduce sortable project item wiring and vertical-only drag constraints
  • prevent accidental project toggle clicks during drag gestures via pointer-move/click suppression logic
  • keep existing project/thread interactions (context menu, new thread action, keyboard toggle) while moving from Collapsible to inline animated expand/collapse layout
  • extend store logic and tests to cover project reordering behavior

Testing

  • Updated unit tests in apps/web/src/store.test.ts for project reorder behavior
  • Not run: bun lint
  • Not run: bun typecheck
  • Not run: bun run test

Note

Medium Risk
Moderate UI/state change that adds new drag interactions and persists project ordering in localStorage, which could impact sidebar behavior and read-model sync ordering if edge cases are missed.

Overview
Sidebar projects can now be reordered via drag-and-drop. The sidebar wraps each project in a @dnd-kit sortable context (vertical-only, parent-bounded) and adds click/keyboard suppression logic to prevent accidental expand/collapse toggles during drag gestures.

Project ordering is now stateful and persisted. The Zustand store adds reorderProjects, persists projectOrderCwds alongside expanded state, and updates read-model syncing to preserve existing (or persisted) project order when server updates arrive; tests were extended to cover both reorder and sync-order preservation.

Small UI plumbing updates include a hideScrollbars option on ScrollArea (used by SidebarContent), a Collapsible panel animation tweak, and minor build tooling adjustments (Vite override / config cleanup).

Written by Cursor Bugbot for commit 2c6bbc3. This will update automatically on new commits. Configure here.

Note

Add drag-and-drop project reordering to the sidebar

  • Wraps the sidebar project list in DndContext and SortableContext from @dnd-kit, with a new SortableProjectItem component that applies transform/transition styles and drag handle props during drag interactions.
  • Adds reorderProjects to the Zustand store as a pure function that moves a project to a target index; project order is persisted to and restored from localStorage.
  • When syncing the server read model, the existing in-memory order is preserved; if none exists, the persisted localStorage order is used; otherwise new projects are appended in incoming order.
  • Replaces CollapsibleTrigger with a SidebarMenuButton that handles click, keyboard (Enter/Space), and context menu events directly, with click suppression immediately after a drag to prevent unintended toggles.
  • Risk: project order is now stored in localStorage under a new projectOrderCwds key; users who clear storage will lose their custom ordering.

Macroscope summarized 2c6bbc3.

@coderabbitai

coderabbitai Bot commented Mar 6, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 82de4b9a-1b6e-4109-9149-c152af40ab9f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch t3code/reorder-projects-drag-drop

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

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Sortable wrapper div creates invalid HTML in list
    • Changed SortableProjectItem to render a SidebarMenuItem (
    • ) instead of a
      , and removed the redundant inner SidebarMenuItem wrapper, producing valid
      • …
      HTML.

Create PR

Or push these changes by commenting:

@cursor push 410550ecbe
Preview (410550ecbe)
diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx
--- a/apps/web/src/components/Sidebar.tsx
+++ b/apps/web/src/components/Sidebar.tsx
@@ -273,15 +273,17 @@
 
 function SortableProjectItem({
   projectId,
+  className,
   children,
 }: {
   projectId: ProjectId;
+  className?: string;
   children: (handleProps: SortableProjectHandleProps) => React.ReactNode;
 }) {
   const { attributes, listeners, setNodeRef, transform, transition, isDragging, isOver } =
     useSortable({ id: projectId });
   return (
-    <div
+    <SidebarMenuItem
       ref={setNodeRef}
       style={{
         transform: CSS.Translate.toString(transform),
@@ -289,10 +291,10 @@
       }}
       className={`rounded-md ${
         isDragging ? "z-20 opacity-80" : ""
-      } ${isOver && !isDragging ? "ring-1 ring-primary/40" : ""}`}
+      } ${isOver && !isDragging ? "ring-1 ring-primary/40" : ""} ${className ?? ""}`}
     >
       {children({ attributes, listeners })}
-    </div>
+    </SidebarMenuItem>
   );
 }
 
@@ -1205,9 +1207,9 @@
                       : projectThreads;
 
                   return (
-                    <SortableProjectItem key={project.id} projectId={project.id}>
+                    <SortableProjectItem key={project.id} projectId={project.id} className="group/collapsible">
                       {(dragHandleProps) => (
-                        <SidebarMenuItem className="group/collapsible">
+                        <>
                           <div className="group/project-header relative">
                             <SidebarMenuButton
                               size="sm"
@@ -1448,7 +1450,7 @@
                               </SidebarMenuSub>
                             </div>
                           </div>
-                        </SidebarMenuItem>
+                        </>
                       )}
                     </SortableProjectItem>
                   );

Comment thread apps/web/src/components/Sidebar.tsx
@vercel

vercel Bot commented Mar 6, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
t3code-marketing Error Error Mar 6, 2026 10:50pm

Request Review

@github-actions github-actions Bot added the vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. label Mar 9, 2026
- wire project list to dnd-kit sortable with vertical drag constraints
- prevent accidental expand/collapse clicks during drag gestures
- update store logic/tests and add dnd-kit dependencies
- prevent accidental project toggles after drag operations
- switch project rows to Collapsible for stable expand/collapse animation
- add optional hidden scrollbar mode to ScrollArea and apply it in SidebarContent
- Reset post-drag click suppression when drag is canceled
- Consume only the synthetic click after drag release, then clear suppression
@juliusmarminge
juliusmarminge force-pushed the t3code/reorder-projects-drag-drop branch from 28df73c to f32db73 Compare March 9, 2026 21:11

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Ambiguous operator precedence in fallback order calculation
    • Added explicit outer parentheses around the fallback arithmetic expression to make the precedence between ?? and + unambiguous.

Create PR

Or push these changes by commenting:

@cursor push 148d455f06
Preview (148d455f06)
diff --git a/apps/web/src/store.ts b/apps/web/src/store.ts
--- a/apps/web/src/store.ts
+++ b/apps/web/src/store.ts
@@ -155,7 +155,7 @@
       const orderIndex =
         previousIndex ??
         persistedIndex ??
-        (usePersistedOrder ? persistedProjectOrderCwds.length : previous.length) + incomingIndex;
+        ((usePersistedOrder ? persistedProjectOrderCwds.length : previous.length) + incomingIndex);
       return { project, incomingIndex, orderIndex };
     })
     .toSorted((a, b) => {

Comment thread apps/web/src/store.ts
const orderIndex =
previousIndex ??
persistedIndex ??
(usePersistedOrder ? persistedProjectOrderCwds.length : previous.length) + incomingIndex;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ambiguous operator precedence in fallback order calculation

Low Severity

The orderIndex fallback expression relies on + having higher precedence than ?? without explicit parentheses. While the current behavior is correct (the addition only applies when both previousIndex and persistedIndex are nullish), a reader could easily misinterpret this as adding incomingIndex to the result of the entire ?? chain. Wrapping the fallback arithmetic in parentheses would make the intent unambiguous and prevent accidental breakage if the expression is modified later.

Fix in Cursor Fix in Web

- Prefer pointer-based hit testing during project reordering
- Fall back to corner-based collision to make drop targeting more reliable

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Drag cancel doesn't suppress synthetic click after release
    • Removed the line that reset suppressProjectClickAfterDragRef to false in handleProjectDragCancel, so the flag stays true and suppresses the synthetic click fired on pointer release after a cancelled drag, matching handleProjectDragEnd's behavior.

Create PR

Or push these changes by commenting:

@cursor push 13c88d8bd1
Preview (13c88d8bd1)
diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx
--- a/apps/web/src/components/Sidebar.tsx
+++ b/apps/web/src/components/Sidebar.tsx
@@ -872,7 +872,6 @@
 
   const handleProjectDragCancel = useCallback((_event: DragCancelEvent) => {
     dragInProgressRef.current = false;
-    suppressProjectClickAfterDragRef.current = false;
   }, []);
 
   const handleProjectTitlePointerDownCapture = useCallback(() => {

Comment thread apps/web/src/components/Sidebar.tsx
@juliusmarminge

Copy link
Copy Markdown
Member Author

@cursor push 13c88d8bd1

…vent unintended toggle

Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>

Applied via @cursor push command
@juliusmarminge
juliusmarminge merged commit 9fb9467 into main Mar 9, 2026
8 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/reorder-projects-drag-drop branch March 9, 2026 22:08

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.

Comment thread apps/web/src/store.ts
const orderIndex =
previousIndex ??
persistedIndex ??
(usePersistedOrder ? persistedProjectOrderCwds.length : previous.length) + incomingIndex;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Operator precedence bug in order index fallback calculation

Low Severity

The + operator has higher precedence than the ternary ?:, so the fallback orderIndex expression is parsed as usePersistedOrder ? persistedProjectOrderCwds.length : (previous.length + incomingIndex) instead of the likely intended (usePersistedOrder ? persistedProjectOrderCwds.length : previous.length) + incomingIndex. When usePersistedOrder is true, incomingIndex is not added, so all new projects receive the same orderIndex. The sort tiebreaker on incomingIndex masks this today, but the asymmetry is almost certainly unintentional and fragile.

Fix in Cursor Fix in Web

davifernan added a commit to davifernan/chicocode that referenced this pull request Mar 22, 2026
ChicoCenter was selecting derived arrays/objects directly from Zustand
(selectAllRuns/selectSelectedRun). Those selectors allocate fresh values on
every read, which makes useSyncExternalStore think the snapshot changed even
when store state is stable. In production builds this surfaced as React error
pingdotgg#185 (too many re-renders) when opening /chico.

Read stable primitives from the store (runs Map + selectedRunId) and derive
runs/selectedRun via useMemo inside the component instead.
Pedrooo24 added a commit to Pedrooo24/t3code that referenced this pull request Apr 20, 2026
…otgg#185 on boot

StatusBar passou a montar sempre na 4.1C; useSessionCostTotal chamava
resolveThreadRouteTarget via useParams selector, devolvendo novo objecto
a cada render e disparando re-render em loop. Selecionar environmentId
e threadId como primitivas e reconstruir o ref com useMemo.
Pedrooo24 added a commit to Pedrooo24/t3code that referenced this pull request Apr 20, 2026
fix(ui): break render loop in useSessionCostTotal causing React pingdotgg#185 on boot
Pedrooo24 added a commit to Pedrooo24/t3code that referenced this pull request Apr 26, 2026
…nterference

O React Compiler (beta) pode reescrever funcoes que mutam refs durante
o render de forma inesperada, potencialmente causando loops de render
(React pingdotgg#185). A directiva 'use no memo' desactiva a optimizacao do
Compiler para useSettings, preservando o comportamento manual do padrao
useRef/shallowEqual que estabiliza referencias do selector.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
highercomve added a commit to highercomve/t3code that referenced this pull request May 28, 2026
…lot driver

Three runtime regressions surfaced after the per-instance driver merge
(commit e06e186) plus the Copilot provider was reinstated.

Server:
- Restore Antigravity conversation table migration. The `028_RenameGeminiToAntigravity`
  migration was shadowed by upstream's `028_ProjectionThreadSessionInstanceId`,
  so the `antigravity_conversations` table never existed at runtime and every
  Antigravity turn aborted with "Failed to load antigravity conversation id."
  Rename ours to `031` and register it in `Migrations.ts`.
- Add `CopilotDriver` per-instance ProviderDriver (PATCH.md §2 restored).
  - `provider/Drivers/CopilotDriver.ts` registered in `BUILT_IN_DRIVERS` with
    `supportsMultipleInstances: true`.
  - `provider/Layers/CopilotProvider.ts` probes the `copilot` binary +
    parses `--version`; checks `~/.config/github-copilot/hosts.json` for
    auth-presence and ships a 5-model catalog (Claude 4.6/4.5, GPT-5.4).
  - `provider/Layers/CopilotAdapter.ts` placeholder adapter — returns clear
    "ACP integration not yet wired" errors rather than silently hanging.
  - `textGeneration/CopilotTextGeneration.ts` stub; routing falls back to
    Codex/Antigravity for commit-message generation.

Web:
- Fix React error pingdotgg#185 (infinite render loop) on `/` and chat routes.
  `apps/web/src/routes/_chat.$environmentId.$threadId.tsx:142-156`:
  `useParams({ select })` returned a fresh `{environmentId, threadId}`
  object on every router commit. The fresh `threadRef` busted the
  "redirect when thread missing" `useEffect` dep equality → `navigate({to:"/"})`
  → router commit → new selector result → loop. Memoize `threadRef` against
  primitive params so the object reference is stable.
- Fix model picker click silent no-op. `apps/web/src/composerDraftStore.js`
  was a stale compiled artifact that shadowed `composerDraftStore.ts` in
  Vite's `.js`-first resolve order. All post-merge edits to the `.ts` were
  invisible at runtime. Rewrite the `.js` as a one-line re-export so the
  active `.ts` source wins; the file should be deleted entirely on the next
  full dev-server restart.
- Add Copilot to `PROVIDER_CLIENT_DEFINITIONS` (Preview badge).
- Remove "Gemini — coming soon" / "Github Copilot — coming soon" placeholders
  from the model picker sidebar (both providers are now first-class).

End-to-end verified in the browser after migration + driver wiring:
- Claude → responded "hello" in 2.5s
- Antigravity → responded "hello" in 8.1s
- OpenCode → responded "hello" in 5.4s
- Codex → blocked by user's ChatGPT Free plan ("gpt-5.4 not supported"),
  not a merge bug
- Copilot → shows correctly with auth status, falls into the picker; CLI
  needs `copilot auth login` for full session
Eliasriv748 added a commit to Eliasriv748/t3code that referenced this pull request Jun 15, 2026
fix(web): prevent StatusBar infinite render loop (React pingdotgg#185)
martinbhans1 added a commit to martinbhans1/m3code that referenced this pull request Aug 3, 2026
zustand v5 passes the selector result straight to useSyncExternalStore and
compares with Object.is, so returning a fresh [] for the empty case made every
snapshot look changed and re-rendered forever. Hoist a shared EMPTY_QUEUED_TURNS
constant behind a selectQueuedTurns helper and cover the invariant with tests.
logancsack added a commit to logancsack/t3code that referenced this pull request Sep 2, 2026
…e limit (#88)

Commit the draft-store write and the composer's local state in one synchronous render so fast typing on a heavy thread no longer accumulates React's nested-update count to the pingdotgg#185 limit; setPrompt is a no-op for unchanged prompts.
tonytangdev added a commit to tonytangdev/t3code that referenced this pull request Sep 17, 2026
…urement

Compact mode unmounted the context block and reset countdown, so the strip's
overflow measurement flipped between compact and expanded on every render and
React threw pingdotgg#185. Keep every segment mounted and collapse the extras with CSS
as composer labels so the measurement reserves their width.
piyushpradhan added a commit to piyushpradhan/t3code-mediocre that referenced this pull request Sep 19, 2026
The item selector returned a new [] whenever a thread had no items, so
zustand saw a changed snapshot on every render and React bailed with
error pingdotgg#185 (maximum update depth). Use a stable empty list.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
riccardopll added a commit to riccardopll/t3code that referenced this pull request Sep 22, 2026
…anded

The strip measured hidden label text as the largest scrollWidth in the label
subtree. A middle-truncated branch label is a clipped head beside an unclipped
tail, so the compact pass reserved the head only while the expanded pass laid
out head and tail. The two passes disagreed by about one tail, more than the
16px hysteresis, and each layout effect flipped the other until React threw
error pingdotgg#185. Scrolling up hit it reliably: the collapsed composer moves its
controls into the strip and parks the labels on that boundary.

Sum the leaf spans instead, capped at the motion element's max-width, so both
states reserve the room the label takes once expanded.

Fixes pingdotgg#12891
aorwall added a commit to aorwall/t3code that referenced this pull request Sep 22, 2026
Merges `pingdotgg/t3code` `5781b5240..5a61f50` (18 commits) into the
fork.

`93` files landed (`git diff --stat HEAD^1 HEAD`) against `92` in the
upstream
range; the one extra is `docs/fork/inventory.json`. Fork delta holds at
`786`
files.

## Conflicts

- **`AGENTS.md`** (`decide` — `agent-instructions`). Upstream replaced
its Taste
prose with a bullet list. Kept the fork's paragraph and re-stated the
four
facts that were new — adapter boundary, inferred types, comment scope,
and the
`components/ui` restyling rule — in the fork's voice; dropped the two
upstream
bullets the fork already states further down. The `shadcn/no-restyle`
sentence
carries the fork's caveat that upstream runs the ceiling gate in CI this
fork
  disables.
- **`apps/web/src/components/settings/ProjectDefaultsSettings.tsx`**
(was
unlisted, now `project-defaults-settings`). pingdotgg#12954 moved t3.json
resolution
into `resolveProjectSettings` and re-based the rows on an `effective`
value,
  deleting the block the fork's gate sat beside. Took upstream whole and
re-wrapped the gated rows. pingdotgg#12955's new **Worktree submodules** row
joined the
gated set by the inventory entry's own test — a Moatless Workspace has
no local
worktree to populate submodules into — so `workspaceOwnsProjectDefaults`
now
  covers five rows rather than four.
- **`pnpm-lock.yaml`** (`theirs`). Upstream's copy, re-derived with
`install.mjs`
  so the fork's `packages/moatless-api` and `mermaid` edges come back.

Owned-concern sweep over new upstream files: no hits. No new upstream
workflow.
Tripwires steady (4 / 98 / 8 files, the 5 known deletions, 4 active
workflows).
Unsupported-method derivation: ADD and DROP both empty, KEEP unchanged
at two —
no edits to the error unions in `packages/contracts/src/rpc.ts`.

## Usable as-is

- `chore(lint)`: `shadcn/no-restyle` reports `className` restyling of
`components/ui` exports, with `scripts/lint-restyle-ceiling.ts` holding
the
  count (pingdotgg#12982). Warning-level, so nothing fails today.
- `fix(web)`: text selection works while renaming a thread (pingdotgg#12935).
- `fix(web)`: the thread undo notice shows in the sidebar;
`showUndoToast` is
  gone and `threadUndo` drives it from `_chat.tsx` (pingdotgg#12972).
- `fix(web)`: the custom snooze calendar starts the week where the
locale does
  (pingdotgg#12745).
- `fix(contracts)`: a `message-sent` event persisted before `turnId`
existed now
decodes to `null` instead of failing the schema (pingdotgg#12763). This one
reaches the
fork's client directly — any older payload Moatless replays decodes the
same.
- `fix(web)`: message copy actions are named accurately (pingdotgg#12865).
- `fix(web)`: selection actions dismiss when a button is pressed
(pingdotgg#12950).
- `fix(mobile)`: iOS autocorrect no longer rewrites search queries
(pingdotgg#12949); a
  proper pull request icon on iOS (pingdotgg#12855); app version to 1.3.0.
- `test(web)`: redundant favicon test removed (pingdotgg#12856).
- `feat(settings)`: t3.json resolution moved into
`resolveProjectSettings`
(pingdotgg#12954). The resolver itself is pure and in `packages/shared`, so the
fork
  gets it; what it resolves is covered below.

## Unsupported in Moatless / needs implementation

- **Pull request surfaces** — the comment and review buttons merged into
one
composer, `PullRequestReviewBar` renamed to `PullRequestReviewForm` with
a new
`PullRequestComposer` and `PullRequestCommentForm` (pingdotgg#12945); per-row
pull
  request actions answered at once via `pullRequestList.logic.ts` and
`_chat.pull-requests.tsx` (pingdotgg#12843); the embed chip's state icon
(pingdotgg#12951). All
behind `FEATURES.pullRequestSurface`, which stays false: Moatless
dispatches
  `pullRequests.summary` and none of `pullRequests.list`, `.detail` or
`.activity`. Already covered by _A pull request link is a listing
change, not
an event_ and _A pull request snapshot carries no update instant and no
checks
  state_ in `docs/fork/gaps.md`.
- **Manual device tool updates** (pingdotgg#12877) — an `updateTool` input on
`device.list` and a `supportsToolUpdate` boolean on
`DeviceServiceState`,
surfaced in the tool version detail row. Behind `FEATURES.deviceHub`,
which
drops the Devices section entirely. Extends the existing _The device
hub_ gap.
- **Worktree submodule policy as a setting** (pingdotgg#12955) — the new
**Worktree submodules** row writes a `worktreeSubmodules` setting
deciding
whether `submodule update` runs recursively, one level, or not at all on
a new
worktree. Moatless cuts no worktree, so the setting governs nothing it
does.
Gated at a project scope with the other four rows and left at an
environment
  scope, where it is a deployment default the backend ignores. Extends
  _Preparing a worktree behind a progress stream_.

## Backend behavior to consider reproducing in Moatless

- **A repository should say how deep its submodules are cloned**
(pingdotgg#12953,
pingdotgg#12955). Upstream reads a `worktreeSubmodules` preference from the
project's
`t3.json` and the resolved settings, and `GitVcsDriverCore` passes it to
the
`submodule update` it runs. Moatless clones and checks a repository out
into
every sandbox, which is the same work and is on the critical path of
starting a
task: a monorepo with heavy nested submodules pays for all of them on
every
sandbox unless the repository can say `top-level` or `none`. The default
is
`recursive`, so honouring the setting is the only change — nothing
breaks while
it is ignored, it is just slower than the repository asked for. Recorded
under
_Runtime fixes upstream made to its own server_ in `docs/fork/gaps.md`.

## Verification

`node .agents/skills/fork-upstream-merge/scripts/verify.mjs` — all ten
checks
pass: duplicate-adds, tripwires, resolution-check, unsupported-methods,
lockfile,
`fmt:check`, lint, typecheck, the production web build, and every
workspace test
suite. `fmt:check` failed the first pass on the re-wrapped settings
rows; fixed
with `vp fmt` and re-run green.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---
Moatless task:
https://moatless.soaplabstest.com/tasks/3f98e49c-b169-424c-90e2-8b42146b5d95
This was referenced Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants