CodeDB Pro v0.2.12: fail-closed edits and a faster MCP response path

Rach Pradhan · 8 min read

CodeDB Pro 0.2.12 is built around one rule: if an edit target is uncertain, stop before mutation. The release resolves symbol targets from the bytes on disk, rejects conflicting coordinates, and makes malformed ranges fail during target resolution instead of somewhere inside the write path.

It also removes an expensive piece of plumbing from MCP edits. Captured edit and patch responses now go directly into their destination buffer instead of crossing a kernel pipe and a newly spawned drainer thread on every call.

Fail closed

Ambiguous or conflicting targets do not write.

Fall back

Known-incomplete indexes do not filter results.

Skip the pipe

MCP edit responses use a direct buffer path.

Edits now fail closed

A cached symbol range is useful for navigation. It is not authoritative permission to mutate those lines later. If another process changed the file, cached coordinates can point at unrelated code; if two symbols share a name, trusting the first cached hit hides the ambiguity. Symbol edits now resolve against current file contents immediately before the edit.

Safe intent

{
  "file": "src/server.zig",
  "symbol": "handleRequest",
  "content": "..."
}

If handleRequest is missing or duplicated, the request fails. It does not silently select cached lines.

The daemon protocol now accepts only four operation names: replace, insert, delete, and str_replace. A typo such as replcae returns an error without modifying the file.

Conflicts rejected

Range + pattern, range + symbol, pattern + symbol, and whole_file + any other authoritative positioner.

Coordinates validated early

Line zero, reversed or malformed ranges, and match_index without a pattern.

The MCP schema now exposes the controls that enforce those boundaries: match_index, whole_file, and confirm_scope_shrink. Clients no longer have to discover them from an error after the fact.

When the index cannot prove coverage, search walks

An index is only a safe exhaustive filter when it represents every searchable file for the request. v0.2.12 indexes the complete contents of eligible files instead of only a prefix and tracks conditions that make coverage incomplete. When one of those conditions is detected, CodeDB Pro uses the ordinary filesystem walker instead of trusting the index to exclude files.

ConditionBehavior
Walk timed out or hit the file capBypass the index and use the ordinary request-time walker
A searchable file exceeds the index size boundDo not use the index as exhaustive
Regex searchBypass the index and use ordinary regex matching
no_ignore:trueBypass the ignore-aware index

Indexed candidates are still verified by the complete matcher. The fallback rules protect known coverage gaps; they are not a claim that an index can provide a transactional snapshot of a file being concurrently rewritten by another process.

A search limit is not a read limit

The default 500-line cap belongs to search-result delivery. Full-file reads do not inherit it, and an explicit limit: 0 means unlimited search output. Regression tests now cover pipe and MCP reads beyond 500 lines and explicit unlimited searches beyond the default cap.

Next retrieval problem

Some MCP hosts still clip an otherwise complete large tool response at their own display ceiling. That is a delivery problem outside the matcher. Hash-guarded pagination is the planned follow-up: bounded pages with a file-version token so pages from different versions are not combined. It is not part of v0.2.12.

Removing a pipe and a thread from every captured edit

Before this release, MCP and batch edit responses were captured through an OS pipe. Each call created two file handles, spawned a drainer thread, copied response bytes into the pipe, copied them into a temporary list, joined the thread, and copied once more into the caller's buffer. That machinery prevented large-output pipe deadlocks, but edit responses are already bounded metadata plus a compact diff.

Before

handler → pipe write

Capture

drainer thread → temporary buffer

Return

join → destination buffer

v0.2.12

handler → destination buffer

Same wire shape

metadata + escaped compact diff

The normal stdout handler still exists. Only the capture paths that already own anArrayList(u8) bypass the pipe, which keeps the change local to MCP and batch response transport.

The response-path benchmark

The comparison used one persistent MCP process, a ReleaseFast build, a warmed request path, and the same single-line dry_run edit request. Dry-run deliberately excludes filesystem commit, index refresh, notification, and post-edit lint time. This isolates the response path; it is not an end-to-end agent or real-write benchmark.

Throughput

3,990 ops/s27,879 ops/s

6.99× in the local persistent-process ReleaseFast, warmed dry-run MCP edit benchmark.

Median latency

225.1 µs34.7 µs

84.6% lower median in that same warmed dry-run MCP edit benchmark.

Throughput — higher is better

Pipe + drainer3,990 ops/s
Direct buffer27,879 ops/s

Median latency — lower is better

Pipe + drainer225.1 µs
Direct buffer34.7 µs

Seven representative batch edit and patch responses, spanning successful dry-runs and validation errors, were compared byte-for-byte with the old capture path. All seven matched. The regression suite separately covers escaped diff content, batch routing, edit versus patch validation, and OOM paths.

A failed response is not always a failed mutation

Direct capture created one subtle safety requirement: an allocation failure must never leave a partial response beginning with {"ok":true. v0.2.12 reserves room for a deterministic failure response before entering the mutation path, tracks every fallible buffer append, and clears the complete capture buffer if one fails.

{
  "ok": false,
  "error": "oom during capture after mutation; file may have changed",
  "outcome_unknown": true
}

That marker does not claim the write committed. It tells the caller that response construction failed after the mutation path reported success, so blindly retrying could duplicate an insert or apply an edit to a different file state. Pre-mutation and dry-run capture failures remain ordinary errors.

Upgrade to v0.2.12

codedb-pro update
codedb-pro --version
codedb-pro --changelog

The release is available for Apple Silicon, Intel macOS, and Linux x86_64. New here? Get CodeDB Pro or read the complete changelog.