Skip to content

Fix search timeout, sort vocabulary, and metadata handling#557

Open
jeremy wants to merge 1 commit into
mainfrom
fix/search-semantics-timeout
Open

Fix search timeout, sort vocabulary, and metadata handling#557
jeremy wants to merge 1 commit into
mainfrom
fix/search-semantics-timeout

Conversation

@jeremy

@jeremy jeremy commented Jul 22, 2026

Copy link
Copy Markdown
Member

Fixes #470
Refs #546

Problem

Root causes

  1. Timeout (basecamp search timing out #470). --limit defaults to 0; the SDK treats 0 as "fetch ALL" and follows Link-header pagination across every page unbounded (followPagination). A broad or blank search paginates for 90s+. Affects all output formats.

  2. "Identical unrelated results" (search ignores query semantics and project filter #546) — already fixed upstream. The primary cause was old SDK GET requests carrying Content-Type: application/json, which made BC3 discard q and every filter (SDK Add lineup list command #324, closed; BC3 #12361). The pinned SDK v0.8.0 sets that header only when the request has a body, so bodyless GETs like search no longer trip it, and BC3 already defaults blank sort to best_match. The residual CLI defect was stale sort docs/vocabulary; unbounded pagination (cause 1) amplified any broad query into the timeout.

  3. --project ignored (search ignores query semantics and project filter #546) — SDK gap. The global --project/--in flag is accepted but never read. SDK SearchParams (v0.8.0, latest published) exposes only Q/Sort — no bucket_ids[]. BC3 #12361 is merged server-side, but no published SDK exposes the filters.

  4. search metadata error (search ignores query semantics and project filter #546) — schema drift. /searches/metadata.json now returns recording/file search types (as key/value pairs) plus default_* filter labels; the SDK SearchMetadata models only Projects, so the response deserializes to an empty projects array, which the CLI turned into a fatal error.

Changes (CLI-only, this PR)

  • Bounded default (fixes basecamp search timing out #470). Default cap of 20 when neither --all nor an explicit --limit is given. --all → unbounded; explicit --limit must be > 0; --all + --limit together is a usage error. Regression tests prove a bare search returns 20 in one HTTP request while --all traverses every page.
  • Sort vocabulary (fixes search ignores query semantics and project filter #546 sort docs). --sort normalizes to relevance (→ best_match, pinned explicitly) or recency (with deprecated created_at/updated_at aliases mapped in); unknown values are rejected. BC3 treats any non-blank, non-best_match sort as created-at descending, so recency works today regardless of the search-filter release. Help and examples updated.
  • Honest --project (interim). Explicit --project/--in is rejected with a message pointing at the pending SDK release; ambient config projects are never rejected.
  • Graceful metadata (fixes search ignores query semantics and project filter #546 metadata). Empty metadata is now a successful envelope with a notice describing the unmodeled fields, not a fatal error. Command help no longer promises project scopes.

Deferred to the post-SDK-bump follow-up (completes #546)

After make bump-sdk to the release that absorbs the search filters/metadata: resolve --project via app.Names.ResolveProject (ID or name) into the SDK's bucket-ID type, add --type/--since, expose the real metadata fields, drop the interim --project rejection, then Fixes #546.

SDK contract still missing

Tracked in the SDK's canonical gap doc spec/api-gaps/search-filter-additions.md (stale — BC3 #12361 has since merged) and closed SDK #324. Missing from a published SDK: bucket_ids[], type_names[], creator_ids[], file_type, exclude_chat, since, best_match/recency sort, the metadata recording_search_types/file_search_types (key/value pairs) and default_creator_label/default_bucket_label/default_circle_label/default_file_type_label/default_type_label fields, and the timelines/searches counterpart.

Verification

bin/ci fully green (fmt, vet, lint, unit + e2e BATS, naming, surface snapshot, skill-drift, SDK provenance, go mod tidy). grep 'replace' go.mod → none. The metadata fixture mirrors bc3 app/views/api/searches/metadata/index.json.jbuilder.

Copilot AI review requested due to automatic review settings July 22, 2026 21:26
@github-actions github-actions Bot added commands CLI command implementations tests Tests (unit and e2e) skills Agent skills breaking Breaking change bug Something isn't working labels Jul 22, 2026
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown

⚠️ Potential breaking changes detected:

  • Renaming of the '--sort' flag values: The flag previously allowed 'created_at' and 'updated_at', which are now treated as aliases for 'recency'. This could break scripts specifying the removed 'created_at' or 'updated_at' values.
  • Introduction of a default search limit of 20 results when neither '--all' nor '--limit' is specified. Previously, there was no default limit, so scripts relying on this behavior may receive fewer results.
  • Change in behavior of '--project/--in' flags: Any explicit use of these flags results in a usage error due to unsupported project-scoped searches.

Review carefully before merging. Consider a major version bump.

Copilot AI 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.

Pull request overview

This PR fixes basecamp search behavior to avoid unbounded pagination timeouts, align --sort with current API vocabulary, and handle search metadata schema drift more gracefully while the pinned SDK lacks search filter fields.

Changes:

  • Cap default search results at 20 unless --all is used; validate --limit (> 0) and forbid --all + --limit.
  • Normalize --sort values to best_match (relevance) or recency, rejecting unknown values.
  • Treat empty search metadata as a successful response with a notice (instead of a fatal error), and update docs/tests accordingly.

Tip

If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
skills/basecamp/SKILL.md Updates the skill docs/examples for capped search defaults, new sort vocabulary, and metadata caveats.
internal/commands/search.go Implements bounded default limit, sort normalization, explicit --project/--in rejection, and graceful metadata handling.
internal/commands/search_test.go Adds regression tests for default cap vs --all, sort mappings, --limit validation, project rejection, and metadata schema drift.
e2e/smoke/smoke_misc_read.bats Updates smoke test to expect search metadata success even when metadata is empty (schema drift).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@cubic-dev-ai cubic-dev-ai Bot 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.

No issues found across 4 files

Re-trigger cubic

`basecamp search` could hang indefinitely and reported confusing sort
options and a fatal metadata error.

- Bound the default result set to 20. `--limit` still defaults to 0, but
  the SDK treats Limit==0 as "fetch every page" and follows Link-header
  pagination unbounded, which paginates for 90s+ on a broad query. Apply a
  default cap unless `--all` opts into an unbounded fetch. Error on
  `--limit 0`/negative and on `--all --limit` together.

- Normalize `--sort` to relevance (best_match) or recency, mapping the
  deprecated created_at/updated_at aliases onto recency and rejecting
  unknown values. Pin best_match explicitly for deterministic output.

- Reject explicit `--project`/`--in` with a clear message: the pinned SDK's
  SearchParams exposes only q/sort, so project scoping needs a later SDK
  release that absorbs bucket_ids[]. Ambient config projects are untouched.

- Stop treating empty search metadata as fatal. /searches/metadata.json now
  returns recording/file search types and labels the SDK does not model, so
  an empty projects list is schema drift, not an error — return success with
  a notice instead.
Copilot AI review requested due to automatic review settings July 22, 2026 22:48
@jeremy
jeremy force-pushed the fix/search-semantics-timeout branch from 6317039 to 731f11b Compare July 22, 2026 22:48

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment thread internal/commands/search.go
Comment thread internal/commands/search.go

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 731f11bd9b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/commands/search.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking Breaking change bug Something isn't working commands CLI command implementations skills Agent skills tests Tests (unit and e2e)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

search ignores query semantics and project filter basecamp search timing out

2 participants