Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
da6eab9
docs: accuracy and contract redesign spec + implementation plan
MyPrototypeWhat Sep 14, 2026
5be3d19
refactor(core): license facts drive the gate, merge and reranker
MyPrototypeWhat Sep 14, 2026
e0784d0
docs(spec): scale obligation credit by grant fraction; facts-keyed co…
MyPrototypeWhat Sep 14, 2026
e308fa8
fix(core): facts-keyed conflict detection; grant-scaled permissivenes…
MyPrototypeWhat Sep 14, 2026
4631a83
docs(spec): conflict iff facts fingerprints differ
MyPrototypeWhat Sep 15, 2026
c114d53
fix(core): open a rights conflict only when facts fingerprints differ
MyPrototypeWhat Sep 15, 2026
2c6a6ac
refactor: remove the legacy filters and queryFeatures channels
MyPrototypeWhat Sep 15, 2026
a8bf03b
refactor(core,mcp): single control registry and core-exported search …
MyPrototypeWhat Sep 15, 2026
a6f33b9
refactor: providers emit EmittedReference; core completes provenance,…
MyPrototypeWhat Sep 15, 2026
7934043
fix(core): count schema rejects where they happen; truncated items ar…
MyPrototypeWhat Sep 15, 2026
739d3f6
feat(providers): descriptive fields and upstream scores for Met, Arti…
MyPrototypeWhat Sep 15, 2026
86d4b50
fix(core): plainText keeps word boundaries, decodes entities, caps by…
MyPrototypeWhat Sep 15, 2026
ab7db52
refactor(core): selection and pipeline stages; multi-pass diagnostics…
MyPrototypeWhat Sep 15, 2026
5ea27bd
feat(core): source-confidence merge weights, default lexical rerank o…
MyPrototypeWhat Sep 15, 2026
a9476d4
docs(spec): fusion weight in the lexical reranker; empty-set jaccard …
MyPrototypeWhat Sep 15, 2026
0908155
fix(core): fused relevance survives lexical rerank; empty-set jaccard…
MyPrototypeWhat Sep 15, 2026
78526ac
docs(spec): threshold stage runs after rerank, before the gate
MyPrototypeWhat Sep 15, 2026
03d0b0b
feat: provider accepts() routing; nailbook declines non-nail queries;…
MyPrototypeWhat Sep 15, 2026
eeb996c
test(core): rerank fixtures that discriminate, and accepts sees the r…
MyPrototypeWhat Sep 15, 2026
e670cb8
fix(providers): nailbook ignores "snail"; polyhaven builds match fiel…
MyPrototypeWhat Sep 15, 2026
939e73f
feat(mcp): minRelevance, deadlineMs and gateContext search parameters
MyPrototypeWhat Sep 15, 2026
4dfd41a
docs: describe the facts-driven gate, the emitted-reference contract …
MyPrototypeWhat Sep 15, 2026
b0aca4a
fix: cache namespace v3; polyhaven tokenises on punctuation; reject s…
MyPrototypeWhat Sep 15, 2026
f260f09
docs: reconcile spec/changeset with shipped nailbook regex and MCP im…
MyPrototypeWhat Sep 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions .changeset/accuracy-and-contract-redesign.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
'@refkit/core': minor
'@refkit/mcp': minor
'@refkit/provider-artic': minor
'@refkit/provider-brave': minor
'@refkit/provider-europeana': minor
'@refkit/provider-flickr': minor
'@refkit/provider-freesound': minor
'@refkit/provider-gutendex': minor
'@refkit/provider-internet-archive': minor
'@refkit/provider-jamendo': minor
'@refkit/provider-met': minor
'@refkit/provider-nailbook': minor
'@refkit/provider-openverse': minor
'@refkit/provider-pexels': minor
'@refkit/provider-pixabay': minor
'@refkit/provider-poetrydb': minor
'@refkit/provider-polyhaven': minor
'@refkit/provider-rijksmuseum': minor
'@refkit/provider-smithsonian': minor
'@refkit/provider-unsplash': minor
'@refkit/provider-wikimedia-commons': minor
---

Accuracy and contract redesign: license **facts** drive every rights decision, providers
only describe what their source knows, and the default search path ranks for the query
without a host-supplied model.

These are **breaking** changes to the public surface. Every package is still `0.x`, so
they ship as `minor` per semver's pre-1.0 rule — nothing is aliased or shimmed, so read
the removed/added lists before upgrading.

### Rights: facts, not license ids

- `LicenseId` is now an **open** string (`KnownLicenseId | (string & {})`); an id with no
row in `LICENSE_FACTS` resolves to the `unknown` row, which grants nothing.
- Added `RightsRecord.facts?: LicenseFacts` — a source whose terms are narrower than the
label it declares supplies its own row. Added `factsOf(rights)`, `licenseFactsSchema`,
`isKnownLicenseId`, `isIndeterminate`, `compareRestrictiveness(factsA, factsB)` and
`permissivenessScore(facts)`.
- **Removed** `stricterLicense(idA, idB)` (replaced by `compareRestrictiveness`) and the
reranker's internal `LICENSE_PERMISSIVENESS` table (replaced by `permissivenessScore`).
- Cross-source conflict detection is keyed on facts, not labels: identical facts under
different ids (`CC0-1.0` vs `PD`) no longer conflict, the same id with narrower facts
now does, and `RightsConflict.licenses` lists the source-declared ids involved.
- `rightsRecordSchema` now rejects a `licenseVersion` on a non-CC-family license.
`CC_VERSIONED_FAMILIES` and `ccVersionFor` moved from `provider-helpers` to `license`
(still exported from the package root).

### Providers emit, core completes

- Added `EmittedReference` — what `ReferenceProvider.search` now returns:
`modality, kind?, title?, description?, tags?, sourceUrl, canonicalUrl?, rights,
thumbnail?, preview?, perceptualHash?, visual?, text?, sourceScore?, raw?`. **Every
`@refkit/provider-*` factory's `search` signature changed accordingly.**
- Core stamps `id`, `source`, `canonicalUrl`, `verifiedAt` and `relevance` and applies the
per-provider `limit`: added `completeReference`, `parseEmitted`, `emittedReferenceSchema`.
Providers no longer compute ids, write provenance, or post-truncate.
- `Reference` and `EmittedReference` gained `description`, `tags: string[]` and
`sourceScore`. Met, Art Institute of Chicago, Wikimedia Commons and Rijksmuseum now
populate descriptive fields (and Art Institute also reports its upstream `_score`), which
directly sharpens ranking.
- Added `okJson(res, label)` for provider mappers, `plainText`, and
`RefkitOptions.userAgent` (`'refkit-client/1'` by default; Art Institute's edge rejects
Node's default UA) plus `withDefaultUserAgent`.

### One search channel, one control registry

- **Removed** `SearchFilters`, `SearchInput.filters`, `NormalizedQuery.filters`,
`SearchMeta.appliedFilters`, `QueryFeature`, `ReferenceProvider.queryFeatures`, the legacy
feature→control routing, and the MCP `filters` parameter. Use `controls` /
`capabilities.controls`.
- Control types and the `key → path` registry moved to `controls.ts`; added `CONTROL_PATHS`,
`SEARCH_CONTROL_KEYS`, `getControl`, `setControl`, `hasControl`,
`buildSearchControlsSchema`, `searchControlsSchema`, `searchControlKeySchema`,
`searchMetaSchema`, `providerSearchStatusSchema` and the `MODALITIES` tuple to the public
surface — `@refkit/mcp` imports only `buildSearchControlsSchema` and `searchMetaSchema`
from core, and derives its modality enum from the registered providers rather than
keeping a local copy.
- Orchestrator stages are exported for testing and reuse: `selectProviders`,
`PROVIDER_SKIP_REASONS`, `runPass`, and `SearchMeta.passes` (per-pass latency, warnings
and rights conflicts now accumulate across cursor page advances).

### Accuracy defaults

- **Source confidence** (`RefkitOptions.sourceConfidence`, default on, floor `0.1`) weights
each source's rank-fusion contribution by how much of its batch mentions the query; each
fulfilled source reports `meta.providers[].confidence`. Added `sourceConfidence` and
`lexicalHit`; `MergeOptions.weights` applies the weights.
- **Reranking is on by default**: `RefkitOptions.rerank` / `SearchInput.rerank` default to
`lexicalReranker()`, `false` returns raw fusion order. The lexical reranker now scores
over `title + description + tags + excerpt`, blends the incoming fused relevance
(`fusionWeight`, default `0.5`), and adds a same-source near-duplicate-title penalty
(`nearDuplicatePenalty`, `nearDuplicateThreshold`) and an optional `sourceScoreWeight`.
Added `refText` alongside `tokenize`. MCP's `rerank` parameter now defaults to true.
- **Relevance threshold**: `SearchInput.minRelevance` drops results the ranker scored below
the bar (after rerank, before the gate) and reports `SearchMeta.threshold`
(`SearchThresholdMeta`). New MCP `minRelevance` parameter. The bar is graded against the
reranker's blended score and does not transfer to `rerank: false`.
- **Query acceptance**: `ReferenceProvider.accepts?({ text, modalities })` lets a narrow
source decline queries it cannot answer — skipped with `reason: 'declined'`, bypassed by
an explicit `sources` whitelist, and an all-declined search returns an empty result
instead of throwing. `@refkit/provider-nailbook` declines queries that do not name nails;
`@refkit/provider-polyhaven` now matches each query token independently and ranks assets
by how many tokens they match.
- **Whole-search deadline and gate context**: `SearchInput.deadlineMs` (bounds the whole
call, cursor advances included) and `SearchInput.gateContext.userJurisdiction` (forwarded
to the search-time gate, matching `evaluateUse`). Both are exposed as MCP parameters.

The internal `@refkit/provider-testkit` (private, never published) dropped its id-prefix,
providerId and licenseVersion conformance rules — core now guarantees all three — and
completes emitted items exactly as the orchestrator does before asserting the rules that
remain a satellite's own responsibility.
Loading