feat: automate Codebase Memory workspace lifecycle - #9
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 62423bd3e7
ℹ️ 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".
| CancellationToken cancellationToken = default) | ||
| { | ||
| var info = _workspaces.Open(path); | ||
| var memory = await _codebaseMemory.EnsureWorkspaceAsync(info.RootPath, cancellationToken); |
There was a problem hiding this comment.
Isolate workspace opening from optional lifecycle failures
If the sidecar disconnects after GetStatusAsync successfully pings it, or any lifecycle tool call fails, this unguarded await throws and open_workspace returns no workspace ID even though _workspaces.Open already registered one. This makes the optional sidecar break the primary workspace flow and contradicts the documented unavailable fallback; non-cancellation lifecycle failures should instead be converted to an unavailable memory state.
Useful? React with 👍 / 👎.
| { | ||
| using var outer = JsonDocument.Parse(serialized); | ||
| var root = outer.RootElement; | ||
| if (root.TryGetProperty("content", out var content) && content.ValueKind == JsonValueKind.Array) |
There was a problem hiding this comment.
Reject MCP error results before unwrapping their content
When an upstream tool returns a valid MCP result with isError: true, this branch ignores that flag and treats its first text block as successful payload. Plain-text errors consequently cause JsonDocument.Parse to throw, while JSON-formatted errors can make a failed index_repository call be reported as indexed or a failed project listing trigger indexing; inspect the outer error flag before extracting content.
Useful? React with 👍 / 👎.
| var projectsRaw = await _client.CallToolAsync("list_projects", JsonSerializer.SerializeToElement(new { include_details = true }), cancellationToken); | ||
| var projects = ExtractPayload(projectsRaw); | ||
| var project = FindProject(projects, workspacePath); | ||
| if (project is null) return await IndexAsync(workspacePath, cancellationToken); |
There was a problem hiding this comment.
Serialize first-time indexing per workspace
When two open_workspace calls target the same previously unindexed path concurrently, both can finish list_projects before either indexing call completes, observe project is null, and invoke index_repository. Because the lifecycle is a singleton but has no per-workspace synchronization, this violates the documented once-per-workspace behavior and can launch duplicate expensive writes against the same graph; gate and recheck initialization by normalized workspace path.
Useful? React with 👍 / 👎.
Automatically coordinate Codebase Memory when LocalCodingMcp opens a workspace: reuse healthy indexes, index missing workspaces, report stale indexes without silently rebuilding, and provide an explicit refresh path. TDD in progress.