Three fixes to the meetings service:
- `offset` was documented as a 1-based page number but implemented as an
item index, so with `pageSize: 20` a request for page 2 returned items
2-21 — nineteen of the twenty the caller already had. This changes the
observable behaviour of `openproject_search_meetings`: paging now
returns disjoint pages. Shipping two identical pagination bugs with
only the work package one fixed would have been worse.
- `author` was added as a shallow field but never to the `matchType`
union, so `resolveMatchType` fell through and reported a meeting found
by a person's name as having matched on project name.
- `getMeeting` retained `.catch(() => undefined)` on its agenda-item
fetch, swallowing 401/403/429. This is the tool a model calls
immediately after a search hit, so an expired token would have been
reported as "this meeting has no agenda items".
Also drops the duplicate `items` array from `MeetingSearchPage`; the
`items` field on `PaginatedResult` and on `listMeetings` is unchanged.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Routes searchMeetings through the shared searchPipeline instead of a
hand-rolled Promise.all fan-out, fixing two live bugs: an expired token
on agenda-item fetch previously produced "no results" (swallowed via
.catch(() => undefined)) instead of propagating the auth error, and up
to 250 candidate meetings could fire simultaneous agenda-item requests.
The pipeline caps enrichment at 25 candidates with 8 in flight, and
isFatalSearchError now lets 401/403/429 propagate while other failures
degrade a single record and set `degraded`.
Also removes the old substring-based extractSnippet from
src/services/meetings.ts in favor of src/search/snippet.ts, and adds
matchMode ("fuzzy" | "exact") to SearchMeetingsParams and the
openproject_search_meetings tool schema.
Updated two pre-existing tests in tests/meetings.test.ts whose fixtures
assumed the old implementation's API surface: one didn't stub the
meeting-detail endpoint the pipeline's deep enrichment now also fetches
(for participants), and one assumed a 50-item candidate page size where
the new pipeline hardcodes 100. Updated one assertion in
tests/tools.test.ts that checked the old literal tool description.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>