5.8.4 Work-item candidate search endpoint for the `@` picker
Type: code · Executor: coding_agent · Repo: motir-core. No blockers (reuses the shipped quickSearch).
The @ picker (5.8.5) needs a query-driven, permission-scoped read of work-item candidates. The read already exists — workItemsService.quickSearch(query, ctx, { limit, excludeIds }) (workItemsService.ts ~line 2843 -> workItemRepository.quickSearch, Postgres pg_trgm, browsable-project scoped, bounded; finding #57). This subtask exposes it for free-text mention search via a thin Route -> Service seam (4-layer rule: route is HTTP-only, calls ONE service method, maps typed errors).
Scope
- Add a GET route (e.g.
app/api/work-items/mention-search/route.ts) takingq+ the currentprojectId/keycontext, returningWorkItemSummaryDto[](key, title, type, status) — capped (default 8, hard max 50),[]for queries under the min length (no DB hit), self excluded when an item id is in context. - Reuse
quickSearchas-is if its scoping fits; only add a service method if the mention search needs different exclusion thanlistLinkCandidates(which is relationship-kind-aware — the mention search is NOT, it just finds items, so prefer a directquickSearchcall overlistLinkCandidates).
Acceptance criteria
- Returns relevance-ordered, browsable-project-scoped candidates by key OR title substring; never unbounded; never leaks items in projects the caller can't browse (the 6.4 gate, reused not re-implemented).
- Short/empty query ->
[]with no DB query. - Route does no Prisma/transaction/business logic; errors map to typed HTTP codes.
- Unit/integration test: scoping (cross-project item excluded), cap, min-length guard.
Context refs: lib/services/workItemsService.ts (quickSearch ~2843, listLinkCandidates ~2802), lib/repositories/workItemRepository.ts (quickSearch), lib/dto/... (WorkItemSummaryDto, toWorkItemSummaryDto).