feat(search): flag-gated v4 query-serve path for entire search#1800
feat(search): flag-gated v4 query-serve path for entire search#1800alishakawaguchi wants to merge 1 commit into
entire search#1800Conversation
Route semantic `entire search` to the v4 query-serve path (entire-api cell gateway) behind the `semantic-search-v4` flag, defaulting to the v3 Cloudflare worker. With the flag off, behavior is byte-identical to today; the `--json` shape is unchanged in both modes. - Flag: `settings.IsSemanticSearchV4Enabled` — env `ENTIRE_SEMANTIC_SEARCH_V4` or the `semantic_search_v4` settings bool, mirroring the existing env+settings gate convention (no PostHog/product-settings flag system exists in the CLI). Default off. - Selection: v4 applies only to a search scoped to the current repo; broader searches (repo:*, --all-repos, a different repo) stay on v3 until the cross-repo v4 route lands (ENT-1054). Repo slug -> ULID via the repo's mirrors; the request dials the repo's owning cell with a jurisdictional identity token, reusing NewAuthenticatedEntireAPICellClient. v4 resolution failures error clearly rather than silently falling back to v3. - search.Search dispatches v3/v4 on Config.useV4(); the v4 response decodes into the same Response struct (extra fields dropped), and the TUI inherits the branch unchanged via its shared Config (pagination + re-search included). Verified end-to-end against production (entireio/cli): flag-on results are byte-identical to a direct cell probe and differ from the v3 set; scoping and --json shape are correct. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 01KXRRN441G0PXXSBD5HVPX0ST
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit f0145cf. Configure here.
| fullName := owner + "/" + repoName | ||
| repoID, _ := currentRepoRef(ctx) | ||
| if repoID == "" { | ||
| return nil, "", fmt.Errorf("semantic-search-v4: could not resolve an Entire repository ID for %s (is it mirrored to Entire?); unset the semantic-search-v4 flag to use v3", fullName) |
There was a problem hiding this comment.
Misleading v4 resolve error
Medium Severity
resolveSemanticSearchV4 treats any empty result from currentRepoRef as “not mirrored,” but that helper is best-effort and swallows timeouts, auth, and control-plane failures as "". Opt-in searches then hard-fail with the wrong cause and remediation, even when the repo is mirrored and v3 auth already succeeded.
Reviewed by Cursor Bugbot for commit f0145cf. Configure here.
| - Flag ON + `--repo entireio/cli` (explicit current): v4 (total 15). | ||
| - `mise run fmt && mise run lint`: 0 issues. Unit tests pass for all touched | ||
| packages (the lone `tokenstore` failure is a stderr-redirect artifact of the | ||
| parallel runner, unrelated — passes in isolation, package untouched). |
There was a problem hiding this comment.
Working notes committed
Low Severity
FINDINGS.md at the repo root is implementation scratch notes (including ephemeral CI noise about an unrelated tokenstore flake). It is not referenced by the PR scope or product docs and looks like accidental Claude Code output rather than intentional project documentation.
Reviewed by Cursor Bugbot for commit f0145cf. Configure here.
There was a problem hiding this comment.
Pull request overview
This PR adds an opt-in (default-off) v4 backend for semantic entire search, routing single-repo searches through the entire-api cell gateway (v4 query-serve) while preserving the existing v3 Cloudflare worker behavior and --json response shape when the gate is disabled.
Changes:
- Added
settings.IsSemanticSearchV4Enabled(env + settings file) to gate v4 routing. - Updated semantic search execution to dispatch v3 vs v4 per-request based on effective repo scope, with shared request-param and response parsing helpers.
- Added tests covering settings gating, v3↔v4 routing behavior, and v4 request/response semantics; documented rollout behavior in
FINDINGS.md.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| FINDINGS.md | Documents the v4 rollout/gating behavior and how v3/v4 routing works. |
| cmd/entire/cli/settings/settings.go | Adds semantic_search_v4 settings field + IsSemanticSearchV4Enabled helper. |
| cmd/entire/cli/settings/settings_semantic_search_v4_test.go | Tests env/settings gating behavior for the v4 flag. |
| cmd/entire/cli/search/search.go | Implements v3/v4 dispatch, v4 query-serve call path, and shared param/response helpers. |
| cmd/entire/cli/search/search_v4_test.go | Adds tests for v4 URL/params, response decoding, and routing fallback rules. |
| cmd/entire/cli/search_cmd.go | Wires the gate into the entire search command and resolves v4 cell client + repo ULID for eligible scopes. |
| cmd/entire/cli/search_cmd_test.go | Tests the “scoped to current repo” predicate used to enable v4 routing. |
| fullName := owner + "/" + repoName | ||
| repoID, _ := currentRepoRef(ctx) | ||
| if repoID == "" { | ||
| return nil, "", fmt.Errorf("semantic-search-v4: could not resolve an Entire repository ID for %s (is it mirrored to Entire?); unset the semantic-search-v4 flag to use v3", fullName) |
| fullName := owner + "/" + repoName | ||
| repoID, _ := currentRepoRef(ctx) | ||
| if repoID == "" { |


https://entire.io/gh/entireio/cli/trails/897
What
Routes semantic
entire searchto the v4 query-serve path (entire-api cell gateway) behind thesemantic-search-v4flag, defaulting to the existing v3 Cloudflare worker. Unblocks CF-worker removal (ENT-935/936).--jsonoutput shape.Closes ENT-1055.
Flag
No PostHog / product-settings flag system exists in the CLI, so this matches the codebase's existing local-gate convention (mirrors
IsImageExternalizationEnabled): envENTIRE_SEMANTIC_SEARCH_V4=1|trueor thesemantic_search_v4settings bool. Default off. There is no server-side/percentage rollout knob — a real cutover to "everyone" is a separate step (flip the default, or add flag delivery).How it works
repo:*,--all-repos, or a different explicit repo stay on v3 until the cross-repo route lands (ENT-1054). The scope check runs per request, so the interactive browser's pagination stays on v4 and a broadened re-search transparently drops back to v3.owner/name→ ULID via the repo's mirrors; the request dials the repo's owning cell with a jurisdictional identity token (the v4 route rejects the v3 data-API bearer), reusingNewAuthenticatedEntireAPICellClient— the same repo-scoped cell auth theexpertscommands use. Going direct-to-cell is equivalent to the BFF path (the BFF just forwards the bearer) and reuses existing plumbing.search.Searchdispatches v3/v4 onConfig.useV4(); the v4 response decodes into the sameResponsestruct (extra fields ignored). The TUI inherits the branch through its sharedConfigwith zero TUI changes.Verification (production, logged in, repo
entireio/cli)Built from this branch and run against prod:
searchMetakeys..entire/settings.local.json(no env): same 15.--all-repos/repo:*/ different repo: stays v3.mise run fmt && mise run lintclean (0 issues); touched-package unit tests + full integration suite (436 tests) pass.Tests
search/search_v4_test.go— v4 URL/params (ULID not slug, notypes, identity token), response decoding, v3↔v4 routing,useV4()gating.settings/settings_semantic_search_v4_test.go— env + settings-file gate, JSON tag.search_cmd_test.go—TestSearchScopedToCurrentRepo.Not in scope
Cross-repo/unfiltered v4 (ENT-1054); multi-repo filter (ENT-1047) — kept compatible.
🤖 Generated with Claude Code
Note
Medium Risk
Changes semantic search routing and auth (cell gateway vs v3 worker) for opted-in users; mitigated by default-off flag, single-repo scope, per-request
useV4()guard, and broad tests.Overview
Adds an opt-in backend for semantic
entire searchthat talks to the v4 query-serve API on the entire-api cell gateway (repo ULID + jurisdictional identity token) instead of the v3 Cloudflare worker. Default stays v3 so flag-off behavior is unchanged;--jsonoutput shape is preserved.Gating follows existing CLI patterns:
ENTIRE_SEMANTIC_SEARCH_V4=1|trueorsemantic_search_v4in.entire/settings.json/.local.jsonviaIsSemanticSearchV4Enabled.Routing in
search_cmd: when the flag is on and scope is exactly the current repo (searchScopedToCurrentRepo),resolveSemanticSearchV4resolves the repo ULID and builds a cell client (NewAuthenticatedEntireAPICellClient). Broader scope (--all-repos,repo:*, other repos) stays on v3; v3 token/URL remain wired for those paths and TUI re-searches.search.Searchdispatches onConfig.useV4()— per-request check that effective repo scope still matchesV4RepoSlugso pagination/re-search cannot send the wrong ULID. v4 usessearchV4; v3 is the prior path refactored with sharedaddCommonSearchParams/parseSearchResponse. v4 failures surface as errors (no silent v3 fallback when opted in).Unit tests cover v4 URL/params, decoding, routing, settings gate, and scope predicate.
FINDINGS.mddocuments the rollout behavior.Reviewed by Cursor Bugbot for commit f0145cf. Configure here.