Skip to content

t1k:contribution-score

FieldValue
Modulet1k-maintainer
Version2.18.3
Effortlow
Tools

Keywords: contribution score, record contribution, score artifact

/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.

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 — after gh issue create succeeds, score the just-filed issue
  • t1k:sync-back — after gh pr create succeeds, score the just-opened PR
  • t1k: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).

Apply this same rubric to issues AND PRs AND triage backfill — single rubric, no drift.

ScoreMeaningIssue examplePR / sync-back example
5Novel & well-evidencedFirst-of-its-kind insight; full repro steps; logs/screenshots; identifies root causeCross-cutting fix with new test; documents a non-obvious gotcha; improves multiple skills/agents
4Clear & actionableSpecific problem described; what was expected vs observed; environment listedTargeted fix to one skill/agent; clear rationale; minimal collateral edits
3Valid but routineReal bug or improvement, but minimal context; reader has to infer detailsSingle-line fix or doc tweak; correct but unremarkable
2Low-effortVague description; missing key context; needs follow-up to be usefulCosmetic-only or wraparound; doesn’t change behavior; could be combined with other PRs
1Spam / duplicate / noiseAlready known; off-topic; unactionable; AI-test/throwaway contentReverts 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.

Caller provides via skill arguments OR via in-context variables:

FieldRequiredNotes
typeyesOne of issue, sync-back-pr, triage-backfill
ref_urlyesCanonical GitHub URL: https://github.com/<owner>/<repo>/(issues|pull)/<n>
kityesKit short-name, e.g., theonekit-core, theonekit-unity
repoyes<owner>/<repo> form, e.g., The1Studio/theonekit-core
titleyesArtifact title (issue title or PR title)
bodyyesArtifact body — issue body, PR description, or PR diff summary
evidence_excerptoptionalShort excerpt (logs, repro snippet) supporting the score

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.

Terminal window
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 ;;
esac

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.

Endpoint resolution order (first match wins):

  1. $T1K_TELEMETRY_ENDPOINT env var
  2. <project>/.claude/t1k-config-core.jsontelemetry.cloud.endpoint, then strip trailing /ingest if present
  3. ~/.claude/t1k-config-core.json (global) — same field
  4. No endpoint configured → log to stderr and return success-with-skip; do NOT block caller
Terminal window
# 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$,,')
fi
if [ -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; }
Terminal window
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" || true

Step 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 error

Always 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:

HTTPBodyMeaning
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
  • 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 token failure 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-backfill requires a CLOSED/MERGED artifact — POSTing type:"triage-backfill" for an OPEN issue/PR returns 403 {"error":"author_attribution_failed","reason":"triage_requires_closed_artifact"}. Triage credit is granted only once the item actually resolves. t1k:triage --yolo arms 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 every gh issue|pr create|merge|close against a T1K repo to <claudeDir>/telemetry/contribution-tracking.jsonl (fact-only, can’t-skip, per-command); and (2) the t1k:contribution-flush skill — reads that tracking file, AI-scores each un-recorded ref against this same rubric, POSTs, drops recorded/terminal entries and keeps triage_requires_closed_artifact for cross-session retry. The flush skill is auto-wired into t1k:triage (end) and t1k: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.
  • The skill never logs the GitHub token, the full POST body, or ai_rationale contents. Only short status lines go to stderr.
  • The worker re-runs secret-redaction on ai_rationale and evidence_excerpt defensively (defense-in-depth), but this skill SHOULD also avoid passing raw command output that may contain credentials.