Skip to content

feat(web): auto-reconcile external agent sessions on project open - #10386

Open
lewismarshall wants to merge 3 commits into
pingdotgg:mainfrom
lewismarshall:cursor/auto-reconcile-agent-sessions-07d1
Open

feat(web): auto-reconcile external agent sessions on project open#10386
lewismarshall wants to merge 3 commits into
pingdotgg:mainfrom
lewismarshall:cursor/auto-reconcile-agent-sessions-07d1

Conversation

@lewismarshall

Copy link
Copy Markdown

What Changed

Added always-on automatic reconciliation of external agent sessions (Claude Code, Codex) when projects become available on a connected environment.

A new useAgentSessionAutoReconcile hook is mounted in the chat layout route. When environment shells bootstrap, it calls the existing idempotent agentSessions.import RPC for every known project, surfacing agent work already on disk in the thread list — without requiring a manual "Import agent sessions…" action.

Related Ideas discussions:

Why

When connecting to a remote environment via T3 Connect, agent sessions already on disk (e.g. Claude CLI history under ~/.claude) do not appear in the project thread list unless the user manually triggers an import. The existing AgentSessionScanner + AgentSessionImporter infrastructure (#5362) handles the heavy lifting, but is only wired into the first-run Welcome Wizard. Post-onboarding, there is no continuous visibility path.

This PR adds the minimal client-side trigger to close that gap. It reuses the existing server-side import RPC, which is fully idempotent (thread IDs are prefixed with import:, and per-source file-identity watermarks prevent re-reading unchanged transcripts).

What shipped

  • useAgentSessionAutoReconcile hook: watches the project list, triggers agentSessions.import once per project per mount cycle
  • selectUnreconciledProjects pure function: extracted for testability
  • Hook mounted in ChatRouteLayout (_chat.tsx)
  • Unit tests for the selection logic

Out of scope

  • Connect-cloud / account-wide session inbox
  • Live attach to running claude --remote-control
  • Cross-environment merged thread list
  • Settings toggle (import is already idempotent and silent)

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • No UI chrome — invisible background reconciliation

Maintainer manual QA checklist

  1. Open existing project whose workspaceRoot matches agent session cwd on disk
  2. Without using the Import UI, external sessions appear (or appear shortly after open) with history
  3. Re-open / re-reconcile does not duplicate import: threads
  4. Opening a thread does not auto-start a provider turn
  5. Mismatched expectedWorkspaceRoot fails clearly / skips safely
  6. No claim of live remote-control attach — transcript history only

Test commands (run in repo)

npx vp test run apps/web/src/hooks/useAgentSessionAutoReconcile.test.ts
npx vp test run apps/server/src/project/AgentSessionImporter.test.ts
npx vp test run apps/server/src/project/AgentSessionScanner.test.ts
npx vp run --filter web typecheck

Refs: #6994, #6680

When environment shells bootstrap, automatically import external Claude
Code and Codex sessions for every known project. This surfaces agent
work already on disk in the thread list without requiring a manual
"Import agent sessions…" action.

The new useAgentSessionAutoReconcile hook reuses the existing idempotent
agentSessions.import RPC. Each project is reconciled once per mount
cycle; failures are silently ignored since a missing agent home is not
actionable for the user.

Refs: pingdotgg#6994, pingdotgg#6680

Co-authored-by: Lewis Marshall <lewismarshall@users.noreply.github.com>
@github-actions github-actions Bot added the size:M 30-99 changed lines (additions + deletions). label Sep 6, 2026
@macroscopeapp

macroscopeapp Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR adds an always-on workflow that scans and imports external agent-session history for every known project when the chat experience starts, replacing a previously manual action. The new asynchronous production logic changes default runtime behavior and can create or update imported threads across projects.

Not approved because:

  • Monthly spending limit reached (workspace setting). Approvability relies on correctness review in order to determine eligibility

Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more.

@github-actions github-actions Bot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Sep 6, 2026
The original hook swallowed all import failures silently (.catch(() => {})),
making E2E debugging impossible when the server doesn't support the
agentSessions.import RPC (e.g. t3@0.0.38 predates PR pingdotgg#5362).

Changes:
- Add classifyImportFailure() that distinguishes four failure kinds:
  unsupported-server (RpcClientError), interrupted, expected domain
  errors, and unexpected defects.
- Log unsupported-server with a one-time console.warn naming the
  required server version and PR pingdotgg#5362. Skip further import attempts
  for that environment.
- Log expected errors (project not found, workspace mismatch, scan
  error, auth) with console.warn including project context.
- Log unexpected errors with console.error for debugging.
- Log successful imports with console.info when importedCount > 0.
- Add 10 new unit tests for classifyImportFailure covering all
  error classifications.

Co-authored-by: Lewis Marshall <lewismarshall@users.noreply.github.com>
@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Sep 6, 2026
selectUnreconciledProjects no longer eagerly adds keys to the reconciled
set. The hook marks a project reconciled only after:

- A successful import (importedCount + skippedCount returned).
- A definitive domain error (project not found, workspace mismatch,
  scan error, auth error) — these won't resolve without user action.

Transient failures (unsupported-server, unexpected defect, interrupted)
leave the project eligible for retry on the next render cycle. This
fixes the scenario where imports fail against an old server (pre-pingdotgg#5362)
and the project is permanently marked done, preventing retry after a
server upgrade without a full client remount.

Also: console.info now logs for every successful import (even when
importedCount is 0) with projectId, workspaceRoot, and skippedCount
for E2E observability.

Co-authored-by: Lewis Marshall <lewismarshall@users.noreply.github.com>
@cursor

cursor Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Bugbot is paused — on-demand spend limit reached

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants