fix(workspace): sync workspace catalog across v1/v2 and soft-delete - #1701
Conversation
- register the cwd in workspaces.json when a v1 (TUI/SDK) session is created, via a shared workspaceRegistryFile read/write/touch module - merge session_index.jsonl into the catalog once at v2 startup (awaited during kap-server boot), adding only paths absent from workspaces.json - make v2 workspace delete a soft delete through the v1-compatible deleted_workspace_ids field: the session-index merge never resurrects tombstoned ids, while an explicit createOrTouch clears the tombstone
🦋 Changeset detectedLatest commit: 73ad361 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 73ad361e91
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| await this.store.save({ | ||
| workspaces: [...cache.values()], | ||
| deletedIds: [...deletedIds], | ||
| }); |
There was a problem hiding this comment.
Merge disk state before saving the cached catalog
When the v2 server has already loaded the registry, a v1 process can now update the same workspaces.json via the new touchWorkspaceRegistry path, but this save writes only the stale in-memory cache. In the scenario where v2 loads the catalog, the v1 TUI creates or reopens another workspace, and then v2 handles any create/update/delete, this overwrite drops the v1-added workspace or tombstone and breaks the cross-engine sync this change is meant to provide. Re-read and merge the current file (or otherwise coordinate writes) before persisting.
Useful? React with 👍 / 👎.
| } from '../session/provider-manager'; | ||
| import { SessionAPIImpl } from '../session/rpc'; | ||
| import { normalizeWorkDir, SessionStore } from '../session/store/index'; | ||
| import { touchWorkspaceRegistry } from '../services/workspace/workspaceRegistryFile'; |
There was a problem hiding this comment.
Keep rpc from importing the services facade
packages/agent-core/src/services/AGENTS.md says the services subtree is an upper facade and that the runtime must not import back into services/; core-impl.ts is under src/rpc and now imports a helper from ../services/..., reversing that boundary. Move the shared workspace-file helper to a lower-level module that both rpc and the service facade can depend on, otherwise this path can pull facade dependencies into the runtime and reintroduce cycles as the service layer evolves.
Useful? React with 👍 / 👎.
Related Issue
No linked issue — the problem is explained below.
Problem
The workspace catalog (
<homeDir>/workspaces.json, shared by the v1 TUI engine and the agent-core-v2 server) drifts from where sessions actually live:session_index.jsonl; their directories never land inworkspaces.json, so the web UI can only show them as unmanaged "derived" workspaces.deleted_workspace_idsfield on write.)What changed
KimiCorenow registers the cwd inworkspaces.jsonwhen a session is created (best-effort, never fails session creation). The read/modify/write lives in a new sharedworkspaceRegistryFilemodule thatWorkspaceRegistryServicealso delegates to, so there is a single implementation of the file format.session_index.jsonlinto the catalog once per fresh load — adding only paths the file does not already know — and kap-server awaits one sync pass during boot, so the catalog is complete before the server accepts traffic.deletenow tombstones the id in the v1-compatibledeleted_workspace_idsfield instead of dropping it silently; the session-index merge never resurrects a tombstoned id, while an explicitcreateOrTouch(TUI session create, web "add workspace", v2 session create) clears the tombstone and brings the workspace back.User-visible effect: the web sidebar lists every workspace that has sessions (including TUI-only ones), and a removed workspace stays removed across server restarts until the user works in that directory again.
Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.