t1k:contribution-score
| Field | Value |
|---|---|
| Module | t1k-maintainer |
| Version | 2.18.3 |
| Effort | low |
| Tools | — |
Keywords: contribution score, record contribution, score artifact
How to invoke
Section titled “How to invoke”/t1k:contribution-score--type=issue|sync-back-pr|triage-backfill --ref-url=URL --title=... --body=...t1k:contribution-score — Score a Contribution Artifact (SSOT)
Section titled “t1k:contribution-score — Score a Contribution Artifact (SSOT)”Single source of truth for AI scoring of contributions (issues, PRs).
Invoked by t1k:issue, t1k:sync-back, and t1k:triage — never user-facing
directly. Owns: rubric, endpoint resolution, POST contract, error handling.
When to use
Section titled “When to use”Call this skill from another skill after that skill has successfully created or identified a GitHub artifact (issue or PR) that should be scored as a contribution. Examples:
t1k:issue— aftergh issue createsucceeds, score the just-filed issuet1k:sync-back— aftergh pr createsucceeds, score the just-opened PRt1k:triage— when iterating open issues/PRs, backfill score for unscored items
This skill is fire-and-forget for callers: any failure is logged to stderr and never blocks the caller’s primary workflow (issue creation, PR opening).
Rubric — 1-to-5 generic quality scale
Section titled “Rubric — 1-to-5 generic quality scale”Apply this same rubric to issues AND PRs AND triage backfill — single rubric, no drift.
| Score | Meaning | Issue example | PR / sync-back example |
|---|---|---|---|
| 5 | Novel & well-evidenced | First-of-its-kind insight; full repro steps; logs/screenshots; identifies root cause | Cross-cutting fix with new test; documents a non-obvious gotcha; improves multiple skills/agents |
| 4 | Clear & actionable | Specific problem described; what was expected vs observed; environment listed | Targeted fix to one skill/agent; clear rationale; minimal collateral edits |
| 3 | Valid but routine | Real bug or improvement, but minimal context; reader has to infer details | Single-line fix or doc tweak; correct but unremarkable |
| 2 | Low-effort | Vague description; missing key context; needs follow-up to be useful | Cosmetic-only or wraparound; doesn’t change behavior; could be combined with other PRs |
| 1 | Spam / duplicate / noise | Already known; off-topic; unactionable; AI-test/throwaway content | Reverts useful work; bypasses linting; pure formatting churn |
When uncertain between two adjacent tiers, pick the lower tier — it is harder to inflate scores than to deflate them, and the rubric is meant to reward effort, not enthusiasm.
Invocation contract
Section titled “Invocation contract”Caller provides via skill arguments OR via in-context variables:
| Field | Required | Notes |
|---|---|---|
type | yes | One of issue, sync-back-pr, triage-backfill |
ref_url | yes | Canonical GitHub URL: https://github.com/<owner>/<repo>/(issues|pull)/<n> |
kit | yes | Kit short-name, e.g., theonekit-core, theonekit-unity |
repo | yes | <owner>/<repo> form, e.g., The1Studio/theonekit-core |
title | yes | Artifact title (issue title or PR title) |
body | yes | Artifact body — issue body, PR description, or PR diff summary |
evidence_excerpt | optional | Short excerpt (logs, repro snippet) supporting the score |
Workflow
Section titled “Workflow”Step 0 — T1K repo gate
Section titled “Step 0 — T1K repo gate”Skip non-T1K repos so callers (t1k:git pr, t1k:ship, t1k:cook, t1k:babysit-pr) are safe from customer apps. Uniform; no per-skill gate.
case "$REPO" in The1Studio/theonekit-*|The1Studio/t1k-*|The1Studio/unity-mcp|The1Studio/cocos-mcp-server) ;; *) echo "[contribution-score] skipped: not a T1K repo ($REPO)" >&2; exit 0 ;;esacStep 1 — AI scores the artifact
Section titled “Step 1 — AI scores the artifact”Read the rubric above. Score the provided title + body against it. Output:
score: <1..5>rationale: <one sentence explaining the score, ≤300 chars>Be conservative — when in doubt, pick the lower tier.
Step 2 — Resolve telemetry endpoint
Section titled “Step 2 — Resolve telemetry endpoint”Endpoint resolution order (first match wins):
$T1K_TELEMETRY_ENDPOINTenv var<project>/.claude/t1k-config-core.json→telemetry.cloud.endpoint, then strip trailing/ingestif present~/.claude/t1k-config-core.json(global) — same field- No endpoint configured → log to stderr and return success-with-skip; do NOT block caller
# Reference resolver — Linux/macOS only. On Windows, run inside WSL or git-bash;# Claude Code's hook runner uses Node.js for cross-platform code (per CLAUDE.md# requirement #3), but skill bodies are instruction text and assume a POSIX# shell. If running on a non-POSIX host, port the same logic to Node.js.EP="${T1K_TELEMETRY_ENDPOINT:-}"if [ -z "$EP" ] && [ -f .claude/t1k-config-core.json ]; then EP=$(jq -r '.telemetry.cloud.endpoint // empty' .claude/t1k-config-core.json | sed 's,/ingest$,,')fiif [ -z "$EP" ] && [ -f "$HOME/.claude/t1k-config-core.json" ]; then EP=$(jq -r '.telemetry.cloud.endpoint // empty' "$HOME/.claude/t1k-config-core.json" | sed 's,/ingest$,,')fi[ -z "$EP" ] && { echo "[contribution-score] no endpoint — skipping" >&2; exit 0; }Step 3 — POST to worker
Section titled “Step 3 — POST to worker”TOKEN=$(gh auth token 2>/dev/null) || { echo "[contribution-score] no gh token — skipping" >&2; exit 0}
USER=$(gh api user --jq .login 2>/dev/null) || { echo "[contribution-score] cannot resolve gh user — skipping" >&2; exit 0}
curl -sS --max-time 8 -X POST \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d "$(jq -n --arg u "$USER" --arg k "$KIT" --arg r "$REPO" --arg t "$TYPE" \ --arg url "$REF_URL" --argjson s "$SCORE" --arg ra "$RATIONALE" \ --arg ev "$EVIDENCE" \ '{user:$u, kit:$k, repo:$r, type:$t, ref_url:$url, ai_score:$s, ai_rationale:$ra} + (if $ev == "" then {} else {evidence_excerpt:$ev} end)')" \ "$EP/api/contributions" || trueStep 4 — Report outcome to caller (one line)
Section titled “Step 4 — Report outcome to caller (one line)”[contribution-score] score=<n> recorded ref=<short-url> # success[contribution-score] score=<n> already_recorded ref=<url> # idempotent[contribution-score] skipped: <reason> # missing config[contribution-score] failed: <reason> # any other errorAlways exit 0 — the caller is fire-and-forget. Errors are observability, not blockers.
POST body schema (for reference — worker enforces)
Section titled “POST body schema (for reference — worker enforces)”{ "user": "<gh-login>", // MUST equal authenticated user (worker rejects mismatch) "kit": "theonekit-core", "repo": "The1Studio/theonekit-core", "type": "issue", // issue | sync-back-pr | triage-backfill "ref_url": "https://github.com/<owner>/<repo>/(issues|pull)/<n>", "ai_score": 4, // integer 1..5 "ai_rationale": "<≤500 chars>", "evidence_excerpt": "<optional, ≤500 chars>"}Worker responses:
| HTTP | Body | Meaning |
|---|---|---|
| 201 | {status:"recorded", id, ref_url} | New contribution row |
| 200 | {status:"already_recorded", ref_url} | Idempotency — same (user, ref_url) already scored |
| 400 | {error:"..."} | Bad body (validation failure, score range, URL shape, user mismatch) |
| 401 | {error:"Missing Authorization header"} | No token |
| 403 | {error:"..."} | Token invalid or not in The1Studio org |
Gotchas
Section titled “Gotchas”- Worker idempotency is
(user, ref_url)— re-running scoring on the same artifact is safe; the second POST returns 200 instead of duplicating. gh auth tokenfailure is non-fatal — skill exits 0 with a stderr note. Caller workflow proceeds normally.- No retries — if the POST fails (network, 5xx), DO NOT retry. The next call to the caller skill will re-score and the worker will deduplicate.
- Endpoint MUST NOT include
/ingest— the resolver strips it. The contributors API is at/api/contributions, not/ingest/api/contributions. - Conservative scoring — when between tiers, pick the lower one. The rubric rewards quality, not enthusiasm.
triage-backfillrequires a CLOSED/MERGED artifact — POSTingtype:"triage-backfill"for an OPEN issue/PR returns403 {"error":"author_attribution_failed","reason":"triage_requires_closed_artifact"}. Triage credit is granted only once the item actually resolves.t1k:triage --yoloarms many PRs for ASYNC auto-merge, so their credit cannot be POSTed at triage time — the deterministic capture layer (below) retains them and the flush skill retries once they merge.- Deterministic safeguard = capture hook + flush skill — this live POST is
the fast, AI-scored path, but it is model-dependent (a skill body can skip it).
The backstop is two pieces: (1)
contribution-capture.cjs— a PostToolUse:Bash hook that records everygh issue|pr create|merge|closeagainst a T1K repo to<claudeDir>/telemetry/contribution-tracking.jsonl(fact-only, can’t-skip, per-command); and (2) thet1k:contribution-flushskill — reads that tracking file, AI-scores each un-recorded ref against this same rubric, POSTs, drops recorded/terminal entries and keepstriage_requires_closed_artifactfor cross-session retry. The flush skill is auto-wired intot1k:triage(end) andt1k:my-score(start), and the capture hook nudges once enough refs accrue. Worker idempotency on(user, ref_url)makes the live POST and the flush safe to both fire — first wins.
Security
Section titled “Security”- The skill never logs the GitHub token, the full POST body, or
ai_rationalecontents. Only short status lines go to stderr. - The worker re-runs secret-redaction on
ai_rationaleandevidence_excerptdefensively (defense-in-depth), but this skill SHOULD also avoid passing raw command output that may contain credentials.