Skip to content

feat(search): flag-gated v4 query-serve path for entire search#1800

Open
alishakawaguchi wants to merge 1 commit into
mainfrom
ent-1055-cli-v4-path
Open

feat(search): flag-gated v4 query-serve path for entire search#1800
alishakawaguchi wants to merge 1 commit into
mainfrom
ent-1055-cli-v4-path

Conversation

@alishakawaguchi

@alishakawaguchi alishakawaguchi commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

https://entire.io/gh/entireio/cli/trails/897

What

Routes semantic entire search to the v4 query-serve path (entire-api cell gateway) behind the semantic-search-v4 flag, defaulting to the existing v3 Cloudflare worker. Unblocks CF-worker removal (ENT-935/936).

  • Flag off (default): byte-identical to today's v3 behavior.
  • Flag on + current-repo scope: results come from the v4 per-repo namespaces via the cell gateway, correctly authz-scoped, with the same --json output 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): env ENTIRE_SEMANTIC_SEARCH_V4=1|true or the semantic_search_v4 settings 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

  • v4 applies only to a search scoped to the current repo. 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.
  • Repo 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), reusing NewAuthenticatedEntireAPICellClient — the same repo-scoped cell auth the experts commands use. Going direct-to-cell is equivalent to the BFF path (the BFF just forwards the bearer) and reuses existing plumbing.
  • v4 resolution failures error clearly rather than silently falling back to v3 (the flag is opt-in; hiding v4 breakage would defeat the rollout).
  • search.Search dispatches v3/v4 on Config.useV4(); the v4 response decodes into the same Response struct (extra fields ignored). The TUI inherits the branch through its shared Config with zero TUI changes.

Verification (production, logged in, repo entireio/cli)

Built from this branch and run against prod:

  • Flag off: v3, 48 results, mixed types.
  • Flag on (env var): v4, 15 results — byte-identical to a direct cell probe that bypasses the CLI code, and different from the v3 set. Same top-level keys / result keys / searchMeta keys.
  • Flag on via .entire/settings.local.json (no env): same 15.
  • Flag on + --all-repos / repo:* / different repo: stays v3.

mise run fmt && mise run lint clean (0 issues); touched-package unit tests + full integration suite (436 tests) pass.

Tests

  • search/search_v4_test.go — v4 URL/params (ULID not slug, no types, 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.goTestSearchScopedToCurrentRepo.

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 search that 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; --json output shape is preserved.

Gating follows existing CLI patterns: ENTIRE_SEMANTIC_SEARCH_V4=1|true or semantic_search_v4 in .entire/settings.json / .local.json via IsSemanticSearchV4Enabled.

Routing in search_cmd: when the flag is on and scope is exactly the current repo (searchScopedToCurrentRepo), resolveSemanticSearchV4 resolves 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.Search dispatches on Config.useV4() — per-request check that effective repo scope still matches V4RepoSlug so pagination/re-search cannot send the wrong ULID. v4 uses searchV4; v3 is the prior path refactored with shared addCommonSearchParams / 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.md documents the rollout behavior.

Reviewed by Cursor Bugbot for commit f0145cf. Configure here.

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
@alishakawaguchi
alishakawaguchi requested a review from a team as a code owner July 17, 2026 20:20
Copilot AI review requested due to automatic review settings July 17, 2026 20:20

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ 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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f0145cf. Configure here.

Comment thread FINDINGS.md
- 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).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f0145cf. Configure here.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Comment on lines +404 to +406
fullName := owner + "/" + repoName
repoID, _ := currentRepoRef(ctx)
if repoID == "" {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants