feat: add search commands (task 0016) #17

Merged
alexion merged 2 commits from task-0016-search-commands into main 2026-07-14 10:24:15 -04:00
Owner

Task: .claude/tasks/0016-search-commands.md

Summary

Adds search issues <query> and search prs <query> — the full-text escape hatch the forbidden --search flag on issue list / pr list redirects to.

Both call Gitea's cross-repo issue-search endpoint (GET /repos/issues/search) with the query, a type of issues or pulls, and the owner param, then filter results to the current repository client-side via each result's repository field (the endpoint has no repo-name filter). The count line reports count: N of T total with T from the filtered set (ADR 0005) — the endpoint's cross-repo X-Total-Count is never used.

The positional query is required (VALIDATION_ERROR if missing). Flags: --state (default open), --label (comma-separated names passed straight through as the API labels param — no name→id lookup, since the search endpoint takes names), --limit (default 30), --fields. Default output is the locator schema (number, title, state, author, created) under issues: / pull_requests: blocks matching the list commands — search finds the number, issue view / pr view load the detail.

Both variants live in one src/commands/search.ts, parameterised by a SearchKind config (the same config-object dispatch used by pr.ts's DependencyGroup).

Deviations from the plan

None material. Beyond the bare acceptance criteria, added ordinary CLI hygiene consistent with the sibling commands: a search group help, per-variant --help text, an unknown-subcommand VALIDATION_ERROR, a too-many-positionals rejection, and top-level-help entries in cli.ts.

Tests

Fixture-server tests cover both types, cross-repo filtering, the count-line rule, each flag (--state/--label/--limit/--fields), the empty state, and missing-query validation. End-to-end tests run search issues and search prs against a live Gitea instance and assert real matches under the locator schema. Full suite: 363 passing; typecheck and build clean.

Review

Risk

Overall: LOW

  • Blast radius: Low — new self-contained search.ts; only touches cli.ts to register it, no existing callers changed.
  • Reversibility: Low — purely additive; deleting the file and one registration line reverts it, no migrations or published schema.
  • Test coverage: Low — thorough fixture tests plus two live e2e tests.
  • Sensitive domain: Low — read-only full-text search; no auth/permissions/concurrency/mutation, reuses existing login/token plumbing.
  • Size & complexity: Low — ~237 LOC of straightforward parse-fetch-filter-render, no tangled control flow.
  • Runtime criticality: Low — dev-facing CLI tooling, not a production hot path.

Unaddressed findings

Standards — 0 violations; Spec — 0 findings. The Standards axis noted two judgement-call nits it deemed correct-by-intent, kept as-is:

  • helpSuggestion is built inline per-call rather than hoisted to a module-level *_HELP_SUGGESTION constant — intentional, because the string is per-kind.
  • formatCountLine's third (atLimit) arg is passed false unconditionally — correct, since search always reports the filtered set's own size as the total (ADR 0005), so the at-limit branch never applies.
Task: `.claude/tasks/0016-search-commands.md` ## Summary Adds `search issues <query>` and `search prs <query>` — the full-text escape hatch the forbidden `--search` flag on `issue list` / `pr list` redirects to. Both call Gitea's cross-repo issue-search endpoint (`GET /repos/issues/search`) with the query, a `type` of `issues` or `pulls`, and the `owner` param, then filter results to the current repository client-side via each result's `repository` field (the endpoint has no repo-name filter). The count line reports `count: N of T total` with `T` from the filtered set (ADR 0005) — the endpoint's cross-repo `X-Total-Count` is never used. The positional query is required (`VALIDATION_ERROR` if missing). Flags: `--state` (default open), `--label` (comma-separated names passed straight through as the API `labels` param — no name→id lookup, since the search endpoint takes names), `--limit` (default 30), `--fields`. Default output is the locator schema (`number`, `title`, `state`, `author`, `created`) under `issues:` / `pull_requests:` blocks matching the list commands — search finds the number, `issue view` / `pr view` load the detail. Both variants live in one `src/commands/search.ts`, parameterised by a `SearchKind` config (the same config-object dispatch used by `pr.ts`'s `DependencyGroup`). ### Deviations from the plan None material. Beyond the bare acceptance criteria, added ordinary CLI hygiene consistent with the sibling commands: a `search` group help, per-variant `--help` text, an unknown-subcommand `VALIDATION_ERROR`, a too-many-positionals rejection, and top-level-help entries in `cli.ts`. ### Tests Fixture-server tests cover both types, cross-repo filtering, the count-line rule, each flag (`--state`/`--label`/`--limit`/`--fields`), the empty state, and missing-query validation. End-to-end tests run `search issues` and `search prs` against a live Gitea instance and assert real matches under the locator schema. Full suite: 363 passing; typecheck and build clean. ## Review ### Risk **Overall: LOW** - Blast radius: Low — new self-contained `search.ts`; only touches `cli.ts` to register it, no existing callers changed. - Reversibility: Low — purely additive; deleting the file and one registration line reverts it, no migrations or published schema. - Test coverage: Low — thorough fixture tests plus two live e2e tests. - Sensitive domain: Low — read-only full-text search; no auth/permissions/concurrency/mutation, reuses existing login/token plumbing. - Size & complexity: Low — ~237 LOC of straightforward parse-fetch-filter-render, no tangled control flow. - Runtime criticality: Low — dev-facing CLI tooling, not a production hot path. ### Unaddressed findings Standards — 0 violations; Spec — 0 findings. The Standards axis noted two judgement-call nits it deemed correct-by-intent, kept as-is: - `helpSuggestion` is built inline per-call rather than hoisted to a module-level `*_HELP_SUGGESTION` constant — intentional, because the string is per-`kind`. - `formatCountLine`'s third (`atLimit`) arg is passed `false` unconditionally — correct, since search always reports the filtered set's own size as the total (ADR 0005), so the at-limit branch never applies.
alexion added 1 commit 2026-07-14 09:55:54 -04:00
feat: add search commands (task 0016)
Some checks failed
CI / test (pull_request) Failing after 45s
4c3dde26b4
Add `search issues <query>` and `search prs <query>`, the full-text escape
hatch the forbidden `--search` flag on the list commands redirects to.

Both hit Gitea's cross-repo issue-search endpoint with the query, a `type`
of issues or pulls, and the owner param, then filter results to the current
repository client-side via each result's `repository` field — the endpoint
has no repo-name filter. The count line reports `count: N of T total` with
`T` from the filtered set (ADR 0005), never the endpoint's cross-repo
`X-Total-Count`.

The positional query is required (VALIDATION_ERROR if missing). Flags:
`--state` (default open), `--label` (comma-separated names passed straight
through as the API `labels` param), `--limit` (default 30), and `--fields`.
Default output is the locator schema (`number`, `title`, `state`, `author`,
`created`) under `issues:` / `pull_requests:` blocks matching the list
commands — search finds the number, `issue view` / `pr view` load the detail.

Covered by fixture-server tests for both types, cross-repo filtering, the
count rule, each flag, the empty state, and missing-query validation, plus
end-to-end tests against a live Gitea instance.
alexion added 1 commit 2026-07-14 10:09:57 -04:00
test: poll for indexer consistency in search e2e (task 0016)
All checks were successful
CI / test (pull_request) Successful in 45s
CI / test (push) Successful in 46s
c2c5f1728c
Gitea's issue/PR search endpoint is backed by an asynchronous, eventually-
consistent indexer (bleve by default), so a PR opened moments earlier in the
e2e `beforeAll` was not yet searchable when `search prs` ran, and the live
assertion saw zero matches. Both live-search tests now poll the search via
`expect.poll` until the freshly-created content is indexed before asserting on
the exact locator-schema output. Record the eventual-consistency behaviour as
a project gotcha.
alexion merged commit c2c5f1728c into main 2026-07-14 10:24:15 -04:00
alexion deleted branch task-0016-search-commands 2026-07-14 10:24:15 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: alexion/gitea-axi#17