Skip to content

🤖 perf: skip git/PR status refresh on unrelated workspace metadata events - #5566

Merged
ThomasK33 merged 12 commits into
mainfrom
perf/git-status-churn
Oct 4, 2026
Merged

ThomasK33 merged 12 commits into
mainfrom
perf/git-status-churn

Conversation

@ThomasK33

@ThomasK33 ThomasK33 commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

Summary

Unrelated workspace metadata events no longer start git status or gh commands. GitStatusStore and PRStatusStore now refresh immediately only when a metadata change affects a workspace the UI shows: the workspace was added or removed, or one of its status inputs changed. Under 10 unrelated events/s, git-status executeBash calls drop from 600/min to 0/min, visible or hidden.

Background

Live flight-recorder data showed workspace.executeBash as the second most frequent RPC. Each metadata event built a new metadata Map. Two calls then fired RefreshController.requestImmediate() once per event:

  1. syncWorkspaces(map) in both stores.
  2. setClient(api) in both stores. AppLoader re-runs its store-sync effect on every metadata change and passes the same api each time.

requestImmediate() skips the debounce, the 500 ms minimum gap and the hidden-window check. The result was one backend process spawn per event. On a large backend each spawn blocks the event loop about 5 ms (page-table copy; this is an estimate).

Implementation

  • setClient returns early when the client reference is unchanged. A first connect or a reconnect (null → client, or a new client) still refreshes.
  • New helper src/browser/utils/statusRefreshInputs.ts (hasSubscribedStatusInputChange) defines the status-relevant metadata fields once. Each field has a comment that explains why it is there: checkout location (name, projectPath, namedWorkspacePath, subProjectPath, runtimeConfig), fetch/multi-project keys (projectName, projects), and lifecycle states that decide whether a command can run (isInitializing, isRemoving, incompatibleRuntime, transcriptOnly, archive timestamps). Only subscribed workspaces are compared. The helper skips entries that kept their reference, so the cost stays small. It returns subscribed workspaces that just appeared, and any workspace whose inputs changed. A change to an undisplayed workspace is remembered but starts no refresh, so its first refresh after resubscribing bypasses the caches below.
  • syncWorkspaces in both stores keeps all cleanup. It calls requestImmediate() only on reactivation or on a relevant change. For other changes it does nothing. It does not call schedule(), because continuous churn would then add one refresh per debounce window.
  • PRStatusStore marks each changed workspace. The next refresh probes its PR and stack regardless of the 5 s and 60 s cache TTLs, so the one metadata-driven refresh cannot be swallowed. This includes a change that lands while a probe is in flight. Before this PR, the next unrelated event retried the refresh. Now no unrelated event retries it.
  • GitStatusStore marks each changed workspace for a passive git fetch. The next refresh fetches its key first and ignores the 3-60 s fetch backoff, but not while that key's fetch is in progress. The changed workspace represents its key, so the fetch runs in the new checkout and covers its new secondary repos. Xum consumes the fetched representative's mark before the fetch starts. Other changed workspaces that share the key keep their marks, and each gets its own fetch after its own runtime eligibility check. When the fetch and its secondary-repo fetches finish, Xum requests one refresh, so status reads the new refs and the next marked key gets its turn. A failed fetch is not retried in a loop.
  • These triggers are unchanged: subscriptions, focus and visibility, file-modifying tools, invalidation, chat-replay and runtime-eligibility retries, and hidden-window behavior for relevant changes.

Before / after

The bench replays AppLoader's real caller sequence (setClient(api) + syncWorkspaces(newMap)) with a stubbed client. It runs 60 s of wall time, with 10 title-change events/s on 3 other workspaces and 1 subscribed workspace. Startup calls are excluded (2 in every run). The bench script was temporary and is not committed.

Store Window base 5ea096bb28 (calls/min) this PR (calls/min)
GitStatusStore visible 619 (600 status + 19 fetch) 0
GitStatusStore hidden 619 (600 status + 19 fetch) 0
PRStatusStore visible 13 0
PRStatusStore hidden 13 0

The live dogfood A/B used a real dev server, counted git status --porcelain processes in workspace worktrees, and ran 10 events/s for 60 s. It measured 501 status runs and 25 gh runs on base, and 0 / 0 on this branch. Title churn on the open workspace itself for 30 s gave 287 status runs on base and 0 on this branch.

Validation

  • New store tests (visible and hidden): unrelated churn, irrelevant fields on the open workspace and identical re-emits cause no executeBash. Runtime, name, project path and initialization changes refresh promptly. Removal and re-add, reconnect, and an in-flight follow-up still refresh. PR and stack probes run promptly after a checkout change within the cache TTLs, and again after a change made during a held probe. A checkout change within the fetch backoff triggers a passive fetch. This holds for a change during a held fetch, for two changed fetch keys, and for a project added to a multi-project workspace. A failed fetch causes no loop. A file-modification refresh still fires during 10/s churn, and churn adds no extra refreshes. 7 of these tests fail on base, and mutation checks cover the setClient guards and the helper branches.
  • Remote dogfood UAT through Coder Agents passed. Commits and edits in the open workspace still updated the footer git indicator (↑1, *) while other workspaces churned. Backend restart and branch switch also refreshed.

Risks

The risk is low and limited to passive git/PR indicators. If a metadata field that affects status were missing from the projection, that workspace's indicator would update on the next focus, file edit or subscription instead of at once. The projection is listed in one place with a rule for when to add fields.

Deferred (not fixed in this PR):

  1. RuntimeStatusStore has the same setClient/syncWorkspaces churn pattern. Tracked in 🤖 perf: stop RuntimeStatusStore refresh churn on unrelated metadata events #5573.
  2. An ordinary passive fetch never triggers a status re-read after it settles. This already happens on an idle main, and churn used to hide it. Tracked in 🤖 perf: re-read git status after a passive fetch settles #5572. Separately, RefreshController.dispose() is permanent, so reactivating a store after dispose() (Strict Mode, dev only) never refreshes. That behavior already exists on main and this PR does not change it.

📋 Implementation Plan

Plan: stop git/PR status refresh churn on unrelated workspace metadata events

Problem

GitStatusStore.syncWorkspaces and PRStatusStore.syncWorkspaces call refreshController.requestImmediate() on every metadata Map change. requestImmediate() bypasses the debounce, the 500 ms minimum interval and the hidden-window check, and it clears a pending debounce timer. AppLoader's store-sync effect (src/browser/components/AppLoader/AppLoader.tsx, deps include workspaceContext.workspaceMetadata and api) also calls gitStatusStore.setClient(api) and getPRStatusStoreInstance().setClient(api) on every metadata change, and both setClient implementations call requestImmediate() even when the client reference is unchanged. Result: one git status executeBash (plus PR commands) per metadata event, visible or hidden. Each onMetadata event replaces exactly one Map entry with a new object (other entries keep their references); snapshot events rebuild the whole map.

Fix

  1. setClient idempotent in GitStatusStore and PRStatusStore: return early when the client reference is unchanged. Keep the immediate refresh for null -> client and for a different client.
  2. Pure helper (new small module under src/browser/utils/, or colocated in stores if more natural) that decides whether a metadata update affects a subscribed workspace's status inputs:
    • true if a subscribed workspace id was added to or removed from the map;
    • true if a subscribed workspace entry changed by reference AND its status-relevant inputs differ structurally;
    • false otherwise (other-workspace churn, re-emits of identical data, changes to irrelevant fields such as title/tags/aiSettings).
      Status-relevant inputs = every metadata field the refresh path reads, directly or through helpers, plus fields that change which checkout the backend runs commands in. Verify by reading: GitStatusStore (checkWorkspaceStatus, checkMultiProjectWorkspaceStatus, getBaseRef, getFetchKey, tryFetchWorkspaces, isMultiProject/getProjects helpers, passive runtime eligibility helpers such as onPassiveRuntimeEligible/canProbe*), PRStatusStore (refreshAll and helpers), and the backend workspace.executeBash workspace resolution (path derived from name/namedWorkspacePath/projectPath/runtimeConfig). Expected candidates (verify, do not trust blindly): runtimeConfig, projectPath, projectName, projects, name, namedWorkspacePath, isInitializing, transcriptOnly, incompatibleRuntime, isRemoving. Define the projection once, with a comment naming why each field is included, and share it between both stores if both depend on the same inputs (PR store may need a different/superset list; verify). Structural comparison is fine for nested values (runtimeConfig, projects); avoid adding a generic deep-equal library.
  3. GitStatusStore.syncWorkspaces and PRStatusStore.syncWorkspaces: keep all existing cleanup; call requestImmediate() only when (a) the store was inactive and is reactivated, or (b) the helper reports a relevant change for a subscribed workspace. Otherwise do nothing (no schedule()). Subscription-triggered immediate refresh (queueImmediateUpdate / subscribeWorkspace microtask), focus/visibility refresh, file-modify schedule(), invalidateWorkspace, chat-replay gate retries and runtime eligibility retries stay unchanged. Metadata arriving after a subscription counts as "added" for that subscribed id, so it refreshes.
  4. Hidden-window behavior unchanged: relevant changes still use requestImmediate (as today).
  5. Out of scope: RuntimeStatusStore has the same sync/setClient pattern (devcontainer status RPC). Leave untouched; record as a deferred follow-up. No RefreshController changes.

Tests (tests first; load test-audit and answer its authoring questions)

In src/browser/stores/GitStatusStore.test.ts and PRStatusStore.test.ts (existing jest-globals style with stubbed client, bun test <file>), plus a helper test only if it covers branching not already covered through the stores:

  • Real caller sequence: repeated setClient(sameClient) followed by syncWorkspaces(newMap) with churn on another workspace -> zero additional executeBash.
  • Irrelevant change to the subscribed workspace (title/tags) and an identical re-emit with rebuilt nested objects -> zero executeBash.
  • Relevant change on the subscribed workspace (runtimeConfig or projectPath/name) -> prompt refresh (no debounce wait).
  • Metadata arriving after subscription, and a new subscription -> refresh.
  • Removal + re-add of a subscribed workspace -> refresh / cleanup.
  • Continuous 10/s unrelated churn while a file-modify schedule() refresh is pending -> the refresh still fires within its debounce window (churn cannot starve it).
  • Dispose then reactivation via syncWorkspaces -> refresh.
  • Relevant change during an in-flight refresh -> a follow-up refresh still happens.
  • setClient(null) then setClient(client) -> refresh still happens.
    Hidden and visible variants where behavior differs. Route any new test file (src/** tests are auto-routed by bun test src; confirm make static-check check-test-routing passes). No "exported for tests" comments; no test-only production exports.

Before/after measurement (parent runs it after the workflow; workflow agents need not)

Temporary bench (not committed) with stubbed client and fake clock: 60 simulated seconds, one subscribed workspace, 10 unrelated metadata events/s through the real AppLoader caller sequence (setClient(same) + syncWorkspaces(new Map)), document hidden and visible; count git-status executeBash, fetch executeBash and PR commands separately; startup calls recorded separately. Run against base main and the branch.

Acceptance criteria

  • Unrelated metadata churn triggers no executeBash from GitStatusStore/PRStatusStore (hidden and visible).
  • Relevant changes, new subscriptions, metadata-after-subscription, reactivation still refresh promptly.
  • Churn cannot postpone scheduled refreshes.
  • make static-check and touched/sibling tests pass. No UI changes.

Dogfooding / UAT focus (synthetic)

Start a dev server (make dev-server with an isolated XUM_ROOT) with a project and at least 3 workspaces. Open workspace A. In a loop generate ~10 metadata events/s on other workspaces (e.g. rename titles / update workspace settings via the server API or xum api CLI). While churn runs: (1) edit a file in A's worktree and commit; verify A's git status indicator (footer/branch selector dirty/ahead counts) updates within the normal refresh window (file-modify debounce ~3 s or on focus); (2) make an uncommitted edit and verify the dirty indicator; (3) confirm backend executeBash/git-status RPC rate stays near idle during churn (e.g. backend debug log or counting requests) compared with base. Capture screenshots of the indicator before/after commit and a short recording. Check UI at 390px width only if UI changed (it should not).


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high

GitStatusStore and PRStatusStore refreshed immediately on every workspace
metadata event, and AppLoader's re-applied setClient(api) refreshed again.
requestImmediate bypasses the debounce and hidden-window checks, so each
event spawned a git status (and gh) process.

- setClient is a no-op when the client reference is unchanged.
- syncWorkspaces refreshes only on reactivation or when a subscribed
  workspace is added/removed or one of its status inputs changes
  (shared projection in browser/utils/statusRefreshInputs.ts).

Generated with xum

Signed-off-by: Thomas Kosiewski <tk@coder.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
Rewrite change-narration comments in timeless terms, shorten the
GitStatusStore syncWorkspaces comment, and share one clean git-status
result helper in the metadata-driven refresh tests.

Signed-off-by: Thomas Kosiewski <tk@coder.com>
Add an initialization-state row to the prompt-refresh table so pruning
lifecycle fields from the status-input projection fails a test, and extend
the churn test past one debounce window so scheduling a debounced refresh on
unrelated metadata events fails it.

Signed-off-by: Thomas Kosiewski <tk@coder.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-04T08:57:00.681417Z 1bab0bc Manual request
🔒 Security Review ✅ Completed 2026-10-04T08:54:50.925266Z 1bab0bc Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7f44d0c09b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/stores/PRStatusStore.ts Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 7f44d0c09b

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Unrelated metadata events no longer retry PR refreshes, so the PR (5 s) and
stack (60 s) cache TTLs could swallow the single refresh a relevant change
requests and keep the previous checkout's PR. Mark changed workspaces and
probe them regardless of TTL on the next refresh, including when the change
lands during an in-flight probe. Drop the no-op removal branch of the helper.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 82369234bf

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 82369234bf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/stores/GitStatusStore.ts Outdated
Unrelated metadata events no longer retry refreshes, so the 3-60 s fetch
backoff could swallow the fetch a checkout change needs and leave ahead/behind
on stale remote refs. Mark changed subscribed workspaces; the next refresh
fetches their key first regardless of backoff (not while in progress), with
the changed workspace as representative. Marks are consumed before the fetch
starts; its completion requests one refresh, as does an ordinary fetch whose
key gained a mark meanwhile.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 38225f61e0

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 38225f61e0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/utils/statusRefreshInputs.ts Outdated
Comment thread src/browser/stores/GitStatusStore.ts
… after secondary fetches

Remember status-input changes of undisplayed workspaces so their first
refresh after resubscribing bypasses the PR/stack TTLs and fetch backoff.
Request the forced follow-up status read only after the secondary repo
fetches settle, so it cannot race them.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: a07f0a1320

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a07f0a1320

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/stores/GitStatusStore.ts
…mark

Other changed workspaces sharing the fetch key keep their marks, so the
follow-up refresh fetches each in its own checkout after its own runtime
eligibility check; a stopped runtime registers a retry instead of losing
its unique secondary repos.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: f58209eb5a

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f58209eb5a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/stores/GitStatusStore.ts
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: f58209eb5a

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f58209eb5a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/stores/GitStatusStore.ts
Comment thread src/browser/utils/statusRefreshInputs.ts
@ThomasK33

Copy link
Copy Markdown
Member Author

Review loop stopped: NOT READY. Round 6 of 6 did not give a clean Codex verdict on f58209eb5a, so this PR needs a human decision.

What happened:

  1. Rounds 1-4 found real gaps in the new "refresh only on relevant change" logic: PR/stack cache TTLs, fetch backoff, undisplayed workspaces, secondary-fetch ordering, and shared fetch keys. Each one has a fix and a test that fails without it.
  2. Rounds 5-6 flagged edge cases in the fetch/refresh coordination. These problems also exist on an idle main, or they need sub-minute timing. Before this PR, metadata churn hid them by accident. They are deferred to 🤖 perf: re-read git status after a passive fetch settles #5572 or rejected with reasons in the threads. All threads are resolved.
  3. Findings no longer shrink and keep landing in one area (passive fetch completion policy). Per the repo's early-stop rule, I am not adding more mechanism here.

Current state: all threads are resolved. Required is red only because of the Codex Comments gate on round 6, and every build/test check passes. The core change (0 git/gh spawns under unrelated churn, down from 619/min) is unchanged since round 1.

Options for the reviewer:

@ThomasK33

Copy link
Copy Markdown
Member Author

Readiness gates on f58209eb5a (head frozen, still NOT READY)

Gate State
Required CI Pass after rerunning the stale Codex Comments job (merge state CLEAN)
Unresolved threads 0
Clean Codex verdict Not met. Round 6 of 6 had findings, and no 👍 or approval exists.
UAT on the exact head Not met. The round-2 isolation stop has not been cleared, so this head has no UAT.
Test audit (tests added in rounds 1-4) Pass: no correctness-blocking gap, 98 pass, mutation-checked
Independent readiness check "Blocked" by the two unmet gates. No code blocker found.

Test-audit suggestions, not applied because they would move the head and need a 7th Codex round:

  1. Add a PRStatusStore test that a change mark is consumed after one probe. Removing that delete brings back TTL-bypassing gh probes, and no test catches it today.
  2. Add a GitStatusStore test for a change that lands during a forced fetch, or make the existing in-flight test hold a forced fetch.
  3. Merge "fetches a repo added to a multi-project workspace" into the secondary-fetch ordering test.
  4. Give the PR "moved while nothing displayed it" test a real negative wait before its zero-calls check.
  5. Move the misplaced fetchWorkspace JSDoc that now sits above hasPendingFetch.

Decisions needed from a human: (a) clear the UAT isolation stop, so a short UAT round can run on this head, and (b) grant one more Codex round or waive the clean-verdict gate. If either moves the head, apply items 1-5 in the same push.

…lacement

From the independent test audit: pin that the PR store consumes a change
mark after one probe and that a change during a forced fetch is fetched
again inside the backoff; fold the multi-project added-repo test into the
secondary-fetch ordering test; give the undisplayed-move PR test a real
negative wait; move the fetchWorkspace JSDoc back above its method.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 6563ce27cb

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6563ce27cb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/stores/PRStatusStore.ts Outdated
refreshAll consumed the mark before the PR and stack probes ran, so a
transient executeBash failure left the previous checkout's PR/stack on
screen until the next focus (no unrelated metadata event retries anymore).
Keep the mark until both probes answer; on failure schedule a debounced
retry, at most 3 attempts in total. A newer change replaces the mark, so a
change during a probe still gets its own refresh.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 1bab0bc3b7

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1bab0bc3b7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/stores/PRStatusStore.ts
@ThomasK33

Copy link
Copy Markdown
Member Author

Readiness record: merging at 1bab0bc3b7 under the maintainer's explicit round-8 rule ("one more round for the round-7 fix; any round-8 finding is deferred to #5572 and the PR is accepted; no round 9").

  • Review: 8 Codex rounds. Round 8 raised 1 P2 and gave no clean approval. That finding (a gh error looks like "no PR", so after a rename during a gh outage the PR link disappears until the next focus) is deferred to 🤖 perf: re-read git status after a passive fetch settles #5572 with an owner and a follow-up trigger. This PR changes that recovery behavior, because it removes the incidental retry from metadata churn. The security review of this head is clean.
  • Round-7 fix: PRStatusStore keeps the checkout-change mark until both probes succeed, with a retry after 5 s and at most 3 attempts. The tests were red on the old code and are green now. Mutation checks pass.
  • Required passes on this head, with 0 open threads. make static-check passes, and 134 tests pass with 0 failures.
  • Remote UAT round 4 passed on this exact head: recovery after transient probe failures in about 5–11 s without a focus change, exactly 3 attempts on a persistent failure, and 0 git or gh processes from 600 unrelated metadata events in 60 s.

Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high

@ThomasK33
ThomasK33 added this pull request to the merge queue Oct 4, 2026
Merged via the queue into main with commit 8209946 Oct 4, 2026
58 of 61 checks passed
@ThomasK33
ThomasK33 deleted the perf/git-status-churn branch October 4, 2026 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant