Early alpha. Not production-ready. No package publication or broad PHP compatibility claim.

Evidence acquisition · NexusScholar.Search

Search

Raw, reconstructable acquisition traces from local imports, recorded provider bytes, or bounded OpenAlex and Semantic Scholar adapters—before any deduplication decision.

Purpose and authority boundary

Search records what was asked, attempted, observed, normalized, skipped, and warned about. Its primary output is a SearchTrace, not a deduplicated corpus. Duplicate sightings stay visible; no-ID records stay unresolved. Search never elects a representative or calls Deduplication.

Acquisition modes: deterministic stubs; user-supplied RIS, BibTeX, and Scopus-like CSV; retained Crossref fixtures; and opt-in OpenAlex or Semantic Scholar transport through exact-host outward adapters. There is no live Crossref adapter, Google Scholar scraping, or provider-completeness claim.

Key types and services

  • SearchQueryInput, SearchTraceRequest, and SearchPlanBinding capture explicit request and plan origin.
  • SearchService validates provider selection/year bounds, builds provider-order-insensitive cache identity, executes ISearchProvider adapters, and preserves attempts, failures, stats, and sightings.
  • SearchProviderCatalog holds local providers; DataProvider and FailingProvider support deterministic fixture scenarios.
  • SearchTrace, SearchSighting, SearchProviderAttempt, and SearchSummary are the raw trace surface.
  • SearchPlanParser parses the schema-closed local plan and an explicitly separate legacy-import profile.
  • SearchImportService parses user-supplied RIS, BibTeX, and Scopus-like CSV bytes into SearchImportTrace with source-file/raw-record digests and parser notices.
  • ProviderAcquisitionRequest, ProviderPageRequest, ProviderAttemptEvidence, and RuntimeProviderResponseEvidence bind sanitized requests, page continuity, observed response facts, parser identity, exact response digests, timestamps, and completeness.
  • ProviderEvidenceCacheKey, ProviderEvidenceCachePolicy, and ProviderEvidenceCacheEntry define provider- and operation-specific retention without making cache state scientific authority.

Core source: NexusScholar.Search. Outward adapters: Crossref, OpenAlex, Semantic Scholar, live host, and cache store. Contracts: ADR 0039, ADR 0040, and ADR 0041.

Trace and import model

query + selected active providers
  → ordered attempts (success / partial failure / all failed)
  → ordered raw sightings + normalized stable identifiers
  → SearchTrace with explicit nonclaims

user export bytes
  → raw source-file digest
  → versioned parser + per-record raw digest/notices
  → SearchImportTrace
  → Deduplication input later

sanitized provider request
  → exact-host transport + bounded identity-encoded response
  → response digest + parser/pagination/attempt evidence
  → normalized raw sightings
  → optional policy-admitted immutable cache entry

Provider-local result order and cross-provider attempt order are semantic. Raw payload material is included only when requested. Source-specific IDs such as Scopus EID or Web of Science accession remain source evidence unless the Shared identity contract admits their namespace.

Two cache identities, two responsibilities

Cache identity includes query, year range, language, limit, offset, sorted active provider aliases, and include_raw_data. It excludes generated trace/query IDs, runtime duration, failure prose, raw bytes, app IDs, paths, URLs, configuration, and credentials. Including raw-data intent intentionally differs from PHP behavior because it changes the evidence surface.

Imported source identity is the exact source-file byte digest plus parser id/version and source metadata. Local path is not identity. Each raw record can carry its own digest. Parser output is a projection over preserved raw evidence, not a replacement for it.

FE-09E’s provider evidence cache is separate from Search result identity. Its key binds provider, operation, sanitized request digest, page request digest, and parser id/version. Only complete 200 responses are eligible. OpenAlex openalex.works may retain exact bodies for 14 days; Semantic Scholar bulk and batch are digest-only; Crossref runtime caching is denied. Expiry prevents a fresh hit but does not erase the verifiable evidence entry.

Typical developer flows

  1. For local provider scenarios, construct a catalog and explicit validation year/clock, then call SearchService.
  2. For imported evidence, read bytes in an adapter and call SearchImportService with format, source tool/database, query/export metadata, and actor/time.
  3. For provider acquisition, build a sanitized request and page descriptor; select a recorded adapter or an exact-host live host; then preserve the returned attempt, response, parser, and pagination evidence.
  4. Resolve credentials outside Core. The live host injects them only at send time and never emits them into descriptors, records, errors, or logs.
  5. Evaluate the provider/operation cache policy before any body write. Treat a cache hit as replay of the original request/receipt evidence, not as a new provider observation.
  6. Persist source bytes or their raw-byte identity alongside the trace.
  7. Display warnings and failed attempts without hiding successful sightings.
  8. Pass the complete verified trace/import records to Deduplication; do not pre-collapse them.

Failure and refusal behavior

Search rejects blank query, invalid/inverted year range, unknown provider alias, invalid limits/offsets, schema-open authoritative plans, unsupported import formats, empty or malformed source data, duplicate source record IDs, and Google Scholar scraping. Provider paths additionally reject wrong scheme/host/port/path/method, redirects, IP literals, user info, fragments, credential-shaped descriptors, encoded or oversized bodies, parser drift, pagination drift, and response-order assumptions. Parser failures retain bounded response evidence but produce no successful page.

Tests, extension points, and nonclaims

SearchServiceTests and SearchImportServiceTests cover local selection, imports, warnings, and trace identity. Provider-specific suites cover recorded Crossref, OpenAlex, Semantic Scholar, transport security, and cache invariants. Live smokes are opt-in and excluded from CI.

Current code makes no live Crossref, automatic retry, background refresh, Semantic Scholar body-retention right, Google Scholar scraping, provider coverage/completeness/parity, Search-time deduplication, corpus membership, API, cloud, production, or broad PHP compatibility claim.