cli: add code search with multi-region fan-out (ENT-993)#1616
Open
evisdren wants to merge 4 commits into
Open
Conversation
This was referenced Jul 2, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new cmd/entire/cli/codesearch package to provide a small, typed Go client for peregrine’s POST /search/api/search endpoint using the existing authenticated api.Client, including response-size capping and basic HTTP error parsing.
Changes:
- Introduces
codesearch.Search()plus request/response types for peregrine code search. - Implements an 8 MiB response read cap with explicit overflow detection.
- Adds unit tests covering success, API error responses, non-JSON error bodies, and oversized responses.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| cmd/entire/cli/codesearch/codesearch.go | New code search client wrapper around api.Client.Post, including response cap and error parsing. |
| cmd/entire/cli/codesearch/codesearch_test.go | Unit tests for the new client (success + error/edge cases). |
Comment on lines
+84
to
+86
| if apiErr.Message == "" && len(body) > 0 { | ||
| apiErr.Message = string(body) | ||
| } |
1e7a2b3 to
0ef9bc1
Compare
Add `entire search --code <query>` to search code content across all jurisdictions via the peregrine search service, gated behind ENTIRE_CODE_SEARCH=1. Architecture: - codesearch package: thin client for peregrine's search endpoint through the cell's entire-api gateway (GET /api/v1/search/api/search) - Multi-region fan-out: list repos from core → group by jurisdiction → search each cell in parallel with per-cell timeouts → merge results by score, deduplicate, cap to --limit - Per-cell repo ID scoping: each cell only receives ULIDs belonging to its jurisdiction, avoiding cross-jurisdiction leakage - Partial failure resilience: a down region warns but returns results from healthy cells; only all-cells-fail is an error Repo filter formats: - gh/owner/repo, et/proj/repo, bare owner/repo, or raw ULID - Defaults to current repo (derived from git origin), matching checkpoint-search behavior; use --all-repos or repo:* for all repos - Multiple filters supported via --repo flag or inline repo: syntax Output: - Text: grep-style (repo:path:line: context), truncated to 200 chars - JSON: full response with stats, repo_stats, and results (--json) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Group fan-out by cell (not jurisdiction), matching BFF pattern - Resolve cell apiUrl from cluster catalog for direct routing - Align resolveRepoFilters with BFF: only strip gh/, try unstripped filter as full_name fallback, match id on raw filter - Use sort.SliceStable with tiebreaker for deterministic output - Route single-cell path through mergeSearchResults for uniform sort/dedup/truncate - TrimSpace error body fallback in codesearch client - Strengthen TestSearch_NonJSONError assertions - Add searchAllCells test seams and 5 integration tests covering cell grouping, cluster URL resolution, partial failure, filter resolution, and single-cell merge - Document case_sensitive as optimistic (peregrine proto lacks it) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1fdef33 to
8ec2ed5
Compare
The cluster catalog is keyed by Cluster.Slug, which corresponds to RepoIndexEntry.ClusterSlug — not RepoIndexEntry.Cell. Using Cell for the lookup would silently miss baseURL resolution when Cell differs from ClusterSlug, falling back to the home-cell URL. - Add clusterSlug field to cellGroup, populated from r.ClusterSlug - Use cells[i].clusterSlug for slugToCluster lookup - Test ResolvesBaseURLFromClusters now uses distinct Cell/ClusterSlug values to prove the lookup path - All test RepoIndexEntry literals updated with ClusterSlug field Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The BFF uses r.cell with a URL template to resolve cell URLs. No other CLI code path does a Cluster.Slug lookup — the experts resolver matches by ClusterHost instead. Revert to using cell for the cluster catalog lookup to mirror the BFF pattern. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Soph
added a commit
that referenced
this pull request
Jul 5, 2026
resolveExpertsCellTarget was experts-named but nothing in it is experts-specific: it maps any repo (ULID or owner/repo) to the entire-api cell hosting it, exactly what every future repo-scoped or fan-out command needs (code search is next, PR #1616). Rename the file and identifiers — resolveRepoCellTarget, cellCoreClient, newCellCoreClient, cellResolveTimeout — and keep experts as the documented example consumer. Mechanical rename; no behavior change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Entire-Checkpoint: 89b4d13bd2b0
Soph
added a commit
that referenced
this pull request
Jul 5, 2026
The data plane has no server-side cross-cell aggregator: a query over all of the caller's repos must be fanned out to each cell hosting them and merged client-side (the entire.io BFF's code-search pattern). PR #1616 inlines that orchestration into search_cmd.go; this extracts the generic layer so code search — and any later repo-set command — shares one implementation: - groupReposByCell: repo index → per-cell groups, deterministic order. - resolveCellBaseURLs: cluster-catalog join on ClusterSlug↔Cluster.Slug. The catalog exposes no cell field, so joining the cell name against Slug (as #1616 currently does) only works when the two coincide. - fanOutCells: parallel per-cell calls under a per-cell timeout, one shared auth.CellClientFactory (subject resolved once, one identity token per jurisdiction), partial failures isolated per result slot. Merge semantics stay with the command. Also documents the three cell-routing shapes in CLAUDE.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Entire-Checkpoint: 842e421e74a8
Soph
added a commit
that referenced
this pull request
Jul 5, 2026
resolveExpertsCellTarget was experts-named but nothing in it is experts-specific: it maps any repo (ULID or owner/repo) to the entire-api cell hosting it, exactly what every future repo-scoped or fan-out command needs (code search is next, PR #1616). Rename the file and identifiers — resolveRepoCellTarget, cellCoreClient, newCellCoreClient, cellResolveTimeout — and keep experts as the documented example consumer. Mechanical rename; no behavior change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Entire-Checkpoint: 89b4d13bd2b0
Soph
added a commit
that referenced
this pull request
Jul 5, 2026
The data plane has no server-side cross-cell aggregator: a query over all of the caller's repos must be fanned out to each cell hosting them and merged client-side (the entire.io BFF's code-search pattern). PR #1616 inlines that orchestration into search_cmd.go; this extracts the generic layer so code search — and any later repo-set command — shares one implementation: - groupReposByCell: repo index → per-cell groups, deterministic order. - resolveCellBaseURLs: cluster-catalog join on ClusterSlug↔Cluster.Slug. The catalog exposes no cell field, so joining the cell name against Slug (as #1616 currently does) only works when the two coincide. - fanOutCells: parallel per-cell calls under a per-cell timeout, one shared auth.CellClientFactory (subject resolved once, one identity token per jurisdiction), partial failures isolated per result slot. Merge semantics stay with the command. Also documents the three cell-routing shapes in CLAUDE.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Entire-Checkpoint: 842e421e74a8
Soph
added a commit
that referenced
this pull request
Jul 6, 2026
resolveExpertsCellTarget was experts-named but nothing in it is experts-specific: it maps any repo (ULID or owner/repo) to the entire-api cell hosting it, exactly what every future repo-scoped or fan-out command needs (code search is next, PR #1616). Rename the file and identifiers — resolveRepoCellTarget, cellCoreClient, newCellCoreClient, cellResolveTimeout — and keep experts as the documented example consumer. Mechanical rename; no behavior change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Entire-Checkpoint: 89b4d13bd2b0
Soph
added a commit
that referenced
this pull request
Jul 6, 2026
The data plane has no server-side cross-cell aggregator: a query over all of the caller's repos must be fanned out to each cell hosting them and merged client-side (the entire.io BFF's code-search pattern). PR #1616 inlines that orchestration into search_cmd.go; this extracts the generic layer so code search — and any later repo-set command — shares one implementation: - groupReposByCell: repo index → per-cell groups, deterministic order. - resolveCellBaseURLs: cluster-catalog join on ClusterSlug↔Cluster.Slug. The catalog exposes no cell field, so joining the cell name against Slug (as #1616 currently does) only works when the two coincide. - fanOutCells: parallel per-cell calls under a per-cell timeout, one shared auth.CellClientFactory (subject resolved once, one identity token per jurisdiction), partial failures isolated per result slot. Merge semantics stay with the command. Also documents the three cell-routing shapes in CLAUDE.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Entire-Checkpoint: 842e421e74a8
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.
Summary
cmd/entire/cli/codesearch/— client package for peregrine's/search/api/searchendpoint--codeand--case-sensitiveflags intoentire search, gated behindENTIRE_CODE_SEARCH=1--repofilter is specified (routes to repo's owning cell)How it works
--code query(no filter)ListRepos→ group by cell →NewEntireAPICellClientper jurisdiction--code --repo owner/name queryNewAuthenticatedEntireAPICellClient--code repo:owner/name query--code --all-repos queryFiles
cmd/entire/cli/codesearch/codesearch.go— client types andSearch()functioncmd/entire/cli/codesearch/codesearch_test.go— client tests (success, API error, non-JSON error, response too large)cmd/entire/cli/search_cmd.go— command wiring, fan-out orchestration, output formatterscmd/entire/cli/search_cmd_test.go— command tests (gate, flags, output, groupReposByCell, mergeSearchResults)Test plan
go test ./cmd/entire/cli/codesearch/...passesgo test ./cmd/entire/cli/ -run "TestSearchCmd|TestWriteCodeSearch|TestCodeSearch|TestGroupRepos|TestMergeSearch"passesmise run lintclean🤖 Generated with Claude Code