name: corpus-curate description: Run the corpus-forge data-improvement chat loop. Use when the user wants to fortify low-confidence or metadata-poor entries — find the weakest, talk through the fix, and commit edits via MCP. allowed-tools: - mcp__corpus-forge__next_curation_target - mcp__corpus-forge__next_curation_batch - mcp__corpus-forge__commit_curation - mcp__corpus-forge__create_enhancement_chunk - mcp__corpus-forge__list_datasets - mcp__corpus-forge__get_chunk - mcp__corpus-forge__search
What corpus-forge curation is
corpus-forge indexes documents, chunks, conversations, and code into a
training-grade corpus. The curation loop is the human-in-the-loop step
that turns a freshly-ingested corpus into a trained-on-able one: the
ranker finds the weakest entry (low classifier confidence, sparse
metadata, anomalous embedding, freshly ingested), you and the user
agree on a fix, and the MCP server writes the edits back atomically.
Citations still matter — every entry you fortify is a candidate row in the next training run.
When to invoke
Invoke this skill when:
- The user says "let's curate", "improve my data", "fix labels", "this looks under-tagged", or any phrasing about making the corpus better (vs. searching it).
- The user just ran an ingest (
corpus-forge ingest …or the daemon caught fresh files) and many recently-imported entries look thin on metadata. - The user has asked twice for the same fact and the cited chunks are poorly labelled — a curation pass on the source is more useful than another search.
- The user explicitly asks the librarian / corpus-curate agent to run a curation pass.
When NOT to invoke
Skip this skill when:
- The user asks a question that needs a citation — that's a job for the
corpus-forge-searchskill, not this one. - The MCP server has
writes_enabled=False—commit_curationwill not be in/mcpand the loop is read-only. Surface that to the user and suggest they relaunch the server with writes enabled. - The user is mid-flow on something else (writing code, debugging, running a long search) and didn't ask for curation. Don't drift the conversation.
Tool playbook
Follow the five-step loop:
- Pick — call
next_curation_target(dataset="<name>"). The response carrieschunk_id,text,heading,current_labels,current_metadata,missing_fields,classifier_confidence,score,score_breakdown, and a one-lineselection_reasonexplaining why this entry was picked.- For batched mode (user said "let's batch many"), call
next_curation_batch(limit=N)instead. The response includes acohesion_score(0–1) so you can show the user how tight the group is before they ratify it.
- For batched mode (user said "let's batch many"), call
- Present — surface the entry to the user in a few lines:
chunk #{chunk_id} (score {score:.2f}, {selection_reason}) text : {text[:200]}… labels : {current_labels} missing: {missing_fields} - Ask — at most three focused questions about what to fix. Useful
prompts:
- Should we add or remove labels? (Offer concrete suggestions when
missing_fieldsincludeslabels.) - Does the heading or description need correcting?
- Is there a factual correction or follow-up note worth recording as feedback?
- Should we add or remove labels? (Offer concrete suggestions when
- Commit — call
commit_curation(chunk_id=..., add_labels=[...], remove_labels=[...], set_metadata={...}, set_description="...", feedback={...}). The server routes each piece through the existing MCP write surface and returns a per-kind count plus a list of audit ids. Passdry_run=truefirst when the change set is big. - Loop — ask "next one?". Yes → step 1. No → emit a short summary of what was changed this session (chunk_ids touched + counts per kind).
Minting an enhancement chunk (creating data, not just editing it)
commit_curation only edits the entry you picked. When the curation
conversation produces new material worth keeping as its own
corpus row — a worked correction, a clarified explanation, a recommended
enhancement, or the salient back-and-forth that resolved a confusion —
call create_enhancement_chunk to persist it:
create_enhancement_chunk(
dataset="<name>",
text="<the conversation snippet + recommended enhancement>",
derived_from_chunk_id=<the chunk you were curating>, # optional but encouraged
heading="<short title>", # optional
metadata={...}, # optional extra keys
dry_run=true, # preview big writes first
)
It appends the new chunk to a per-dataset synthetic document
corpus-forge://curation/<dataset> (created lazily) and stamps lineage
metadata {"kind": "curation_enhancement", "derived_from_chunk_id": ..., "curation_session_id": ...}. Returns {chunk_id, document_id, audit_id}. The new chunk is embedded on the normal backfill lane and is
immediately lexically searchable.
When to mint vs. edit: edit (commit_curation) when the existing entry's
labels/description/metadata are wrong or thin; mint
(create_enhancement_chunk) when the fix is new text that should
stand on its own as a training row. You can do both in one pass — edit
the source chunk, then mint the enhancement that links back to it via
derived_from_chunk_id.
To exclude these synthetic rows from retrieval or eval, filter on
metadata.kind == "curation_enhancement".
Response handling
next_curation_target returns:
{"target": {
"chunk_id": 123, "document_id": 7,
"text": "...", "heading": null,
"current_labels": [["topic", "ml"]],
"current_metadata": {"language": "en"},
"missing_fields": ["description"],
"classifier_confidence": 0.42,
"score": 0.61,
"score_breakdown": {
"confidence_deficit": 0.58, "missing_metadata": 0.17,
"ranker_elevation": 0.50, "freshness": 1.0
},
"selection_reason": "classifier confidence 0.42"
}}
commit_curation returns:
{"writes": {"add_label": 2, "remove_label": 0,
"set_metadata": 1, "set_description": 1, "add_feedback": 1},
"chunk_ids_processed": [123], "dry_run": false,
"audit_ids": [501, 502, 503, 504, 505]}
Citation format
When quoting a chunk during the chat, use:
From {title} ({source_uri}): {quote}
Keep quotes ≤ 2 sentences; call get_chunk for the full text when the
user needs more context.
When to call record_demonstration
record_demonstration captures a generalizable edit as a supervised
demonstration triple for fine-tuning (SDFT format). Use it when the
curation session surfaces an improvement that would teach a future model
how to curate, not merely what this entry should say.
Demonstration triple shape
{
"query": "<the question or text that prompted the edit>",
"student_messages": [
{"role": "assistant", "content": "<original / before state>"}
],
"teacher_messages": [
{"role": "assistant", "content": "<improved / after state>"}
],
"target": "<the final committed value (description, label, etc.)>",
"source": "claude_code",
"dataset_id": "<dataset name>"
}
Call it for generalizable edits — not pure metadata fixes
Call record_demonstration when:
- You rewrote a description that was factually thin or misleading.
- You reassigned labels and the rationale would transfer to other similar
entries (e.g. "short code snippets without docstrings get the
needs_docstringlabel"). - The user articulated a policy during the fix ("always add the language tag for multilingual docs").
Do not call it when:
- The edit is purely structural (adding a missing
languagemetadata key, fixing a typo in a field name). - The commit only adjusts numeric metadata (timestamps, token counts).
- The fix is idiosyncratic to a single entry with no transfer value.
Source value for this client
Always set source="claude_code" when recording demonstrations from a
Claude Code session. This value identifies the capture origin in the
sdft_demonstrations table and lets the fine-tuning pipeline filter by
assistant client.
MCP tool names (all four)
| Tool | When to call |
|---|---|
record_demonstration |
Capture a generalizable curated edit as an SDFT triple |
commit_curation |
Atomically write label / metadata / description edits |
create_enhancement_chunk |
Mint a NEW chunk (conversation + recommended enhancement) linked to its source |
rate_search_result |
Record thumbs-up/down on a retrieved chunk |
add_feedback |
Attach free-text feedback to a chunk without a full curation commit |