Conversation
Adds first-class support for multi-repo "workspaces" — a project that spans several independent git repos (a `.code-workspace` as the source of truth) without forcing them into a single monorepo. Checkpointing, turn/ thread diffs, VCS status, agent launches, @-mention search, file previews, worktrees, terminals, and the Source Control UI all fan out across every repo root, with isolated runs getting one worktree per repo. Squashed from 36 phased commits during rebase onto upstream pingdotgg/main (client connection architecture rewrite pingdotgg#2978 + server Services/Layers flattening). Original commits preserved in branch multi-repo-workspaces-backup. Squashed commits (oldest first): feat(project): multi-repo-root projects ("monorepo-like" without being a monorepo) chore(multi-repo-root): review fixes fix(multi-repo-root): repair 123-commit rebase drift fix(multi-repo-root): integrate scanGitRepos RPC with auth-scope feature fix(multi-repo-root): repair fork test failures chore: ignore .playwright-mcp tooling artifacts docs(multi-repo-root): design plan for multi-repo workspaces feat(multi-repo-root): .code-workspace as project source of truth (Phase 1b) feat(multi-repo-root): per-root checkpoint refs foundation (Phase 2a) feat(multi-repo-root): fan checkpoint capture out over all repo roots (Phase 2a) feat(multi-repo-root): aggregate turn/thread diffs across repo roots (Phase 2a) feat(multi-repo-root): fan checkpoint restore out over all repo roots (Phase 2a) feat(multi-repo-root): per-repo grouped turn-diff payload (Phase 2c) feat(multi-repo-root): render per-repo diff sections in DiffPanel (Phase 2c) feat(multi-repo-root): surface repoRoots on web Project model (Phase 2b) feat(multi-repo-root): grouped per-root VCS status hook (Phase 2b) feat(multi-repo-root): render per-repo git status in the chat header (Phase 2b) feat(multi-repo-root): don't flap thread branch across per-repo controls (Phase 2b) feat(multi-repo-root): launch agents with a per-root workspace manifest (Phase 3) feat(multi-repo-root): fan @-mention file search across every repo root (Phase 3) feat(multi-repo-root): resolve cross-root file previews in AssetAccess (Phase 3) feat(multi-repo-root): carry a per-root worktree map on threads (Phase 4) feat(multi-repo-root): fan worktrees out across every repo root (Phase 4) feat(multi-repo-root): resolve agent/diff/checkpoint to per-root worktrees (Phase 4) feat(multi-repo-root): remove every per-root worktree on thread delete (Phase 4) feat(multi-repo-root): hide bare *.git dirs from the file tree (Phase 5) feat(multi-repo-root): add filesystem.writeWorkspaceFile RPC round-tripping unknown keys (Phase 5) feat(multi-repo-root): add Manage folders dialog to round-trip the .code-workspace (Phase 5) feat(multi-repo-root): re-read .code-workspace on project load and reconcile roots (Phase 5) feat(multi-repo-root): browse files and resolve file links across all repo roots (pingdotgg#923) feat(multi-repo-root): consolidate per-repo git actions into one Source Control control feat(multi-repo-root): pick which repo to open a terminal in feat(diff): show all repos in multi-repo branch/working diff with repo filter fix(terminal): open per-repo terminal in that repo's worktree feat(diff): show working/branch diff for non-isolated multi-repo workspaces fix(diff): refresh diff panel on reopen to avoid stale cached patch Follow-up details (post-rebase work folded in): - Branch/working diff fans out per repo with a repo-filter dropdown (All repos / per repo), replacing the single-repo computation; the base-ref selector is hidden in multi-repo mode since one base ref isn't valid across repos. - Non-isolated `.code-workspace` projects (no per-repo worktrees, a container workspaceRoot that isn't a git repo) diff each project repoRoot directly instead of running `git diff` in the container and reporting "no changes". The WS handler passes allowedRepoRoots from the shell snapshot and ReviewService accepts them in its workspace-boundary check, since these repos can live anywhere on disk. - Per-repo terminals open in the targeted repo's worktree (resolved via the thread's worktree map), falling back to the plain repo root. - The diff panel refreshes on reopen (useRefreshOnReopen) so the stale-while-revalidate atoms don't serve a stale cached patch after the panel is unmounted and remounted.
The multi-repo migrations were originally numbered 033-036 and shipped in pre-rebase branch builds, so those slots were recorded in effect_sql_migrations on every machine that ran one. The rebase renumbered them to 037-040, but Migrator.fromRecord only runs migrations whose numeric id exceeds the highest recorded id and never compares names -- so main's real 033-036 (Settled/Snoozed/TitleRegeneration/Pinned) were skipped on those databases and could never run again. The result was a projection_threads table missing seven columns that ProjectionSnapshotQuery selects. listThreads failed statement preparation with "no such column: settled_override", which crash-looped the backend before it could serve the client; the desktop window waited 30s for a backend that never came up and showed an empty screen with no visible error. Migration 041 adds the seven columns if absent, which is equivalent to letting 033-036 run -- each is a nullable TEXT ADD COLUMN with no index or backfill. Healthy databases already have them and it is a no-op. detectMigrationLedgerDrift compares the recorded ledger against the manifest and names the migrations that were consequently skipped, so this surfaces as a migration problem rather than a corrupt-looking database. It runs after migrations so healing has already applied, and is wrapped so it can never fail startup. It warns rather than errors: recorded names cannot be corrected without rewriting the ledger, so drift is permanent even once healed, and anything louder would fire on every boot of a database that is actually fine. Also documents at the manifest that migration ids are immutable once any build has applied them, and that a rebase should append after main's highest id rather than renumber. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
The sidebar header artwork was reachable only on Nightly and Dev builds: any other stage label resolved to no variant, and the Appearance setting that controls it was hidden along with it, so self-built clients (which resolve to Alpha) had no way to turn it on. Fall back to the night sky for stages without their own artwork, and let the environment pill carry an unrecognised stage label through instead of dropping it, which is what un-hides the existing artwork/pill/none setting on those builds.
"Open in" pointed every editor at the project's `workspaceRoot`, which for a `.code-workspace` project is only the anchor directory holding the file. VS Code opened it as a plain folder, so none of the repo roots appeared in the tree -- the multi-root workspace the project is defined by was never what got opened. Pass the `.code-workspace` file alongside the anchor directory and pick between them per editor. The choice is made server-side, in the launcher, because the target depends on which editor the user picks from the menu and that is not known when the picker renders. `supportsWorkspaceFile` on the editor registry marks the VS Code family; Zed and JetBrains would show the raw JSON and the file manager would hand it to the OS opener, so those keep getting the directory. Isolated runs keep getting their worktree. The fanned-out worktrees have no workspace file of their own, and the project's would open the original checkouts instead of the copies the thread is working in. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
New-worktree mode was unusable for any `.code-workspace` project. The base branch selector ran its ref queries against `workspaceRoot`, which for those projects is the anchor directory holding the workspace file and usually not a git repo, so every query reported `isRepo: false` and the selector came up empty. Sending then refused outright, by design, rather than silently falling back to local execution. Populating the selector alone would not have been enough. The server compared each `repoRoot` against the client's `projectCwd` to find the repo the chosen base ref belongs to; for a workspace-file project that comparison never matched, so the base ref was dropped for every root and each repo quietly branched off its own HEAD instead. `startFromOrigin` went further and ran `git fetch` in the anchor directory, which fails and aborts the whole send. `resolveAnchorRepoRoot` picks the repo root that stands in for the project in single-repo git flows: the anchor when the workspace file lists it, else the first root in file order. Single-repo projects resolve to exactly today's value. Both the selector and the worktree fan-out now go through it, so refs list, the chosen base lands on the anchor repo while cousins still branch off their own HEAD, and the origin fetch runs in a repo. The selector's existing auto-default picks the repo's `origin/HEAD` once refs load, so this works without the user opening the dropdown. Per-root base selection still needs a wider `prepareWorktree` contract and is left for follow-up. Also repairs a stale assertion in the bootstrap worktree test: it still expected the pre-fan-out `createWorktree` shape (`path: null`, `baseRefName`) and had been failing on this branch. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Rebasing the multi-repo branch onto main picked up tests written against the single-repo shapes: thread shells now carry a per-root `worktrees` map, checkpoint diffs carry per-repo `groups`, and every worktree comes from the fan-out (which supplies a placement path instead of the old `path: null` / `baseRefName` pair). The heal-skipped-columns migration also moved from 041 to 045, appending after main's 037-040 rather than renumbering into slots main now owns, so its test walks to 44 before healing at 45. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
The rebase onto main moved the multi-repo migrations from 037-040 to 041-044, which recreates the drift the healing migration was written for. Every machine that ran the branch between the two rebases recorded 37-40 under the multi-repo names, so main's real 037-040 -- TurnsKeysetIndex, PinOrderKey, DefaultThreadEnvMode, FaviconPath -- were skipped and, since the migrator only runs ids above the highest recorded one, never will. ProjectionSnapshotQuery selects favicon_path and default_thread_env_mode, so those databases crash-loop the backend exactly as before. Healing them is just re-running them: all four already guard on a PRAGMA table_info check or CREATE INDEX IF NOT EXISTS, so a second run is defined behavior and a no-op on databases that ran them for real. That keeps the repair in one place rather than restating their SQL. Renamed to HealSkippedRenumberedMigrations since it no longer heals only thread columns, and the id has not shipped under the old name. Verified against a copy of a real drifted database: the migrator runs 42-45, skips 41 as already-recorded, and pin_order_key, default_thread_env_mode, favicon_path and the turns keyset index all come back. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
The multi-repo work landed before sidebar v2 became the default, so all of it sat in what is now LegacySidebar: the once-per-session `.code-workspace` reconcile and the "Manage folders..." project context menu. The default sidebar had no multi-repo awareness at all. The reconcile moves to `useWorkspaceProjectReconcile`, mounted in AppSidebarLayout so it runs under whichever sidebar is active -- and runs at all, rather than only when a project row happens to render. The legacy copy goes with it. "Manage folders..." moves to the project settings page. The default sidebar has no project context menu (its only two are thread-scoped) and already routes rename/grouping/remove to /projects/$projectKey, so the folder editor belongs in the same place, scoped to the selected checkout. Thread rows resolved git status against `workspaceRoot`, which for a `.code-workspace` project is the folder holding the file and usually not a repo -- so branch-mismatch never fired and the PR pill went blank. They now resolve against the anchor repo root. `repoRoots` is backfilled to `[workspaceRoot]` for single-root projects, so this is a no-op outside multi-repo workspaces and costs no extra queries. Isolated runs still report the anchor worktree only; per-root fan-out in a list of rows is a separate question. Workspace-backed projects also get the palette's `.code-workspace` marker as their favicon fallback, so they read as workspaces in the thread card, the draft row, the hover card and the project picker. A project with its own icon keeps it. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
The diff panel probed git status in a single cwd, falling back to the project's workspaceRoot. For a workspace-file project that is the anchor directory holding the .code-workspace, which usually is not a repo, so the probe returned isRepo: false. That rendered "this project is not a git repository" and disabled the checkpoint diff query outright, so the client never asked the server for diffs it already had. The per-repo grouping below it was never reached. Resolve the project fallback through resolveAnchorRepoRoot, the helper the branch selector already uses, and stop gating the panel on the probe when there are repo targets to diff: each one is a repo by construction. Single-root projects are unchanged, and a genuinely non-repo project still gets the message. With the anchor fixed, the single-cwd branch preview would fetch a patch the multi-repo view never renders, so it is disabled there. That left the header refresh button dead, since the per-repo sections own their queries, so refresh, window focus, and turn completion now bump a token those sections watch. Fixes LoganRupe#156
Rebasing onto main moved the multi-repo migrations from 041-045 to 042-046 so main's 041_AuthSessionClientConnection keeps its slot. Every machine that ran the branch before this rebase has 41 recorded as ProjectionProjectsRepoRoots, so main's 041 was skipped there and auth_sessions is missing client_surface and client_app_version. 041 already guards on PRAGMA table_info, so the heal migration just runs it alongside 037-040.
The mobile review screen diffed one cwd, the thread's anchor. For a multi-repo workspace that is the container repo, which usually has no changes, so Working tree and Branch changes silently dropped every other repo's edits. Move resolveDiffRepoTargets into client-runtime so web and mobile share the targeting rule (an isolated thread without a worktree map never falls back to the project checkouts), and have web import it from there. On mobile, fan the diff preview out over every target through one derived atom, fold the per-repo previews into the existing Working tree and Branch sections as groups, and carry the server's turn diff groups the same way. Files of a multi-repo diff are labelled with their repo folder in the native list and in review comments. Single-repo threads keep the single-cwd diff and render as before. Verified on an Android emulator against a seeded three-repo workspace: Turn, Working tree and Branch changes all list the non-primary repo's changes. Claude Fable 5 via T3 Code.
Working tree and branch diffs for a multi-repo thread showed 0 files in every repo while the turn diff showed the changes. The thread's per-root worktree map only reaches clients on the shell stream: `thread.meta-updated` is not a detail event, so the detail snapshot keeps the empty map from creation and the diff panel fell back to diffing the project's repo roots, which are the user's own clean checkouts. Take `worktrees` from the shell when merging, like `worktreePath`. Stop the panel from ever falling back to repo roots for an isolated thread. Name the repo a single-repo turn diff actually touched instead of the anchor worktree, and render an unparseable per-repo patch raw instead of reporting "0 files".
The projection snapshot queries never selected the workspace_file column and never mapped it, so workspaceFile silently dropped out of every client-facing project shell. Open-in fell back to the folder, the sidebar never showed the workspace icon, and Manage folders never appeared (LoganRupe#185). Select the column in the three project SELECTs and map it in mapProjectShellRow plus the three inline OrchestrationProject literals that build read models from the same rows.
The rebase onto upstream main moved the multi-repo migrations from 044-048 to 048-052, vacating four ids that upstream has since claimed: 044_ClearAutomaticProjectModelDefaults, 045_ProjectionProjectsAutoPull, 046_RepairAutomaticSettlementTimestamps and 047_ProjectionProjectIcon. Machines that ran the previous branch build recorded 44-48 under the multi-repo names, so the migrator will never run main's real migrations for those ids: `projection_projects` stays without `auto_pull` and `project_icon_json`, which ProjectionSnapshotQuery selects on every project read, and the two data repairs never happen. Extend 052_HealSkippedRenumberedMigrations to re-run 044-047 after the 033-036 column restore. All four are idempotent: 045 and 047 guard on a PRAGMA table_info check, and the 044 and 046 repairs only match rows they have not already rewritten. 046 also needed a guard of its own. It reads `projection_threads.settled_at`, a column 033 adds, so on a database carrying the 033-036 drift it aborts the boot at id 46 before the heal at 52 can restore the column. It now returns early when the column is absent; the heal re-runs it once the column is back, so the repair is deferred rather than lost. Proven on a VACUUM INTO copy of the real ~/.t3/userdata database (ledger ids 33-48 all recorded under branch names): after migrating, every column the snapshot query reads is present and the ledger ends at 52.
Upstream's local-only base branch fallback (pingdotgg#8751) added a remoteBranchExists probe to the worktree bootstrap, which the multi-repo anchor test's GitVcsDriver layer did not implement.
Rebasing onto main moved the multi-repo migrations from 048-051 to 050-053, and the healing migration from 052 to 054. Machines that ran the previous branch build recorded 48-52 under the multi-repo names, so main's real 048_ProjectionThreadBranchPullRequest and 049_ProjectionThreadsActiveOrderKey were skipped and, since the migrator only runs ids above the highest recorded one, never will. ProjectionSnapshotQuery selects branch_pull_request_json and active_order_key on every thread read, so those databases crash-loop the backend. Both are idempotent ADD COLUMN migrations guarded by a PRAGMA table_info check, so healing them is just re-running them from 054.
Opening a multi-repo project from a remote environment emitted a
`vscode://vscode-remote/ssh-remote+<host><path>` link built from the
project's anchor directory, so VS Code showed one folder instead of the
multi-root workspace. Only the local-exec branch of OpenInPicker read
`openInWorkspaceFile`; the remote-links branch never consulted it.
No new URI form is needed. VS Code's protocol handler
(`getWindowOpenableFromProtocolUrl` in `src/vs/code/electron-main/app.ts`)
returns `{ workspaceUri }` instead of `{ folderUri }` whenever the path
ends in `.code-workspace`, so `buildRemoteOpenUrl` now runs the same
`resolveEditorTarget` the server uses and links the workspace file for
editors that support one. Every remote-capable editor is a VS Code fork,
so all of them get it.
Fixes LoganRupe#234.
Two repo roots in one turn diff that both changed the same relative path produced two tree entries at the same path, and Pierre's PathStore threw. The tree now builds from the per-repo groups the panel already renders, with each root's files under a folder named for that root. A repeated path is dropped instead of handed to the tree. Fixes LoganRupe#240
Upstream claimed 050_ProjectionThreadPullRequests and 051_ProjectionThreadMessageContext, so the multi-repo migrations move to 052-055 and the heal to 056. Machines that ran the previous build recorded 50-54 under the multi-repo names, which skips both of main's migrations for good: `projection_thread_pull_requests` never exists and `projection_thread_messages` has no `context_json`. The heal now re-runs 050 and 051 after 037-049. Both are idempotent: the table and index use IF NOT EXISTS, the legacy link backfill inserts with OR IGNORE, and 051 guards on PRAGMA table_info. 050 also hits the reverse hazard 046 did. On a database that skipped 042, 050 runs before the heal and selects `linked_pull_request_json`, which aborts the boot. It now skips the backfill when that column is absent, and the heal re-runs it once 042 has restored the column. The existing 042-043 case covers that path. Verified against a VACUUM INTO copy of the live ledger (max id 54): 055 and 056 ran and the database passes integrity_check.
The rebase resolution keeps upstream's createWorktree call, with progress and cancel, for single-root projects. Only multi-repo projects fan out under <worktreesDir>/<projectId>/<threadId>. Restore upstream's assertion.
`t3 app` now accepts a .code-workspace file as well as a project directory. The CLI sends the file as workspaceFile and its parent as workspaceRoot; the desktop renderer resolves repoRoots through the existing filesystem.readWorkspaceFile query and creates the project the same way the command palette does. Workspace projects opened from the CLI are titled after the file, matching the palette.
Upstream claimed 052_ProjectionThreadTitleState and 053_PullRequestFilesViewed, so the multi-repo migrations move to 054-057 and the heal to 058. Machines that ran the previous build recorded 52-56 under the multi-repo names, which skips both of main's migrations for good: `projection_threads` has no `title_state_json`, which the snapshot query selects on every thread read, and `pull_request_files_viewed` never exists. 052 is a bare ADD COLUMN, so the heal guards it on PRAGMA table_info like 033-036. 053 uses CREATE TABLE IF NOT EXISTS and is re-run as is. Neither reads a column an earlier skipped migration owns, so there is no reverse hazard this time. Verified against a VACUUM INTO copy of nauvoo's live ledger (max id 56): 057 and 058 ran, both objects exist, and the database passes integrity_check.
Upstream's rewind guard (pingdotgg#12306) refuses a file restore unless the checkpoint cwd is the thread's own worktree and no other thread or live session owns a path inside it. It read a single `checkpointCwd`, which the multi-repo revert replaced with one root per repo, so the guard no longer compiled. Run the guard for each checkpoint root. A root counts as the thread's own when it is any of its per-repo worktrees, not just `worktreePath`, and other threads contribute every worktree they own, or every repo root of their project when they run on the checkouts, since a workspace file can list repos outside its container.
New upstream fixtures build threads without `worktrees`, and the mobile lazy file placeholder had no `repoLabel`. The no-origin bootstrap test still asserted the fan-out worktree path, which single-root projects no longer take; it now matches upstream's worktree call like its sibling.
DropdownMenuItem stayed exported from ui/menu but fell out of DiffPanel's
import list when upstream rewrote the block, and nodeSqliteClient's
layerMemory collapsed into layer({ filename: ":memory:" }).
…o UI The rebase brought in upstream's UI-system work (ghost-muted, PopoverPopup width, DialogPanel spacing) and the restyle ceiling that goes with it. The branch's hand-styled triggers put the count at 651 against a ceiling of 628, failing the gate. Routing them through the variants drops it to 616.
WorkspaceGitScan and WorkspaceFile each carried a copy of what pathExpansion.ts already exports as expandHomePathWith.
…pe#294) "Open in" on an isolated run opened the anchor worktree as a plain folder, so the other repos were missing from the editor. The worktree fan-out now writes a copy of the project's .code-workspace into the per-thread directory, with each repo folder pointed at its worktree and non-repo folders left at their original path. The client opens that copy for fanned-out threads. Threads created before this have no copy, so the launcher falls back to the directory when the workspace file is missing. Fixes LoganRupe#125 Co-authored-by: Logan Rupe <logzerroneous@gmail.com>
…Rupe#295) A multi-repo isolated run based only the anchor repo on the chosen branch; every other repo branched off whatever it had checked out, and mobile's base-branch list was empty because it queried the directory holding the .code-workspace. prepareWorktree gains an optional repoBaseBranches list of per-repo picks. The server bases each non-anchor repo on its pick, else its own default branch (origin/HEAD), else its checkout, and "start from origin" now fetches per repo. The web composer shows a "+N repos" menu next to the anchor's base selector with a branch submenu per repo. Mobile lists the anchor repo's branches and leaves the rest to the server default. Fixes LoganRupe#113 Co-authored-by: Logan Rupe <logzerroneous@gmail.com>
The +N PR badge in the sidebar and composer now opens a right-panel tab per pull request when they are unrelated (one per repo, say), and lists them all on hover. Stacks still open the ordered Pull requests list. The multi-repo Source Control popover reads each repo's worktree for an isolated run instead of the original checkout, so each row shows the run's PR. View PR passes the PR's URL, so a non-primary repo row opens its own repository's PR rather than the same number in the primary repo. Fixes LoganRupe#298 Co-authored-by: Logan Rupe <logzerroneous@gmail.com>
Upstream moved composer-strip triggers onto ComposerControl and made shadcn/no-restyle a lint error. The per-repo base branch trigger now uses ComposerControl like the branch selector beside it, and the diff worktree tooltip drops its leading-tight override.
In a multi-repo project whose workspace root is a parent folder, chat file chips resolved repo-relative paths against the workspace root and failed to open, or opened a same-named file in another repo. - Multi-repo sessions get runtime instructions to write absolute file paths; every provider adapter passes the flag. - Chat file chips pass their owning repo root to the file panel, and skip the workspace-wide basename lookup when a root is known, for both open and reveal. - The file tree reveals files and repo roots under their repo label; breadcrumbs name the owning repo using the tree's labels. - A link to the workspace root or a repo root opens as a folder. Fixes LoganRupe#302
When a project's repos sit inside its workspace folder, Claude Code leaves them out of the environment block it shows the model, and Cursor, Grok, OpenCode and Antigravity get no repo list at all. The model then treats the workspace folder as the project and searches it for repos. The multi-repo instructions now list every repo root, and say that the working directory is the workspace folder, not a repo, when it is not one of the roots. The session start input carries the full root list so adapters can tell whether the working directory is a repo root. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks for picking this up so quickly, and for testing it across providers. The Codex write-up is a good catch too. I wouldn't have spotted that newer models were skipping our instructions on this branch. I checked out the branch: the tests pass and the server typecheck is clean. Two things before I merge:
I'll comment here once the branch is updated. |
44b00df to
3f17cf7
Compare
|
One change from what I asked earlier: I had to resolve the #307 commit against pingdotgg#13547 during the rebase. Both Codex changes you described are already on the branch. |
In a multi-repo project, the agent is often not told which repos belong to the project, so it searches the workspace folder for them. Claude isn't told about repos inside the workspace folder, and Cursor, Grok, OpenCode and Antigravity aren't told about any. Details are in #309.
Fix
This is option A from #309. The runtime instructions now list the project's repos, in a new block after #307's path block. #307's wording is unchanged, and the new block is added in the same cases. For a project whose
.code-workspaceis in the home folder, the model now sees:The last sentence is left out when the working directory is itself one of the repos. That happens in isolated worktree runs, and when the
.code-workspacefile is in a repo's root folder. To tell these cases apart, the session now starts with the full repo list (a new optionalrepoRootsfield onProviderSessionStartInput).additionalRootsleaves the working directory out, so it can't be used for this.Codex: needs a step when
mainis merged inOn this branch, newer Codex models don't receive T3 Code's instructions at all, including #307's path block and this list. GPT-6 Luna got Codex's built-in instructions instead. pingdotgg#13547 fixes this. It's on this fork's
main, but not yet onmulti-repo-workspaces.When merging
mainin, two changes keep both blocks for Codex. I tested them in a local merge.CodexSessionRuntime.ts, keepmultiRepoinbuildCodexTurnInstructions' input and pass it tobuildCodexAdditionalContext, next tomodel,modelNameandreasoningEffort. Without this, Codex silently loses both blocks.CodexSessionRuntime.test.ts, change the multi-repo test to readadditionalContext.t3_code_runtime.valueinstead ofdeveloper_instructions.Size check: Codex allows about 4,000 bytes per entry. With five repos, T3 Code's entry is 3,113 bytes.
Testing
Fixes #309
Model: Claude Opus 5.5, harness: Claude Code.