name: rlat-curate
description: >-
Human-in-the-loop curation of an rlat knowledge model (.rlat): surface the
self-audit findings (gaps, contradictions, stale external facts), then let the
USER decide each one — approve a drafted fill, hand-provide an authoritative
source, or skip — so nothing the user hasn't sanctioned ever lands. Trigger when
the user says "curate my knowledge base", "let me review before adding", "I'll
approve what gets added", "human in the loop", "I'll provide the source", "review
the findings with me", or wants final say over what enters the corpus's earned
layer. This is the approval/authority front-end over rlat-gap-scan,
rlat-contradictions, and rlat-refresh-facts. NOT for: autonomous filling (the
loop does that unattended); answering questions (use the rlat skill).
allowed-tools: Bash(rlat:*), WebFetch, WebSearch, Read, Write, Edit, Glob, Grep
rlat-curate — the human decides what enters the corpus
The self-audit and its skills can run unattended, but some .rlats want a human in
the loop: the user reviews each finding and either approves a drafted fill,
hand-provides the authoritative fact/source, or skips it. This skill is that
front-end. Its whole point is authority + trust tier: what the user vouches for
lands at the highest trust; nothing lands without the user's say-so.
The trust model is explicit and ordered (the seed prior in
store/insight.py::seed_confidence):
user ≥ verified-external (≥2 agreeing web sources) ≥ single-external ≥ corpus (synthesis)
A user-vouched fact seeds the band at the user tier — the highest starting trust — because the user is the authority. Every fill, even a user-vouched one, is still faithfulness-gated: the user provides a source, not just an assertion, and the claim must trace to it. A fill is born at its tier's trust and then earns or loses rank by outcomes; the tier is the prior, not a permanent verdict.
The loop
1. Surface the findings (free)
Find the .rlat (Glob "*.rlat"; prefer the project-named one or ask). Gather what
the corpus's self-audit flags, by driving the sibling skills / CLI:
- Gaps —
rlat-gap-scan(questions the corpus can't answer). - Contradictions —
rlat audit <km> --shape --min-cosine 0.85 --with-text --format json, then judge stance yourself (therlat-contradictionsrubric). - Stale external facts —
rlat audit <km> --external --format json, then re-fetch- re-judge (the
rlat-refresh-factsrubric).
- re-judge (the
Present them to the user as a short, plain list — what's missing / conflicting / out-of-date, and where it would belong. Don't fix anything yet.
2. Let the user decide each finding
For each, offer the three choices and wait for the user:
- Approve a draft — you propose a grounded, cited fill (for a gap: researched from authoritative sources with cross-source agreement; for a stale fact: the corrected value from the re-fetched source). The user okays it → it lands at verified-external (≥2 agreeing sources) or single-external (one source).
- Hand-provide the source — the user gives the authoritative fact and a source (a URL, a doc, a quote). You verify the claim traces to that source (read it — free), then it lands at the user tier (highest trust).
- Skip — nothing lands. A finding the user doesn't sanction never enters.
If the user gives a fact with no source, ask for one. The user is the authority on what's true, but the band still records where it traces — a sourceless assertion can't be faithfulness-checked and shouldn't land as settled.
3. Land it at the right tier (only on the user's go)
A sanctioned fill lands via the promotion path with its provenance set. The FREE (no-API) way — you verified it yourself, so no judge client is needed:
- Approved web draft (≥2 agreeing sources):
curator.agent_fill.land_external_fact(km, question, claim, sources, provenance="verified_external", faithfulness=<your confidence>)wheresourcesis the[{"url","text"}, …]you fetched + judged to agree. It builds the external evidence and lands via the caller-verified path; it requires ≥2 DISTINCT sources structurally. - User-vouched fact (with the user's source): the same helper with
provenance="user"(the user is the authority), orstore.promotion.promote_if_faithful(km, question=…, answer=<claim>, evidence_passages=[…], client=None, faithfulness=<conf>, provenance="user")directly.client=Noneskips the LLM gate because YOU verified the claim traces to the user's source; an explicitfaithfulnessis required (no silent unverified write), and the compression + ≥2-citation + trust gates still apply.
(If you'd rather have the metered model do the grounding check, pass an
anthropic-shaped client instead of None — a one-at-a-time user-initiated write,
so the cost is negligible.)
Land one finding at a time, on the user's explicit go. Report what landed, at what tier, and from what source.
Honest limits (state them, never paper over)
- Authority is not infallibility. A user-vouched fact seeds high trust, not permanent truth — it still earns or loses rank by outcomes, and a later authoritative correction supersedes it. The tier is a prior.
- Every fill is still faithfulness-gated. "The user said so" is not enough to land a sourceless claim — require a source so the band stays traceable. This protects the user from their own typo as much as anything.
- Surfacing is probabilistic. The findings (gaps/contradictions/stale) are candidates, not certainties (see each sibling skill's limits). Curation is exactly where a human corrects those misses — which is the point of the loop.
- One at a time, reversible-minded. Landing grows the earned layer; do it deliberately, per finding, on the user's word — never in a silent batch.
Reference
store/insight.py::seed_confidence(provenance=…)+provenance_tier— the trust-tier prior (user ≥ verified-external ≥ single-external ≥ corpus).store/promotion.py::promote_if_faithful(provenance=…)— the gated landing path.rlat-gap-scan/rlat-contradictions/rlat-refresh-facts— the finding sources.curator/external_fill.py— the cross-source-agreement fill (the verified-external tier).