cli: add multi-cell fan-out helpers (groupReposByCell, fanOutCells) · Entire
cli: add multi-cell fan-out helpers (groupReposByCell, fanOutCells)
6055b38→main·
Soph·1w ago·4 files·+457 added/-0 removed
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
Sessions
842e421e74a8View transcript
Changes
4
MCLAUDE.md+29
cmd/entire/cli
Acell_fanout.go+199
Acell_fanout_test.go+227
Mcell_target_test.go+2
505 unmodified lines
### Entire-API Cell Routing (which cell does a data-plane request go to?)
The data plane (entire-api) is deployed per jurisdiction; a repo placement
lives in exactly one cell, user `/me/*` activity is consolidated in the
caller's home cell, and no server-side cross-cell aggregator exists. The CLI
therefore has exactly three routing shapes, mirroring the entire.io BFF:
- **Repo-scoped → one cell**: `resolveRepoCellTarget` (`cell_target.go`) maps
a repo (ULID or owner/repo) to the cell hosting it via mirrors + the cluster
catalog. Best-effort: any failure returns nil and the auth layer falls back
to home-jurisdiction routing. Used by experts
(`NewAuthenticatedEntireAPICellClient` in `api_client.go`).
- **User-scoped `/me` → home cell, never fan out**:
`auth.NewEntireAPICellClient(ctx, insecure, nil)` routes by the
`home_jurisdiction` JWT claim; activity/recap use it with a data-API
fallback (`runAuthenticatedActivityAPI` in `entireapi_client.go`).
- **Repo-set queries → fan out and merge client-side**: `cell_fanout.go` —
`groupReposByCell` (repo index → per-cell groups; the catalog join key is
`ClusterSlug`↔`Cluster.Slug`, NOT the cell name, which the catalog does not
expose), `resolveCellBaseURLs`, and `fanOutCells` (parallel per-cell calls,
per-cell timeout, partial failures isolated per slot). Merge semantics stay
with the command.
Token rule: identity tokens are **per-jurisdiction, not per-cell**. Multi-cell
callers must build one `auth.CellClientFactory`
(`NewEntireAPICellClientFactory`) per operation — it resolves the login
subject once and mints at most one token per jurisdiction. `fanOutCells` does
this automatically; do not call `NewEntireAPICellClient` in a loop.
### Session Strategy (`cmd/entire/cli/strategy/`)
The CLI uses a manual-commit strategy for managing session data and checkpoints. The strategy implements the `Strategy` interface defined in `strategy.go`.