Files
gitea-axi/.claude/tasks/0016-search-commands.md
alexion 4c3dde26b4
Some checks failed
CI / test (pull_request) Failing after 45s
feat: add search commands (task 0016)
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.
2026-07-14 09:55:20 -04:00

3.4 KiB

spec, blocked-by
spec blocked-by
gitea-axi 0008-pr-list

What to build

The full-text escape hatch: search issues <query> and search prs <query>, the destination of the forbidden --search redirects. Both hit Gitea's repo-issues search endpoint with the query, a type of issues or pulls, and the owner param; since the endpoint has no repo-name filter, results are filtered client-side to the current repository via each result's repository field, following the client-side filtering policy including its count-line rule. The positional query is required (VALIDATION_ERROR if missing). Flags: --state (default open), --label (comma-separated names, API-supported), --limit (default 30), --fields. Both commands use the locator schema (number, title, state, author, created) — search finds the number, issue view/pr view load the detail — and output blocks issues:/pull_requests: matching the list commands.

Acceptance criteria

  • search issues "<query>" and search prs "<query>" query the search endpoint with the right type and owner, then filter to the current repo client-side
  • The count line reports count: N of T total with T from the client-side-filtered set
  • A missing query yields VALIDATION_ERROR (exit 2)
  • --state, --label, --limit, and --fields work; default fields are the locator schema
  • Empty results emit the standard <noun>[0]: (none) empty state
  • Fixture-server tests cover both types, cross-repo results being filtered out, and the missing-query validation
  • End-to-end tests run search issues and search prs against a live Gitea instance and assert real matches are returned with the locator schema, confirming the live search-endpoint response shape and the type/owner/q query behavior the fixture server cannot attest to

Implementation Notes

  • Both variants live in one src/commands/search.ts, parameterised by a SearchKind config (type, output noun, the view command a match feeds into, and --help text) — the same config-object dispatch used elsewhere (pr.ts's DependencyGroup). search issues and search prs share the endpoint call, the client-side repo filter, and the render, differing only in that config.
  • The repo filter is always client-side (the endpoint has no repo-name param), so every call fully paginates via fetchAllPages and then filters to the current repo by matching each result's repository.owner/repository.name case-insensitively. The count-line total T is the filtered set's own size, so the endpoint's cross-repo X-Total-Count is never used — the ADR 0005 client-side-filtering rule.
  • --limit caps the shown rows after filtering while T keeps the full filtered total, matching pr list's client-filter behaviour.
  • --label is passed straight through as the endpoint's labels param (comma-separated names): the search endpoint takes names directly, so there is no name→id lookup, unlike pr list --label.
  • The --fields extra-field vocabulary (body, closedAt, labels, milestone, updatedAt, url) mirrors issue list's, since search results are Issue-shaped for both types.
  • Added, beyond the bare acceptance criteria, 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.