Two field-test follow-ups against openalex_search_entities, both addressing
production traffic gaps where LLM callers either lacked an OpenAlex feature
surface or guessed intuitive names that don't match upstream's vocabulary.
Random sampling (#14): expose `sample` (1-100) and `seed` parameters.
Single page only; mutually exclusive with `cursor`; `seed` requires
`sample`. Both rejections carry typed contract reasons
(sample_with_cursor, seed_without_sample) so the LLM gets a clean
recovery hint instead of a 400 from upstream. Service layer aligns
per_page to sample to avoid silent truncation when sample > per_page.
Field-name aliases (#17): pure key renames at the service layer.
Filters (works-only) cited_works → cites, year → publication_year, plus
a universal id → openalex rewrite when the value matches an OpenAlex ID
pattern (bare or URL-form, pipe-joined OR supported). Select (works-only)
year → publication_year, authors → authorships, joining the existing
abstract → abstract_inverted_index. Misses fall through so upstream's
helpful 400 still fires for typos. Filter description anchors positive
priors with concrete common keys (openalex, cites, publication_year,
authorships.author.id, type, is_oa).
Reclassified semantic_per_page_cap from InvalidParams → ValidationError
for parity with the other pre-upstream input-shape rejections.
Added tool-defs-analysis skill (read-only audit of LLM-facing definition
language across tools/resources/prompts).
devcheck, rebuild, all 107 tests passing.