Contributing
Manual Curation Pipeline
The exact commands to take a skill from discovery to a closed intake. No AI required. Every phase with every command, typed by a human.
The reference below explains what runs inside each gate. Use it when you need full control or are debugging a step.
On this page
Pipeline overview
| # | Phase | What you produce | Gate |
|---|---|---|---|
| 1 | gaia-curate | A discovery-packet-v2 JSON in registry-for-review/discovery-packets/ | Human L4 |
| 2 | L4 Review | You append l4Resolution to the packet | Hard stop — must be you |
| 3 | gaia push → PR | Intake issue opened; draft PR on a review/meta branch | CI green |
| 4 | ev-pipeline | Verified evidence lake ready for ingest | Human approves evidence |
| 5 | gaia-ingest | Evidence rows written, TM appraised, stars calibrated | Human approves calibration |
| 6 | Close | PR merged, intake issue closed with findings comment | Done |
gaia-curate — Discover & package the skill
You have a real repo with a SKILL.md. Run prefill, apply the 6-rule mapping decision, write the packet, validate. Nothing touches the registry yet.
Step 1 — Preflight
# confirm gaia CLI is installed gaia --version # confirm gh CLI is authenticated gh auth status # confirm python3 available python3 --version
Step 2 — Snapshot the generic list
Save this file. It's the trust anchor for packet validation. Don't overwrite it mid-run.
gaia dev list --generic --json > /tmp/generic-snapshot.json wc -l /tmp/generic-snapshot.json
Step 3 — Run prefill against the SKILL.md URL
gaia dev prefill contributor/skill-name \ --name "Skill Name" \ --description "Verbatim from SKILL.md frontmatter" \ --url "https://github.com/owner/repo/blob/main/SKILL.md" \ --stdout > /tmp/prefill-output.json cat /tmp/prefill-output.json | python3 -m json.tool | head -80
Drop --stdout and gaia dev prefill writes the packet straight to registry-for-review/discovery-packets/<candidate-id-slug>.json — there is no --output flag.
Step 4 — Apply the 6-rule mapping decision
| Rule (first match wins) | Decision | When |
|---|---|---|
| 1 | NOT_A_SKILL | artifactGate != "valid-skill" |
| 2 | DUPLICATE | exactDedupe != null |
| 3 | DEFER | ambiguity != null |
| 4 | NEW_GENERIC | nTotal == 0 |
| 5 | MAP | nStrong == 1 — use that genericId |
| 6 | DEFER | All other cases (weak only, or nStrong ≥ 2) |
Count nStrong = entries with matchTier == "strong" in mappingOptions[]. Count nTotal = total entries. Do not re-rank.
Step 5 — Write and validate the discovery-packet-v2
Update the packet at registry-for-review/discovery-packets/owner--skill-name.json with your Step 4 decision. Key fields (matching what validate_discovery_packet.py actually checks — decision is an object, not a string, and the top-level field is contractVersion, not schemaVersion):
{
"contractVersion": "discovery-packet-v2",
"candidateId": "owner/skill-name",
"source": { "canonicalUrl": "<blob-url>", "sourceLane": "source-repository" },
"normalized": { "name": "verbatim from frontmatter", "description": "verbatim" },
"exactDedupe": { "matched": false },
"mappingOptions": [ /* copy from prefill-output.json — each needs genericId, rationale, similarity, matchTier */ ],
"decision": { "value": "MAP", "reasonCode": "MAP_EXISTING_GENERIC", "genericId": "<id from strong option>" },
"flags": [ /* copy from prefill-output.json */ ],
"genericSnapshot": { "capturedAt": "<ISO timestamp>", "command": "gaia dev list --generic --json", "contentSha256": "<hash>", "mappingOptionsSha256": "<hash>", "generics": [ /* snapshot contents */ ] },
"lifecycle": [ "discovered", "fetched", "parsed", "normalized", "deduped", "mapped", "review-ready" ]
}
The "review-ready" lifecycle end state requires the full six-stage prefix shown above. gaia dev prefill (Step 3) only ever emits ["discovered", "deferred"] — that's by design, not a gap: prefill just ranks mapping options, it never fetches or reads anything. Advancing to "fetched" and "parsed" is on you, the curator who actually opened the URL. Add source.hostRepository (the repo URL), source.fetchedAt (an ISO timestamp for when you fetched it), and source.contentSha256 (a SHA-256 of the raw SKILL.md text — sha256sum <file> or shasum -a 256 <file>) for "fetched"; add source.frontmatter.name and source.frontmatter.description — the same verbatim values you already passed to Step 3's --name/--description — for "parsed". Run the validator after every edit rather than guessing.
python3 .agents/skills/gaia-curate/scripts/validate_discovery_packet.py \ --generic-snapshot /tmp/generic-snapshot.json \ registry-for-review/discovery-packets/owner--skill-name.json # Must exit 0 with no MALFORMED_PACKET or MISSING_REQUIRED_FIELD errors
L4 Review — You ratify the topology
No one else does this step. Check the packet, append l4Resolution, re-validate.
What to check
- Mapping decision is correct — does
selectedGenericIdmatch the skill's actual capability? - If
NEW_GENERIC: is the proposed name and description vendor-neutral and falsifiable? source.urlis a realblob/GitHub URL — nottree/or a listing page.normalized.descriptionis verbatim from theSKILL.mdfrontmatter — not paraphrased.- Similarity score (
mappingOptions[].similarity) andmatchTiermake sense.
Append l4Resolution
"l4Resolution": { "generic": { "id": "final-generic-id", "name": "Human Readable Name", "description": "Vendor-neutral, falsifiable.", "type": "basic", "prerequisites": [] }, "named": { "contributor": "github-handle", "skillName": "kebab-case-name" }, "upstreamSkillFileUrl": "https://github.com/owner/repo/blob/main/SKILL.md" }
python3 .agents/skills/gaia-curate/scripts/validate_discovery_packet.py \ --generic-snapshot /tmp/generic-snapshot.json \ registry-for-review/discovery-packets/owner--skill-name.json
gaia push → Draft PR — Open the intake issue
git checkout -b review/meta/github-handle--skill-name # Dry run first gaia push --from-file registry-for-review/discovery-packets/owner--skill-name.json --dry-run # Real run — opens intake issue (auto-labels: intake + needs-triage) gaia push --from-file registry-for-review/discovery-packets/owner--skill-name.json git add registry-for-review/discovery-packets/owner--skill-name.json git commit -m "feat(intake): curate contributor/skill-name [closes #ISSUE]" git push -u origin review/meta/github-handle--skill-name gh pr create --draft --title "feat(intake): ..." --body-file /tmp/pr-body.md
intake:* label lifecycle
These are machine gates — intake-approval.yml watches for them and fires automatically.
| Label | Who applies | What it triggers |
|---|---|---|
intake | Auto (gaia push) | Routes into intake queue |
needs-triage | Auto (gaia push) | Marks as awaiting review |
intake:topology-approved | Maintainer only | Workflow fires: adds evidence-review, removes needs-triage |
intake:evidence-review | Auto (workflow) | Signals agent to prepare Stage-1 seed |
intake:evidence-ready | Agent / you | Evidence plan ready for human approval |
intake:evidence-approved | Maintainer only | Opens the single draft promotion PR |
intake:rejected | Maintainer only | Closes intake; no automation fires |
intake:evidence-approved requires both intake:evidence-review and intake:evidence-ready to already be present. The workflow errors if either is missing.
gh issue edit <ISSUE_NUMBER> --add-label "intake:topology-approved" # Fires intake-approval.yml — watch it: gh run list --workflow=intake-approval.yml
ev-pipeline — Verify evidence before ingesting
Operates on evidence/by-type/ files only. Never touches registry/. Each phase produces review artifacts; you decide what to approve.
Phase 0 — ev-discovery (skippable)
The only phase that searches the web for new evidence. Skip for routine Stage-1 intakes. Run when you need benchmark-result, arxiv, peer-review, or richer social-signal rows.
No gaia CLI command runs this phase — there is no gaia dev discover. Trigger the ev-discovery agent skill directly (/ev-discovery in Claude Code), naming the skill id, source repo, and evidence types needed. It requires FIRECRAWL_API_KEY and skips gracefully if absent. This is the one phase on this page that needs an AI agent — every other phase is a plain command.
Discovered rows get appended to evidence/by-type/<type>.md under the same source-input format Phase 1 already reads — see Phase 1 below.
Phase 1 — ev-collection
This runs on the entire registry — not just your new skill. generate_source_dump.py reads all named-skill evidence rows across every skill in registry/named/. Your new skill's rows appear alongside all others. That is expected.
python3 evidence/scripts/generate_source_dump.py \ --output-dir evidence --by-type-dir evidence/by-type python3 evidence/scripts/compile_data_lake.py \ --sources evidence/by-type --lake evidence
Phase 2 — ev-star-verification
# Check auth first — zero stars from an unauth'd call is poison data gh auth status gh api repos/OWNER/REPO --jq '.stargazers_count' # Flag rows where recorded stars differ from live count. Do NOT silently update.
Phase 3 — ev-adversarial-audit
# Find github tree/ URLs that should be blob/ grep -rn "github.com/.*/tree/" evidence/by-type/ # Find subjective wording not backed by source grep -rni "elite\|high-quality\|best-in-class\|leading" evidence/by-type/
Phase 4 — ev-link-validation
python3 evidence/scripts/validate_sources.py # Or a 10-URL sample first: python3 evidence/scripts/validate_sources.py 10
gaia-ingest — Write evidence to the named skill
First time mutating registry/. Docs rebuild is skipped by default — no flag needed. Run gaia dev build once after all rows, or pass --build on a single row instead. You approve calibration before it runs.
Ingest each approved evidence row
GAIA_OPERATOR_OVERRIDE=1 gaia dev evidence contributor/skill-id \ "https://github.com/owner/repo" \ --type repo-own --commits 847 --contributors 12 \ --notes "Official upstream repo. Counts verified via GitHub API." \ --source-started-at 2024-03-01
GAIA_OPERATOR_OVERRIDE=1 gaia dev evidence contributor/skill-id \ "https://github.com/owner/repo/blob/main/SKILL.md" \ --type github-stars-own --stars 3421 --skill-count-in-repo 1 \ --notes "Official SKILL.md. Star count verified live via gh api." \ --source-started-at 2024-03-01
# Single build after all rows are written GAIA_OPERATOR_OVERRIDE=1 gaia dev build # Appraise Trust Magnitude PYTHONPATH=src python3 scripts/trust_appraise.py --skill contributor/skill-id # Only after you approve the proposed calibration: GAIA_OPERATOR_OVERRIDE=1 gaia dev calibrate contributor/skill-id 2★ GAIA_OPERATOR_OVERRIDE=1 gaia dev validate
TM grade reference
Trust Magnitude is the sole promotion gate under Yggdrasil II. Thresholds sourced from src/gaia_cli/grading.py and META.md §1.1.
| Grade | TM floor | Stars it gates | Notes |
|---|---|---|---|
| ungraded | < 20 | 1★–2★ | Stage-1 minimum (Awakened / Named baseline) |
| C | ≥ 20 | up to 3★ | Badge unlock floor at 2★ Named |
| B | ≥ 50 | up to 3★ | Solid adoption signals (Evolved) |
| A | ≥ 100 | gates 4★ | 4★ Extra/Unique gate — Origin + TM ≥ 100 |
| S | ≥ 250 + diversity | gates 5★–6★ | Diversity gate: ≥3 evidence types + non-self-producible row. 5★ = TM ≥ 250. 6★ Apex adds 6-predicate gate. |
The per-star Evidence Floor is retired. TM is the sole gate. But the Star Bar (installability, 3★+ requires a verified GitHub blob/ link) still applies.
Close — Merge PR & post intake comments
gh pr ready <PR_NUMBER> gh pr checks <PR_NUMBER> # When CI is green: gh pr merge <PR_NUMBER> --subject "feat(registry): ingest contributor/skill-name [closes #ISSUE]" # Post findings comment on PR (evidence table + TM + badge status) gh pr comment <PR_NUMBER> --body-file /tmp/pr-close-comment.md # Post closing comment on intake issue (path-to-promotion, @contributor tag) gh issue comment <ISSUE_NUMBER> --body-file /tmp/issue-close-comment.md gh issue close <ISSUE_NUMBER> # Regenerate Class S site artifacts GAIA_OPERATOR_OVERRIDE=1 gaia dev docs git add docs/graph/ && git commit -m "chore: regenerate Class S artifacts" && git push
Common errors
UNTRUSTED_GENERIC_SNAPSHOT
The contentSha256 in the packet doesn't match the snapshot file passed to --generic-snapshot.
python3 -c "import json,hashlib; d=json.load(open('/tmp/generic-snapshot.json')); print(hashlib.sha256(json.dumps(d,sort_keys=True,separators=(',',':')).encode()).hexdigest())"
INVALID_GENERIC_SELECTION — mapped ID not in snapshot
You used a genericId that wasn't in the snapshot you captured. Re-capture the snapshot after adding the new generic, or use an ID that's actually there.
gaia dev evidence fails — "unknown evidence type"
gaia dev evidence --help # Lists all supported --type values and required flags
gaia dev validate fails after ingest
GAIA_OPERATOR_OVERRIDE=1 gaia dev validate --verbose # Read the first error — usually a missing field or schema mismatch
Cheat sheet — every command in order
# ── Phase 1: Curate ────────────────────────────────────────── gaia dev list --generic --json > /tmp/generic-snapshot.json gaia dev prefill contributor/skill-name --name "Skill Name" --description "..." --url "<blob-url>" --stdout > /tmp/prefill-output.json # ... write packet JSON ... python3 .agents/skills/gaia-curate/scripts/validate_discovery_packet.py --generic-snapshot /tmp/generic-snapshot.json <packet>.json # ── Phase 2: L4 ────────────────────────────────────────────── # Append l4Resolution to packet, re-validate # ── Phase 3: Push + PR ─────────────────────────────────────── git checkout -b review/meta/handle--skill gaia push --from-file <packet>.json --dry-run gaia push --from-file <packet>.json # auto-labels issue: intake + needs-triage git add . && git commit -m "feat(intake): ..." && git push -u origin <branch> gh pr create --draft --title "..." --body-file /tmp/pr-body.md gh issue edit <ISSUE> --add-label "intake:topology-approved" # maintainer only gh issue edit <ISSUE> --add-label "intake:evidence-approved" # maintainer only, after evidence-ready # ── Phase 4: ev-pipeline ───────────────────────────────────── # Phase 0 (skippable, no CLI equivalent — run the ev-discovery agent skill instead) # /ev-discovery contributor/skill "<repo-url>" arxiv,peer-review,social-signal # Phase 1 (whole-registry lake rebuild) python3 evidence/scripts/generate_source_dump.py --output-dir evidence --by-type-dir evidence/by-type python3 evidence/scripts/compile_data_lake.py --sources evidence/by-type --lake evidence gh api repos/OWNER/REPO --jq '.stargazers_count' # phase 2 star check grep -rn "github.com/.*/tree/" evidence/by-type/ # phase 3 adversarial python3 evidence/scripts/validate_sources.py # phase 4 link health # ── Phase 5: gaia-ingest ───────────────────────────────────── GAIA_OPERATOR_OVERRIDE=1 gaia dev evidence contributor/skill "<url>" \ --type repo-own --commits N --contributors N --notes "..." --source-started-at YYYY-MM-DD # ... repeat for each evidence type ... GAIA_OPERATOR_OVERRIDE=1 gaia dev build PYTHONPATH=src python3 scripts/trust_appraise.py --skill contributor/skill GAIA_OPERATOR_OVERRIDE=1 gaia dev calibrate contributor/skill N★ # after your approval GAIA_OPERATOR_OVERRIDE=1 gaia dev validate # ── Phase 6: Close ─────────────────────────────────────────── gh pr ready <PR> && gh pr checks <PR> gh pr merge <PR> --subject "feat(registry): ... [closes #ISSUE]" gh pr comment <PR> --body-file /tmp/pr-close-comment.md gh issue comment <ISSUE> --body-file /tmp/issue-close-comment.md gh issue close <ISSUE> GAIA_OPERATOR_OVERRIDE=1 gaia dev docs
Want to automate this? Become a contributor.
Once you've curated a skill manually, you can contribute back to the registry directly using gaia dev commands — the same CLI the pipeline runs under the hood. No intake queue. Direct mutations with your approval.
| What you want to do | Command |
|---|---|
| Add a generic skill node | gaia dev add "Name" --id kebab-id --type basic --description "..." |
| Add a named implementation | gaia dev named --contributor handle --skill slug --generic id --upstream <blob-url> |
| Add an evidence row | gaia dev evidence contributor/skill "<url>" --type repo-own --commits N ... |
| Appraise Trust Magnitude | PYTHONPATH=src python3 scripts/trust_appraise.py --skill contributor/skill |
| Calibrate star level | gaia dev calibrate contributor/skill N★ |
| Fuse a suite capstone | gaia dev fuse <id> --name "..." --prereqs id1,id2 --named-capstone contributor/slug |
| Validate registry | GAIA_OPERATOR_OVERRIDE=1 gaia dev validate |
| Regenerate site artifacts | GAIA_OPERATOR_OVERRIDE=1 gaia dev docs |
All gaia dev mutations require GAIA_OPERATOR_OVERRIDE=1 or maintainer permissions. Read Contributing §1C before making direct registry changes. Or run gaia curate <url> to automate the full pipeline with 2 human gates.