Release v0.2.5821 — merge to main#510
Merged
Merged
Conversation
- npm/: codedeebee npm package (codedb's npx-friendly sibling)
- postinstall downloads matching native binary from GH release
and verifies against checksums.sha256
- thin spawnSync launcher preserves cwd/stdio/args/env
- published at codedeebee@0.2.5820 (closes #501)
- README.md:
- new "Or via npm/npx" install section
- updated "16 MCP tools" → "21 MCP tools" everywhere
- rewrote tools table: dropped codedb_bundle (no longer registered),
added codedb_callers / codedb_context / codedb_find / codedb_glob
/ codedb_ls / codedb_query / disambiguated codedb_find vs codedb_symbol
- added `codedb read <path>` to CLI table
- removed v0.2.579 hotfix section (long obsolete)
- install/install.sh merge_hook: when a competing legacy-tools hook
(block-legacy-tools.sh / muonry / zigrep / zigread) is already
registered for the same event/matcher, insert codedb's entry at
index 0 instead of appending. Reshuffles existing installs too.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#503: codedb mcp <path> hung on loading_snapshot because isCommand("mcp") matched at main.zig:150, parser set root=".", dropped /path, and entered deferred mode waiting for an MCP roots/list that a shell user never sends. #502: codedb mcp --help started the MCP server instead of printing help — same isCommand branch silently consumed --help as a command-arg. Both are fixed by factoring positional parsing into pub fn parsePositional() with two new special cases when args[1]=="mcp": - args[2] in {--help,-h,help} → cmd="--help" - args[2] looks like a path (not -flag) → root=args[2], root_is_explicit=true #507: after a snapshot rebuild, search returned 0 results for substrings demonstrably present in files that `tree` and `read` both surfaced. Root cause: Explorer.commitParsedFileOwnedOutline with full_index=false (snapshot.zig outline-only fallback + watcher.zig incremental indexFileOutline + WASM fast-path) registered files in `outlines` and `contents` but NOT in trigram_index, word_index, OR skip_trigram_files. Search then missed them at every tier: • tier 1 (trigram candidates) — file not in trigram_index • tier 3 (skip_trigram_files scan) — file not in this set • tier 5 (full outline scan) — short-circuited by trigram_ruled_out Fix: in the !full_index branch, also do skip_trigram_files.put(), so tier 3 substring-scans these files via searchInContent. Tests in test_mcp.zig (all fail on parent commit): issue-503: parsePositional treats `codedb mcp <path>` as path-as-root issue-503: `codedb <path> mcp` still works (original order) issue-503: `codedb mcp` alone keeps cwd-as-root deferred behavior issue-502: `codedb mcp --help` rewrites to --help, does not start server issue-502: `codedb mcp -h` rewrites to --help parsePositional: existing commands still parse correctly (regression) issue-507: indexFileOutlineOnly files remain searchable via tier 3 Full suite: 514/514 across all 7 test binaries. Closes #502 (partial — reject-unknown-flags, git-root detection, scan-stuck recovery still open), closes #503, closes #507. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Before, `codedb mcp --snapshot` silently swallowed the unknown flag
and started the MCP server with surprising state. mainImpl now
whitelists post-`mcp` flags via isValidMcpFlag and exits 1 with a
listed-valid-flags error message on the first unrecognised flag.
Edge cases:
• `--help`/`-h`/`help` anywhere after `mcp` short-circuits to
printUsage + exit 0 (parsePositional only catches them when
they sit immediately after `mcp`, so combos like
`mcp --no-telemetry --help` need their own bypass).
• `--config-file=<path>` is stripped before positional parsing
and never reaches this whitelist.
• `--no-telemetry` stays accepted; existing behaviour preserved.
Test in test_mcp.zig: issue-502: isValidMcpFlag whitelist rejects
unknown flags (fails on parent commit). Full test-mcp: 88/88 pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When `codedb mcp` is launched from a subdirectory of a git repo
(typical pattern for editor MCP clients spawning from the buffer's
directory), walk up from cwd to the nearest `.git` and use that as
the indexed root. Without this, opencode/Zed/etc were silently
indexing only the subdir the user happened to be in.
• Pin order: CODEDB_ROOT env var > positional `<path>` arg >
findGitRoot > cwd-deferred mode.
• Only triggers in deferred mode (root==".", !root_is_explicit)
— explicit paths and the `${workspaceFolder}` shim are left
untouched.
• `.git` may be a dir (normal repo) or a file (git worktree);
statFile covers both.
• Walks until the first `/<dir>` segment, then bails — does not
treat `/` itself as a project root.
Factored as findGitRoot(io, buf) + findGitRootFrom(io, buf, len)
so tests can hand in synthetic absolute paths without chdir'ing
the process.
Tests in test_mcp.zig: walks-up case + null case (both fail on
parent commit; both pass after).
Full test-mcp: 90/90 pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
watcherDeferredLoop polled scan_done indefinitely. After the 3s
fallback fired, triggerDeferredScanWithFallback could still return
false (e.g. fallback_cwd failed root_policy.isIndexableRoot — `/`,
`/tmp`, or any other denied path). That left `triggered=false`,
`scan_done=false`, and the loop spinning forever — visible to the
user as scan=loading_snapshot with files=0 forever.
Now after a give_up_after_ms (13s total) without a successful
trigger, the loop:
• logs a warn-level message pointing the user at CODEDB_ROOT
or the `codedb <path> mcp` invocation,
• flips scan_done so MCP tool calls stop replying with the
"still loading" hint and return empty results cleanly,
• skips the post-loop incrementalLoop call (resolved_root is
empty in the give-up path).
The 3s pre-fallback path is unchanged for the happy case where
fallback_cwd is indexable — only the previously-unreachable hang
is fixed.
Full test-mcp: 90/90.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The remote tool previously surfaced raw HTTP status + Cloudflare
body to the caller — "api.wiki.codes HTTP 530 for X/Y — error
code: 1033" — with no remediation guidance. Agents treated this
as an opaque failure and either retried in tight loops or bailed.
appendRemoteErrorHint distinguishes the common upstream cases:
530 + "error code: 1033/1034" / "Argo Tunnel error"
→ "origin unreachable, service temporarily down, retry in a
few minutes or fall back to local `codedb_index`"
530 (plain)
→ "retry in a few minutes; if it persists, repo may not be
indexed"
404
→ "repo or path not indexed; verify slug or clone + index
locally"
429
→ "rate limited; wait and retry, or batch fewer requests"
500/502/503
→ "upstream server error, retry"
504
→ "gateway timeout; wiki may still be indexing this repo"
The hint is appended after the existing status line so consumers
that parsed the old format still work; the new line is purely
additive and human-/agent-readable.
Note: the underlying server outage (api.wiki.codes returning 530
for several public repos as of 2026-05-28) is server-side and
not fixable client-side. This change makes the failure mode
actionable but does not restore the service.
Tests in test_mcp.zig — covers Cloudflare 530 vs plain 530, 404,
429, 200 (no-op). Full test-mcp: 91/91.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
codedb previously hardcoded a "2025-06-18" protocolVersion in the initialize reply, regardless of what the client sent. Older Zed builds and certain opencode versions reject a server reply whose protocolVersion they don't recognize — manifesting as a startup timeout (#506) or as "No MCP tools" (#505) when the client gives up on the handshake. handleInitialize now extracts params.protocolVersion and feeds it through negotiateProtocolVersion: • Echo the client's version if it's one we've verified against (2024-11-05, 2025-03-26, 2025-06-18). • If the client sent something newer than our latest known version, reply with our latest (forward-compatibility hint to the client that we're as new as we can be). • If the client sent something ancient (lex-orders below our oldest known), reply with our oldest known so older clients still get a shape they recognise; client decides if it can proceed. • Empty/missing → fall back to the default ("2025-06-18"). Tests in test_mcp.zig cover all four branches. E2E: client 2024-11-05 → server 2024-11-05 ✓ client 2025-03-26 → server 2025-03-26 ✓ client 2025-06-18 → server 2025-06-18 ✓ Full test-mcp: 95/95. Closes #505 (opencode), closes #506 (Zed). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A macOS Intel x64 user reported a segfault on plain `codedb` with
no args. We can't reproduce on arm64, so the fix is to reduce
blast radius: handle the three most common no-real-work
invocations (no args, --version/-v/version) directly in `pub fn
main` using raw c_write to stdout/stderr, before any of the
heavier startup machinery runs (worker-thread spawn, io-Threaded
init, c_allocator + global state setup).
If the underlying bug lives somewhere in that machinery, this
short-circuit means users with broken environments can still:
• run `codedb` and get a usage message
• run `codedb --version` and confirm install
• run `codedb --help` (still goes through the full path
because help formatting needs styling; intentional)
Worst case for the fast paths is uncoloured output — kept minimal
on purpose. The fast path is a no-op for every other invocation
(returns false → continues to the existing thread trampoline).
E2E:
codedb → usage to stderr, exit 1 ✓
codedb --version → "codedb 0.2.5821" to stdout, exit 0 ✓
codedb tree, mcp, … → unchanged (full path)
Full test-mcp: 95/95.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Verified via Rosetta on Apple Silicon: the previous "segfault on
bare codedb" was conflated with a separate, universal bug — Out's
flush() runs from a deferred cleanup, but std.process.exit()
skips deferred cleanup. Every error / usage path that did
out.p("...message...", .{...});
std.process.exit(1);
was silently dropping the message and just returning exit 1. The
user's Intel Mac may also have a real segfault deeper in startup,
but the *user-visible* symptom ("nothing prints, just dies") is
this bug and it reproduces on arm64 too.
Add Out.exitWithFlush(code) noreturn that flushes then exits, and
convert the three early-exit sites that fire BEFORE the heavier
init (the only paths a freshly-installed binary will hit on
first invocation):
• parsePositional usage_exit — `codedb foo` now prints usage
• cannot-resolve-root — bad path now shows the error
• refusing-to-index — denied root now shows the error
The fast-path commit (22959b8) still catches bare codedb /
--version on the main thread before any of this runs, so even if
Rosetta or the user's environment has a problem in the worker
thread itself, those two commands keep working. With both fixes
in place, the user from #504 should now at least see a usage
message instead of a silent failure or segfault.
E2E (arm64 + x86_64 under Rosetta):
codedb → fast-path: usage to stderr, exit 1 ✓
codedb foo → mainImpl: usage to stdout, exit 1 ✓
codedb /bogus mcp → mainImpl: "cannot resolve root", exit 1 ✓
codedb --version → fast-path: "codedb 0.2.5820", exit 0 ✓
Full test suite: 635/635.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
x86_64-macos at startup Reproduced via Rosetta on Apple Silicon (`arch -x86_64`) with the ad-hoc-signed release-build binary. SIGSEGV (exit 139) before any user code runs. Bisected against a minimal program: pub fn main(init) void → works pub fn main(init) !void → SIGSEGV under adhoc + Rosetta The crash is in the Zig 0.16 runtime wrapper around an error-union main, not in our code. The wrapper expands argv, allocates the error return slot, and calls user main — something in that sequence trips a startup-path bug specific to x86_64-macos when the binary is signed. Same crash behaviour also fires for binaries that spawn a thread before writing anything, but the underlying trigger is the same wrapper. Fix: make `pub fn main(init) void` infallible. Move the original fallible body (thread spawn + join + error propagation) into `mainTrampoline() !void` which the new main calls via catch. On the catch arm we write a minimal "fatal startup error: <name>" message to stderr via std.c.write so the user sees *something* even if the trampoline itself crashes — though now it shouldn't, because the runtime wrapper for `!void` is the actual broken thing. Verified end-to-end with ad-hoc-signed x86_64-macos binary under Rosetta: codedb → usage to stderr, exit 1 ✓ codedb --version → "codedb 0.2.5820", exit 0 ✓ codedb foo → usage from mainImpl, exit 1 ✓ codedb tree → loaded snapshot, 284 files, real output ✓ codedb mcp → starts, "stdin closed, exiting" ✓ All previously: SIGSEGV / silent. arm64 native unchanged. Full test suite: 635/635. Note: the user's reported segfault was on a native macOS Intel Mac with a Dev-cert-signed binary, not Rosetta with ad-hoc. The trigger (`!void` runtime wrapper) is the same regardless of sign type, so this should resolve the user's case too — but they need to reinstall + retest to confirm. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Benchmark Regression ReportThresholds: 10.00% and 50,000 ns absolute delta
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Promote release/0.2.5821 to main. Includes the v0.2.5821 release bundle (#509). See release notes at https://github.com/justrach/codedb/releases/tag/v0.2.5821 and PR #509 for the 7-issue fix bundle.