Skip to content

fix(sidebar): put the path row above recent activity and bound its scan - #561

Merged
Tryanks merged 2 commits into
mainfrom
fix/add-project-path-first
Oct 1, 2026
Merged

Tryanks merged 2 commits into
mainfrom
fix/add-project-path-first

Conversation

@Tryanks

@Tryanks Tryanks commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner

Behaviour

  • Path row first. The Add Project dialog now shows the path input and Browse… at the top, with the recent-activity list below it. Before this change the list sat above the path row and loaded asynchronously. When the scan finished, the input and Browse button moved down under the pointer, and a click meant for Browse could open a recent project instead. Now the list fills in below a row that stays put.
  • Per-provider counts in words. Each recent project lists its conversations per provider as localized text, e.g. Claude Code: 3 conversations · Codex CLI: 1 conversation (zh: Claude Code:3 条对话). Previously it showed Claude Code ×3.
  • The import is stated up front. A hint under the "Recently active" heading says that choosing a project there also imports the conversations listed under it. The accessible name of each row says the same.

No new abstractions; tool_counts keeps its owner and only switches to localized strings. New keys are in both locales/en.yml and locales/zh-CN.yml.

Checks run

  • cargo fmt --all --check
  • cargo clippy -p tcode-ui --all-targets --locked -- -D warnings
  • cargo nextest run -p tcode-ui --locked: 322 passed, including locale parity
  • Not done: a visual check in the running app. This environment has no Accessibility or Screen Recording permission, so I could not open the dialog and look at it in either theme or at narrow width. The full workspace and mobile/Web checks are left to CI.

Recent-activity scan bounds (second commit)

I reviewed the host-side scan that feeds this list (crates/services/src/import) and measured it on a real profile (341 Claude Code and 3,493 Codex transcripts, 9 GB):

  • Symlink loop could hang the scan indefinitely. collect_files followed directory symlinks, so a link back to an ancestor under ~/.codex/sessions made the walk branch without end. Measured: two links took 5.4 s, three links were still running after 60 s, and the dialog stayed on "Looking for recent activity…" the whole time. The walk now uses DirEntry::file_type and does not descend into symlinked directories; the same case takes 36 µs. The existing scanner test now has a loop link under its Codex fixture: without the fix that session is listed 17 times instead of once, and the test fails.
  • Exclusion cost grew with threads × projects. Every thread re-checked is_dir on its cwd and canonicalized every project root again. On 850 threads that added about 4 ms per project (25 projects: 185 ms, 55 projects: 295 ms). The checks now run once per distinct directory, with project roots canonicalized once: 92 ms whatever the project count. The result is unchanged (87 directories either way), and exclusion stays covered by scanner_groups_attributes_orders_and_excludes. Doing the checks per directory also means a cwd on a slow or unreachable mount blocks once, not once per thread.

Checked and left alone:

  • Claude transcripts are read only until the first line with a cwd. On real data the most read before that was 415 KB. A synthetic 400 MB file with no cwd line scans in about 110 ms.
  • Codex transcripts are read only up to their first line.
  • The scan runs on the host's blocking pool (Host::unblock). The path row and Browse work while it loads.

Still unbounded: a cwd on an unreachable network mount can block is_dir for as long as the OS lets it. There is no timeout. The dialog keeps showing the loading row, and typing a path or using Browse still works.

cargo clippy -p tcode-services --all-targets --locked -- -D warnings and cargo nextest run -p tcode-services --locked (78 passed) also run.

The recents list loads asynchronously above the path row, so the input and
Browse button moved down under the pointer once the scan finished and a
click meant for Browse landed on a recent project. The path row now comes
first and the list loads below it.

Each recent project lists its conversations per provider in words, and the
section states that choosing a project also imports those conversations.
The session walk followed directory symlinks, so a link back to an
ancestor in the Codex sessions tree branched without end: with three such
links the scan never finished and Add Project stayed on its loading row.
Symlinked directories are no longer walked.

Directory existence and project exclusion were checked per thread, with
every project root canonicalized again for every thread; the scan grew by
about 4 ms per project on 850 threads. They now run once per directory,
with project roots canonicalized once.
@Tryanks Tryanks changed the title fix(sidebar): put the path row above recent activity in Add Project fix(sidebar): put the path row above recent activity and bound its scan Oct 1, 2026
@Tryanks
Tryanks merged commit 7214a93 into main Oct 1, 2026
7 checks passed
@Tryanks
Tryanks deleted the fix/add-project-path-first branch October 1, 2026 16:06
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