perf(outline): zero-copy renderOutline saves the deep clone
handleOutline used to:
1. getOutline → cloneOutline allocates new strings for path + every
symbol name + every symbol detail (deep copy under the read lock)
2. format the cloned outline into `out`
3. deinit the clone
For src/main.zig (~140 symbols) that's hundreds of allocations + frees
per call. New `Explorer.renderOutline` writes directly to the output
buffer under the read lock, skipping the clone entirely.
Bench, 3-run avg:
codedb_outline 66.4 µs → 29 µs (−56%)
Tradeoff: holds the read lock for the format duration. In practice
the watcher's incremental loop is the only competing reader and it
runs ~once per second, so contention is effectively zero.
getOutline remains for callers that need an owned FileOutline
(snapshot serialization, agent registry).
633/633 tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> J
justrach committed
2cd51629083e41294ad69b0f32095b0b52f41fe5
Parent: cd721c9